diff options
190 files changed, 4267 insertions, 1584 deletions
diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 1d3756d3176c..bacefc5b222e 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl | |||
| @@ -315,7 +315,7 @@ char *date;</synopsis> | |||
| 315 | <function>drm_dev_unregister()</function> followed by a call to | 315 | <function>drm_dev_unregister()</function> followed by a call to |
| 316 | <function>drm_dev_unref()</function>. | 316 | <function>drm_dev_unref()</function>. |
| 317 | </para> | 317 | </para> |
| 318 | !Edrivers/gpu/drm/drm_stub.c | 318 | !Edrivers/gpu/drm/drm_drv.c |
| 319 | </sect2> | 319 | </sect2> |
| 320 | <sect2> | 320 | <sect2> |
| 321 | <title>Driver Load</title> | 321 | <title>Driver Load</title> |
diff --git a/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt b/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt index 1486497a24c1..ce6a1a072028 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt | |||
| @@ -4,11 +4,13 @@ Specifying interrupt information for devices | |||
| 4 | 1) Interrupt client nodes | 4 | 1) Interrupt client nodes |
| 5 | ------------------------- | 5 | ------------------------- |
| 6 | 6 | ||
| 7 | Nodes that describe devices which generate interrupts must contain an either an | 7 | Nodes that describe devices which generate interrupts must contain an |
| 8 | "interrupts" property or an "interrupts-extended" property. These properties | 8 | "interrupts" property, an "interrupts-extended" property, or both. If both are |
| 9 | contain a list of interrupt specifiers, one per output interrupt. The format of | 9 | present, the latter should take precedence; the former may be provided simply |
| 10 | the interrupt specifier is determined by the interrupt controller to which the | 10 | for compatibility with software that does not recognize the latter. These |
| 11 | interrupts are routed; see section 2 below for details. | 11 | properties contain a list of interrupt specifiers, one per output interrupt. The |
| 12 | format of the interrupt specifier is determined by the interrupt controller to | ||
| 13 | which the interrupts are routed; see section 2 below for details. | ||
| 12 | 14 | ||
| 13 | Example: | 15 | Example: |
| 14 | interrupt-parent = <&intc1>; | 16 | interrupt-parent = <&intc1>; |
diff --git a/Documentation/devicetree/bindings/pci/designware-pcie.txt b/Documentation/devicetree/bindings/pci/designware-pcie.txt index d0d15ee42834..ed0d9b9fff2b 100644 --- a/Documentation/devicetree/bindings/pci/designware-pcie.txt +++ b/Documentation/devicetree/bindings/pci/designware-pcie.txt | |||
| @@ -2,6 +2,10 @@ | |||
| 2 | 2 | ||
| 3 | Required properties: | 3 | Required properties: |
| 4 | - compatible: should contain "snps,dw-pcie" to identify the core. | 4 | - compatible: should contain "snps,dw-pcie" to identify the core. |
| 5 | - reg: Should contain the configuration address space. | ||
| 6 | - reg-names: Must be "config" for the PCIe configuration space. | ||
| 7 | (The old way of getting the configuration address space from "ranges" | ||
| 8 | is deprecated and should be avoided.) | ||
| 5 | - #address-cells: set to <3> | 9 | - #address-cells: set to <3> |
| 6 | - #size-cells: set to <2> | 10 | - #size-cells: set to <2> |
| 7 | - device_type: set to "pci" | 11 | - device_type: set to "pci" |
diff --git a/Documentation/devicetree/bindings/pci/ti-pci.txt b/Documentation/devicetree/bindings/pci/ti-pci.txt new file mode 100644 index 000000000000..3d217911b313 --- /dev/null +++ b/Documentation/devicetree/bindings/pci/ti-pci.txt | |||
| @@ -0,0 +1,59 @@ | |||
| 1 | TI PCI Controllers | ||
| 2 | |||
| 3 | PCIe Designware Controller | ||
| 4 | - compatible: Should be "ti,dra7-pcie"" | ||
| 5 | - reg : Two register ranges as listed in the reg-names property | ||
| 6 | - reg-names : The first entry must be "ti-conf" for the TI specific registers | ||
| 7 | The second entry must be "rc-dbics" for the designware pcie | ||
| 8 | registers | ||
| 9 | The third entry must be "config" for the PCIe configuration space | ||
| 10 | - phys : list of PHY specifiers (used by generic PHY framework) | ||
| 11 | - phy-names : must be "pcie-phy0", "pcie-phy1", "pcie-phyN".. based on the | ||
| 12 | number of PHYs as specified in *phys* property. | ||
| 13 | - ti,hwmods : Name of the hwmod associated to the pcie, "pcie<X>", | ||
| 14 | where <X> is the instance number of the pcie from the HW spec. | ||
| 15 | - interrupts : Two interrupt entries must be specified. The first one is for | ||
| 16 | main interrupt line and the second for MSI interrupt line. | ||
| 17 | - #address-cells, | ||
| 18 | #size-cells, | ||
| 19 | #interrupt-cells, | ||
| 20 | device_type, | ||
| 21 | ranges, | ||
| 22 | num-lanes, | ||
| 23 | interrupt-map-mask, | ||
| 24 | interrupt-map : as specified in ../designware-pcie.txt | ||
| 25 | |||
| 26 | Example: | ||
| 27 | axi { | ||
| 28 | compatible = "simple-bus"; | ||
| 29 | #size-cells = <1>; | ||
| 30 | #address-cells = <1>; | ||
| 31 | ranges = <0x51000000 0x51000000 0x3000 | ||
| 32 | 0x0 0x20000000 0x10000000>; | ||
| 33 | pcie@51000000 { | ||
| 34 | compatible = "ti,dra7-pcie"; | ||
| 35 | reg = <0x51000000 0x2000>, <0x51002000 0x14c>, <0x1000 0x2000>; | ||
| 36 | reg-names = "rc_dbics", "ti_conf", "config"; | ||
| 37 | interrupts = <0 232 0x4>, <0 233 0x4>; | ||
| 38 | #address-cells = <3>; | ||
| 39 | #size-cells = <2>; | ||
| 40 | device_type = "pci"; | ||
| 41 | ranges = <0x81000000 0 0 0x03000 0 0x00010000 | ||
| 42 | 0x82000000 0 0x20013000 0x13000 0 0xffed000>; | ||
| 43 | #interrupt-cells = <1>; | ||
| 44 | num-lanes = <1>; | ||
| 45 | ti,hwmods = "pcie1"; | ||
| 46 | phys = <&pcie1_phy>; | ||
| 47 | phy-names = "pcie-phy0"; | ||
| 48 | interrupt-map-mask = <0 0 0 7>; | ||
| 49 | interrupt-map = <0 0 0 1 &pcie_intc 1>, | ||
| 50 | <0 0 0 2 &pcie_intc 2>, | ||
| 51 | <0 0 0 3 &pcie_intc 3>, | ||
| 52 | <0 0 0 4 &pcie_intc 4>; | ||
| 53 | pcie_intc: interrupt-controller { | ||
| 54 | interrupt-controller; | ||
| 55 | #address-cells = <0>; | ||
| 56 | #interrupt-cells = <1>; | ||
| 57 | }; | ||
| 58 | }; | ||
| 59 | }; | ||
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index b18dd1779029..f1997e9da61f 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking | |||
| @@ -349,7 +349,11 @@ prototypes: | |||
| 349 | locking rules: | 349 | locking rules: |
| 350 | inode->i_lock may block | 350 | inode->i_lock may block |
| 351 | fl_copy_lock: yes no | 351 | fl_copy_lock: yes no |
| 352 | fl_release_private: maybe no | 352 | fl_release_private: maybe maybe[1] |
| 353 | |||
| 354 | [1]: ->fl_release_private for flock or POSIX locks is currently allowed | ||
| 355 | to block. Leases however can still be freed while the i_lock is held and | ||
| 356 | so fl_release_private called on a lease should not block. | ||
| 353 | 357 | ||
| 354 | ----------------------- lock_manager_operations --------------------------- | 358 | ----------------------- lock_manager_operations --------------------------- |
| 355 | prototypes: | 359 | prototypes: |
diff --git a/Documentation/laptops/00-INDEX b/Documentation/laptops/00-INDEX index d399ae1fc724..a3b4f209e562 100644 --- a/Documentation/laptops/00-INDEX +++ b/Documentation/laptops/00-INDEX | |||
| @@ -18,3 +18,5 @@ sonypi.txt | |||
| 18 | - info on Linux Sony Programmable I/O Device support. | 18 | - info on Linux Sony Programmable I/O Device support. |
| 19 | thinkpad-acpi.txt | 19 | thinkpad-acpi.txt |
| 20 | - information on the (IBM and Lenovo) ThinkPad ACPI Extras driver. | 20 | - information on the (IBM and Lenovo) ThinkPad ACPI Extras driver. |
| 21 | toshiba_haps.txt | ||
| 22 | - information on the Toshiba HDD Active Protection Sensor driver. | ||
diff --git a/Documentation/laptops/toshiba_haps.txt b/Documentation/laptops/toshiba_haps.txt new file mode 100644 index 000000000000..11dbcfdc9e7a --- /dev/null +++ b/Documentation/laptops/toshiba_haps.txt | |||
| @@ -0,0 +1,76 @@ | |||
| 1 | Kernel driver toshiba_haps | ||
| 2 | Toshiba HDD Active Protection Sensor | ||
| 3 | ==================================== | ||
| 4 | |||
| 5 | Author: Azael Avalos <coproscefalo@gmail.com> | ||
| 6 | |||
| 7 | |||
| 8 | 0. Contents | ||
| 9 | ----------- | ||
| 10 | |||
| 11 | 1. Description | ||
| 12 | 2. Interface | ||
| 13 | 3. Accelerometer axes | ||
| 14 | 4. Supported devices | ||
| 15 | 5. Usage | ||
| 16 | |||
| 17 | |||
| 18 | 1. Description | ||
| 19 | -------------- | ||
| 20 | |||
| 21 | This driver provides support for the accelerometer found in various Toshiba | ||
| 22 | laptops, being called "Toshiba HDD Protection - Shock Sensor" officialy, | ||
| 23 | and detects laptops automatically with this device. | ||
| 24 | On Windows, Toshiba provided software monitors this device and provides | ||
| 25 | automatic HDD protection (head unload) on sudden moves or harsh vibrations, | ||
| 26 | however, this driver only provides a notification via a sysfs file to let | ||
| 27 | userspace tools or daemons act accordingly, as well as providing a sysfs | ||
| 28 | file to set the desired protection level or sensor sensibility. | ||
| 29 | |||
| 30 | |||
| 31 | 2. Interface | ||
| 32 | ------------ | ||
| 33 | |||
| 34 | This device comes with 3 methods: | ||
| 35 | _STA - Checks existence of the device, returning Zero if the device does not | ||
| 36 | exists or is not supported. | ||
| 37 | PTLV - Sets the desired protection level. | ||
| 38 | RSSS - Shuts down the HDD protection interface for a few seconds, | ||
| 39 | then restores normal operation. | ||
| 40 | |||
| 41 | Note: | ||
| 42 | The presence of Solid State Drives (SSD) can make this driver to fail loading, | ||
| 43 | given the fact that such drives have no movable parts, and thus, not requiring | ||
| 44 | any "protection" as well as failing during the evaluation of the _STA method | ||
| 45 | found under this device. | ||
| 46 | |||
| 47 | |||
| 48 | 3. Accelerometer axes | ||
| 49 | --------------------- | ||
| 50 | |||
| 51 | This device does not report any axes, however, to query the sensor position | ||
| 52 | a couple HCI (Hardware Configuration Interface) calls (0x6D and 0xA6) are | ||
| 53 | provided to query such information, handled by the kernel module toshiba_acpi | ||
| 54 | since kernel version 3.15. | ||
| 55 | |||
| 56 | |||
| 57 | 4. Supported devices | ||
| 58 | -------------------- | ||
| 59 | |||
| 60 | This driver binds itself to the ACPI device TOS620A, and any Toshiba laptop | ||
| 61 | with this device is supported, given the fact that they have the presence of | ||
| 62 | conventional HDD and not only SSD, or a combination of both HDD and SSD. | ||
| 63 | |||
| 64 | |||
| 65 | 5. Usage | ||
| 66 | -------- | ||
| 67 | |||
| 68 | The sysfs files under /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS620A:00/ are: | ||
| 69 | protection_level - The protection_level is readable and writeable, and | ||
| 70 | provides a way to let userspace query the current protection | ||
| 71 | level, as well as set the desired protection level, the | ||
| 72 | available protection levels are: | ||
| 73 | 0 - Disabled | 1 - Low | 2 - Medium | 3 - High | ||
| 74 | reset_protection - The reset_protection entry is writeable only, being "1" | ||
| 75 | the only parameter it accepts, it is used to trigger | ||
| 76 | a reset of the protection interface. | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 92b5234aad75..f01f54f27750 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -3849,10 +3849,13 @@ F: drivers/tty/serial/ucc_uart.c | |||
| 3849 | 3849 | ||
| 3850 | FREESCALE SOC SOUND DRIVERS | 3850 | FREESCALE SOC SOUND DRIVERS |
| 3851 | M: Timur Tabi <timur@tabi.org> | 3851 | M: Timur Tabi <timur@tabi.org> |
| 3852 | M: Nicolin Chen <nicoleotsuka@gmail.com> | ||
| 3853 | M: Xiubo Li <Li.Xiubo@freescale.com> | ||
| 3852 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) | 3854 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) |
| 3853 | L: linuxppc-dev@lists.ozlabs.org | 3855 | L: linuxppc-dev@lists.ozlabs.org |
| 3854 | S: Maintained | 3856 | S: Maintained |
| 3855 | F: sound/soc/fsl/fsl* | 3857 | F: sound/soc/fsl/fsl* |
| 3858 | F: sound/soc/fsl/imx* | ||
| 3856 | F: sound/soc/fsl/mpc8610_hpcd.c | 3859 | F: sound/soc/fsl/mpc8610_hpcd.c |
| 3857 | 3860 | ||
| 3858 | FREEVXFS FILESYSTEM | 3861 | FREEVXFS FILESYSTEM |
| @@ -4452,6 +4455,13 @@ F: include/linux/i2c-*.h | |||
| 4452 | F: include/uapi/linux/i2c.h | 4455 | F: include/uapi/linux/i2c.h |
| 4453 | F: include/uapi/linux/i2c-*.h | 4456 | F: include/uapi/linux/i2c-*.h |
| 4454 | 4457 | ||
| 4458 | I2C ACPI SUPPORT | ||
| 4459 | M: Mika Westerberg <mika.westerberg@linux.intel.com> | ||
| 4460 | L: linux-i2c@vger.kernel.org | ||
| 4461 | L: linux-acpi@vger.kernel.org | ||
| 4462 | S: Maintained | ||
| 4463 | F: drivers/i2c/i2c-acpi.c | ||
| 4464 | |||
| 4455 | I2C-TAOS-EVM DRIVER | 4465 | I2C-TAOS-EVM DRIVER |
| 4456 | M: Jean Delvare <jdelvare@suse.de> | 4466 | M: Jean Delvare <jdelvare@suse.de> |
| 4457 | L: linux-i2c@vger.kernel.org | 4467 | L: linux-i2c@vger.kernel.org |
| @@ -6870,6 +6880,14 @@ S: Supported | |||
| 6870 | F: Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt | 6880 | F: Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt |
| 6871 | F: drivers/pci/host/pci-tegra.c | 6881 | F: drivers/pci/host/pci-tegra.c |
| 6872 | 6882 | ||
| 6883 | PCI DRIVER FOR TI DRA7XX | ||
| 6884 | M: Kishon Vijay Abraham I <kishon@ti.com> | ||
| 6885 | L: linux-omap@vger.kernel.org | ||
| 6886 | L: linux-pci@vger.kernel.org | ||
| 6887 | S: Supported | ||
| 6888 | F: Documentation/devicetree/bindings/pci/ti-pci.txt | ||
| 6889 | F: drivers/pci/host/pci-dra7xx.c | ||
| 6890 | |||
| 6873 | PCI DRIVER FOR RENESAS R-CAR | 6891 | PCI DRIVER FOR RENESAS R-CAR |
| 6874 | M: Simon Horman <horms@verge.net.au> | 6892 | M: Simon Horman <horms@verge.net.au> |
| 6875 | L: linux-pci@vger.kernel.org | 6893 | L: linux-pci@vger.kernel.org |
| @@ -7071,6 +7089,7 @@ F: drivers/scsi/pmcraid.* | |||
| 7071 | PMC SIERRA PM8001 DRIVER | 7089 | PMC SIERRA PM8001 DRIVER |
| 7072 | M: xjtuwjp@gmail.com | 7090 | M: xjtuwjp@gmail.com |
| 7073 | M: lindar_liu@usish.com | 7091 | M: lindar_liu@usish.com |
| 7092 | L: pmchba@pmcs.com | ||
| 7074 | L: linux-scsi@vger.kernel.org | 7093 | L: linux-scsi@vger.kernel.org |
| 7075 | S: Supported | 7094 | S: Supported |
| 7076 | F: drivers/scsi/pm8001/ | 7095 | F: drivers/scsi/pm8001/ |
| @@ -10028,7 +10047,7 @@ F: arch/x86/ | |||
| 10028 | X86 PLATFORM DRIVERS | 10047 | X86 PLATFORM DRIVERS |
| 10029 | M: Matthew Garrett <matthew.garrett@nebula.com> | 10048 | M: Matthew Garrett <matthew.garrett@nebula.com> |
| 10030 | L: platform-driver-x86@vger.kernel.org | 10049 | L: platform-driver-x86@vger.kernel.org |
| 10031 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86.git | 10050 | T: git git://cavan.codon.org.uk/platform-drivers-x86.git |
| 10032 | S: Maintained | 10051 | S: Maintained |
| 10033 | F: drivers/platform/x86/ | 10052 | F: drivers/platform/x86/ |
| 10034 | 10053 | ||
| @@ -1,7 +1,7 @@ | |||
| 1 | VERSION = 3 | 1 | VERSION = 3 |
| 2 | PATCHLEVEL = 16 | 2 | PATCHLEVEL = 17 |
| 3 | SUBLEVEL = 0 | 3 | SUBLEVEL = 0 |
| 4 | EXTRAVERSION = | 4 | EXTRAVERSION = -rc1 |
| 5 | NAME = Shuffling Zombie Juror | 5 | NAME = Shuffling Zombie Juror |
| 6 | 6 | ||
| 7 | # *DOCUMENTATION* | 7 | # *DOCUMENTATION* |
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index 57833546bf00..2df5e5daeebe 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile | |||
| @@ -39,7 +39,7 @@ head-y := arch/arm64/kernel/head.o | |||
| 39 | 39 | ||
| 40 | # The byte offset of the kernel image in RAM from the start of RAM. | 40 | # The byte offset of the kernel image in RAM from the start of RAM. |
| 41 | ifeq ($(CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET), y) | 41 | ifeq ($(CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET), y) |
| 42 | TEXT_OFFSET := $(shell awk 'BEGIN {srand(); printf "0x%04x0\n", int(65535 * rand())}') | 42 | TEXT_OFFSET := $(shell awk 'BEGIN {srand(); printf "0x%03x000\n", int(512 * rand())}') |
| 43 | else | 43 | else |
| 44 | TEXT_OFFSET := 0x00080000 | 44 | TEXT_OFFSET := 0x00080000 |
| 45 | endif | 45 | endif |
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 1e52b741d806..d92ef3c54161 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig | |||
| @@ -64,6 +64,8 @@ CONFIG_VIRTIO_BLK=y | |||
| 64 | CONFIG_BLK_DEV_SD=y | 64 | CONFIG_BLK_DEV_SD=y |
| 65 | # CONFIG_SCSI_LOWLEVEL is not set | 65 | # CONFIG_SCSI_LOWLEVEL is not set |
| 66 | CONFIG_ATA=y | 66 | CONFIG_ATA=y |
| 67 | CONFIG_AHCI_XGENE=y | ||
| 68 | CONFIG_PHY_XGENE=y | ||
| 67 | CONFIG_PATA_PLATFORM=y | 69 | CONFIG_PATA_PLATFORM=y |
| 68 | CONFIG_PATA_OF_PLATFORM=y | 70 | CONFIG_PATA_OF_PLATFORM=y |
| 69 | CONFIG_NETDEVICES=y | 71 | CONFIG_NETDEVICES=y |
| @@ -71,6 +73,7 @@ CONFIG_TUN=y | |||
| 71 | CONFIG_VIRTIO_NET=y | 73 | CONFIG_VIRTIO_NET=y |
| 72 | CONFIG_SMC91X=y | 74 | CONFIG_SMC91X=y |
| 73 | CONFIG_SMSC911X=y | 75 | CONFIG_SMSC911X=y |
| 76 | CONFIG_NET_XGENE=y | ||
| 74 | # CONFIG_WLAN is not set | 77 | # CONFIG_WLAN is not set |
| 75 | CONFIG_INPUT_EVDEV=y | 78 | CONFIG_INPUT_EVDEV=y |
| 76 | # CONFIG_SERIO_SERPORT is not set | 79 | # CONFIG_SERIO_SERPORT is not set |
diff --git a/arch/arm64/include/asm/sparsemem.h b/arch/arm64/include/asm/sparsemem.h index 1be62bcb9d47..74a9d301819f 100644 --- a/arch/arm64/include/asm/sparsemem.h +++ b/arch/arm64/include/asm/sparsemem.h | |||
| @@ -17,7 +17,7 @@ | |||
| 17 | #define __ASM_SPARSEMEM_H | 17 | #define __ASM_SPARSEMEM_H |
| 18 | 18 | ||
| 19 | #ifdef CONFIG_SPARSEMEM | 19 | #ifdef CONFIG_SPARSEMEM |
| 20 | #define MAX_PHYSMEM_BITS 40 | 20 | #define MAX_PHYSMEM_BITS 48 |
| 21 | #define SECTION_SIZE_BITS 30 | 21 | #define SECTION_SIZE_BITS 30 |
| 22 | #endif | 22 | #endif |
| 23 | 23 | ||
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h index 4bc95d27e063..6d2bf419431d 100644 --- a/arch/arm64/include/asm/unistd.h +++ b/arch/arm64/include/asm/unistd.h | |||
| @@ -41,7 +41,7 @@ | |||
| 41 | #define __ARM_NR_compat_cacheflush (__ARM_NR_COMPAT_BASE+2) | 41 | #define __ARM_NR_compat_cacheflush (__ARM_NR_COMPAT_BASE+2) |
| 42 | #define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE+5) | 42 | #define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE+5) |
| 43 | 43 | ||
| 44 | #define __NR_compat_syscalls 383 | 44 | #define __NR_compat_syscalls 386 |
| 45 | #endif | 45 | #endif |
| 46 | 46 | ||
| 47 | #define __ARCH_WANT_SYS_CLONE | 47 | #define __ARCH_WANT_SYS_CLONE |
diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h index e242600c4046..da1f06b535e3 100644 --- a/arch/arm64/include/asm/unistd32.h +++ b/arch/arm64/include/asm/unistd32.h | |||
| @@ -787,3 +787,8 @@ __SYSCALL(__NR_sched_setattr, sys_sched_setattr) | |||
| 787 | __SYSCALL(__NR_sched_getattr, sys_sched_getattr) | 787 | __SYSCALL(__NR_sched_getattr, sys_sched_getattr) |
| 788 | #define __NR_renameat2 382 | 788 | #define __NR_renameat2 382 |
| 789 | __SYSCALL(__NR_renameat2, sys_renameat2) | 789 | __SYSCALL(__NR_renameat2, sys_renameat2) |
| 790 | /* 383 for seccomp */ | ||
| 791 | #define __NR_getrandom 384 | ||
| 792 | __SYSCALL(__NR_getrandom, sys_getrandom) | ||
| 793 | #define __NR_memfd_create 385 | ||
| 794 | __SYSCALL(__NR_memfd_create, sys_memfd_create) | ||
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c index f798f66634af..177169623026 100644 --- a/arch/arm64/kernel/cpuinfo.c +++ b/arch/arm64/kernel/cpuinfo.c | |||
| @@ -49,7 +49,7 @@ static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info) | |||
| 49 | 49 | ||
| 50 | if (l1ip != ICACHE_POLICY_PIPT) | 50 | if (l1ip != ICACHE_POLICY_PIPT) |
| 51 | set_bit(ICACHEF_ALIASING, &__icache_flags); | 51 | set_bit(ICACHEF_ALIASING, &__icache_flags); |
| 52 | if (l1ip == ICACHE_POLICY_AIVIVT); | 52 | if (l1ip == ICACHE_POLICY_AIVIVT) |
| 53 | set_bit(ICACHEF_AIVIVT, &__icache_flags); | 53 | set_bit(ICACHEF_AIVIVT, &__icache_flags); |
| 54 | 54 | ||
| 55 | pr_info("Detected %s I-cache on CPU%d\n", icache_policy_str[l1ip], cpu); | 55 | pr_info("Detected %s I-cache on CPU%d\n", icache_policy_str[l1ip], cpu); |
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index e72f3100958f..24f0c6fb61d8 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c | |||
| @@ -188,6 +188,8 @@ static __init void reserve_regions(void) | |||
| 188 | if (uefi_debug) | 188 | if (uefi_debug) |
| 189 | pr_cont("\n"); | 189 | pr_cont("\n"); |
| 190 | } | 190 | } |
| 191 | |||
| 192 | set_bit(EFI_MEMMAP, &efi.flags); | ||
| 191 | } | 193 | } |
| 192 | 194 | ||
| 193 | 195 | ||
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 144f10567f82..bed028364a93 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S | |||
| @@ -38,11 +38,11 @@ | |||
| 38 | 38 | ||
| 39 | #define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET) | 39 | #define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET) |
| 40 | 40 | ||
| 41 | #if (TEXT_OFFSET & 0xf) != 0 | 41 | #if (TEXT_OFFSET & 0xfff) != 0 |
| 42 | #error TEXT_OFFSET must be at least 16B aligned | 42 | #error TEXT_OFFSET must be at least 4KB aligned |
| 43 | #elif (PAGE_OFFSET & 0xfffff) != 0 | 43 | #elif (PAGE_OFFSET & 0x1fffff) != 0 |
| 44 | #error PAGE_OFFSET must be at least 2MB aligned | 44 | #error PAGE_OFFSET must be at least 2MB aligned |
| 45 | #elif TEXT_OFFSET > 0xfffff | 45 | #elif TEXT_OFFSET > 0x1fffff |
| 46 | #error TEXT_OFFSET must be less than 2MB | 46 | #error TEXT_OFFSET must be less than 2MB |
| 47 | #endif | 47 | #endif |
| 48 | 48 | ||
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index 0310811bd77d..70526cfda056 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c | |||
| @@ -1115,19 +1115,15 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs) | |||
| 1115 | if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) | 1115 | if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) |
| 1116 | trace_sys_enter(regs, regs->syscallno); | 1116 | trace_sys_enter(regs, regs->syscallno); |
| 1117 | 1117 | ||
| 1118 | #ifdef CONFIG_AUDITSYSCALL | ||
| 1119 | audit_syscall_entry(syscall_get_arch(), regs->syscallno, | 1118 | audit_syscall_entry(syscall_get_arch(), regs->syscallno, |
| 1120 | regs->orig_x0, regs->regs[1], regs->regs[2], regs->regs[3]); | 1119 | regs->orig_x0, regs->regs[1], regs->regs[2], regs->regs[3]); |
| 1121 | #endif | ||
| 1122 | 1120 | ||
| 1123 | return regs->syscallno; | 1121 | return regs->syscallno; |
| 1124 | } | 1122 | } |
| 1125 | 1123 | ||
| 1126 | asmlinkage void syscall_trace_exit(struct pt_regs *regs) | 1124 | asmlinkage void syscall_trace_exit(struct pt_regs *regs) |
| 1127 | { | 1125 | { |
| 1128 | #ifdef CONFIG_AUDITSYSCALL | ||
| 1129 | audit_syscall_exit(regs); | 1126 | audit_syscall_exit(regs); |
| 1130 | #endif | ||
| 1131 | 1127 | ||
| 1132 | if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) | 1128 | if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) |
| 1133 | trace_sys_exit(regs, regs_return_value(regs)); | 1129 | trace_sys_exit(regs, regs_return_value(regs)); |
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 5b4526ee3a01..5472c2401876 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/of_fdt.h> | 32 | #include <linux/of_fdt.h> |
| 33 | #include <linux/dma-mapping.h> | 33 | #include <linux/dma-mapping.h> |
| 34 | #include <linux/dma-contiguous.h> | 34 | #include <linux/dma-contiguous.h> |
| 35 | #include <linux/efi.h> | ||
| 35 | 36 | ||
| 36 | #include <asm/fixmap.h> | 37 | #include <asm/fixmap.h> |
| 37 | #include <asm/sections.h> | 38 | #include <asm/sections.h> |
| @@ -148,7 +149,8 @@ void __init arm64_memblock_init(void) | |||
| 148 | memblock_reserve(__virt_to_phys(initrd_start), initrd_end - initrd_start); | 149 | memblock_reserve(__virt_to_phys(initrd_start), initrd_end - initrd_start); |
| 149 | #endif | 150 | #endif |
| 150 | 151 | ||
| 151 | early_init_fdt_scan_reserved_mem(); | 152 | if (!efi_enabled(EFI_MEMMAP)) |
| 153 | early_init_fdt_scan_reserved_mem(); | ||
| 152 | 154 | ||
| 153 | /* 4GB maximum for 32-bit only capable devices */ | 155 | /* 4GB maximum for 32-bit only capable devices */ |
| 154 | if (IS_ENABLED(CONFIG_ZONE_DMA)) | 156 | if (IS_ENABLED(CONFIG_ZONE_DMA)) |
diff --git a/arch/frv/include/asm/processor.h b/arch/frv/include/asm/processor.h index a34f309e5801..6554e78893f2 100644 --- a/arch/frv/include/asm/processor.h +++ b/arch/frv/include/asm/processor.h | |||
| @@ -129,7 +129,8 @@ unsigned long get_wchan(struct task_struct *p); | |||
| 129 | #define KSTK_EIP(tsk) ((tsk)->thread.frame0->pc) | 129 | #define KSTK_EIP(tsk) ((tsk)->thread.frame0->pc) |
| 130 | #define KSTK_ESP(tsk) ((tsk)->thread.frame0->sp) | 130 | #define KSTK_ESP(tsk) ((tsk)->thread.frame0->sp) |
| 131 | 131 | ||
| 132 | #define cpu_relax() barrier() | 132 | #define cpu_relax() barrier() |
| 133 | #define cpu_relax_lowlatency() cpu_relax() | ||
| 133 | 134 | ||
| 134 | /* data cache prefetch */ | 135 | /* data cache prefetch */ |
| 135 | #define ARCH_HAS_PREFETCH | 136 | #define ARCH_HAS_PREFETCH |
diff --git a/arch/ia64/include/asm/unistd.h b/arch/ia64/include/asm/unistd.h index 4254f5d3218c..10a14ead70b9 100644 --- a/arch/ia64/include/asm/unistd.h +++ b/arch/ia64/include/asm/unistd.h | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | #define NR_syscalls 316 /* length of syscall table */ | 14 | #define NR_syscalls 317 /* length of syscall table */ |
| 15 | 15 | ||
| 16 | /* | 16 | /* |
| 17 | * The following defines stop scripts/checksyscalls.sh from complaining about | 17 | * The following defines stop scripts/checksyscalls.sh from complaining about |
diff --git a/arch/ia64/include/uapi/asm/unistd.h b/arch/ia64/include/uapi/asm/unistd.h index 99801c3be914..6a65bb7d0657 100644 --- a/arch/ia64/include/uapi/asm/unistd.h +++ b/arch/ia64/include/uapi/asm/unistd.h | |||
| @@ -329,5 +329,6 @@ | |||
| 329 | #define __NR_sched_getattr 1337 | 329 | #define __NR_sched_getattr 1337 |
| 330 | #define __NR_renameat2 1338 | 330 | #define __NR_renameat2 1338 |
| 331 | #define __NR_getrandom 1339 | 331 | #define __NR_getrandom 1339 |
| 332 | #define __NR_memfd_create 1339 | ||
| 332 | 333 | ||
| 333 | #endif /* _UAPI_ASM_IA64_UNISTD_H */ | 334 | #endif /* _UAPI_ASM_IA64_UNISTD_H */ |
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 4c13837a9269..01edf242eb29 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S | |||
| @@ -1777,6 +1777,7 @@ sys_call_table: | |||
| 1777 | data8 sys_sched_getattr | 1777 | data8 sys_sched_getattr |
| 1778 | data8 sys_renameat2 | 1778 | data8 sys_renameat2 |
| 1779 | data8 sys_getrandom | 1779 | data8 sys_getrandom |
| 1780 | data8 sys_memfd_create // 1340 | ||
| 1780 | 1781 | ||
| 1781 | .org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls | 1782 | .org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls |
| 1782 | #endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */ | 1783 | #endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */ |
diff --git a/arch/microblaze/include/uapi/asm/unistd.h b/arch/microblaze/include/uapi/asm/unistd.h index 4e1ddc930a68..1c2380bf8fe6 100644 --- a/arch/microblaze/include/uapi/asm/unistd.h +++ b/arch/microblaze/include/uapi/asm/unistd.h | |||
| @@ -399,5 +399,8 @@ | |||
| 399 | #define __NR_sched_setattr 381 | 399 | #define __NR_sched_setattr 381 |
| 400 | #define __NR_sched_getattr 382 | 400 | #define __NR_sched_getattr 382 |
| 401 | #define __NR_renameat2 383 | 401 | #define __NR_renameat2 383 |
| 402 | #define __NR_seccomp 384 | ||
| 403 | #define __NR_getrandom 385 | ||
| 404 | #define __NR_memfd_create 386 | ||
| 402 | 405 | ||
| 403 | #endif /* _UAPI_ASM_MICROBLAZE_UNISTD_H */ | 406 | #endif /* _UAPI_ASM_MICROBLAZE_UNISTD_H */ |
diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S index 1a23d5d5480c..de59ee1d7010 100644 --- a/arch/microblaze/kernel/syscall_table.S +++ b/arch/microblaze/kernel/syscall_table.S | |||
| @@ -384,3 +384,6 @@ ENTRY(sys_call_table) | |||
| 384 | .long sys_sched_setattr | 384 | .long sys_sched_setattr |
| 385 | .long sys_sched_getattr | 385 | .long sys_sched_getattr |
| 386 | .long sys_renameat2 | 386 | .long sys_renameat2 |
| 387 | .long sys_seccomp | ||
| 388 | .long sys_getrandom /* 385 */ | ||
| 389 | .long sys_memfd_create | ||
diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c index 329d7fdd0a6a..b9615ba5b083 100644 --- a/arch/powerpc/kvm/book3s_hv_builtin.c +++ b/arch/powerpc/kvm/book3s_hv_builtin.c | |||
| @@ -101,7 +101,7 @@ struct kvm_rma_info *kvm_alloc_rma() | |||
| 101 | ri = kmalloc(sizeof(struct kvm_rma_info), GFP_KERNEL); | 101 | ri = kmalloc(sizeof(struct kvm_rma_info), GFP_KERNEL); |
| 102 | if (!ri) | 102 | if (!ri) |
| 103 | return NULL; | 103 | return NULL; |
| 104 | page = cma_alloc(kvm_cma, kvm_rma_pages, get_order(kvm_rma_pages)); | 104 | page = cma_alloc(kvm_cma, kvm_rma_pages, order_base_2(kvm_rma_pages)); |
| 105 | if (!page) | 105 | if (!page) |
| 106 | goto err_out; | 106 | goto err_out; |
| 107 | atomic_set(&ri->use_count, 1); | 107 | atomic_set(&ri->use_count, 1); |
| @@ -135,12 +135,12 @@ struct page *kvm_alloc_hpt(unsigned long nr_pages) | |||
| 135 | { | 135 | { |
| 136 | unsigned long align_pages = HPT_ALIGN_PAGES; | 136 | unsigned long align_pages = HPT_ALIGN_PAGES; |
| 137 | 137 | ||
| 138 | VM_BUG_ON(get_order(nr_pages) < KVM_CMA_CHUNK_ORDER - PAGE_SHIFT); | 138 | VM_BUG_ON(order_base_2(nr_pages) < KVM_CMA_CHUNK_ORDER - PAGE_SHIFT); |
| 139 | 139 | ||
| 140 | /* Old CPUs require HPT aligned on a multiple of its size */ | 140 | /* Old CPUs require HPT aligned on a multiple of its size */ |
| 141 | if (!cpu_has_feature(CPU_FTR_ARCH_206)) | 141 | if (!cpu_has_feature(CPU_FTR_ARCH_206)) |
| 142 | align_pages = nr_pages; | 142 | align_pages = nr_pages; |
| 143 | return cma_alloc(kvm_cma, nr_pages, get_order(align_pages)); | 143 | return cma_alloc(kvm_cma, nr_pages, order_base_2(align_pages)); |
| 144 | } | 144 | } |
| 145 | EXPORT_SYMBOL_GPL(kvm_alloc_hpt); | 145 | EXPORT_SYMBOL_GPL(kvm_alloc_hpt); |
| 146 | 146 | ||
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 572460175ba5..7c492ed9087b 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h | |||
| @@ -95,7 +95,7 @@ static inline gfn_t gfn_to_index(gfn_t gfn, gfn_t base_gfn, int level) | |||
| 95 | #define KVM_REFILL_PAGES 25 | 95 | #define KVM_REFILL_PAGES 25 |
| 96 | #define KVM_MAX_CPUID_ENTRIES 80 | 96 | #define KVM_MAX_CPUID_ENTRIES 80 |
| 97 | #define KVM_NR_FIXED_MTRR_REGION 88 | 97 | #define KVM_NR_FIXED_MTRR_REGION 88 |
| 98 | #define KVM_NR_VAR_MTRR 10 | 98 | #define KVM_NR_VAR_MTRR 8 |
| 99 | 99 | ||
| 100 | #define ASYNC_PF_PER_VCPU 64 | 100 | #define ASYNC_PF_PER_VCPU 64 |
| 101 | 101 | ||
diff --git a/arch/x86/include/uapi/asm/msr-index.h b/arch/x86/include/uapi/asm/msr-index.h index eac9e92fe181..e21331ce368f 100644 --- a/arch/x86/include/uapi/asm/msr-index.h +++ b/arch/x86/include/uapi/asm/msr-index.h | |||
| @@ -149,6 +149,9 @@ | |||
| 149 | 149 | ||
| 150 | #define MSR_CORE_C1_RES 0x00000660 | 150 | #define MSR_CORE_C1_RES 0x00000660 |
| 151 | 151 | ||
| 152 | #define MSR_CC6_DEMOTION_POLICY_CONFIG 0x00000668 | ||
| 153 | #define MSR_MC6_DEMOTION_POLICY_CONFIG 0x00000669 | ||
| 154 | |||
| 152 | #define MSR_AMD64_MC0_MASK 0xc0010044 | 155 | #define MSR_AMD64_MC0_MASK 0xc0010044 |
| 153 | 156 | ||
| 154 | #define MSR_IA32_MCx_CTL(x) (MSR_IA32_MC0_CTL + 4*(x)) | 157 | #define MSR_IA32_MCx_CTL(x) (MSR_IA32_MC0_CTL + 4*(x)) |
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 56657b0bb3bb..03954f7900f5 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
| @@ -1491,9 +1491,6 @@ static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt, | |||
| 1491 | goto exception; | 1491 | goto exception; |
| 1492 | break; | 1492 | break; |
| 1493 | case VCPU_SREG_CS: | 1493 | case VCPU_SREG_CS: |
| 1494 | if (in_task_switch && rpl != dpl) | ||
| 1495 | goto exception; | ||
| 1496 | |||
| 1497 | if (!(seg_desc.type & 8)) | 1494 | if (!(seg_desc.type & 8)) |
| 1498 | goto exception; | 1495 | goto exception; |
| 1499 | 1496 | ||
| @@ -4394,8 +4391,11 @@ done_prefixes: | |||
| 4394 | 4391 | ||
| 4395 | ctxt->execute = opcode.u.execute; | 4392 | ctxt->execute = opcode.u.execute; |
| 4396 | 4393 | ||
| 4394 | if (unlikely(ctxt->ud) && likely(!(ctxt->d & EmulateOnUD))) | ||
| 4395 | return EMULATION_FAILED; | ||
| 4396 | |||
| 4397 | if (unlikely(ctxt->d & | 4397 | if (unlikely(ctxt->d & |
| 4398 | (NotImpl|EmulateOnUD|Stack|Op3264|Sse|Mmx|Intercept|CheckPerm))) { | 4398 | (NotImpl|Stack|Op3264|Sse|Mmx|Intercept|CheckPerm))) { |
| 4399 | /* | 4399 | /* |
| 4400 | * These are copied unconditionally here, and checked unconditionally | 4400 | * These are copied unconditionally here, and checked unconditionally |
| 4401 | * in x86_emulate_insn. | 4401 | * in x86_emulate_insn. |
| @@ -4406,9 +4406,6 @@ done_prefixes: | |||
| 4406 | if (ctxt->d & NotImpl) | 4406 | if (ctxt->d & NotImpl) |
| 4407 | return EMULATION_FAILED; | 4407 | return EMULATION_FAILED; |
| 4408 | 4408 | ||
| 4409 | if (!(ctxt->d & EmulateOnUD) && ctxt->ud) | ||
| 4410 | return EMULATION_FAILED; | ||
| 4411 | |||
| 4412 | if (mode == X86EMUL_MODE_PROT64 && (ctxt->d & Stack)) | 4409 | if (mode == X86EMUL_MODE_PROT64 && (ctxt->d & Stack)) |
| 4413 | ctxt->op_bytes = 8; | 4410 | ctxt->op_bytes = 8; |
| 4414 | 4411 | ||
diff --git a/drivers/ata/ahci_tegra.c b/drivers/ata/ahci_tegra.c index fc3df47fca35..f1fef74e503c 100644 --- a/drivers/ata/ahci_tegra.c +++ b/drivers/ata/ahci_tegra.c | |||
| @@ -24,8 +24,8 @@ | |||
| 24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
| 25 | #include <linux/of_device.h> | 25 | #include <linux/of_device.h> |
| 26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
| 27 | #include <linux/tegra-powergate.h> | ||
| 28 | #include <linux/regulator/consumer.h> | 27 | #include <linux/regulator/consumer.h> |
| 28 | #include <soc/tegra/pmc.h> | ||
| 29 | #include "ahci.h" | 29 | #include "ahci.h" |
| 30 | 30 | ||
| 31 | #define SATA_CONFIGURATION_0 0x180 | 31 | #define SATA_CONFIGURATION_0 0x180 |
diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c index bc281115490b..c6962300b93c 100644 --- a/drivers/ata/ahci_xgene.c +++ b/drivers/ata/ahci_xgene.c | |||
| @@ -344,7 +344,7 @@ static struct ata_port_operations xgene_ahci_ops = { | |||
| 344 | }; | 344 | }; |
| 345 | 345 | ||
| 346 | static const struct ata_port_info xgene_ahci_port_info = { | 346 | static const struct ata_port_info xgene_ahci_port_info = { |
| 347 | .flags = AHCI_FLAG_COMMON | ATA_FLAG_NCQ, | 347 | .flags = AHCI_FLAG_COMMON, |
| 348 | .pio_mask = ATA_PIO4, | 348 | .pio_mask = ATA_PIO4, |
| 349 | .udma_mask = ATA_UDMA6, | 349 | .udma_mask = ATA_UDMA6, |
| 350 | .port_ops = &xgene_ahci_ops, | 350 | .port_ops = &xgene_ahci_ops, |
| @@ -480,7 +480,7 @@ static int xgene_ahci_probe(struct platform_device *pdev) | |||
| 480 | /* Configure the host controller */ | 480 | /* Configure the host controller */ |
| 481 | xgene_ahci_hw_init(hpriv); | 481 | xgene_ahci_hw_init(hpriv); |
| 482 | 482 | ||
| 483 | hpriv->flags = AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ; | 483 | hpriv->flags = AHCI_HFLAG_NO_PMP | AHCI_HFLAG_NO_NCQ; |
| 484 | 484 | ||
| 485 | rc = ahci_platform_init_host(pdev, hpriv, &xgene_ahci_port_info); | 485 | rc = ahci_platform_init_host(pdev, hpriv, &xgene_ahci_port_info); |
| 486 | if (rc) | 486 | if (rc) |
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index dbdc5d32343f..f3e7b9f894cd 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
| @@ -4228,7 +4228,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { | |||
| 4228 | { "Micron_M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, | 4228 | { "Micron_M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, |
| 4229 | { "Crucial_CT???M500SSD*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, | 4229 | { "Crucial_CT???M500SSD*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, |
| 4230 | { "Micron_M550*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, | 4230 | { "Micron_M550*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, |
| 4231 | { "Crucial_CT???M550SSD*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, | 4231 | { "Crucial_CT*M550SSD*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, |
| 4232 | 4232 | ||
| 4233 | /* | 4233 | /* |
| 4234 | * Some WD SATA-I drives spin up and down erratically when the link | 4234 | * Some WD SATA-I drives spin up and down erratically when the link |
diff --git a/drivers/ata/pata_samsung_cf.c b/drivers/ata/pata_samsung_cf.c index 2578fc16960a..1a24a5dc3940 100644 --- a/drivers/ata/pata_samsung_cf.c +++ b/drivers/ata/pata_samsung_cf.c | |||
| @@ -360,7 +360,7 @@ static int pata_s3c_wait_after_reset(struct ata_link *link, | |||
| 360 | /* | 360 | /* |
| 361 | * pata_s3c_bus_softreset - PATA device software reset | 361 | * pata_s3c_bus_softreset - PATA device software reset |
| 362 | */ | 362 | */ |
| 363 | static unsigned int pata_s3c_bus_softreset(struct ata_port *ap, | 363 | static int pata_s3c_bus_softreset(struct ata_port *ap, |
| 364 | unsigned long deadline) | 364 | unsigned long deadline) |
| 365 | { | 365 | { |
| 366 | struct ata_ioports *ioaddr = &ap->ioaddr; | 366 | struct ata_ioports *ioaddr = &ap->ioaddr; |
diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c index 4e006d74bef8..7f4cb76ed9fa 100644 --- a/drivers/ata/pata_scc.c +++ b/drivers/ata/pata_scc.c | |||
| @@ -585,7 +585,7 @@ static int scc_wait_after_reset(struct ata_link *link, unsigned int devmask, | |||
| 585 | * Note: Original code is ata_bus_softreset(). | 585 | * Note: Original code is ata_bus_softreset(). |
| 586 | */ | 586 | */ |
| 587 | 587 | ||
| 588 | static unsigned int scc_bus_softreset(struct ata_port *ap, unsigned int devmask, | 588 | static int scc_bus_softreset(struct ata_port *ap, unsigned int devmask, |
| 589 | unsigned long deadline) | 589 | unsigned long deadline) |
| 590 | { | 590 | { |
| 591 | struct ata_ioports *ioaddr = &ap->ioaddr; | 591 | struct ata_ioports *ioaddr = &ap->ioaddr; |
| @@ -599,9 +599,7 @@ static unsigned int scc_bus_softreset(struct ata_port *ap, unsigned int devmask, | |||
| 599 | udelay(20); | 599 | udelay(20); |
| 600 | out_be32(ioaddr->ctl_addr, ap->ctl); | 600 | out_be32(ioaddr->ctl_addr, ap->ctl); |
| 601 | 601 | ||
| 602 | scc_wait_after_reset(&ap->link, devmask, deadline); | 602 | return scc_wait_after_reset(&ap->link, devmask, deadline); |
| 603 | |||
| 604 | return 0; | ||
| 605 | } | 603 | } |
| 606 | 604 | ||
| 607 | /** | 605 | /** |
| @@ -618,7 +616,8 @@ static int scc_softreset(struct ata_link *link, unsigned int *classes, | |||
| 618 | { | 616 | { |
| 619 | struct ata_port *ap = link->ap; | 617 | struct ata_port *ap = link->ap; |
| 620 | unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS; | 618 | unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS; |
| 621 | unsigned int devmask = 0, err_mask; | 619 | unsigned int devmask = 0; |
| 620 | int rc; | ||
| 622 | u8 err; | 621 | u8 err; |
| 623 | 622 | ||
| 624 | DPRINTK("ENTER\n"); | 623 | DPRINTK("ENTER\n"); |
| @@ -634,9 +633,9 @@ static int scc_softreset(struct ata_link *link, unsigned int *classes, | |||
| 634 | 633 | ||
| 635 | /* issue bus reset */ | 634 | /* issue bus reset */ |
| 636 | DPRINTK("about to softreset, devmask=%x\n", devmask); | 635 | DPRINTK("about to softreset, devmask=%x\n", devmask); |
| 637 | err_mask = scc_bus_softreset(ap, devmask, deadline); | 636 | rc = scc_bus_softreset(ap, devmask, deadline); |
| 638 | if (err_mask) { | 637 | if (rc) { |
| 639 | ata_port_err(ap, "SRST failed (err_mask=0x%x)\n", err_mask); | 638 | ata_port_err(ap, "SRST failed (err_mask=0x%x)\n", rc); |
| 640 | return -EIO; | 639 | return -EIO; |
| 641 | } | 640 | } |
| 642 | 641 | ||
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index 0027137daa56..2e3139eda93b 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c | |||
| @@ -116,6 +116,7 @@ static int probe_common(struct virtio_device *vdev) | |||
| 116 | .cleanup = virtio_cleanup, | 116 | .cleanup = virtio_cleanup, |
| 117 | .priv = (unsigned long)vi, | 117 | .priv = (unsigned long)vi, |
| 118 | .name = vi->name, | 118 | .name = vi->name, |
| 119 | .quality = 1000, | ||
| 119 | }; | 120 | }; |
| 120 | vdev->priv = vi; | 121 | vdev->priv = vi; |
| 121 | 122 | ||
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index f8665f9c3e03..fd89ca982748 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig | |||
| @@ -253,12 +253,12 @@ config EDAC_I7300 | |||
| 253 | Clarksboro MCH (Intel 7300 chipset). | 253 | Clarksboro MCH (Intel 7300 chipset). |
| 254 | 254 | ||
| 255 | config EDAC_SBRIDGE | 255 | config EDAC_SBRIDGE |
| 256 | tristate "Intel Sandy-Bridge Integrated MC" | 256 | tristate "Intel Sandy-Bridge/Ivy-Bridge/Haswell Integrated MC" |
| 257 | depends on EDAC_MM_EDAC && PCI && X86_64 && X86_MCE_INTEL | 257 | depends on EDAC_MM_EDAC && PCI && X86_64 && X86_MCE_INTEL |
| 258 | depends on PCI_MMCONFIG | 258 | depends on PCI_MMCONFIG |
| 259 | help | 259 | help |
| 260 | Support for error detection and correction the Intel | 260 | Support for error detection and correction the Intel |
| 261 | Sandy Bridge Integrated Memory Controller. | 261 | Sandy Bridge, Ivy Bridge and Haswell Integrated Memory Controllers. |
| 262 | 262 | ||
| 263 | config EDAC_MPC85XX | 263 | config EDAC_MPC85XX |
| 264 | tristate "Freescale MPC83xx / MPC85xx" | 264 | tristate "Freescale MPC83xx / MPC85xx" |
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 01fae8289cf0..a6cd36100663 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c | |||
| @@ -108,7 +108,9 @@ static const char * const mem_types[] = { | |||
| 108 | [MEM_RDDR2] = "Registered-DDR2", | 108 | [MEM_RDDR2] = "Registered-DDR2", |
| 109 | [MEM_XDR] = "XDR", | 109 | [MEM_XDR] = "XDR", |
| 110 | [MEM_DDR3] = "Unbuffered-DDR3", | 110 | [MEM_DDR3] = "Unbuffered-DDR3", |
| 111 | [MEM_RDDR3] = "Registered-DDR3" | 111 | [MEM_RDDR3] = "Registered-DDR3", |
| 112 | [MEM_DDR4] = "Unbuffered-DDR4", | ||
| 113 | [MEM_RDDR4] = "Registered-DDR4" | ||
| 112 | }; | 114 | }; |
| 113 | 115 | ||
| 114 | static const char * const dev_types[] = { | 116 | static const char * const dev_types[] = { |
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index deea0dc9999b..0034c4844428 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c | |||
| @@ -99,6 +99,7 @@ static const u32 ibridge_dram_rule[] = { | |||
| 99 | #define DRAM_ATTR(reg) GET_BITFIELD(reg, 2, 3) | 99 | #define DRAM_ATTR(reg) GET_BITFIELD(reg, 2, 3) |
| 100 | #define INTERLEAVE_MODE(reg) GET_BITFIELD(reg, 1, 1) | 100 | #define INTERLEAVE_MODE(reg) GET_BITFIELD(reg, 1, 1) |
| 101 | #define DRAM_RULE_ENABLE(reg) GET_BITFIELD(reg, 0, 0) | 101 | #define DRAM_RULE_ENABLE(reg) GET_BITFIELD(reg, 0, 0) |
| 102 | #define A7MODE(reg) GET_BITFIELD(reg, 26, 26) | ||
| 102 | 103 | ||
| 103 | static char *get_dram_attr(u32 reg) | 104 | static char *get_dram_attr(u32 reg) |
| 104 | { | 105 | { |
| @@ -164,6 +165,8 @@ static inline int sad_pkg(const struct interleave_pkg *table, u32 reg, | |||
| 164 | 165 | ||
| 165 | #define TOLM 0x80 | 166 | #define TOLM 0x80 |
| 166 | #define TOHM 0x84 | 167 | #define TOHM 0x84 |
| 168 | #define HASWELL_TOHM_0 0xd4 | ||
| 169 | #define HASWELL_TOHM_1 0xd8 | ||
| 167 | 170 | ||
| 168 | #define GET_TOLM(reg) ((GET_BITFIELD(reg, 0, 3) << 28) | 0x3ffffff) | 171 | #define GET_TOLM(reg) ((GET_BITFIELD(reg, 0, 3) << 28) | 0x3ffffff) |
| 169 | #define GET_TOHM(reg) ((GET_BITFIELD(reg, 0, 20) << 25) | 0x3ffffff) | 172 | #define GET_TOHM(reg) ((GET_BITFIELD(reg, 0, 20) << 25) | 0x3ffffff) |
| @@ -176,8 +179,6 @@ static inline int sad_pkg(const struct interleave_pkg *table, u32 reg, | |||
| 176 | 179 | ||
| 177 | #define SAD_CONTROL 0xf4 | 180 | #define SAD_CONTROL 0xf4 |
| 178 | 181 | ||
| 179 | #define NODE_ID(reg) GET_BITFIELD(reg, 0, 2) | ||
| 180 | |||
| 181 | /* Device 14 function 0 */ | 182 | /* Device 14 function 0 */ |
| 182 | 183 | ||
| 183 | static const u32 tad_dram_rule[] = { | 184 | static const u32 tad_dram_rule[] = { |
| @@ -235,7 +236,6 @@ static const u32 rir_way_limit[] = { | |||
| 235 | 236 | ||
| 236 | #define IS_RIR_VALID(reg) GET_BITFIELD(reg, 31, 31) | 237 | #define IS_RIR_VALID(reg) GET_BITFIELD(reg, 31, 31) |
| 237 | #define RIR_WAY(reg) GET_BITFIELD(reg, 28, 29) | 238 | #define RIR_WAY(reg) GET_BITFIELD(reg, 28, 29) |
| 238 | #define RIR_LIMIT(reg) ((GET_BITFIELD(reg, 1, 10) << 29)| 0x1fffffff) | ||
| 239 | 239 | ||
| 240 | #define MAX_RIR_WAY 8 | 240 | #define MAX_RIR_WAY 8 |
| 241 | 241 | ||
| @@ -279,8 +279,6 @@ static const u32 correrrthrsld[] = { | |||
| 279 | 279 | ||
| 280 | #define IB_RANK_CFG_A 0x0320 | 280 | #define IB_RANK_CFG_A 0x0320 |
| 281 | 281 | ||
| 282 | #define IS_RDIMM_ENABLED(reg) GET_BITFIELD(reg, 11, 11) | ||
| 283 | |||
| 284 | /* | 282 | /* |
| 285 | * sbridge structs | 283 | * sbridge structs |
| 286 | */ | 284 | */ |
| @@ -291,6 +289,7 @@ static const u32 correrrthrsld[] = { | |||
| 291 | enum type { | 289 | enum type { |
| 292 | SANDY_BRIDGE, | 290 | SANDY_BRIDGE, |
| 293 | IVY_BRIDGE, | 291 | IVY_BRIDGE, |
| 292 | HASWELL, | ||
| 294 | }; | 293 | }; |
| 295 | 294 | ||
| 296 | struct sbridge_pvt; | 295 | struct sbridge_pvt; |
| @@ -300,11 +299,15 @@ struct sbridge_info { | |||
| 300 | u32 rankcfgr; | 299 | u32 rankcfgr; |
| 301 | u64 (*get_tolm)(struct sbridge_pvt *pvt); | 300 | u64 (*get_tolm)(struct sbridge_pvt *pvt); |
| 302 | u64 (*get_tohm)(struct sbridge_pvt *pvt); | 301 | u64 (*get_tohm)(struct sbridge_pvt *pvt); |
| 302 | u64 (*rir_limit)(u32 reg); | ||
| 303 | const u32 *dram_rule; | 303 | const u32 *dram_rule; |
| 304 | const u32 *interleave_list; | 304 | const u32 *interleave_list; |
| 305 | const struct interleave_pkg *interleave_pkg; | 305 | const struct interleave_pkg *interleave_pkg; |
| 306 | u8 max_sad; | 306 | u8 max_sad; |
| 307 | u8 max_interleave; | 307 | u8 max_interleave; |
| 308 | u8 (*get_node_id)(struct sbridge_pvt *pvt); | ||
| 309 | enum mem_type (*get_memory_type)(struct sbridge_pvt *pvt); | ||
| 310 | struct pci_dev *pci_vtd; | ||
| 308 | }; | 311 | }; |
| 309 | 312 | ||
| 310 | struct sbridge_channel { | 313 | struct sbridge_channel { |
| @@ -313,9 +316,7 @@ struct sbridge_channel { | |||
| 313 | }; | 316 | }; |
| 314 | 317 | ||
| 315 | struct pci_id_descr { | 318 | struct pci_id_descr { |
| 316 | int dev; | 319 | int dev_id; |
| 317 | int func; | ||
| 318 | int dev_id; | ||
| 319 | int optional; | 320 | int optional; |
| 320 | }; | 321 | }; |
| 321 | 322 | ||
| @@ -338,6 +339,7 @@ struct sbridge_pvt { | |||
| 338 | struct pci_dev *pci_sad0, *pci_sad1; | 339 | struct pci_dev *pci_sad0, *pci_sad1; |
| 339 | struct pci_dev *pci_ha0, *pci_ha1; | 340 | struct pci_dev *pci_ha0, *pci_ha1; |
| 340 | struct pci_dev *pci_br0, *pci_br1; | 341 | struct pci_dev *pci_br0, *pci_br1; |
| 342 | struct pci_dev *pci_ha1_ta; | ||
| 341 | struct pci_dev *pci_tad[NUM_CHANNELS]; | 343 | struct pci_dev *pci_tad[NUM_CHANNELS]; |
| 342 | 344 | ||
| 343 | struct sbridge_dev *sbridge_dev; | 345 | struct sbridge_dev *sbridge_dev; |
| @@ -362,31 +364,29 @@ struct sbridge_pvt { | |||
| 362 | u64 tolm, tohm; | 364 | u64 tolm, tohm; |
| 363 | }; | 365 | }; |
| 364 | 366 | ||
| 365 | #define PCI_DESCR(device, function, device_id, opt) \ | 367 | #define PCI_DESCR(device_id, opt) \ |
| 366 | .dev = (device), \ | 368 | .dev_id = (device_id), \ |
| 367 | .func = (function), \ | ||
| 368 | .dev_id = (device_id), \ | ||
| 369 | .optional = opt | 369 | .optional = opt |
| 370 | 370 | ||
| 371 | static const struct pci_id_descr pci_dev_descr_sbridge[] = { | 371 | static const struct pci_id_descr pci_dev_descr_sbridge[] = { |
| 372 | /* Processor Home Agent */ | 372 | /* Processor Home Agent */ |
| 373 | { PCI_DESCR(14, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0, 0) }, | 373 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0, 0) }, |
| 374 | 374 | ||
| 375 | /* Memory controller */ | 375 | /* Memory controller */ |
| 376 | { PCI_DESCR(15, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA, 0) }, | 376 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA, 0) }, |
| 377 | { PCI_DESCR(15, 1, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS, 0) }, | 377 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS, 0) }, |
| 378 | { PCI_DESCR(15, 2, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0, 0) }, | 378 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0, 0) }, |
| 379 | { PCI_DESCR(15, 3, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1, 0) }, | 379 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1, 0) }, |
| 380 | { PCI_DESCR(15, 4, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2, 0) }, | 380 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2, 0) }, |
| 381 | { PCI_DESCR(15, 5, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3, 0) }, | 381 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3, 0) }, |
| 382 | { PCI_DESCR(17, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO, 1) }, | 382 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO, 1) }, |
| 383 | 383 | ||
| 384 | /* System Address Decoder */ | 384 | /* System Address Decoder */ |
| 385 | { PCI_DESCR(12, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0, 0) }, | 385 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0, 0) }, |
| 386 | { PCI_DESCR(12, 7, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1, 0) }, | 386 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1, 0) }, |
| 387 | 387 | ||
| 388 | /* Broadcast Registers */ | 388 | /* Broadcast Registers */ |
| 389 | { PCI_DESCR(13, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_BR, 0) }, | 389 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_BR, 0) }, |
| 390 | }; | 390 | }; |
| 391 | 391 | ||
| 392 | #define PCI_ID_TABLE_ENTRY(A) { .descr=A, .n_devs = ARRAY_SIZE(A) } | 392 | #define PCI_ID_TABLE_ENTRY(A) { .descr=A, .n_devs = ARRAY_SIZE(A) } |
| @@ -423,34 +423,34 @@ static const struct pci_id_table pci_dev_descr_sbridge_table[] = { | |||
| 423 | 423 | ||
| 424 | static const struct pci_id_descr pci_dev_descr_ibridge[] = { | 424 | static const struct pci_id_descr pci_dev_descr_ibridge[] = { |
| 425 | /* Processor Home Agent */ | 425 | /* Processor Home Agent */ |
| 426 | { PCI_DESCR(14, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0, 0) }, | 426 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0, 0) }, |
| 427 | 427 | ||
| 428 | /* Memory controller */ | 428 | /* Memory controller */ |
| 429 | { PCI_DESCR(15, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA, 0) }, | 429 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA, 0) }, |
| 430 | { PCI_DESCR(15, 1, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS, 0) }, | 430 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS, 0) }, |
| 431 | { PCI_DESCR(15, 2, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0, 0) }, | 431 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0, 0) }, |
| 432 | { PCI_DESCR(15, 3, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1, 0) }, | 432 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1, 0) }, |
| 433 | { PCI_DESCR(15, 4, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2, 0) }, | 433 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2, 0) }, |
| 434 | { PCI_DESCR(15, 5, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3, 0) }, | 434 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3, 0) }, |
| 435 | 435 | ||
| 436 | /* System Address Decoder */ | 436 | /* System Address Decoder */ |
| 437 | { PCI_DESCR(22, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_SAD, 0) }, | 437 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_SAD, 0) }, |
| 438 | 438 | ||
| 439 | /* Broadcast Registers */ | 439 | /* Broadcast Registers */ |
| 440 | { PCI_DESCR(22, 1, PCI_DEVICE_ID_INTEL_IBRIDGE_BR0, 1) }, | 440 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR0, 1) }, |
| 441 | { PCI_DESCR(22, 2, PCI_DEVICE_ID_INTEL_IBRIDGE_BR1, 0) }, | 441 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR1, 0) }, |
| 442 | 442 | ||
| 443 | /* Optional, mode 2HA */ | 443 | /* Optional, mode 2HA */ |
| 444 | { PCI_DESCR(28, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1, 1) }, | 444 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1, 1) }, |
| 445 | #if 0 | 445 | #if 0 |
| 446 | { PCI_DESCR(29, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA, 1) }, | 446 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA, 1) }, |
| 447 | { PCI_DESCR(29, 1, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS, 1) }, | 447 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS, 1) }, |
| 448 | #endif | 448 | #endif |
| 449 | { PCI_DESCR(29, 2, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0, 1) }, | 449 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0, 1) }, |
| 450 | { PCI_DESCR(29, 3, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1, 1) }, | 450 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1, 1) }, |
| 451 | 451 | ||
| 452 | { PCI_DESCR(17, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0, 1) }, | 452 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0, 1) }, |
| 453 | { PCI_DESCR(17, 4, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0, 1) }, | 453 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0, 1) }, |
| 454 | }; | 454 | }; |
| 455 | 455 | ||
| 456 | static const struct pci_id_table pci_dev_descr_ibridge_table[] = { | 456 | static const struct pci_id_table pci_dev_descr_ibridge_table[] = { |
| @@ -458,12 +458,80 @@ static const struct pci_id_table pci_dev_descr_ibridge_table[] = { | |||
| 458 | {0,} /* 0 terminated list. */ | 458 | {0,} /* 0 terminated list. */ |
| 459 | }; | 459 | }; |
| 460 | 460 | ||
| 461 | /* Haswell support */ | ||
| 462 | /* EN processor: | ||
| 463 | * - 1 IMC | ||
| 464 | * - 3 DDR3 channels, 2 DPC per channel | ||
| 465 | * EP processor: | ||
| 466 | * - 1 or 2 IMC | ||
| 467 | * - 4 DDR4 channels, 3 DPC per channel | ||
| 468 | * EP 4S processor: | ||
| 469 | * - 2 IMC | ||
| 470 | * - 4 DDR4 channels, 3 DPC per channel | ||
| 471 | * EX processor: | ||
| 472 | * - 2 IMC | ||
| 473 | * - each IMC interfaces with a SMI 2 channel | ||
| 474 | * - each SMI channel interfaces with a scalable memory buffer | ||
| 475 | * - each scalable memory buffer supports 4 DDR3/DDR4 channels, 3 DPC | ||
| 476 | */ | ||
| 477 | #define HASWELL_DDRCRCLKCONTROLS 0xa10 | ||
| 478 | #define HASWELL_HASYSDEFEATURE2 0x84 | ||
| 479 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_VTD_MISC 0x2f28 | ||
| 480 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0 0x2fa0 | ||
| 481 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1 0x2f60 | ||
| 482 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA 0x2fa8 | ||
| 483 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_THERMAL 0x2f71 | ||
| 484 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA 0x2f68 | ||
| 485 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_THERMAL 0x2f79 | ||
| 486 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0 0x2ffc | ||
| 487 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1 0x2ffd | ||
| 488 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0 0x2faa | ||
| 489 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1 0x2fab | ||
| 490 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2 0x2fac | ||
| 491 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3 0x2fad | ||
| 492 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0 0x2f6a | ||
| 493 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1 0x2f6b | ||
| 494 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2 0x2f6c | ||
| 495 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3 0x2f6d | ||
| 496 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0 0x2fbd | ||
| 497 | static const struct pci_id_descr pci_dev_descr_haswell[] = { | ||
| 498 | /* first item must be the HA */ | ||
| 499 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0, 0) }, | ||
| 500 | |||
| 501 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0, 0) }, | ||
| 502 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1, 0) }, | ||
| 503 | |||
| 504 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1, 1) }, | ||
| 505 | |||
| 506 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA, 0) }, | ||
| 507 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_THERMAL, 0) }, | ||
| 508 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0, 0) }, | ||
| 509 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1, 0) }, | ||
| 510 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2, 1) }, | ||
| 511 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3, 1) }, | ||
| 512 | |||
| 513 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0, 1) }, | ||
| 514 | |||
| 515 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA, 1) }, | ||
| 516 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_THERMAL, 1) }, | ||
| 517 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0, 1) }, | ||
| 518 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1, 1) }, | ||
| 519 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2, 1) }, | ||
| 520 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3, 1) }, | ||
| 521 | }; | ||
| 522 | |||
| 523 | static const struct pci_id_table pci_dev_descr_haswell_table[] = { | ||
| 524 | PCI_ID_TABLE_ENTRY(pci_dev_descr_haswell), | ||
| 525 | {0,} /* 0 terminated list. */ | ||
| 526 | }; | ||
| 527 | |||
| 461 | /* | 528 | /* |
| 462 | * pci_device_id table for which devices we are looking for | 529 | * pci_device_id table for which devices we are looking for |
| 463 | */ | 530 | */ |
| 464 | static const struct pci_device_id sbridge_pci_tbl[] = { | 531 | static const struct pci_device_id sbridge_pci_tbl[] = { |
| 465 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA)}, | 532 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA)}, |
| 466 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA)}, | 533 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA)}, |
| 534 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0)}, | ||
| 467 | {0,} /* 0 terminated list. */ | 535 | {0,} /* 0 terminated list. */ |
| 468 | }; | 536 | }; |
| 469 | 537 | ||
| @@ -472,13 +540,17 @@ static const struct pci_device_id sbridge_pci_tbl[] = { | |||
| 472 | Ancillary status routines | 540 | Ancillary status routines |
| 473 | ****************************************************************************/ | 541 | ****************************************************************************/ |
| 474 | 542 | ||
| 475 | static inline int numrank(u32 mtr) | 543 | static inline int numrank(enum type type, u32 mtr) |
| 476 | { | 544 | { |
| 477 | int ranks = (1 << RANK_CNT_BITS(mtr)); | 545 | int ranks = (1 << RANK_CNT_BITS(mtr)); |
| 546 | int max = 4; | ||
| 478 | 547 | ||
| 479 | if (ranks > 4) { | 548 | if (type == HASWELL) |
| 480 | edac_dbg(0, "Invalid number of ranks: %d (max = 4) raw value = %x (%04x)\n", | 549 | max = 8; |
| 481 | ranks, (unsigned int)RANK_CNT_BITS(mtr), mtr); | 550 | |
| 551 | if (ranks > max) { | ||
| 552 | edac_dbg(0, "Invalid number of ranks: %d (max = %i) raw value = %x (%04x)\n", | ||
| 553 | ranks, max, (unsigned int)RANK_CNT_BITS(mtr), mtr); | ||
| 482 | return -EINVAL; | 554 | return -EINVAL; |
| 483 | } | 555 | } |
| 484 | 556 | ||
| @@ -588,10 +660,107 @@ static u64 ibridge_get_tohm(struct sbridge_pvt *pvt) | |||
| 588 | return GET_TOHM(reg); | 660 | return GET_TOHM(reg); |
| 589 | } | 661 | } |
| 590 | 662 | ||
| 663 | static u64 rir_limit(u32 reg) | ||
| 664 | { | ||
| 665 | return ((u64)GET_BITFIELD(reg, 1, 10) << 29) | 0x1fffffff; | ||
| 666 | } | ||
| 667 | |||
| 668 | static enum mem_type get_memory_type(struct sbridge_pvt *pvt) | ||
| 669 | { | ||
| 670 | u32 reg; | ||
| 671 | enum mem_type mtype; | ||
| 672 | |||
| 673 | if (pvt->pci_ddrio) { | ||
| 674 | pci_read_config_dword(pvt->pci_ddrio, pvt->info.rankcfgr, | ||
| 675 | ®); | ||
| 676 | if (GET_BITFIELD(reg, 11, 11)) | ||
| 677 | /* FIXME: Can also be LRDIMM */ | ||
| 678 | mtype = MEM_RDDR3; | ||
| 679 | else | ||
| 680 | mtype = MEM_DDR3; | ||
| 681 | } else | ||
| 682 | mtype = MEM_UNKNOWN; | ||
| 683 | |||
| 684 | return mtype; | ||
| 685 | } | ||
| 686 | |||
| 687 | static enum mem_type haswell_get_memory_type(struct sbridge_pvt *pvt) | ||
| 688 | { | ||
| 689 | u32 reg; | ||
| 690 | bool registered = false; | ||
| 691 | enum mem_type mtype = MEM_UNKNOWN; | ||
| 692 | |||
| 693 | if (!pvt->pci_ddrio) | ||
| 694 | goto out; | ||
| 695 | |||
| 696 | pci_read_config_dword(pvt->pci_ddrio, | ||
| 697 | HASWELL_DDRCRCLKCONTROLS, ®); | ||
| 698 | /* Is_Rdimm */ | ||
| 699 | if (GET_BITFIELD(reg, 16, 16)) | ||
| 700 | registered = true; | ||
| 701 | |||
| 702 | pci_read_config_dword(pvt->pci_ta, MCMTR, ®); | ||
| 703 | if (GET_BITFIELD(reg, 14, 14)) { | ||
| 704 | if (registered) | ||
| 705 | mtype = MEM_RDDR4; | ||
| 706 | else | ||
| 707 | mtype = MEM_DDR4; | ||
| 708 | } else { | ||
| 709 | if (registered) | ||
| 710 | mtype = MEM_RDDR3; | ||
| 711 | else | ||
| 712 | mtype = MEM_DDR3; | ||
| 713 | } | ||
| 714 | |||
| 715 | out: | ||
| 716 | return mtype; | ||
| 717 | } | ||
| 718 | |||
| 719 | static u8 get_node_id(struct sbridge_pvt *pvt) | ||
| 720 | { | ||
| 721 | u32 reg; | ||
| 722 | pci_read_config_dword(pvt->pci_br0, SAD_CONTROL, ®); | ||
| 723 | return GET_BITFIELD(reg, 0, 2); | ||
| 724 | } | ||
| 725 | |||
| 726 | static u8 haswell_get_node_id(struct sbridge_pvt *pvt) | ||
| 727 | { | ||
| 728 | u32 reg; | ||
| 729 | |||
| 730 | pci_read_config_dword(pvt->pci_sad1, SAD_CONTROL, ®); | ||
| 731 | return GET_BITFIELD(reg, 0, 3); | ||
| 732 | } | ||
| 733 | |||
| 734 | static u64 haswell_get_tolm(struct sbridge_pvt *pvt) | ||
| 735 | { | ||
| 736 | u32 reg; | ||
| 737 | |||
| 738 | pci_read_config_dword(pvt->info.pci_vtd, TOLM, ®); | ||
| 739 | return (GET_BITFIELD(reg, 26, 31) << 26) | 0x1ffffff; | ||
| 740 | } | ||
| 741 | |||
| 742 | static u64 haswell_get_tohm(struct sbridge_pvt *pvt) | ||
| 743 | { | ||
| 744 | u64 rc; | ||
| 745 | u32 reg; | ||
| 746 | |||
| 747 | pci_read_config_dword(pvt->info.pci_vtd, HASWELL_TOHM_0, ®); | ||
| 748 | rc = GET_BITFIELD(reg, 26, 31); | ||
| 749 | pci_read_config_dword(pvt->info.pci_vtd, HASWELL_TOHM_1, ®); | ||
| 750 | rc = ((reg << 6) | rc) << 26; | ||
| 751 | |||
| 752 | return rc | 0x1ffffff; | ||
| 753 | } | ||
| 754 | |||
| 755 | static u64 haswell_rir_limit(u32 reg) | ||
| 756 | { | ||
| 757 | return (((u64)GET_BITFIELD(reg, 1, 11) + 1) << 29) - 1; | ||
| 758 | } | ||
| 759 | |||
| 591 | static inline u8 sad_pkg_socket(u8 pkg) | 760 | static inline u8 sad_pkg_socket(u8 pkg) |
| 592 | { | 761 | { |
| 593 | /* on Ivy Bridge, nodeID is SASS, where A is HA and S is node id */ | 762 | /* on Ivy Bridge, nodeID is SASS, where A is HA and S is node id */ |
| 594 | return (pkg >> 3) | (pkg & 0x3); | 763 | return ((pkg >> 3) << 2) | (pkg & 0x3); |
| 595 | } | 764 | } |
| 596 | 765 | ||
| 597 | static inline u8 sad_pkg_ha(u8 pkg) | 766 | static inline u8 sad_pkg_ha(u8 pkg) |
| @@ -602,44 +771,43 @@ static inline u8 sad_pkg_ha(u8 pkg) | |||
| 602 | /**************************************************************************** | 771 | /**************************************************************************** |
| 603 | Memory check routines | 772 | Memory check routines |
| 604 | ****************************************************************************/ | 773 | ****************************************************************************/ |
| 605 | static struct pci_dev *get_pdev_slot_func(u8 bus, unsigned slot, | 774 | static struct pci_dev *get_pdev_same_bus(u8 bus, u32 id) |
| 606 | unsigned func) | ||
| 607 | { | 775 | { |
| 608 | struct sbridge_dev *sbridge_dev = get_sbridge_dev(bus); | 776 | struct pci_dev *pdev = NULL; |
| 609 | int i; | ||
| 610 | |||
| 611 | if (!sbridge_dev) | ||
| 612 | return NULL; | ||
| 613 | |||
| 614 | for (i = 0; i < sbridge_dev->n_devs; i++) { | ||
| 615 | if (!sbridge_dev->pdev[i]) | ||
| 616 | continue; | ||
| 617 | 777 | ||
| 618 | if (PCI_SLOT(sbridge_dev->pdev[i]->devfn) == slot && | 778 | do { |
| 619 | PCI_FUNC(sbridge_dev->pdev[i]->devfn) == func) { | 779 | pdev = pci_get_device(PCI_VENDOR_ID_INTEL, id, pdev); |
| 620 | edac_dbg(1, "Associated %02x.%02x.%d with %p\n", | 780 | if (pdev && pdev->bus->number == bus) |
| 621 | bus, slot, func, sbridge_dev->pdev[i]); | 781 | break; |
| 622 | return sbridge_dev->pdev[i]; | 782 | } while (pdev); |
| 623 | } | ||
| 624 | } | ||
| 625 | 783 | ||
| 626 | return NULL; | 784 | return pdev; |
| 627 | } | 785 | } |
| 628 | 786 | ||
| 629 | /** | 787 | /** |
| 630 | * check_if_ecc_is_active() - Checks if ECC is active | 788 | * check_if_ecc_is_active() - Checks if ECC is active |
| 631 | * bus: Device bus | 789 | * @bus: Device bus |
| 790 | * @type: Memory controller type | ||
| 791 | * returns: 0 in case ECC is active, -ENODEV if it can't be determined or | ||
| 792 | * disabled | ||
| 632 | */ | 793 | */ |
| 633 | static int check_if_ecc_is_active(const u8 bus) | 794 | static int check_if_ecc_is_active(const u8 bus, enum type type) |
| 634 | { | 795 | { |
| 635 | struct pci_dev *pdev = NULL; | 796 | struct pci_dev *pdev = NULL; |
| 636 | u32 mcmtr; | 797 | u32 mcmtr, id; |
| 798 | |||
| 799 | if (type == IVY_BRIDGE) | ||
| 800 | id = PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA; | ||
| 801 | else if (type == HASWELL) | ||
| 802 | id = PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA; | ||
| 803 | else | ||
| 804 | id = PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA; | ||
| 637 | 805 | ||
| 638 | pdev = get_pdev_slot_func(bus, 15, 0); | 806 | pdev = get_pdev_same_bus(bus, id); |
| 639 | if (!pdev) { | 807 | if (!pdev) { |
| 640 | sbridge_printk(KERN_ERR, "Couldn't find PCI device " | 808 | sbridge_printk(KERN_ERR, "Couldn't find PCI device " |
| 641 | "%2x.%02d.%d!!!\n", | 809 | "%04x:%04x! on bus %02d\n", |
| 642 | bus, 15, 0); | 810 | PCI_VENDOR_ID_INTEL, id, bus); |
| 643 | return -ENODEV; | 811 | return -ENODEV; |
| 644 | } | 812 | } |
| 645 | 813 | ||
| @@ -661,11 +829,14 @@ static int get_dimm_config(struct mem_ctl_info *mci) | |||
| 661 | enum edac_type mode; | 829 | enum edac_type mode; |
| 662 | enum mem_type mtype; | 830 | enum mem_type mtype; |
| 663 | 831 | ||
| 664 | pci_read_config_dword(pvt->pci_br0, SAD_TARGET, ®); | 832 | if (pvt->info.type == HASWELL) |
| 833 | pci_read_config_dword(pvt->pci_sad1, SAD_TARGET, ®); | ||
| 834 | else | ||
| 835 | pci_read_config_dword(pvt->pci_br0, SAD_TARGET, ®); | ||
| 836 | |||
| 665 | pvt->sbridge_dev->source_id = SOURCE_ID(reg); | 837 | pvt->sbridge_dev->source_id = SOURCE_ID(reg); |
| 666 | 838 | ||
| 667 | pci_read_config_dword(pvt->pci_br0, SAD_CONTROL, ®); | 839 | pvt->sbridge_dev->node_id = pvt->info.get_node_id(pvt); |
| 668 | pvt->sbridge_dev->node_id = NODE_ID(reg); | ||
| 669 | edac_dbg(0, "mc#%d: Node ID: %d, source ID: %d\n", | 840 | edac_dbg(0, "mc#%d: Node ID: %d, source ID: %d\n", |
| 670 | pvt->sbridge_dev->mc, | 841 | pvt->sbridge_dev->mc, |
| 671 | pvt->sbridge_dev->node_id, | 842 | pvt->sbridge_dev->node_id, |
| @@ -698,24 +869,18 @@ static int get_dimm_config(struct mem_ctl_info *mci) | |||
| 698 | pvt->is_close_pg = false; | 869 | pvt->is_close_pg = false; |
| 699 | } | 870 | } |
| 700 | 871 | ||
| 701 | if (pvt->pci_ddrio) { | 872 | mtype = pvt->info.get_memory_type(pvt); |
| 702 | pci_read_config_dword(pvt->pci_ddrio, pvt->info.rankcfgr, | 873 | if (mtype == MEM_RDDR3 || mtype == MEM_RDDR4) |
| 703 | ®); | 874 | edac_dbg(0, "Memory is registered\n"); |
| 704 | if (IS_RDIMM_ENABLED(reg)) { | 875 | else if (mtype == MEM_UNKNOWN) |
| 705 | /* FIXME: Can also be LRDIMM */ | ||
| 706 | edac_dbg(0, "Memory is registered\n"); | ||
| 707 | mtype = MEM_RDDR3; | ||
| 708 | } else { | ||
| 709 | edac_dbg(0, "Memory is unregistered\n"); | ||
| 710 | mtype = MEM_DDR3; | ||
| 711 | } | ||
| 712 | } else { | ||
| 713 | edac_dbg(0, "Cannot determine memory type\n"); | 876 | edac_dbg(0, "Cannot determine memory type\n"); |
| 714 | mtype = MEM_UNKNOWN; | 877 | else |
| 715 | } | 878 | edac_dbg(0, "Memory is unregistered\n"); |
| 716 | 879 | ||
| 717 | /* On all supported DDR3 DIMM types, there are 8 banks available */ | 880 | if (mtype == MEM_DDR4 || MEM_RDDR4) |
| 718 | banks = 8; | 881 | banks = 16; |
| 882 | else | ||
| 883 | banks = 8; | ||
| 719 | 884 | ||
| 720 | for (i = 0; i < NUM_CHANNELS; i++) { | 885 | for (i = 0; i < NUM_CHANNELS; i++) { |
| 721 | u32 mtr; | 886 | u32 mtr; |
| @@ -729,11 +894,10 @@ static int get_dimm_config(struct mem_ctl_info *mci) | |||
| 729 | if (IS_DIMM_PRESENT(mtr)) { | 894 | if (IS_DIMM_PRESENT(mtr)) { |
| 730 | pvt->channel[i].dimms++; | 895 | pvt->channel[i].dimms++; |
| 731 | 896 | ||
| 732 | ranks = numrank(mtr); | 897 | ranks = numrank(pvt->info.type, mtr); |
| 733 | rows = numrow(mtr); | 898 | rows = numrow(mtr); |
| 734 | cols = numcol(mtr); | 899 | cols = numcol(mtr); |
| 735 | 900 | ||
| 736 | /* DDR3 has 8 I/O banks */ | ||
| 737 | size = ((u64)rows * cols * banks * ranks) >> (20 - 3); | 901 | size = ((u64)rows * cols * banks * ranks) >> (20 - 3); |
| 738 | npages = MiB_TO_PAGES(size); | 902 | npages = MiB_TO_PAGES(size); |
| 739 | 903 | ||
| @@ -744,7 +908,17 @@ static int get_dimm_config(struct mem_ctl_info *mci) | |||
| 744 | 908 | ||
| 745 | dimm->nr_pages = npages; | 909 | dimm->nr_pages = npages; |
| 746 | dimm->grain = 32; | 910 | dimm->grain = 32; |
| 747 | dimm->dtype = (banks == 8) ? DEV_X8 : DEV_X4; | 911 | switch (banks) { |
| 912 | case 16: | ||
| 913 | dimm->dtype = DEV_X16; | ||
| 914 | break; | ||
| 915 | case 8: | ||
| 916 | dimm->dtype = DEV_X8; | ||
| 917 | break; | ||
| 918 | case 4: | ||
| 919 | dimm->dtype = DEV_X4; | ||
| 920 | break; | ||
| 921 | } | ||
| 748 | dimm->mtype = mtype; | 922 | dimm->mtype = mtype; |
| 749 | dimm->edac_mode = mode; | 923 | dimm->edac_mode = mode; |
| 750 | snprintf(dimm->label, sizeof(dimm->label), | 924 | snprintf(dimm->label, sizeof(dimm->label), |
| @@ -887,7 +1061,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci) | |||
| 887 | if (!IS_RIR_VALID(reg)) | 1061 | if (!IS_RIR_VALID(reg)) |
| 888 | continue; | 1062 | continue; |
| 889 | 1063 | ||
| 890 | tmp_mb = RIR_LIMIT(reg) >> 20; | 1064 | tmp_mb = pvt->info.rir_limit(reg) >> 20; |
| 891 | rir_way = 1 << RIR_WAY(reg); | 1065 | rir_way = 1 << RIR_WAY(reg); |
| 892 | mb = div_u64_rem(tmp_mb, 1000, &kb); | 1066 | mb = div_u64_rem(tmp_mb, 1000, &kb); |
| 893 | edac_dbg(0, "CH#%d RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d, reg=0x%08x\n", | 1067 | edac_dbg(0, "CH#%d RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d, reg=0x%08x\n", |
| @@ -936,11 +1110,11 @@ static int get_memory_error_data(struct mem_ctl_info *mci, | |||
| 936 | struct mem_ctl_info *new_mci; | 1110 | struct mem_ctl_info *new_mci; |
| 937 | struct sbridge_pvt *pvt = mci->pvt_info; | 1111 | struct sbridge_pvt *pvt = mci->pvt_info; |
| 938 | struct pci_dev *pci_ha; | 1112 | struct pci_dev *pci_ha; |
| 939 | int n_rir, n_sads, n_tads, sad_way, sck_xch; | 1113 | int n_rir, n_sads, n_tads, sad_way, sck_xch; |
| 940 | int sad_interl, idx, base_ch; | 1114 | int sad_interl, idx, base_ch; |
| 941 | int interleave_mode; | 1115 | int interleave_mode, shiftup = 0; |
| 942 | unsigned sad_interleave[pvt->info.max_interleave]; | 1116 | unsigned sad_interleave[pvt->info.max_interleave]; |
| 943 | u32 reg; | 1117 | u32 reg, dram_rule; |
| 944 | u8 ch_way, sck_way, pkg, sad_ha = 0; | 1118 | u8 ch_way, sck_way, pkg, sad_ha = 0; |
| 945 | u32 tad_offset; | 1119 | u32 tad_offset; |
| 946 | u32 rir_way; | 1120 | u32 rir_way; |
| @@ -987,8 +1161,9 @@ static int get_memory_error_data(struct mem_ctl_info *mci, | |||
| 987 | sprintf(msg, "Can't discover the memory socket"); | 1161 | sprintf(msg, "Can't discover the memory socket"); |
| 988 | return -EINVAL; | 1162 | return -EINVAL; |
| 989 | } | 1163 | } |
| 990 | *area_type = get_dram_attr(reg); | 1164 | dram_rule = reg; |
| 991 | interleave_mode = INTERLEAVE_MODE(reg); | 1165 | *area_type = get_dram_attr(dram_rule); |
| 1166 | interleave_mode = INTERLEAVE_MODE(dram_rule); | ||
| 992 | 1167 | ||
| 993 | pci_read_config_dword(pvt->pci_sad0, pvt->info.interleave_list[n_sads], | 1168 | pci_read_config_dword(pvt->pci_sad0, pvt->info.interleave_list[n_sads], |
| 994 | ®); | 1169 | ®); |
| @@ -1033,6 +1208,36 @@ static int get_memory_error_data(struct mem_ctl_info *mci, | |||
| 1033 | *socket = sad_interleave[idx]; | 1208 | *socket = sad_interleave[idx]; |
| 1034 | edac_dbg(0, "SAD interleave index: %d (wayness %d) = CPU socket %d\n", | 1209 | edac_dbg(0, "SAD interleave index: %d (wayness %d) = CPU socket %d\n", |
| 1035 | idx, sad_way, *socket); | 1210 | idx, sad_way, *socket); |
| 1211 | } else if (pvt->info.type == HASWELL) { | ||
| 1212 | int bits, a7mode = A7MODE(dram_rule); | ||
| 1213 | |||
| 1214 | if (a7mode) { | ||
| 1215 | /* A7 mode swaps P9 with P6 */ | ||
| 1216 | bits = GET_BITFIELD(addr, 7, 8) << 1; | ||
| 1217 | bits |= GET_BITFIELD(addr, 9, 9); | ||
| 1218 | } else | ||
| 1219 | bits = GET_BITFIELD(addr, 7, 9); | ||
| 1220 | |||
| 1221 | if (interleave_mode) { | ||
| 1222 | /* interleave mode will XOR {8,7,6} with {18,17,16} */ | ||
| 1223 | idx = GET_BITFIELD(addr, 16, 18); | ||
| 1224 | idx ^= bits; | ||
| 1225 | } else | ||
| 1226 | idx = bits; | ||
| 1227 | |||
| 1228 | pkg = sad_pkg(pvt->info.interleave_pkg, reg, idx); | ||
| 1229 | *socket = sad_pkg_socket(pkg); | ||
| 1230 | sad_ha = sad_pkg_ha(pkg); | ||
| 1231 | |||
| 1232 | if (a7mode) { | ||
| 1233 | /* MCChanShiftUpEnable */ | ||
| 1234 | pci_read_config_dword(pvt->pci_ha0, | ||
| 1235 | HASWELL_HASYSDEFEATURE2, ®); | ||
| 1236 | shiftup = GET_BITFIELD(reg, 22, 22); | ||
| 1237 | } | ||
| 1238 | |||
| 1239 | edac_dbg(0, "SAD interleave package: %d = CPU socket %d, HA %i, shiftup: %i\n", | ||
| 1240 | idx, *socket, sad_ha, shiftup); | ||
| 1036 | } else { | 1241 | } else { |
| 1037 | /* Ivy Bridge's SAD mode doesn't support XOR interleave mode */ | 1242 | /* Ivy Bridge's SAD mode doesn't support XOR interleave mode */ |
| 1038 | idx = (addr >> 6) & 7; | 1243 | idx = (addr >> 6) & 7; |
| @@ -1090,7 +1295,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, | |||
| 1090 | if (ch_way == 3) | 1295 | if (ch_way == 3) |
| 1091 | idx = addr >> 6; | 1296 | idx = addr >> 6; |
| 1092 | else | 1297 | else |
| 1093 | idx = addr >> (6 + sck_way); | 1298 | idx = (addr >> (6 + sck_way + shiftup)) & 0x3; |
| 1094 | idx = idx % ch_way; | 1299 | idx = idx % ch_way; |
| 1095 | 1300 | ||
| 1096 | /* | 1301 | /* |
| @@ -1181,7 +1386,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, | |||
| 1181 | if (!IS_RIR_VALID(reg)) | 1386 | if (!IS_RIR_VALID(reg)) |
| 1182 | continue; | 1387 | continue; |
| 1183 | 1388 | ||
| 1184 | limit = RIR_LIMIT(reg); | 1389 | limit = pvt->info.rir_limit(reg); |
| 1185 | mb = div_u64_rem(limit >> 20, 1000, &kb); | 1390 | mb = div_u64_rem(limit >> 20, 1000, &kb); |
| 1186 | edac_dbg(0, "RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d\n", | 1391 | edac_dbg(0, "RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d\n", |
| 1187 | n_rir, | 1392 | n_rir, |
| @@ -1197,6 +1402,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, | |||
| 1197 | return -EINVAL; | 1402 | return -EINVAL; |
| 1198 | } | 1403 | } |
| 1199 | rir_way = RIR_WAY(reg); | 1404 | rir_way = RIR_WAY(reg); |
| 1405 | |||
| 1200 | if (pvt->is_close_pg) | 1406 | if (pvt->is_close_pg) |
| 1201 | idx = (ch_addr >> 6); | 1407 | idx = (ch_addr >> 6); |
| 1202 | else | 1408 | else |
| @@ -1259,13 +1465,11 @@ static int sbridge_get_onedevice(struct pci_dev **prev, | |||
| 1259 | { | 1465 | { |
| 1260 | struct sbridge_dev *sbridge_dev; | 1466 | struct sbridge_dev *sbridge_dev; |
| 1261 | const struct pci_id_descr *dev_descr = &table->descr[devno]; | 1467 | const struct pci_id_descr *dev_descr = &table->descr[devno]; |
| 1262 | |||
| 1263 | struct pci_dev *pdev = NULL; | 1468 | struct pci_dev *pdev = NULL; |
| 1264 | u8 bus = 0; | 1469 | u8 bus = 0; |
| 1265 | 1470 | ||
| 1266 | sbridge_printk(KERN_DEBUG, | 1471 | sbridge_printk(KERN_DEBUG, |
| 1267 | "Seeking for: dev %02x.%d PCI ID %04x:%04x\n", | 1472 | "Seeking for: PCI ID %04x:%04x\n", |
| 1268 | dev_descr->dev, dev_descr->func, | ||
| 1269 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id); | 1473 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id); |
| 1270 | 1474 | ||
| 1271 | pdev = pci_get_device(PCI_VENDOR_ID_INTEL, | 1475 | pdev = pci_get_device(PCI_VENDOR_ID_INTEL, |
| @@ -1280,12 +1484,12 @@ static int sbridge_get_onedevice(struct pci_dev **prev, | |||
| 1280 | if (dev_descr->optional) | 1484 | if (dev_descr->optional) |
| 1281 | return 0; | 1485 | return 0; |
| 1282 | 1486 | ||
| 1487 | /* if the HA wasn't found */ | ||
| 1283 | if (devno == 0) | 1488 | if (devno == 0) |
| 1284 | return -ENODEV; | 1489 | return -ENODEV; |
| 1285 | 1490 | ||
| 1286 | sbridge_printk(KERN_INFO, | 1491 | sbridge_printk(KERN_INFO, |
| 1287 | "Device not found: dev %02x.%d PCI ID %04x:%04x\n", | 1492 | "Device not found: %04x:%04x\n", |
| 1288 | dev_descr->dev, dev_descr->func, | ||
| 1289 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id); | 1493 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id); |
| 1290 | 1494 | ||
| 1291 | /* End of list, leave */ | 1495 | /* End of list, leave */ |
| @@ -1305,9 +1509,7 @@ static int sbridge_get_onedevice(struct pci_dev **prev, | |||
| 1305 | 1509 | ||
| 1306 | if (sbridge_dev->pdev[devno]) { | 1510 | if (sbridge_dev->pdev[devno]) { |
| 1307 | sbridge_printk(KERN_ERR, | 1511 | sbridge_printk(KERN_ERR, |
| 1308 | "Duplicated device for " | 1512 | "Duplicated device for %04x:%04x\n", |
| 1309 | "dev %02x:%d.%d PCI ID %04x:%04x\n", | ||
| 1310 | bus, dev_descr->dev, dev_descr->func, | ||
| 1311 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id); | 1513 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id); |
| 1312 | pci_dev_put(pdev); | 1514 | pci_dev_put(pdev); |
| 1313 | return -ENODEV; | 1515 | return -ENODEV; |
| @@ -1315,30 +1517,15 @@ static int sbridge_get_onedevice(struct pci_dev **prev, | |||
| 1315 | 1517 | ||
| 1316 | sbridge_dev->pdev[devno] = pdev; | 1518 | sbridge_dev->pdev[devno] = pdev; |
| 1317 | 1519 | ||
| 1318 | /* Sanity check */ | ||
| 1319 | if (unlikely(PCI_SLOT(pdev->devfn) != dev_descr->dev || | ||
| 1320 | PCI_FUNC(pdev->devfn) != dev_descr->func)) { | ||
| 1321 | sbridge_printk(KERN_ERR, | ||
| 1322 | "Device PCI ID %04x:%04x " | ||
| 1323 | "has dev %02x:%d.%d instead of dev %02x:%02x.%d\n", | ||
| 1324 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id, | ||
| 1325 | bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), | ||
| 1326 | bus, dev_descr->dev, dev_descr->func); | ||
| 1327 | return -ENODEV; | ||
| 1328 | } | ||
| 1329 | |||
| 1330 | /* Be sure that the device is enabled */ | 1520 | /* Be sure that the device is enabled */ |
| 1331 | if (unlikely(pci_enable_device(pdev) < 0)) { | 1521 | if (unlikely(pci_enable_device(pdev) < 0)) { |
| 1332 | sbridge_printk(KERN_ERR, | 1522 | sbridge_printk(KERN_ERR, |
| 1333 | "Couldn't enable " | 1523 | "Couldn't enable %04x:%04x\n", |
| 1334 | "dev %02x:%d.%d PCI ID %04x:%04x\n", | ||
| 1335 | bus, dev_descr->dev, dev_descr->func, | ||
| 1336 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id); | 1524 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id); |
| 1337 | return -ENODEV; | 1525 | return -ENODEV; |
| 1338 | } | 1526 | } |
| 1339 | 1527 | ||
| 1340 | edac_dbg(0, "Detected dev %02x:%d.%d PCI ID %04x:%04x\n", | 1528 | edac_dbg(0, "Detected %04x:%04x\n", |
| 1341 | bus, dev_descr->dev, dev_descr->func, | ||
| 1342 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id); | 1529 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id); |
| 1343 | 1530 | ||
| 1344 | /* | 1531 | /* |
| @@ -1355,10 +1542,9 @@ static int sbridge_get_onedevice(struct pci_dev **prev, | |||
| 1355 | 1542 | ||
| 1356 | /* | 1543 | /* |
| 1357 | * sbridge_get_all_devices - Find and perform 'get' operation on the MCH's | 1544 | * sbridge_get_all_devices - Find and perform 'get' operation on the MCH's |
| 1358 | * device/functions we want to reference for this driver. | 1545 | * devices we want to reference for this driver. |
| 1359 | * Need to 'get' device 16 func 1 and func 2. | ||
| 1360 | * @num_mc: pointer to the memory controllers count, to be incremented in case | 1546 | * @num_mc: pointer to the memory controllers count, to be incremented in case |
| 1361 | * of success. | 1547 | * of success. |
| 1362 | * @table: model specific table | 1548 | * @table: model specific table |
| 1363 | * | 1549 | * |
| 1364 | * returns 0 in case of success or error code | 1550 | * returns 0 in case of success or error code |
| @@ -1396,79 +1582,51 @@ static int sbridge_mci_bind_devs(struct mem_ctl_info *mci, | |||
| 1396 | { | 1582 | { |
| 1397 | struct sbridge_pvt *pvt = mci->pvt_info; | 1583 | struct sbridge_pvt *pvt = mci->pvt_info; |
| 1398 | struct pci_dev *pdev; | 1584 | struct pci_dev *pdev; |
| 1399 | int i, func, slot; | 1585 | int i; |
| 1400 | 1586 | ||
| 1401 | for (i = 0; i < sbridge_dev->n_devs; i++) { | 1587 | for (i = 0; i < sbridge_dev->n_devs; i++) { |
| 1402 | pdev = sbridge_dev->pdev[i]; | 1588 | pdev = sbridge_dev->pdev[i]; |
| 1403 | if (!pdev) | 1589 | if (!pdev) |
| 1404 | continue; | 1590 | continue; |
| 1405 | slot = PCI_SLOT(pdev->devfn); | 1591 | |
| 1406 | func = PCI_FUNC(pdev->devfn); | 1592 | switch (pdev->device) { |
| 1407 | switch (slot) { | 1593 | case PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0: |
| 1408 | case 12: | 1594 | pvt->pci_sad0 = pdev; |
| 1409 | switch (func) { | ||
| 1410 | case 6: | ||
| 1411 | pvt->pci_sad0 = pdev; | ||
| 1412 | break; | ||
| 1413 | case 7: | ||
| 1414 | pvt->pci_sad1 = pdev; | ||
| 1415 | break; | ||
| 1416 | default: | ||
| 1417 | goto error; | ||
| 1418 | } | ||
| 1419 | break; | 1595 | break; |
| 1420 | case 13: | 1596 | case PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1: |
| 1421 | switch (func) { | 1597 | pvt->pci_sad1 = pdev; |
| 1422 | case 6: | ||
| 1423 | pvt->pci_br0 = pdev; | ||
| 1424 | break; | ||
| 1425 | default: | ||
| 1426 | goto error; | ||
| 1427 | } | ||
| 1428 | break; | 1598 | break; |
| 1429 | case 14: | 1599 | case PCI_DEVICE_ID_INTEL_SBRIDGE_BR: |
| 1430 | switch (func) { | 1600 | pvt->pci_br0 = pdev; |
| 1431 | case 0: | ||
| 1432 | pvt->pci_ha0 = pdev; | ||
| 1433 | break; | ||
| 1434 | default: | ||
| 1435 | goto error; | ||
| 1436 | } | ||
| 1437 | break; | 1601 | break; |
| 1438 | case 15: | 1602 | case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0: |
| 1439 | switch (func) { | 1603 | pvt->pci_ha0 = pdev; |
| 1440 | case 0: | ||
| 1441 | pvt->pci_ta = pdev; | ||
| 1442 | break; | ||
| 1443 | case 1: | ||
| 1444 | pvt->pci_ras = pdev; | ||
| 1445 | break; | ||
| 1446 | case 2: | ||
| 1447 | case 3: | ||
| 1448 | case 4: | ||
| 1449 | case 5: | ||
| 1450 | pvt->pci_tad[func - 2] = pdev; | ||
| 1451 | break; | ||
| 1452 | default: | ||
| 1453 | goto error; | ||
| 1454 | } | ||
| 1455 | break; | 1604 | break; |
| 1456 | case 17: | 1605 | case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA: |
| 1457 | switch (func) { | 1606 | pvt->pci_ta = pdev; |
| 1458 | case 0: | 1607 | break; |
| 1459 | pvt->pci_ddrio = pdev; | 1608 | case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS: |
| 1460 | break; | 1609 | pvt->pci_ras = pdev; |
| 1461 | default: | 1610 | break; |
| 1462 | goto error; | 1611 | case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0: |
| 1463 | } | 1612 | case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1: |
| 1613 | case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2: | ||
| 1614 | case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3: | ||
| 1615 | { | ||
| 1616 | int id = pdev->device - PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0; | ||
| 1617 | pvt->pci_tad[id] = pdev; | ||
| 1618 | } | ||
| 1619 | break; | ||
| 1620 | case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO: | ||
| 1621 | pvt->pci_ddrio = pdev; | ||
| 1464 | break; | 1622 | break; |
| 1465 | default: | 1623 | default: |
| 1466 | goto error; | 1624 | goto error; |
| 1467 | } | 1625 | } |
| 1468 | 1626 | ||
| 1469 | edac_dbg(0, "Associated PCI %02x.%02d.%d with dev = %p\n", | 1627 | edac_dbg(0, "Associated PCI %02x:%02x, bus %d with dev = %p\n", |
| 1628 | pdev->vendor, pdev->device, | ||
| 1470 | sbridge_dev->bus, | 1629 | sbridge_dev->bus, |
| 1471 | PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), | ||
| 1472 | pdev); | 1630 | pdev); |
| 1473 | } | 1631 | } |
| 1474 | 1632 | ||
| @@ -1488,9 +1646,8 @@ enodev: | |||
| 1488 | return -ENODEV; | 1646 | return -ENODEV; |
| 1489 | 1647 | ||
| 1490 | error: | 1648 | error: |
| 1491 | sbridge_printk(KERN_ERR, "Device %d, function %d " | 1649 | sbridge_printk(KERN_ERR, "Unexpected device %02x:%02x\n", |
| 1492 | "is out of the expected range\n", | 1650 | PCI_VENDOR_ID_INTEL, pdev->device); |
| 1493 | slot, func); | ||
| 1494 | return -EINVAL; | 1651 | return -EINVAL; |
| 1495 | } | 1652 | } |
| 1496 | 1653 | ||
| @@ -1499,7 +1656,7 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci, | |||
| 1499 | { | 1656 | { |
| 1500 | struct sbridge_pvt *pvt = mci->pvt_info; | 1657 | struct sbridge_pvt *pvt = mci->pvt_info; |
| 1501 | struct pci_dev *pdev, *tmp; | 1658 | struct pci_dev *pdev, *tmp; |
| 1502 | int i, func, slot; | 1659 | int i; |
| 1503 | bool mode_2ha = false; | 1660 | bool mode_2ha = false; |
| 1504 | 1661 | ||
| 1505 | tmp = pci_get_device(PCI_VENDOR_ID_INTEL, | 1662 | tmp = pci_get_device(PCI_VENDOR_ID_INTEL, |
| @@ -1513,79 +1670,60 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci, | |||
| 1513 | pdev = sbridge_dev->pdev[i]; | 1670 | pdev = sbridge_dev->pdev[i]; |
| 1514 | if (!pdev) | 1671 | if (!pdev) |
| 1515 | continue; | 1672 | continue; |
| 1516 | slot = PCI_SLOT(pdev->devfn); | ||
| 1517 | func = PCI_FUNC(pdev->devfn); | ||
| 1518 | 1673 | ||
| 1519 | switch (slot) { | 1674 | switch (pdev->device) { |
| 1520 | case 14: | 1675 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0: |
| 1521 | if (func == 0) { | 1676 | pvt->pci_ha0 = pdev; |
| 1522 | pvt->pci_ha0 = pdev; | 1677 | break; |
| 1523 | break; | 1678 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA: |
| 1524 | } | 1679 | pvt->pci_ta = pdev; |
| 1525 | goto error; | 1680 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS: |
| 1526 | case 15: | 1681 | pvt->pci_ras = pdev; |
| 1527 | switch (func) { | 1682 | break; |
| 1528 | case 0: | 1683 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2: |
| 1529 | pvt->pci_ta = pdev; | 1684 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3: |
| 1530 | break; | 1685 | /* if we have 2 HAs active, channels 2 and 3 |
| 1531 | case 1: | 1686 | * are in other device */ |
| 1532 | pvt->pci_ras = pdev; | 1687 | if (mode_2ha) |
| 1533 | break; | ||
| 1534 | case 4: | ||
| 1535 | case 5: | ||
| 1536 | /* if we have 2 HAs active, channels 2 and 3 | ||
| 1537 | * are in other device */ | ||
| 1538 | if (mode_2ha) | ||
| 1539 | break; | ||
| 1540 | /* fall through */ | ||
| 1541 | case 2: | ||
| 1542 | case 3: | ||
| 1543 | pvt->pci_tad[func - 2] = pdev; | ||
| 1544 | break; | 1688 | break; |
| 1545 | default: | 1689 | /* fall through */ |
| 1546 | goto error; | 1690 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0: |
| 1547 | } | 1691 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1: |
| 1692 | { | ||
| 1693 | int id = pdev->device - PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0; | ||
| 1694 | pvt->pci_tad[id] = pdev; | ||
| 1695 | } | ||
| 1548 | break; | 1696 | break; |
| 1549 | case 17: | 1697 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0: |
| 1550 | if (func == 4) { | 1698 | pvt->pci_ddrio = pdev; |
| 1699 | break; | ||
| 1700 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0: | ||
| 1701 | if (!mode_2ha) | ||
| 1551 | pvt->pci_ddrio = pdev; | 1702 | pvt->pci_ddrio = pdev; |
| 1552 | break; | ||
| 1553 | } else if (func == 0) { | ||
| 1554 | if (!mode_2ha) | ||
| 1555 | pvt->pci_ddrio = pdev; | ||
| 1556 | break; | ||
| 1557 | } | ||
| 1558 | goto error; | ||
| 1559 | case 22: | ||
| 1560 | switch (func) { | ||
| 1561 | case 0: | ||
| 1562 | pvt->pci_sad0 = pdev; | ||
| 1563 | break; | ||
| 1564 | case 1: | ||
| 1565 | pvt->pci_br0 = pdev; | ||
| 1566 | break; | ||
| 1567 | case 2: | ||
| 1568 | pvt->pci_br1 = pdev; | ||
| 1569 | break; | ||
| 1570 | default: | ||
| 1571 | goto error; | ||
| 1572 | } | ||
| 1573 | break; | 1703 | break; |
| 1574 | case 28: | 1704 | case PCI_DEVICE_ID_INTEL_IBRIDGE_SAD: |
| 1575 | if (func == 0) { | 1705 | pvt->pci_sad0 = pdev; |
| 1576 | pvt->pci_ha1 = pdev; | 1706 | break; |
| 1577 | break; | 1707 | case PCI_DEVICE_ID_INTEL_IBRIDGE_BR0: |
| 1578 | } | 1708 | pvt->pci_br0 = pdev; |
| 1579 | goto error; | 1709 | break; |
| 1580 | case 29: | 1710 | case PCI_DEVICE_ID_INTEL_IBRIDGE_BR1: |
| 1711 | pvt->pci_br1 = pdev; | ||
| 1712 | break; | ||
| 1713 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1: | ||
| 1714 | pvt->pci_ha1 = pdev; | ||
| 1715 | break; | ||
| 1716 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0: | ||
| 1717 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1: | ||
| 1718 | { | ||
| 1719 | int id = pdev->device - PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0 + 2; | ||
| 1720 | |||
| 1581 | /* we shouldn't have this device if we have just one | 1721 | /* we shouldn't have this device if we have just one |
| 1582 | * HA present */ | 1722 | * HA present */ |
| 1583 | WARN_ON(!mode_2ha); | 1723 | WARN_ON(!mode_2ha); |
| 1584 | if (func == 2 || func == 3) { | 1724 | pvt->pci_tad[id] = pdev; |
| 1585 | pvt->pci_tad[func] = pdev; | 1725 | } |
| 1586 | break; | 1726 | break; |
| 1587 | } | ||
| 1588 | goto error; | ||
| 1589 | default: | 1727 | default: |
| 1590 | goto error; | 1728 | goto error; |
| 1591 | } | 1729 | } |
| @@ -1614,11 +1752,111 @@ enodev: | |||
| 1614 | 1752 | ||
| 1615 | error: | 1753 | error: |
| 1616 | sbridge_printk(KERN_ERR, | 1754 | sbridge_printk(KERN_ERR, |
| 1617 | "Device %d, function %d is out of the expected range\n", | 1755 | "Unexpected device %02x:%02x\n", PCI_VENDOR_ID_INTEL, |
| 1618 | slot, func); | 1756 | pdev->device); |
| 1619 | return -EINVAL; | 1757 | return -EINVAL; |
| 1620 | } | 1758 | } |
| 1621 | 1759 | ||
| 1760 | static int haswell_mci_bind_devs(struct mem_ctl_info *mci, | ||
| 1761 | struct sbridge_dev *sbridge_dev) | ||
| 1762 | { | ||
| 1763 | struct sbridge_pvt *pvt = mci->pvt_info; | ||
| 1764 | struct pci_dev *pdev, *tmp; | ||
| 1765 | int i; | ||
| 1766 | bool mode_2ha = false; | ||
| 1767 | |||
| 1768 | tmp = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
| 1769 | PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1, NULL); | ||
| 1770 | if (tmp) { | ||
| 1771 | mode_2ha = true; | ||
| 1772 | pci_dev_put(tmp); | ||
| 1773 | } | ||
| 1774 | |||
| 1775 | /* there's only one device per system; not tied to any bus */ | ||
| 1776 | if (pvt->info.pci_vtd == NULL) | ||
| 1777 | /* result will be checked later */ | ||
| 1778 | pvt->info.pci_vtd = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
| 1779 | PCI_DEVICE_ID_INTEL_HASWELL_IMC_VTD_MISC, | ||
| 1780 | NULL); | ||
| 1781 | |||
| 1782 | for (i = 0; i < sbridge_dev->n_devs; i++) { | ||
| 1783 | pdev = sbridge_dev->pdev[i]; | ||
| 1784 | if (!pdev) | ||
| 1785 | continue; | ||
| 1786 | |||
| 1787 | switch (pdev->device) { | ||
| 1788 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0: | ||
| 1789 | pvt->pci_sad0 = pdev; | ||
| 1790 | break; | ||
| 1791 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1: | ||
| 1792 | pvt->pci_sad1 = pdev; | ||
| 1793 | break; | ||
| 1794 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0: | ||
| 1795 | pvt->pci_ha0 = pdev; | ||
| 1796 | break; | ||
| 1797 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA: | ||
| 1798 | pvt->pci_ta = pdev; | ||
| 1799 | break; | ||
| 1800 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_THERMAL: | ||
| 1801 | pvt->pci_ras = pdev; | ||
| 1802 | break; | ||
| 1803 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0: | ||
| 1804 | pvt->pci_tad[0] = pdev; | ||
| 1805 | break; | ||
| 1806 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1: | ||
| 1807 | pvt->pci_tad[1] = pdev; | ||
| 1808 | break; | ||
| 1809 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2: | ||
| 1810 | if (!mode_2ha) | ||
| 1811 | pvt->pci_tad[2] = pdev; | ||
| 1812 | break; | ||
| 1813 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3: | ||
| 1814 | if (!mode_2ha) | ||
| 1815 | pvt->pci_tad[3] = pdev; | ||
| 1816 | break; | ||
| 1817 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0: | ||
| 1818 | pvt->pci_ddrio = pdev; | ||
| 1819 | break; | ||
| 1820 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1: | ||
| 1821 | pvt->pci_ha1 = pdev; | ||
| 1822 | break; | ||
| 1823 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA: | ||
| 1824 | pvt->pci_ha1_ta = pdev; | ||
| 1825 | break; | ||
| 1826 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0: | ||
| 1827 | if (mode_2ha) | ||
| 1828 | pvt->pci_tad[2] = pdev; | ||
| 1829 | break; | ||
| 1830 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1: | ||
| 1831 | if (mode_2ha) | ||
| 1832 | pvt->pci_tad[3] = pdev; | ||
| 1833 | break; | ||
| 1834 | default: | ||
| 1835 | break; | ||
| 1836 | } | ||
| 1837 | |||
| 1838 | edac_dbg(0, "Associated PCI %02x.%02d.%d with dev = %p\n", | ||
| 1839 | sbridge_dev->bus, | ||
| 1840 | PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), | ||
| 1841 | pdev); | ||
| 1842 | } | ||
| 1843 | |||
| 1844 | /* Check if everything were registered */ | ||
| 1845 | if (!pvt->pci_sad0 || !pvt->pci_ha0 || !pvt->pci_sad1 || | ||
| 1846 | !pvt->pci_ras || !pvt->pci_ta || !pvt->info.pci_vtd) | ||
| 1847 | goto enodev; | ||
| 1848 | |||
| 1849 | for (i = 0; i < NUM_CHANNELS; i++) { | ||
| 1850 | if (!pvt->pci_tad[i]) | ||
| 1851 | goto enodev; | ||
| 1852 | } | ||
| 1853 | return 0; | ||
| 1854 | |||
| 1855 | enodev: | ||
| 1856 | sbridge_printk(KERN_ERR, "Some needed devices are missing\n"); | ||
| 1857 | return -ENODEV; | ||
| 1858 | } | ||
| 1859 | |||
| 1622 | /**************************************************************************** | 1860 | /**************************************************************************** |
| 1623 | Error check routines | 1861 | Error check routines |
| 1624 | ****************************************************************************/ | 1862 | ****************************************************************************/ |
| @@ -1736,6 +1974,9 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, | |||
| 1736 | * EDAC core should be handling the channel mask, in order to point | 1974 | * EDAC core should be handling the channel mask, in order to point |
| 1737 | * to the group of dimm's where the error may be happening. | 1975 | * to the group of dimm's where the error may be happening. |
| 1738 | */ | 1976 | */ |
| 1977 | if (!pvt->is_lockstep && !pvt->is_mirrored && !pvt->is_close_pg) | ||
| 1978 | channel = first_channel; | ||
| 1979 | |||
| 1739 | snprintf(msg, sizeof(msg), | 1980 | snprintf(msg, sizeof(msg), |
| 1740 | "%s%s area:%s err_code:%04x:%04x socket:%d channel_mask:%ld rank:%d", | 1981 | "%s%s area:%s err_code:%04x:%04x socket:%d channel_mask:%ld rank:%d", |
| 1741 | overflow ? " OVERFLOW" : "", | 1982 | overflow ? " OVERFLOW" : "", |
| @@ -1865,10 +2106,6 @@ static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val, | |||
| 1865 | "%u APIC %x\n", mce->cpuvendor, mce->cpuid, | 2106 | "%u APIC %x\n", mce->cpuvendor, mce->cpuid, |
| 1866 | mce->time, mce->socketid, mce->apicid); | 2107 | mce->time, mce->socketid, mce->apicid); |
| 1867 | 2108 | ||
| 1868 | /* Only handle if it is the right mc controller */ | ||
| 1869 | if (cpu_data(mce->cpu).phys_proc_id != pvt->sbridge_dev->mc) | ||
| 1870 | return NOTIFY_DONE; | ||
| 1871 | |||
| 1872 | smp_rmb(); | 2109 | smp_rmb(); |
| 1873 | if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) { | 2110 | if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) { |
| 1874 | smp_wmb(); | 2111 | smp_wmb(); |
| @@ -1932,7 +2169,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) | |||
| 1932 | int rc; | 2169 | int rc; |
| 1933 | 2170 | ||
| 1934 | /* Check the number of active and not disabled channels */ | 2171 | /* Check the number of active and not disabled channels */ |
| 1935 | rc = check_if_ecc_is_active(sbridge_dev->bus); | 2172 | rc = check_if_ecc_is_active(sbridge_dev->bus, type); |
| 1936 | if (unlikely(rc < 0)) | 2173 | if (unlikely(rc < 0)) |
| 1937 | return rc; | 2174 | return rc; |
| 1938 | 2175 | ||
| @@ -1971,11 +2208,15 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) | |||
| 1971 | mci->edac_check = sbridge_check_error; | 2208 | mci->edac_check = sbridge_check_error; |
| 1972 | 2209 | ||
| 1973 | pvt->info.type = type; | 2210 | pvt->info.type = type; |
| 1974 | if (type == IVY_BRIDGE) { | 2211 | switch (type) { |
| 2212 | case IVY_BRIDGE: | ||
| 1975 | pvt->info.rankcfgr = IB_RANK_CFG_A; | 2213 | pvt->info.rankcfgr = IB_RANK_CFG_A; |
| 1976 | pvt->info.get_tolm = ibridge_get_tolm; | 2214 | pvt->info.get_tolm = ibridge_get_tolm; |
| 1977 | pvt->info.get_tohm = ibridge_get_tohm; | 2215 | pvt->info.get_tohm = ibridge_get_tohm; |
| 1978 | pvt->info.dram_rule = ibridge_dram_rule; | 2216 | pvt->info.dram_rule = ibridge_dram_rule; |
| 2217 | pvt->info.get_memory_type = get_memory_type; | ||
| 2218 | pvt->info.get_node_id = get_node_id; | ||
| 2219 | pvt->info.rir_limit = rir_limit; | ||
| 1979 | pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule); | 2220 | pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule); |
| 1980 | pvt->info.interleave_list = ibridge_interleave_list; | 2221 | pvt->info.interleave_list = ibridge_interleave_list; |
| 1981 | pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); | 2222 | pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); |
| @@ -1986,11 +2227,15 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) | |||
| 1986 | rc = ibridge_mci_bind_devs(mci, sbridge_dev); | 2227 | rc = ibridge_mci_bind_devs(mci, sbridge_dev); |
| 1987 | if (unlikely(rc < 0)) | 2228 | if (unlikely(rc < 0)) |
| 1988 | goto fail0; | 2229 | goto fail0; |
| 1989 | } else { | 2230 | break; |
| 2231 | case SANDY_BRIDGE: | ||
| 1990 | pvt->info.rankcfgr = SB_RANK_CFG_A; | 2232 | pvt->info.rankcfgr = SB_RANK_CFG_A; |
| 1991 | pvt->info.get_tolm = sbridge_get_tolm; | 2233 | pvt->info.get_tolm = sbridge_get_tolm; |
| 1992 | pvt->info.get_tohm = sbridge_get_tohm; | 2234 | pvt->info.get_tohm = sbridge_get_tohm; |
| 1993 | pvt->info.dram_rule = sbridge_dram_rule; | 2235 | pvt->info.dram_rule = sbridge_dram_rule; |
| 2236 | pvt->info.get_memory_type = get_memory_type; | ||
| 2237 | pvt->info.get_node_id = get_node_id; | ||
| 2238 | pvt->info.rir_limit = rir_limit; | ||
| 1994 | pvt->info.max_sad = ARRAY_SIZE(sbridge_dram_rule); | 2239 | pvt->info.max_sad = ARRAY_SIZE(sbridge_dram_rule); |
| 1995 | pvt->info.interleave_list = sbridge_interleave_list; | 2240 | pvt->info.interleave_list = sbridge_interleave_list; |
| 1996 | pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list); | 2241 | pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list); |
| @@ -2001,8 +2246,27 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) | |||
| 2001 | rc = sbridge_mci_bind_devs(mci, sbridge_dev); | 2246 | rc = sbridge_mci_bind_devs(mci, sbridge_dev); |
| 2002 | if (unlikely(rc < 0)) | 2247 | if (unlikely(rc < 0)) |
| 2003 | goto fail0; | 2248 | goto fail0; |
| 2004 | } | 2249 | break; |
| 2250 | case HASWELL: | ||
| 2251 | /* rankcfgr isn't used */ | ||
| 2252 | pvt->info.get_tolm = haswell_get_tolm; | ||
| 2253 | pvt->info.get_tohm = haswell_get_tohm; | ||
| 2254 | pvt->info.dram_rule = ibridge_dram_rule; | ||
| 2255 | pvt->info.get_memory_type = haswell_get_memory_type; | ||
| 2256 | pvt->info.get_node_id = haswell_get_node_id; | ||
| 2257 | pvt->info.rir_limit = haswell_rir_limit; | ||
| 2258 | pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule); | ||
| 2259 | pvt->info.interleave_list = ibridge_interleave_list; | ||
| 2260 | pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); | ||
| 2261 | pvt->info.interleave_pkg = ibridge_interleave_pkg; | ||
| 2262 | mci->ctl_name = kasprintf(GFP_KERNEL, "Haswell Socket#%d", mci->mc_idx); | ||
| 2005 | 2263 | ||
| 2264 | /* Store pci devices at mci for faster access */ | ||
| 2265 | rc = haswell_mci_bind_devs(mci, sbridge_dev); | ||
| 2266 | if (unlikely(rc < 0)) | ||
| 2267 | goto fail0; | ||
| 2268 | break; | ||
| 2269 | } | ||
| 2006 | 2270 | ||
| 2007 | /* Get dimm basic config and the memory layout */ | 2271 | /* Get dimm basic config and the memory layout */ |
| 2008 | get_dimm_config(mci); | 2272 | get_dimm_config(mci); |
| @@ -2037,10 +2301,10 @@ fail0: | |||
| 2037 | 2301 | ||
| 2038 | static int sbridge_probe(struct pci_dev *pdev, const struct pci_device_id *id) | 2302 | static int sbridge_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
| 2039 | { | 2303 | { |
| 2040 | int rc; | 2304 | int rc = -ENODEV; |
| 2041 | u8 mc, num_mc = 0; | 2305 | u8 mc, num_mc = 0; |
| 2042 | struct sbridge_dev *sbridge_dev; | 2306 | struct sbridge_dev *sbridge_dev; |
| 2043 | enum type type; | 2307 | enum type type = SANDY_BRIDGE; |
| 2044 | 2308 | ||
| 2045 | /* get the pci devices we want to reserve for our use */ | 2309 | /* get the pci devices we want to reserve for our use */ |
| 2046 | mutex_lock(&sbridge_edac_lock); | 2310 | mutex_lock(&sbridge_edac_lock); |
| @@ -2054,12 +2318,19 @@ static int sbridge_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 2054 | } | 2318 | } |
| 2055 | probed++; | 2319 | probed++; |
| 2056 | 2320 | ||
| 2057 | if (pdev->device == PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA) { | 2321 | switch (pdev->device) { |
| 2322 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA: | ||
| 2058 | rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_ibridge_table); | 2323 | rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_ibridge_table); |
| 2059 | type = IVY_BRIDGE; | 2324 | type = IVY_BRIDGE; |
| 2060 | } else { | 2325 | break; |
| 2326 | case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA: | ||
| 2061 | rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_sbridge_table); | 2327 | rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_sbridge_table); |
| 2062 | type = SANDY_BRIDGE; | 2328 | type = SANDY_BRIDGE; |
| 2329 | break; | ||
| 2330 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0: | ||
| 2331 | rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_haswell_table); | ||
| 2332 | type = HASWELL; | ||
| 2333 | break; | ||
| 2063 | } | 2334 | } |
| 2064 | if (unlikely(rc < 0)) | 2335 | if (unlikely(rc < 0)) |
| 2065 | goto fail0; | 2336 | goto fail0; |
| @@ -2068,6 +2339,7 @@ static int sbridge_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 2068 | list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) { | 2339 | list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) { |
| 2069 | edac_dbg(0, "Registering MC#%d (%d of %d)\n", | 2340 | edac_dbg(0, "Registering MC#%d (%d of %d)\n", |
| 2070 | mc, mc + 1, num_mc); | 2341 | mc, mc + 1, num_mc); |
| 2342 | |||
| 2071 | sbridge_dev->mc = mc++; | 2343 | sbridge_dev->mc = mc++; |
| 2072 | rc = sbridge_register_mci(sbridge_dev, type); | 2344 | rc = sbridge_register_mci(sbridge_dev, type); |
| 2073 | if (unlikely(rc < 0)) | 2345 | if (unlikely(rc < 0)) |
diff --git a/drivers/gpu/drm/nouveau/core/core/client.c b/drivers/gpu/drm/nouveau/core/core/client.c index 10598dede9e9..68bf06768123 100644 --- a/drivers/gpu/drm/nouveau/core/core/client.c +++ b/drivers/gpu/drm/nouveau/core/core/client.c | |||
| @@ -132,12 +132,12 @@ nvkm_client_notify_new(struct nouveau_client *client, | |||
| 132 | if (ret == 0) { | 132 | if (ret == 0) { |
| 133 | client->notify[index] = notify; | 133 | client->notify[index] = notify; |
| 134 | notify->client = client; | 134 | notify->client = client; |
| 135 | return 0; | 135 | return index; |
| 136 | } | 136 | } |
| 137 | } | 137 | } |
| 138 | 138 | ||
| 139 | kfree(notify); | 139 | kfree(notify); |
| 140 | return 0; | 140 | return ret; |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | static int | 143 | static int |
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nve0.c b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c index 54ec53bc6252..cdf9147f32a1 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c | |||
| @@ -163,6 +163,7 @@ nve0_identify(struct nouveau_device *device) | |||
| 163 | device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass; | 163 | device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass; |
| 164 | device->oclass[NVDEV_SUBDEV_TIMER ] = &gk20a_timer_oclass; | 164 | device->oclass[NVDEV_SUBDEV_TIMER ] = &gk20a_timer_oclass; |
| 165 | device->oclass[NVDEV_SUBDEV_FB ] = gk20a_fb_oclass; | 165 | device->oclass[NVDEV_SUBDEV_FB ] = gk20a_fb_oclass; |
| 166 | device->oclass[NVDEV_SUBDEV_LTC ] = gk104_ltc_oclass; | ||
| 166 | device->oclass[NVDEV_SUBDEV_IBUS ] = &gk20a_ibus_oclass; | 167 | device->oclass[NVDEV_SUBDEV_IBUS ] = &gk20a_ibus_oclass; |
| 167 | device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; | 168 | device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; |
| 168 | device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; | 169 | device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; |
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c index db19191176fa..30fd1dc64f93 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c | |||
| @@ -68,6 +68,9 @@ nvc0_graph_zbc_color_get(struct nvc0_graph_priv *priv, int format, | |||
| 68 | } | 68 | } |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | if (zbc < 0) | ||
| 72 | return zbc; | ||
| 73 | |||
| 71 | memcpy(priv->zbc_color[zbc].ds, ds, sizeof(priv->zbc_color[zbc].ds)); | 74 | memcpy(priv->zbc_color[zbc].ds, ds, sizeof(priv->zbc_color[zbc].ds)); |
| 72 | memcpy(priv->zbc_color[zbc].l2, l2, sizeof(priv->zbc_color[zbc].l2)); | 75 | memcpy(priv->zbc_color[zbc].l2, l2, sizeof(priv->zbc_color[zbc].l2)); |
| 73 | priv->zbc_color[zbc].format = format; | 76 | priv->zbc_color[zbc].format = format; |
| @@ -109,6 +112,9 @@ nvc0_graph_zbc_depth_get(struct nvc0_graph_priv *priv, int format, | |||
| 109 | } | 112 | } |
| 110 | } | 113 | } |
| 111 | 114 | ||
| 115 | if (zbc < 0) | ||
| 116 | return zbc; | ||
| 117 | |||
| 112 | priv->zbc_depth[zbc].format = format; | 118 | priv->zbc_depth[zbc].format = format; |
| 113 | priv->zbc_depth[zbc].ds = ds; | 119 | priv->zbc_depth[zbc].ds = ds; |
| 114 | priv->zbc_depth[zbc].l2 = l2; | 120 | priv->zbc_depth[zbc].l2 = l2; |
diff --git a/drivers/gpu/drm/nouveau/core/include/core/client.h b/drivers/gpu/drm/nouveau/core/include/core/client.h index 4fc6ab12382d..1794a05205d8 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/client.h +++ b/drivers/gpu/drm/nouveau/core/include/core/client.h | |||
| @@ -14,7 +14,7 @@ struct nouveau_client { | |||
| 14 | void *data; | 14 | void *data; |
| 15 | 15 | ||
| 16 | int (*ntfy)(const void *, u32, const void *, u32); | 16 | int (*ntfy)(const void *, u32, const void *, u32); |
| 17 | struct nvkm_client_notify *notify[8]; | 17 | struct nvkm_client_notify *notify[16]; |
| 18 | }; | 18 | }; |
| 19 | 19 | ||
| 20 | static inline struct nouveau_client * | 20 | static inline struct nouveau_client * |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/base.c b/drivers/gpu/drm/nouveau/core/subdev/bar/base.c index 73b1ed20c8d5..8bcbdf39cfb2 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bar/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bar/base.c | |||
| @@ -99,8 +99,13 @@ nouveau_bar_alloc(struct nouveau_bar *bar, struct nouveau_object *parent, | |||
| 99 | struct nouveau_mem *mem, struct nouveau_object **pobject) | 99 | struct nouveau_mem *mem, struct nouveau_object **pobject) |
| 100 | { | 100 | { |
| 101 | struct nouveau_object *engine = nv_object(bar); | 101 | struct nouveau_object *engine = nv_object(bar); |
| 102 | return nouveau_object_ctor(parent, engine, &nouveau_barobj_oclass, | 102 | int ret = -ENOMEM; |
| 103 | mem, 0, pobject); | 103 | if (bar->iomem) { |
| 104 | ret = nouveau_object_ctor(parent, engine, | ||
| 105 | &nouveau_barobj_oclass, | ||
| 106 | mem, 0, pobject); | ||
| 107 | } | ||
| 108 | return ret; | ||
| 104 | } | 109 | } |
| 105 | 110 | ||
| 106 | int | 111 | int |
| @@ -118,9 +123,12 @@ nouveau_bar_create_(struct nouveau_object *parent, | |||
| 118 | if (ret) | 123 | if (ret) |
| 119 | return ret; | 124 | return ret; |
| 120 | 125 | ||
| 121 | if (nv_device_resource_len(device, 3) != 0) | 126 | if (nv_device_resource_len(device, 3) != 0) { |
| 122 | bar->iomem = ioremap(nv_device_resource_start(device, 3), | 127 | bar->iomem = ioremap(nv_device_resource_start(device, 3), |
| 123 | nv_device_resource_len(device, 3)); | 128 | nv_device_resource_len(device, 3)); |
| 129 | if (!bar->iomem) | ||
| 130 | nv_warn(bar, "PRAMIN ioremap failed\n"); | ||
| 131 | } | ||
| 124 | 132 | ||
| 125 | return 0; | 133 | return 0; |
| 126 | } | 134 | } |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c index 946518572346..2b284b192763 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c | |||
| @@ -554,13 +554,13 @@ nvc0_ram_create_(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 554 | } else { | 554 | } else { |
| 555 | /* otherwise, address lowest common amount from 0GiB */ | 555 | /* otherwise, address lowest common amount from 0GiB */ |
| 556 | ret = nouveau_mm_init(&pfb->vram, rsvd_head, | 556 | ret = nouveau_mm_init(&pfb->vram, rsvd_head, |
| 557 | (bsize << 8) * parts, 1); | 557 | (bsize << 8) * parts - rsvd_head, 1); |
| 558 | if (ret) | 558 | if (ret) |
| 559 | return ret; | 559 | return ret; |
| 560 | 560 | ||
| 561 | /* and the rest starting from (8GiB + common_size) */ | 561 | /* and the rest starting from (8GiB + common_size) */ |
| 562 | offset = (0x0200000000ULL >> 12) + (bsize << 8); | 562 | offset = (0x0200000000ULL >> 12) + (bsize << 8); |
| 563 | length = (ram->size >> 12) - (bsize << 8) - rsvd_tail; | 563 | length = (ram->size >> 12) - ((bsize * parts) << 8) - rsvd_tail; |
| 564 | 564 | ||
| 565 | ret = nouveau_mm_init(&pfb->vram, offset, length, 0); | 565 | ret = nouveau_mm_init(&pfb->vram, offset, length, 0); |
| 566 | if (ret) | 566 | if (ret) |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltc/gf100.c b/drivers/gpu/drm/nouveau/core/subdev/ltc/gf100.c index 9e00a1ede120..b54b582e72c4 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/ltc/gf100.c +++ b/drivers/gpu/drm/nouveau/core/subdev/ltc/gf100.c | |||
| @@ -156,7 +156,7 @@ gf100_ltc_init_tag_ram(struct nouveau_fb *pfb, struct nvkm_ltc_priv *priv) | |||
| 156 | if (ret) { | 156 | if (ret) { |
| 157 | priv->num_tags = 0; | 157 | priv->num_tags = 0; |
| 158 | } else { | 158 | } else { |
| 159 | u64 tag_base = (priv->tag_ram->offset << 12) + tag_margin; | 159 | u64 tag_base = ((u64)priv->tag_ram->offset << 12) + tag_margin; |
| 160 | 160 | ||
| 161 | tag_base += tag_align - 1; | 161 | tag_base += tag_align - 1; |
| 162 | ret = do_div(tag_base, tag_align); | 162 | ret = do_div(tag_base, tag_align); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index da5d631aa5b9..01da508625f2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c | |||
| @@ -1228,7 +1228,6 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) | |||
| 1228 | struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; | 1228 | struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; |
| 1229 | struct nouveau_drm *drm = nouveau_bdev(bdev); | 1229 | struct nouveau_drm *drm = nouveau_bdev(bdev); |
| 1230 | struct nouveau_mem *node = mem->mm_node; | 1230 | struct nouveau_mem *node = mem->mm_node; |
| 1231 | struct drm_device *dev = drm->dev; | ||
| 1232 | int ret; | 1231 | int ret; |
| 1233 | 1232 | ||
| 1234 | mem->bus.addr = NULL; | 1233 | mem->bus.addr = NULL; |
| @@ -1247,7 +1246,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) | |||
| 1247 | if (drm->agp.stat == ENABLED) { | 1246 | if (drm->agp.stat == ENABLED) { |
| 1248 | mem->bus.offset = mem->start << PAGE_SHIFT; | 1247 | mem->bus.offset = mem->start << PAGE_SHIFT; |
| 1249 | mem->bus.base = drm->agp.base; | 1248 | mem->bus.base = drm->agp.base; |
| 1250 | mem->bus.is_iomem = !dev->agp->cant_use_aperture; | 1249 | mem->bus.is_iomem = !drm->dev->agp->cant_use_aperture; |
| 1251 | } | 1250 | } |
| 1252 | #endif | 1251 | #endif |
| 1253 | if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA || !node->memtype) | 1252 | if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA || !node->memtype) |
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 1cc7b603c753..65b4fd53dd4e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c | |||
| @@ -592,7 +592,9 @@ nouveau_display_repin(struct drm_device *dev) | |||
| 592 | if (!nouveau_fb || !nouveau_fb->nvbo) | 592 | if (!nouveau_fb || !nouveau_fb->nvbo) |
| 593 | continue; | 593 | continue; |
| 594 | 594 | ||
| 595 | nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM); | 595 | ret = nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM); |
| 596 | if (ret) | ||
| 597 | NV_ERROR(drm, "Could not pin framebuffer\n"); | ||
| 596 | } | 598 | } |
| 597 | 599 | ||
| 598 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | 600 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index ebfe3180109e..8bdd27091db8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c | |||
| @@ -226,7 +226,7 @@ nouveau_fbcon_accel_restore(struct drm_device *dev) | |||
| 226 | } | 226 | } |
| 227 | } | 227 | } |
| 228 | 228 | ||
| 229 | void | 229 | static void |
| 230 | nouveau_fbcon_accel_fini(struct drm_device *dev) | 230 | nouveau_fbcon_accel_fini(struct drm_device *dev) |
| 231 | { | 231 | { |
| 232 | struct nouveau_drm *drm = nouveau_drm(dev); | 232 | struct nouveau_drm *drm = nouveau_drm(dev); |
| @@ -246,7 +246,7 @@ nouveau_fbcon_accel_fini(struct drm_device *dev) | |||
| 246 | } | 246 | } |
| 247 | } | 247 | } |
| 248 | 248 | ||
| 249 | void | 249 | static void |
| 250 | nouveau_fbcon_accel_init(struct drm_device *dev) | 250 | nouveau_fbcon_accel_init(struct drm_device *dev) |
| 251 | { | 251 | { |
| 252 | struct nouveau_drm *drm = nouveau_drm(dev); | 252 | struct nouveau_drm *drm = nouveau_drm(dev); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_platform.c b/drivers/gpu/drm/nouveau/nouveau_platform.c index 0ffeb50d0088..246a824c16ca 100644 --- a/drivers/gpu/drm/nouveau/nouveau_platform.c +++ b/drivers/gpu/drm/nouveau/nouveau_platform.c | |||
| @@ -149,7 +149,8 @@ power_down: | |||
| 149 | static int nouveau_platform_remove(struct platform_device *pdev) | 149 | static int nouveau_platform_remove(struct platform_device *pdev) |
| 150 | { | 150 | { |
| 151 | struct drm_device *drm_dev = platform_get_drvdata(pdev); | 151 | struct drm_device *drm_dev = platform_get_drvdata(pdev); |
| 152 | struct nouveau_device *device = nouveau_dev(drm_dev); | 152 | struct nouveau_drm *drm = nouveau_drm(drm_dev); |
| 153 | struct nouveau_device *device = nvkm_device(&drm->device); | ||
| 153 | struct nouveau_platform_gpu *gpu = nv_device_to_platform(device)->gpu; | 154 | struct nouveau_platform_gpu *gpu = nv_device_to_platform(device)->gpu; |
| 154 | 155 | ||
| 155 | nouveau_drm_device_remove(drm_dev); | 156 | nouveau_drm_device_remove(drm_dev); |
diff --git a/drivers/gpu/drm/nouveau/nvif/class.h b/drivers/gpu/drm/nouveau/nvif/class.h index cc81e0e5fd30..573491f84792 100644 --- a/drivers/gpu/drm/nouveau/nvif/class.h +++ b/drivers/gpu/drm/nouveau/nvif/class.h | |||
| @@ -428,8 +428,8 @@ struct nv50_disp_dac_pwr_v0 { | |||
| 428 | struct nv50_disp_dac_load_v0 { | 428 | struct nv50_disp_dac_load_v0 { |
| 429 | __u8 version; | 429 | __u8 version; |
| 430 | __u8 load; | 430 | __u8 load; |
| 431 | __u16 data; | 431 | __u8 pad02[2]; |
| 432 | __u8 pad04[4]; | 432 | __u32 data; |
| 433 | }; | 433 | }; |
| 434 | 434 | ||
| 435 | struct nv50_disp_sor_pwr_v0 { | 435 | struct nv50_disp_sor_pwr_v0 { |
diff --git a/drivers/gpu/drm/nouveau/nvif/notify.c b/drivers/gpu/drm/nouveau/nvif/notify.c index 7c06123a559c..0898c3155292 100644 --- a/drivers/gpu/drm/nouveau/nvif/notify.c +++ b/drivers/gpu/drm/nouveau/nvif/notify.c | |||
| @@ -87,12 +87,25 @@ nvif_notify_get(struct nvif_notify *notify) | |||
| 87 | return 0; | 87 | return 0; |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | static inline int | ||
| 91 | nvif_notify_func(struct nvif_notify *notify, bool keep) | ||
| 92 | { | ||
| 93 | int ret = notify->func(notify); | ||
| 94 | if (ret == NVIF_NOTIFY_KEEP || | ||
| 95 | !test_and_clear_bit(NVKM_NOTIFY_USER, ¬ify->flags)) { | ||
| 96 | if (!keep) | ||
| 97 | atomic_dec(¬ify->putcnt); | ||
| 98 | else | ||
| 99 | nvif_notify_get_(notify); | ||
| 100 | } | ||
| 101 | return ret; | ||
| 102 | } | ||
| 103 | |||
| 90 | static void | 104 | static void |
| 91 | nvif_notify_work(struct work_struct *work) | 105 | nvif_notify_work(struct work_struct *work) |
| 92 | { | 106 | { |
| 93 | struct nvif_notify *notify = container_of(work, typeof(*notify), work); | 107 | struct nvif_notify *notify = container_of(work, typeof(*notify), work); |
| 94 | if (notify->func(notify) == NVIF_NOTIFY_KEEP) | 108 | nvif_notify_func(notify, true); |
| 95 | nvif_notify_get_(notify); | ||
| 96 | } | 109 | } |
| 97 | 110 | ||
| 98 | int | 111 | int |
| @@ -113,19 +126,15 @@ nvif_notify(const void *header, u32 length, const void *data, u32 size) | |||
| 113 | if (!WARN_ON(notify == NULL)) { | 126 | if (!WARN_ON(notify == NULL)) { |
| 114 | struct nvif_client *client = nvif_client(notify->object); | 127 | struct nvif_client *client = nvif_client(notify->object); |
| 115 | if (!WARN_ON(notify->size != size)) { | 128 | if (!WARN_ON(notify->size != size)) { |
| 129 | atomic_inc(¬ify->putcnt); | ||
| 116 | if (test_bit(NVIF_NOTIFY_WORK, ¬ify->flags)) { | 130 | if (test_bit(NVIF_NOTIFY_WORK, ¬ify->flags)) { |
| 117 | atomic_inc(¬ify->putcnt); | ||
| 118 | memcpy((void *)notify->data, data, size); | 131 | memcpy((void *)notify->data, data, size); |
| 119 | schedule_work(¬ify->work); | 132 | schedule_work(¬ify->work); |
| 120 | return NVIF_NOTIFY_DROP; | 133 | return NVIF_NOTIFY_DROP; |
| 121 | } | 134 | } |
| 122 | notify->data = data; | 135 | notify->data = data; |
| 123 | ret = notify->func(notify); | 136 | ret = nvif_notify_func(notify, client->driver->keep); |
| 124 | notify->data = NULL; | 137 | notify->data = NULL; |
| 125 | if (ret != NVIF_NOTIFY_DROP && client->driver->keep) { | ||
| 126 | atomic_inc(¬ify->putcnt); | ||
| 127 | nvif_notify_get_(notify); | ||
| 128 | } | ||
| 129 | } | 138 | } |
| 130 | } | 139 | } |
| 131 | 140 | ||
| @@ -228,8 +237,10 @@ nvif_notify_new(struct nvif_object *object, int (*func)(struct nvif_notify *), | |||
| 228 | if (notify) { | 237 | if (notify) { |
| 229 | int ret = nvif_notify_init(object, nvif_notify_del, func, work, | 238 | int ret = nvif_notify_init(object, nvif_notify_del, func, work, |
| 230 | type, data, size, reply, notify); | 239 | type, data, size, reply, notify); |
| 231 | if (ret) | 240 | if (ret) { |
| 232 | kfree(notify); | 241 | kfree(notify); |
| 242 | notify = NULL; | ||
| 243 | } | ||
| 233 | *pnotify = notify; | 244 | *pnotify = notify; |
| 234 | return ret; | 245 | return ret; |
| 235 | } | 246 | } |
diff --git a/drivers/gpu/drm/nouveau/nvif/object.c b/drivers/gpu/drm/nouveau/nvif/object.c index b0c82206ece2..dd85b56f6aa5 100644 --- a/drivers/gpu/drm/nouveau/nvif/object.c +++ b/drivers/gpu/drm/nouveau/nvif/object.c | |||
| @@ -275,8 +275,10 @@ nvif_object_new(struct nvif_object *parent, u32 handle, u32 oclass, | |||
| 275 | if (object) { | 275 | if (object) { |
| 276 | int ret = nvif_object_init(parent, nvif_object_del, handle, | 276 | int ret = nvif_object_init(parent, nvif_object_del, handle, |
| 277 | oclass, data, size, object); | 277 | oclass, data, size, object); |
| 278 | if (ret) | 278 | if (ret) { |
| 279 | kfree(object); | 279 | kfree(object); |
| 280 | object = NULL; | ||
| 281 | } | ||
| 280 | *pobject = object; | 282 | *pobject = object; |
| 281 | return ret; | 283 | return ret; |
| 282 | } | 284 | } |
diff --git a/drivers/hid/hid-cherry.c b/drivers/hid/hid-cherry.c index 1bdcccc54a1d..f745d2c1325e 100644 --- a/drivers/hid/hid-cherry.c +++ b/drivers/hid/hid-cherry.c | |||
| @@ -28,7 +28,7 @@ | |||
| 28 | static __u8 *ch_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 28 | static __u8 *ch_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 29 | unsigned int *rsize) | 29 | unsigned int *rsize) |
| 30 | { | 30 | { |
| 31 | if (*rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) { | 31 | if (*rsize >= 18 && rdesc[11] == 0x3c && rdesc[12] == 0x02) { |
| 32 | hid_info(hdev, "fixing up Cherry Cymotion report descriptor\n"); | 32 | hid_info(hdev, "fixing up Cherry Cymotion report descriptor\n"); |
| 33 | rdesc[11] = rdesc[16] = 0xff; | 33 | rdesc[11] = rdesc[16] = 0xff; |
| 34 | rdesc[12] = rdesc[17] = 0x03; | 34 | rdesc[12] = rdesc[17] = 0x03; |
diff --git a/drivers/hid/hid-huion.c b/drivers/hid/hid-huion.c index 60f44cd1b0ed..61b68ca27790 100644 --- a/drivers/hid/hid-huion.c +++ b/drivers/hid/hid-huion.c | |||
| @@ -84,6 +84,15 @@ static const __u8 huion_tablet_rdesc_template[] = { | |||
| 84 | 0xC0 /* End Collection */ | 84 | 0xC0 /* End Collection */ |
| 85 | }; | 85 | }; |
| 86 | 86 | ||
| 87 | /* Parameter indices */ | ||
| 88 | enum huion_prm { | ||
| 89 | HUION_PRM_X_LM = 1, | ||
| 90 | HUION_PRM_Y_LM = 2, | ||
| 91 | HUION_PRM_PRESSURE_LM = 4, | ||
| 92 | HUION_PRM_RESOLUTION = 5, | ||
| 93 | HUION_PRM_NUM | ||
| 94 | }; | ||
| 95 | |||
| 87 | /* Driver data */ | 96 | /* Driver data */ |
| 88 | struct huion_drvdata { | 97 | struct huion_drvdata { |
| 89 | __u8 *rdesc; | 98 | __u8 *rdesc; |
| @@ -115,7 +124,12 @@ static int huion_tablet_enable(struct hid_device *hdev) | |||
| 115 | int rc; | 124 | int rc; |
| 116 | struct usb_device *usb_dev = hid_to_usb_dev(hdev); | 125 | struct usb_device *usb_dev = hid_to_usb_dev(hdev); |
| 117 | struct huion_drvdata *drvdata = hid_get_drvdata(hdev); | 126 | struct huion_drvdata *drvdata = hid_get_drvdata(hdev); |
| 118 | __le16 buf[6]; | 127 | __le16 *buf = NULL; |
| 128 | size_t len; | ||
| 129 | s32 params[HUION_PH_ID_NUM]; | ||
| 130 | s32 resolution; | ||
| 131 | __u8 *p; | ||
| 132 | s32 v; | ||
| 119 | 133 | ||
| 120 | /* | 134 | /* |
| 121 | * Read string descriptor containing tablet parameters. The specific | 135 | * Read string descriptor containing tablet parameters. The specific |
| @@ -123,65 +137,79 @@ static int huion_tablet_enable(struct hid_device *hdev) | |||
| 123 | * driver traffic. | 137 | * driver traffic. |
| 124 | * NOTE: This enables fully-functional tablet mode. | 138 | * NOTE: This enables fully-functional tablet mode. |
| 125 | */ | 139 | */ |
| 140 | len = HUION_PRM_NUM * sizeof(*buf); | ||
| 141 | buf = kmalloc(len, GFP_KERNEL); | ||
| 142 | if (buf == NULL) { | ||
| 143 | hid_err(hdev, "failed to allocate parameter buffer\n"); | ||
| 144 | rc = -ENOMEM; | ||
| 145 | goto cleanup; | ||
| 146 | } | ||
| 126 | rc = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), | 147 | rc = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), |
| 127 | USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, | 148 | USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, |
| 128 | (USB_DT_STRING << 8) + 0x64, | 149 | (USB_DT_STRING << 8) + 0x64, |
| 129 | 0x0409, buf, sizeof(buf), | 150 | 0x0409, buf, len, |
| 130 | USB_CTRL_GET_TIMEOUT); | 151 | USB_CTRL_GET_TIMEOUT); |
| 131 | if (rc == -EPIPE) | 152 | if (rc == -EPIPE) { |
| 132 | hid_warn(hdev, "device parameters not found\n"); | 153 | hid_err(hdev, "device parameters not found\n"); |
| 133 | else if (rc < 0) | 154 | rc = -ENODEV; |
| 134 | hid_warn(hdev, "failed to get device parameters: %d\n", rc); | 155 | goto cleanup; |
| 135 | else if (rc != sizeof(buf)) | 156 | } else if (rc < 0) { |
| 136 | hid_warn(hdev, "invalid device parameters\n"); | 157 | hid_err(hdev, "failed to get device parameters: %d\n", rc); |
| 137 | else { | 158 | rc = -ENODEV; |
| 138 | s32 params[HUION_PH_ID_NUM]; | 159 | goto cleanup; |
| 139 | s32 resolution; | 160 | } else if (rc != len) { |
| 140 | __u8 *p; | 161 | hid_err(hdev, "invalid device parameters\n"); |
| 141 | s32 v; | 162 | rc = -ENODEV; |
| 163 | goto cleanup; | ||
| 164 | } | ||
| 142 | 165 | ||
| 143 | /* Extract device parameters */ | 166 | /* Extract device parameters */ |
| 144 | params[HUION_PH_ID_X_LM] = le16_to_cpu(buf[1]); | 167 | params[HUION_PH_ID_X_LM] = le16_to_cpu(buf[HUION_PRM_X_LM]); |
| 145 | params[HUION_PH_ID_Y_LM] = le16_to_cpu(buf[2]); | 168 | params[HUION_PH_ID_Y_LM] = le16_to_cpu(buf[HUION_PRM_Y_LM]); |
| 146 | params[HUION_PH_ID_PRESSURE_LM] = le16_to_cpu(buf[4]); | 169 | params[HUION_PH_ID_PRESSURE_LM] = |
| 147 | resolution = le16_to_cpu(buf[5]); | 170 | le16_to_cpu(buf[HUION_PRM_PRESSURE_LM]); |
| 148 | if (resolution == 0) { | 171 | resolution = le16_to_cpu(buf[HUION_PRM_RESOLUTION]); |
| 149 | params[HUION_PH_ID_X_PM] = 0; | 172 | if (resolution == 0) { |
| 150 | params[HUION_PH_ID_Y_PM] = 0; | 173 | params[HUION_PH_ID_X_PM] = 0; |
| 151 | } else { | 174 | params[HUION_PH_ID_Y_PM] = 0; |
| 152 | params[HUION_PH_ID_X_PM] = params[HUION_PH_ID_X_LM] * | 175 | } else { |
| 153 | 1000 / resolution; | 176 | params[HUION_PH_ID_X_PM] = params[HUION_PH_ID_X_LM] * |
| 154 | params[HUION_PH_ID_Y_PM] = params[HUION_PH_ID_Y_LM] * | 177 | 1000 / resolution; |
| 155 | 1000 / resolution; | 178 | params[HUION_PH_ID_Y_PM] = params[HUION_PH_ID_Y_LM] * |
| 156 | } | 179 | 1000 / resolution; |
| 180 | } | ||
| 157 | 181 | ||
| 158 | /* Allocate fixed report descriptor */ | 182 | /* Allocate fixed report descriptor */ |
| 159 | drvdata->rdesc = devm_kmalloc(&hdev->dev, | 183 | drvdata->rdesc = devm_kmalloc(&hdev->dev, |
| 160 | sizeof(huion_tablet_rdesc_template), | 184 | sizeof(huion_tablet_rdesc_template), |
| 161 | GFP_KERNEL); | 185 | GFP_KERNEL); |
| 162 | if (drvdata->rdesc == NULL) { | 186 | if (drvdata->rdesc == NULL) { |
| 163 | hid_err(hdev, "failed to allocate fixed rdesc\n"); | 187 | hid_err(hdev, "failed to allocate fixed rdesc\n"); |
| 164 | return -ENOMEM; | 188 | rc = -ENOMEM; |
| 165 | } | 189 | goto cleanup; |
| 166 | drvdata->rsize = sizeof(huion_tablet_rdesc_template); | 190 | } |
| 191 | drvdata->rsize = sizeof(huion_tablet_rdesc_template); | ||
| 167 | 192 | ||
| 168 | /* Format fixed report descriptor */ | 193 | /* Format fixed report descriptor */ |
| 169 | memcpy(drvdata->rdesc, huion_tablet_rdesc_template, | 194 | memcpy(drvdata->rdesc, huion_tablet_rdesc_template, |
| 170 | drvdata->rsize); | 195 | drvdata->rsize); |
| 171 | for (p = drvdata->rdesc; | 196 | for (p = drvdata->rdesc; |
| 172 | p <= drvdata->rdesc + drvdata->rsize - 4;) { | 197 | p <= drvdata->rdesc + drvdata->rsize - 4;) { |
| 173 | if (p[0] == 0xFE && p[1] == 0xED && p[2] == 0x1D && | 198 | if (p[0] == 0xFE && p[1] == 0xED && p[2] == 0x1D && |
| 174 | p[3] < sizeof(params)) { | 199 | p[3] < sizeof(params)) { |
| 175 | v = params[p[3]]; | 200 | v = params[p[3]]; |
| 176 | put_unaligned(cpu_to_le32(v), (s32 *)p); | 201 | put_unaligned(cpu_to_le32(v), (s32 *)p); |
| 177 | p += 4; | 202 | p += 4; |
| 178 | } else { | 203 | } else { |
| 179 | p++; | 204 | p++; |
| 180 | } | ||
| 181 | } | 205 | } |
| 182 | } | 206 | } |
| 183 | 207 | ||
| 184 | return 0; | 208 | rc = 0; |
| 209 | |||
| 210 | cleanup: | ||
| 211 | kfree(buf); | ||
| 212 | return rc; | ||
| 185 | } | 213 | } |
| 186 | 214 | ||
| 187 | static int huion_probe(struct hid_device *hdev, const struct hid_device_id *id) | 215 | static int huion_probe(struct hid_device *hdev, const struct hid_device_id *id) |
diff --git a/drivers/hid/hid-kye.c b/drivers/hid/hid-kye.c index e77696367591..b92bf01a1ae8 100644 --- a/drivers/hid/hid-kye.c +++ b/drivers/hid/hid-kye.c | |||
| @@ -300,7 +300,7 @@ static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
| 300 | * - change the button usage range to 4-7 for the extra | 300 | * - change the button usage range to 4-7 for the extra |
| 301 | * buttons | 301 | * buttons |
| 302 | */ | 302 | */ |
| 303 | if (*rsize >= 74 && | 303 | if (*rsize >= 75 && |
| 304 | rdesc[61] == 0x05 && rdesc[62] == 0x08 && | 304 | rdesc[61] == 0x05 && rdesc[62] == 0x08 && |
| 305 | rdesc[63] == 0x19 && rdesc[64] == 0x08 && | 305 | rdesc[63] == 0x19 && rdesc[64] == 0x08 && |
| 306 | rdesc[65] == 0x29 && rdesc[66] == 0x0f && | 306 | rdesc[65] == 0x29 && rdesc[66] == 0x0f && |
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index a976f48263f6..f91ff145db9a 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c | |||
| @@ -345,14 +345,14 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
| 345 | struct usb_device_descriptor *udesc; | 345 | struct usb_device_descriptor *udesc; |
| 346 | __u16 bcdDevice, rev_maj, rev_min; | 346 | __u16 bcdDevice, rev_maj, rev_min; |
| 347 | 347 | ||
| 348 | if ((drv_data->quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 && | 348 | if ((drv_data->quirks & LG_RDESC) && *rsize >= 91 && rdesc[83] == 0x26 && |
| 349 | rdesc[84] == 0x8c && rdesc[85] == 0x02) { | 349 | rdesc[84] == 0x8c && rdesc[85] == 0x02) { |
| 350 | hid_info(hdev, | 350 | hid_info(hdev, |
| 351 | "fixing up Logitech keyboard report descriptor\n"); | 351 | "fixing up Logitech keyboard report descriptor\n"); |
| 352 | rdesc[84] = rdesc[89] = 0x4d; | 352 | rdesc[84] = rdesc[89] = 0x4d; |
| 353 | rdesc[85] = rdesc[90] = 0x10; | 353 | rdesc[85] = rdesc[90] = 0x10; |
| 354 | } | 354 | } |
| 355 | if ((drv_data->quirks & LG_RDESC_REL_ABS) && *rsize >= 50 && | 355 | if ((drv_data->quirks & LG_RDESC_REL_ABS) && *rsize >= 51 && |
| 356 | rdesc[32] == 0x81 && rdesc[33] == 0x06 && | 356 | rdesc[32] == 0x81 && rdesc[33] == 0x06 && |
| 357 | rdesc[49] == 0x81 && rdesc[50] == 0x06) { | 357 | rdesc[49] == 0x81 && rdesc[50] == 0x06) { |
| 358 | hid_info(hdev, | 358 | hid_info(hdev, |
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index cc2bd2022198..7835717bc020 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c | |||
| @@ -451,13 +451,13 @@ static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *at | |||
| 451 | drv_data = hid_get_drvdata(hid); | 451 | drv_data = hid_get_drvdata(hid); |
| 452 | if (!drv_data) { | 452 | if (!drv_data) { |
| 453 | hid_err(hid, "Private driver data not found!\n"); | 453 | hid_err(hid, "Private driver data not found!\n"); |
| 454 | return 0; | 454 | return -EINVAL; |
| 455 | } | 455 | } |
| 456 | 456 | ||
| 457 | entry = drv_data->device_props; | 457 | entry = drv_data->device_props; |
| 458 | if (!entry) { | 458 | if (!entry) { |
| 459 | hid_err(hid, "Device properties not found!\n"); | 459 | hid_err(hid, "Device properties not found!\n"); |
| 460 | return 0; | 460 | return -EINVAL; |
| 461 | } | 461 | } |
| 462 | 462 | ||
| 463 | if (range == 0) | 463 | if (range == 0) |
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 486dbde2ba2d..b7ba82960c79 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c | |||
| @@ -238,13 +238,6 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, | |||
| 238 | return; | 238 | return; |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) || | ||
| 242 | (dj_report->device_index > DJ_DEVICE_INDEX_MAX)) { | ||
| 243 | dev_err(&djrcv_hdev->dev, "%s: invalid device index:%d\n", | ||
| 244 | __func__, dj_report->device_index); | ||
| 245 | return; | ||
| 246 | } | ||
| 247 | |||
| 248 | if (djrcv_dev->paired_dj_devices[dj_report->device_index]) { | 241 | if (djrcv_dev->paired_dj_devices[dj_report->device_index]) { |
| 249 | /* The device is already known. No need to reallocate it. */ | 242 | /* The device is already known. No need to reallocate it. */ |
| 250 | dbg_hid("%s: device is already known\n", __func__); | 243 | dbg_hid("%s: device is already known\n", __func__); |
| @@ -557,7 +550,7 @@ static int logi_dj_ll_raw_request(struct hid_device *hid, | |||
| 557 | if (!out_buf) | 550 | if (!out_buf) |
| 558 | return -ENOMEM; | 551 | return -ENOMEM; |
| 559 | 552 | ||
| 560 | if (count < DJREPORT_SHORT_LENGTH - 2) | 553 | if (count > DJREPORT_SHORT_LENGTH - 2) |
| 561 | count = DJREPORT_SHORT_LENGTH - 2; | 554 | count = DJREPORT_SHORT_LENGTH - 2; |
| 562 | 555 | ||
| 563 | out_buf[0] = REPORT_ID_DJ_SHORT; | 556 | out_buf[0] = REPORT_ID_DJ_SHORT; |
| @@ -690,6 +683,12 @@ static int logi_dj_raw_event(struct hid_device *hdev, | |||
| 690 | * device (via hid_input_report() ) and return 1 so hid-core does not do | 683 | * device (via hid_input_report() ) and return 1 so hid-core does not do |
| 691 | * anything else with it. | 684 | * anything else with it. |
| 692 | */ | 685 | */ |
| 686 | if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) || | ||
| 687 | (dj_report->device_index > DJ_DEVICE_INDEX_MAX)) { | ||
| 688 | dev_err(&hdev->dev, "%s: invalid device index:%d\n", | ||
| 689 | __func__, dj_report->device_index); | ||
| 690 | return false; | ||
| 691 | } | ||
| 693 | 692 | ||
| 694 | spin_lock_irqsave(&djrcv_dev->lock, flags); | 693 | spin_lock_irqsave(&djrcv_dev->lock, flags); |
| 695 | if (dj_report->report_id == REPORT_ID_DJ_SHORT) { | 694 | if (dj_report->report_id == REPORT_ID_DJ_SHORT) { |
diff --git a/drivers/hid/hid-monterey.c b/drivers/hid/hid-monterey.c index 9e14c00eb1b6..25daf28b26bd 100644 --- a/drivers/hid/hid-monterey.c +++ b/drivers/hid/hid-monterey.c | |||
| @@ -24,7 +24,7 @@ | |||
| 24 | static __u8 *mr_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 24 | static __u8 *mr_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 25 | unsigned int *rsize) | 25 | unsigned int *rsize) |
| 26 | { | 26 | { |
| 27 | if (*rsize >= 30 && rdesc[29] == 0x05 && rdesc[30] == 0x09) { | 27 | if (*rsize >= 31 && rdesc[29] == 0x05 && rdesc[30] == 0x09) { |
| 28 | hid_info(hdev, "fixing up button/consumer in HID report descriptor\n"); | 28 | hid_info(hdev, "fixing up button/consumer in HID report descriptor\n"); |
| 29 | rdesc[30] = 0x0c; | 29 | rdesc[30] = 0x0c; |
| 30 | } | 30 | } |
diff --git a/drivers/hid/hid-petalynx.c b/drivers/hid/hid-petalynx.c index 736b2502df4f..6aca4f2554bf 100644 --- a/drivers/hid/hid-petalynx.c +++ b/drivers/hid/hid-petalynx.c | |||
| @@ -25,7 +25,7 @@ | |||
| 25 | static __u8 *pl_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 25 | static __u8 *pl_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 26 | unsigned int *rsize) | 26 | unsigned int *rsize) |
| 27 | { | 27 | { |
| 28 | if (*rsize >= 60 && rdesc[39] == 0x2a && rdesc[40] == 0xf5 && | 28 | if (*rsize >= 62 && rdesc[39] == 0x2a && rdesc[40] == 0xf5 && |
| 29 | rdesc[41] == 0x00 && rdesc[59] == 0x26 && | 29 | rdesc[41] == 0x00 && rdesc[59] == 0x26 && |
| 30 | rdesc[60] == 0xf9 && rdesc[61] == 0x00) { | 30 | rdesc[60] == 0xf9 && rdesc[61] == 0x00) { |
| 31 | hid_info(hdev, "fixing up Petalynx Maxter Remote report descriptor\n"); | 31 | hid_info(hdev, "fixing up Petalynx Maxter Remote report descriptor\n"); |
diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c index 0dc25142f451..8389e8109218 100644 --- a/drivers/hid/hid-rmi.c +++ b/drivers/hid/hid-rmi.c | |||
| @@ -909,10 +909,15 @@ static int rmi_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 909 | return ret; | 909 | return ret; |
| 910 | } | 910 | } |
| 911 | 911 | ||
| 912 | if (!test_bit(RMI_STARTED, &data->flags)) { | 912 | if (!test_bit(RMI_STARTED, &data->flags)) |
| 913 | hid_hw_stop(hdev); | 913 | /* |
| 914 | return -EIO; | 914 | * The device maybe in the bootloader if rmi_input_configured |
| 915 | } | 915 | * failed to find F11 in the PDT. Print an error, but don't |
| 916 | * return an error from rmi_probe so that hidraw will be | ||
| 917 | * accessible from userspace. That way a userspace tool | ||
| 918 | * can be used to reload working firmware on the touchpad. | ||
| 919 | */ | ||
| 920 | hid_err(hdev, "Device failed to be properly configured\n"); | ||
| 916 | 921 | ||
| 917 | return 0; | 922 | return 0; |
| 918 | } | 923 | } |
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index e244e449cbba..2ac25760a9a9 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c | |||
| @@ -604,9 +604,9 @@ static int sensor_hub_probe(struct hid_device *hdev, | |||
| 604 | ret = -EINVAL; | 604 | ret = -EINVAL; |
| 605 | goto err_stop_hw; | 605 | goto err_stop_hw; |
| 606 | } | 606 | } |
| 607 | sd->hid_sensor_hub_client_devs = kzalloc(dev_cnt * | 607 | sd->hid_sensor_hub_client_devs = devm_kzalloc(&hdev->dev, dev_cnt * |
| 608 | sizeof(struct mfd_cell), | 608 | sizeof(struct mfd_cell), |
| 609 | GFP_KERNEL); | 609 | GFP_KERNEL); |
| 610 | if (sd->hid_sensor_hub_client_devs == NULL) { | 610 | if (sd->hid_sensor_hub_client_devs == NULL) { |
| 611 | hid_err(hdev, "Failed to allocate memory for mfd cells\n"); | 611 | hid_err(hdev, "Failed to allocate memory for mfd cells\n"); |
| 612 | ret = -ENOMEM; | 612 | ret = -ENOMEM; |
| @@ -618,11 +618,12 @@ static int sensor_hub_probe(struct hid_device *hdev, | |||
| 618 | 618 | ||
| 619 | if (collection->type == HID_COLLECTION_PHYSICAL) { | 619 | if (collection->type == HID_COLLECTION_PHYSICAL) { |
| 620 | 620 | ||
| 621 | hsdev = kzalloc(sizeof(*hsdev), GFP_KERNEL); | 621 | hsdev = devm_kzalloc(&hdev->dev, sizeof(*hsdev), |
| 622 | GFP_KERNEL); | ||
| 622 | if (!hsdev) { | 623 | if (!hsdev) { |
| 623 | hid_err(hdev, "cannot allocate hid_sensor_hub_device\n"); | 624 | hid_err(hdev, "cannot allocate hid_sensor_hub_device\n"); |
| 624 | ret = -ENOMEM; | 625 | ret = -ENOMEM; |
| 625 | goto err_no_mem; | 626 | goto err_stop_hw; |
| 626 | } | 627 | } |
| 627 | hsdev->hdev = hdev; | 628 | hsdev->hdev = hdev; |
| 628 | hsdev->vendor_id = hdev->vendor; | 629 | hsdev->vendor_id = hdev->vendor; |
| @@ -631,13 +632,13 @@ static int sensor_hub_probe(struct hid_device *hdev, | |||
| 631 | if (last_hsdev) | 632 | if (last_hsdev) |
| 632 | last_hsdev->end_collection_index = i; | 633 | last_hsdev->end_collection_index = i; |
| 633 | last_hsdev = hsdev; | 634 | last_hsdev = hsdev; |
| 634 | name = kasprintf(GFP_KERNEL, "HID-SENSOR-%x", | 635 | name = devm_kasprintf(&hdev->dev, GFP_KERNEL, |
| 635 | collection->usage); | 636 | "HID-SENSOR-%x", |
| 637 | collection->usage); | ||
| 636 | if (name == NULL) { | 638 | if (name == NULL) { |
| 637 | hid_err(hdev, "Failed MFD device name\n"); | 639 | hid_err(hdev, "Failed MFD device name\n"); |
| 638 | ret = -ENOMEM; | 640 | ret = -ENOMEM; |
| 639 | kfree(hsdev); | 641 | goto err_stop_hw; |
| 640 | goto err_no_mem; | ||
| 641 | } | 642 | } |
| 642 | sd->hid_sensor_hub_client_devs[ | 643 | sd->hid_sensor_hub_client_devs[ |
| 643 | sd->hid_sensor_client_cnt].id = | 644 | sd->hid_sensor_client_cnt].id = |
| @@ -661,16 +662,10 @@ static int sensor_hub_probe(struct hid_device *hdev, | |||
| 661 | ret = mfd_add_devices(&hdev->dev, 0, sd->hid_sensor_hub_client_devs, | 662 | ret = mfd_add_devices(&hdev->dev, 0, sd->hid_sensor_hub_client_devs, |
| 662 | sd->hid_sensor_client_cnt, NULL, 0, NULL); | 663 | sd->hid_sensor_client_cnt, NULL, 0, NULL); |
| 663 | if (ret < 0) | 664 | if (ret < 0) |
| 664 | goto err_no_mem; | 665 | goto err_stop_hw; |
| 665 | 666 | ||
| 666 | return ret; | 667 | return ret; |
| 667 | 668 | ||
| 668 | err_no_mem: | ||
| 669 | for (i = 0; i < sd->hid_sensor_client_cnt; ++i) { | ||
| 670 | kfree(sd->hid_sensor_hub_client_devs[i].name); | ||
| 671 | kfree(sd->hid_sensor_hub_client_devs[i].platform_data); | ||
| 672 | } | ||
| 673 | kfree(sd->hid_sensor_hub_client_devs); | ||
| 674 | err_stop_hw: | 669 | err_stop_hw: |
| 675 | hid_hw_stop(hdev); | 670 | hid_hw_stop(hdev); |
| 676 | 671 | ||
| @@ -681,7 +676,6 @@ static void sensor_hub_remove(struct hid_device *hdev) | |||
| 681 | { | 676 | { |
| 682 | struct sensor_hub_data *data = hid_get_drvdata(hdev); | 677 | struct sensor_hub_data *data = hid_get_drvdata(hdev); |
| 683 | unsigned long flags; | 678 | unsigned long flags; |
| 684 | int i; | ||
| 685 | 679 | ||
| 686 | hid_dbg(hdev, " hardware removed\n"); | 680 | hid_dbg(hdev, " hardware removed\n"); |
| 687 | hid_hw_close(hdev); | 681 | hid_hw_close(hdev); |
| @@ -691,11 +685,6 @@ static void sensor_hub_remove(struct hid_device *hdev) | |||
| 691 | complete(&data->pending.ready); | 685 | complete(&data->pending.ready); |
| 692 | spin_unlock_irqrestore(&data->lock, flags); | 686 | spin_unlock_irqrestore(&data->lock, flags); |
| 693 | mfd_remove_devices(&hdev->dev); | 687 | mfd_remove_devices(&hdev->dev); |
| 694 | for (i = 0; i < data->hid_sensor_client_cnt; ++i) { | ||
| 695 | kfree(data->hid_sensor_hub_client_devs[i].name); | ||
| 696 | kfree(data->hid_sensor_hub_client_devs[i].platform_data); | ||
| 697 | } | ||
| 698 | kfree(data->hid_sensor_hub_client_devs); | ||
| 699 | hid_set_drvdata(hdev, NULL); | 688 | hid_set_drvdata(hdev, NULL); |
| 700 | mutex_destroy(&data->mutex); | 689 | mutex_destroy(&data->mutex); |
| 701 | } | 690 | } |
diff --git a/drivers/hid/hid-sunplus.c b/drivers/hid/hid-sunplus.c index 87fc91e1c8de..91072fa54663 100644 --- a/drivers/hid/hid-sunplus.c +++ b/drivers/hid/hid-sunplus.c | |||
| @@ -24,7 +24,7 @@ | |||
| 24 | static __u8 *sp_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 24 | static __u8 *sp_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 25 | unsigned int *rsize) | 25 | unsigned int *rsize) |
| 26 | { | 26 | { |
| 27 | if (*rsize >= 107 && rdesc[104] == 0x26 && rdesc[105] == 0x80 && | 27 | if (*rsize >= 112 && rdesc[104] == 0x26 && rdesc[105] == 0x80 && |
| 28 | rdesc[106] == 0x03) { | 28 | rdesc[106] == 0x03) { |
| 29 | hid_info(hdev, "fixing up Sunplus Wireless Desktop report descriptor\n"); | 29 | hid_info(hdev, "fixing up Sunplus Wireless Desktop report descriptor\n"); |
| 30 | rdesc[105] = rdesc[110] = 0x03; | 30 | rdesc[105] = rdesc[110] = 0x03; |
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 3e388ec31da8..f0db7eca9023 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c | |||
| @@ -1416,6 +1416,7 @@ static void wacom_remove(struct hid_device *hdev) | |||
| 1416 | kfree(wacom); | 1416 | kfree(wacom); |
| 1417 | } | 1417 | } |
| 1418 | 1418 | ||
| 1419 | #ifdef CONFIG_PM | ||
| 1419 | static int wacom_resume(struct hid_device *hdev) | 1420 | static int wacom_resume(struct hid_device *hdev) |
| 1420 | { | 1421 | { |
| 1421 | struct wacom *wacom = hid_get_drvdata(hdev); | 1422 | struct wacom *wacom = hid_get_drvdata(hdev); |
| @@ -1436,6 +1437,7 @@ static int wacom_reset_resume(struct hid_device *hdev) | |||
| 1436 | { | 1437 | { |
| 1437 | return wacom_resume(hdev); | 1438 | return wacom_resume(hdev); |
| 1438 | } | 1439 | } |
| 1440 | #endif /* CONFIG_PM */ | ||
| 1439 | 1441 | ||
| 1440 | static struct hid_driver wacom_driver = { | 1442 | static struct hid_driver wacom_driver = { |
| 1441 | .name = "wacom", | 1443 | .name = "wacom", |
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 3e3b680dc007..b51a402752c4 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig | |||
| @@ -23,17 +23,14 @@ config I2C | |||
| 23 | This I2C support can also be built as a module. If so, the module | 23 | This I2C support can also be built as a module. If so, the module |
| 24 | will be called i2c-core. | 24 | will be called i2c-core. |
| 25 | 25 | ||
| 26 | config I2C_ACPI | 26 | config ACPI_I2C_OPREGION |
| 27 | bool "I2C ACPI support" | 27 | bool "ACPI I2C Operation region support" |
| 28 | select I2C | 28 | depends on I2C=y && ACPI |
| 29 | depends on ACPI | ||
| 30 | default y | 29 | default y |
| 31 | help | 30 | help |
| 32 | Say Y here if you want to enable ACPI I2C support. This includes support | 31 | Say Y here if you want to enable ACPI I2C operation region support. |
| 33 | for automatic enumeration of I2C slave devices and support for ACPI I2C | 32 | Operation Regions allow firmware (BIOS) code to access I2C slave devices, |
| 34 | Operation Regions. Operation Regions allow firmware (BIOS) code to | 33 | such as smart batteries through an I2C host controller driver. |
| 35 | access I2C slave devices, such as smart batteries through an I2C host | ||
| 36 | controller driver. | ||
| 37 | 34 | ||
| 38 | if I2C | 35 | if I2C |
| 39 | 36 | ||
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index a1f590cbb435..e0228b228256 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | i2ccore-y := i2c-core.o | 5 | i2ccore-y := i2c-core.o |
| 6 | i2ccore-$(CONFIG_I2C_ACPI) += i2c-acpi.o | 6 | i2ccore-$(CONFIG_ACPI) += i2c-acpi.o |
| 7 | 7 | ||
| 8 | obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o | 8 | obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o |
| 9 | obj-$(CONFIG_I2C) += i2ccore.o | 9 | obj-$(CONFIG_I2C) += i2ccore.o |
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 2994690b26e9..10467a327749 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c | |||
| @@ -164,6 +164,7 @@ | |||
| 164 | 164 | ||
| 165 | /* Older devices have their ID defined in <linux/pci_ids.h> */ | 165 | /* Older devices have their ID defined in <linux/pci_ids.h> */ |
| 166 | #define PCI_DEVICE_ID_INTEL_BAYTRAIL_SMBUS 0x0f12 | 166 | #define PCI_DEVICE_ID_INTEL_BAYTRAIL_SMBUS 0x0f12 |
| 167 | #define PCI_DEVICE_ID_INTEL_BRASWELL_SMBUS 0x2292 | ||
| 167 | #define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22 | 168 | #define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22 |
| 168 | #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS 0x1d22 | 169 | #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS 0x1d22 |
| 169 | /* Patsburg also has three 'Integrated Device Function' SMBus controllers */ | 170 | /* Patsburg also has three 'Integrated Device Function' SMBus controllers */ |
| @@ -828,6 +829,7 @@ static const struct pci_device_id i801_ids[] = { | |||
| 828 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WILDCATPOINT_SMBUS) }, | 829 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WILDCATPOINT_SMBUS) }, |
| 829 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_SMBUS) }, | 830 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_SMBUS) }, |
| 830 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BAYTRAIL_SMBUS) }, | 831 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BAYTRAIL_SMBUS) }, |
| 832 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BRASWELL_SMBUS) }, | ||
| 831 | { 0, } | 833 | { 0, } |
| 832 | }; | 834 | }; |
| 833 | 835 | ||
diff --git a/drivers/i2c/i2c-acpi.c b/drivers/i2c/i2c-acpi.c index e8b61967334b..0dbc18c15c43 100644 --- a/drivers/i2c/i2c-acpi.c +++ b/drivers/i2c/i2c-acpi.c | |||
| @@ -126,6 +126,7 @@ void acpi_i2c_register_devices(struct i2c_adapter *adap) | |||
| 126 | dev_warn(&adap->dev, "failed to enumerate I2C slaves\n"); | 126 | dev_warn(&adap->dev, "failed to enumerate I2C slaves\n"); |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | #ifdef CONFIG_ACPI_I2C_OPREGION | ||
| 129 | static int acpi_gsb_i2c_read_bytes(struct i2c_client *client, | 130 | static int acpi_gsb_i2c_read_bytes(struct i2c_client *client, |
| 130 | u8 cmd, u8 *data, u8 data_len) | 131 | u8 cmd, u8 *data, u8 data_len) |
| 131 | { | 132 | { |
| @@ -360,3 +361,4 @@ void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter) | |||
| 360 | 361 | ||
| 361 | acpi_bus_detach_private_data(handle); | 362 | acpi_bus_detach_private_data(handle); |
| 362 | } | 363 | } |
| 364 | #endif | ||
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 4d140bbbe100..9b7ee7e427df 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c | |||
| @@ -89,6 +89,7 @@ struct idle_cpu { | |||
| 89 | * Indicate which enable bits to clear here. | 89 | * Indicate which enable bits to clear here. |
| 90 | */ | 90 | */ |
| 91 | unsigned long auto_demotion_disable_flags; | 91 | unsigned long auto_demotion_disable_flags; |
| 92 | bool byt_auto_demotion_disable_flag; | ||
| 92 | bool disable_promotion_to_c1e; | 93 | bool disable_promotion_to_c1e; |
| 93 | }; | 94 | }; |
| 94 | 95 | ||
| @@ -442,6 +443,66 @@ static struct cpuidle_state hsw_cstates[] = { | |||
| 442 | { | 443 | { |
| 443 | .enter = NULL } | 444 | .enter = NULL } |
| 444 | }; | 445 | }; |
| 446 | static struct cpuidle_state bdw_cstates[] = { | ||
| 447 | { | ||
| 448 | .name = "C1-BDW", | ||
| 449 | .desc = "MWAIT 0x00", | ||
| 450 | .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID, | ||
| 451 | .exit_latency = 2, | ||
| 452 | .target_residency = 2, | ||
| 453 | .enter = &intel_idle }, | ||
| 454 | { | ||
| 455 | .name = "C1E-BDW", | ||
| 456 | .desc = "MWAIT 0x01", | ||
| 457 | .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_TIME_VALID, | ||
| 458 | .exit_latency = 10, | ||
| 459 | .target_residency = 20, | ||
| 460 | .enter = &intel_idle }, | ||
| 461 | { | ||
| 462 | .name = "C3-BDW", | ||
| 463 | .desc = "MWAIT 0x10", | ||
| 464 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | ||
| 465 | .exit_latency = 40, | ||
| 466 | .target_residency = 100, | ||
| 467 | .enter = &intel_idle }, | ||
| 468 | { | ||
| 469 | .name = "C6-BDW", | ||
| 470 | .desc = "MWAIT 0x20", | ||
| 471 | .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | ||
| 472 | .exit_latency = 133, | ||
| 473 | .target_residency = 400, | ||
| 474 | .enter = &intel_idle }, | ||
| 475 | { | ||
| 476 | .name = "C7s-BDW", | ||
| 477 | .desc = "MWAIT 0x32", | ||
| 478 | .flags = MWAIT2flg(0x32) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | ||
| 479 | .exit_latency = 166, | ||
| 480 | .target_residency = 500, | ||
| 481 | .enter = &intel_idle }, | ||
| 482 | { | ||
| 483 | .name = "C8-BDW", | ||
| 484 | .desc = "MWAIT 0x40", | ||
| 485 | .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | ||
| 486 | .exit_latency = 300, | ||
| 487 | .target_residency = 900, | ||
| 488 | .enter = &intel_idle }, | ||
| 489 | { | ||
| 490 | .name = "C9-BDW", | ||
| 491 | .desc = "MWAIT 0x50", | ||
| 492 | .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | ||
| 493 | .exit_latency = 600, | ||
| 494 | .target_residency = 1800, | ||
| 495 | .enter = &intel_idle }, | ||
| 496 | { | ||
| 497 | .name = "C10-BDW", | ||
| 498 | .desc = "MWAIT 0x60", | ||
| 499 | .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | ||
| 500 | .exit_latency = 2600, | ||
| 501 | .target_residency = 7700, | ||
| 502 | .enter = &intel_idle }, | ||
| 503 | { | ||
| 504 | .enter = NULL } | ||
| 505 | }; | ||
| 445 | 506 | ||
| 446 | static struct cpuidle_state atom_cstates[] = { | 507 | static struct cpuidle_state atom_cstates[] = { |
| 447 | { | 508 | { |
| @@ -613,6 +674,7 @@ static const struct idle_cpu idle_cpu_snb = { | |||
| 613 | static const struct idle_cpu idle_cpu_byt = { | 674 | static const struct idle_cpu idle_cpu_byt = { |
| 614 | .state_table = byt_cstates, | 675 | .state_table = byt_cstates, |
| 615 | .disable_promotion_to_c1e = true, | 676 | .disable_promotion_to_c1e = true, |
| 677 | .byt_auto_demotion_disable_flag = true, | ||
| 616 | }; | 678 | }; |
| 617 | 679 | ||
| 618 | static const struct idle_cpu idle_cpu_ivb = { | 680 | static const struct idle_cpu idle_cpu_ivb = { |
| @@ -630,6 +692,11 @@ static const struct idle_cpu idle_cpu_hsw = { | |||
| 630 | .disable_promotion_to_c1e = true, | 692 | .disable_promotion_to_c1e = true, |
| 631 | }; | 693 | }; |
| 632 | 694 | ||
| 695 | static const struct idle_cpu idle_cpu_bdw = { | ||
| 696 | .state_table = bdw_cstates, | ||
| 697 | .disable_promotion_to_c1e = true, | ||
| 698 | }; | ||
| 699 | |||
| 633 | static const struct idle_cpu idle_cpu_avn = { | 700 | static const struct idle_cpu idle_cpu_avn = { |
| 634 | .state_table = avn_cstates, | 701 | .state_table = avn_cstates, |
| 635 | .disable_promotion_to_c1e = true, | 702 | .disable_promotion_to_c1e = true, |
| @@ -658,7 +725,10 @@ static const struct x86_cpu_id intel_idle_ids[] = { | |||
| 658 | ICPU(0x3f, idle_cpu_hsw), | 725 | ICPU(0x3f, idle_cpu_hsw), |
| 659 | ICPU(0x45, idle_cpu_hsw), | 726 | ICPU(0x45, idle_cpu_hsw), |
| 660 | ICPU(0x46, idle_cpu_hsw), | 727 | ICPU(0x46, idle_cpu_hsw), |
| 661 | ICPU(0x4D, idle_cpu_avn), | 728 | ICPU(0x4d, idle_cpu_avn), |
| 729 | ICPU(0x3d, idle_cpu_bdw), | ||
| 730 | ICPU(0x4f, idle_cpu_bdw), | ||
| 731 | ICPU(0x56, idle_cpu_bdw), | ||
| 662 | {} | 732 | {} |
| 663 | }; | 733 | }; |
| 664 | MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids); | 734 | MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids); |
| @@ -814,6 +884,11 @@ static int __init intel_idle_cpuidle_driver_init(void) | |||
| 814 | if (icpu->auto_demotion_disable_flags) | 884 | if (icpu->auto_demotion_disable_flags) |
| 815 | on_each_cpu(auto_demotion_disable, NULL, 1); | 885 | on_each_cpu(auto_demotion_disable, NULL, 1); |
| 816 | 886 | ||
| 887 | if (icpu->byt_auto_demotion_disable_flag) { | ||
| 888 | wrmsrl(MSR_CC6_DEMOTION_POLICY_CONFIG, 0); | ||
| 889 | wrmsrl(MSR_MC6_DEMOTION_POLICY_CONFIG, 0); | ||
| 890 | } | ||
| 891 | |||
| 817 | if (icpu->disable_promotion_to_c1e) /* each-cpu is redundant */ | 892 | if (icpu->disable_promotion_to_c1e) /* each-cpu is redundant */ |
| 818 | on_each_cpu(c1e_promotion_disable, NULL, 1); | 893 | on_each_cpu(c1e_promotion_disable, NULL, 1); |
| 819 | 894 | ||
diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c index d398f1321f14..c30204f2fa30 100644 --- a/drivers/input/input-mt.c +++ b/drivers/input/input-mt.c | |||
| @@ -237,6 +237,31 @@ void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count) | |||
| 237 | EXPORT_SYMBOL(input_mt_report_pointer_emulation); | 237 | EXPORT_SYMBOL(input_mt_report_pointer_emulation); |
| 238 | 238 | ||
| 239 | /** | 239 | /** |
| 240 | * input_mt_drop_unused() - Inactivate slots not seen in this frame | ||
| 241 | * @dev: input device with allocated MT slots | ||
| 242 | * | ||
| 243 | * Lift all slots not seen since the last call to this function. | ||
| 244 | */ | ||
| 245 | void input_mt_drop_unused(struct input_dev *dev) | ||
| 246 | { | ||
| 247 | struct input_mt *mt = dev->mt; | ||
| 248 | int i; | ||
| 249 | |||
| 250 | if (!mt) | ||
| 251 | return; | ||
| 252 | |||
| 253 | for (i = 0; i < mt->num_slots; i++) { | ||
| 254 | if (!input_mt_is_used(mt, &mt->slots[i])) { | ||
| 255 | input_mt_slot(dev, i); | ||
| 256 | input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1); | ||
| 257 | } | ||
| 258 | } | ||
| 259 | |||
| 260 | mt->frame++; | ||
| 261 | } | ||
| 262 | EXPORT_SYMBOL(input_mt_drop_unused); | ||
| 263 | |||
| 264 | /** | ||
| 240 | * input_mt_sync_frame() - synchronize mt frame | 265 | * input_mt_sync_frame() - synchronize mt frame |
| 241 | * @dev: input device with allocated MT slots | 266 | * @dev: input device with allocated MT slots |
| 242 | * | 267 | * |
| @@ -247,27 +272,18 @@ EXPORT_SYMBOL(input_mt_report_pointer_emulation); | |||
| 247 | void input_mt_sync_frame(struct input_dev *dev) | 272 | void input_mt_sync_frame(struct input_dev *dev) |
| 248 | { | 273 | { |
| 249 | struct input_mt *mt = dev->mt; | 274 | struct input_mt *mt = dev->mt; |
| 250 | struct input_mt_slot *s; | ||
| 251 | bool use_count = false; | 275 | bool use_count = false; |
| 252 | 276 | ||
| 253 | if (!mt) | 277 | if (!mt) |
| 254 | return; | 278 | return; |
| 255 | 279 | ||
| 256 | if (mt->flags & INPUT_MT_DROP_UNUSED) { | 280 | if (mt->flags & INPUT_MT_DROP_UNUSED) |
| 257 | for (s = mt->slots; s != mt->slots + mt->num_slots; s++) { | 281 | input_mt_drop_unused(dev); |
| 258 | if (input_mt_is_used(mt, s)) | ||
| 259 | continue; | ||
| 260 | input_mt_slot(dev, s - mt->slots); | ||
| 261 | input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1); | ||
| 262 | } | ||
| 263 | } | ||
| 264 | 282 | ||
| 265 | if ((mt->flags & INPUT_MT_POINTER) && !(mt->flags & INPUT_MT_SEMI_MT)) | 283 | if ((mt->flags & INPUT_MT_POINTER) && !(mt->flags & INPUT_MT_SEMI_MT)) |
| 266 | use_count = true; | 284 | use_count = true; |
| 267 | 285 | ||
| 268 | input_mt_report_pointer_emulation(dev, use_count); | 286 | input_mt_report_pointer_emulation(dev, use_count); |
| 269 | |||
| 270 | mt->frame++; | ||
| 271 | } | 287 | } |
| 272 | EXPORT_SYMBOL(input_mt_sync_frame); | 288 | EXPORT_SYMBOL(input_mt_sync_frame); |
| 273 | 289 | ||
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index 9135606c8649..ab0fdcd36e18 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c | |||
| @@ -158,7 +158,7 @@ static unsigned int get_time_pit(void) | |||
| 158 | #define GET_TIME(x) rdtscl(x) | 158 | #define GET_TIME(x) rdtscl(x) |
| 159 | #define DELTA(x,y) ((y)-(x)) | 159 | #define DELTA(x,y) ((y)-(x)) |
| 160 | #define TIME_NAME "TSC" | 160 | #define TIME_NAME "TSC" |
| 161 | #elif defined(__alpha__) || defined(CONFIG_MN10300) || defined(CONFIG_ARM) || defined(CONFIG_TILE) | 161 | #elif defined(__alpha__) || defined(CONFIG_MN10300) || defined(CONFIG_ARM) || defined(CONFIG_ARM64) || defined(CONFIG_TILE) |
| 162 | #define GET_TIME(x) do { x = get_cycles(); } while (0) | 162 | #define GET_TIME(x) do { x = get_cycles(); } while (0) |
| 163 | #define DELTA(x,y) ((y)-(x)) | 163 | #define DELTA(x,y) ((y)-(x)) |
| 164 | #define TIME_NAME "get_cycles" | 164 | #define TIME_NAME "get_cycles" |
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 603fe0dd3682..177602cf7079 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c | |||
| @@ -95,7 +95,8 @@ | |||
| 95 | #define XTYPE_XBOX 0 | 95 | #define XTYPE_XBOX 0 |
| 96 | #define XTYPE_XBOX360 1 | 96 | #define XTYPE_XBOX360 1 |
| 97 | #define XTYPE_XBOX360W 2 | 97 | #define XTYPE_XBOX360W 2 |
| 98 | #define XTYPE_UNKNOWN 3 | 98 | #define XTYPE_XBOXONE 3 |
| 99 | #define XTYPE_UNKNOWN 4 | ||
| 99 | 100 | ||
| 100 | static bool dpad_to_buttons; | 101 | static bool dpad_to_buttons; |
| 101 | module_param(dpad_to_buttons, bool, S_IRUGO); | 102 | module_param(dpad_to_buttons, bool, S_IRUGO); |
| @@ -121,6 +122,7 @@ static const struct xpad_device { | |||
| 121 | { 0x045e, 0x0287, "Microsoft Xbox Controller S", 0, XTYPE_XBOX }, | 122 | { 0x045e, 0x0287, "Microsoft Xbox Controller S", 0, XTYPE_XBOX }, |
| 122 | { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", 0, XTYPE_XBOX }, | 123 | { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", 0, XTYPE_XBOX }, |
| 123 | { 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 }, | 124 | { 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 }, |
| 125 | { 0x045e, 0x02d1, "Microsoft X-Box One pad", 0, XTYPE_XBOXONE }, | ||
| 124 | { 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, | 126 | { 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, |
| 125 | { 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, | 127 | { 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, |
| 126 | { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX }, | 128 | { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX }, |
| @@ -231,10 +233,12 @@ static const signed short xpad_abs_triggers[] = { | |||
| 231 | -1 | 233 | -1 |
| 232 | }; | 234 | }; |
| 233 | 235 | ||
| 234 | /* Xbox 360 has a vendor-specific class, so we cannot match it with only | 236 | /* |
| 237 | * Xbox 360 has a vendor-specific class, so we cannot match it with only | ||
| 235 | * USB_INTERFACE_INFO (also specifically refused by USB subsystem), so we | 238 | * USB_INTERFACE_INFO (also specifically refused by USB subsystem), so we |
| 236 | * match against vendor id as well. Wired Xbox 360 devices have protocol 1, | 239 | * match against vendor id as well. Wired Xbox 360 devices have protocol 1, |
| 237 | * wireless controllers have protocol 129. */ | 240 | * wireless controllers have protocol 129. |
| 241 | */ | ||
| 238 | #define XPAD_XBOX360_VENDOR_PROTOCOL(vend,pr) \ | 242 | #define XPAD_XBOX360_VENDOR_PROTOCOL(vend,pr) \ |
| 239 | .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, \ | 243 | .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, \ |
| 240 | .idVendor = (vend), \ | 244 | .idVendor = (vend), \ |
| @@ -245,9 +249,20 @@ static const signed short xpad_abs_triggers[] = { | |||
| 245 | { XPAD_XBOX360_VENDOR_PROTOCOL(vend,1) }, \ | 249 | { XPAD_XBOX360_VENDOR_PROTOCOL(vend,1) }, \ |
| 246 | { XPAD_XBOX360_VENDOR_PROTOCOL(vend,129) } | 250 | { XPAD_XBOX360_VENDOR_PROTOCOL(vend,129) } |
| 247 | 251 | ||
| 252 | /* The Xbox One controller uses subclass 71 and protocol 208. */ | ||
| 253 | #define XPAD_XBOXONE_VENDOR_PROTOCOL(vend, pr) \ | ||
| 254 | .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, \ | ||
| 255 | .idVendor = (vend), \ | ||
| 256 | .bInterfaceClass = USB_CLASS_VENDOR_SPEC, \ | ||
| 257 | .bInterfaceSubClass = 71, \ | ||
| 258 | .bInterfaceProtocol = (pr) | ||
| 259 | #define XPAD_XBOXONE_VENDOR(vend) \ | ||
| 260 | { XPAD_XBOXONE_VENDOR_PROTOCOL(vend, 208) } | ||
| 261 | |||
| 248 | static struct usb_device_id xpad_table[] = { | 262 | static struct usb_device_id xpad_table[] = { |
| 249 | { USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */ | 263 | { USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */ |
| 250 | XPAD_XBOX360_VENDOR(0x045e), /* Microsoft X-Box 360 controllers */ | 264 | XPAD_XBOX360_VENDOR(0x045e), /* Microsoft X-Box 360 controllers */ |
| 265 | XPAD_XBOXONE_VENDOR(0x045e), /* Microsoft X-Box One controllers */ | ||
| 251 | XPAD_XBOX360_VENDOR(0x046d), /* Logitech X-Box 360 style controllers */ | 266 | XPAD_XBOX360_VENDOR(0x046d), /* Logitech X-Box 360 style controllers */ |
| 252 | XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */ | 267 | XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */ |
| 253 | { USB_DEVICE(0x0738, 0x4540) }, /* Mad Catz Beat Pad */ | 268 | { USB_DEVICE(0x0738, 0x4540) }, /* Mad Catz Beat Pad */ |
| @@ -278,12 +293,10 @@ struct usb_xpad { | |||
| 278 | struct urb *bulk_out; | 293 | struct urb *bulk_out; |
| 279 | unsigned char *bdata; | 294 | unsigned char *bdata; |
| 280 | 295 | ||
| 281 | #if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS) | ||
| 282 | struct urb *irq_out; /* urb for interrupt out report */ | 296 | struct urb *irq_out; /* urb for interrupt out report */ |
| 283 | unsigned char *odata; /* output data */ | 297 | unsigned char *odata; /* output data */ |
| 284 | dma_addr_t odata_dma; | 298 | dma_addr_t odata_dma; |
| 285 | struct mutex odata_mutex; | 299 | struct mutex odata_mutex; |
| 286 | #endif | ||
| 287 | 300 | ||
| 288 | #if defined(CONFIG_JOYSTICK_XPAD_LEDS) | 301 | #if defined(CONFIG_JOYSTICK_XPAD_LEDS) |
| 289 | struct xpad_led *led; | 302 | struct xpad_led *led; |
| @@ -470,6 +483,105 @@ static void xpad360w_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned cha | |||
| 470 | xpad360_process_packet(xpad, cmd, &data[4]); | 483 | xpad360_process_packet(xpad, cmd, &data[4]); |
| 471 | } | 484 | } |
| 472 | 485 | ||
| 486 | /* | ||
| 487 | * xpadone_process_buttons | ||
| 488 | * | ||
| 489 | * Process a button update packet from an Xbox one controller. | ||
| 490 | */ | ||
| 491 | static void xpadone_process_buttons(struct usb_xpad *xpad, | ||
| 492 | struct input_dev *dev, | ||
| 493 | unsigned char *data) | ||
| 494 | { | ||
| 495 | /* menu/view buttons */ | ||
| 496 | input_report_key(dev, BTN_START, data[4] & 0x04); | ||
| 497 | input_report_key(dev, BTN_SELECT, data[4] & 0x08); | ||
| 498 | |||
| 499 | /* buttons A,B,X,Y */ | ||
| 500 | input_report_key(dev, BTN_A, data[4] & 0x10); | ||
| 501 | input_report_key(dev, BTN_B, data[4] & 0x20); | ||
| 502 | input_report_key(dev, BTN_X, data[4] & 0x40); | ||
| 503 | input_report_key(dev, BTN_Y, data[4] & 0x80); | ||
| 504 | |||
| 505 | /* digital pad */ | ||
| 506 | if (xpad->mapping & MAP_DPAD_TO_BUTTONS) { | ||
| 507 | /* dpad as buttons (left, right, up, down) */ | ||
| 508 | input_report_key(dev, BTN_TRIGGER_HAPPY1, data[5] & 0x04); | ||
| 509 | input_report_key(dev, BTN_TRIGGER_HAPPY2, data[5] & 0x08); | ||
| 510 | input_report_key(dev, BTN_TRIGGER_HAPPY3, data[5] & 0x01); | ||
| 511 | input_report_key(dev, BTN_TRIGGER_HAPPY4, data[5] & 0x02); | ||
| 512 | } else { | ||
| 513 | input_report_abs(dev, ABS_HAT0X, | ||
| 514 | !!(data[5] & 0x08) - !!(data[5] & 0x04)); | ||
| 515 | input_report_abs(dev, ABS_HAT0Y, | ||
| 516 | !!(data[5] & 0x02) - !!(data[5] & 0x01)); | ||
| 517 | } | ||
| 518 | |||
| 519 | /* TL/TR */ | ||
| 520 | input_report_key(dev, BTN_TL, data[5] & 0x10); | ||
| 521 | input_report_key(dev, BTN_TR, data[5] & 0x20); | ||
| 522 | |||
| 523 | /* stick press left/right */ | ||
| 524 | input_report_key(dev, BTN_THUMBL, data[5] & 0x40); | ||
| 525 | input_report_key(dev, BTN_THUMBR, data[5] & 0x80); | ||
| 526 | |||
| 527 | if (!(xpad->mapping & MAP_STICKS_TO_NULL)) { | ||
| 528 | /* left stick */ | ||
| 529 | input_report_abs(dev, ABS_X, | ||
| 530 | (__s16) le16_to_cpup((__le16 *)(data + 10))); | ||
| 531 | input_report_abs(dev, ABS_Y, | ||
| 532 | ~(__s16) le16_to_cpup((__le16 *)(data + 12))); | ||
| 533 | |||
| 534 | /* right stick */ | ||
| 535 | input_report_abs(dev, ABS_RX, | ||
| 536 | (__s16) le16_to_cpup((__le16 *)(data + 14))); | ||
| 537 | input_report_abs(dev, ABS_RY, | ||
| 538 | ~(__s16) le16_to_cpup((__le16 *)(data + 16))); | ||
| 539 | } | ||
| 540 | |||
| 541 | /* triggers left/right */ | ||
| 542 | if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) { | ||
| 543 | input_report_key(dev, BTN_TL2, | ||
| 544 | (__u16) le16_to_cpup((__le16 *)(data + 6))); | ||
| 545 | input_report_key(dev, BTN_TR2, | ||
| 546 | (__u16) le16_to_cpup((__le16 *)(data + 8))); | ||
| 547 | } else { | ||
| 548 | input_report_abs(dev, ABS_Z, | ||
| 549 | (__u16) le16_to_cpup((__le16 *)(data + 6))); | ||
| 550 | input_report_abs(dev, ABS_RZ, | ||
| 551 | (__u16) le16_to_cpup((__le16 *)(data + 8))); | ||
| 552 | } | ||
| 553 | |||
| 554 | input_sync(dev); | ||
| 555 | } | ||
| 556 | |||
| 557 | /* | ||
| 558 | * xpadone_process_packet | ||
| 559 | * | ||
| 560 | * Completes a request by converting the data into events for the | ||
| 561 | * input subsystem. This version is for the Xbox One controller. | ||
| 562 | * | ||
| 563 | * The report format was gleaned from | ||
| 564 | * https://github.com/kylelemons/xbox/blob/master/xbox.go | ||
| 565 | */ | ||
| 566 | |||
| 567 | static void xpadone_process_packet(struct usb_xpad *xpad, | ||
| 568 | u16 cmd, unsigned char *data) | ||
| 569 | { | ||
| 570 | struct input_dev *dev = xpad->dev; | ||
| 571 | |||
| 572 | switch (data[0]) { | ||
| 573 | case 0x20: | ||
| 574 | xpadone_process_buttons(xpad, dev, data); | ||
| 575 | break; | ||
| 576 | |||
| 577 | case 0x07: | ||
| 578 | /* the xbox button has its own special report */ | ||
| 579 | input_report_key(dev, BTN_MODE, data[4] & 0x01); | ||
| 580 | input_sync(dev); | ||
| 581 | break; | ||
| 582 | } | ||
| 583 | } | ||
| 584 | |||
| 473 | static void xpad_irq_in(struct urb *urb) | 585 | static void xpad_irq_in(struct urb *urb) |
| 474 | { | 586 | { |
| 475 | struct usb_xpad *xpad = urb->context; | 587 | struct usb_xpad *xpad = urb->context; |
| @@ -502,6 +614,9 @@ static void xpad_irq_in(struct urb *urb) | |||
| 502 | case XTYPE_XBOX360W: | 614 | case XTYPE_XBOX360W: |
| 503 | xpad360w_process_packet(xpad, 0, xpad->idata); | 615 | xpad360w_process_packet(xpad, 0, xpad->idata); |
| 504 | break; | 616 | break; |
| 617 | case XTYPE_XBOXONE: | ||
| 618 | xpadone_process_packet(xpad, 0, xpad->idata); | ||
| 619 | break; | ||
| 505 | default: | 620 | default: |
| 506 | xpad_process_packet(xpad, 0, xpad->idata); | 621 | xpad_process_packet(xpad, 0, xpad->idata); |
| 507 | } | 622 | } |
| @@ -535,7 +650,6 @@ static void xpad_bulk_out(struct urb *urb) | |||
| 535 | } | 650 | } |
| 536 | } | 651 | } |
| 537 | 652 | ||
| 538 | #if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS) | ||
| 539 | static void xpad_irq_out(struct urb *urb) | 653 | static void xpad_irq_out(struct urb *urb) |
| 540 | { | 654 | { |
| 541 | struct usb_xpad *xpad = urb->context; | 655 | struct usb_xpad *xpad = urb->context; |
| @@ -573,6 +687,7 @@ exit: | |||
| 573 | static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) | 687 | static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) |
| 574 | { | 688 | { |
| 575 | struct usb_endpoint_descriptor *ep_irq_out; | 689 | struct usb_endpoint_descriptor *ep_irq_out; |
| 690 | int ep_irq_out_idx; | ||
| 576 | int error; | 691 | int error; |
| 577 | 692 | ||
| 578 | if (xpad->xtype == XTYPE_UNKNOWN) | 693 | if (xpad->xtype == XTYPE_UNKNOWN) |
| @@ -593,7 +708,10 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) | |||
| 593 | goto fail2; | 708 | goto fail2; |
| 594 | } | 709 | } |
| 595 | 710 | ||
| 596 | ep_irq_out = &intf->cur_altsetting->endpoint[1].desc; | 711 | /* Xbox One controller has in/out endpoints swapped. */ |
| 712 | ep_irq_out_idx = xpad->xtype == XTYPE_XBOXONE ? 0 : 1; | ||
| 713 | ep_irq_out = &intf->cur_altsetting->endpoint[ep_irq_out_idx].desc; | ||
| 714 | |||
| 597 | usb_fill_int_urb(xpad->irq_out, xpad->udev, | 715 | usb_fill_int_urb(xpad->irq_out, xpad->udev, |
| 598 | usb_sndintpipe(xpad->udev, ep_irq_out->bEndpointAddress), | 716 | usb_sndintpipe(xpad->udev, ep_irq_out->bEndpointAddress), |
| 599 | xpad->odata, XPAD_PKT_LEN, | 717 | xpad->odata, XPAD_PKT_LEN, |
| @@ -621,11 +739,6 @@ static void xpad_deinit_output(struct usb_xpad *xpad) | |||
| 621 | xpad->odata, xpad->odata_dma); | 739 | xpad->odata, xpad->odata_dma); |
| 622 | } | 740 | } |
| 623 | } | 741 | } |
| 624 | #else | ||
| 625 | static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) { return 0; } | ||
| 626 | static void xpad_deinit_output(struct usb_xpad *xpad) {} | ||
| 627 | static void xpad_stop_output(struct usb_xpad *xpad) {} | ||
| 628 | #endif | ||
| 629 | 742 | ||
| 630 | #ifdef CONFIG_JOYSTICK_XPAD_FF | 743 | #ifdef CONFIG_JOYSTICK_XPAD_FF |
| 631 | static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect) | 744 | static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect) |
| @@ -692,7 +805,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect | |||
| 692 | 805 | ||
| 693 | static int xpad_init_ff(struct usb_xpad *xpad) | 806 | static int xpad_init_ff(struct usb_xpad *xpad) |
| 694 | { | 807 | { |
| 695 | if (xpad->xtype == XTYPE_UNKNOWN) | 808 | if (xpad->xtype == XTYPE_UNKNOWN || xpad->xtype == XTYPE_XBOXONE) |
| 696 | return 0; | 809 | return 0; |
| 697 | 810 | ||
| 698 | input_set_capability(xpad->dev, EV_FF, FF_RUMBLE); | 811 | input_set_capability(xpad->dev, EV_FF, FF_RUMBLE); |
| @@ -801,6 +914,14 @@ static int xpad_open(struct input_dev *dev) | |||
| 801 | if (usb_submit_urb(xpad->irq_in, GFP_KERNEL)) | 914 | if (usb_submit_urb(xpad->irq_in, GFP_KERNEL)) |
| 802 | return -EIO; | 915 | return -EIO; |
| 803 | 916 | ||
| 917 | if (xpad->xtype == XTYPE_XBOXONE) { | ||
| 918 | /* Xbox one controller needs to be initialized. */ | ||
| 919 | xpad->odata[0] = 0x05; | ||
| 920 | xpad->odata[1] = 0x20; | ||
| 921 | xpad->irq_out->transfer_buffer_length = 2; | ||
| 922 | return usb_submit_urb(xpad->irq_out, GFP_KERNEL); | ||
| 923 | } | ||
| 924 | |||
| 804 | return 0; | 925 | return 0; |
| 805 | } | 926 | } |
| 806 | 927 | ||
| @@ -816,6 +937,7 @@ static void xpad_close(struct input_dev *dev) | |||
| 816 | 937 | ||
| 817 | static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs) | 938 | static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs) |
| 818 | { | 939 | { |
| 940 | struct usb_xpad *xpad = input_get_drvdata(input_dev); | ||
| 819 | set_bit(abs, input_dev->absbit); | 941 | set_bit(abs, input_dev->absbit); |
| 820 | 942 | ||
| 821 | switch (abs) { | 943 | switch (abs) { |
| @@ -827,7 +949,10 @@ static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs) | |||
| 827 | break; | 949 | break; |
| 828 | case ABS_Z: | 950 | case ABS_Z: |
| 829 | case ABS_RZ: /* the triggers (if mapped to axes) */ | 951 | case ABS_RZ: /* the triggers (if mapped to axes) */ |
| 830 | input_set_abs_params(input_dev, abs, 0, 255, 0, 0); | 952 | if (xpad->xtype == XTYPE_XBOXONE) |
| 953 | input_set_abs_params(input_dev, abs, 0, 1023, 0, 0); | ||
| 954 | else | ||
| 955 | input_set_abs_params(input_dev, abs, 0, 255, 0, 0); | ||
| 831 | break; | 956 | break; |
| 832 | case ABS_HAT0X: | 957 | case ABS_HAT0X: |
| 833 | case ABS_HAT0Y: /* the d-pad (only if dpad is mapped to axes */ | 958 | case ABS_HAT0Y: /* the d-pad (only if dpad is mapped to axes */ |
| @@ -842,6 +967,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
| 842 | struct usb_xpad *xpad; | 967 | struct usb_xpad *xpad; |
| 843 | struct input_dev *input_dev; | 968 | struct input_dev *input_dev; |
| 844 | struct usb_endpoint_descriptor *ep_irq_in; | 969 | struct usb_endpoint_descriptor *ep_irq_in; |
| 970 | int ep_irq_in_idx; | ||
| 845 | int i, error; | 971 | int i, error; |
| 846 | 972 | ||
| 847 | for (i = 0; xpad_device[i].idVendor; i++) { | 973 | for (i = 0; xpad_device[i].idVendor; i++) { |
| @@ -850,6 +976,16 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
| 850 | break; | 976 | break; |
| 851 | } | 977 | } |
| 852 | 978 | ||
| 979 | if (xpad_device[i].xtype == XTYPE_XBOXONE && | ||
| 980 | intf->cur_altsetting->desc.bInterfaceNumber != 0) { | ||
| 981 | /* | ||
| 982 | * The Xbox One controller lists three interfaces all with the | ||
| 983 | * same interface class, subclass and protocol. Differentiate by | ||
| 984 | * interface number. | ||
| 985 | */ | ||
| 986 | return -ENODEV; | ||
| 987 | } | ||
| 988 | |||
| 853 | xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL); | 989 | xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL); |
| 854 | input_dev = input_allocate_device(); | 990 | input_dev = input_allocate_device(); |
| 855 | if (!xpad || !input_dev) { | 991 | if (!xpad || !input_dev) { |
| @@ -920,7 +1056,8 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
| 920 | __set_bit(xpad_common_btn[i], input_dev->keybit); | 1056 | __set_bit(xpad_common_btn[i], input_dev->keybit); |
| 921 | 1057 | ||
| 922 | /* set up model-specific ones */ | 1058 | /* set up model-specific ones */ |
| 923 | if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX360W) { | 1059 | if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX360W || |
| 1060 | xpad->xtype == XTYPE_XBOXONE) { | ||
| 924 | for (i = 0; xpad360_btn[i] >= 0; i++) | 1061 | for (i = 0; xpad360_btn[i] >= 0; i++) |
| 925 | __set_bit(xpad360_btn[i], input_dev->keybit); | 1062 | __set_bit(xpad360_btn[i], input_dev->keybit); |
| 926 | } else { | 1063 | } else { |
| @@ -933,7 +1070,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
| 933 | __set_bit(xpad_btn_pad[i], input_dev->keybit); | 1070 | __set_bit(xpad_btn_pad[i], input_dev->keybit); |
| 934 | } else { | 1071 | } else { |
| 935 | for (i = 0; xpad_abs_pad[i] >= 0; i++) | 1072 | for (i = 0; xpad_abs_pad[i] >= 0; i++) |
| 936 | xpad_set_up_abs(input_dev, xpad_abs_pad[i]); | 1073 | xpad_set_up_abs(input_dev, xpad_abs_pad[i]); |
| 937 | } | 1074 | } |
| 938 | 1075 | ||
| 939 | if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) { | 1076 | if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) { |
| @@ -956,7 +1093,10 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
| 956 | if (error) | 1093 | if (error) |
| 957 | goto fail5; | 1094 | goto fail5; |
| 958 | 1095 | ||
| 959 | ep_irq_in = &intf->cur_altsetting->endpoint[0].desc; | 1096 | /* Xbox One controller has in/out endpoints swapped. */ |
| 1097 | ep_irq_in_idx = xpad->xtype == XTYPE_XBOXONE ? 1 : 0; | ||
| 1098 | ep_irq_in = &intf->cur_altsetting->endpoint[ep_irq_in_idx].desc; | ||
| 1099 | |||
| 960 | usb_fill_int_urb(xpad->irq_in, udev, | 1100 | usb_fill_int_urb(xpad->irq_in, udev, |
| 961 | usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), | 1101 | usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), |
| 962 | xpad->idata, XPAD_PKT_LEN, xpad_irq_in, | 1102 | xpad->idata, XPAD_PKT_LEN, xpad_irq_in, |
diff --git a/drivers/input/keyboard/cap1106.c b/drivers/input/keyboard/cap1106.c index f7d7a0d4ab4e..180b184ab90f 100644 --- a/drivers/input/keyboard/cap1106.c +++ b/drivers/input/keyboard/cap1106.c | |||
| @@ -64,7 +64,7 @@ struct cap1106_priv { | |||
| 64 | struct input_dev *idev; | 64 | struct input_dev *idev; |
| 65 | 65 | ||
| 66 | /* config */ | 66 | /* config */ |
| 67 | unsigned int keycodes[CAP1106_NUM_CHN]; | 67 | unsigned short keycodes[CAP1106_NUM_CHN]; |
| 68 | }; | 68 | }; |
| 69 | 69 | ||
| 70 | static const struct reg_default cap1106_reg_defaults[] = { | 70 | static const struct reg_default cap1106_reg_defaults[] = { |
| @@ -272,6 +272,12 @@ static int cap1106_i2c_probe(struct i2c_client *i2c_client, | |||
| 272 | for (i = 0; i < CAP1106_NUM_CHN; i++) | 272 | for (i = 0; i < CAP1106_NUM_CHN; i++) |
| 273 | __set_bit(priv->keycodes[i], priv->idev->keybit); | 273 | __set_bit(priv->keycodes[i], priv->idev->keybit); |
| 274 | 274 | ||
| 275 | __clear_bit(KEY_RESERVED, priv->idev->keybit); | ||
| 276 | |||
| 277 | priv->idev->keycode = priv->keycodes; | ||
| 278 | priv->idev->keycodesize = sizeof(priv->keycodes[0]); | ||
| 279 | priv->idev->keycodemax = ARRAY_SIZE(priv->keycodes); | ||
| 280 | |||
| 275 | priv->idev->id.vendor = CAP1106_MANUFACTURER_ID; | 281 | priv->idev->id.vendor = CAP1106_MANUFACTURER_ID; |
| 276 | priv->idev->id.product = CAP1106_PRODUCT_ID; | 282 | priv->idev->id.product = CAP1106_PRODUCT_ID; |
| 277 | priv->idev->id.version = rev; | 283 | priv->idev->id.version = rev; |
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index ef9e0b8a9aa7..e8573c68f77e 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
| @@ -117,6 +117,9 @@ void synaptics_reset(struct psmouse *psmouse) | |||
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | #ifdef CONFIG_MOUSE_PS2_SYNAPTICS | 119 | #ifdef CONFIG_MOUSE_PS2_SYNAPTICS |
| 120 | |||
| 121 | static bool cr48_profile_sensor; | ||
| 122 | |||
| 120 | struct min_max_quirk { | 123 | struct min_max_quirk { |
| 121 | const char * const *pnp_ids; | 124 | const char * const *pnp_ids; |
| 122 | int x_min, x_max, y_min, y_max; | 125 | int x_min, x_max, y_min, y_max; |
| @@ -1152,6 +1155,42 @@ static void synaptics_image_sensor_process(struct psmouse *psmouse, | |||
| 1152 | priv->agm_pending = false; | 1155 | priv->agm_pending = false; |
| 1153 | } | 1156 | } |
| 1154 | 1157 | ||
| 1158 | static void synaptics_profile_sensor_process(struct psmouse *psmouse, | ||
| 1159 | struct synaptics_hw_state *sgm, | ||
| 1160 | int num_fingers) | ||
| 1161 | { | ||
| 1162 | struct input_dev *dev = psmouse->dev; | ||
| 1163 | struct synaptics_data *priv = psmouse->private; | ||
| 1164 | struct synaptics_hw_state *hw[2] = { sgm, &priv->agm }; | ||
| 1165 | struct input_mt_pos pos[2]; | ||
| 1166 | int slot[2], nsemi, i; | ||
| 1167 | |||
| 1168 | nsemi = clamp_val(num_fingers, 0, 2); | ||
| 1169 | |||
| 1170 | for (i = 0; i < nsemi; i++) { | ||
| 1171 | pos[i].x = hw[i]->x; | ||
| 1172 | pos[i].y = synaptics_invert_y(hw[i]->y); | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | input_mt_assign_slots(dev, slot, pos, nsemi); | ||
| 1176 | |||
| 1177 | for (i = 0; i < nsemi; i++) { | ||
| 1178 | input_mt_slot(dev, slot[i]); | ||
| 1179 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, true); | ||
| 1180 | input_report_abs(dev, ABS_MT_POSITION_X, pos[i].x); | ||
| 1181 | input_report_abs(dev, ABS_MT_POSITION_Y, pos[i].y); | ||
| 1182 | input_report_abs(dev, ABS_MT_PRESSURE, hw[i]->z); | ||
| 1183 | } | ||
| 1184 | |||
| 1185 | input_mt_drop_unused(dev); | ||
| 1186 | input_mt_report_pointer_emulation(dev, false); | ||
| 1187 | input_mt_report_finger_count(dev, num_fingers); | ||
| 1188 | |||
| 1189 | synaptics_report_buttons(psmouse, sgm); | ||
| 1190 | |||
| 1191 | input_sync(dev); | ||
| 1192 | } | ||
| 1193 | |||
| 1155 | /* | 1194 | /* |
| 1156 | * called for each full received packet from the touchpad | 1195 | * called for each full received packet from the touchpad |
| 1157 | */ | 1196 | */ |
| @@ -1215,6 +1254,11 @@ static void synaptics_process_packet(struct psmouse *psmouse) | |||
| 1215 | finger_width = 0; | 1254 | finger_width = 0; |
| 1216 | } | 1255 | } |
| 1217 | 1256 | ||
| 1257 | if (cr48_profile_sensor) { | ||
| 1258 | synaptics_profile_sensor_process(psmouse, &hw, num_fingers); | ||
| 1259 | return; | ||
| 1260 | } | ||
| 1261 | |||
| 1218 | if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) | 1262 | if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) |
| 1219 | synaptics_report_semi_mt_data(dev, &hw, &priv->agm, | 1263 | synaptics_report_semi_mt_data(dev, &hw, &priv->agm, |
| 1220 | num_fingers); | 1264 | num_fingers); |
| @@ -1360,6 +1404,9 @@ static void set_input_params(struct psmouse *psmouse, | |||
| 1360 | set_abs_position_params(dev, priv, ABS_X, ABS_Y); | 1404 | set_abs_position_params(dev, priv, ABS_X, ABS_Y); |
| 1361 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); | 1405 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); |
| 1362 | 1406 | ||
| 1407 | if (cr48_profile_sensor) | ||
| 1408 | input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0); | ||
| 1409 | |||
| 1363 | if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) { | 1410 | if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) { |
| 1364 | set_abs_position_params(dev, priv, ABS_MT_POSITION_X, | 1411 | set_abs_position_params(dev, priv, ABS_MT_POSITION_X, |
| 1365 | ABS_MT_POSITION_Y); | 1412 | ABS_MT_POSITION_Y); |
| @@ -1371,11 +1418,16 @@ static void set_input_params(struct psmouse *psmouse, | |||
| 1371 | __set_bit(BTN_TOOL_QUADTAP, dev->keybit); | 1418 | __set_bit(BTN_TOOL_QUADTAP, dev->keybit); |
| 1372 | __set_bit(BTN_TOOL_QUINTTAP, dev->keybit); | 1419 | __set_bit(BTN_TOOL_QUINTTAP, dev->keybit); |
| 1373 | } else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) { | 1420 | } else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) { |
| 1374 | /* Non-image sensors with AGM use semi-mt */ | ||
| 1375 | __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); | ||
| 1376 | input_mt_init_slots(dev, 2, 0); | ||
| 1377 | set_abs_position_params(dev, priv, ABS_MT_POSITION_X, | 1421 | set_abs_position_params(dev, priv, ABS_MT_POSITION_X, |
| 1378 | ABS_MT_POSITION_Y); | 1422 | ABS_MT_POSITION_Y); |
| 1423 | /* | ||
| 1424 | * Profile sensor in CR-48 tracks contacts reasonably well, | ||
| 1425 | * other non-image sensors with AGM use semi-mt. | ||
| 1426 | */ | ||
| 1427 | input_mt_init_slots(dev, 2, | ||
| 1428 | INPUT_MT_POINTER | | ||
| 1429 | (cr48_profile_sensor ? | ||
| 1430 | INPUT_MT_TRACK : INPUT_MT_SEMI_MT)); | ||
| 1379 | } | 1431 | } |
| 1380 | 1432 | ||
| 1381 | if (SYN_CAP_PALMDETECT(priv->capabilities)) | 1433 | if (SYN_CAP_PALMDETECT(priv->capabilities)) |
| @@ -1577,10 +1629,24 @@ static const struct dmi_system_id olpc_dmi_table[] __initconst = { | |||
| 1577 | { } | 1629 | { } |
| 1578 | }; | 1630 | }; |
| 1579 | 1631 | ||
| 1632 | static const struct dmi_system_id __initconst cr48_dmi_table[] = { | ||
| 1633 | #if defined(CONFIG_DMI) && defined(CONFIG_X86) | ||
| 1634 | { | ||
| 1635 | /* Cr-48 Chromebook (Codename Mario) */ | ||
| 1636 | .matches = { | ||
| 1637 | DMI_MATCH(DMI_SYS_VENDOR, "IEC"), | ||
| 1638 | DMI_MATCH(DMI_PRODUCT_NAME, "Mario"), | ||
| 1639 | }, | ||
| 1640 | }, | ||
| 1641 | #endif | ||
| 1642 | { } | ||
| 1643 | }; | ||
| 1644 | |||
| 1580 | void __init synaptics_module_init(void) | 1645 | void __init synaptics_module_init(void) |
| 1581 | { | 1646 | { |
| 1582 | impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table); | 1647 | impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table); |
| 1583 | broken_olpc_ec = dmi_check_system(olpc_dmi_table); | 1648 | broken_olpc_ec = dmi_check_system(olpc_dmi_table); |
| 1649 | cr48_profile_sensor = dmi_check_system(cr48_dmi_table); | ||
| 1584 | } | 1650 | } |
| 1585 | 1651 | ||
| 1586 | static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode) | 1652 | static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode) |
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 03b85711cb70..db178ed2b47e 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c | |||
| @@ -359,7 +359,6 @@ static int mxt_bootloader_read(struct mxt_data *data, | |||
| 359 | msg.buf = val; | 359 | msg.buf = val; |
| 360 | 360 | ||
| 361 | ret = i2c_transfer(data->client->adapter, &msg, 1); | 361 | ret = i2c_transfer(data->client->adapter, &msg, 1); |
| 362 | |||
| 363 | if (ret == 1) { | 362 | if (ret == 1) { |
| 364 | ret = 0; | 363 | ret = 0; |
| 365 | } else { | 364 | } else { |
| @@ -414,6 +413,7 @@ static int mxt_lookup_bootloader_address(struct mxt_data *data, bool retry) | |||
| 414 | case 0x5b: | 413 | case 0x5b: |
| 415 | bootloader = appmode - 0x26; | 414 | bootloader = appmode - 0x26; |
| 416 | break; | 415 | break; |
| 416 | |||
| 417 | default: | 417 | default: |
| 418 | dev_err(&data->client->dev, | 418 | dev_err(&data->client->dev, |
| 419 | "Appmode i2c address 0x%02x not found\n", | 419 | "Appmode i2c address 0x%02x not found\n", |
| @@ -425,20 +425,20 @@ static int mxt_lookup_bootloader_address(struct mxt_data *data, bool retry) | |||
| 425 | return 0; | 425 | return 0; |
| 426 | } | 426 | } |
| 427 | 427 | ||
| 428 | static int mxt_probe_bootloader(struct mxt_data *data, bool retry) | 428 | static int mxt_probe_bootloader(struct mxt_data *data, bool alt_address) |
| 429 | { | 429 | { |
| 430 | struct device *dev = &data->client->dev; | 430 | struct device *dev = &data->client->dev; |
| 431 | int ret; | 431 | int error; |
| 432 | u8 val; | 432 | u8 val; |
| 433 | bool crc_failure; | 433 | bool crc_failure; |
| 434 | 434 | ||
| 435 | ret = mxt_lookup_bootloader_address(data, retry); | 435 | error = mxt_lookup_bootloader_address(data, alt_address); |
| 436 | if (ret) | 436 | if (error) |
| 437 | return ret; | 437 | return error; |
| 438 | 438 | ||
| 439 | ret = mxt_bootloader_read(data, &val, 1); | 439 | error = mxt_bootloader_read(data, &val, 1); |
| 440 | if (ret) | 440 | if (error) |
| 441 | return ret; | 441 | return error; |
| 442 | 442 | ||
| 443 | /* Check app crc fail mode */ | 443 | /* Check app crc fail mode */ |
| 444 | crc_failure = (val & ~MXT_BOOT_STATUS_MASK) == MXT_APP_CRC_FAIL; | 444 | crc_failure = (val & ~MXT_BOOT_STATUS_MASK) == MXT_APP_CRC_FAIL; |
| @@ -1064,6 +1064,137 @@ static u32 mxt_calculate_crc(u8 *base, off_t start_off, off_t end_off) | |||
| 1064 | return crc; | 1064 | return crc; |
| 1065 | } | 1065 | } |
| 1066 | 1066 | ||
| 1067 | static int mxt_prepare_cfg_mem(struct mxt_data *data, | ||
| 1068 | const struct firmware *cfg, | ||
| 1069 | unsigned int data_pos, | ||
| 1070 | unsigned int cfg_start_ofs, | ||
| 1071 | u8 *config_mem, | ||
| 1072 | size_t config_mem_size) | ||
| 1073 | { | ||
| 1074 | struct device *dev = &data->client->dev; | ||
| 1075 | struct mxt_object *object; | ||
| 1076 | unsigned int type, instance, size, byte_offset; | ||
| 1077 | int offset; | ||
| 1078 | int ret; | ||
| 1079 | int i; | ||
| 1080 | u16 reg; | ||
| 1081 | u8 val; | ||
| 1082 | |||
| 1083 | while (data_pos < cfg->size) { | ||
| 1084 | /* Read type, instance, length */ | ||
| 1085 | ret = sscanf(cfg->data + data_pos, "%x %x %x%n", | ||
| 1086 | &type, &instance, &size, &offset); | ||
| 1087 | if (ret == 0) { | ||
| 1088 | /* EOF */ | ||
| 1089 | break; | ||
| 1090 | } else if (ret != 3) { | ||
| 1091 | dev_err(dev, "Bad format: failed to parse object\n"); | ||
| 1092 | return -EINVAL; | ||
| 1093 | } | ||
| 1094 | data_pos += offset; | ||
| 1095 | |||
| 1096 | object = mxt_get_object(data, type); | ||
| 1097 | if (!object) { | ||
| 1098 | /* Skip object */ | ||
| 1099 | for (i = 0; i < size; i++) { | ||
| 1100 | ret = sscanf(cfg->data + data_pos, "%hhx%n", | ||
| 1101 | &val, &offset); | ||
| 1102 | if (ret != 1) { | ||
| 1103 | dev_err(dev, "Bad format in T%d at %d\n", | ||
| 1104 | type, i); | ||
| 1105 | return -EINVAL; | ||
| 1106 | } | ||
| 1107 | data_pos += offset; | ||
| 1108 | } | ||
| 1109 | continue; | ||
| 1110 | } | ||
| 1111 | |||
| 1112 | if (size > mxt_obj_size(object)) { | ||
| 1113 | /* | ||
| 1114 | * Either we are in fallback mode due to wrong | ||
| 1115 | * config or config from a later fw version, | ||
| 1116 | * or the file is corrupt or hand-edited. | ||
| 1117 | */ | ||
| 1118 | dev_warn(dev, "Discarding %zu byte(s) in T%u\n", | ||
| 1119 | size - mxt_obj_size(object), type); | ||
| 1120 | } else if (mxt_obj_size(object) > size) { | ||
| 1121 | /* | ||
| 1122 | * If firmware is upgraded, new bytes may be added to | ||
| 1123 | * end of objects. It is generally forward compatible | ||
| 1124 | * to zero these bytes - previous behaviour will be | ||
| 1125 | * retained. However this does invalidate the CRC and | ||
| 1126 | * will force fallback mode until the configuration is | ||
| 1127 | * updated. We warn here but do nothing else - the | ||
| 1128 | * malloc has zeroed the entire configuration. | ||
| 1129 | */ | ||
| 1130 | dev_warn(dev, "Zeroing %zu byte(s) in T%d\n", | ||
| 1131 | mxt_obj_size(object) - size, type); | ||
| 1132 | } | ||
| 1133 | |||
| 1134 | if (instance >= mxt_obj_instances(object)) { | ||
| 1135 | dev_err(dev, "Object instances exceeded!\n"); | ||
| 1136 | return -EINVAL; | ||
| 1137 | } | ||
| 1138 | |||
| 1139 | reg = object->start_address + mxt_obj_size(object) * instance; | ||
| 1140 | |||
| 1141 | for (i = 0; i < size; i++) { | ||
| 1142 | ret = sscanf(cfg->data + data_pos, "%hhx%n", | ||
| 1143 | &val, | ||
| 1144 | &offset); | ||
| 1145 | if (ret != 1) { | ||
| 1146 | dev_err(dev, "Bad format in T%d at %d\n", | ||
| 1147 | type, i); | ||
| 1148 | return -EINVAL; | ||
| 1149 | } | ||
| 1150 | data_pos += offset; | ||
| 1151 | |||
| 1152 | if (i > mxt_obj_size(object)) | ||
| 1153 | continue; | ||
| 1154 | |||
| 1155 | byte_offset = reg + i - cfg_start_ofs; | ||
| 1156 | |||
| 1157 | if (byte_offset >= 0 && byte_offset < config_mem_size) { | ||
| 1158 | *(config_mem + byte_offset) = val; | ||
| 1159 | } else { | ||
| 1160 | dev_err(dev, "Bad object: reg:%d, T%d, ofs=%d\n", | ||
| 1161 | reg, object->type, byte_offset); | ||
| 1162 | return -EINVAL; | ||
| 1163 | } | ||
| 1164 | } | ||
| 1165 | } | ||
| 1166 | |||
| 1167 | return 0; | ||
| 1168 | } | ||
| 1169 | |||
| 1170 | static int mxt_upload_cfg_mem(struct mxt_data *data, unsigned int cfg_start, | ||
| 1171 | u8 *config_mem, size_t config_mem_size) | ||
| 1172 | { | ||
| 1173 | unsigned int byte_offset = 0; | ||
| 1174 | int error; | ||
| 1175 | |||
| 1176 | /* Write configuration as blocks */ | ||
| 1177 | while (byte_offset < config_mem_size) { | ||
| 1178 | unsigned int size = config_mem_size - byte_offset; | ||
| 1179 | |||
| 1180 | if (size > MXT_MAX_BLOCK_WRITE) | ||
| 1181 | size = MXT_MAX_BLOCK_WRITE; | ||
| 1182 | |||
| 1183 | error = __mxt_write_reg(data->client, | ||
| 1184 | cfg_start + byte_offset, | ||
| 1185 | size, config_mem + byte_offset); | ||
| 1186 | if (error) { | ||
| 1187 | dev_err(&data->client->dev, | ||
| 1188 | "Config write error, ret=%d\n", error); | ||
| 1189 | return error; | ||
| 1190 | } | ||
| 1191 | |||
| 1192 | byte_offset += size; | ||
| 1193 | } | ||
| 1194 | |||
| 1195 | return 0; | ||
| 1196 | } | ||
| 1197 | |||
| 1067 | /* | 1198 | /* |
| 1068 | * mxt_update_cfg - download configuration to chip | 1199 | * mxt_update_cfg - download configuration to chip |
| 1069 | * | 1200 | * |
| @@ -1087,26 +1218,20 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg) | |||
| 1087 | { | 1218 | { |
| 1088 | struct device *dev = &data->client->dev; | 1219 | struct device *dev = &data->client->dev; |
| 1089 | struct mxt_info cfg_info; | 1220 | struct mxt_info cfg_info; |
| 1090 | struct mxt_object *object; | ||
| 1091 | int ret; | 1221 | int ret; |
| 1092 | int offset; | 1222 | int offset; |
| 1093 | int data_pos; | 1223 | int data_pos; |
| 1094 | int byte_offset; | ||
| 1095 | int i; | 1224 | int i; |
| 1096 | int cfg_start_ofs; | 1225 | int cfg_start_ofs; |
| 1097 | u32 info_crc, config_crc, calculated_crc; | 1226 | u32 info_crc, config_crc, calculated_crc; |
| 1098 | u8 *config_mem; | 1227 | u8 *config_mem; |
| 1099 | size_t config_mem_size; | 1228 | size_t config_mem_size; |
| 1100 | unsigned int type, instance, size; | ||
| 1101 | u8 val; | ||
| 1102 | u16 reg; | ||
| 1103 | 1229 | ||
| 1104 | mxt_update_crc(data, MXT_COMMAND_REPORTALL, 1); | 1230 | mxt_update_crc(data, MXT_COMMAND_REPORTALL, 1); |
| 1105 | 1231 | ||
| 1106 | if (strncmp(cfg->data, MXT_CFG_MAGIC, strlen(MXT_CFG_MAGIC))) { | 1232 | if (strncmp(cfg->data, MXT_CFG_MAGIC, strlen(MXT_CFG_MAGIC))) { |
| 1107 | dev_err(dev, "Unrecognised config file\n"); | 1233 | dev_err(dev, "Unrecognised config file\n"); |
| 1108 | ret = -EINVAL; | 1234 | return -EINVAL; |
| 1109 | goto release; | ||
| 1110 | } | 1235 | } |
| 1111 | 1236 | ||
| 1112 | data_pos = strlen(MXT_CFG_MAGIC); | 1237 | data_pos = strlen(MXT_CFG_MAGIC); |
| @@ -1118,8 +1243,7 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg) | |||
| 1118 | &offset); | 1243 | &offset); |
| 1119 | if (ret != 1) { | 1244 | if (ret != 1) { |
| 1120 | dev_err(dev, "Bad format\n"); | 1245 | dev_err(dev, "Bad format\n"); |
| 1121 | ret = -EINVAL; | 1246 | return -EINVAL; |
| 1122 | goto release; | ||
| 1123 | } | 1247 | } |
| 1124 | 1248 | ||
| 1125 | data_pos += offset; | 1249 | data_pos += offset; |
| @@ -1127,30 +1251,26 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg) | |||
| 1127 | 1251 | ||
| 1128 | if (cfg_info.family_id != data->info.family_id) { | 1252 | if (cfg_info.family_id != data->info.family_id) { |
| 1129 | dev_err(dev, "Family ID mismatch!\n"); | 1253 | dev_err(dev, "Family ID mismatch!\n"); |
| 1130 | ret = -EINVAL; | 1254 | return -EINVAL; |
| 1131 | goto release; | ||
| 1132 | } | 1255 | } |
| 1133 | 1256 | ||
| 1134 | if (cfg_info.variant_id != data->info.variant_id) { | 1257 | if (cfg_info.variant_id != data->info.variant_id) { |
| 1135 | dev_err(dev, "Variant ID mismatch!\n"); | 1258 | dev_err(dev, "Variant ID mismatch!\n"); |
| 1136 | ret = -EINVAL; | 1259 | return -EINVAL; |
| 1137 | goto release; | ||
| 1138 | } | 1260 | } |
| 1139 | 1261 | ||
| 1140 | /* Read CRCs */ | 1262 | /* Read CRCs */ |
| 1141 | ret = sscanf(cfg->data + data_pos, "%x%n", &info_crc, &offset); | 1263 | ret = sscanf(cfg->data + data_pos, "%x%n", &info_crc, &offset); |
| 1142 | if (ret != 1) { | 1264 | if (ret != 1) { |
| 1143 | dev_err(dev, "Bad format: failed to parse Info CRC\n"); | 1265 | dev_err(dev, "Bad format: failed to parse Info CRC\n"); |
| 1144 | ret = -EINVAL; | 1266 | return -EINVAL; |
| 1145 | goto release; | ||
| 1146 | } | 1267 | } |
| 1147 | data_pos += offset; | 1268 | data_pos += offset; |
| 1148 | 1269 | ||
| 1149 | ret = sscanf(cfg->data + data_pos, "%x%n", &config_crc, &offset); | 1270 | ret = sscanf(cfg->data + data_pos, "%x%n", &config_crc, &offset); |
| 1150 | if (ret != 1) { | 1271 | if (ret != 1) { |
| 1151 | dev_err(dev, "Bad format: failed to parse Config CRC\n"); | 1272 | dev_err(dev, "Bad format: failed to parse Config CRC\n"); |
| 1152 | ret = -EINVAL; | 1273 | return -EINVAL; |
| 1153 | goto release; | ||
| 1154 | } | 1274 | } |
| 1155 | data_pos += offset; | 1275 | data_pos += offset; |
| 1156 | 1276 | ||
| @@ -1166,8 +1286,7 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg) | |||
| 1166 | } else if (config_crc == data->config_crc) { | 1286 | } else if (config_crc == data->config_crc) { |
| 1167 | dev_dbg(dev, "Config CRC 0x%06X: OK\n", | 1287 | dev_dbg(dev, "Config CRC 0x%06X: OK\n", |
| 1168 | data->config_crc); | 1288 | data->config_crc); |
| 1169 | ret = 0; | 1289 | return 0; |
| 1170 | goto release; | ||
| 1171 | } else { | 1290 | } else { |
| 1172 | dev_info(dev, "Config CRC 0x%06X: does not match file 0x%06X\n", | 1291 | dev_info(dev, "Config CRC 0x%06X: does not match file 0x%06X\n", |
| 1173 | data->config_crc, config_crc); | 1292 | data->config_crc, config_crc); |
| @@ -1186,93 +1305,13 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg) | |||
| 1186 | config_mem = kzalloc(config_mem_size, GFP_KERNEL); | 1305 | config_mem = kzalloc(config_mem_size, GFP_KERNEL); |
| 1187 | if (!config_mem) { | 1306 | if (!config_mem) { |
| 1188 | dev_err(dev, "Failed to allocate memory\n"); | 1307 | dev_err(dev, "Failed to allocate memory\n"); |
| 1189 | ret = -ENOMEM; | 1308 | return -ENOMEM; |
| 1190 | goto release; | ||
| 1191 | } | 1309 | } |
| 1192 | 1310 | ||
| 1193 | while (data_pos < cfg->size) { | 1311 | ret = mxt_prepare_cfg_mem(data, cfg, data_pos, cfg_start_ofs, |
| 1194 | /* Read type, instance, length */ | 1312 | config_mem, config_mem_size); |
| 1195 | ret = sscanf(cfg->data + data_pos, "%x %x %x%n", | 1313 | if (ret) |
| 1196 | &type, &instance, &size, &offset); | 1314 | goto release_mem; |
| 1197 | if (ret == 0) { | ||
| 1198 | /* EOF */ | ||
| 1199 | break; | ||
| 1200 | } else if (ret != 3) { | ||
| 1201 | dev_err(dev, "Bad format: failed to parse object\n"); | ||
| 1202 | ret = -EINVAL; | ||
| 1203 | goto release_mem; | ||
| 1204 | } | ||
| 1205 | data_pos += offset; | ||
| 1206 | |||
| 1207 | object = mxt_get_object(data, type); | ||
| 1208 | if (!object) { | ||
| 1209 | /* Skip object */ | ||
| 1210 | for (i = 0; i < size; i++) { | ||
| 1211 | ret = sscanf(cfg->data + data_pos, "%hhx%n", | ||
| 1212 | &val, | ||
| 1213 | &offset); | ||
| 1214 | data_pos += offset; | ||
| 1215 | } | ||
| 1216 | continue; | ||
| 1217 | } | ||
| 1218 | |||
| 1219 | if (size > mxt_obj_size(object)) { | ||
| 1220 | /* | ||
| 1221 | * Either we are in fallback mode due to wrong | ||
| 1222 | * config or config from a later fw version, | ||
| 1223 | * or the file is corrupt or hand-edited. | ||
| 1224 | */ | ||
| 1225 | dev_warn(dev, "Discarding %zu byte(s) in T%u\n", | ||
| 1226 | size - mxt_obj_size(object), type); | ||
| 1227 | } else if (mxt_obj_size(object) > size) { | ||
| 1228 | /* | ||
| 1229 | * If firmware is upgraded, new bytes may be added to | ||
| 1230 | * end of objects. It is generally forward compatible | ||
| 1231 | * to zero these bytes - previous behaviour will be | ||
| 1232 | * retained. However this does invalidate the CRC and | ||
| 1233 | * will force fallback mode until the configuration is | ||
| 1234 | * updated. We warn here but do nothing else - the | ||
| 1235 | * malloc has zeroed the entire configuration. | ||
| 1236 | */ | ||
| 1237 | dev_warn(dev, "Zeroing %zu byte(s) in T%d\n", | ||
| 1238 | mxt_obj_size(object) - size, type); | ||
| 1239 | } | ||
| 1240 | |||
| 1241 | if (instance >= mxt_obj_instances(object)) { | ||
| 1242 | dev_err(dev, "Object instances exceeded!\n"); | ||
| 1243 | ret = -EINVAL; | ||
| 1244 | goto release_mem; | ||
| 1245 | } | ||
| 1246 | |||
| 1247 | reg = object->start_address + mxt_obj_size(object) * instance; | ||
| 1248 | |||
| 1249 | for (i = 0; i < size; i++) { | ||
| 1250 | ret = sscanf(cfg->data + data_pos, "%hhx%n", | ||
| 1251 | &val, | ||
| 1252 | &offset); | ||
| 1253 | if (ret != 1) { | ||
| 1254 | dev_err(dev, "Bad format in T%d\n", type); | ||
| 1255 | ret = -EINVAL; | ||
| 1256 | goto release_mem; | ||
| 1257 | } | ||
| 1258 | data_pos += offset; | ||
| 1259 | |||
| 1260 | if (i > mxt_obj_size(object)) | ||
| 1261 | continue; | ||
| 1262 | |||
| 1263 | byte_offset = reg + i - cfg_start_ofs; | ||
| 1264 | |||
| 1265 | if ((byte_offset >= 0) | ||
| 1266 | && (byte_offset <= config_mem_size)) { | ||
| 1267 | *(config_mem + byte_offset) = val; | ||
| 1268 | } else { | ||
| 1269 | dev_err(dev, "Bad object: reg:%d, T%d, ofs=%d\n", | ||
| 1270 | reg, object->type, byte_offset); | ||
| 1271 | ret = -EINVAL; | ||
| 1272 | goto release_mem; | ||
| 1273 | } | ||
| 1274 | } | ||
| 1275 | } | ||
| 1276 | 1315 | ||
| 1277 | /* Calculate crc of the received configs (not the raw config file) */ | 1316 | /* Calculate crc of the received configs (not the raw config file) */ |
| 1278 | if (data->T7_address < cfg_start_ofs) { | 1317 | if (data->T7_address < cfg_start_ofs) { |
| @@ -1286,28 +1325,14 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg) | |||
| 1286 | data->T7_address - cfg_start_ofs, | 1325 | data->T7_address - cfg_start_ofs, |
| 1287 | config_mem_size); | 1326 | config_mem_size); |
| 1288 | 1327 | ||
| 1289 | if (config_crc > 0 && (config_crc != calculated_crc)) | 1328 | if (config_crc > 0 && config_crc != calculated_crc) |
| 1290 | dev_warn(dev, "Config CRC error, calculated=%06X, file=%06X\n", | 1329 | dev_warn(dev, "Config CRC error, calculated=%06X, file=%06X\n", |
| 1291 | calculated_crc, config_crc); | 1330 | calculated_crc, config_crc); |
| 1292 | 1331 | ||
| 1293 | /* Write configuration as blocks */ | 1332 | ret = mxt_upload_cfg_mem(data, cfg_start_ofs, |
| 1294 | byte_offset = 0; | 1333 | config_mem, config_mem_size); |
| 1295 | while (byte_offset < config_mem_size) { | 1334 | if (ret) |
| 1296 | size = config_mem_size - byte_offset; | 1335 | goto release_mem; |
| 1297 | |||
| 1298 | if (size > MXT_MAX_BLOCK_WRITE) | ||
| 1299 | size = MXT_MAX_BLOCK_WRITE; | ||
| 1300 | |||
| 1301 | ret = __mxt_write_reg(data->client, | ||
| 1302 | cfg_start_ofs + byte_offset, | ||
| 1303 | size, config_mem + byte_offset); | ||
| 1304 | if (ret != 0) { | ||
| 1305 | dev_err(dev, "Config write error, ret=%d\n", ret); | ||
| 1306 | goto release_mem; | ||
| 1307 | } | ||
| 1308 | |||
| 1309 | byte_offset += size; | ||
| 1310 | } | ||
| 1311 | 1336 | ||
| 1312 | mxt_update_crc(data, MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE); | 1337 | mxt_update_crc(data, MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE); |
| 1313 | 1338 | ||
| @@ -1319,8 +1344,6 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg) | |||
| 1319 | 1344 | ||
| 1320 | release_mem: | 1345 | release_mem: |
| 1321 | kfree(config_mem); | 1346 | kfree(config_mem); |
| 1322 | release: | ||
| 1323 | release_firmware(cfg); | ||
| 1324 | return ret; | 1347 | return ret; |
| 1325 | } | 1348 | } |
| 1326 | 1349 | ||
| @@ -1422,10 +1445,12 @@ static int mxt_get_object_table(struct mxt_data *data) | |||
| 1422 | 1445 | ||
| 1423 | switch (object->type) { | 1446 | switch (object->type) { |
| 1424 | case MXT_GEN_MESSAGE_T5: | 1447 | case MXT_GEN_MESSAGE_T5: |
| 1425 | if (data->info.family_id == 0x80) { | 1448 | if (data->info.family_id == 0x80 && |
| 1449 | data->info.version < 0x20) { | ||
| 1426 | /* | 1450 | /* |
| 1427 | * On mXT224 read and discard unused CRC byte | 1451 | * On mXT224 firmware versions prior to V2.0 |
| 1428 | * otherwise DMA reads are misaligned | 1452 | * read and discard unused CRC byte otherwise |
| 1453 | * DMA reads are misaligned. | ||
| 1429 | */ | 1454 | */ |
| 1430 | data->T5_msg_size = mxt_obj_size(object); | 1455 | data->T5_msg_size = mxt_obj_size(object); |
| 1431 | } else { | 1456 | } else { |
| @@ -1433,6 +1458,7 @@ static int mxt_get_object_table(struct mxt_data *data) | |||
| 1433 | data->T5_msg_size = mxt_obj_size(object) - 1; | 1458 | data->T5_msg_size = mxt_obj_size(object) - 1; |
| 1434 | } | 1459 | } |
| 1435 | data->T5_address = object->start_address; | 1460 | data->T5_address = object->start_address; |
| 1461 | break; | ||
| 1436 | case MXT_GEN_COMMAND_T6: | 1462 | case MXT_GEN_COMMAND_T6: |
| 1437 | data->T6_reportid = min_id; | 1463 | data->T6_reportid = min_id; |
| 1438 | data->T6_address = object->start_address; | 1464 | data->T6_address = object->start_address; |
| @@ -1638,46 +1664,45 @@ static int mxt_configure_objects(struct mxt_data *data, | |||
| 1638 | static void mxt_config_cb(const struct firmware *cfg, void *ctx) | 1664 | static void mxt_config_cb(const struct firmware *cfg, void *ctx) |
| 1639 | { | 1665 | { |
| 1640 | mxt_configure_objects(ctx, cfg); | 1666 | mxt_configure_objects(ctx, cfg); |
| 1667 | release_firmware(cfg); | ||
| 1641 | } | 1668 | } |
| 1642 | 1669 | ||
| 1643 | static int mxt_initialize(struct mxt_data *data) | 1670 | static int mxt_initialize(struct mxt_data *data) |
| 1644 | { | 1671 | { |
| 1645 | struct i2c_client *client = data->client; | 1672 | struct i2c_client *client = data->client; |
| 1673 | int recovery_attempts = 0; | ||
| 1646 | int error; | 1674 | int error; |
| 1647 | bool alt_bootloader_addr = false; | ||
| 1648 | bool retry = false; | ||
| 1649 | 1675 | ||
| 1650 | retry_info: | 1676 | while (1) { |
| 1651 | error = mxt_get_info(data); | 1677 | error = mxt_get_info(data); |
| 1652 | if (error) { | 1678 | if (!error) |
| 1653 | retry_bootloader: | 1679 | break; |
| 1654 | error = mxt_probe_bootloader(data, alt_bootloader_addr); | 1680 | |
| 1681 | /* Check bootloader state */ | ||
| 1682 | error = mxt_probe_bootloader(data, false); | ||
| 1655 | if (error) { | 1683 | if (error) { |
| 1656 | if (alt_bootloader_addr) { | 1684 | dev_info(&client->dev, "Trying alternate bootloader address\n"); |
| 1685 | error = mxt_probe_bootloader(data, true); | ||
| 1686 | if (error) { | ||
| 1657 | /* Chip is not in appmode or bootloader mode */ | 1687 | /* Chip is not in appmode or bootloader mode */ |
| 1658 | return error; | 1688 | return error; |
| 1659 | } | 1689 | } |
| 1690 | } | ||
| 1660 | 1691 | ||
| 1661 | dev_info(&client->dev, "Trying alternate bootloader address\n"); | 1692 | /* OK, we are in bootloader, see if we can recover */ |
| 1662 | alt_bootloader_addr = true; | 1693 | if (++recovery_attempts > 1) { |
| 1663 | goto retry_bootloader; | 1694 | dev_err(&client->dev, "Could not recover from bootloader mode\n"); |
| 1664 | } else { | 1695 | /* |
| 1665 | if (retry) { | 1696 | * We can reflash from this state, so do not |
| 1666 | dev_err(&client->dev, "Could not recover from bootloader mode\n"); | 1697 | * abort initialization. |
| 1667 | /* | 1698 | */ |
| 1668 | * We can reflash from this state, so do not | 1699 | data->in_bootloader = true; |
| 1669 | * abort init | 1700 | return 0; |
| 1670 | */ | ||
| 1671 | data->in_bootloader = true; | ||
| 1672 | return 0; | ||
| 1673 | } | ||
| 1674 | |||
| 1675 | /* Attempt to exit bootloader into app mode */ | ||
| 1676 | mxt_send_bootloader_cmd(data, false); | ||
| 1677 | msleep(MXT_FW_RESET_TIME); | ||
| 1678 | retry = true; | ||
| 1679 | goto retry_info; | ||
| 1680 | } | 1701 | } |
| 1702 | |||
| 1703 | /* Attempt to exit bootloader into app mode */ | ||
| 1704 | mxt_send_bootloader_cmd(data, false); | ||
| 1705 | msleep(MXT_FW_RESET_TIME); | ||
| 1681 | } | 1706 | } |
| 1682 | 1707 | ||
| 1683 | /* Get object table information */ | 1708 | /* Get object table information */ |
| @@ -1687,13 +1712,18 @@ retry_bootloader: | |||
| 1687 | return error; | 1712 | return error; |
| 1688 | } | 1713 | } |
| 1689 | 1714 | ||
| 1690 | mxt_acquire_irq(data); | 1715 | error = mxt_acquire_irq(data); |
| 1691 | if (error) | 1716 | if (error) |
| 1692 | goto err_free_object_table; | 1717 | goto err_free_object_table; |
| 1693 | 1718 | ||
| 1694 | request_firmware_nowait(THIS_MODULE, true, MXT_CFG_NAME, | 1719 | error = request_firmware_nowait(THIS_MODULE, true, MXT_CFG_NAME, |
| 1695 | &data->client->dev, GFP_KERNEL, data, | 1720 | &client->dev, GFP_KERNEL, data, |
| 1696 | mxt_config_cb); | 1721 | mxt_config_cb); |
| 1722 | if (error) { | ||
| 1723 | dev_err(&client->dev, "Failed to invoke firmware loader: %d\n", | ||
| 1724 | error); | ||
| 1725 | goto err_free_object_table; | ||
| 1726 | } | ||
| 1697 | 1727 | ||
| 1698 | return 0; | 1728 | return 0; |
| 1699 | 1729 | ||
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 5a6d50c004d7..8857d5b9be71 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c | |||
| @@ -262,7 +262,6 @@ static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata, | |||
| 262 | case M06: | 262 | case M06: |
| 263 | wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc; | 263 | wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc; |
| 264 | wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; | 264 | wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; |
| 265 | wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; | ||
| 266 | wrbuf[2] = value; | 265 | wrbuf[2] = value; |
| 267 | wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2]; | 266 | wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2]; |
| 268 | return edt_ft5x06_ts_readwrite(tsdata->client, 4, | 267 | return edt_ft5x06_ts_readwrite(tsdata->client, 4, |
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 18405314168b..ecb0109a5360 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c | |||
| @@ -3149,14 +3149,16 @@ free_domains: | |||
| 3149 | 3149 | ||
| 3150 | static void cleanup_domain(struct protection_domain *domain) | 3150 | static void cleanup_domain(struct protection_domain *domain) |
| 3151 | { | 3151 | { |
| 3152 | struct iommu_dev_data *dev_data, *next; | 3152 | struct iommu_dev_data *entry; |
| 3153 | unsigned long flags; | 3153 | unsigned long flags; |
| 3154 | 3154 | ||
| 3155 | write_lock_irqsave(&amd_iommu_devtable_lock, flags); | 3155 | write_lock_irqsave(&amd_iommu_devtable_lock, flags); |
| 3156 | 3156 | ||
| 3157 | list_for_each_entry_safe(dev_data, next, &domain->dev_list, list) { | 3157 | while (!list_empty(&domain->dev_list)) { |
| 3158 | __detach_device(dev_data); | 3158 | entry = list_first_entry(&domain->dev_list, |
| 3159 | atomic_set(&dev_data->bind, 0); | 3159 | struct iommu_dev_data, list); |
| 3160 | __detach_device(entry); | ||
| 3161 | atomic_set(&entry->bind, 0); | ||
| 3160 | } | 3162 | } |
| 3161 | 3163 | ||
| 3162 | write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); | 3164 | write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); |
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index d1f5caad04f9..5619f264862d 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c | |||
| @@ -3869,6 +3869,14 @@ static int device_notifier(struct notifier_block *nb, | |||
| 3869 | action != BUS_NOTIFY_DEL_DEVICE) | 3869 | action != BUS_NOTIFY_DEL_DEVICE) |
| 3870 | return 0; | 3870 | return 0; |
| 3871 | 3871 | ||
| 3872 | /* | ||
| 3873 | * If the device is still attached to a device driver we can't | ||
| 3874 | * tear down the domain yet as DMA mappings may still be in use. | ||
| 3875 | * Wait for the BUS_NOTIFY_UNBOUND_DRIVER event to do that. | ||
| 3876 | */ | ||
| 3877 | if (action == BUS_NOTIFY_DEL_DEVICE && dev->driver != NULL) | ||
| 3878 | return 0; | ||
| 3879 | |||
| 3872 | domain = find_domain(dev); | 3880 | domain = find_domain(dev); |
| 3873 | if (!domain) | 3881 | if (!domain) |
| 3874 | return 0; | 3882 | return 0; |
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 169836020208..ac4adb337038 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c | |||
| @@ -995,7 +995,7 @@ int iommu_map(struct iommu_domain *domain, unsigned long iova, | |||
| 995 | size_t orig_size = size; | 995 | size_t orig_size = size; |
| 996 | int ret = 0; | 996 | int ret = 0; |
| 997 | 997 | ||
| 998 | if (unlikely(domain->ops->unmap == NULL || | 998 | if (unlikely(domain->ops->map == NULL || |
| 999 | domain->ops->pgsize_bitmap == 0UL)) | 999 | domain->ops->pgsize_bitmap == 0UL)) |
| 1000 | return -ENODEV; | 1000 | return -ENODEV; |
| 1001 | 1001 | ||
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index b08c18871323..6703751d87d7 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
| @@ -2953,6 +2953,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, | |||
| 2953 | */ | 2953 | */ |
| 2954 | if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) { | 2954 | if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) { |
| 2955 | end_reshape(conf); | 2955 | end_reshape(conf); |
| 2956 | close_sync(conf); | ||
| 2956 | return 0; | 2957 | return 0; |
| 2957 | } | 2958 | } |
| 2958 | 2959 | ||
| @@ -3081,6 +3082,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, | |||
| 3081 | } | 3082 | } |
| 3082 | 3083 | ||
| 3083 | r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO); | 3084 | r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO); |
| 3085 | r10_bio->state = 0; | ||
| 3084 | raise_barrier(conf, rb2 != NULL); | 3086 | raise_barrier(conf, rb2 != NULL); |
| 3085 | atomic_set(&r10_bio->remaining, 0); | 3087 | atomic_set(&r10_bio->remaining, 0); |
| 3086 | 3088 | ||
| @@ -3269,6 +3271,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, | |||
| 3269 | if (sync_blocks < max_sync) | 3271 | if (sync_blocks < max_sync) |
| 3270 | max_sync = sync_blocks; | 3272 | max_sync = sync_blocks; |
| 3271 | r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO); | 3273 | r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO); |
| 3274 | r10_bio->state = 0; | ||
| 3272 | 3275 | ||
| 3273 | r10_bio->mddev = mddev; | 3276 | r10_bio->mddev = mddev; |
| 3274 | atomic_set(&r10_bio->remaining, 0); | 3277 | atomic_set(&r10_bio->remaining, 0); |
| @@ -4384,6 +4387,7 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, | |||
| 4384 | read_more: | 4387 | read_more: |
| 4385 | /* Now schedule reads for blocks from sector_nr to last */ | 4388 | /* Now schedule reads for blocks from sector_nr to last */ |
| 4386 | r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO); | 4389 | r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO); |
| 4390 | r10_bio->state = 0; | ||
| 4387 | raise_barrier(conf, sectors_done != 0); | 4391 | raise_barrier(conf, sectors_done != 0); |
| 4388 | atomic_set(&r10_bio->remaining, 0); | 4392 | atomic_set(&r10_bio->remaining, 0); |
| 4389 | r10_bio->mddev = mddev; | 4393 | r10_bio->mddev = mddev; |
| @@ -4398,6 +4402,7 @@ read_more: | |||
| 4398 | * on all the target devices. | 4402 | * on all the target devices. |
| 4399 | */ | 4403 | */ |
| 4400 | // FIXME | 4404 | // FIXME |
| 4405 | mempool_free(r10_bio, conf->r10buf_pool); | ||
| 4401 | set_bit(MD_RECOVERY_INTR, &mddev->recovery); | 4406 | set_bit(MD_RECOVERY_INTR, &mddev->recovery); |
| 4402 | return sectors_done; | 4407 | return sectors_done; |
| 4403 | } | 4408 | } |
| @@ -4410,7 +4415,7 @@ read_more: | |||
| 4410 | read_bio->bi_private = r10_bio; | 4415 | read_bio->bi_private = r10_bio; |
| 4411 | read_bio->bi_end_io = end_sync_read; | 4416 | read_bio->bi_end_io = end_sync_read; |
| 4412 | read_bio->bi_rw = READ; | 4417 | read_bio->bi_rw = READ; |
| 4413 | read_bio->bi_flags &= ~(BIO_POOL_MASK - 1); | 4418 | read_bio->bi_flags &= (~0UL << BIO_RESET_BITS); |
| 4414 | read_bio->bi_flags |= 1 << BIO_UPTODATE; | 4419 | read_bio->bi_flags |= 1 << BIO_UPTODATE; |
| 4415 | read_bio->bi_vcnt = 0; | 4420 | read_bio->bi_vcnt = 0; |
| 4416 | read_bio->bi_iter.bi_size = 0; | 4421 | read_bio->bi_iter.bi_size = 0; |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 6234b2e84587..183588b11fc1 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
| @@ -2922,7 +2922,7 @@ static int fetch_block(struct stripe_head *sh, struct stripe_head_state *s, | |||
| 2922 | (!test_bit(R5_Insync, &dev->flags) || test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) && | 2922 | (!test_bit(R5_Insync, &dev->flags) || test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) && |
| 2923 | !test_bit(R5_OVERWRITE, &fdev[0]->flags)) || | 2923 | !test_bit(R5_OVERWRITE, &fdev[0]->flags)) || |
| 2924 | (sh->raid_conf->level == 6 && s->failed && s->to_write && | 2924 | (sh->raid_conf->level == 6 && s->failed && s->to_write && |
| 2925 | s->to_write < sh->raid_conf->raid_disks - 2 && | 2925 | s->to_write - s->non_overwrite < sh->raid_conf->raid_disks - 2 && |
| 2926 | (!test_bit(R5_Insync, &dev->flags) || test_bit(STRIPE_PREREAD_ACTIVE, &sh->state))))) { | 2926 | (!test_bit(R5_Insync, &dev->flags) || test_bit(STRIPE_PREREAD_ACTIVE, &sh->state))))) { |
| 2927 | /* we would like to get this block, possibly by computing it, | 2927 | /* we would like to get this block, possibly by computing it, |
| 2928 | * otherwise read it if the backing disk is insync | 2928 | * otherwise read it if the backing disk is insync |
| @@ -3817,6 +3817,8 @@ static void handle_stripe(struct stripe_head *sh) | |||
| 3817 | set_bit(R5_Wantwrite, &dev->flags); | 3817 | set_bit(R5_Wantwrite, &dev->flags); |
| 3818 | if (prexor) | 3818 | if (prexor) |
| 3819 | continue; | 3819 | continue; |
| 3820 | if (s.failed > 1) | ||
| 3821 | continue; | ||
| 3820 | if (!test_bit(R5_Insync, &dev->flags) || | 3822 | if (!test_bit(R5_Insync, &dev->flags) || |
| 3821 | ((i == sh->pd_idx || i == sh->qd_idx) && | 3823 | ((i == sh->pd_idx || i == sh->qd_idx) && |
| 3822 | s.failed == 0)) | 3824 | s.failed == 0)) |
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index f46a24ffa3fe..79cb8313c7d8 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c | |||
| @@ -453,7 +453,7 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, | |||
| 453 | base = dt_mem_next_cell(dt_root_addr_cells, &prop); | 453 | base = dt_mem_next_cell(dt_root_addr_cells, &prop); |
| 454 | size = dt_mem_next_cell(dt_root_size_cells, &prop); | 454 | size = dt_mem_next_cell(dt_root_size_cells, &prop); |
| 455 | 455 | ||
| 456 | if (base && size && | 456 | if (size && |
| 457 | early_init_dt_reserve_memory_arch(base, size, nomap) == 0) | 457 | early_init_dt_reserve_memory_arch(base, size, nomap) == 0) |
| 458 | pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %ld MiB\n", | 458 | pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %ld MiB\n", |
| 459 | uname, &base, (unsigned long)size / SZ_1M); | 459 | uname, &base, (unsigned long)size / SZ_1M); |
diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 3e06a699352d..1471e0a223a5 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c | |||
| @@ -301,16 +301,17 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar | |||
| 301 | /* Get the reg property (if any) */ | 301 | /* Get the reg property (if any) */ |
| 302 | addr = of_get_property(device, "reg", NULL); | 302 | addr = of_get_property(device, "reg", NULL); |
| 303 | 303 | ||
| 304 | /* Try the new-style interrupts-extended first */ | ||
| 305 | res = of_parse_phandle_with_args(device, "interrupts-extended", | ||
| 306 | "#interrupt-cells", index, out_irq); | ||
| 307 | if (!res) | ||
| 308 | return of_irq_parse_raw(addr, out_irq); | ||
| 309 | |||
| 304 | /* Get the interrupts property */ | 310 | /* Get the interrupts property */ |
| 305 | intspec = of_get_property(device, "interrupts", &intlen); | 311 | intspec = of_get_property(device, "interrupts", &intlen); |
| 306 | if (intspec == NULL) { | 312 | if (intspec == NULL) |
| 307 | /* Try the new-style interrupts-extended */ | 313 | return -EINVAL; |
| 308 | res = of_parse_phandle_with_args(device, "interrupts-extended", | 314 | |
| 309 | "#interrupt-cells", index, out_irq); | ||
| 310 | if (res) | ||
| 311 | return -EINVAL; | ||
| 312 | return of_irq_parse_raw(addr, out_irq); | ||
| 313 | } | ||
| 314 | intlen /= sizeof(*intspec); | 315 | intlen /= sizeof(*intspec); |
| 315 | 316 | ||
| 316 | pr_debug(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen); | 317 | pr_debug(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen); |
diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c index d41002667833..a737cb5974de 100644 --- a/drivers/of/selftest.c +++ b/drivers/of/selftest.c | |||
| @@ -27,6 +27,7 @@ static struct selftest_results { | |||
| 27 | #define NO_OF_NODES 2 | 27 | #define NO_OF_NODES 2 |
| 28 | static struct device_node *nodes[NO_OF_NODES]; | 28 | static struct device_node *nodes[NO_OF_NODES]; |
| 29 | static int last_node_index; | 29 | static int last_node_index; |
| 30 | static bool selftest_live_tree; | ||
| 30 | 31 | ||
| 31 | #define selftest(result, fmt, ...) { \ | 32 | #define selftest(result, fmt, ...) { \ |
| 32 | if (!(result)) { \ | 33 | if (!(result)) { \ |
| @@ -630,13 +631,6 @@ static int attach_node_and_children(struct device_node *np) | |||
| 630 | { | 631 | { |
| 631 | struct device_node *next, *root = np, *dup; | 632 | struct device_node *next, *root = np, *dup; |
| 632 | 633 | ||
| 633 | if (!np) { | ||
| 634 | pr_warn("%s: No tree to attach; not running tests\n", | ||
| 635 | __func__); | ||
| 636 | return -ENODATA; | ||
| 637 | } | ||
| 638 | |||
| 639 | |||
| 640 | /* skip root node */ | 634 | /* skip root node */ |
| 641 | np = np->child; | 635 | np = np->child; |
| 642 | /* storing a copy in temporary node */ | 636 | /* storing a copy in temporary node */ |
| @@ -672,12 +666,12 @@ static int attach_node_and_children(struct device_node *np) | |||
| 672 | static int __init selftest_data_add(void) | 666 | static int __init selftest_data_add(void) |
| 673 | { | 667 | { |
| 674 | void *selftest_data; | 668 | void *selftest_data; |
| 675 | struct device_node *selftest_data_node; | 669 | struct device_node *selftest_data_node, *np; |
| 676 | extern uint8_t __dtb_testcases_begin[]; | 670 | extern uint8_t __dtb_testcases_begin[]; |
| 677 | extern uint8_t __dtb_testcases_end[]; | 671 | extern uint8_t __dtb_testcases_end[]; |
| 678 | const int size = __dtb_testcases_end - __dtb_testcases_begin; | 672 | const int size = __dtb_testcases_end - __dtb_testcases_begin; |
| 679 | 673 | ||
| 680 | if (!size || !of_allnodes) { | 674 | if (!size) { |
| 681 | pr_warn("%s: No testcase data to attach; not running tests\n", | 675 | pr_warn("%s: No testcase data to attach; not running tests\n", |
| 682 | __func__); | 676 | __func__); |
| 683 | return -ENODATA; | 677 | return -ENODATA; |
| @@ -692,6 +686,22 @@ static int __init selftest_data_add(void) | |||
| 692 | return -ENOMEM; | 686 | return -ENOMEM; |
| 693 | } | 687 | } |
| 694 | of_fdt_unflatten_tree(selftest_data, &selftest_data_node); | 688 | of_fdt_unflatten_tree(selftest_data, &selftest_data_node); |
| 689 | if (!selftest_data_node) { | ||
| 690 | pr_warn("%s: No tree to attach; not running tests\n", __func__); | ||
| 691 | return -ENODATA; | ||
| 692 | } | ||
| 693 | |||
| 694 | if (!of_allnodes) { | ||
| 695 | /* enabling flag for removing nodes */ | ||
| 696 | selftest_live_tree = true; | ||
| 697 | of_allnodes = selftest_data_node; | ||
| 698 | |||
| 699 | for_each_of_allnodes(np) | ||
| 700 | __of_attach_node_sysfs(np); | ||
| 701 | of_aliases = of_find_node_by_path("/aliases"); | ||
| 702 | of_chosen = of_find_node_by_path("/chosen"); | ||
| 703 | return 0; | ||
| 704 | } | ||
| 695 | 705 | ||
| 696 | /* attach the sub-tree to live tree */ | 706 | /* attach the sub-tree to live tree */ |
| 697 | return attach_node_and_children(selftest_data_node); | 707 | return attach_node_and_children(selftest_data_node); |
| @@ -723,6 +733,18 @@ static void selftest_data_remove(void) | |||
| 723 | struct device_node *np; | 733 | struct device_node *np; |
| 724 | struct property *prop; | 734 | struct property *prop; |
| 725 | 735 | ||
| 736 | if (selftest_live_tree) { | ||
| 737 | of_node_put(of_aliases); | ||
| 738 | of_node_put(of_chosen); | ||
| 739 | of_aliases = NULL; | ||
| 740 | of_chosen = NULL; | ||
| 741 | for_each_child_of_node(of_allnodes, np) | ||
| 742 | detach_node_and_children(np); | ||
| 743 | __of_detach_node_sysfs(of_allnodes); | ||
| 744 | of_allnodes = NULL; | ||
| 745 | return; | ||
| 746 | } | ||
| 747 | |||
| 726 | while (last_node_index >= 0) { | 748 | while (last_node_index >= 0) { |
| 727 | if (nodes[last_node_index]) { | 749 | if (nodes[last_node_index]) { |
| 728 | np = of_find_node_by_path(nodes[last_node_index]->full_name); | 750 | np = of_find_node_by_path(nodes[last_node_index]->full_name); |
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index 2d8a4d05d78f..8922c376456a 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig | |||
| @@ -1,9 +1,18 @@ | |||
| 1 | menu "PCI host controller drivers" | 1 | menu "PCI host controller drivers" |
| 2 | depends on PCI | 2 | depends on PCI |
| 3 | 3 | ||
| 4 | config PCI_DRA7XX | ||
| 5 | bool "TI DRA7xx PCIe controller" | ||
| 6 | select PCIE_DW | ||
| 7 | depends on OF && HAS_IOMEM && TI_PIPE3 | ||
| 8 | help | ||
| 9 | Enables support for the PCIe controller in the DRA7xx SoC. There | ||
| 10 | are two instances of PCIe controller in DRA7xx. This controller can | ||
| 11 | act both as EP and RC. This reuses the Designware core. | ||
| 12 | |||
| 4 | config PCI_MVEBU | 13 | config PCI_MVEBU |
| 5 | bool "Marvell EBU PCIe controller" | 14 | bool "Marvell EBU PCIe controller" |
| 6 | depends on ARCH_MVEBU || ARCH_DOVE || ARCH_KIRKWOOD | 15 | depends on ARCH_MVEBU || ARCH_DOVE |
| 7 | depends on OF | 16 | depends on OF |
| 8 | 17 | ||
| 9 | config PCIE_DW | 18 | config PCIE_DW |
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile index 0daec7941aba..d0e88f114ff9 100644 --- a/drivers/pci/host/Makefile +++ b/drivers/pci/host/Makefile | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | obj-$(CONFIG_PCIE_DW) += pcie-designware.o | 1 | obj-$(CONFIG_PCIE_DW) += pcie-designware.o |
| 2 | obj-$(CONFIG_PCI_DRA7XX) += pci-dra7xx.o | ||
| 2 | obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o | 3 | obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o |
| 3 | obj-$(CONFIG_PCI_IMX6) += pci-imx6.o | 4 | obj-$(CONFIG_PCI_IMX6) += pci-imx6.o |
| 4 | obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o | 5 | obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o |
diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c new file mode 100644 index 000000000000..52b34fee07fd --- /dev/null +++ b/drivers/pci/host/pci-dra7xx.c | |||
| @@ -0,0 +1,458 @@ | |||
| 1 | /* | ||
| 2 | * pcie-dra7xx - PCIe controller driver for TI DRA7xx SoCs | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013-2014 Texas Instruments Incorporated - http://www.ti.com | ||
| 5 | * | ||
| 6 | * Authors: Kishon Vijay Abraham I <kishon@ti.com> | ||
| 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 version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/delay.h> | ||
| 14 | #include <linux/err.h> | ||
| 15 | #include <linux/interrupt.h> | ||
| 16 | #include <linux/irq.h> | ||
| 17 | #include <linux/irqdomain.h> | ||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/pci.h> | ||
| 21 | #include <linux/phy/phy.h> | ||
| 22 | #include <linux/platform_device.h> | ||
| 23 | #include <linux/pm_runtime.h> | ||
| 24 | #include <linux/resource.h> | ||
| 25 | #include <linux/types.h> | ||
| 26 | |||
| 27 | #include "pcie-designware.h" | ||
| 28 | |||
| 29 | /* PCIe controller wrapper DRA7XX configuration registers */ | ||
| 30 | |||
| 31 | #define PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN 0x0024 | ||
| 32 | #define PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MAIN 0x0028 | ||
| 33 | #define ERR_SYS BIT(0) | ||
| 34 | #define ERR_FATAL BIT(1) | ||
| 35 | #define ERR_NONFATAL BIT(2) | ||
| 36 | #define ERR_COR BIT(3) | ||
| 37 | #define ERR_AXI BIT(4) | ||
| 38 | #define ERR_ECRC BIT(5) | ||
| 39 | #define PME_TURN_OFF BIT(8) | ||
| 40 | #define PME_TO_ACK BIT(9) | ||
| 41 | #define PM_PME BIT(10) | ||
| 42 | #define LINK_REQ_RST BIT(11) | ||
| 43 | #define LINK_UP_EVT BIT(12) | ||
| 44 | #define CFG_BME_EVT BIT(13) | ||
| 45 | #define CFG_MSE_EVT BIT(14) | ||
| 46 | #define INTERRUPTS (ERR_SYS | ERR_FATAL | ERR_NONFATAL | ERR_COR | ERR_AXI | \ | ||
| 47 | ERR_ECRC | PME_TURN_OFF | PME_TO_ACK | PM_PME | \ | ||
| 48 | LINK_REQ_RST | LINK_UP_EVT | CFG_BME_EVT | CFG_MSE_EVT) | ||
| 49 | |||
| 50 | #define PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI 0x0034 | ||
| 51 | #define PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MSI 0x0038 | ||
| 52 | #define INTA BIT(0) | ||
| 53 | #define INTB BIT(1) | ||
| 54 | #define INTC BIT(2) | ||
| 55 | #define INTD BIT(3) | ||
| 56 | #define MSI BIT(4) | ||
| 57 | #define LEG_EP_INTERRUPTS (INTA | INTB | INTC | INTD) | ||
| 58 | |||
| 59 | #define PCIECTRL_DRA7XX_CONF_DEVICE_CMD 0x0104 | ||
| 60 | #define LTSSM_EN 0x1 | ||
| 61 | |||
| 62 | #define PCIECTRL_DRA7XX_CONF_PHY_CS 0x010C | ||
| 63 | #define LINK_UP BIT(16) | ||
| 64 | |||
| 65 | struct dra7xx_pcie { | ||
| 66 | void __iomem *base; | ||
| 67 | struct phy **phy; | ||
| 68 | int phy_count; | ||
| 69 | struct device *dev; | ||
| 70 | struct pcie_port pp; | ||
| 71 | }; | ||
| 72 | |||
| 73 | #define to_dra7xx_pcie(x) container_of((x), struct dra7xx_pcie, pp) | ||
| 74 | |||
| 75 | static inline u32 dra7xx_pcie_readl(struct dra7xx_pcie *pcie, u32 offset) | ||
| 76 | { | ||
| 77 | return readl(pcie->base + offset); | ||
| 78 | } | ||
| 79 | |||
| 80 | static inline void dra7xx_pcie_writel(struct dra7xx_pcie *pcie, u32 offset, | ||
| 81 | u32 value) | ||
| 82 | { | ||
| 83 | writel(value, pcie->base + offset); | ||
| 84 | } | ||
| 85 | |||
| 86 | static int dra7xx_pcie_link_up(struct pcie_port *pp) | ||
| 87 | { | ||
| 88 | struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp); | ||
| 89 | u32 reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_PHY_CS); | ||
| 90 | |||
| 91 | return !!(reg & LINK_UP); | ||
| 92 | } | ||
| 93 | |||
| 94 | static int dra7xx_pcie_establish_link(struct pcie_port *pp) | ||
| 95 | { | ||
| 96 | u32 reg; | ||
| 97 | unsigned int retries = 1000; | ||
| 98 | struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp); | ||
| 99 | |||
| 100 | if (dw_pcie_link_up(pp)) { | ||
| 101 | dev_err(pp->dev, "link is already up\n"); | ||
| 102 | return 0; | ||
| 103 | } | ||
| 104 | |||
| 105 | reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD); | ||
| 106 | reg |= LTSSM_EN; | ||
| 107 | dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD, reg); | ||
| 108 | |||
| 109 | while (retries--) { | ||
| 110 | reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_PHY_CS); | ||
| 111 | if (reg & LINK_UP) | ||
| 112 | break; | ||
| 113 | usleep_range(10, 20); | ||
| 114 | } | ||
| 115 | |||
| 116 | if (retries == 0) { | ||
| 117 | dev_err(pp->dev, "link is not up\n"); | ||
| 118 | return -ETIMEDOUT; | ||
| 119 | } | ||
| 120 | |||
| 121 | return 0; | ||
| 122 | } | ||
| 123 | |||
| 124 | static void dra7xx_pcie_enable_interrupts(struct pcie_port *pp) | ||
| 125 | { | ||
| 126 | struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp); | ||
| 127 | |||
| 128 | dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN, | ||
| 129 | ~INTERRUPTS); | ||
| 130 | dra7xx_pcie_writel(dra7xx, | ||
| 131 | PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MAIN, INTERRUPTS); | ||
| 132 | dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI, | ||
| 133 | ~LEG_EP_INTERRUPTS & ~MSI); | ||
| 134 | |||
| 135 | if (IS_ENABLED(CONFIG_PCI_MSI)) | ||
| 136 | dra7xx_pcie_writel(dra7xx, | ||
| 137 | PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MSI, MSI); | ||
| 138 | else | ||
| 139 | dra7xx_pcie_writel(dra7xx, | ||
| 140 | PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MSI, | ||
| 141 | LEG_EP_INTERRUPTS); | ||
| 142 | } | ||
| 143 | |||
| 144 | static void dra7xx_pcie_host_init(struct pcie_port *pp) | ||
| 145 | { | ||
| 146 | dw_pcie_setup_rc(pp); | ||
| 147 | dra7xx_pcie_establish_link(pp); | ||
| 148 | if (IS_ENABLED(CONFIG_PCI_MSI)) | ||
| 149 | dw_pcie_msi_init(pp); | ||
| 150 | dra7xx_pcie_enable_interrupts(pp); | ||
| 151 | } | ||
| 152 | |||
| 153 | static struct pcie_host_ops dra7xx_pcie_host_ops = { | ||
| 154 | .link_up = dra7xx_pcie_link_up, | ||
| 155 | .host_init = dra7xx_pcie_host_init, | ||
| 156 | }; | ||
| 157 | |||
| 158 | static int dra7xx_pcie_intx_map(struct irq_domain *domain, unsigned int irq, | ||
| 159 | irq_hw_number_t hwirq) | ||
| 160 | { | ||
| 161 | irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq); | ||
| 162 | irq_set_chip_data(irq, domain->host_data); | ||
| 163 | set_irq_flags(irq, IRQF_VALID); | ||
| 164 | |||
| 165 | return 0; | ||
| 166 | } | ||
| 167 | |||
| 168 | static const struct irq_domain_ops intx_domain_ops = { | ||
| 169 | .map = dra7xx_pcie_intx_map, | ||
| 170 | }; | ||
| 171 | |||
| 172 | static int dra7xx_pcie_init_irq_domain(struct pcie_port *pp) | ||
| 173 | { | ||
| 174 | struct device *dev = pp->dev; | ||
| 175 | struct device_node *node = dev->of_node; | ||
| 176 | struct device_node *pcie_intc_node = of_get_next_child(node, NULL); | ||
| 177 | |||
| 178 | if (!pcie_intc_node) { | ||
| 179 | dev_err(dev, "No PCIe Intc node found\n"); | ||
| 180 | return PTR_ERR(pcie_intc_node); | ||
| 181 | } | ||
| 182 | |||
| 183 | pp->irq_domain = irq_domain_add_linear(pcie_intc_node, 4, | ||
| 184 | &intx_domain_ops, pp); | ||
| 185 | if (!pp->irq_domain) { | ||
| 186 | dev_err(dev, "Failed to get a INTx IRQ domain\n"); | ||
| 187 | return PTR_ERR(pp->irq_domain); | ||
| 188 | } | ||
| 189 | |||
| 190 | return 0; | ||
| 191 | } | ||
| 192 | |||
| 193 | static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg) | ||
| 194 | { | ||
| 195 | struct pcie_port *pp = arg; | ||
| 196 | struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp); | ||
| 197 | u32 reg; | ||
| 198 | |||
| 199 | reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI); | ||
| 200 | |||
| 201 | switch (reg) { | ||
| 202 | case MSI: | ||
| 203 | dw_handle_msi_irq(pp); | ||
| 204 | break; | ||
| 205 | case INTA: | ||
| 206 | case INTB: | ||
| 207 | case INTC: | ||
| 208 | case INTD: | ||
| 209 | generic_handle_irq(irq_find_mapping(pp->irq_domain, ffs(reg))); | ||
| 210 | break; | ||
| 211 | } | ||
| 212 | |||
| 213 | dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI, reg); | ||
| 214 | |||
| 215 | return IRQ_HANDLED; | ||
| 216 | } | ||
| 217 | |||
| 218 | |||
| 219 | static irqreturn_t dra7xx_pcie_irq_handler(int irq, void *arg) | ||
| 220 | { | ||
| 221 | struct dra7xx_pcie *dra7xx = arg; | ||
| 222 | u32 reg; | ||
| 223 | |||
| 224 | reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN); | ||
| 225 | |||
| 226 | if (reg & ERR_SYS) | ||
| 227 | dev_dbg(dra7xx->dev, "System Error\n"); | ||
| 228 | |||
| 229 | if (reg & ERR_FATAL) | ||
| 230 | dev_dbg(dra7xx->dev, "Fatal Error\n"); | ||
| 231 | |||
| 232 | if (reg & ERR_NONFATAL) | ||
| 233 | dev_dbg(dra7xx->dev, "Non Fatal Error\n"); | ||
| 234 | |||
| 235 | if (reg & ERR_COR) | ||
| 236 | dev_dbg(dra7xx->dev, "Correctable Error\n"); | ||
| 237 | |||
| 238 | if (reg & ERR_AXI) | ||
| 239 | dev_dbg(dra7xx->dev, "AXI tag lookup fatal Error\n"); | ||
| 240 | |||
| 241 | if (reg & ERR_ECRC) | ||
| 242 | dev_dbg(dra7xx->dev, "ECRC Error\n"); | ||
| 243 | |||
| 244 | if (reg & PME_TURN_OFF) | ||
| 245 | dev_dbg(dra7xx->dev, | ||
| 246 | "Power Management Event Turn-Off message received\n"); | ||
| 247 | |||
| 248 | if (reg & PME_TO_ACK) | ||
| 249 | dev_dbg(dra7xx->dev, | ||
| 250 | "Power Management Turn-Off Ack message received\n"); | ||
| 251 | |||
| 252 | if (reg & PM_PME) | ||
| 253 | dev_dbg(dra7xx->dev, | ||
| 254 | "PM Power Management Event message received\n"); | ||
| 255 | |||
| 256 | if (reg & LINK_REQ_RST) | ||
| 257 | dev_dbg(dra7xx->dev, "Link Request Reset\n"); | ||
| 258 | |||
| 259 | if (reg & LINK_UP_EVT) | ||
| 260 | dev_dbg(dra7xx->dev, "Link-up state change\n"); | ||
| 261 | |||
| 262 | if (reg & CFG_BME_EVT) | ||
| 263 | dev_dbg(dra7xx->dev, "CFG 'Bus Master Enable' change\n"); | ||
| 264 | |||
| 265 | if (reg & CFG_MSE_EVT) | ||
| 266 | dev_dbg(dra7xx->dev, "CFG 'Memory Space Enable' change\n"); | ||
| 267 | |||
| 268 | dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN, reg); | ||
| 269 | |||
| 270 | return IRQ_HANDLED; | ||
| 271 | } | ||
| 272 | |||
| 273 | static int add_pcie_port(struct dra7xx_pcie *dra7xx, | ||
| 274 | struct platform_device *pdev) | ||
| 275 | { | ||
| 276 | int ret; | ||
| 277 | struct pcie_port *pp; | ||
| 278 | struct resource *res; | ||
| 279 | struct device *dev = &pdev->dev; | ||
| 280 | |||
| 281 | pp = &dra7xx->pp; | ||
| 282 | pp->dev = dev; | ||
| 283 | pp->ops = &dra7xx_pcie_host_ops; | ||
| 284 | |||
| 285 | pp->irq = platform_get_irq(pdev, 1); | ||
| 286 | if (pp->irq < 0) { | ||
| 287 | dev_err(dev, "missing IRQ resource\n"); | ||
| 288 | return -EINVAL; | ||
| 289 | } | ||
| 290 | |||
| 291 | ret = devm_request_irq(&pdev->dev, pp->irq, | ||
| 292 | dra7xx_pcie_msi_irq_handler, IRQF_SHARED, | ||
| 293 | "dra7-pcie-msi", pp); | ||
| 294 | if (ret) { | ||
| 295 | dev_err(&pdev->dev, "failed to request irq\n"); | ||
| 296 | return ret; | ||
| 297 | } | ||
| 298 | |||
| 299 | if (!IS_ENABLED(CONFIG_PCI_MSI)) { | ||
| 300 | ret = dra7xx_pcie_init_irq_domain(pp); | ||
| 301 | if (ret < 0) | ||
| 302 | return ret; | ||
| 303 | } | ||
| 304 | |||
| 305 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rc_dbics"); | ||
| 306 | pp->dbi_base = devm_ioremap(dev, res->start, resource_size(res)); | ||
| 307 | if (!pp->dbi_base) | ||
| 308 | return -ENOMEM; | ||
| 309 | |||
| 310 | ret = dw_pcie_host_init(pp); | ||
| 311 | if (ret) { | ||
| 312 | dev_err(dra7xx->dev, "failed to initialize host\n"); | ||
| 313 | return ret; | ||
| 314 | } | ||
| 315 | |||
| 316 | return 0; | ||
| 317 | } | ||
| 318 | |||
| 319 | static int __init dra7xx_pcie_probe(struct platform_device *pdev) | ||
| 320 | { | ||
| 321 | u32 reg; | ||
| 322 | int ret; | ||
| 323 | int irq; | ||
| 324 | int i; | ||
| 325 | int phy_count; | ||
| 326 | struct phy **phy; | ||
| 327 | void __iomem *base; | ||
| 328 | struct resource *res; | ||
| 329 | struct dra7xx_pcie *dra7xx; | ||
| 330 | struct device *dev = &pdev->dev; | ||
| 331 | struct device_node *np = dev->of_node; | ||
| 332 | char name[10]; | ||
| 333 | |||
| 334 | dra7xx = devm_kzalloc(dev, sizeof(*dra7xx), GFP_KERNEL); | ||
| 335 | if (!dra7xx) | ||
| 336 | return -ENOMEM; | ||
| 337 | |||
| 338 | irq = platform_get_irq(pdev, 0); | ||
| 339 | if (irq < 0) { | ||
| 340 | dev_err(dev, "missing IRQ resource\n"); | ||
| 341 | return -EINVAL; | ||
| 342 | } | ||
| 343 | |||
| 344 | ret = devm_request_irq(dev, irq, dra7xx_pcie_irq_handler, | ||
| 345 | IRQF_SHARED, "dra7xx-pcie-main", dra7xx); | ||
| 346 | if (ret) { | ||
| 347 | dev_err(dev, "failed to request irq\n"); | ||
| 348 | return ret; | ||
| 349 | } | ||
| 350 | |||
| 351 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ti_conf"); | ||
| 352 | base = devm_ioremap_nocache(dev, res->start, resource_size(res)); | ||
| 353 | if (!base) | ||
| 354 | return -ENOMEM; | ||
| 355 | |||
| 356 | phy_count = of_property_count_strings(np, "phy-names"); | ||
| 357 | if (phy_count < 0) { | ||
| 358 | dev_err(dev, "unable to find the strings\n"); | ||
| 359 | return phy_count; | ||
| 360 | } | ||
| 361 | |||
| 362 | phy = devm_kzalloc(dev, sizeof(*phy) * phy_count, GFP_KERNEL); | ||
| 363 | if (!phy) | ||
| 364 | return -ENOMEM; | ||
| 365 | |||
| 366 | for (i = 0; i < phy_count; i++) { | ||
| 367 | snprintf(name, sizeof(name), "pcie-phy%d", i); | ||
| 368 | phy[i] = devm_phy_get(dev, name); | ||
| 369 | if (IS_ERR(phy[i])) | ||
| 370 | return PTR_ERR(phy[i]); | ||
| 371 | |||
| 372 | ret = phy_init(phy[i]); | ||
| 373 | if (ret < 0) | ||
| 374 | goto err_phy; | ||
| 375 | |||
| 376 | ret = phy_power_on(phy[i]); | ||
| 377 | if (ret < 0) { | ||
| 378 | phy_exit(phy[i]); | ||
| 379 | goto err_phy; | ||
| 380 | } | ||
| 381 | } | ||
| 382 | |||
| 383 | dra7xx->base = base; | ||
| 384 | dra7xx->phy = phy; | ||
| 385 | dra7xx->dev = dev; | ||
| 386 | dra7xx->phy_count = phy_count; | ||
| 387 | |||
| 388 | pm_runtime_enable(dev); | ||
| 389 | ret = pm_runtime_get_sync(dev); | ||
| 390 | if (IS_ERR_VALUE(ret)) { | ||
| 391 | dev_err(dev, "pm_runtime_get_sync failed\n"); | ||
| 392 | goto err_phy; | ||
| 393 | } | ||
| 394 | |||
| 395 | reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD); | ||
| 396 | reg &= ~LTSSM_EN; | ||
| 397 | dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD, reg); | ||
| 398 | |||
| 399 | platform_set_drvdata(pdev, dra7xx); | ||
| 400 | |||
| 401 | ret = add_pcie_port(dra7xx, pdev); | ||
| 402 | if (ret < 0) | ||
| 403 | goto err_add_port; | ||
| 404 | |||
| 405 | return 0; | ||
| 406 | |||
| 407 | err_add_port: | ||
| 408 | pm_runtime_put(dev); | ||
| 409 | pm_runtime_disable(dev); | ||
| 410 | |||
| 411 | err_phy: | ||
| 412 | while (--i >= 0) { | ||
| 413 | phy_power_off(phy[i]); | ||
| 414 | phy_exit(phy[i]); | ||
| 415 | } | ||
| 416 | |||
| 417 | return ret; | ||
| 418 | } | ||
| 419 | |||
| 420 | static int __exit dra7xx_pcie_remove(struct platform_device *pdev) | ||
| 421 | { | ||
| 422 | struct dra7xx_pcie *dra7xx = platform_get_drvdata(pdev); | ||
| 423 | struct pcie_port *pp = &dra7xx->pp; | ||
| 424 | struct device *dev = &pdev->dev; | ||
| 425 | int count = dra7xx->phy_count; | ||
| 426 | |||
| 427 | if (pp->irq_domain) | ||
| 428 | irq_domain_remove(pp->irq_domain); | ||
| 429 | pm_runtime_put(dev); | ||
| 430 | pm_runtime_disable(dev); | ||
| 431 | while (count--) { | ||
| 432 | phy_power_off(dra7xx->phy[count]); | ||
| 433 | phy_exit(dra7xx->phy[count]); | ||
| 434 | } | ||
| 435 | |||
| 436 | return 0; | ||
| 437 | } | ||
| 438 | |||
| 439 | static const struct of_device_id of_dra7xx_pcie_match[] = { | ||
| 440 | { .compatible = "ti,dra7-pcie", }, | ||
| 441 | {}, | ||
| 442 | }; | ||
| 443 | MODULE_DEVICE_TABLE(of, of_dra7xx_pcie_match); | ||
| 444 | |||
| 445 | static struct platform_driver dra7xx_pcie_driver = { | ||
| 446 | .remove = __exit_p(dra7xx_pcie_remove), | ||
| 447 | .driver = { | ||
| 448 | .name = "dra7-pcie", | ||
| 449 | .owner = THIS_MODULE, | ||
| 450 | .of_match_table = of_dra7xx_pcie_match, | ||
| 451 | }, | ||
| 452 | }; | ||
| 453 | |||
| 454 | module_platform_driver_probe(dra7xx_pcie_driver, dra7xx_pcie_probe); | ||
| 455 | |||
| 456 | MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>"); | ||
| 457 | MODULE_DESCRIPTION("TI PCIe controller driver"); | ||
| 458 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index abd65784618d..0fb0fdb223d5 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | */ | 25 | */ |
| 26 | 26 | ||
| 27 | #include <linux/clk.h> | 27 | #include <linux/clk.h> |
| 28 | #include <linux/debugfs.h> | ||
| 28 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
| 29 | #include <linux/export.h> | 30 | #include <linux/export.h> |
| 30 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
| @@ -276,6 +277,7 @@ struct tegra_pcie { | |||
| 276 | unsigned int num_supplies; | 277 | unsigned int num_supplies; |
| 277 | 278 | ||
| 278 | const struct tegra_pcie_soc_data *soc_data; | 279 | const struct tegra_pcie_soc_data *soc_data; |
| 280 | struct dentry *debugfs; | ||
| 279 | }; | 281 | }; |
| 280 | 282 | ||
| 281 | struct tegra_pcie_port { | 283 | struct tegra_pcie_port { |
| @@ -1739,6 +1741,115 @@ static const struct of_device_id tegra_pcie_of_match[] = { | |||
| 1739 | }; | 1741 | }; |
| 1740 | MODULE_DEVICE_TABLE(of, tegra_pcie_of_match); | 1742 | MODULE_DEVICE_TABLE(of, tegra_pcie_of_match); |
| 1741 | 1743 | ||
| 1744 | static void *tegra_pcie_ports_seq_start(struct seq_file *s, loff_t *pos) | ||
| 1745 | { | ||
| 1746 | struct tegra_pcie *pcie = s->private; | ||
| 1747 | |||
| 1748 | if (list_empty(&pcie->ports)) | ||
| 1749 | return NULL; | ||
| 1750 | |||
| 1751 | seq_printf(s, "Index Status\n"); | ||
| 1752 | |||
| 1753 | return seq_list_start(&pcie->ports, *pos); | ||
| 1754 | } | ||
| 1755 | |||
| 1756 | static void *tegra_pcie_ports_seq_next(struct seq_file *s, void *v, loff_t *pos) | ||
| 1757 | { | ||
| 1758 | struct tegra_pcie *pcie = s->private; | ||
| 1759 | |||
| 1760 | return seq_list_next(v, &pcie->ports, pos); | ||
| 1761 | } | ||
| 1762 | |||
| 1763 | static void tegra_pcie_ports_seq_stop(struct seq_file *s, void *v) | ||
| 1764 | { | ||
| 1765 | } | ||
| 1766 | |||
| 1767 | static int tegra_pcie_ports_seq_show(struct seq_file *s, void *v) | ||
| 1768 | { | ||
| 1769 | bool up = false, active = false; | ||
| 1770 | struct tegra_pcie_port *port; | ||
| 1771 | unsigned int value; | ||
| 1772 | |||
| 1773 | port = list_entry(v, struct tegra_pcie_port, list); | ||
| 1774 | |||
| 1775 | value = readl(port->base + RP_VEND_XP); | ||
| 1776 | |||
| 1777 | if (value & RP_VEND_XP_DL_UP) | ||
| 1778 | up = true; | ||
| 1779 | |||
| 1780 | value = readl(port->base + RP_LINK_CONTROL_STATUS); | ||
| 1781 | |||
| 1782 | if (value & RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE) | ||
| 1783 | active = true; | ||
| 1784 | |||
| 1785 | seq_printf(s, "%2u ", port->index); | ||
| 1786 | |||
| 1787 | if (up) | ||
| 1788 | seq_printf(s, "up"); | ||
| 1789 | |||
| 1790 | if (active) { | ||
| 1791 | if (up) | ||
| 1792 | seq_printf(s, ", "); | ||
| 1793 | |||
| 1794 | seq_printf(s, "active"); | ||
| 1795 | } | ||
| 1796 | |||
| 1797 | seq_printf(s, "\n"); | ||
| 1798 | return 0; | ||
| 1799 | } | ||
| 1800 | |||
| 1801 | static const struct seq_operations tegra_pcie_ports_seq_ops = { | ||
| 1802 | .start = tegra_pcie_ports_seq_start, | ||
| 1803 | .next = tegra_pcie_ports_seq_next, | ||
| 1804 | .stop = tegra_pcie_ports_seq_stop, | ||
| 1805 | .show = tegra_pcie_ports_seq_show, | ||
| 1806 | }; | ||
| 1807 | |||
| 1808 | static int tegra_pcie_ports_open(struct inode *inode, struct file *file) | ||
| 1809 | { | ||
| 1810 | struct tegra_pcie *pcie = inode->i_private; | ||
| 1811 | struct seq_file *s; | ||
| 1812 | int err; | ||
| 1813 | |||
| 1814 | err = seq_open(file, &tegra_pcie_ports_seq_ops); | ||
| 1815 | if (err) | ||
| 1816 | return err; | ||
| 1817 | |||
| 1818 | s = file->private_data; | ||
| 1819 | s->private = pcie; | ||
| 1820 | |||
| 1821 | return 0; | ||
| 1822 | } | ||
| 1823 | |||
| 1824 | static const struct file_operations tegra_pcie_ports_ops = { | ||
| 1825 | .owner = THIS_MODULE, | ||
| 1826 | .open = tegra_pcie_ports_open, | ||
| 1827 | .read = seq_read, | ||
| 1828 | .llseek = seq_lseek, | ||
| 1829 | .release = seq_release, | ||
| 1830 | }; | ||
| 1831 | |||
| 1832 | static int tegra_pcie_debugfs_init(struct tegra_pcie *pcie) | ||
| 1833 | { | ||
| 1834 | struct dentry *file; | ||
| 1835 | |||
| 1836 | pcie->debugfs = debugfs_create_dir("pcie", NULL); | ||
| 1837 | if (!pcie->debugfs) | ||
| 1838 | return -ENOMEM; | ||
| 1839 | |||
| 1840 | file = debugfs_create_file("ports", S_IFREG | S_IRUGO, pcie->debugfs, | ||
| 1841 | pcie, &tegra_pcie_ports_ops); | ||
| 1842 | if (!file) | ||
| 1843 | goto remove; | ||
| 1844 | |||
| 1845 | return 0; | ||
| 1846 | |||
| 1847 | remove: | ||
| 1848 | debugfs_remove_recursive(pcie->debugfs); | ||
| 1849 | pcie->debugfs = NULL; | ||
| 1850 | return -ENOMEM; | ||
| 1851 | } | ||
| 1852 | |||
| 1742 | static int tegra_pcie_probe(struct platform_device *pdev) | 1853 | static int tegra_pcie_probe(struct platform_device *pdev) |
| 1743 | { | 1854 | { |
| 1744 | const struct of_device_id *match; | 1855 | const struct of_device_id *match; |
| @@ -1793,6 +1904,13 @@ static int tegra_pcie_probe(struct platform_device *pdev) | |||
| 1793 | goto disable_msi; | 1904 | goto disable_msi; |
| 1794 | } | 1905 | } |
| 1795 | 1906 | ||
| 1907 | if (IS_ENABLED(CONFIG_DEBUG_FS)) { | ||
| 1908 | err = tegra_pcie_debugfs_init(pcie); | ||
| 1909 | if (err < 0) | ||
| 1910 | dev_err(&pdev->dev, "failed to setup debugfs: %d\n", | ||
| 1911 | err); | ||
| 1912 | } | ||
| 1913 | |||
| 1796 | platform_set_drvdata(pdev, pcie); | 1914 | platform_set_drvdata(pdev, pcie); |
| 1797 | return 0; | 1915 | return 0; |
| 1798 | 1916 | ||
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index 1eaf4df3618a..52bd3a143563 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/of_pci.h> | 20 | #include <linux/of_pci.h> |
| 21 | #include <linux/pci.h> | 21 | #include <linux/pci.h> |
| 22 | #include <linux/pci_regs.h> | 22 | #include <linux/pci_regs.h> |
| 23 | #include <linux/platform_device.h> | ||
| 23 | #include <linux/types.h> | 24 | #include <linux/types.h> |
| 24 | 25 | ||
| 25 | #include "pcie-designware.h" | 26 | #include "pcie-designware.h" |
| @@ -217,27 +218,47 @@ static int find_valid_pos0(struct pcie_port *pp, int msgvec, int pos, int *pos0) | |||
| 217 | return 0; | 218 | return 0; |
| 218 | } | 219 | } |
| 219 | 220 | ||
| 221 | static void dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq) | ||
| 222 | { | ||
| 223 | unsigned int res, bit, val; | ||
| 224 | |||
| 225 | res = (irq / 32) * 12; | ||
| 226 | bit = irq % 32; | ||
| 227 | dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val); | ||
| 228 | val &= ~(1 << bit); | ||
| 229 | dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val); | ||
| 230 | } | ||
| 231 | |||
| 220 | static void clear_irq_range(struct pcie_port *pp, unsigned int irq_base, | 232 | static void clear_irq_range(struct pcie_port *pp, unsigned int irq_base, |
| 221 | unsigned int nvec, unsigned int pos) | 233 | unsigned int nvec, unsigned int pos) |
| 222 | { | 234 | { |
| 223 | unsigned int i, res, bit, val; | 235 | unsigned int i; |
| 224 | 236 | ||
| 225 | for (i = 0; i < nvec; i++) { | 237 | for (i = 0; i < nvec; i++) { |
| 226 | irq_set_msi_desc_off(irq_base, i, NULL); | 238 | irq_set_msi_desc_off(irq_base, i, NULL); |
| 227 | clear_bit(pos + i, pp->msi_irq_in_use); | 239 | clear_bit(pos + i, pp->msi_irq_in_use); |
| 228 | /* Disable corresponding interrupt on MSI controller */ | 240 | /* Disable corresponding interrupt on MSI controller */ |
| 229 | res = ((pos + i) / 32) * 12; | 241 | if (pp->ops->msi_clear_irq) |
| 230 | bit = (pos + i) % 32; | 242 | pp->ops->msi_clear_irq(pp, pos + i); |
| 231 | dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val); | 243 | else |
| 232 | val &= ~(1 << bit); | 244 | dw_pcie_msi_clear_irq(pp, pos + i); |
| 233 | dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val); | ||
| 234 | } | 245 | } |
| 235 | } | 246 | } |
| 236 | 247 | ||
| 248 | static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq) | ||
| 249 | { | ||
| 250 | unsigned int res, bit, val; | ||
| 251 | |||
| 252 | res = (irq / 32) * 12; | ||
| 253 | bit = irq % 32; | ||
| 254 | dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val); | ||
| 255 | val |= 1 << bit; | ||
| 256 | dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val); | ||
| 257 | } | ||
| 258 | |||
| 237 | static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos) | 259 | static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos) |
| 238 | { | 260 | { |
| 239 | int res, bit, irq, pos0, pos1, i; | 261 | int irq, pos0, pos1, i; |
| 240 | u32 val; | ||
| 241 | struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata); | 262 | struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata); |
| 242 | 263 | ||
| 243 | if (!pp) { | 264 | if (!pp) { |
| @@ -281,11 +302,10 @@ static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos) | |||
| 281 | } | 302 | } |
| 282 | set_bit(pos0 + i, pp->msi_irq_in_use); | 303 | set_bit(pos0 + i, pp->msi_irq_in_use); |
| 283 | /*Enable corresponding interrupt in MSI interrupt controller */ | 304 | /*Enable corresponding interrupt in MSI interrupt controller */ |
| 284 | res = ((pos0 + i) / 32) * 12; | 305 | if (pp->ops->msi_set_irq) |
| 285 | bit = (pos0 + i) % 32; | 306 | pp->ops->msi_set_irq(pp, pos0 + i); |
| 286 | dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val); | 307 | else |
| 287 | val |= 1 << bit; | 308 | dw_pcie_msi_set_irq(pp, pos0 + i); |
| 288 | dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val); | ||
| 289 | } | 309 | } |
| 290 | 310 | ||
| 291 | *pos = pos0; | 311 | *pos = pos0; |
| @@ -353,7 +373,10 @@ static int dw_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev, | |||
| 353 | */ | 373 | */ |
| 354 | desc->msi_attrib.multiple = msgvec; | 374 | desc->msi_attrib.multiple = msgvec; |
| 355 | 375 | ||
| 356 | msg.address_lo = virt_to_phys((void *)pp->msi_data); | 376 | if (pp->ops->get_msi_data) |
| 377 | msg.address_lo = pp->ops->get_msi_data(pp); | ||
| 378 | else | ||
| 379 | msg.address_lo = virt_to_phys((void *)pp->msi_data); | ||
| 357 | msg.address_hi = 0x0; | 380 | msg.address_hi = 0x0; |
| 358 | msg.data = pos; | 381 | msg.data = pos; |
| 359 | write_msi_msg(irq, &msg); | 382 | write_msi_msg(irq, &msg); |
| @@ -396,10 +419,35 @@ static const struct irq_domain_ops msi_domain_ops = { | |||
| 396 | int __init dw_pcie_host_init(struct pcie_port *pp) | 419 | int __init dw_pcie_host_init(struct pcie_port *pp) |
| 397 | { | 420 | { |
| 398 | struct device_node *np = pp->dev->of_node; | 421 | struct device_node *np = pp->dev->of_node; |
| 422 | struct platform_device *pdev = to_platform_device(pp->dev); | ||
| 399 | struct of_pci_range range; | 423 | struct of_pci_range range; |
| 400 | struct of_pci_range_parser parser; | 424 | struct of_pci_range_parser parser; |
| 401 | u32 val; | 425 | struct resource *cfg_res; |
| 402 | int i; | 426 | u32 val, na, ns; |
| 427 | const __be32 *addrp; | ||
| 428 | int i, index; | ||
| 429 | |||
| 430 | /* Find the address cell size and the number of cells in order to get | ||
| 431 | * the untranslated address. | ||
| 432 | */ | ||
| 433 | of_property_read_u32(np, "#address-cells", &na); | ||
| 434 | ns = of_n_size_cells(np); | ||
| 435 | |||
| 436 | cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config"); | ||
| 437 | if (cfg_res) { | ||
| 438 | pp->config.cfg0_size = resource_size(cfg_res)/2; | ||
| 439 | pp->config.cfg1_size = resource_size(cfg_res)/2; | ||
| 440 | pp->cfg0_base = cfg_res->start; | ||
| 441 | pp->cfg1_base = cfg_res->start + pp->config.cfg0_size; | ||
| 442 | |||
| 443 | /* Find the untranslated configuration space address */ | ||
| 444 | index = of_property_match_string(np, "reg-names", "config"); | ||
| 445 | addrp = of_get_address(np, index, false, false); | ||
| 446 | pp->cfg0_mod_base = of_read_number(addrp, ns); | ||
| 447 | pp->cfg1_mod_base = pp->cfg0_mod_base + pp->config.cfg0_size; | ||
| 448 | } else { | ||
| 449 | dev_err(pp->dev, "missing *config* reg space\n"); | ||
| 450 | } | ||
| 403 | 451 | ||
| 404 | if (of_pci_range_parser_init(&parser, np)) { | 452 | if (of_pci_range_parser_init(&parser, np)) { |
| 405 | dev_err(pp->dev, "missing ranges property\n"); | 453 | dev_err(pp->dev, "missing ranges property\n"); |
| @@ -422,17 +470,33 @@ int __init dw_pcie_host_init(struct pcie_port *pp) | |||
| 422 | pp->config.io_size = resource_size(&pp->io); | 470 | pp->config.io_size = resource_size(&pp->io); |
| 423 | pp->config.io_bus_addr = range.pci_addr; | 471 | pp->config.io_bus_addr = range.pci_addr; |
| 424 | pp->io_base = range.cpu_addr; | 472 | pp->io_base = range.cpu_addr; |
| 473 | |||
| 474 | /* Find the untranslated IO space address */ | ||
| 475 | pp->io_mod_base = of_read_number(parser.range - | ||
| 476 | parser.np + na, ns); | ||
| 425 | } | 477 | } |
| 426 | if (restype == IORESOURCE_MEM) { | 478 | if (restype == IORESOURCE_MEM) { |
| 427 | of_pci_range_to_resource(&range, np, &pp->mem); | 479 | of_pci_range_to_resource(&range, np, &pp->mem); |
| 428 | pp->mem.name = "MEM"; | 480 | pp->mem.name = "MEM"; |
| 429 | pp->config.mem_size = resource_size(&pp->mem); | 481 | pp->config.mem_size = resource_size(&pp->mem); |
| 430 | pp->config.mem_bus_addr = range.pci_addr; | 482 | pp->config.mem_bus_addr = range.pci_addr; |
| 483 | |||
| 484 | /* Find the untranslated MEM space address */ | ||
| 485 | pp->mem_mod_base = of_read_number(parser.range - | ||
| 486 | parser.np + na, ns); | ||
| 431 | } | 487 | } |
| 432 | if (restype == 0) { | 488 | if (restype == 0) { |
| 433 | of_pci_range_to_resource(&range, np, &pp->cfg); | 489 | of_pci_range_to_resource(&range, np, &pp->cfg); |
| 434 | pp->config.cfg0_size = resource_size(&pp->cfg)/2; | 490 | pp->config.cfg0_size = resource_size(&pp->cfg)/2; |
| 435 | pp->config.cfg1_size = resource_size(&pp->cfg)/2; | 491 | pp->config.cfg1_size = resource_size(&pp->cfg)/2; |
| 492 | pp->cfg0_base = pp->cfg.start; | ||
| 493 | pp->cfg1_base = pp->cfg.start + pp->config.cfg0_size; | ||
| 494 | |||
| 495 | /* Find the untranslated configuration space address */ | ||
| 496 | pp->cfg0_mod_base = of_read_number(parser.range - | ||
| 497 | parser.np + na, ns); | ||
| 498 | pp->cfg1_mod_base = pp->cfg0_mod_base + | ||
| 499 | pp->config.cfg0_size; | ||
| 436 | } | 500 | } |
| 437 | } | 501 | } |
| 438 | 502 | ||
| @@ -445,8 +509,6 @@ int __init dw_pcie_host_init(struct pcie_port *pp) | |||
| 445 | } | 509 | } |
| 446 | } | 510 | } |
| 447 | 511 | ||
| 448 | pp->cfg0_base = pp->cfg.start; | ||
| 449 | pp->cfg1_base = pp->cfg.start + pp->config.cfg0_size; | ||
| 450 | pp->mem_base = pp->mem.start; | 512 | pp->mem_base = pp->mem.start; |
| 451 | 513 | ||
| 452 | pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base, | 514 | pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base, |
| @@ -509,9 +571,9 @@ static void dw_pcie_prog_viewport_cfg0(struct pcie_port *pp, u32 busdev) | |||
| 509 | /* Program viewport 0 : OUTBOUND : CFG0 */ | 571 | /* Program viewport 0 : OUTBOUND : CFG0 */ |
| 510 | dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0, | 572 | dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0, |
| 511 | PCIE_ATU_VIEWPORT); | 573 | PCIE_ATU_VIEWPORT); |
| 512 | dw_pcie_writel_rc(pp, pp->cfg0_base, PCIE_ATU_LOWER_BASE); | 574 | dw_pcie_writel_rc(pp, pp->cfg0_mod_base, PCIE_ATU_LOWER_BASE); |
| 513 | dw_pcie_writel_rc(pp, (pp->cfg0_base >> 32), PCIE_ATU_UPPER_BASE); | 575 | dw_pcie_writel_rc(pp, (pp->cfg0_mod_base >> 32), PCIE_ATU_UPPER_BASE); |
| 514 | dw_pcie_writel_rc(pp, pp->cfg0_base + pp->config.cfg0_size - 1, | 576 | dw_pcie_writel_rc(pp, pp->cfg0_mod_base + pp->config.cfg0_size - 1, |
| 515 | PCIE_ATU_LIMIT); | 577 | PCIE_ATU_LIMIT); |
| 516 | dw_pcie_writel_rc(pp, busdev, PCIE_ATU_LOWER_TARGET); | 578 | dw_pcie_writel_rc(pp, busdev, PCIE_ATU_LOWER_TARGET); |
| 517 | dw_pcie_writel_rc(pp, 0, PCIE_ATU_UPPER_TARGET); | 579 | dw_pcie_writel_rc(pp, 0, PCIE_ATU_UPPER_TARGET); |
| @@ -525,9 +587,9 @@ static void dw_pcie_prog_viewport_cfg1(struct pcie_port *pp, u32 busdev) | |||
| 525 | dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1, | 587 | dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1, |
| 526 | PCIE_ATU_VIEWPORT); | 588 | PCIE_ATU_VIEWPORT); |
| 527 | dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_CFG1, PCIE_ATU_CR1); | 589 | dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_CFG1, PCIE_ATU_CR1); |
| 528 | dw_pcie_writel_rc(pp, pp->cfg1_base, PCIE_ATU_LOWER_BASE); | 590 | dw_pcie_writel_rc(pp, pp->cfg1_mod_base, PCIE_ATU_LOWER_BASE); |
| 529 | dw_pcie_writel_rc(pp, (pp->cfg1_base >> 32), PCIE_ATU_UPPER_BASE); | 591 | dw_pcie_writel_rc(pp, (pp->cfg1_mod_base >> 32), PCIE_ATU_UPPER_BASE); |
| 530 | dw_pcie_writel_rc(pp, pp->cfg1_base + pp->config.cfg1_size - 1, | 592 | dw_pcie_writel_rc(pp, pp->cfg1_mod_base + pp->config.cfg1_size - 1, |
| 531 | PCIE_ATU_LIMIT); | 593 | PCIE_ATU_LIMIT); |
| 532 | dw_pcie_writel_rc(pp, busdev, PCIE_ATU_LOWER_TARGET); | 594 | dw_pcie_writel_rc(pp, busdev, PCIE_ATU_LOWER_TARGET); |
| 533 | dw_pcie_writel_rc(pp, 0, PCIE_ATU_UPPER_TARGET); | 595 | dw_pcie_writel_rc(pp, 0, PCIE_ATU_UPPER_TARGET); |
| @@ -540,9 +602,9 @@ static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp) | |||
| 540 | dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0, | 602 | dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0, |
| 541 | PCIE_ATU_VIEWPORT); | 603 | PCIE_ATU_VIEWPORT); |
| 542 | dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_MEM, PCIE_ATU_CR1); | 604 | dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_MEM, PCIE_ATU_CR1); |
| 543 | dw_pcie_writel_rc(pp, pp->mem_base, PCIE_ATU_LOWER_BASE); | 605 | dw_pcie_writel_rc(pp, pp->mem_mod_base, PCIE_ATU_LOWER_BASE); |
| 544 | dw_pcie_writel_rc(pp, (pp->mem_base >> 32), PCIE_ATU_UPPER_BASE); | 606 | dw_pcie_writel_rc(pp, (pp->mem_mod_base >> 32), PCIE_ATU_UPPER_BASE); |
| 545 | dw_pcie_writel_rc(pp, pp->mem_base + pp->config.mem_size - 1, | 607 | dw_pcie_writel_rc(pp, pp->mem_mod_base + pp->config.mem_size - 1, |
| 546 | PCIE_ATU_LIMIT); | 608 | PCIE_ATU_LIMIT); |
| 547 | dw_pcie_writel_rc(pp, pp->config.mem_bus_addr, PCIE_ATU_LOWER_TARGET); | 609 | dw_pcie_writel_rc(pp, pp->config.mem_bus_addr, PCIE_ATU_LOWER_TARGET); |
| 548 | dw_pcie_writel_rc(pp, upper_32_bits(pp->config.mem_bus_addr), | 610 | dw_pcie_writel_rc(pp, upper_32_bits(pp->config.mem_bus_addr), |
| @@ -556,9 +618,9 @@ static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp) | |||
| 556 | dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1, | 618 | dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1, |
| 557 | PCIE_ATU_VIEWPORT); | 619 | PCIE_ATU_VIEWPORT); |
| 558 | dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_IO, PCIE_ATU_CR1); | 620 | dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_IO, PCIE_ATU_CR1); |
| 559 | dw_pcie_writel_rc(pp, pp->io_base, PCIE_ATU_LOWER_BASE); | 621 | dw_pcie_writel_rc(pp, pp->io_mod_base, PCIE_ATU_LOWER_BASE); |
| 560 | dw_pcie_writel_rc(pp, (pp->io_base >> 32), PCIE_ATU_UPPER_BASE); | 622 | dw_pcie_writel_rc(pp, (pp->io_mod_base >> 32), PCIE_ATU_UPPER_BASE); |
| 561 | dw_pcie_writel_rc(pp, pp->io_base + pp->config.io_size - 1, | 623 | dw_pcie_writel_rc(pp, pp->io_mod_base + pp->config.io_size - 1, |
| 562 | PCIE_ATU_LIMIT); | 624 | PCIE_ATU_LIMIT); |
| 563 | dw_pcie_writel_rc(pp, pp->config.io_bus_addr, PCIE_ATU_LOWER_TARGET); | 625 | dw_pcie_writel_rc(pp, pp->config.io_bus_addr, PCIE_ATU_LOWER_TARGET); |
| 564 | dw_pcie_writel_rc(pp, upper_32_bits(pp->config.io_bus_addr), | 626 | dw_pcie_writel_rc(pp, upper_32_bits(pp->config.io_bus_addr), |
| @@ -656,7 +718,11 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, | |||
| 656 | } | 718 | } |
| 657 | 719 | ||
| 658 | if (bus->number != pp->root_bus_nr) | 720 | if (bus->number != pp->root_bus_nr) |
| 659 | ret = dw_pcie_rd_other_conf(pp, bus, devfn, | 721 | if (pp->ops->rd_other_conf) |
| 722 | ret = pp->ops->rd_other_conf(pp, bus, devfn, | ||
| 723 | where, size, val); | ||
| 724 | else | ||
| 725 | ret = dw_pcie_rd_other_conf(pp, bus, devfn, | ||
| 660 | where, size, val); | 726 | where, size, val); |
| 661 | else | 727 | else |
| 662 | ret = dw_pcie_rd_own_conf(pp, where, size, val); | 728 | ret = dw_pcie_rd_own_conf(pp, where, size, val); |
| @@ -679,7 +745,11 @@ static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn, | |||
| 679 | return PCIBIOS_DEVICE_NOT_FOUND; | 745 | return PCIBIOS_DEVICE_NOT_FOUND; |
| 680 | 746 | ||
| 681 | if (bus->number != pp->root_bus_nr) | 747 | if (bus->number != pp->root_bus_nr) |
| 682 | ret = dw_pcie_wr_other_conf(pp, bus, devfn, | 748 | if (pp->ops->wr_other_conf) |
| 749 | ret = pp->ops->wr_other_conf(pp, bus, devfn, | ||
| 750 | where, size, val); | ||
| 751 | else | ||
| 752 | ret = dw_pcie_wr_other_conf(pp, bus, devfn, | ||
| 683 | where, size, val); | 753 | where, size, val); |
| 684 | else | 754 | else |
| 685 | ret = dw_pcie_wr_own_conf(pp, where, size, val); | 755 | ret = dw_pcie_wr_own_conf(pp, where, size, val); |
diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h index 77f592faa7bf..daf81f922cda 100644 --- a/drivers/pci/host/pcie-designware.h +++ b/drivers/pci/host/pcie-designware.h | |||
| @@ -36,11 +36,15 @@ struct pcie_port { | |||
| 36 | u8 root_bus_nr; | 36 | u8 root_bus_nr; |
| 37 | void __iomem *dbi_base; | 37 | void __iomem *dbi_base; |
| 38 | u64 cfg0_base; | 38 | u64 cfg0_base; |
| 39 | u64 cfg0_mod_base; | ||
| 39 | void __iomem *va_cfg0_base; | 40 | void __iomem *va_cfg0_base; |
| 40 | u64 cfg1_base; | 41 | u64 cfg1_base; |
| 42 | u64 cfg1_mod_base; | ||
| 41 | void __iomem *va_cfg1_base; | 43 | void __iomem *va_cfg1_base; |
| 42 | u64 io_base; | 44 | u64 io_base; |
| 45 | u64 io_mod_base; | ||
| 43 | u64 mem_base; | 46 | u64 mem_base; |
| 47 | u64 mem_mod_base; | ||
| 44 | struct resource cfg; | 48 | struct resource cfg; |
| 45 | struct resource io; | 49 | struct resource io; |
| 46 | struct resource mem; | 50 | struct resource mem; |
| @@ -61,8 +65,15 @@ struct pcie_host_ops { | |||
| 61 | u32 val, void __iomem *dbi_base); | 65 | u32 val, void __iomem *dbi_base); |
| 62 | int (*rd_own_conf)(struct pcie_port *pp, int where, int size, u32 *val); | 66 | int (*rd_own_conf)(struct pcie_port *pp, int where, int size, u32 *val); |
| 63 | int (*wr_own_conf)(struct pcie_port *pp, int where, int size, u32 val); | 67 | int (*wr_own_conf)(struct pcie_port *pp, int where, int size, u32 val); |
| 68 | int (*rd_other_conf)(struct pcie_port *pp, struct pci_bus *bus, | ||
| 69 | unsigned int devfn, int where, int size, u32 *val); | ||
| 70 | int (*wr_other_conf)(struct pcie_port *pp, struct pci_bus *bus, | ||
| 71 | unsigned int devfn, int where, int size, u32 val); | ||
| 64 | int (*link_up)(struct pcie_port *pp); | 72 | int (*link_up)(struct pcie_port *pp); |
| 65 | void (*host_init)(struct pcie_port *pp); | 73 | void (*host_init)(struct pcie_port *pp); |
| 74 | void (*msi_set_irq)(struct pcie_port *pp, int irq); | ||
| 75 | void (*msi_clear_irq)(struct pcie_port *pp, int irq); | ||
| 76 | u32 (*get_msi_data)(struct pcie_port *pp); | ||
| 66 | }; | 77 | }; |
| 67 | 78 | ||
| 68 | int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val); | 79 | int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val); |
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 172f26ce59ac..3bbcbf12c1fb 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
| @@ -652,6 +652,25 @@ config TOSHIBA_BT_RFKILL | |||
| 652 | If you have a modern Toshiba laptop with a Bluetooth and an | 652 | If you have a modern Toshiba laptop with a Bluetooth and an |
| 653 | RFKill switch (such as the Portege R500), say Y. | 653 | RFKill switch (such as the Portege R500), say Y. |
| 654 | 654 | ||
| 655 | config TOSHIBA_HAPS | ||
| 656 | tristate "Toshiba HDD Active Protection Sensor" | ||
| 657 | depends on ACPI | ||
| 658 | ---help--- | ||
| 659 | This driver adds support for the built-in accelerometer | ||
| 660 | found on recent Toshiba laptops equiped with HID TOS620A | ||
| 661 | device. | ||
| 662 | |||
| 663 | This driver receives ACPI notify events 0x80 when the sensor | ||
| 664 | detects a sudden move or a harsh vibration, as well as an | ||
| 665 | ACPI notify event 0x81 whenever the movement or vibration has | ||
| 666 | been stabilized. | ||
| 667 | |||
| 668 | Also provides sysfs entries to get/set the desired protection | ||
| 669 | level and reseting the HDD protection interface. | ||
| 670 | |||
| 671 | If you have a recent Toshiba laptop with a built-in accelerometer | ||
| 672 | device, say Y. | ||
| 673 | |||
| 655 | config ACPI_CMPC | 674 | config ACPI_CMPC |
| 656 | tristate "CMPC Laptop Extras" | 675 | tristate "CMPC Laptop Extras" |
| 657 | depends on X86 && ACPI | 676 | depends on X86 && ACPI |
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index c4ca428fd3db..f82232b1fc4d 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile | |||
| @@ -38,6 +38,7 @@ obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o | |||
| 38 | obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o | 38 | obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o |
| 39 | 39 | ||
| 40 | obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o | 40 | obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o |
| 41 | obj-$(CONFIG_TOSHIBA_HAPS) += toshiba_haps.o | ||
| 41 | obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o | 42 | obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o |
| 42 | obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o | 43 | obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o |
| 43 | obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o | 44 | obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o |
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index bbf78b2d6d93..96a0b75c52c9 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c | |||
| @@ -96,7 +96,7 @@ enum acer_wmi_event_ids { | |||
| 96 | WMID_ACCEL_EVENT = 0x5, | 96 | WMID_ACCEL_EVENT = 0x5, |
| 97 | }; | 97 | }; |
| 98 | 98 | ||
| 99 | static const struct key_entry acer_wmi_keymap[] = { | 99 | static const struct key_entry acer_wmi_keymap[] __initconst = { |
| 100 | {KE_KEY, 0x01, {KEY_WLAN} }, /* WiFi */ | 100 | {KE_KEY, 0x01, {KEY_WLAN} }, /* WiFi */ |
| 101 | {KE_KEY, 0x03, {KEY_WLAN} }, /* WiFi */ | 101 | {KE_KEY, 0x03, {KEY_WLAN} }, /* WiFi */ |
| 102 | {KE_KEY, 0x04, {KEY_WLAN} }, /* WiFi */ | 102 | {KE_KEY, 0x04, {KEY_WLAN} }, /* WiFi */ |
| @@ -294,7 +294,7 @@ struct quirk_entry { | |||
| 294 | 294 | ||
| 295 | static struct quirk_entry *quirks; | 295 | static struct quirk_entry *quirks; |
| 296 | 296 | ||
| 297 | static void set_quirks(void) | 297 | static void __init set_quirks(void) |
| 298 | { | 298 | { |
| 299 | if (!interface) | 299 | if (!interface) |
| 300 | return; | 300 | return; |
| @@ -306,7 +306,7 @@ static void set_quirks(void) | |||
| 306 | interface->capability |= ACER_CAP_BRIGHTNESS; | 306 | interface->capability |= ACER_CAP_BRIGHTNESS; |
| 307 | } | 307 | } |
| 308 | 308 | ||
| 309 | static int dmi_matched(const struct dmi_system_id *dmi) | 309 | static int __init dmi_matched(const struct dmi_system_id *dmi) |
| 310 | { | 310 | { |
| 311 | quirks = dmi->driver_data; | 311 | quirks = dmi->driver_data; |
| 312 | return 1; | 312 | return 1; |
| @@ -337,7 +337,7 @@ static struct quirk_entry quirk_lenovo_ideapad_s205 = { | |||
| 337 | }; | 337 | }; |
| 338 | 338 | ||
| 339 | /* The Aspire One has a dummy ACPI-WMI interface - disable it */ | 339 | /* The Aspire One has a dummy ACPI-WMI interface - disable it */ |
| 340 | static struct dmi_system_id acer_blacklist[] = { | 340 | static const struct dmi_system_id acer_blacklist[] __initconst = { |
| 341 | { | 341 | { |
| 342 | .ident = "Acer Aspire One (SSD)", | 342 | .ident = "Acer Aspire One (SSD)", |
| 343 | .matches = { | 343 | .matches = { |
| @@ -355,7 +355,7 @@ static struct dmi_system_id acer_blacklist[] = { | |||
| 355 | {} | 355 | {} |
| 356 | }; | 356 | }; |
| 357 | 357 | ||
| 358 | static struct dmi_system_id acer_quirks[] = { | 358 | static const struct dmi_system_id acer_quirks[] __initconst = { |
| 359 | { | 359 | { |
| 360 | .callback = dmi_matched, | 360 | .callback = dmi_matched, |
| 361 | .ident = "Acer Aspire 1360", | 361 | .ident = "Acer Aspire 1360", |
| @@ -530,14 +530,15 @@ static struct dmi_system_id acer_quirks[] = { | |||
| 530 | {} | 530 | {} |
| 531 | }; | 531 | }; |
| 532 | 532 | ||
| 533 | static int video_set_backlight_video_vendor(const struct dmi_system_id *d) | 533 | static int __init |
| 534 | video_set_backlight_video_vendor(const struct dmi_system_id *d) | ||
| 534 | { | 535 | { |
| 535 | interface->capability &= ~ACER_CAP_BRIGHTNESS; | 536 | interface->capability &= ~ACER_CAP_BRIGHTNESS; |
| 536 | pr_info("Brightness must be controlled by generic video driver\n"); | 537 | pr_info("Brightness must be controlled by generic video driver\n"); |
| 537 | return 0; | 538 | return 0; |
| 538 | } | 539 | } |
| 539 | 540 | ||
| 540 | static const struct dmi_system_id video_vendor_dmi_table[] = { | 541 | static const struct dmi_system_id video_vendor_dmi_table[] __initconst = { |
| 541 | { | 542 | { |
| 542 | .callback = video_set_backlight_video_vendor, | 543 | .callback = video_set_backlight_video_vendor, |
| 543 | .ident = "Acer TravelMate 4750", | 544 | .ident = "Acer TravelMate 4750", |
| @@ -582,7 +583,7 @@ static const struct dmi_system_id video_vendor_dmi_table[] = { | |||
| 582 | }; | 583 | }; |
| 583 | 584 | ||
| 584 | /* Find which quirks are needed for a particular vendor/ model pair */ | 585 | /* Find which quirks are needed for a particular vendor/ model pair */ |
| 585 | static void find_quirks(void) | 586 | static void __init find_quirks(void) |
| 586 | { | 587 | { |
| 587 | if (!force_series) { | 588 | if (!force_series) { |
| 588 | dmi_check_system(acer_quirks); | 589 | dmi_check_system(acer_quirks); |
| @@ -749,7 +750,7 @@ static acpi_status AMW0_set_u32(u32 value, u32 cap) | |||
| 749 | return wmab_execute(&args, NULL); | 750 | return wmab_execute(&args, NULL); |
| 750 | } | 751 | } |
| 751 | 752 | ||
| 752 | static acpi_status AMW0_find_mailled(void) | 753 | static acpi_status __init AMW0_find_mailled(void) |
| 753 | { | 754 | { |
| 754 | struct wmab_args args; | 755 | struct wmab_args args; |
| 755 | struct wmab_ret ret; | 756 | struct wmab_ret ret; |
| @@ -781,16 +782,16 @@ static acpi_status AMW0_find_mailled(void) | |||
| 781 | return AE_OK; | 782 | return AE_OK; |
| 782 | } | 783 | } |
| 783 | 784 | ||
| 784 | static int AMW0_set_cap_acpi_check_device_found; | 785 | static int AMW0_set_cap_acpi_check_device_found __initdata; |
| 785 | 786 | ||
| 786 | static acpi_status AMW0_set_cap_acpi_check_device_cb(acpi_handle handle, | 787 | static acpi_status __init AMW0_set_cap_acpi_check_device_cb(acpi_handle handle, |
| 787 | u32 level, void *context, void **retval) | 788 | u32 level, void *context, void **retval) |
| 788 | { | 789 | { |
| 789 | AMW0_set_cap_acpi_check_device_found = 1; | 790 | AMW0_set_cap_acpi_check_device_found = 1; |
| 790 | return AE_OK; | 791 | return AE_OK; |
| 791 | } | 792 | } |
| 792 | 793 | ||
| 793 | static const struct acpi_device_id norfkill_ids[] = { | 794 | static const struct acpi_device_id norfkill_ids[] __initconst = { |
| 794 | { "VPC2004", 0}, | 795 | { "VPC2004", 0}, |
| 795 | { "IBM0068", 0}, | 796 | { "IBM0068", 0}, |
| 796 | { "LEN0068", 0}, | 797 | { "LEN0068", 0}, |
| @@ -798,7 +799,7 @@ static const struct acpi_device_id norfkill_ids[] = { | |||
| 798 | { "", 0}, | 799 | { "", 0}, |
| 799 | }; | 800 | }; |
| 800 | 801 | ||
| 801 | static int AMW0_set_cap_acpi_check_device(void) | 802 | static int __init AMW0_set_cap_acpi_check_device(void) |
| 802 | { | 803 | { |
| 803 | const struct acpi_device_id *id; | 804 | const struct acpi_device_id *id; |
| 804 | 805 | ||
| @@ -808,7 +809,7 @@ static int AMW0_set_cap_acpi_check_device(void) | |||
| 808 | return AMW0_set_cap_acpi_check_device_found; | 809 | return AMW0_set_cap_acpi_check_device_found; |
| 809 | } | 810 | } |
| 810 | 811 | ||
| 811 | static acpi_status AMW0_set_capabilities(void) | 812 | static acpi_status __init AMW0_set_capabilities(void) |
| 812 | { | 813 | { |
| 813 | struct wmab_args args; | 814 | struct wmab_args args; |
| 814 | struct wmab_ret ret; | 815 | struct wmab_ret ret; |
| @@ -1184,7 +1185,7 @@ static acpi_status wmid_v2_set_u32(u32 value, u32 cap) | |||
| 1184 | return wmid3_set_device_status(value, device); | 1185 | return wmid3_set_device_status(value, device); |
| 1185 | } | 1186 | } |
| 1186 | 1187 | ||
| 1187 | static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy) | 1188 | static void __init type_aa_dmi_decode(const struct dmi_header *header, void *d) |
| 1188 | { | 1189 | { |
| 1189 | struct hotkey_function_type_aa *type_aa; | 1190 | struct hotkey_function_type_aa *type_aa; |
| 1190 | 1191 | ||
| @@ -1209,7 +1210,7 @@ static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy) | |||
| 1209 | commun_fn_key_number = type_aa->commun_fn_key_number; | 1210 | commun_fn_key_number = type_aa->commun_fn_key_number; |
| 1210 | } | 1211 | } |
| 1211 | 1212 | ||
| 1212 | static acpi_status WMID_set_capabilities(void) | 1213 | static acpi_status __init WMID_set_capabilities(void) |
| 1213 | { | 1214 | { |
| 1214 | struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL}; | 1215 | struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL}; |
| 1215 | union acpi_object *obj; | 1216 | union acpi_object *obj; |
| @@ -1658,7 +1659,7 @@ static ssize_t show_bool_threeg(struct device *dev, | |||
| 1658 | u32 result; \ | 1659 | u32 result; \ |
| 1659 | acpi_status status; | 1660 | acpi_status status; |
| 1660 | 1661 | ||
| 1661 | pr_info("This threeg sysfs will be removed in 2012 - used by: %s\n", | 1662 | pr_info("This threeg sysfs will be removed in 2014 - used by: %s\n", |
| 1662 | current->comm); | 1663 | current->comm); |
| 1663 | status = get_u32(&result, ACER_CAP_THREEG); | 1664 | status = get_u32(&result, ACER_CAP_THREEG); |
| 1664 | if (ACPI_SUCCESS(status)) | 1665 | if (ACPI_SUCCESS(status)) |
| @@ -1671,7 +1672,7 @@ static ssize_t set_bool_threeg(struct device *dev, | |||
| 1671 | { | 1672 | { |
| 1672 | u32 tmp = simple_strtoul(buf, NULL, 10); | 1673 | u32 tmp = simple_strtoul(buf, NULL, 10); |
| 1673 | acpi_status status = set_u32(tmp, ACER_CAP_THREEG); | 1674 | acpi_status status = set_u32(tmp, ACER_CAP_THREEG); |
| 1674 | pr_info("This threeg sysfs will be removed in 2012 - used by: %s\n", | 1675 | pr_info("This threeg sysfs will be removed in 2014 - used by: %s\n", |
| 1675 | current->comm); | 1676 | current->comm); |
| 1676 | if (ACPI_FAILURE(status)) | 1677 | if (ACPI_FAILURE(status)) |
| 1677 | return -EINVAL; | 1678 | return -EINVAL; |
| @@ -1683,7 +1684,7 @@ static DEVICE_ATTR(threeg, S_IRUGO | S_IWUSR, show_bool_threeg, | |||
| 1683 | static ssize_t show_interface(struct device *dev, struct device_attribute *attr, | 1684 | static ssize_t show_interface(struct device *dev, struct device_attribute *attr, |
| 1684 | char *buf) | 1685 | char *buf) |
| 1685 | { | 1686 | { |
| 1686 | pr_info("This interface sysfs will be removed in 2012 - used by: %s\n", | 1687 | pr_info("This interface sysfs will be removed in 2014 - used by: %s\n", |
| 1687 | current->comm); | 1688 | current->comm); |
| 1688 | switch (interface->type) { | 1689 | switch (interface->type) { |
| 1689 | case ACER_AMW0: | 1690 | case ACER_AMW0: |
| @@ -1777,7 +1778,7 @@ static void acer_wmi_notify(u32 value, void *context) | |||
| 1777 | } | 1778 | } |
| 1778 | } | 1779 | } |
| 1779 | 1780 | ||
| 1780 | static acpi_status | 1781 | static acpi_status __init |
| 1781 | wmid3_set_lm_mode(struct lm_input_params *params, | 1782 | wmid3_set_lm_mode(struct lm_input_params *params, |
| 1782 | struct lm_return_value *return_value) | 1783 | struct lm_return_value *return_value) |
| 1783 | { | 1784 | { |
| @@ -1811,7 +1812,7 @@ wmid3_set_lm_mode(struct lm_input_params *params, | |||
| 1811 | return status; | 1812 | return status; |
| 1812 | } | 1813 | } |
| 1813 | 1814 | ||
| 1814 | static int acer_wmi_enable_ec_raw(void) | 1815 | static int __init acer_wmi_enable_ec_raw(void) |
| 1815 | { | 1816 | { |
| 1816 | struct lm_return_value return_value; | 1817 | struct lm_return_value return_value; |
| 1817 | acpi_status status; | 1818 | acpi_status status; |
| @@ -1834,7 +1835,7 @@ static int acer_wmi_enable_ec_raw(void) | |||
| 1834 | return status; | 1835 | return status; |
| 1835 | } | 1836 | } |
| 1836 | 1837 | ||
| 1837 | static int acer_wmi_enable_lm(void) | 1838 | static int __init acer_wmi_enable_lm(void) |
| 1838 | { | 1839 | { |
| 1839 | struct lm_return_value return_value; | 1840 | struct lm_return_value return_value; |
| 1840 | acpi_status status; | 1841 | acpi_status status; |
| @@ -2043,6 +2044,7 @@ static int acer_platform_remove(struct platform_device *device) | |||
| 2043 | return 0; | 2044 | return 0; |
| 2044 | } | 2045 | } |
| 2045 | 2046 | ||
| 2047 | #ifdef CONFIG_PM_SLEEP | ||
| 2046 | static int acer_suspend(struct device *dev) | 2048 | static int acer_suspend(struct device *dev) |
| 2047 | { | 2049 | { |
| 2048 | u32 value; | 2050 | u32 value; |
| @@ -2083,6 +2085,10 @@ static int acer_resume(struct device *dev) | |||
| 2083 | 2085 | ||
| 2084 | return 0; | 2086 | return 0; |
| 2085 | } | 2087 | } |
| 2088 | #else | ||
| 2089 | #define acer_suspend NULL | ||
| 2090 | #define acer_resume NULL | ||
| 2091 | #endif | ||
| 2086 | 2092 | ||
| 2087 | static SIMPLE_DEV_PM_OPS(acer_pm, acer_suspend, acer_resume); | 2093 | static SIMPLE_DEV_PM_OPS(acer_pm, acer_suspend, acer_resume); |
| 2088 | 2094 | ||
| @@ -2120,7 +2126,7 @@ static int remove_sysfs(struct platform_device *device) | |||
| 2120 | return 0; | 2126 | return 0; |
| 2121 | } | 2127 | } |
| 2122 | 2128 | ||
| 2123 | static int create_sysfs(void) | 2129 | static int __init create_sysfs(void) |
| 2124 | { | 2130 | { |
| 2125 | int retval = -ENOMEM; | 2131 | int retval = -ENOMEM; |
| 2126 | 2132 | ||
| @@ -2149,7 +2155,7 @@ static void remove_debugfs(void) | |||
| 2149 | debugfs_remove(interface->debug.root); | 2155 | debugfs_remove(interface->debug.root); |
| 2150 | } | 2156 | } |
| 2151 | 2157 | ||
| 2152 | static int create_debugfs(void) | 2158 | static int __init create_debugfs(void) |
| 2153 | { | 2159 | { |
| 2154 | interface->debug.root = debugfs_create_dir("acer-wmi", NULL); | 2160 | interface->debug.root = debugfs_create_dir("acer-wmi", NULL); |
| 2155 | if (!interface->debug.root) { | 2161 | if (!interface->debug.root) { |
diff --git a/drivers/platform/x86/alienware-wmi.c b/drivers/platform/x86/alienware-wmi.c index 297b6640213f..c5af23b64438 100644 --- a/drivers/platform/x86/alienware-wmi.c +++ b/drivers/platform/x86/alienware-wmi.c | |||
| @@ -59,25 +59,33 @@ enum WMAX_CONTROL_STATES { | |||
| 59 | 59 | ||
| 60 | struct quirk_entry { | 60 | struct quirk_entry { |
| 61 | u8 num_zones; | 61 | u8 num_zones; |
| 62 | u8 hdmi_mux; | ||
| 62 | }; | 63 | }; |
| 63 | 64 | ||
| 64 | static struct quirk_entry *quirks; | 65 | static struct quirk_entry *quirks; |
| 65 | 66 | ||
| 66 | static struct quirk_entry quirk_unknown = { | 67 | static struct quirk_entry quirk_unknown = { |
| 67 | .num_zones = 2, | 68 | .num_zones = 2, |
| 69 | .hdmi_mux = 0, | ||
| 68 | }; | 70 | }; |
| 69 | 71 | ||
| 70 | static struct quirk_entry quirk_x51_family = { | 72 | static struct quirk_entry quirk_x51_family = { |
| 71 | .num_zones = 3, | 73 | .num_zones = 3, |
| 74 | .hdmi_mux = 0. | ||
| 72 | }; | 75 | }; |
| 73 | 76 | ||
| 74 | static int dmi_matched(const struct dmi_system_id *dmi) | 77 | static struct quirk_entry quirk_asm100 = { |
| 78 | .num_zones = 2, | ||
| 79 | .hdmi_mux = 1, | ||
| 80 | }; | ||
| 81 | |||
| 82 | static int __init dmi_matched(const struct dmi_system_id *dmi) | ||
| 75 | { | 83 | { |
| 76 | quirks = dmi->driver_data; | 84 | quirks = dmi->driver_data; |
| 77 | return 1; | 85 | return 1; |
| 78 | } | 86 | } |
| 79 | 87 | ||
| 80 | static struct dmi_system_id alienware_quirks[] = { | 88 | static const struct dmi_system_id alienware_quirks[] __initconst = { |
| 81 | { | 89 | { |
| 82 | .callback = dmi_matched, | 90 | .callback = dmi_matched, |
| 83 | .ident = "Alienware X51 R1", | 91 | .ident = "Alienware X51 R1", |
| @@ -96,6 +104,15 @@ static struct dmi_system_id alienware_quirks[] = { | |||
| 96 | }, | 104 | }, |
| 97 | .driver_data = &quirk_x51_family, | 105 | .driver_data = &quirk_x51_family, |
| 98 | }, | 106 | }, |
| 107 | { | ||
| 108 | .callback = dmi_matched, | ||
| 109 | .ident = "Alienware ASM100", | ||
| 110 | .matches = { | ||
| 111 | DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), | ||
| 112 | DMI_MATCH(DMI_PRODUCT_NAME, "ASM100"), | ||
| 113 | }, | ||
| 114 | .driver_data = &quirk_asm100, | ||
| 115 | }, | ||
| 99 | {} | 116 | {} |
| 100 | }; | 117 | }; |
| 101 | 118 | ||
| @@ -537,7 +554,8 @@ static struct attribute_group hdmi_attribute_group = { | |||
| 537 | 554 | ||
| 538 | static void remove_hdmi(struct platform_device *dev) | 555 | static void remove_hdmi(struct platform_device *dev) |
| 539 | { | 556 | { |
| 540 | sysfs_remove_group(&dev->dev.kobj, &hdmi_attribute_group); | 557 | if (quirks->hdmi_mux > 0) |
| 558 | sysfs_remove_group(&dev->dev.kobj, &hdmi_attribute_group); | ||
| 541 | } | 559 | } |
| 542 | 560 | ||
| 543 | static int create_hdmi(struct platform_device *dev) | 561 | static int create_hdmi(struct platform_device *dev) |
| @@ -583,7 +601,7 @@ static int __init alienware_wmi_init(void) | |||
| 583 | if (ret) | 601 | if (ret) |
| 584 | goto fail_platform_device2; | 602 | goto fail_platform_device2; |
| 585 | 603 | ||
| 586 | if (interface == WMAX) { | 604 | if (quirks->hdmi_mux > 0) { |
| 587 | ret = create_hdmi(platform_device); | 605 | ret = create_hdmi(platform_device); |
| 588 | if (ret) | 606 | if (ret) |
| 589 | goto fail_prep_hdmi; | 607 | goto fail_prep_hdmi; |
diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index ddf0eefd862c..3a4951f46065 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c | |||
| @@ -70,17 +70,35 @@ static struct quirk_entry quirk_asus_x55u = { | |||
| 70 | .no_display_toggle = true, | 70 | .no_display_toggle = true, |
| 71 | }; | 71 | }; |
| 72 | 72 | ||
| 73 | static struct quirk_entry quirk_asus_x401u = { | 73 | static struct quirk_entry quirk_asus_wapf4 = { |
| 74 | .wapf = 4, | 74 | .wapf = 4, |
| 75 | }; | 75 | }; |
| 76 | 76 | ||
| 77 | static struct quirk_entry quirk_asus_x200ca = { | ||
| 78 | .wapf = 2, | ||
| 79 | }; | ||
| 80 | |||
| 77 | static int dmi_matched(const struct dmi_system_id *dmi) | 81 | static int dmi_matched(const struct dmi_system_id *dmi) |
| 78 | { | 82 | { |
| 79 | quirks = dmi->driver_data; | 83 | quirks = dmi->driver_data; |
| 80 | return 1; | 84 | return 1; |
| 81 | } | 85 | } |
| 82 | 86 | ||
| 83 | static struct dmi_system_id asus_quirks[] = { | 87 | static const struct dmi_system_id asus_quirks[] = { |
| 88 | { | ||
| 89 | .callback = dmi_matched, | ||
| 90 | .ident = "ASUSTeK COMPUTER INC. U32U", | ||
| 91 | .matches = { | ||
| 92 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), | ||
| 93 | DMI_MATCH(DMI_PRODUCT_NAME, "U32U"), | ||
| 94 | }, | ||
| 95 | /* | ||
| 96 | * Note this machine has a Brazos APU, and most Brazos Asus | ||
| 97 | * machines need quirk_asus_x55u / wmi_backlight_power but | ||
| 98 | * here acpi-video seems to work fine for backlight control. | ||
| 99 | */ | ||
| 100 | .driver_data = &quirk_asus_wapf4, | ||
| 101 | }, | ||
| 84 | { | 102 | { |
| 85 | .callback = dmi_matched, | 103 | .callback = dmi_matched, |
| 86 | .ident = "ASUSTeK COMPUTER INC. X401U", | 104 | .ident = "ASUSTeK COMPUTER INC. X401U", |
| @@ -97,7 +115,7 @@ static struct dmi_system_id asus_quirks[] = { | |||
| 97 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | 115 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
| 98 | DMI_MATCH(DMI_PRODUCT_NAME, "X401A"), | 116 | DMI_MATCH(DMI_PRODUCT_NAME, "X401A"), |
| 99 | }, | 117 | }, |
| 100 | .driver_data = &quirk_asus_x401u, | 118 | .driver_data = &quirk_asus_wapf4, |
| 101 | }, | 119 | }, |
| 102 | { | 120 | { |
| 103 | .callback = dmi_matched, | 121 | .callback = dmi_matched, |
| @@ -106,7 +124,7 @@ static struct dmi_system_id asus_quirks[] = { | |||
| 106 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | 124 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
| 107 | DMI_MATCH(DMI_PRODUCT_NAME, "X401A1"), | 125 | DMI_MATCH(DMI_PRODUCT_NAME, "X401A1"), |
| 108 | }, | 126 | }, |
| 109 | .driver_data = &quirk_asus_x401u, | 127 | .driver_data = &quirk_asus_wapf4, |
| 110 | }, | 128 | }, |
| 111 | { | 129 | { |
| 112 | .callback = dmi_matched, | 130 | .callback = dmi_matched, |
| @@ -124,7 +142,7 @@ static struct dmi_system_id asus_quirks[] = { | |||
| 124 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | 142 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
| 125 | DMI_MATCH(DMI_PRODUCT_NAME, "X501A"), | 143 | DMI_MATCH(DMI_PRODUCT_NAME, "X501A"), |
| 126 | }, | 144 | }, |
| 127 | .driver_data = &quirk_asus_x401u, | 145 | .driver_data = &quirk_asus_wapf4, |
| 128 | }, | 146 | }, |
| 129 | { | 147 | { |
| 130 | .callback = dmi_matched, | 148 | .callback = dmi_matched, |
| @@ -133,7 +151,7 @@ static struct dmi_system_id asus_quirks[] = { | |||
| 133 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | 151 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
| 134 | DMI_MATCH(DMI_PRODUCT_NAME, "X501A1"), | 152 | DMI_MATCH(DMI_PRODUCT_NAME, "X501A1"), |
| 135 | }, | 153 | }, |
| 136 | .driver_data = &quirk_asus_x401u, | 154 | .driver_data = &quirk_asus_wapf4, |
| 137 | }, | 155 | }, |
| 138 | { | 156 | { |
| 139 | .callback = dmi_matched, | 157 | .callback = dmi_matched, |
| @@ -142,7 +160,25 @@ static struct dmi_system_id asus_quirks[] = { | |||
| 142 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | 160 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
| 143 | DMI_MATCH(DMI_PRODUCT_NAME, "X550CA"), | 161 | DMI_MATCH(DMI_PRODUCT_NAME, "X550CA"), |
| 144 | }, | 162 | }, |
| 145 | .driver_data = &quirk_asus_x401u, | 163 | .driver_data = &quirk_asus_wapf4, |
| 164 | }, | ||
| 165 | { | ||
| 166 | .callback = dmi_matched, | ||
| 167 | .ident = "ASUSTeK COMPUTER INC. X550CC", | ||
| 168 | .matches = { | ||
| 169 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | ||
| 170 | DMI_MATCH(DMI_PRODUCT_NAME, "X550CC"), | ||
| 171 | }, | ||
| 172 | .driver_data = &quirk_asus_wapf4, | ||
| 173 | }, | ||
| 174 | { | ||
| 175 | .callback = dmi_matched, | ||
| 176 | .ident = "ASUSTeK COMPUTER INC. X550CL", | ||
| 177 | .matches = { | ||
| 178 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | ||
| 179 | DMI_MATCH(DMI_PRODUCT_NAME, "X550CL"), | ||
| 180 | }, | ||
| 181 | .driver_data = &quirk_asus_wapf4, | ||
| 146 | }, | 182 | }, |
| 147 | { | 183 | { |
| 148 | .callback = dmi_matched, | 184 | .callback = dmi_matched, |
| @@ -151,7 +187,7 @@ static struct dmi_system_id asus_quirks[] = { | |||
| 151 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | 187 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
| 152 | DMI_MATCH(DMI_PRODUCT_NAME, "X55A"), | 188 | DMI_MATCH(DMI_PRODUCT_NAME, "X55A"), |
| 153 | }, | 189 | }, |
| 154 | .driver_data = &quirk_asus_x401u, | 190 | .driver_data = &quirk_asus_wapf4, |
| 155 | }, | 191 | }, |
| 156 | { | 192 | { |
| 157 | .callback = dmi_matched, | 193 | .callback = dmi_matched, |
| @@ -160,7 +196,7 @@ static struct dmi_system_id asus_quirks[] = { | |||
| 160 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | 196 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
| 161 | DMI_MATCH(DMI_PRODUCT_NAME, "X55C"), | 197 | DMI_MATCH(DMI_PRODUCT_NAME, "X55C"), |
| 162 | }, | 198 | }, |
| 163 | .driver_data = &quirk_asus_x401u, | 199 | .driver_data = &quirk_asus_wapf4, |
| 164 | }, | 200 | }, |
| 165 | { | 201 | { |
| 166 | .callback = dmi_matched, | 202 | .callback = dmi_matched, |
| @@ -178,7 +214,7 @@ static struct dmi_system_id asus_quirks[] = { | |||
| 178 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | 214 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
| 179 | DMI_MATCH(DMI_PRODUCT_NAME, "X55VD"), | 215 | DMI_MATCH(DMI_PRODUCT_NAME, "X55VD"), |
| 180 | }, | 216 | }, |
| 181 | .driver_data = &quirk_asus_x401u, | 217 | .driver_data = &quirk_asus_wapf4, |
| 182 | }, | 218 | }, |
| 183 | { | 219 | { |
| 184 | .callback = dmi_matched, | 220 | .callback = dmi_matched, |
| @@ -187,7 +223,16 @@ static struct dmi_system_id asus_quirks[] = { | |||
| 187 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | 223 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
| 188 | DMI_MATCH(DMI_PRODUCT_NAME, "X75A"), | 224 | DMI_MATCH(DMI_PRODUCT_NAME, "X75A"), |
| 189 | }, | 225 | }, |
| 190 | .driver_data = &quirk_asus_x401u, | 226 | .driver_data = &quirk_asus_wapf4, |
| 227 | }, | ||
| 228 | { | ||
| 229 | .callback = dmi_matched, | ||
| 230 | .ident = "ASUSTeK COMPUTER INC. X75VBP", | ||
| 231 | .matches = { | ||
| 232 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | ||
| 233 | DMI_MATCH(DMI_PRODUCT_NAME, "X75VBP"), | ||
| 234 | }, | ||
| 235 | .driver_data = &quirk_asus_wapf4, | ||
| 191 | }, | 236 | }, |
| 192 | { | 237 | { |
| 193 | .callback = dmi_matched, | 238 | .callback = dmi_matched, |
| @@ -196,7 +241,7 @@ static struct dmi_system_id asus_quirks[] = { | |||
| 196 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | 241 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
| 197 | DMI_MATCH(DMI_PRODUCT_NAME, "1015E"), | 242 | DMI_MATCH(DMI_PRODUCT_NAME, "1015E"), |
| 198 | }, | 243 | }, |
| 199 | .driver_data = &quirk_asus_x401u, | 244 | .driver_data = &quirk_asus_wapf4, |
| 200 | }, | 245 | }, |
| 201 | { | 246 | { |
| 202 | .callback = dmi_matched, | 247 | .callback = dmi_matched, |
| @@ -205,7 +250,16 @@ static struct dmi_system_id asus_quirks[] = { | |||
| 205 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | 250 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
| 206 | DMI_MATCH(DMI_PRODUCT_NAME, "1015U"), | 251 | DMI_MATCH(DMI_PRODUCT_NAME, "1015U"), |
| 207 | }, | 252 | }, |
| 208 | .driver_data = &quirk_asus_x401u, | 253 | .driver_data = &quirk_asus_wapf4, |
| 254 | }, | ||
| 255 | { | ||
| 256 | .callback = dmi_matched, | ||
| 257 | .ident = "ASUSTeK COMPUTER INC. X200CA", | ||
| 258 | .matches = { | ||
| 259 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | ||
| 260 | DMI_MATCH(DMI_PRODUCT_NAME, "X200CA"), | ||
| 261 | }, | ||
| 262 | .driver_data = &quirk_asus_x200ca, | ||
| 209 | }, | 263 | }, |
| 210 | {}, | 264 | {}, |
| 211 | }; | 265 | }; |
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 3c6ccedc82b6..21fc932da3a1 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c | |||
| @@ -46,6 +46,7 @@ | |||
| 46 | #include <linux/platform_device.h> | 46 | #include <linux/platform_device.h> |
| 47 | #include <linux/thermal.h> | 47 | #include <linux/thermal.h> |
| 48 | #include <linux/acpi.h> | 48 | #include <linux/acpi.h> |
| 49 | #include <linux/dmi.h> | ||
| 49 | #include <acpi/video.h> | 50 | #include <acpi/video.h> |
| 50 | 51 | ||
| 51 | #include "asus-wmi.h" | 52 | #include "asus-wmi.h" |
| @@ -554,7 +555,7 @@ static int asus_wmi_led_init(struct asus_wmi *asus) | |||
| 554 | goto error; | 555 | goto error; |
| 555 | } | 556 | } |
| 556 | 557 | ||
| 557 | if (wlan_led_presence(asus) && (asus->driver->quirks->wapf == 4)) { | 558 | if (wlan_led_presence(asus) && (asus->driver->quirks->wapf > 0)) { |
| 558 | INIT_WORK(&asus->wlan_led_work, wlan_led_update); | 559 | INIT_WORK(&asus->wlan_led_work, wlan_led_update); |
| 559 | 560 | ||
| 560 | asus->wlan_led.name = "asus::wlan"; | 561 | asus->wlan_led.name = "asus::wlan"; |
| @@ -884,7 +885,7 @@ static int asus_new_rfkill(struct asus_wmi *asus, | |||
| 884 | return -EINVAL; | 885 | return -EINVAL; |
| 885 | 886 | ||
| 886 | if ((dev_id == ASUS_WMI_DEVID_WLAN) && | 887 | if ((dev_id == ASUS_WMI_DEVID_WLAN) && |
| 887 | (asus->driver->quirks->wapf == 4)) | 888 | (asus->driver->quirks->wapf > 0)) |
| 888 | rfkill_set_led_trigger_name(*rfkill, "asus-wlan"); | 889 | rfkill_set_led_trigger_name(*rfkill, "asus-wlan"); |
| 889 | 890 | ||
| 890 | rfkill_init_sw_state(*rfkill, !result); | 891 | rfkill_init_sw_state(*rfkill, !result); |
| @@ -1270,10 +1271,7 @@ static int asus_wmi_backlight_init(struct asus_wmi *asus) | |||
| 1270 | int power; | 1271 | int power; |
| 1271 | 1272 | ||
| 1272 | max = read_brightness_max(asus); | 1273 | max = read_brightness_max(asus); |
| 1273 | 1274 | if (max < 0) | |
| 1274 | if (max == -ENODEV) | ||
| 1275 | max = 0; | ||
| 1276 | else if (max < 0) | ||
| 1277 | return max; | 1275 | return max; |
| 1278 | 1276 | ||
| 1279 | power = read_backlight_power(asus); | 1277 | power = read_backlight_power(asus); |
| @@ -1734,6 +1732,7 @@ static int asus_wmi_add(struct platform_device *pdev) | |||
| 1734 | struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver); | 1732 | struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver); |
| 1735 | struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv); | 1733 | struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv); |
| 1736 | struct asus_wmi *asus; | 1734 | struct asus_wmi *asus; |
| 1735 | const char *chassis_type; | ||
| 1737 | acpi_status status; | 1736 | acpi_status status; |
| 1738 | int err; | 1737 | int err; |
| 1739 | u32 result; | 1738 | u32 result; |
| @@ -1770,6 +1769,11 @@ static int asus_wmi_add(struct platform_device *pdev) | |||
| 1770 | if (err) | 1769 | if (err) |
| 1771 | goto fail_rfkill; | 1770 | goto fail_rfkill; |
| 1772 | 1771 | ||
| 1772 | /* Some Asus desktop boards export an acpi-video backlight interface, | ||
| 1773 | stop this from showing up */ | ||
| 1774 | chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE); | ||
| 1775 | if (chassis_type && !strcmp(chassis_type, "3")) | ||
| 1776 | acpi_video_dmi_promote_vendor(); | ||
| 1773 | if (asus->driver->quirks->wmi_backlight_power) | 1777 | if (asus->driver->quirks->wmi_backlight_power) |
| 1774 | acpi_video_dmi_promote_vendor(); | 1778 | acpi_video_dmi_promote_vendor(); |
| 1775 | if (!acpi_video_backlight_support()) { | 1779 | if (!acpi_video_backlight_support()) { |
diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c index 7297df2ebf50..26bfd7bb5c13 100644 --- a/drivers/platform/x86/compal-laptop.c +++ b/drivers/platform/x86/compal-laptop.c | |||
| @@ -1028,7 +1028,7 @@ static int compal_probe(struct platform_device *pdev) | |||
| 1028 | return err; | 1028 | return err; |
| 1029 | 1029 | ||
| 1030 | hwmon_dev = hwmon_device_register_with_groups(&pdev->dev, | 1030 | hwmon_dev = hwmon_device_register_with_groups(&pdev->dev, |
| 1031 | DRIVER_NAME, data, | 1031 | "compal", data, |
| 1032 | compal_hwmon_groups); | 1032 | compal_hwmon_groups); |
| 1033 | if (IS_ERR(hwmon_dev)) { | 1033 | if (IS_ERR(hwmon_dev)) { |
| 1034 | err = PTR_ERR(hwmon_dev); | 1034 | err = PTR_ERR(hwmon_dev); |
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index fed4111ac31a..233d2ee598a6 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c | |||
| @@ -70,7 +70,7 @@ static struct quirk_entry quirk_dell_vostro_v130 = { | |||
| 70 | .touchpad_led = 1, | 70 | .touchpad_led = 1, |
| 71 | }; | 71 | }; |
| 72 | 72 | ||
| 73 | static int dmi_matched(const struct dmi_system_id *dmi) | 73 | static int __init dmi_matched(const struct dmi_system_id *dmi) |
| 74 | { | 74 | { |
| 75 | quirks = dmi->driver_data; | 75 | quirks = dmi->driver_data; |
| 76 | return 1; | 76 | return 1; |
| @@ -123,7 +123,7 @@ static const struct dmi_system_id dell_device_table[] __initconst = { | |||
| 123 | }; | 123 | }; |
| 124 | MODULE_DEVICE_TABLE(dmi, dell_device_table); | 124 | MODULE_DEVICE_TABLE(dmi, dell_device_table); |
| 125 | 125 | ||
| 126 | static struct dmi_system_id dell_quirks[] = { | 126 | static const struct dmi_system_id dell_quirks[] __initconst = { |
| 127 | { | 127 | { |
| 128 | .callback = dmi_matched, | 128 | .callback = dmi_matched, |
| 129 | .ident = "Dell Vostro V130", | 129 | .ident = "Dell Vostro V130", |
| @@ -780,7 +780,7 @@ static struct led_classdev touchpad_led = { | |||
| 780 | .flags = LED_CORE_SUSPENDRESUME, | 780 | .flags = LED_CORE_SUSPENDRESUME, |
| 781 | }; | 781 | }; |
| 782 | 782 | ||
| 783 | static int touchpad_led_init(struct device *dev) | 783 | static int __init touchpad_led_init(struct device *dev) |
| 784 | { | 784 | { |
| 785 | return led_classdev_register(dev, &touchpad_led); | 785 | return led_classdev_register(dev, &touchpad_led); |
| 786 | } | 786 | } |
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 9b0c57cd1d4a..bd533c22be57 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c | |||
| @@ -1053,20 +1053,20 @@ static ssize_t show_sys_hwmon(int (*get)(void), char *buf) | |||
| 1053 | return sprintf(buf, "%d\n", get()); | 1053 | return sprintf(buf, "%d\n", get()); |
| 1054 | } | 1054 | } |
| 1055 | 1055 | ||
| 1056 | #define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _set, _get) \ | 1056 | #define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _get, _set) \ |
| 1057 | static ssize_t show_##_name(struct device *dev, \ | 1057 | static ssize_t show_##_name(struct device *dev, \ |
| 1058 | struct device_attribute *attr, \ | 1058 | struct device_attribute *attr, \ |
| 1059 | char *buf) \ | 1059 | char *buf) \ |
| 1060 | { \ | 1060 | { \ |
| 1061 | return show_sys_hwmon(_set, buf); \ | 1061 | return show_sys_hwmon(_get, buf); \ |
| 1062 | } \ | 1062 | } \ |
| 1063 | static ssize_t store_##_name(struct device *dev, \ | 1063 | static ssize_t store_##_name(struct device *dev, \ |
| 1064 | struct device_attribute *attr, \ | 1064 | struct device_attribute *attr, \ |
| 1065 | const char *buf, size_t count) \ | 1065 | const char *buf, size_t count) \ |
| 1066 | { \ | 1066 | { \ |
| 1067 | return store_sys_hwmon(_get, buf, count); \ | 1067 | return store_sys_hwmon(_set, buf, count); \ |
| 1068 | } \ | 1068 | } \ |
| 1069 | static DEVICE_ATTR(_name, _mode, show_##_name, store_##_name); | 1069 | static DEVICE_ATTR(_name, _mode, show_##_name, store_##_name) |
| 1070 | 1070 | ||
| 1071 | EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL); | 1071 | EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL); |
| 1072 | EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR, | 1072 | EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR, |
diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c index 6112933f6278..14fd2ecb06a1 100644 --- a/drivers/platform/x86/eeepc-wmi.c +++ b/drivers/platform/x86/eeepc-wmi.c | |||
| @@ -145,7 +145,7 @@ static int dmi_matched(const struct dmi_system_id *dmi) | |||
| 145 | return 1; | 145 | return 1; |
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | static struct dmi_system_id asus_quirks[] = { | 148 | static const struct dmi_system_id asus_quirks[] = { |
| 149 | { | 149 | { |
| 150 | .callback = dmi_matched, | 150 | .callback = dmi_matched, |
| 151 | .ident = "ASUSTeK Computer INC. 1000H", | 151 | .ident = "ASUSTeK Computer INC. 1000H", |
diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index e6f336270c21..87aa28c4280f 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c | |||
| @@ -129,15 +129,14 @@ | |||
| 129 | #define FUJLAPTOP_DBG_INFO 0x0004 | 129 | #define FUJLAPTOP_DBG_INFO 0x0004 |
| 130 | #define FUJLAPTOP_DBG_TRACE 0x0008 | 130 | #define FUJLAPTOP_DBG_TRACE 0x0008 |
| 131 | 131 | ||
| 132 | #define dbg_printk(a_dbg_level, format, arg...) \ | 132 | #ifdef CONFIG_FUJITSU_LAPTOP_DEBUG |
| 133 | #define vdbg_printk(a_dbg_level, format, arg...) \ | ||
| 133 | do { if (dbg_level & a_dbg_level) \ | 134 | do { if (dbg_level & a_dbg_level) \ |
| 134 | printk(FUJLAPTOP_DEBUG "%s: " format, __func__ , ## arg); \ | 135 | printk(FUJLAPTOP_DEBUG "%s: " format, __func__ , ## arg); \ |
| 135 | } while (0) | 136 | } while (0) |
| 136 | #ifdef CONFIG_FUJITSU_LAPTOP_DEBUG | ||
| 137 | #define vdbg_printk(a_dbg_level, format, arg...) \ | ||
| 138 | dbg_printk(a_dbg_level, format, ## arg) | ||
| 139 | #else | 137 | #else |
| 140 | #define vdbg_printk(a_dbg_level, format, arg...) | 138 | #define vdbg_printk(a_dbg_level, format, arg...) \ |
| 139 | do { } while (0) | ||
| 141 | #endif | 140 | #endif |
| 142 | 141 | ||
| 143 | /* Device controlling the backlight and associated keys */ | 142 | /* Device controlling the backlight and associated keys */ |
| @@ -564,7 +563,7 @@ static struct platform_driver fujitsupf_driver = { | |||
| 564 | } | 563 | } |
| 565 | }; | 564 | }; |
| 566 | 565 | ||
| 567 | static void dmi_check_cb_common(const struct dmi_system_id *id) | 566 | static void __init dmi_check_cb_common(const struct dmi_system_id *id) |
| 568 | { | 567 | { |
| 569 | pr_info("Identified laptop model '%s'\n", id->ident); | 568 | pr_info("Identified laptop model '%s'\n", id->ident); |
| 570 | if (use_alt_lcd_levels == -1) { | 569 | if (use_alt_lcd_levels == -1) { |
| @@ -578,7 +577,7 @@ static void dmi_check_cb_common(const struct dmi_system_id *id) | |||
| 578 | } | 577 | } |
| 579 | } | 578 | } |
| 580 | 579 | ||
| 581 | static int dmi_check_cb_s6410(const struct dmi_system_id *id) | 580 | static int __init dmi_check_cb_s6410(const struct dmi_system_id *id) |
| 582 | { | 581 | { |
| 583 | dmi_check_cb_common(id); | 582 | dmi_check_cb_common(id); |
| 584 | fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */ | 583 | fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */ |
| @@ -586,7 +585,7 @@ static int dmi_check_cb_s6410(const struct dmi_system_id *id) | |||
| 586 | return 1; | 585 | return 1; |
| 587 | } | 586 | } |
| 588 | 587 | ||
| 589 | static int dmi_check_cb_s6420(const struct dmi_system_id *id) | 588 | static int __init dmi_check_cb_s6420(const struct dmi_system_id *id) |
| 590 | { | 589 | { |
| 591 | dmi_check_cb_common(id); | 590 | dmi_check_cb_common(id); |
| 592 | fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */ | 591 | fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */ |
| @@ -594,7 +593,7 @@ static int dmi_check_cb_s6420(const struct dmi_system_id *id) | |||
| 594 | return 1; | 593 | return 1; |
| 595 | } | 594 | } |
| 596 | 595 | ||
| 597 | static int dmi_check_cb_p8010(const struct dmi_system_id *id) | 596 | static int __init dmi_check_cb_p8010(const struct dmi_system_id *id) |
| 598 | { | 597 | { |
| 599 | dmi_check_cb_common(id); | 598 | dmi_check_cb_common(id); |
| 600 | fujitsu->keycode1 = KEY_HELP; /* "Support" */ | 599 | fujitsu->keycode1 = KEY_HELP; /* "Support" */ |
| @@ -603,7 +602,7 @@ static int dmi_check_cb_p8010(const struct dmi_system_id *id) | |||
| 603 | return 1; | 602 | return 1; |
| 604 | } | 603 | } |
| 605 | 604 | ||
| 606 | static struct dmi_system_id fujitsu_dmi_table[] = { | 605 | static const struct dmi_system_id fujitsu_dmi_table[] __initconst = { |
| 607 | { | 606 | { |
| 608 | .ident = "Fujitsu Siemens S6410", | 607 | .ident = "Fujitsu Siemens S6410", |
| 609 | .matches = { | 608 | .matches = { |
diff --git a/drivers/platform/x86/fujitsu-tablet.c b/drivers/platform/x86/fujitsu-tablet.c index c3784baceae3..53bdbb01bd3f 100644 --- a/drivers/platform/x86/fujitsu-tablet.c +++ b/drivers/platform/x86/fujitsu-tablet.c | |||
| @@ -315,21 +315,21 @@ static irqreturn_t fujitsu_interrupt(int irq, void *dev_id) | |||
| 315 | return IRQ_HANDLED; | 315 | return IRQ_HANDLED; |
| 316 | } | 316 | } |
| 317 | 317 | ||
| 318 | static void fujitsu_dmi_common(const struct dmi_system_id *dmi) | 318 | static void __init fujitsu_dmi_common(const struct dmi_system_id *dmi) |
| 319 | { | 319 | { |
| 320 | pr_info("%s\n", dmi->ident); | 320 | pr_info("%s\n", dmi->ident); |
| 321 | memcpy(fujitsu.config.keymap, dmi->driver_data, | 321 | memcpy(fujitsu.config.keymap, dmi->driver_data, |
| 322 | sizeof(fujitsu.config.keymap)); | 322 | sizeof(fujitsu.config.keymap)); |
| 323 | } | 323 | } |
| 324 | 324 | ||
| 325 | static int fujitsu_dmi_lifebook(const struct dmi_system_id *dmi) | 325 | static int __init fujitsu_dmi_lifebook(const struct dmi_system_id *dmi) |
| 326 | { | 326 | { |
| 327 | fujitsu_dmi_common(dmi); | 327 | fujitsu_dmi_common(dmi); |
| 328 | fujitsu.config.quirks |= INVERT_TABLET_MODE_BIT; | 328 | fujitsu.config.quirks |= INVERT_TABLET_MODE_BIT; |
| 329 | return 1; | 329 | return 1; |
| 330 | } | 330 | } |
| 331 | 331 | ||
| 332 | static int fujitsu_dmi_stylistic(const struct dmi_system_id *dmi) | 332 | static int __init fujitsu_dmi_stylistic(const struct dmi_system_id *dmi) |
| 333 | { | 333 | { |
| 334 | fujitsu_dmi_common(dmi); | 334 | fujitsu_dmi_common(dmi); |
| 335 | fujitsu.config.quirks |= FORCE_TABLET_MODE_IF_UNDOCK; | 335 | fujitsu.config.quirks |= FORCE_TABLET_MODE_IF_UNDOCK; |
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 484a8673b835..4c559640dcba 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c | |||
| @@ -295,7 +295,7 @@ static int hp_wmi_tablet_state(void) | |||
| 295 | return (state & 0x4) ? 1 : 0; | 295 | return (state & 0x4) ? 1 : 0; |
| 296 | } | 296 | } |
| 297 | 297 | ||
| 298 | static int hp_wmi_bios_2009_later(void) | 298 | static int __init hp_wmi_bios_2009_later(void) |
| 299 | { | 299 | { |
| 300 | int state = 0; | 300 | int state = 0; |
| 301 | int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, 0, &state, | 301 | int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, 0, &state, |
| @@ -704,7 +704,7 @@ static void cleanup_sysfs(struct platform_device *device) | |||
| 704 | device_remove_file(&device->dev, &dev_attr_postcode); | 704 | device_remove_file(&device->dev, &dev_attr_postcode); |
| 705 | } | 705 | } |
| 706 | 706 | ||
| 707 | static int hp_wmi_rfkill_setup(struct platform_device *device) | 707 | static int __init hp_wmi_rfkill_setup(struct platform_device *device) |
| 708 | { | 708 | { |
| 709 | int err; | 709 | int err; |
| 710 | int wireless = 0; | 710 | int wireless = 0; |
| @@ -806,7 +806,7 @@ register_wifi_error: | |||
| 806 | return err; | 806 | return err; |
| 807 | } | 807 | } |
| 808 | 808 | ||
| 809 | static int hp_wmi_rfkill2_setup(struct platform_device *device) | 809 | static int __init hp_wmi_rfkill2_setup(struct platform_device *device) |
| 810 | { | 810 | { |
| 811 | int err, i; | 811 | int err, i; |
| 812 | struct bios_rfkill2_state state; | 812 | struct bios_rfkill2_state state; |
diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c index 3dc934438c28..13e14ec1d3d7 100644 --- a/drivers/platform/x86/hp_accel.c +++ b/drivers/platform/x86/hp_accel.c | |||
| @@ -74,7 +74,7 @@ static inline void delayed_sysfs_set(struct led_classdev *led_cdev, | |||
| 74 | /* HP-specific accelerometer driver ------------------------------------ */ | 74 | /* HP-specific accelerometer driver ------------------------------------ */ |
| 75 | 75 | ||
| 76 | /* For automatic insertion of the module */ | 76 | /* For automatic insertion of the module */ |
| 77 | static struct acpi_device_id lis3lv02d_device_ids[] = { | 77 | static const struct acpi_device_id lis3lv02d_device_ids[] = { |
| 78 | {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */ | 78 | {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */ |
| 79 | {"HPQ6000", 0}, /* HP Mobile Data Protection System PNP */ | 79 | {"HPQ6000", 0}, /* HP Mobile Data Protection System PNP */ |
| 80 | {"HPQ6007", 0}, /* HP Mobile Data Protection System PNP */ | 80 | {"HPQ6007", 0}, /* HP Mobile Data Protection System PNP */ |
| @@ -192,7 +192,7 @@ DEFINE_CONV(xy_swap_yz_inverted, 2, -1, -3); | |||
| 192 | }, \ | 192 | }, \ |
| 193 | .driver_data = &lis3lv02d_axis_##_axis \ | 193 | .driver_data = &lis3lv02d_axis_##_axis \ |
| 194 | } | 194 | } |
| 195 | static struct dmi_system_id lis3lv02d_dmi_ids[] = { | 195 | static const struct dmi_system_id lis3lv02d_dmi_ids[] = { |
| 196 | /* product names are truncated to match all kinds of a same model */ | 196 | /* product names are truncated to match all kinds of a same model */ |
| 197 | AXIS_DMI_MATCH("NC64x0", "HP Compaq nc64", x_inverted), | 197 | AXIS_DMI_MATCH("NC64x0", "HP Compaq nc64", x_inverted), |
| 198 | AXIS_DMI_MATCH("NC84x0", "HP Compaq nc84", z_inverted), | 198 | AXIS_DMI_MATCH("NC84x0", "HP Compaq nc84", z_inverted), |
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index b4c495a62eec..fc468a3d95ce 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c | |||
| @@ -87,6 +87,8 @@ struct ideapad_private { | |||
| 87 | struct backlight_device *blightdev; | 87 | struct backlight_device *blightdev; |
| 88 | struct dentry *debug; | 88 | struct dentry *debug; |
| 89 | unsigned long cfg; | 89 | unsigned long cfg; |
| 90 | bool has_hw_rfkill_switch; | ||
| 91 | bool has_touchpad_control; | ||
| 90 | }; | 92 | }; |
| 91 | 93 | ||
| 92 | static bool no_bt_rfkill; | 94 | static bool no_bt_rfkill; |
| @@ -439,7 +441,7 @@ static umode_t ideapad_is_visible(struct kobject *kobj, | |||
| 439 | return supported ? attr->mode : 0; | 441 | return supported ? attr->mode : 0; |
| 440 | } | 442 | } |
| 441 | 443 | ||
| 442 | static struct attribute_group ideapad_attribute_group = { | 444 | static const struct attribute_group ideapad_attribute_group = { |
| 443 | .is_visible = ideapad_is_visible, | 445 | .is_visible = ideapad_is_visible, |
| 444 | .attrs = ideapad_attributes | 446 | .attrs = ideapad_attributes |
| 445 | }; | 447 | }; |
| @@ -454,7 +456,7 @@ struct ideapad_rfk_data { | |||
| 454 | int type; | 456 | int type; |
| 455 | }; | 457 | }; |
| 456 | 458 | ||
| 457 | const struct ideapad_rfk_data ideapad_rfk_data[] = { | 459 | const const struct ideapad_rfk_data ideapad_rfk_data[] = { |
| 458 | { "ideapad_wlan", CFG_WIFI_BIT, VPCCMD_W_WIFI, RFKILL_TYPE_WLAN }, | 460 | { "ideapad_wlan", CFG_WIFI_BIT, VPCCMD_W_WIFI, RFKILL_TYPE_WLAN }, |
| 459 | { "ideapad_bluetooth", CFG_BT_BIT, VPCCMD_W_BT, RFKILL_TYPE_BLUETOOTH }, | 461 | { "ideapad_bluetooth", CFG_BT_BIT, VPCCMD_W_BT, RFKILL_TYPE_BLUETOOTH }, |
| 460 | { "ideapad_3g", CFG_3G_BIT, VPCCMD_W_3G, RFKILL_TYPE_WWAN }, | 462 | { "ideapad_3g", CFG_3G_BIT, VPCCMD_W_3G, RFKILL_TYPE_WWAN }, |
| @@ -473,12 +475,14 @@ static struct rfkill_ops ideapad_rfk_ops = { | |||
| 473 | 475 | ||
| 474 | static void ideapad_sync_rfk_state(struct ideapad_private *priv) | 476 | static void ideapad_sync_rfk_state(struct ideapad_private *priv) |
| 475 | { | 477 | { |
| 476 | unsigned long hw_blocked; | 478 | unsigned long hw_blocked = 0; |
| 477 | int i; | 479 | int i; |
| 478 | 480 | ||
| 479 | if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked)) | 481 | if (priv->has_hw_rfkill_switch) { |
| 480 | return; | 482 | if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked)) |
| 481 | hw_blocked = !hw_blocked; | 483 | return; |
| 484 | hw_blocked = !hw_blocked; | ||
| 485 | } | ||
| 482 | 486 | ||
| 483 | for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) | 487 | for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) |
| 484 | if (priv->rfk[i]) | 488 | if (priv->rfk[i]) |
| @@ -763,6 +767,9 @@ static void ideapad_sync_touchpad_state(struct ideapad_private *priv) | |||
| 763 | { | 767 | { |
| 764 | unsigned long value; | 768 | unsigned long value; |
| 765 | 769 | ||
| 770 | if (!priv->has_touchpad_control) | ||
| 771 | return; | ||
| 772 | |||
| 766 | /* Without reading from EC touchpad LED doesn't switch state */ | 773 | /* Without reading from EC touchpad LED doesn't switch state */ |
| 767 | if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) { | 774 | if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) { |
| 768 | /* Some IdeaPads don't really turn off touchpad - they only | 775 | /* Some IdeaPads don't really turn off touchpad - they only |
| @@ -821,14 +828,39 @@ static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data) | |||
| 821 | } | 828 | } |
| 822 | } | 829 | } |
| 823 | 830 | ||
| 824 | /* Blacklist for devices where the ideapad rfkill interface does not work */ | 831 | /* |
| 825 | static struct dmi_system_id rfkill_blacklist[] = { | 832 | * Some ideapads don't have a hardware rfkill switch, reading VPCCMD_R_RF |
| 826 | /* The Lenovo Yoga 2 11 always reports everything as blocked */ | 833 | * always results in 0 on these models, causing ideapad_laptop to wrongly |
| 834 | * report all radios as hardware-blocked. | ||
| 835 | */ | ||
| 836 | static struct dmi_system_id no_hw_rfkill_list[] = { | ||
| 827 | { | 837 | { |
| 828 | .ident = "Lenovo Yoga 2 11", | 838 | .ident = "Lenovo Yoga 2 11 / 13 / Pro", |
| 829 | .matches = { | 839 | .matches = { |
| 830 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | 840 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
| 831 | DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2 11"), | 841 | DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2"), |
| 842 | }, | ||
| 843 | }, | ||
| 844 | {} | ||
| 845 | }; | ||
| 846 | |||
| 847 | /* | ||
| 848 | * Some models don't offer touchpad ctrl through the ideapad interface, causing | ||
| 849 | * ideapad_sync_touchpad_state to send wrong touchpad enable/disable events. | ||
| 850 | */ | ||
| 851 | static struct dmi_system_id no_touchpad_ctrl_list[] = { | ||
| 852 | { | ||
| 853 | .ident = "Lenovo Yoga 1 series", | ||
| 854 | .matches = { | ||
| 855 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
| 856 | DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo IdeaPad Yoga"), | ||
| 857 | }, | ||
| 858 | }, | ||
| 859 | { | ||
| 860 | .ident = "Lenovo Yoga 2 11 / 13 / Pro", | ||
| 861 | .matches = { | ||
| 862 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
| 863 | DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2"), | ||
| 832 | }, | 864 | }, |
| 833 | }, | 865 | }, |
| 834 | {} | 866 | {} |
| @@ -856,6 +888,8 @@ static int ideapad_acpi_add(struct platform_device *pdev) | |||
| 856 | priv->cfg = cfg; | 888 | priv->cfg = cfg; |
| 857 | priv->adev = adev; | 889 | priv->adev = adev; |
| 858 | priv->platform_device = pdev; | 890 | priv->platform_device = pdev; |
| 891 | priv->has_hw_rfkill_switch = !dmi_check_system(no_hw_rfkill_list); | ||
| 892 | priv->has_touchpad_control = !dmi_check_system(no_touchpad_ctrl_list); | ||
| 859 | 893 | ||
| 860 | ret = ideapad_sysfs_init(priv); | 894 | ret = ideapad_sysfs_init(priv); |
| 861 | if (ret) | 895 | if (ret) |
| @@ -869,11 +903,17 @@ static int ideapad_acpi_add(struct platform_device *pdev) | |||
| 869 | if (ret) | 903 | if (ret) |
| 870 | goto input_failed; | 904 | goto input_failed; |
| 871 | 905 | ||
| 872 | if (!dmi_check_system(rfkill_blacklist)) { | 906 | /* |
| 873 | for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) | 907 | * On some models without a hw-switch (the yoga 2 13 at least) |
| 874 | if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg)) | 908 | * VPCCMD_W_RF must be explicitly set to 1 for the wifi to work. |
| 875 | ideapad_register_rfkill(priv, i); | 909 | */ |
| 876 | } | 910 | if (!priv->has_hw_rfkill_switch) |
| 911 | write_ec_cmd(priv->adev->handle, VPCCMD_W_RF, 1); | ||
| 912 | |||
| 913 | for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) | ||
| 914 | if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg)) | ||
| 915 | ideapad_register_rfkill(priv, i); | ||
| 916 | |||
| 877 | ideapad_sync_rfk_state(priv); | 917 | ideapad_sync_rfk_state(priv); |
| 878 | ideapad_sync_touchpad_state(priv); | 918 | ideapad_sync_touchpad_state(priv); |
| 879 | 919 | ||
diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index a0d1f576cf40..c0242ed13d9e 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c | |||
| @@ -269,7 +269,7 @@ struct ips_mcp_limits { | |||
| 269 | 269 | ||
| 270 | /* Max temps are -10 degrees C to avoid PROCHOT# */ | 270 | /* Max temps are -10 degrees C to avoid PROCHOT# */ |
| 271 | 271 | ||
| 272 | struct ips_mcp_limits ips_sv_limits = { | 272 | static struct ips_mcp_limits ips_sv_limits = { |
| 273 | .mcp_power_limit = 35000, | 273 | .mcp_power_limit = 35000, |
| 274 | .core_power_limit = 29000, | 274 | .core_power_limit = 29000, |
| 275 | .mch_power_limit = 20000, | 275 | .mch_power_limit = 20000, |
| @@ -277,7 +277,7 @@ struct ips_mcp_limits ips_sv_limits = { | |||
| 277 | .mch_temp_limit = 90 | 277 | .mch_temp_limit = 90 |
| 278 | }; | 278 | }; |
| 279 | 279 | ||
| 280 | struct ips_mcp_limits ips_lv_limits = { | 280 | static struct ips_mcp_limits ips_lv_limits = { |
| 281 | .mcp_power_limit = 25000, | 281 | .mcp_power_limit = 25000, |
| 282 | .core_power_limit = 21000, | 282 | .core_power_limit = 21000, |
| 283 | .mch_power_limit = 13000, | 283 | .mch_power_limit = 13000, |
| @@ -285,7 +285,7 @@ struct ips_mcp_limits ips_lv_limits = { | |||
| 285 | .mch_temp_limit = 90 | 285 | .mch_temp_limit = 90 |
| 286 | }; | 286 | }; |
| 287 | 287 | ||
| 288 | struct ips_mcp_limits ips_ulv_limits = { | 288 | static struct ips_mcp_limits ips_ulv_limits = { |
| 289 | .mcp_power_limit = 18000, | 289 | .mcp_power_limit = 18000, |
| 290 | .core_power_limit = 14000, | 290 | .core_power_limit = 14000, |
| 291 | .mch_power_limit = 11000, | 291 | .mch_power_limit = 11000, |
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 9c5a07417b2b..26ad9ff12ac5 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c | |||
| @@ -2389,7 +2389,7 @@ static int sony_nc_lid_resume_setup(struct platform_device *pd, | |||
| 2389 | lid_ctl->attrs[LID_RESUME_S3].store = sony_nc_lid_resume_store; | 2389 | lid_ctl->attrs[LID_RESUME_S3].store = sony_nc_lid_resume_store; |
| 2390 | } | 2390 | } |
| 2391 | for (i = 0; i < LID_RESUME_MAX && | 2391 | for (i = 0; i < LID_RESUME_MAX && |
| 2392 | lid_ctl->attrs[LID_RESUME_S3].attr.name; i++) { | 2392 | lid_ctl->attrs[i].attr.name; i++) { |
| 2393 | result = device_create_file(&pd->dev, &lid_ctl->attrs[i]); | 2393 | result = device_create_file(&pd->dev, &lid_ctl->attrs[i]); |
| 2394 | if (result) | 2394 | if (result) |
| 2395 | goto liderror; | 2395 | goto liderror; |
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index d82f196e3cfe..3bbc6eb60de5 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
| @@ -3174,7 +3174,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
| 3174 | KEY_UNKNOWN, | 3174 | KEY_UNKNOWN, |
| 3175 | 3175 | ||
| 3176 | /* Extra keys in use since the X240 / T440 / T540 */ | 3176 | /* Extra keys in use since the X240 / T440 / T540 */ |
| 3177 | KEY_CONFIG, KEY_SEARCH, KEY_SCALE, KEY_COMPUTER, | 3177 | KEY_CONFIG, KEY_SEARCH, KEY_SCALE, KEY_FILE, |
| 3178 | }, | 3178 | }, |
| 3179 | }; | 3179 | }; |
| 3180 | 3180 | ||
| @@ -6144,7 +6144,7 @@ static int brightness_set(unsigned int value) | |||
| 6144 | { | 6144 | { |
| 6145 | int res; | 6145 | int res; |
| 6146 | 6146 | ||
| 6147 | if (value > bright_maxlvl || value < 0) | 6147 | if (value > bright_maxlvl) |
| 6148 | return -EINVAL; | 6148 | return -EINVAL; |
| 6149 | 6149 | ||
| 6150 | vdbg_printk(TPACPI_DBG_BRGHT, | 6150 | vdbg_printk(TPACPI_DBG_BRGHT, |
| @@ -6860,7 +6860,7 @@ static int volume_alsa_mute_put(struct snd_kcontrol *kcontrol, | |||
| 6860 | return volume_alsa_set_mute(!ucontrol->value.integer.value[0]); | 6860 | return volume_alsa_set_mute(!ucontrol->value.integer.value[0]); |
| 6861 | } | 6861 | } |
| 6862 | 6862 | ||
| 6863 | static struct snd_kcontrol_new volume_alsa_control_vol = { | 6863 | static struct snd_kcontrol_new volume_alsa_control_vol __initdata = { |
| 6864 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 6864 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
| 6865 | .name = "Console Playback Volume", | 6865 | .name = "Console Playback Volume", |
| 6866 | .index = 0, | 6866 | .index = 0, |
| @@ -6869,7 +6869,7 @@ static struct snd_kcontrol_new volume_alsa_control_vol = { | |||
| 6869 | .get = volume_alsa_vol_get, | 6869 | .get = volume_alsa_vol_get, |
| 6870 | }; | 6870 | }; |
| 6871 | 6871 | ||
| 6872 | static struct snd_kcontrol_new volume_alsa_control_mute = { | 6872 | static struct snd_kcontrol_new volume_alsa_control_mute __initdata = { |
| 6873 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 6873 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
| 6874 | .name = "Console Playback Switch", | 6874 | .name = "Console Playback Switch", |
| 6875 | .index = 0, | 6875 | .index = 0, |
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 76441dcbe5ff..b062d3d7b373 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c | |||
| @@ -222,6 +222,12 @@ static const struct dmi_system_id toshiba_alt_keymap_dmi[] = { | |||
| 222 | DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M840"), | 222 | DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M840"), |
| 223 | }, | 223 | }, |
| 224 | }, | 224 | }, |
| 225 | { | ||
| 226 | .matches = { | ||
| 227 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | ||
| 228 | DMI_MATCH(DMI_PRODUCT_NAME, "Qosmio X75-A"), | ||
| 229 | }, | ||
| 230 | }, | ||
| 225 | {} | 231 | {} |
| 226 | }; | 232 | }; |
| 227 | 233 | ||
| @@ -229,6 +235,7 @@ static const struct key_entry toshiba_acpi_alt_keymap[] = { | |||
| 229 | { KE_KEY, 0x157, { KEY_MUTE } }, | 235 | { KE_KEY, 0x157, { KEY_MUTE } }, |
| 230 | { KE_KEY, 0x102, { KEY_ZOOMOUT } }, | 236 | { KE_KEY, 0x102, { KEY_ZOOMOUT } }, |
| 231 | { KE_KEY, 0x103, { KEY_ZOOMIN } }, | 237 | { KE_KEY, 0x103, { KEY_ZOOMIN } }, |
| 238 | { KE_KEY, 0x12c, { KEY_KBDILLUMTOGGLE } }, | ||
| 232 | { KE_KEY, 0x139, { KEY_ZOOMRESET } }, | 239 | { KE_KEY, 0x139, { KEY_ZOOMRESET } }, |
| 233 | { KE_KEY, 0x13e, { KEY_SWITCHVIDEOMODE } }, | 240 | { KE_KEY, 0x13e, { KEY_SWITCHVIDEOMODE } }, |
| 234 | { KE_KEY, 0x13c, { KEY_BRIGHTNESSDOWN } }, | 241 | { KE_KEY, 0x13c, { KEY_BRIGHTNESSDOWN } }, |
| @@ -872,7 +879,9 @@ static int lcd_proc_open(struct inode *inode, struct file *file) | |||
| 872 | 879 | ||
| 873 | static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value) | 880 | static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value) |
| 874 | { | 881 | { |
| 875 | u32 hci_result; | 882 | u32 in[HCI_WORDS] = { HCI_SET, HCI_LCD_BRIGHTNESS, 0, 0, 0, 0 }; |
| 883 | u32 out[HCI_WORDS]; | ||
| 884 | acpi_status status; | ||
| 876 | 885 | ||
| 877 | if (dev->tr_backlight_supported) { | 886 | if (dev->tr_backlight_supported) { |
| 878 | bool enable = !value; | 887 | bool enable = !value; |
| @@ -883,9 +892,20 @@ static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value) | |||
| 883 | value--; | 892 | value--; |
| 884 | } | 893 | } |
| 885 | 894 | ||
| 886 | value = value << HCI_LCD_BRIGHTNESS_SHIFT; | 895 | in[2] = value << HCI_LCD_BRIGHTNESS_SHIFT; |
| 887 | hci_write1(dev, HCI_LCD_BRIGHTNESS, value, &hci_result); | 896 | status = hci_raw(dev, in, out); |
| 888 | return hci_result == HCI_SUCCESS ? 0 : -EIO; | 897 | if (ACPI_FAILURE(status) || out[0] == HCI_FAILURE) { |
| 898 | pr_err("ACPI call to set brightness failed"); | ||
| 899 | return -EIO; | ||
| 900 | } | ||
| 901 | /* Extra check for "incomplete" backlight method, where the AML code | ||
| 902 | * doesn't check for HCI_SET or HCI_GET and returns HCI_SUCCESS, | ||
| 903 | * the actual brightness, and in some cases the max brightness. | ||
| 904 | */ | ||
| 905 | if (out[2] > 0 || out[3] == 0xE000) | ||
| 906 | return -ENODEV; | ||
| 907 | |||
| 908 | return out[0] == HCI_SUCCESS ? 0 : -EIO; | ||
| 889 | } | 909 | } |
| 890 | 910 | ||
| 891 | static int set_lcd_status(struct backlight_device *bd) | 911 | static int set_lcd_status(struct backlight_device *bd) |
diff --git a/drivers/platform/x86/toshiba_haps.c b/drivers/platform/x86/toshiba_haps.c new file mode 100644 index 000000000000..65300b6a84b9 --- /dev/null +++ b/drivers/platform/x86/toshiba_haps.c | |||
| @@ -0,0 +1,265 @@ | |||
| 1 | /* | ||
| 2 | * Toshiba HDD Active Protection Sensor (HAPS) driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014 Azael Avalos <coproscefalo@gmail.com> | ||
| 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 | */ | ||
| 17 | |||
| 18 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 19 | |||
| 20 | #include <linux/kernel.h> | ||
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/init.h> | ||
| 23 | #include <linux/types.h> | ||
| 24 | #include <linux/acpi.h> | ||
| 25 | |||
| 26 | MODULE_AUTHOR("Azael Avalos <coproscefalo@gmail.com>"); | ||
| 27 | MODULE_DESCRIPTION("Toshiba HDD Active Protection Sensor"); | ||
| 28 | MODULE_LICENSE("GPL"); | ||
| 29 | |||
| 30 | struct toshiba_haps_dev { | ||
| 31 | struct acpi_device *acpi_dev; | ||
| 32 | |||
| 33 | int protection_level; | ||
| 34 | }; | ||
| 35 | |||
| 36 | static struct toshiba_haps_dev *toshiba_haps; | ||
| 37 | |||
| 38 | /* HAPS functions */ | ||
| 39 | static int toshiba_haps_reset_protection(acpi_handle handle) | ||
| 40 | { | ||
| 41 | acpi_status status; | ||
| 42 | |||
| 43 | status = acpi_evaluate_object(handle, "RSSS", NULL, NULL); | ||
| 44 | if (ACPI_FAILURE(status)) { | ||
| 45 | pr_err("Unable to reset the HDD protection\n"); | ||
| 46 | return -EIO; | ||
| 47 | } | ||
| 48 | |||
| 49 | return 0; | ||
| 50 | } | ||
| 51 | |||
| 52 | static int toshiba_haps_protection_level(acpi_handle handle, int level) | ||
| 53 | { | ||
| 54 | acpi_status status; | ||
| 55 | |||
| 56 | status = acpi_execute_simple_method(handle, "PTLV", level); | ||
| 57 | if (ACPI_FAILURE(status)) { | ||
| 58 | pr_err("Error while setting the protection level\n"); | ||
| 59 | return -EIO; | ||
| 60 | } | ||
| 61 | |||
| 62 | pr_info("HDD protection level set to: %d\n", level); | ||
| 63 | |||
| 64 | return 0; | ||
| 65 | } | ||
| 66 | |||
| 67 | /* sysfs files */ | ||
| 68 | static ssize_t protection_level_show(struct device *dev, | ||
| 69 | struct device_attribute *attr, char *buf) | ||
| 70 | { | ||
| 71 | struct toshiba_haps_dev *haps = dev_get_drvdata(dev); | ||
| 72 | |||
| 73 | return sprintf(buf, "%i\n", haps->protection_level); | ||
| 74 | } | ||
| 75 | |||
| 76 | static ssize_t protection_level_store(struct device *dev, | ||
| 77 | struct device_attribute *attr, | ||
| 78 | const char *buf, size_t count) | ||
| 79 | { | ||
| 80 | struct toshiba_haps_dev *haps = dev_get_drvdata(dev); | ||
| 81 | int level, ret; | ||
| 82 | |||
| 83 | if (sscanf(buf, "%d", &level) != 1 || level < 0 || level > 3) | ||
| 84 | return -EINVAL; | ||
| 85 | |||
| 86 | /* Set the sensor level. | ||
| 87 | * Acceptable levels are: | ||
| 88 | * 0 - Disabled | 1 - Low | 2 - Medium | 3 - High | ||
| 89 | */ | ||
| 90 | ret = toshiba_haps_protection_level(haps->acpi_dev->handle, level); | ||
| 91 | if (ret != 0) | ||
| 92 | return ret; | ||
| 93 | |||
| 94 | haps->protection_level = level; | ||
| 95 | |||
| 96 | return count; | ||
| 97 | } | ||
| 98 | |||
| 99 | static ssize_t reset_protection_store(struct device *dev, | ||
| 100 | struct device_attribute *attr, | ||
| 101 | const char *buf, size_t count) | ||
| 102 | { | ||
| 103 | struct toshiba_haps_dev *haps = dev_get_drvdata(dev); | ||
| 104 | int reset, ret; | ||
| 105 | |||
| 106 | if (sscanf(buf, "%d", &reset) != 1 || reset != 1) | ||
| 107 | return -EINVAL; | ||
| 108 | |||
| 109 | /* Reset the protection interface */ | ||
| 110 | ret = toshiba_haps_reset_protection(haps->acpi_dev->handle); | ||
| 111 | if (ret != 0) | ||
| 112 | return ret; | ||
| 113 | |||
| 114 | return count; | ||
| 115 | } | ||
| 116 | |||
| 117 | static DEVICE_ATTR(protection_level, S_IRUGO | S_IWUSR, | ||
| 118 | protection_level_show, protection_level_store); | ||
| 119 | static DEVICE_ATTR(reset_protection, S_IWUSR, NULL, reset_protection_store); | ||
| 120 | |||
| 121 | static struct attribute *haps_attributes[] = { | ||
| 122 | &dev_attr_protection_level.attr, | ||
| 123 | &dev_attr_reset_protection.attr, | ||
| 124 | NULL, | ||
| 125 | }; | ||
| 126 | |||
| 127 | static struct attribute_group haps_attr_group = { | ||
| 128 | .attrs = haps_attributes, | ||
| 129 | }; | ||
| 130 | |||
| 131 | /* | ||
| 132 | * ACPI stuff | ||
| 133 | */ | ||
| 134 | static void toshiba_haps_notify(struct acpi_device *device, u32 event) | ||
| 135 | { | ||
| 136 | pr_info("Received event: 0x%x", event); | ||
| 137 | |||
| 138 | acpi_bus_generate_netlink_event(device->pnp.device_class, | ||
| 139 | dev_name(&device->dev), | ||
| 140 | event, 0); | ||
| 141 | } | ||
| 142 | |||
| 143 | static int toshiba_haps_remove(struct acpi_device *device) | ||
| 144 | { | ||
| 145 | sysfs_remove_group(&device->dev.kobj, &haps_attr_group); | ||
| 146 | |||
| 147 | if (toshiba_haps) | ||
| 148 | toshiba_haps = NULL; | ||
| 149 | |||
| 150 | return 0; | ||
| 151 | } | ||
| 152 | |||
| 153 | /* Helper function */ | ||
| 154 | static int toshiba_haps_available(acpi_handle handle) | ||
| 155 | { | ||
| 156 | acpi_status status; | ||
| 157 | u64 hdd_present; | ||
| 158 | |||
| 159 | /* | ||
| 160 | * A non existent device as well as having (only) | ||
| 161 | * Solid State Drives can cause the call to fail. | ||
| 162 | */ | ||
| 163 | status = acpi_evaluate_integer(handle, "_STA", NULL, | ||
| 164 | &hdd_present); | ||
| 165 | if (ACPI_FAILURE(status) || !hdd_present) { | ||
| 166 | pr_info("HDD protection not available or using SSD\n"); | ||
| 167 | return 0; | ||
| 168 | } | ||
| 169 | |||
| 170 | return 1; | ||
| 171 | } | ||
| 172 | |||
| 173 | static int toshiba_haps_add(struct acpi_device *acpi_dev) | ||
| 174 | { | ||
| 175 | struct toshiba_haps_dev *haps; | ||
| 176 | int ret; | ||
| 177 | |||
| 178 | if (toshiba_haps) | ||
| 179 | return -EBUSY; | ||
| 180 | |||
| 181 | if (!toshiba_haps_available(acpi_dev->handle)) | ||
| 182 | return -ENODEV; | ||
| 183 | |||
| 184 | pr_info("Toshiba HDD Active Protection Sensor device\n"); | ||
| 185 | |||
| 186 | haps = kzalloc(sizeof(struct toshiba_haps_dev), GFP_KERNEL); | ||
| 187 | if (!haps) | ||
| 188 | return -ENOMEM; | ||
| 189 | |||
| 190 | haps->acpi_dev = acpi_dev; | ||
| 191 | haps->protection_level = 2; | ||
| 192 | acpi_dev->driver_data = haps; | ||
| 193 | dev_set_drvdata(&acpi_dev->dev, haps); | ||
| 194 | |||
| 195 | /* Set the protection level, currently at level 2 (Medium) */ | ||
| 196 | ret = toshiba_haps_protection_level(acpi_dev->handle, 2); | ||
| 197 | if (ret != 0) | ||
| 198 | return ret; | ||
| 199 | |||
| 200 | ret = sysfs_create_group(&acpi_dev->dev.kobj, &haps_attr_group); | ||
| 201 | if (ret) | ||
| 202 | return ret; | ||
| 203 | |||
| 204 | toshiba_haps = haps; | ||
| 205 | |||
| 206 | return 0; | ||
| 207 | } | ||
| 208 | |||
| 209 | #ifdef CONFIG_PM_SLEEP | ||
| 210 | static int toshiba_haps_suspend(struct device *device) | ||
| 211 | { | ||
| 212 | struct toshiba_haps_dev *haps; | ||
| 213 | int ret; | ||
| 214 | |||
| 215 | haps = acpi_driver_data(to_acpi_device(device)); | ||
| 216 | |||
| 217 | /* Deactivate the protection on suspend */ | ||
| 218 | ret = toshiba_haps_protection_level(haps->acpi_dev->handle, 0); | ||
| 219 | |||
| 220 | return ret; | ||
| 221 | } | ||
| 222 | |||
| 223 | static int toshiba_haps_resume(struct device *device) | ||
| 224 | { | ||
| 225 | struct toshiba_haps_dev *haps; | ||
| 226 | int ret; | ||
| 227 | |||
| 228 | haps = acpi_driver_data(to_acpi_device(device)); | ||
| 229 | |||
| 230 | /* Set the stored protection level */ | ||
| 231 | ret = toshiba_haps_protection_level(haps->acpi_dev->handle, | ||
| 232 | haps->protection_level); | ||
| 233 | |||
| 234 | /* Reset the protection on resume */ | ||
| 235 | ret = toshiba_haps_reset_protection(haps->acpi_dev->handle); | ||
| 236 | if (ret != 0) | ||
| 237 | return ret; | ||
| 238 | |||
| 239 | return ret; | ||
| 240 | } | ||
| 241 | #endif | ||
| 242 | |||
| 243 | static SIMPLE_DEV_PM_OPS(toshiba_haps_pm, | ||
| 244 | toshiba_haps_suspend, toshiba_haps_resume); | ||
| 245 | |||
| 246 | static const struct acpi_device_id haps_device_ids[] = { | ||
| 247 | {"TOS620A", 0}, | ||
| 248 | {"", 0}, | ||
| 249 | }; | ||
| 250 | MODULE_DEVICE_TABLE(acpi, haps_device_ids); | ||
| 251 | |||
| 252 | static struct acpi_driver toshiba_haps_driver = { | ||
| 253 | .name = "Toshiba HAPS", | ||
| 254 | .owner = THIS_MODULE, | ||
| 255 | .ids = haps_device_ids, | ||
| 256 | .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, | ||
| 257 | .ops = { | ||
| 258 | .add = toshiba_haps_add, | ||
| 259 | .remove = toshiba_haps_remove, | ||
| 260 | .notify = toshiba_haps_notify, | ||
| 261 | }, | ||
| 262 | .drv.pm = &toshiba_haps_pm, | ||
| 263 | }; | ||
| 264 | |||
| 265 | module_acpi_driver(toshiba_haps_driver); | ||
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 43d13295e63d..737e56d46f61 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c | |||
| @@ -256,10 +256,6 @@ static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable) | |||
| 256 | block = &wblock->gblock; | 256 | block = &wblock->gblock; |
| 257 | handle = wblock->handle; | 257 | handle = wblock->handle; |
| 258 | 258 | ||
| 259 | if (!block) | ||
| 260 | return AE_NOT_EXIST; | ||
| 261 | |||
| 262 | |||
| 263 | snprintf(method, 5, "WE%02X", block->notify_id); | 259 | snprintf(method, 5, "WE%02X", block->notify_id); |
| 264 | status = acpi_execute_simple_method(handle, method, enable); | 260 | status = acpi_execute_simple_method(handle, method, enable); |
| 265 | 261 | ||
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index f9f3a1224dfa..ea025e4806b6 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
| @@ -2097,7 +2097,7 @@ static void iscsi_check_transport_timeouts(unsigned long data) | |||
| 2097 | conn->ping_timeout, conn->recv_timeout, | 2097 | conn->ping_timeout, conn->recv_timeout, |
| 2098 | last_recv, conn->last_ping, jiffies); | 2098 | last_recv, conn->last_ping, jiffies); |
| 2099 | spin_unlock(&session->frwd_lock); | 2099 | spin_unlock(&session->frwd_lock); |
| 2100 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); | 2100 | iscsi_conn_failure(conn, ISCSI_ERR_NOP_TIMEDOUT); |
| 2101 | return; | 2101 | return; |
| 2102 | } | 2102 | } |
| 2103 | 2103 | ||
diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c index d3a08aea0948..7abbf284da1a 100644 --- a/drivers/scsi/pm8001/pm8001_ctl.c +++ b/drivers/scsi/pm8001/pm8001_ctl.c | |||
| @@ -526,18 +526,19 @@ static int pm8001_set_nvmd(struct pm8001_hba_info *pm8001_ha) | |||
| 526 | { | 526 | { |
| 527 | struct pm8001_ioctl_payload *payload; | 527 | struct pm8001_ioctl_payload *payload; |
| 528 | DECLARE_COMPLETION_ONSTACK(completion); | 528 | DECLARE_COMPLETION_ONSTACK(completion); |
| 529 | u8 *ioctlbuffer = NULL; | 529 | u8 *ioctlbuffer; |
| 530 | u32 length = 0; | 530 | u32 ret; |
| 531 | u32 ret = 0; | 531 | u32 length = 1024 * 5 + sizeof(*payload) - 1; |
| 532 | |||
| 533 | if (pm8001_ha->fw_image->size > 4096) { | ||
| 534 | pm8001_ha->fw_status = FAIL_FILE_SIZE; | ||
| 535 | return -EFAULT; | ||
| 536 | } | ||
| 532 | 537 | ||
| 533 | length = 1024 * 5 + sizeof(*payload) - 1; | ||
| 534 | ioctlbuffer = kzalloc(length, GFP_KERNEL); | 538 | ioctlbuffer = kzalloc(length, GFP_KERNEL); |
| 535 | if (!ioctlbuffer) | 539 | if (!ioctlbuffer) { |
| 540 | pm8001_ha->fw_status = FAIL_OUT_MEMORY; | ||
| 536 | return -ENOMEM; | 541 | return -ENOMEM; |
| 537 | if ((pm8001_ha->fw_image->size <= 0) || | ||
| 538 | (pm8001_ha->fw_image->size > 4096)) { | ||
| 539 | ret = FAIL_FILE_SIZE; | ||
| 540 | goto out; | ||
| 541 | } | 542 | } |
| 542 | payload = (struct pm8001_ioctl_payload *)ioctlbuffer; | 543 | payload = (struct pm8001_ioctl_payload *)ioctlbuffer; |
| 543 | memcpy((u8 *)&payload->func_specific, (u8 *)pm8001_ha->fw_image->data, | 544 | memcpy((u8 *)&payload->func_specific, (u8 *)pm8001_ha->fw_image->data, |
| @@ -547,6 +548,10 @@ static int pm8001_set_nvmd(struct pm8001_hba_info *pm8001_ha) | |||
| 547 | payload->minor_function = 0x1; | 548 | payload->minor_function = 0x1; |
| 548 | pm8001_ha->nvmd_completion = &completion; | 549 | pm8001_ha->nvmd_completion = &completion; |
| 549 | ret = PM8001_CHIP_DISP->set_nvmd_req(pm8001_ha, payload); | 550 | ret = PM8001_CHIP_DISP->set_nvmd_req(pm8001_ha, payload); |
| 551 | if (ret) { | ||
| 552 | pm8001_ha->fw_status = FAIL_OUT_MEMORY; | ||
| 553 | goto out; | ||
| 554 | } | ||
| 550 | wait_for_completion(&completion); | 555 | wait_for_completion(&completion); |
| 551 | out: | 556 | out: |
| 552 | kfree(ioctlbuffer); | 557 | kfree(ioctlbuffer); |
| @@ -557,35 +562,31 @@ static int pm8001_update_flash(struct pm8001_hba_info *pm8001_ha) | |||
| 557 | { | 562 | { |
| 558 | struct pm8001_ioctl_payload *payload; | 563 | struct pm8001_ioctl_payload *payload; |
| 559 | DECLARE_COMPLETION_ONSTACK(completion); | 564 | DECLARE_COMPLETION_ONSTACK(completion); |
| 560 | u8 *ioctlbuffer = NULL; | 565 | u8 *ioctlbuffer; |
| 561 | u32 length = 0; | ||
| 562 | struct fw_control_info *fwControl; | 566 | struct fw_control_info *fwControl; |
| 563 | u32 loopNumber, loopcount = 0; | ||
| 564 | u32 sizeRead = 0; | ||
| 565 | u32 partitionSize, partitionSizeTmp; | 567 | u32 partitionSize, partitionSizeTmp; |
| 566 | u32 ret = 0; | 568 | u32 loopNumber, loopcount; |
| 567 | u32 partitionNumber = 0; | ||
| 568 | struct pm8001_fw_image_header *image_hdr; | 569 | struct pm8001_fw_image_header *image_hdr; |
| 570 | u32 sizeRead = 0; | ||
| 571 | u32 ret = 0; | ||
| 572 | u32 length = 1024 * 16 + sizeof(*payload) - 1; | ||
| 569 | 573 | ||
| 570 | length = 1024 * 16 + sizeof(*payload) - 1; | 574 | if (pm8001_ha->fw_image->size < 28) { |
| 575 | pm8001_ha->fw_status = FAIL_FILE_SIZE; | ||
| 576 | return -EFAULT; | ||
| 577 | } | ||
| 571 | ioctlbuffer = kzalloc(length, GFP_KERNEL); | 578 | ioctlbuffer = kzalloc(length, GFP_KERNEL); |
| 572 | image_hdr = (struct pm8001_fw_image_header *)pm8001_ha->fw_image->data; | 579 | if (!ioctlbuffer) { |
| 573 | if (!ioctlbuffer) | 580 | pm8001_ha->fw_status = FAIL_OUT_MEMORY; |
| 574 | return -ENOMEM; | 581 | return -ENOMEM; |
| 575 | if (pm8001_ha->fw_image->size < 28) { | ||
| 576 | ret = FAIL_FILE_SIZE; | ||
| 577 | goto out; | ||
| 578 | } | 582 | } |
| 579 | 583 | image_hdr = (struct pm8001_fw_image_header *)pm8001_ha->fw_image->data; | |
| 580 | while (sizeRead < pm8001_ha->fw_image->size) { | 584 | while (sizeRead < pm8001_ha->fw_image->size) { |
| 581 | partitionSizeTmp = | 585 | partitionSizeTmp = |
| 582 | *(u32 *)((u8 *)&image_hdr->image_length + sizeRead); | 586 | *(u32 *)((u8 *)&image_hdr->image_length + sizeRead); |
| 583 | partitionSize = be32_to_cpu(partitionSizeTmp); | 587 | partitionSize = be32_to_cpu(partitionSizeTmp); |
| 584 | loopcount = (partitionSize + HEADER_LEN)/IOCTL_BUF_SIZE; | 588 | loopcount = DIV_ROUND_UP(partitionSize + HEADER_LEN, |
| 585 | if (loopcount % IOCTL_BUF_SIZE) | 589 | IOCTL_BUF_SIZE); |
| 586 | loopcount++; | ||
| 587 | if (loopcount == 0) | ||
| 588 | loopcount++; | ||
| 589 | for (loopNumber = 0; loopNumber < loopcount; loopNumber++) { | 590 | for (loopNumber = 0; loopNumber < loopcount; loopNumber++) { |
| 590 | payload = (struct pm8001_ioctl_payload *)ioctlbuffer; | 591 | payload = (struct pm8001_ioctl_payload *)ioctlbuffer; |
| 591 | payload->length = 1024*16; | 592 | payload->length = 1024*16; |
| @@ -617,18 +618,18 @@ static int pm8001_update_flash(struct pm8001_hba_info *pm8001_ha) | |||
| 617 | 618 | ||
| 618 | pm8001_ha->nvmd_completion = &completion; | 619 | pm8001_ha->nvmd_completion = &completion; |
| 619 | ret = PM8001_CHIP_DISP->fw_flash_update_req(pm8001_ha, payload); | 620 | ret = PM8001_CHIP_DISP->fw_flash_update_req(pm8001_ha, payload); |
| 620 | if (ret) | 621 | if (ret) { |
| 621 | break; | 622 | pm8001_ha->fw_status = FAIL_OUT_MEMORY; |
| 623 | goto out; | ||
| 624 | } | ||
| 622 | wait_for_completion(&completion); | 625 | wait_for_completion(&completion); |
| 623 | if (fwControl->retcode > FLASH_UPDATE_IN_PROGRESS) { | 626 | if (fwControl->retcode > FLASH_UPDATE_IN_PROGRESS) { |
| 624 | ret = fwControl->retcode; | 627 | pm8001_ha->fw_status = fwControl->retcode; |
| 625 | break; | 628 | ret = -EFAULT; |
| 629 | goto out; | ||
| 630 | } | ||
| 626 | } | 631 | } |
| 627 | } | 632 | } |
| 628 | if (ret) | ||
| 629 | break; | ||
| 630 | partitionNumber++; | ||
| 631 | } | ||
| 632 | out: | 633 | out: |
| 633 | kfree(ioctlbuffer); | 634 | kfree(ioctlbuffer); |
| 634 | return ret; | 635 | return ret; |
| @@ -643,22 +644,29 @@ static ssize_t pm8001_store_update_fw(struct device *cdev, | |||
| 643 | char *cmd_ptr, *filename_ptr; | 644 | char *cmd_ptr, *filename_ptr; |
| 644 | int res, i; | 645 | int res, i; |
| 645 | int flash_command = FLASH_CMD_NONE; | 646 | int flash_command = FLASH_CMD_NONE; |
| 646 | int err = 0; | 647 | int ret; |
| 648 | |||
| 647 | if (!capable(CAP_SYS_ADMIN)) | 649 | if (!capable(CAP_SYS_ADMIN)) |
| 648 | return -EACCES; | 650 | return -EACCES; |
| 649 | 651 | ||
| 650 | cmd_ptr = kzalloc(count*2, GFP_KERNEL); | 652 | /* this test protects us from running two flash processes at once, |
| 653 | * so we should start with this test */ | ||
| 654 | if (pm8001_ha->fw_status == FLASH_IN_PROGRESS) | ||
| 655 | return -EINPROGRESS; | ||
| 656 | pm8001_ha->fw_status = FLASH_IN_PROGRESS; | ||
| 651 | 657 | ||
| 658 | cmd_ptr = kzalloc(count*2, GFP_KERNEL); | ||
| 652 | if (!cmd_ptr) { | 659 | if (!cmd_ptr) { |
| 653 | err = FAIL_OUT_MEMORY; | 660 | pm8001_ha->fw_status = FAIL_OUT_MEMORY; |
| 654 | goto out; | 661 | return -ENOMEM; |
| 655 | } | 662 | } |
| 656 | 663 | ||
| 657 | filename_ptr = cmd_ptr + count; | 664 | filename_ptr = cmd_ptr + count; |
| 658 | res = sscanf(buf, "%s %s", cmd_ptr, filename_ptr); | 665 | res = sscanf(buf, "%s %s", cmd_ptr, filename_ptr); |
| 659 | if (res != 2) { | 666 | if (res != 2) { |
| 660 | err = FAIL_PARAMETERS; | 667 | pm8001_ha->fw_status = FAIL_PARAMETERS; |
| 661 | goto out1; | 668 | ret = -EINVAL; |
| 669 | goto out; | ||
| 662 | } | 670 | } |
| 663 | 671 | ||
| 664 | for (i = 0; flash_command_table[i].code != FLASH_CMD_NONE; i++) { | 672 | for (i = 0; flash_command_table[i].code != FLASH_CMD_NONE; i++) { |
| @@ -669,50 +677,38 @@ static ssize_t pm8001_store_update_fw(struct device *cdev, | |||
| 669 | } | 677 | } |
| 670 | } | 678 | } |
| 671 | if (flash_command == FLASH_CMD_NONE) { | 679 | if (flash_command == FLASH_CMD_NONE) { |
| 672 | err = FAIL_PARAMETERS; | 680 | pm8001_ha->fw_status = FAIL_PARAMETERS; |
| 673 | goto out1; | 681 | ret = -EINVAL; |
| 682 | goto out; | ||
| 674 | } | 683 | } |
| 675 | 684 | ||
| 676 | if (pm8001_ha->fw_status == FLASH_IN_PROGRESS) { | 685 | ret = request_firmware(&pm8001_ha->fw_image, |
| 677 | err = FLASH_IN_PROGRESS; | ||
| 678 | goto out1; | ||
| 679 | } | ||
| 680 | err = request_firmware(&pm8001_ha->fw_image, | ||
| 681 | filename_ptr, | 686 | filename_ptr, |
| 682 | pm8001_ha->dev); | 687 | pm8001_ha->dev); |
| 683 | 688 | ||
| 684 | if (err) { | 689 | if (ret) { |
| 685 | PM8001_FAIL_DBG(pm8001_ha, | 690 | PM8001_FAIL_DBG(pm8001_ha, |
| 686 | pm8001_printk("Failed to load firmware image file %s," | 691 | pm8001_printk( |
| 687 | " error %d\n", filename_ptr, err)); | 692 | "Failed to load firmware image file %s, error %d\n", |
| 688 | err = FAIL_OPEN_BIOS_FILE; | 693 | filename_ptr, ret)); |
| 689 | goto out1; | 694 | pm8001_ha->fw_status = FAIL_OPEN_BIOS_FILE; |
| 695 | goto out; | ||
| 690 | } | 696 | } |
| 691 | 697 | ||
| 692 | switch (flash_command) { | 698 | if (FLASH_CMD_UPDATE == flash_command) |
| 693 | case FLASH_CMD_UPDATE: | 699 | ret = pm8001_update_flash(pm8001_ha); |
| 694 | pm8001_ha->fw_status = FLASH_IN_PROGRESS; | 700 | else |
| 695 | err = pm8001_update_flash(pm8001_ha); | 701 | ret = pm8001_set_nvmd(pm8001_ha); |
| 696 | break; | 702 | |
| 697 | case FLASH_CMD_SET_NVMD: | ||
| 698 | pm8001_ha->fw_status = FLASH_IN_PROGRESS; | ||
| 699 | err = pm8001_set_nvmd(pm8001_ha); | ||
| 700 | break; | ||
| 701 | default: | ||
| 702 | pm8001_ha->fw_status = FAIL_PARAMETERS; | ||
| 703 | err = FAIL_PARAMETERS; | ||
| 704 | break; | ||
| 705 | } | ||
| 706 | release_firmware(pm8001_ha->fw_image); | 703 | release_firmware(pm8001_ha->fw_image); |
| 707 | out1: | ||
| 708 | kfree(cmd_ptr); | ||
| 709 | out: | 704 | out: |
| 710 | pm8001_ha->fw_status = err; | 705 | kfree(cmd_ptr); |
| 711 | 706 | ||
| 712 | if (!err) | 707 | if (ret) |
| 713 | return count; | 708 | return ret; |
| 714 | else | 709 | |
| 715 | return -err; | 710 | pm8001_ha->fw_status = FLASH_OK; |
| 711 | return count; | ||
| 716 | } | 712 | } |
| 717 | 713 | ||
| 718 | static ssize_t pm8001_show_update_fw(struct device *cdev, | 714 | static ssize_t pm8001_show_update_fw(struct device *cdev, |
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 173831016f5f..dd12c6fe57a6 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c | |||
| @@ -4824,7 +4824,7 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, | |||
| 4824 | rc = pm8001_tag_alloc(pm8001_ha, &tag); | 4824 | rc = pm8001_tag_alloc(pm8001_ha, &tag); |
| 4825 | if (rc) { | 4825 | if (rc) { |
| 4826 | kfree(fw_control_context); | 4826 | kfree(fw_control_context); |
| 4827 | return rc; | 4827 | return -EBUSY; |
| 4828 | } | 4828 | } |
| 4829 | ccb = &pm8001_ha->ccb_info[tag]; | 4829 | ccb = &pm8001_ha->ccb_info[tag]; |
| 4830 | ccb->fw_control_context = fw_control_context; | 4830 | ccb->fw_control_context = fw_control_context; |
| @@ -4946,7 +4946,7 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha, | |||
| 4946 | rc = pm8001_tag_alloc(pm8001_ha, &tag); | 4946 | rc = pm8001_tag_alloc(pm8001_ha, &tag); |
| 4947 | if (rc) { | 4947 | if (rc) { |
| 4948 | kfree(fw_control_context); | 4948 | kfree(fw_control_context); |
| 4949 | return rc; | 4949 | return -EBUSY; |
| 4950 | } | 4950 | } |
| 4951 | ccb = &pm8001_ha->ccb_info[tag]; | 4951 | ccb = &pm8001_ha->ccb_info[tag]; |
| 4952 | ccb->fw_control_context = fw_control_context; | 4952 | ccb->fw_control_context = fw_control_context; |
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index e49623a897a7..666bf5af06e2 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c | |||
| @@ -748,34 +748,35 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha) | |||
| 748 | sizeof(pm8001_ha->msix_entries[0]); | 748 | sizeof(pm8001_ha->msix_entries[0]); |
| 749 | for (i = 0; i < max_entry ; i++) | 749 | for (i = 0; i < max_entry ; i++) |
| 750 | pm8001_ha->msix_entries[i].entry = i; | 750 | pm8001_ha->msix_entries[i].entry = i; |
| 751 | rc = pci_enable_msix(pm8001_ha->pdev, pm8001_ha->msix_entries, | 751 | rc = pci_enable_msix_exact(pm8001_ha->pdev, pm8001_ha->msix_entries, |
| 752 | number_of_intr); | 752 | number_of_intr); |
| 753 | pm8001_ha->number_of_intr = number_of_intr; | 753 | pm8001_ha->number_of_intr = number_of_intr; |
| 754 | if (!rc) { | 754 | if (rc) |
| 755 | PM8001_INIT_DBG(pm8001_ha, pm8001_printk( | 755 | return rc; |
| 756 | "pci_enable_msix request ret:%d no of intr %d\n", | ||
| 757 | rc, pm8001_ha->number_of_intr)); | ||
| 758 | 756 | ||
| 757 | PM8001_INIT_DBG(pm8001_ha, pm8001_printk( | ||
| 758 | "pci_enable_msix_exact request ret:%d no of intr %d\n", | ||
| 759 | rc, pm8001_ha->number_of_intr)); | ||
| 759 | 760 | ||
| 760 | for (i = 0; i < number_of_intr; i++) { | 761 | for (i = 0; i < number_of_intr; i++) { |
| 761 | snprintf(intr_drvname[i], sizeof(intr_drvname[0]), | 762 | snprintf(intr_drvname[i], sizeof(intr_drvname[0]), |
| 762 | DRV_NAME"%d", i); | 763 | DRV_NAME"%d", i); |
| 763 | pm8001_ha->irq_vector[i].irq_id = i; | 764 | pm8001_ha->irq_vector[i].irq_id = i; |
| 764 | pm8001_ha->irq_vector[i].drv_inst = pm8001_ha; | 765 | pm8001_ha->irq_vector[i].drv_inst = pm8001_ha; |
| 765 | 766 | ||
| 766 | rc = request_irq(pm8001_ha->msix_entries[i].vector, | 767 | rc = request_irq(pm8001_ha->msix_entries[i].vector, |
| 767 | pm8001_interrupt_handler_msix, flag, | 768 | pm8001_interrupt_handler_msix, flag, |
| 768 | intr_drvname[i], &(pm8001_ha->irq_vector[i])); | 769 | intr_drvname[i], &(pm8001_ha->irq_vector[i])); |
| 769 | if (rc) { | 770 | if (rc) { |
| 770 | for (j = 0; j < i; j++) | 771 | for (j = 0; j < i; j++) { |
| 771 | free_irq( | 772 | free_irq(pm8001_ha->msix_entries[j].vector, |
| 772 | pm8001_ha->msix_entries[j].vector, | ||
| 773 | &(pm8001_ha->irq_vector[i])); | 773 | &(pm8001_ha->irq_vector[i])); |
| 774 | pci_disable_msix(pm8001_ha->pdev); | ||
| 775 | break; | ||
| 776 | } | 774 | } |
| 775 | pci_disable_msix(pm8001_ha->pdev); | ||
| 776 | break; | ||
| 777 | } | 777 | } |
| 778 | } | 778 | } |
| 779 | |||
| 779 | return rc; | 780 | return rc; |
| 780 | } | 781 | } |
| 781 | #endif | 782 | #endif |
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 6f12f859b11d..4180d6d9fe78 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c | |||
| @@ -334,6 +334,12 @@ void qla4xxx_alloc_fw_dump(struct scsi_qla_host *ha) | |||
| 334 | /* Allocate memory for saving the template */ | 334 | /* Allocate memory for saving the template */ |
| 335 | md_tmp = dma_alloc_coherent(&ha->pdev->dev, ha->fw_dump_tmplt_size, | 335 | md_tmp = dma_alloc_coherent(&ha->pdev->dev, ha->fw_dump_tmplt_size, |
| 336 | &md_tmp_dma, GFP_KERNEL); | 336 | &md_tmp_dma, GFP_KERNEL); |
| 337 | if (!md_tmp) { | ||
| 338 | ql4_printk(KERN_INFO, ha, | ||
| 339 | "scsi%ld: Failed to allocate DMA memory\n", | ||
| 340 | ha->host_no); | ||
| 341 | return; | ||
| 342 | } | ||
| 337 | 343 | ||
| 338 | /* Request template */ | 344 | /* Request template */ |
| 339 | status = qla4xxx_get_minidump_template(ha, md_tmp_dma); | 345 | status = qla4xxx_get_minidump_template(ha, md_tmp_dma); |
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index fdfae79924ac..c291fdff1b33 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c | |||
| @@ -1620,8 +1620,8 @@ int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password, | |||
| 1620 | goto exit_get_chap; | 1620 | goto exit_get_chap; |
| 1621 | } | 1621 | } |
| 1622 | 1622 | ||
| 1623 | strncpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN); | 1623 | strlcpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN); |
| 1624 | strncpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN); | 1624 | strlcpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN); |
| 1625 | chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE); | 1625 | chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE); |
| 1626 | 1626 | ||
| 1627 | exit_get_chap: | 1627 | exit_get_chap: |
| @@ -1663,8 +1663,8 @@ int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username, char *password, | |||
| 1663 | else | 1663 | else |
| 1664 | chap_table->flags |= BIT_7; /* local */ | 1664 | chap_table->flags |= BIT_7; /* local */ |
| 1665 | chap_table->secret_len = strlen(password); | 1665 | chap_table->secret_len = strlen(password); |
| 1666 | strncpy(chap_table->secret, password, MAX_CHAP_SECRET_LEN); | 1666 | strncpy(chap_table->secret, password, MAX_CHAP_SECRET_LEN - 1); |
| 1667 | strncpy(chap_table->name, username, MAX_CHAP_NAME_LEN); | 1667 | strncpy(chap_table->name, username, MAX_CHAP_NAME_LEN - 1); |
| 1668 | chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE); | 1668 | chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE); |
| 1669 | 1669 | ||
| 1670 | if (is_qla40XX(ha)) { | 1670 | if (is_qla40XX(ha)) { |
| @@ -1742,8 +1742,8 @@ int qla4xxx_get_uni_chap_at_index(struct scsi_qla_host *ha, char *username, | |||
| 1742 | goto exit_unlock_uni_chap; | 1742 | goto exit_unlock_uni_chap; |
| 1743 | } | 1743 | } |
| 1744 | 1744 | ||
| 1745 | strncpy(password, chap_table->secret, MAX_CHAP_SECRET_LEN); | 1745 | strlcpy(password, chap_table->secret, MAX_CHAP_SECRET_LEN); |
| 1746 | strncpy(username, chap_table->name, MAX_CHAP_NAME_LEN); | 1746 | strlcpy(username, chap_table->name, MAX_CHAP_NAME_LEN); |
| 1747 | 1747 | ||
| 1748 | rval = QLA_SUCCESS; | 1748 | rval = QLA_SUCCESS; |
| 1749 | 1749 | ||
| @@ -2295,7 +2295,7 @@ int qla4_8xxx_set_param(struct scsi_qla_host *ha, int param) | |||
| 2295 | if (param == SET_DRVR_VERSION) { | 2295 | if (param == SET_DRVR_VERSION) { |
| 2296 | mbox_cmd[1] = SET_DRVR_VERSION; | 2296 | mbox_cmd[1] = SET_DRVR_VERSION; |
| 2297 | strncpy((char *)&mbox_cmd[2], QLA4XXX_DRIVER_VERSION, | 2297 | strncpy((char *)&mbox_cmd[2], QLA4XXX_DRIVER_VERSION, |
| 2298 | MAX_DRVR_VER_LEN); | 2298 | MAX_DRVR_VER_LEN - 1); |
| 2299 | } else { | 2299 | } else { |
| 2300 | ql4_printk(KERN_ERR, ha, "%s: invalid parameter 0x%x\n", | 2300 | ql4_printk(KERN_ERR, ha, "%s: invalid parameter 0x%x\n", |
| 2301 | __func__, param); | 2301 | __func__, param); |
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index 9dbdb4be2d8f..7c3365864242 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c | |||
| @@ -4221,7 +4221,7 @@ qla4_8xxx_enable_msix(struct scsi_qla_host *ha) | |||
| 4221 | for (i = 0; i < QLA_MSIX_ENTRIES; i++) | 4221 | for (i = 0; i < QLA_MSIX_ENTRIES; i++) |
| 4222 | entries[i].entry = qla4_8xxx_msix_entries[i].entry; | 4222 | entries[i].entry = qla4_8xxx_msix_entries[i].entry; |
| 4223 | 4223 | ||
| 4224 | ret = pci_enable_msix(ha->pdev, entries, ARRAY_SIZE(entries)); | 4224 | ret = pci_enable_msix_exact(ha->pdev, entries, ARRAY_SIZE(entries)); |
| 4225 | if (ret) { | 4225 | if (ret) { |
| 4226 | ql4_printk(KERN_WARNING, ha, | 4226 | ql4_printk(KERN_WARNING, ha, |
| 4227 | "MSI-X: Failed to enable support -- %d/%d\n", | 4227 | "MSI-X: Failed to enable support -- %d/%d\n", |
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index c5d9564d455c..199fcf79a051 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
| @@ -756,9 +756,9 @@ static int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx, | |||
| 756 | continue; | 756 | continue; |
| 757 | 757 | ||
| 758 | chap_rec->chap_tbl_idx = i; | 758 | chap_rec->chap_tbl_idx = i; |
| 759 | strncpy(chap_rec->username, chap_table->name, | 759 | strlcpy(chap_rec->username, chap_table->name, |
| 760 | ISCSI_CHAP_AUTH_NAME_MAX_LEN); | 760 | ISCSI_CHAP_AUTH_NAME_MAX_LEN); |
| 761 | strncpy(chap_rec->password, chap_table->secret, | 761 | strlcpy(chap_rec->password, chap_table->secret, |
| 762 | QL4_CHAP_MAX_SECRET_LEN); | 762 | QL4_CHAP_MAX_SECRET_LEN); |
| 763 | chap_rec->password_length = chap_table->secret_len; | 763 | chap_rec->password_length = chap_table->secret_len; |
| 764 | 764 | ||
| @@ -1050,6 +1050,7 @@ static int qla4xxx_get_host_stats(struct Scsi_Host *shost, char *buf, int len) | |||
| 1050 | if (!ql_iscsi_stats) { | 1050 | if (!ql_iscsi_stats) { |
| 1051 | ql4_printk(KERN_ERR, ha, | 1051 | ql4_printk(KERN_ERR, ha, |
| 1052 | "Unable to allocate memory for iscsi stats\n"); | 1052 | "Unable to allocate memory for iscsi stats\n"); |
| 1053 | ret = -ENOMEM; | ||
| 1053 | goto exit_host_stats; | 1054 | goto exit_host_stats; |
| 1054 | } | 1055 | } |
| 1055 | 1056 | ||
| @@ -1058,6 +1059,7 @@ static int qla4xxx_get_host_stats(struct Scsi_Host *shost, char *buf, int len) | |||
| 1058 | if (ret != QLA_SUCCESS) { | 1059 | if (ret != QLA_SUCCESS) { |
| 1059 | ql4_printk(KERN_ERR, ha, | 1060 | ql4_printk(KERN_ERR, ha, |
| 1060 | "Unable to retrieve iscsi stats\n"); | 1061 | "Unable to retrieve iscsi stats\n"); |
| 1062 | ret = -EIO; | ||
| 1061 | goto exit_host_stats; | 1063 | goto exit_host_stats; |
| 1062 | } | 1064 | } |
| 1063 | host_stats->mactx_frames = le64_to_cpu(ql_iscsi_stats->mac_tx_frames); | 1065 | host_stats->mactx_frames = le64_to_cpu(ql_iscsi_stats->mac_tx_frames); |
| @@ -6027,8 +6029,8 @@ static int qla4xxx_get_bidi_chap(struct scsi_qla_host *ha, char *username, | |||
| 6027 | if (!(chap_table->flags & BIT_6)) /* Not BIDI */ | 6029 | if (!(chap_table->flags & BIT_6)) /* Not BIDI */ |
| 6028 | continue; | 6030 | continue; |
| 6029 | 6031 | ||
| 6030 | strncpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN); | 6032 | strlcpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN); |
| 6031 | strncpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN); | 6033 | strlcpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN); |
| 6032 | ret = 0; | 6034 | ret = 0; |
| 6033 | break; | 6035 | break; |
| 6034 | } | 6036 | } |
| @@ -6258,8 +6260,8 @@ static void qla4xxx_get_param_ddb(struct ddb_entry *ddb_entry, | |||
| 6258 | 6260 | ||
| 6259 | tddb->tpgt = sess->tpgt; | 6261 | tddb->tpgt = sess->tpgt; |
| 6260 | tddb->port = conn->persistent_port; | 6262 | tddb->port = conn->persistent_port; |
| 6261 | strncpy(tddb->iscsi_name, sess->targetname, ISCSI_NAME_SIZE); | 6263 | strlcpy(tddb->iscsi_name, sess->targetname, ISCSI_NAME_SIZE); |
| 6262 | strncpy(tddb->ip_addr, conn->persistent_address, DDB_IPADDR_LEN); | 6264 | strlcpy(tddb->ip_addr, conn->persistent_address, DDB_IPADDR_LEN); |
| 6263 | } | 6265 | } |
| 6264 | 6266 | ||
| 6265 | static void qla4xxx_convert_param_ddb(struct dev_db_entry *fw_ddb_entry, | 6267 | static void qla4xxx_convert_param_ddb(struct dev_db_entry *fw_ddb_entry, |
| @@ -7764,7 +7766,7 @@ static int qla4xxx_sysfs_ddb_logout(struct iscsi_bus_flash_session *fnode_sess, | |||
| 7764 | goto exit_ddb_logout; | 7766 | goto exit_ddb_logout; |
| 7765 | } | 7767 | } |
| 7766 | 7768 | ||
| 7767 | strncpy(flash_tddb->iscsi_name, fnode_sess->targetname, | 7769 | strlcpy(flash_tddb->iscsi_name, fnode_sess->targetname, |
| 7768 | ISCSI_NAME_SIZE); | 7770 | ISCSI_NAME_SIZE); |
| 7769 | 7771 | ||
| 7770 | if (!strncmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4)) | 7772 | if (!strncmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4)) |
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index df3306019a7e..d81f3cc43ff1 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c | |||
| @@ -377,6 +377,10 @@ scsi_alloc_host_cmd_pool(struct Scsi_Host *shost) | |||
| 377 | pool->slab_flags |= SLAB_CACHE_DMA; | 377 | pool->slab_flags |= SLAB_CACHE_DMA; |
| 378 | pool->gfp_mask = __GFP_DMA; | 378 | pool->gfp_mask = __GFP_DMA; |
| 379 | } | 379 | } |
| 380 | |||
| 381 | if (hostt->cmd_size) | ||
| 382 | hostt->cmd_pool = pool; | ||
| 383 | |||
| 380 | return pool; | 384 | return pool; |
| 381 | } | 385 | } |
| 382 | 386 | ||
| @@ -421,8 +425,10 @@ out: | |||
| 421 | out_free_slab: | 425 | out_free_slab: |
| 422 | kmem_cache_destroy(pool->cmd_slab); | 426 | kmem_cache_destroy(pool->cmd_slab); |
| 423 | out_free_pool: | 427 | out_free_pool: |
| 424 | if (hostt->cmd_size) | 428 | if (hostt->cmd_size) { |
| 425 | scsi_free_host_cmd_pool(pool); | 429 | scsi_free_host_cmd_pool(pool); |
| 430 | hostt->cmd_pool = NULL; | ||
| 431 | } | ||
| 426 | goto out; | 432 | goto out; |
| 427 | } | 433 | } |
| 428 | 434 | ||
| @@ -444,8 +450,10 @@ static void scsi_put_host_cmd_pool(struct Scsi_Host *shost) | |||
| 444 | if (!--pool->users) { | 450 | if (!--pool->users) { |
| 445 | kmem_cache_destroy(pool->cmd_slab); | 451 | kmem_cache_destroy(pool->cmd_slab); |
| 446 | kmem_cache_destroy(pool->sense_slab); | 452 | kmem_cache_destroy(pool->sense_slab); |
| 447 | if (hostt->cmd_size) | 453 | if (hostt->cmd_size) { |
| 448 | scsi_free_host_cmd_pool(pool); | 454 | scsi_free_host_cmd_pool(pool); |
| 455 | hostt->cmd_pool = NULL; | ||
| 456 | } | ||
| 449 | } | 457 | } |
| 450 | mutex_unlock(&host_cmd_pool_mutex); | 458 | mutex_unlock(&host_cmd_pool_mutex); |
| 451 | } | 459 | } |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 9c44392b748f..ce62e8798cc8 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
| @@ -1774,7 +1774,7 @@ static void scsi_request_fn(struct request_queue *q) | |||
| 1774 | blk_requeue_request(q, req); | 1774 | blk_requeue_request(q, req); |
| 1775 | atomic_dec(&sdev->device_busy); | 1775 | atomic_dec(&sdev->device_busy); |
| 1776 | out_delay: | 1776 | out_delay: |
| 1777 | if (atomic_read(&sdev->device_busy) && !scsi_device_blocked(sdev)) | 1777 | if (!atomic_read(&sdev->device_busy) && !scsi_device_blocked(sdev)) |
| 1778 | blk_delay_queue(q, SCSI_QUEUE_DELAY); | 1778 | blk_delay_queue(q, SCSI_QUEUE_DELAY); |
| 1779 | } | 1779 | } |
| 1780 | 1780 | ||
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index b481e62a12cc..67d43e35693d 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c | |||
| @@ -3429,7 +3429,7 @@ iscsi_get_host_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh) | |||
| 3429 | char *buf; | 3429 | char *buf; |
| 3430 | 3430 | ||
| 3431 | if (!transport->get_host_stats) | 3431 | if (!transport->get_host_stats) |
| 3432 | return -EINVAL; | 3432 | return -ENOSYS; |
| 3433 | 3433 | ||
| 3434 | priv = iscsi_if_transport_lookup(transport); | 3434 | priv = iscsi_if_transport_lookup(transport); |
| 3435 | if (!priv) | 3435 | if (!priv) |
| @@ -3467,6 +3467,10 @@ iscsi_get_host_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh) | |||
| 3467 | memset(buf, 0, host_stats_size); | 3467 | memset(buf, 0, host_stats_size); |
| 3468 | 3468 | ||
| 3469 | err = transport->get_host_stats(shost, buf, host_stats_size); | 3469 | err = transport->get_host_stats(shost, buf, host_stats_size); |
| 3470 | if (err) { | ||
| 3471 | kfree_skb(skbhost_stats); | ||
| 3472 | goto exit_host_stats; | ||
| 3473 | } | ||
| 3470 | 3474 | ||
| 3471 | actual_size = nlmsg_total_size(sizeof(*ev) + host_stats_size); | 3475 | actual_size = nlmsg_total_size(sizeof(*ev) + host_stats_size); |
| 3472 | skb_trim(skbhost_stats, NLMSG_ALIGN(actual_size)); | 3476 | skb_trim(skbhost_stats, NLMSG_ALIGN(actual_size)); |
diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c index 4e76fe863fc4..d8dcf36aed11 100644 --- a/drivers/scsi/u14-34f.c +++ b/drivers/scsi/u14-34f.c | |||
| @@ -1006,7 +1006,7 @@ static int port_detect \ | |||
| 1006 | sh[j]->irq, dma_name, sh[j]->sg_tablesize, sh[j]->can_queue); | 1006 | sh[j]->irq, dma_name, sh[j]->sg_tablesize, sh[j]->can_queue); |
| 1007 | 1007 | ||
| 1008 | if (sh[j]->max_id > 8 || sh[j]->max_lun > 8) | 1008 | if (sh[j]->max_id > 8 || sh[j]->max_lun > 8) |
| 1009 | printk("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n", | 1009 | printk("%s: wide SCSI support enabled, max_id %u, max_lun %llu.\n", |
| 1010 | BN(j), sh[j]->max_id, sh[j]->max_lun); | 1010 | BN(j), sh[j]->max_id, sh[j]->max_lun); |
| 1011 | 1011 | ||
| 1012 | for (i = 0; i <= sh[j]->max_channel; i++) | 1012 | for (i = 0; i <= sh[j]->max_channel; i++) |
| @@ -1285,7 +1285,7 @@ static int u14_34f_queuecommand_lck(struct scsi_cmnd *SCpnt, void (*done)(struct | |||
| 1285 | cpp->cpp_index = i; | 1285 | cpp->cpp_index = i; |
| 1286 | SCpnt->host_scribble = (unsigned char *) &cpp->cpp_index; | 1286 | SCpnt->host_scribble = (unsigned char *) &cpp->cpp_index; |
| 1287 | 1287 | ||
| 1288 | if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%llu.\n", | 1288 | if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%u.\n", |
| 1289 | BN(j), i, SCpnt->device->channel, SCpnt->device->id, | 1289 | BN(j), i, SCpnt->device->channel, SCpnt->device->id, |
| 1290 | (u8)SCpnt->device->lun); | 1290 | (u8)SCpnt->device->lun); |
| 1291 | 1291 | ||
| @@ -192,7 +192,6 @@ static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages) | |||
| 192 | } | 192 | } |
| 193 | 193 | ||
| 194 | file->f_flags = O_RDWR; | 194 | file->f_flags = O_RDWR; |
| 195 | file->private_data = ctx; | ||
| 196 | return file; | 195 | return file; |
| 197 | } | 196 | } |
| 198 | 197 | ||
| @@ -202,7 +201,7 @@ static struct dentry *aio_mount(struct file_system_type *fs_type, | |||
| 202 | static const struct dentry_operations ops = { | 201 | static const struct dentry_operations ops = { |
| 203 | .d_dname = simple_dname, | 202 | .d_dname = simple_dname, |
| 204 | }; | 203 | }; |
| 205 | return mount_pseudo(fs_type, "aio:", NULL, &ops, 0xa10a10a1); | 204 | return mount_pseudo(fs_type, "aio:", NULL, &ops, AIO_RING_MAGIC); |
| 206 | } | 205 | } |
| 207 | 206 | ||
| 208 | /* aio_setup | 207 | /* aio_setup |
| @@ -556,8 +555,7 @@ static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm) | |||
| 556 | struct aio_ring *ring; | 555 | struct aio_ring *ring; |
| 557 | 556 | ||
| 558 | spin_lock(&mm->ioctx_lock); | 557 | spin_lock(&mm->ioctx_lock); |
| 559 | rcu_read_lock(); | 558 | table = rcu_dereference_raw(mm->ioctx_table); |
| 560 | table = rcu_dereference(mm->ioctx_table); | ||
| 561 | 559 | ||
| 562 | while (1) { | 560 | while (1) { |
| 563 | if (table) | 561 | if (table) |
| @@ -565,7 +563,6 @@ static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm) | |||
| 565 | if (!table->table[i]) { | 563 | if (!table->table[i]) { |
| 566 | ctx->id = i; | 564 | ctx->id = i; |
| 567 | table->table[i] = ctx; | 565 | table->table[i] = ctx; |
| 568 | rcu_read_unlock(); | ||
| 569 | spin_unlock(&mm->ioctx_lock); | 566 | spin_unlock(&mm->ioctx_lock); |
| 570 | 567 | ||
| 571 | /* While kioctx setup is in progress, | 568 | /* While kioctx setup is in progress, |
| @@ -579,8 +576,6 @@ static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm) | |||
| 579 | } | 576 | } |
| 580 | 577 | ||
| 581 | new_nr = (table ? table->nr : 1) * 4; | 578 | new_nr = (table ? table->nr : 1) * 4; |
| 582 | |||
| 583 | rcu_read_unlock(); | ||
| 584 | spin_unlock(&mm->ioctx_lock); | 579 | spin_unlock(&mm->ioctx_lock); |
| 585 | 580 | ||
| 586 | table = kzalloc(sizeof(*table) + sizeof(struct kioctx *) * | 581 | table = kzalloc(sizeof(*table) + sizeof(struct kioctx *) * |
| @@ -591,8 +586,7 @@ static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm) | |||
| 591 | table->nr = new_nr; | 586 | table->nr = new_nr; |
| 592 | 587 | ||
| 593 | spin_lock(&mm->ioctx_lock); | 588 | spin_lock(&mm->ioctx_lock); |
| 594 | rcu_read_lock(); | 589 | old = rcu_dereference_raw(mm->ioctx_table); |
| 595 | old = rcu_dereference(mm->ioctx_table); | ||
| 596 | 590 | ||
| 597 | if (!old) { | 591 | if (!old) { |
| 598 | rcu_assign_pointer(mm->ioctx_table, table); | 592 | rcu_assign_pointer(mm->ioctx_table, table); |
| @@ -739,12 +733,9 @@ static int kill_ioctx(struct mm_struct *mm, struct kioctx *ctx, | |||
| 739 | 733 | ||
| 740 | 734 | ||
| 741 | spin_lock(&mm->ioctx_lock); | 735 | spin_lock(&mm->ioctx_lock); |
| 742 | rcu_read_lock(); | 736 | table = rcu_dereference_raw(mm->ioctx_table); |
| 743 | table = rcu_dereference(mm->ioctx_table); | ||
| 744 | |||
| 745 | WARN_ON(ctx != table->table[ctx->id]); | 737 | WARN_ON(ctx != table->table[ctx->id]); |
| 746 | table->table[ctx->id] = NULL; | 738 | table->table[ctx->id] = NULL; |
| 747 | rcu_read_unlock(); | ||
| 748 | spin_unlock(&mm->ioctx_lock); | 739 | spin_unlock(&mm->ioctx_lock); |
| 749 | 740 | ||
| 750 | /* percpu_ref_kill() will do the necessary call_rcu() */ | 741 | /* percpu_ref_kill() will do the necessary call_rcu() */ |
| @@ -793,40 +784,30 @@ EXPORT_SYMBOL(wait_on_sync_kiocb); | |||
| 793 | */ | 784 | */ |
| 794 | void exit_aio(struct mm_struct *mm) | 785 | void exit_aio(struct mm_struct *mm) |
| 795 | { | 786 | { |
| 796 | struct kioctx_table *table; | 787 | struct kioctx_table *table = rcu_dereference_raw(mm->ioctx_table); |
| 797 | struct kioctx *ctx; | 788 | int i; |
| 798 | unsigned i = 0; | ||
| 799 | |||
| 800 | while (1) { | ||
| 801 | rcu_read_lock(); | ||
| 802 | table = rcu_dereference(mm->ioctx_table); | ||
| 803 | |||
| 804 | do { | ||
| 805 | if (!table || i >= table->nr) { | ||
| 806 | rcu_read_unlock(); | ||
| 807 | rcu_assign_pointer(mm->ioctx_table, NULL); | ||
| 808 | if (table) | ||
| 809 | kfree(table); | ||
| 810 | return; | ||
| 811 | } | ||
| 812 | 789 | ||
| 813 | ctx = table->table[i++]; | 790 | if (!table) |
| 814 | } while (!ctx); | 791 | return; |
| 815 | 792 | ||
| 816 | rcu_read_unlock(); | 793 | for (i = 0; i < table->nr; ++i) { |
| 794 | struct kioctx *ctx = table->table[i]; | ||
| 817 | 795 | ||
| 796 | if (!ctx) | ||
| 797 | continue; | ||
| 818 | /* | 798 | /* |
| 819 | * We don't need to bother with munmap() here - | 799 | * We don't need to bother with munmap() here - exit_mmap(mm) |
| 820 | * exit_mmap(mm) is coming and it'll unmap everything. | 800 | * is coming and it'll unmap everything. And we simply can't, |
| 821 | * Since aio_free_ring() uses non-zero ->mmap_size | 801 | * this is not necessarily our ->mm. |
| 822 | * as indicator that it needs to unmap the area, | 802 | * Since kill_ioctx() uses non-zero ->mmap_size as indicator |
| 823 | * just set it to 0; aio_free_ring() is the only | 803 | * that it needs to unmap the area, just set it to 0. |
| 824 | * place that uses ->mmap_size, so it's safe. | ||
| 825 | */ | 804 | */ |
| 826 | ctx->mmap_size = 0; | 805 | ctx->mmap_size = 0; |
| 827 | |||
| 828 | kill_ioctx(mm, ctx, NULL); | 806 | kill_ioctx(mm, ctx, NULL); |
| 829 | } | 807 | } |
| 808 | |||
| 809 | RCU_INIT_POINTER(mm->ioctx_table, NULL); | ||
| 810 | kfree(table); | ||
| 830 | } | 811 | } |
| 831 | 812 | ||
| 832 | static void put_reqs_available(struct kioctx *ctx, unsigned nr) | 813 | static void put_reqs_available(struct kioctx *ctx, unsigned nr) |
| @@ -834,10 +815,8 @@ static void put_reqs_available(struct kioctx *ctx, unsigned nr) | |||
| 834 | struct kioctx_cpu *kcpu; | 815 | struct kioctx_cpu *kcpu; |
| 835 | unsigned long flags; | 816 | unsigned long flags; |
| 836 | 817 | ||
| 837 | preempt_disable(); | ||
| 838 | kcpu = this_cpu_ptr(ctx->cpu); | ||
| 839 | |||
| 840 | local_irq_save(flags); | 818 | local_irq_save(flags); |
| 819 | kcpu = this_cpu_ptr(ctx->cpu); | ||
| 841 | kcpu->reqs_available += nr; | 820 | kcpu->reqs_available += nr; |
| 842 | 821 | ||
| 843 | while (kcpu->reqs_available >= ctx->req_batch * 2) { | 822 | while (kcpu->reqs_available >= ctx->req_batch * 2) { |
| @@ -846,7 +825,6 @@ static void put_reqs_available(struct kioctx *ctx, unsigned nr) | |||
| 846 | } | 825 | } |
| 847 | 826 | ||
| 848 | local_irq_restore(flags); | 827 | local_irq_restore(flags); |
| 849 | preempt_enable(); | ||
| 850 | } | 828 | } |
| 851 | 829 | ||
| 852 | static bool get_reqs_available(struct kioctx *ctx) | 830 | static bool get_reqs_available(struct kioctx *ctx) |
| @@ -855,10 +833,8 @@ static bool get_reqs_available(struct kioctx *ctx) | |||
| 855 | bool ret = false; | 833 | bool ret = false; |
| 856 | unsigned long flags; | 834 | unsigned long flags; |
| 857 | 835 | ||
| 858 | preempt_disable(); | ||
| 859 | kcpu = this_cpu_ptr(ctx->cpu); | ||
| 860 | |||
| 861 | local_irq_save(flags); | 836 | local_irq_save(flags); |
| 837 | kcpu = this_cpu_ptr(ctx->cpu); | ||
| 862 | if (!kcpu->reqs_available) { | 838 | if (!kcpu->reqs_available) { |
| 863 | int old, avail = atomic_read(&ctx->reqs_available); | 839 | int old, avail = atomic_read(&ctx->reqs_available); |
| 864 | 840 | ||
| @@ -878,7 +854,6 @@ static bool get_reqs_available(struct kioctx *ctx) | |||
| 878 | kcpu->reqs_available--; | 854 | kcpu->reqs_available--; |
| 879 | out: | 855 | out: |
| 880 | local_irq_restore(flags); | 856 | local_irq_restore(flags); |
| 881 | preempt_enable(); | ||
| 882 | return ret; | 857 | return ret; |
| 883 | } | 858 | } |
| 884 | 859 | ||
| @@ -1047,7 +1022,7 @@ void aio_complete(struct kiocb *iocb, long res, long res2) | |||
| 1047 | } | 1022 | } |
| 1048 | EXPORT_SYMBOL(aio_complete); | 1023 | EXPORT_SYMBOL(aio_complete); |
| 1049 | 1024 | ||
| 1050 | /* aio_read_events | 1025 | /* aio_read_events_ring |
| 1051 | * Pull an event off of the ioctx's event ring. Returns the number of | 1026 | * Pull an event off of the ioctx's event ring. Returns the number of |
| 1052 | * events fetched | 1027 | * events fetched |
| 1053 | */ | 1028 | */ |
| @@ -1270,12 +1245,12 @@ static ssize_t aio_setup_vectored_rw(struct kiocb *kiocb, | |||
| 1270 | if (compat) | 1245 | if (compat) |
| 1271 | ret = compat_rw_copy_check_uvector(rw, | 1246 | ret = compat_rw_copy_check_uvector(rw, |
| 1272 | (struct compat_iovec __user *)buf, | 1247 | (struct compat_iovec __user *)buf, |
| 1273 | *nr_segs, 1, *iovec, iovec); | 1248 | *nr_segs, UIO_FASTIOV, *iovec, iovec); |
| 1274 | else | 1249 | else |
| 1275 | #endif | 1250 | #endif |
| 1276 | ret = rw_copy_check_uvector(rw, | 1251 | ret = rw_copy_check_uvector(rw, |
| 1277 | (struct iovec __user *)buf, | 1252 | (struct iovec __user *)buf, |
| 1278 | *nr_segs, 1, *iovec, iovec); | 1253 | *nr_segs, UIO_FASTIOV, *iovec, iovec); |
| 1279 | if (ret < 0) | 1254 | if (ret < 0) |
| 1280 | return ret; | 1255 | return ret; |
| 1281 | 1256 | ||
| @@ -1299,9 +1274,8 @@ static ssize_t aio_setup_single_vector(struct kiocb *kiocb, | |||
| 1299 | } | 1274 | } |
| 1300 | 1275 | ||
| 1301 | /* | 1276 | /* |
| 1302 | * aio_setup_iocb: | 1277 | * aio_run_iocb: |
| 1303 | * Performs the initial checks and aio retry method | 1278 | * Performs the initial checks and io submission. |
| 1304 | * setup for the kiocb at the time of io submission. | ||
| 1305 | */ | 1279 | */ |
| 1306 | static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode, | 1280 | static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode, |
| 1307 | char __user *buf, bool compat) | 1281 | char __user *buf, bool compat) |
| @@ -1313,7 +1287,7 @@ static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode, | |||
| 1313 | fmode_t mode; | 1287 | fmode_t mode; |
| 1314 | aio_rw_op *rw_op; | 1288 | aio_rw_op *rw_op; |
| 1315 | rw_iter_op *iter_op; | 1289 | rw_iter_op *iter_op; |
| 1316 | struct iovec inline_vec, *iovec = &inline_vec; | 1290 | struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs; |
| 1317 | struct iov_iter iter; | 1291 | struct iov_iter iter; |
| 1318 | 1292 | ||
| 1319 | switch (opcode) { | 1293 | switch (opcode) { |
| @@ -1348,7 +1322,7 @@ rw_common: | |||
| 1348 | if (!ret) | 1322 | if (!ret) |
| 1349 | ret = rw_verify_area(rw, file, &req->ki_pos, req->ki_nbytes); | 1323 | ret = rw_verify_area(rw, file, &req->ki_pos, req->ki_nbytes); |
| 1350 | if (ret < 0) { | 1324 | if (ret < 0) { |
| 1351 | if (iovec != &inline_vec) | 1325 | if (iovec != inline_vecs) |
| 1352 | kfree(iovec); | 1326 | kfree(iovec); |
| 1353 | return ret; | 1327 | return ret; |
| 1354 | } | 1328 | } |
| @@ -1395,7 +1369,7 @@ rw_common: | |||
| 1395 | return -EINVAL; | 1369 | return -EINVAL; |
| 1396 | } | 1370 | } |
| 1397 | 1371 | ||
| 1398 | if (iovec != &inline_vec) | 1372 | if (iovec != inline_vecs) |
| 1399 | kfree(iovec); | 1373 | kfree(iovec); |
| 1400 | 1374 | ||
| 1401 | if (ret != -EIOCBQUEUED) { | 1375 | if (ret != -EIOCBQUEUED) { |
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index e25564bfcb46..54a201dac7f9 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c | |||
| @@ -276,9 +276,8 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path, | |||
| 276 | } | 276 | } |
| 277 | if (ret > 0) | 277 | if (ret > 0) |
| 278 | goto next; | 278 | goto next; |
| 279 | ret = ulist_add_merge(parents, eb->start, | 279 | ret = ulist_add_merge_ptr(parents, eb->start, |
| 280 | (uintptr_t)eie, | 280 | eie, (void **)&old, GFP_NOFS); |
| 281 | (u64 *)&old, GFP_NOFS); | ||
| 282 | if (ret < 0) | 281 | if (ret < 0) |
| 283 | break; | 282 | break; |
| 284 | if (!ret && extent_item_pos) { | 283 | if (!ret && extent_item_pos) { |
| @@ -1001,16 +1000,19 @@ again: | |||
| 1001 | ret = -EIO; | 1000 | ret = -EIO; |
| 1002 | goto out; | 1001 | goto out; |
| 1003 | } | 1002 | } |
| 1003 | btrfs_tree_read_lock(eb); | ||
| 1004 | btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); | ||
| 1004 | ret = find_extent_in_eb(eb, bytenr, | 1005 | ret = find_extent_in_eb(eb, bytenr, |
| 1005 | *extent_item_pos, &eie); | 1006 | *extent_item_pos, &eie); |
| 1007 | btrfs_tree_read_unlock_blocking(eb); | ||
| 1006 | free_extent_buffer(eb); | 1008 | free_extent_buffer(eb); |
| 1007 | if (ret < 0) | 1009 | if (ret < 0) |
| 1008 | goto out; | 1010 | goto out; |
| 1009 | ref->inode_list = eie; | 1011 | ref->inode_list = eie; |
| 1010 | } | 1012 | } |
| 1011 | ret = ulist_add_merge(refs, ref->parent, | 1013 | ret = ulist_add_merge_ptr(refs, ref->parent, |
| 1012 | (uintptr_t)ref->inode_list, | 1014 | ref->inode_list, |
| 1013 | (u64 *)&eie, GFP_NOFS); | 1015 | (void **)&eie, GFP_NOFS); |
| 1014 | if (ret < 0) | 1016 | if (ret < 0) |
| 1015 | goto out; | 1017 | goto out; |
| 1016 | if (!ret && extent_item_pos) { | 1018 | if (!ret && extent_item_pos) { |
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index 4794923c410c..43527fd78825 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h | |||
| @@ -84,12 +84,6 @@ struct btrfs_inode { | |||
| 84 | */ | 84 | */ |
| 85 | struct list_head delalloc_inodes; | 85 | struct list_head delalloc_inodes; |
| 86 | 86 | ||
| 87 | /* | ||
| 88 | * list for tracking inodes that must be sent to disk before a | ||
| 89 | * rename or truncate commit | ||
| 90 | */ | ||
| 91 | struct list_head ordered_operations; | ||
| 92 | |||
| 93 | /* node for the red-black tree that links inodes in subvolume root */ | 87 | /* node for the red-black tree that links inodes in subvolume root */ |
| 94 | struct rb_node rb_node; | 88 | struct rb_node rb_node; |
| 95 | 89 | ||
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index aeab453b8e24..44ee5d2e52a4 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
| @@ -280,9 +280,9 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, | |||
| 280 | 280 | ||
| 281 | WARN_ON(btrfs_header_generation(buf) > trans->transid); | 281 | WARN_ON(btrfs_header_generation(buf) > trans->transid); |
| 282 | if (new_root_objectid == BTRFS_TREE_RELOC_OBJECTID) | 282 | if (new_root_objectid == BTRFS_TREE_RELOC_OBJECTID) |
| 283 | ret = btrfs_inc_ref(trans, root, cow, 1, 1); | 283 | ret = btrfs_inc_ref(trans, root, cow, 1); |
| 284 | else | 284 | else |
| 285 | ret = btrfs_inc_ref(trans, root, cow, 0, 1); | 285 | ret = btrfs_inc_ref(trans, root, cow, 0); |
| 286 | 286 | ||
| 287 | if (ret) | 287 | if (ret) |
| 288 | return ret; | 288 | return ret; |
| @@ -1035,14 +1035,14 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, | |||
| 1035 | if ((owner == root->root_key.objectid || | 1035 | if ((owner == root->root_key.objectid || |
| 1036 | root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) && | 1036 | root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) && |
| 1037 | !(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF)) { | 1037 | !(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF)) { |
| 1038 | ret = btrfs_inc_ref(trans, root, buf, 1, 1); | 1038 | ret = btrfs_inc_ref(trans, root, buf, 1); |
| 1039 | BUG_ON(ret); /* -ENOMEM */ | 1039 | BUG_ON(ret); /* -ENOMEM */ |
| 1040 | 1040 | ||
| 1041 | if (root->root_key.objectid == | 1041 | if (root->root_key.objectid == |
| 1042 | BTRFS_TREE_RELOC_OBJECTID) { | 1042 | BTRFS_TREE_RELOC_OBJECTID) { |
| 1043 | ret = btrfs_dec_ref(trans, root, buf, 0, 1); | 1043 | ret = btrfs_dec_ref(trans, root, buf, 0); |
| 1044 | BUG_ON(ret); /* -ENOMEM */ | 1044 | BUG_ON(ret); /* -ENOMEM */ |
| 1045 | ret = btrfs_inc_ref(trans, root, cow, 1, 1); | 1045 | ret = btrfs_inc_ref(trans, root, cow, 1); |
| 1046 | BUG_ON(ret); /* -ENOMEM */ | 1046 | BUG_ON(ret); /* -ENOMEM */ |
| 1047 | } | 1047 | } |
| 1048 | new_flags |= BTRFS_BLOCK_FLAG_FULL_BACKREF; | 1048 | new_flags |= BTRFS_BLOCK_FLAG_FULL_BACKREF; |
| @@ -1050,9 +1050,9 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, | |||
| 1050 | 1050 | ||
| 1051 | if (root->root_key.objectid == | 1051 | if (root->root_key.objectid == |
| 1052 | BTRFS_TREE_RELOC_OBJECTID) | 1052 | BTRFS_TREE_RELOC_OBJECTID) |
| 1053 | ret = btrfs_inc_ref(trans, root, cow, 1, 1); | 1053 | ret = btrfs_inc_ref(trans, root, cow, 1); |
| 1054 | else | 1054 | else |
| 1055 | ret = btrfs_inc_ref(trans, root, cow, 0, 1); | 1055 | ret = btrfs_inc_ref(trans, root, cow, 0); |
| 1056 | BUG_ON(ret); /* -ENOMEM */ | 1056 | BUG_ON(ret); /* -ENOMEM */ |
| 1057 | } | 1057 | } |
| 1058 | if (new_flags != 0) { | 1058 | if (new_flags != 0) { |
| @@ -1069,11 +1069,11 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, | |||
| 1069 | if (flags & BTRFS_BLOCK_FLAG_FULL_BACKREF) { | 1069 | if (flags & BTRFS_BLOCK_FLAG_FULL_BACKREF) { |
| 1070 | if (root->root_key.objectid == | 1070 | if (root->root_key.objectid == |
| 1071 | BTRFS_TREE_RELOC_OBJECTID) | 1071 | BTRFS_TREE_RELOC_OBJECTID) |
| 1072 | ret = btrfs_inc_ref(trans, root, cow, 1, 1); | 1072 | ret = btrfs_inc_ref(trans, root, cow, 1); |
| 1073 | else | 1073 | else |
| 1074 | ret = btrfs_inc_ref(trans, root, cow, 0, 1); | 1074 | ret = btrfs_inc_ref(trans, root, cow, 0); |
| 1075 | BUG_ON(ret); /* -ENOMEM */ | 1075 | BUG_ON(ret); /* -ENOMEM */ |
| 1076 | ret = btrfs_dec_ref(trans, root, buf, 1, 1); | 1076 | ret = btrfs_dec_ref(trans, root, buf, 1); |
| 1077 | BUG_ON(ret); /* -ENOMEM */ | 1077 | BUG_ON(ret); /* -ENOMEM */ |
| 1078 | } | 1078 | } |
| 1079 | clean_tree_block(trans, root, buf); | 1079 | clean_tree_block(trans, root, buf); |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index be91397f4e92..8e29b614fe93 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -3326,9 +3326,9 @@ int btrfs_reserve_extent(struct btrfs_root *root, u64 num_bytes, | |||
| 3326 | u64 min_alloc_size, u64 empty_size, u64 hint_byte, | 3326 | u64 min_alloc_size, u64 empty_size, u64 hint_byte, |
| 3327 | struct btrfs_key *ins, int is_data, int delalloc); | 3327 | struct btrfs_key *ins, int is_data, int delalloc); |
| 3328 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 3328 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
| 3329 | struct extent_buffer *buf, int full_backref, int no_quota); | 3329 | struct extent_buffer *buf, int full_backref); |
| 3330 | int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 3330 | int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
| 3331 | struct extent_buffer *buf, int full_backref, int no_quota); | 3331 | struct extent_buffer *buf, int full_backref); |
| 3332 | int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans, | 3332 | int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans, |
| 3333 | struct btrfs_root *root, | 3333 | struct btrfs_root *root, |
| 3334 | u64 bytenr, u64 num_bytes, u64 flags, | 3334 | u64 bytenr, u64 num_bytes, u64 flags, |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 08e65e9cf2aa..d0ed9e664f7d 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -60,8 +60,6 @@ static void end_workqueue_fn(struct btrfs_work *work); | |||
| 60 | static void free_fs_root(struct btrfs_root *root); | 60 | static void free_fs_root(struct btrfs_root *root); |
| 61 | static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info, | 61 | static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info, |
| 62 | int read_only); | 62 | int read_only); |
| 63 | static void btrfs_destroy_ordered_operations(struct btrfs_transaction *t, | ||
| 64 | struct btrfs_root *root); | ||
| 65 | static void btrfs_destroy_ordered_extents(struct btrfs_root *root); | 63 | static void btrfs_destroy_ordered_extents(struct btrfs_root *root); |
| 66 | static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, | 64 | static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, |
| 67 | struct btrfs_root *root); | 65 | struct btrfs_root *root); |
| @@ -3829,34 +3827,6 @@ static void btrfs_error_commit_super(struct btrfs_root *root) | |||
| 3829 | btrfs_cleanup_transaction(root); | 3827 | btrfs_cleanup_transaction(root); |
| 3830 | } | 3828 | } |
| 3831 | 3829 | ||
| 3832 | static void btrfs_destroy_ordered_operations(struct btrfs_transaction *t, | ||
| 3833 | struct btrfs_root *root) | ||
| 3834 | { | ||
| 3835 | struct btrfs_inode *btrfs_inode; | ||
| 3836 | struct list_head splice; | ||
| 3837 | |||
| 3838 | INIT_LIST_HEAD(&splice); | ||
| 3839 | |||
| 3840 | mutex_lock(&root->fs_info->ordered_operations_mutex); | ||
| 3841 | spin_lock(&root->fs_info->ordered_root_lock); | ||
| 3842 | |||
| 3843 | list_splice_init(&t->ordered_operations, &splice); | ||
| 3844 | while (!list_empty(&splice)) { | ||
| 3845 | btrfs_inode = list_entry(splice.next, struct btrfs_inode, | ||
| 3846 | ordered_operations); | ||
| 3847 | |||
| 3848 | list_del_init(&btrfs_inode->ordered_operations); | ||
| 3849 | spin_unlock(&root->fs_info->ordered_root_lock); | ||
| 3850 | |||
| 3851 | btrfs_invalidate_inodes(btrfs_inode->root); | ||
| 3852 | |||
| 3853 | spin_lock(&root->fs_info->ordered_root_lock); | ||
| 3854 | } | ||
| 3855 | |||
| 3856 | spin_unlock(&root->fs_info->ordered_root_lock); | ||
| 3857 | mutex_unlock(&root->fs_info->ordered_operations_mutex); | ||
| 3858 | } | ||
| 3859 | |||
| 3860 | static void btrfs_destroy_ordered_extents(struct btrfs_root *root) | 3830 | static void btrfs_destroy_ordered_extents(struct btrfs_root *root) |
| 3861 | { | 3831 | { |
| 3862 | struct btrfs_ordered_extent *ordered; | 3832 | struct btrfs_ordered_extent *ordered; |
| @@ -4093,8 +4063,6 @@ again: | |||
| 4093 | void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans, | 4063 | void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans, |
| 4094 | struct btrfs_root *root) | 4064 | struct btrfs_root *root) |
| 4095 | { | 4065 | { |
| 4096 | btrfs_destroy_ordered_operations(cur_trans, root); | ||
| 4097 | |||
| 4098 | btrfs_destroy_delayed_refs(cur_trans, root); | 4066 | btrfs_destroy_delayed_refs(cur_trans, root); |
| 4099 | 4067 | ||
| 4100 | cur_trans->state = TRANS_STATE_COMMIT_START; | 4068 | cur_trans->state = TRANS_STATE_COMMIT_START; |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 813537f362f9..102ed3143976 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -3057,7 +3057,7 @@ out: | |||
| 3057 | static int __btrfs_mod_ref(struct btrfs_trans_handle *trans, | 3057 | static int __btrfs_mod_ref(struct btrfs_trans_handle *trans, |
| 3058 | struct btrfs_root *root, | 3058 | struct btrfs_root *root, |
| 3059 | struct extent_buffer *buf, | 3059 | struct extent_buffer *buf, |
| 3060 | int full_backref, int inc, int no_quota) | 3060 | int full_backref, int inc) |
| 3061 | { | 3061 | { |
| 3062 | u64 bytenr; | 3062 | u64 bytenr; |
| 3063 | u64 num_bytes; | 3063 | u64 num_bytes; |
| @@ -3111,7 +3111,7 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans, | |||
| 3111 | key.offset -= btrfs_file_extent_offset(buf, fi); | 3111 | key.offset -= btrfs_file_extent_offset(buf, fi); |
| 3112 | ret = process_func(trans, root, bytenr, num_bytes, | 3112 | ret = process_func(trans, root, bytenr, num_bytes, |
| 3113 | parent, ref_root, key.objectid, | 3113 | parent, ref_root, key.objectid, |
| 3114 | key.offset, no_quota); | 3114 | key.offset, 1); |
| 3115 | if (ret) | 3115 | if (ret) |
| 3116 | goto fail; | 3116 | goto fail; |
| 3117 | } else { | 3117 | } else { |
| @@ -3119,7 +3119,7 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans, | |||
| 3119 | num_bytes = btrfs_level_size(root, level - 1); | 3119 | num_bytes = btrfs_level_size(root, level - 1); |
| 3120 | ret = process_func(trans, root, bytenr, num_bytes, | 3120 | ret = process_func(trans, root, bytenr, num_bytes, |
| 3121 | parent, ref_root, level - 1, 0, | 3121 | parent, ref_root, level - 1, 0, |
| 3122 | no_quota); | 3122 | 1); |
| 3123 | if (ret) | 3123 | if (ret) |
| 3124 | goto fail; | 3124 | goto fail; |
| 3125 | } | 3125 | } |
| @@ -3130,15 +3130,15 @@ fail: | |||
| 3130 | } | 3130 | } |
| 3131 | 3131 | ||
| 3132 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 3132 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
| 3133 | struct extent_buffer *buf, int full_backref, int no_quota) | 3133 | struct extent_buffer *buf, int full_backref) |
| 3134 | { | 3134 | { |
| 3135 | return __btrfs_mod_ref(trans, root, buf, full_backref, 1, no_quota); | 3135 | return __btrfs_mod_ref(trans, root, buf, full_backref, 1); |
| 3136 | } | 3136 | } |
| 3137 | 3137 | ||
| 3138 | int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 3138 | int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
| 3139 | struct extent_buffer *buf, int full_backref, int no_quota) | 3139 | struct extent_buffer *buf, int full_backref) |
| 3140 | { | 3140 | { |
| 3141 | return __btrfs_mod_ref(trans, root, buf, full_backref, 0, no_quota); | 3141 | return __btrfs_mod_ref(trans, root, buf, full_backref, 0); |
| 3142 | } | 3142 | } |
| 3143 | 3143 | ||
| 3144 | static int write_one_cache_group(struct btrfs_trans_handle *trans, | 3144 | static int write_one_cache_group(struct btrfs_trans_handle *trans, |
| @@ -7478,6 +7478,220 @@ reada: | |||
| 7478 | wc->reada_slot = slot; | 7478 | wc->reada_slot = slot; |
| 7479 | } | 7479 | } |
| 7480 | 7480 | ||
| 7481 | static int account_leaf_items(struct btrfs_trans_handle *trans, | ||
| 7482 | struct btrfs_root *root, | ||
| 7483 | struct extent_buffer *eb) | ||
| 7484 | { | ||
| 7485 | int nr = btrfs_header_nritems(eb); | ||
| 7486 | int i, extent_type, ret; | ||
| 7487 | struct btrfs_key key; | ||
| 7488 | struct btrfs_file_extent_item *fi; | ||
| 7489 | u64 bytenr, num_bytes; | ||
| 7490 | |||
| 7491 | for (i = 0; i < nr; i++) { | ||
| 7492 | btrfs_item_key_to_cpu(eb, &key, i); | ||
| 7493 | |||
| 7494 | if (key.type != BTRFS_EXTENT_DATA_KEY) | ||
| 7495 | continue; | ||
| 7496 | |||
| 7497 | fi = btrfs_item_ptr(eb, i, struct btrfs_file_extent_item); | ||
| 7498 | /* filter out non qgroup-accountable extents */ | ||
| 7499 | extent_type = btrfs_file_extent_type(eb, fi); | ||
| 7500 | |||
| 7501 | if (extent_type == BTRFS_FILE_EXTENT_INLINE) | ||
| 7502 | continue; | ||
| 7503 | |||
| 7504 | bytenr = btrfs_file_extent_disk_bytenr(eb, fi); | ||
| 7505 | if (!bytenr) | ||
| 7506 | continue; | ||
| 7507 | |||
| 7508 | num_bytes = btrfs_file_extent_disk_num_bytes(eb, fi); | ||
| 7509 | |||
| 7510 | ret = btrfs_qgroup_record_ref(trans, root->fs_info, | ||
| 7511 | root->objectid, | ||
| 7512 | bytenr, num_bytes, | ||
| 7513 | BTRFS_QGROUP_OPER_SUB_SUBTREE, 0); | ||
| 7514 | if (ret) | ||
| 7515 | return ret; | ||
| 7516 | } | ||
| 7517 | return 0; | ||
| 7518 | } | ||
| 7519 | |||
| 7520 | /* | ||
| 7521 | * Walk up the tree from the bottom, freeing leaves and any interior | ||
| 7522 | * nodes which have had all slots visited. If a node (leaf or | ||
| 7523 | * interior) is freed, the node above it will have it's slot | ||
| 7524 | * incremented. The root node will never be freed. | ||
| 7525 | * | ||
| 7526 | * At the end of this function, we should have a path which has all | ||
| 7527 | * slots incremented to the next position for a search. If we need to | ||
| 7528 | * read a new node it will be NULL and the node above it will have the | ||
| 7529 | * correct slot selected for a later read. | ||
| 7530 | * | ||
| 7531 | * If we increment the root nodes slot counter past the number of | ||
| 7532 | * elements, 1 is returned to signal completion of the search. | ||
| 7533 | */ | ||
| 7534 | static int adjust_slots_upwards(struct btrfs_root *root, | ||
| 7535 | struct btrfs_path *path, int root_level) | ||
| 7536 | { | ||
| 7537 | int level = 0; | ||
| 7538 | int nr, slot; | ||
| 7539 | struct extent_buffer *eb; | ||
| 7540 | |||
| 7541 | if (root_level == 0) | ||
| 7542 | return 1; | ||
| 7543 | |||
| 7544 | while (level <= root_level) { | ||
| 7545 | eb = path->nodes[level]; | ||
| 7546 | nr = btrfs_header_nritems(eb); | ||
| 7547 | path->slots[level]++; | ||
| 7548 | slot = path->slots[level]; | ||
| 7549 | if (slot >= nr || level == 0) { | ||
| 7550 | /* | ||
| 7551 | * Don't free the root - we will detect this | ||
| 7552 | * condition after our loop and return a | ||
| 7553 | * positive value for caller to stop walking the tree. | ||
| 7554 | */ | ||
| 7555 | if (level != root_level) { | ||
| 7556 | btrfs_tree_unlock_rw(eb, path->locks[level]); | ||
| 7557 | path->locks[level] = 0; | ||
| 7558 | |||
| 7559 | free_extent_buffer(eb); | ||
| 7560 | path->nodes[level] = NULL; | ||
| 7561 | path->slots[level] = 0; | ||
| 7562 | } | ||
| 7563 | } else { | ||
| 7564 | /* | ||
| 7565 | * We have a valid slot to walk back down | ||
| 7566 | * from. Stop here so caller can process these | ||
| 7567 | * new nodes. | ||
| 7568 | */ | ||
| 7569 | break; | ||
| 7570 | } | ||
| 7571 | |||
| 7572 | level++; | ||
| 7573 | } | ||
| 7574 | |||
| 7575 | eb = path->nodes[root_level]; | ||
| 7576 | if (path->slots[root_level] >= btrfs_header_nritems(eb)) | ||
| 7577 | return 1; | ||
| 7578 | |||
| 7579 | return 0; | ||
| 7580 | } | ||
| 7581 | |||
| 7582 | /* | ||
| 7583 | * root_eb is the subtree root and is locked before this function is called. | ||
| 7584 | */ | ||
| 7585 | static int account_shared_subtree(struct btrfs_trans_handle *trans, | ||
| 7586 | struct btrfs_root *root, | ||
| 7587 | struct extent_buffer *root_eb, | ||
| 7588 | u64 root_gen, | ||
| 7589 | int root_level) | ||
| 7590 | { | ||
| 7591 | int ret = 0; | ||
| 7592 | int level; | ||
| 7593 | struct extent_buffer *eb = root_eb; | ||
| 7594 | struct btrfs_path *path = NULL; | ||
| 7595 | |||
| 7596 | BUG_ON(root_level < 0 || root_level > BTRFS_MAX_LEVEL); | ||
| 7597 | BUG_ON(root_eb == NULL); | ||
| 7598 | |||
| 7599 | if (!root->fs_info->quota_enabled) | ||
| 7600 | return 0; | ||
| 7601 | |||
| 7602 | if (!extent_buffer_uptodate(root_eb)) { | ||
| 7603 | ret = btrfs_read_buffer(root_eb, root_gen); | ||
| 7604 | if (ret) | ||
| 7605 | goto out; | ||
| 7606 | } | ||
| 7607 | |||
| 7608 | if (root_level == 0) { | ||
| 7609 | ret = account_leaf_items(trans, root, root_eb); | ||
| 7610 | goto out; | ||
| 7611 | } | ||
| 7612 | |||
| 7613 | path = btrfs_alloc_path(); | ||
| 7614 | if (!path) | ||
| 7615 | return -ENOMEM; | ||
| 7616 | |||
| 7617 | /* | ||
| 7618 | * Walk down the tree. Missing extent blocks are filled in as | ||
| 7619 | * we go. Metadata is accounted every time we read a new | ||
| 7620 | * extent block. | ||
| 7621 | * | ||
| 7622 | * When we reach a leaf, we account for file extent items in it, | ||
| 7623 | * walk back up the tree (adjusting slot pointers as we go) | ||
| 7624 | * and restart the search process. | ||
| 7625 | */ | ||
| 7626 | extent_buffer_get(root_eb); /* For path */ | ||
| 7627 | path->nodes[root_level] = root_eb; | ||
| 7628 | path->slots[root_level] = 0; | ||
| 7629 | path->locks[root_level] = 0; /* so release_path doesn't try to unlock */ | ||
| 7630 | walk_down: | ||
| 7631 | level = root_level; | ||
| 7632 | while (level >= 0) { | ||
| 7633 | if (path->nodes[level] == NULL) { | ||
| 7634 | int child_bsize = root->nodesize; | ||
| 7635 | int parent_slot; | ||
| 7636 | u64 child_gen; | ||
| 7637 | u64 child_bytenr; | ||
| 7638 | |||
| 7639 | /* We need to get child blockptr/gen from | ||
| 7640 | * parent before we can read it. */ | ||
| 7641 | eb = path->nodes[level + 1]; | ||
| 7642 | parent_slot = path->slots[level + 1]; | ||
| 7643 | child_bytenr = btrfs_node_blockptr(eb, parent_slot); | ||
| 7644 | child_gen = btrfs_node_ptr_generation(eb, parent_slot); | ||
| 7645 | |||
| 7646 | eb = read_tree_block(root, child_bytenr, child_bsize, | ||
| 7647 | child_gen); | ||
| 7648 | if (!eb || !extent_buffer_uptodate(eb)) { | ||
| 7649 | ret = -EIO; | ||
| 7650 | goto out; | ||
| 7651 | } | ||
| 7652 | |||
| 7653 | path->nodes[level] = eb; | ||
| 7654 | path->slots[level] = 0; | ||
| 7655 | |||
| 7656 | btrfs_tree_read_lock(eb); | ||
| 7657 | btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); | ||
| 7658 | path->locks[level] = BTRFS_READ_LOCK_BLOCKING; | ||
| 7659 | |||
| 7660 | ret = btrfs_qgroup_record_ref(trans, root->fs_info, | ||
| 7661 | root->objectid, | ||
| 7662 | child_bytenr, | ||
| 7663 | child_bsize, | ||
| 7664 | BTRFS_QGROUP_OPER_SUB_SUBTREE, | ||
| 7665 | 0); | ||
| 7666 | if (ret) | ||
| 7667 | goto out; | ||
| 7668 | |||
| 7669 | } | ||
| 7670 | |||
| 7671 | if (level == 0) { | ||
| 7672 | ret = account_leaf_items(trans, root, path->nodes[level]); | ||
| 7673 | if (ret) | ||
| 7674 | goto out; | ||
| 7675 | |||
| 7676 | /* Nonzero return here means we completed our search */ | ||
| 7677 | ret = adjust_slots_upwards(root, path, root_level); | ||
| 7678 | if (ret) | ||
| 7679 | break; | ||
| 7680 | |||
| 7681 | /* Restart search with new slots */ | ||
| 7682 | goto walk_down; | ||
| 7683 | } | ||
| 7684 | |||
| 7685 | level--; | ||
| 7686 | } | ||
| 7687 | |||
| 7688 | ret = 0; | ||
| 7689 | out: | ||
| 7690 | btrfs_free_path(path); | ||
| 7691 | |||
| 7692 | return ret; | ||
| 7693 | } | ||
| 7694 | |||
| 7481 | /* | 7695 | /* |
| 7482 | * helper to process tree block while walking down the tree. | 7696 | * helper to process tree block while walking down the tree. |
| 7483 | * | 7697 | * |
| @@ -7532,9 +7746,9 @@ static noinline int walk_down_proc(struct btrfs_trans_handle *trans, | |||
| 7532 | /* wc->stage == UPDATE_BACKREF */ | 7746 | /* wc->stage == UPDATE_BACKREF */ |
| 7533 | if (!(wc->flags[level] & flag)) { | 7747 | if (!(wc->flags[level] & flag)) { |
| 7534 | BUG_ON(!path->locks[level]); | 7748 | BUG_ON(!path->locks[level]); |
| 7535 | ret = btrfs_inc_ref(trans, root, eb, 1, wc->for_reloc); | 7749 | ret = btrfs_inc_ref(trans, root, eb, 1); |
| 7536 | BUG_ON(ret); /* -ENOMEM */ | 7750 | BUG_ON(ret); /* -ENOMEM */ |
| 7537 | ret = btrfs_dec_ref(trans, root, eb, 0, wc->for_reloc); | 7751 | ret = btrfs_dec_ref(trans, root, eb, 0); |
| 7538 | BUG_ON(ret); /* -ENOMEM */ | 7752 | BUG_ON(ret); /* -ENOMEM */ |
| 7539 | ret = btrfs_set_disk_extent_flags(trans, root, eb->start, | 7753 | ret = btrfs_set_disk_extent_flags(trans, root, eb->start, |
| 7540 | eb->len, flag, | 7754 | eb->len, flag, |
| @@ -7581,6 +7795,7 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans, | |||
| 7581 | int level = wc->level; | 7795 | int level = wc->level; |
| 7582 | int reada = 0; | 7796 | int reada = 0; |
| 7583 | int ret = 0; | 7797 | int ret = 0; |
| 7798 | bool need_account = false; | ||
| 7584 | 7799 | ||
| 7585 | generation = btrfs_node_ptr_generation(path->nodes[level], | 7800 | generation = btrfs_node_ptr_generation(path->nodes[level], |
| 7586 | path->slots[level]); | 7801 | path->slots[level]); |
| @@ -7626,6 +7841,7 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans, | |||
| 7626 | 7841 | ||
| 7627 | if (wc->stage == DROP_REFERENCE) { | 7842 | if (wc->stage == DROP_REFERENCE) { |
| 7628 | if (wc->refs[level - 1] > 1) { | 7843 | if (wc->refs[level - 1] > 1) { |
| 7844 | need_account = true; | ||
| 7629 | if (level == 1 && | 7845 | if (level == 1 && |
| 7630 | (wc->flags[0] & BTRFS_BLOCK_FLAG_FULL_BACKREF)) | 7846 | (wc->flags[0] & BTRFS_BLOCK_FLAG_FULL_BACKREF)) |
| 7631 | goto skip; | 7847 | goto skip; |
| @@ -7689,6 +7905,16 @@ skip: | |||
| 7689 | parent = 0; | 7905 | parent = 0; |
| 7690 | } | 7906 | } |
| 7691 | 7907 | ||
| 7908 | if (need_account) { | ||
| 7909 | ret = account_shared_subtree(trans, root, next, | ||
| 7910 | generation, level - 1); | ||
| 7911 | if (ret) { | ||
| 7912 | printk_ratelimited(KERN_ERR "BTRFS: %s Error " | ||
| 7913 | "%d accounting shared subtree. Quota " | ||
| 7914 | "is out of sync, rescan required.\n", | ||
| 7915 | root->fs_info->sb->s_id, ret); | ||
| 7916 | } | ||
| 7917 | } | ||
| 7692 | ret = btrfs_free_extent(trans, root, bytenr, blocksize, parent, | 7918 | ret = btrfs_free_extent(trans, root, bytenr, blocksize, parent, |
| 7693 | root->root_key.objectid, level - 1, 0, 0); | 7919 | root->root_key.objectid, level - 1, 0, 0); |
| 7694 | BUG_ON(ret); /* -ENOMEM */ | 7920 | BUG_ON(ret); /* -ENOMEM */ |
| @@ -7769,12 +7995,17 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans, | |||
| 7769 | if (wc->refs[level] == 1) { | 7995 | if (wc->refs[level] == 1) { |
| 7770 | if (level == 0) { | 7996 | if (level == 0) { |
| 7771 | if (wc->flags[level] & BTRFS_BLOCK_FLAG_FULL_BACKREF) | 7997 | if (wc->flags[level] & BTRFS_BLOCK_FLAG_FULL_BACKREF) |
| 7772 | ret = btrfs_dec_ref(trans, root, eb, 1, | 7998 | ret = btrfs_dec_ref(trans, root, eb, 1); |
| 7773 | wc->for_reloc); | ||
| 7774 | else | 7999 | else |
| 7775 | ret = btrfs_dec_ref(trans, root, eb, 0, | 8000 | ret = btrfs_dec_ref(trans, root, eb, 0); |
| 7776 | wc->for_reloc); | ||
| 7777 | BUG_ON(ret); /* -ENOMEM */ | 8001 | BUG_ON(ret); /* -ENOMEM */ |
| 8002 | ret = account_leaf_items(trans, root, eb); | ||
| 8003 | if (ret) { | ||
| 8004 | printk_ratelimited(KERN_ERR "BTRFS: %s Error " | ||
| 8005 | "%d accounting leaf items. Quota " | ||
| 8006 | "is out of sync, rescan required.\n", | ||
| 8007 | root->fs_info->sb->s_id, ret); | ||
| 8008 | } | ||
| 7778 | } | 8009 | } |
| 7779 | /* make block locked assertion in clean_tree_block happy */ | 8010 | /* make block locked assertion in clean_tree_block happy */ |
| 7780 | if (!path->locks[level] && | 8011 | if (!path->locks[level] && |
| @@ -7900,6 +8131,8 @@ int btrfs_drop_snapshot(struct btrfs_root *root, | |||
| 7900 | int level; | 8131 | int level; |
| 7901 | bool root_dropped = false; | 8132 | bool root_dropped = false; |
| 7902 | 8133 | ||
| 8134 | btrfs_debug(root->fs_info, "Drop subvolume %llu", root->objectid); | ||
| 8135 | |||
| 7903 | path = btrfs_alloc_path(); | 8136 | path = btrfs_alloc_path(); |
| 7904 | if (!path) { | 8137 | if (!path) { |
| 7905 | err = -ENOMEM; | 8138 | err = -ENOMEM; |
| @@ -8025,6 +8258,24 @@ int btrfs_drop_snapshot(struct btrfs_root *root, | |||
| 8025 | goto out_end_trans; | 8258 | goto out_end_trans; |
| 8026 | } | 8259 | } |
| 8027 | 8260 | ||
| 8261 | /* | ||
| 8262 | * Qgroup update accounting is run from | ||
| 8263 | * delayed ref handling. This usually works | ||
| 8264 | * out because delayed refs are normally the | ||
| 8265 | * only way qgroup updates are added. However, | ||
| 8266 | * we may have added updates during our tree | ||
| 8267 | * walk so run qgroups here to make sure we | ||
| 8268 | * don't lose any updates. | ||
| 8269 | */ | ||
| 8270 | ret = btrfs_delayed_qgroup_accounting(trans, | ||
| 8271 | root->fs_info); | ||
| 8272 | if (ret) | ||
| 8273 | printk_ratelimited(KERN_ERR "BTRFS: Failure %d " | ||
| 8274 | "running qgroup updates " | ||
| 8275 | "during snapshot delete. " | ||
| 8276 | "Quota is out of sync, " | ||
| 8277 | "rescan required.\n", ret); | ||
| 8278 | |||
| 8028 | btrfs_end_transaction_throttle(trans, tree_root); | 8279 | btrfs_end_transaction_throttle(trans, tree_root); |
| 8029 | if (!for_reloc && btrfs_need_cleaner_sleep(root)) { | 8280 | if (!for_reloc && btrfs_need_cleaner_sleep(root)) { |
| 8030 | pr_debug("BTRFS: drop snapshot early exit\n"); | 8281 | pr_debug("BTRFS: drop snapshot early exit\n"); |
| @@ -8078,6 +8329,14 @@ int btrfs_drop_snapshot(struct btrfs_root *root, | |||
| 8078 | } | 8329 | } |
| 8079 | root_dropped = true; | 8330 | root_dropped = true; |
| 8080 | out_end_trans: | 8331 | out_end_trans: |
| 8332 | ret = btrfs_delayed_qgroup_accounting(trans, tree_root->fs_info); | ||
| 8333 | if (ret) | ||
| 8334 | printk_ratelimited(KERN_ERR "BTRFS: Failure %d " | ||
| 8335 | "running qgroup updates " | ||
| 8336 | "during snapshot delete. " | ||
| 8337 | "Quota is out of sync, " | ||
| 8338 | "rescan required.\n", ret); | ||
| 8339 | |||
| 8081 | btrfs_end_transaction_throttle(trans, tree_root); | 8340 | btrfs_end_transaction_throttle(trans, tree_root); |
| 8082 | out_free: | 8341 | out_free: |
| 8083 | kfree(wc); | 8342 | kfree(wc); |
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index f46cfe45d686..54c84daec9b5 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c | |||
| @@ -756,7 +756,7 @@ again: | |||
| 756 | found_next = 1; | 756 | found_next = 1; |
| 757 | if (ret != 0) | 757 | if (ret != 0) |
| 758 | goto insert; | 758 | goto insert; |
| 759 | slot = 0; | 759 | slot = path->slots[0]; |
| 760 | } | 760 | } |
| 761 | btrfs_item_key_to_cpu(path->nodes[0], &found_key, slot); | 761 | btrfs_item_key_to_cpu(path->nodes[0], &found_key, slot); |
| 762 | if (found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID || | 762 | if (found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID || |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 1f2b99cb55ea..d3afac292d67 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
| @@ -1838,33 +1838,9 @@ out: | |||
| 1838 | 1838 | ||
| 1839 | int btrfs_release_file(struct inode *inode, struct file *filp) | 1839 | int btrfs_release_file(struct inode *inode, struct file *filp) |
| 1840 | { | 1840 | { |
| 1841 | /* | ||
| 1842 | * ordered_data_close is set by settattr when we are about to truncate | ||
| 1843 | * a file from a non-zero size to a zero size. This tries to | ||
| 1844 | * flush down new bytes that may have been written if the | ||
| 1845 | * application were using truncate to replace a file in place. | ||
| 1846 | */ | ||
| 1847 | if (test_and_clear_bit(BTRFS_INODE_ORDERED_DATA_CLOSE, | ||
| 1848 | &BTRFS_I(inode)->runtime_flags)) { | ||
| 1849 | struct btrfs_trans_handle *trans; | ||
| 1850 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
| 1851 | |||
| 1852 | /* | ||
| 1853 | * We need to block on a committing transaction to keep us from | ||
| 1854 | * throwing a ordered operation on to the list and causing | ||
| 1855 | * something like sync to deadlock trying to flush out this | ||
| 1856 | * inode. | ||
| 1857 | */ | ||
| 1858 | trans = btrfs_start_transaction(root, 0); | ||
| 1859 | if (IS_ERR(trans)) | ||
| 1860 | return PTR_ERR(trans); | ||
| 1861 | btrfs_add_ordered_operation(trans, BTRFS_I(inode)->root, inode); | ||
| 1862 | btrfs_end_transaction(trans, root); | ||
| 1863 | if (inode->i_size > BTRFS_ORDERED_OPERATIONS_FLUSH_LIMIT) | ||
| 1864 | filemap_flush(inode->i_mapping); | ||
| 1865 | } | ||
| 1866 | if (filp->private_data) | 1841 | if (filp->private_data) |
| 1867 | btrfs_ioctl_trans_end(filp); | 1842 | btrfs_ioctl_trans_end(filp); |
| 1843 | filemap_flush(inode->i_mapping); | ||
| 1868 | return 0; | 1844 | return 0; |
| 1869 | } | 1845 | } |
| 1870 | 1846 | ||
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 3183742d6f0d..03708ef3deef 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -709,6 +709,18 @@ retry: | |||
| 709 | unlock_extent(io_tree, async_extent->start, | 709 | unlock_extent(io_tree, async_extent->start, |
| 710 | async_extent->start + | 710 | async_extent->start + |
| 711 | async_extent->ram_size - 1); | 711 | async_extent->ram_size - 1); |
| 712 | |||
| 713 | /* | ||
| 714 | * we need to redirty the pages if we decide to | ||
| 715 | * fallback to uncompressed IO, otherwise we | ||
| 716 | * will not submit these pages down to lower | ||
| 717 | * layers. | ||
| 718 | */ | ||
| 719 | extent_range_redirty_for_io(inode, | ||
| 720 | async_extent->start, | ||
| 721 | async_extent->start + | ||
| 722 | async_extent->ram_size - 1); | ||
| 723 | |||
| 712 | goto retry; | 724 | goto retry; |
| 713 | } | 725 | } |
| 714 | goto out_free; | 726 | goto out_free; |
| @@ -7939,27 +7951,6 @@ static int btrfs_truncate(struct inode *inode) | |||
| 7939 | BUG_ON(ret); | 7951 | BUG_ON(ret); |
| 7940 | 7952 | ||
| 7941 | /* | 7953 | /* |
| 7942 | * setattr is responsible for setting the ordered_data_close flag, | ||
| 7943 | * but that is only tested during the last file release. That | ||
| 7944 | * could happen well after the next commit, leaving a great big | ||
| 7945 | * window where new writes may get lost if someone chooses to write | ||
| 7946 | * to this file after truncating to zero | ||
| 7947 | * | ||
| 7948 | * The inode doesn't have any dirty data here, and so if we commit | ||
| 7949 | * this is a noop. If someone immediately starts writing to the inode | ||
| 7950 | * it is very likely we'll catch some of their writes in this | ||
| 7951 | * transaction, and the commit will find this file on the ordered | ||
| 7952 | * data list with good things to send down. | ||
| 7953 | * | ||
| 7954 | * This is a best effort solution, there is still a window where | ||
| 7955 | * using truncate to replace the contents of the file will | ||
| 7956 | * end up with a zero length file after a crash. | ||
| 7957 | */ | ||
| 7958 | if (inode->i_size == 0 && test_bit(BTRFS_INODE_ORDERED_DATA_CLOSE, | ||
| 7959 | &BTRFS_I(inode)->runtime_flags)) | ||
| 7960 | btrfs_add_ordered_operation(trans, root, inode); | ||
| 7961 | |||
| 7962 | /* | ||
| 7963 | * So if we truncate and then write and fsync we normally would just | 7954 | * So if we truncate and then write and fsync we normally would just |
| 7964 | * write the extents that changed, which is a problem if we need to | 7955 | * write the extents that changed, which is a problem if we need to |
| 7965 | * first truncate that entire inode. So set this flag so we write out | 7956 | * first truncate that entire inode. So set this flag so we write out |
| @@ -8106,7 +8097,6 @@ struct inode *btrfs_alloc_inode(struct super_block *sb) | |||
| 8106 | mutex_init(&ei->delalloc_mutex); | 8097 | mutex_init(&ei->delalloc_mutex); |
| 8107 | btrfs_ordered_inode_tree_init(&ei->ordered_tree); | 8098 | btrfs_ordered_inode_tree_init(&ei->ordered_tree); |
| 8108 | INIT_LIST_HEAD(&ei->delalloc_inodes); | 8099 | INIT_LIST_HEAD(&ei->delalloc_inodes); |
| 8109 | INIT_LIST_HEAD(&ei->ordered_operations); | ||
| 8110 | RB_CLEAR_NODE(&ei->rb_node); | 8100 | RB_CLEAR_NODE(&ei->rb_node); |
| 8111 | 8101 | ||
| 8112 | return inode; | 8102 | return inode; |
| @@ -8146,17 +8136,6 @@ void btrfs_destroy_inode(struct inode *inode) | |||
| 8146 | if (!root) | 8136 | if (!root) |
| 8147 | goto free; | 8137 | goto free; |
| 8148 | 8138 | ||
| 8149 | /* | ||
| 8150 | * Make sure we're properly removed from the ordered operation | ||
| 8151 | * lists. | ||
| 8152 | */ | ||
| 8153 | smp_mb(); | ||
| 8154 | if (!list_empty(&BTRFS_I(inode)->ordered_operations)) { | ||
| 8155 | spin_lock(&root->fs_info->ordered_root_lock); | ||
| 8156 | list_del_init(&BTRFS_I(inode)->ordered_operations); | ||
| 8157 | spin_unlock(&root->fs_info->ordered_root_lock); | ||
| 8158 | } | ||
| 8159 | |||
| 8160 | if (test_bit(BTRFS_INODE_HAS_ORPHAN_ITEM, | 8139 | if (test_bit(BTRFS_INODE_HAS_ORPHAN_ITEM, |
| 8161 | &BTRFS_I(inode)->runtime_flags)) { | 8140 | &BTRFS_I(inode)->runtime_flags)) { |
| 8162 | btrfs_info(root->fs_info, "inode %llu still on the orphan list", | 8141 | btrfs_info(root->fs_info, "inode %llu still on the orphan list", |
| @@ -8338,12 +8317,10 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 8338 | ret = 0; | 8317 | ret = 0; |
| 8339 | 8318 | ||
| 8340 | /* | 8319 | /* |
| 8341 | * we're using rename to replace one file with another. | 8320 | * we're using rename to replace one file with another. Start IO on it |
| 8342 | * and the replacement file is large. Start IO on it now so | 8321 | * now so we don't add too much work to the end of the transaction |
| 8343 | * we don't add too much work to the end of the transaction | ||
| 8344 | */ | 8322 | */ |
| 8345 | if (new_inode && S_ISREG(old_inode->i_mode) && new_inode->i_size && | 8323 | if (new_inode && S_ISREG(old_inode->i_mode) && new_inode->i_size) |
| 8346 | old_inode->i_size > BTRFS_ORDERED_OPERATIONS_FLUSH_LIMIT) | ||
| 8347 | filemap_flush(old_inode->i_mapping); | 8324 | filemap_flush(old_inode->i_mapping); |
| 8348 | 8325 | ||
| 8349 | /* close the racy window with snapshot create/destroy ioctl */ | 8326 | /* close the racy window with snapshot create/destroy ioctl */ |
| @@ -8391,12 +8368,6 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 8391 | */ | 8368 | */ |
| 8392 | btrfs_pin_log_trans(root); | 8369 | btrfs_pin_log_trans(root); |
| 8393 | } | 8370 | } |
| 8394 | /* | ||
| 8395 | * make sure the inode gets flushed if it is replacing | ||
| 8396 | * something. | ||
| 8397 | */ | ||
| 8398 | if (new_inode && new_inode->i_size && S_ISREG(old_inode->i_mode)) | ||
| 8399 | btrfs_add_ordered_operation(trans, root, old_inode); | ||
| 8400 | 8371 | ||
| 8401 | inode_inc_iversion(old_dir); | 8372 | inode_inc_iversion(old_dir); |
| 8402 | inode_inc_iversion(new_dir); | 8373 | inode_inc_iversion(new_dir); |
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 7187b14faa6c..963895c1f801 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
| @@ -571,18 +571,6 @@ void btrfs_remove_ordered_extent(struct inode *inode, | |||
| 571 | 571 | ||
| 572 | trace_btrfs_ordered_extent_remove(inode, entry); | 572 | trace_btrfs_ordered_extent_remove(inode, entry); |
| 573 | 573 | ||
| 574 | /* | ||
| 575 | * we have no more ordered extents for this inode and | ||
| 576 | * no dirty pages. We can safely remove it from the | ||
| 577 | * list of ordered extents | ||
| 578 | */ | ||
| 579 | if (RB_EMPTY_ROOT(&tree->tree) && | ||
| 580 | !mapping_tagged(inode->i_mapping, PAGECACHE_TAG_DIRTY)) { | ||
| 581 | spin_lock(&root->fs_info->ordered_root_lock); | ||
| 582 | list_del_init(&BTRFS_I(inode)->ordered_operations); | ||
| 583 | spin_unlock(&root->fs_info->ordered_root_lock); | ||
| 584 | } | ||
| 585 | |||
| 586 | if (!root->nr_ordered_extents) { | 574 | if (!root->nr_ordered_extents) { |
| 587 | spin_lock(&root->fs_info->ordered_root_lock); | 575 | spin_lock(&root->fs_info->ordered_root_lock); |
| 588 | BUG_ON(list_empty(&root->ordered_root)); | 576 | BUG_ON(list_empty(&root->ordered_root)); |
| @@ -687,81 +675,6 @@ void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr) | |||
| 687 | } | 675 | } |
| 688 | 676 | ||
| 689 | /* | 677 | /* |
| 690 | * this is used during transaction commit to write all the inodes | ||
| 691 | * added to the ordered operation list. These files must be fully on | ||
| 692 | * disk before the transaction commits. | ||
| 693 | * | ||
| 694 | * we have two modes here, one is to just start the IO via filemap_flush | ||
| 695 | * and the other is to wait for all the io. When we wait, we have an | ||
| 696 | * extra check to make sure the ordered operation list really is empty | ||
| 697 | * before we return | ||
| 698 | */ | ||
| 699 | int btrfs_run_ordered_operations(struct btrfs_trans_handle *trans, | ||
| 700 | struct btrfs_root *root, int wait) | ||
| 701 | { | ||
| 702 | struct btrfs_inode *btrfs_inode; | ||
| 703 | struct inode *inode; | ||
| 704 | struct btrfs_transaction *cur_trans = trans->transaction; | ||
| 705 | struct list_head splice; | ||
| 706 | struct list_head works; | ||
| 707 | struct btrfs_delalloc_work *work, *next; | ||
| 708 | int ret = 0; | ||
| 709 | |||
| 710 | INIT_LIST_HEAD(&splice); | ||
| 711 | INIT_LIST_HEAD(&works); | ||
| 712 | |||
| 713 | mutex_lock(&root->fs_info->ordered_extent_flush_mutex); | ||
| 714 | spin_lock(&root->fs_info->ordered_root_lock); | ||
| 715 | list_splice_init(&cur_trans->ordered_operations, &splice); | ||
| 716 | while (!list_empty(&splice)) { | ||
| 717 | btrfs_inode = list_entry(splice.next, struct btrfs_inode, | ||
| 718 | ordered_operations); | ||
| 719 | inode = &btrfs_inode->vfs_inode; | ||
| 720 | |||
| 721 | list_del_init(&btrfs_inode->ordered_operations); | ||
| 722 | |||
| 723 | /* | ||
| 724 | * the inode may be getting freed (in sys_unlink path). | ||
| 725 | */ | ||
| 726 | inode = igrab(inode); | ||
| 727 | if (!inode) | ||
| 728 | continue; | ||
| 729 | |||
| 730 | if (!wait) | ||
| 731 | list_add_tail(&BTRFS_I(inode)->ordered_operations, | ||
| 732 | &cur_trans->ordered_operations); | ||
| 733 | spin_unlock(&root->fs_info->ordered_root_lock); | ||
| 734 | |||
| 735 | work = btrfs_alloc_delalloc_work(inode, wait, 1); | ||
| 736 | if (!work) { | ||
| 737 | spin_lock(&root->fs_info->ordered_root_lock); | ||
| 738 | if (list_empty(&BTRFS_I(inode)->ordered_operations)) | ||
| 739 | list_add_tail(&btrfs_inode->ordered_operations, | ||
| 740 | &splice); | ||
| 741 | list_splice_tail(&splice, | ||
| 742 | &cur_trans->ordered_operations); | ||
| 743 | spin_unlock(&root->fs_info->ordered_root_lock); | ||
| 744 | ret = -ENOMEM; | ||
| 745 | goto out; | ||
| 746 | } | ||
| 747 | list_add_tail(&work->list, &works); | ||
| 748 | btrfs_queue_work(root->fs_info->flush_workers, | ||
| 749 | &work->work); | ||
| 750 | |||
| 751 | cond_resched(); | ||
| 752 | spin_lock(&root->fs_info->ordered_root_lock); | ||
| 753 | } | ||
| 754 | spin_unlock(&root->fs_info->ordered_root_lock); | ||
| 755 | out: | ||
| 756 | list_for_each_entry_safe(work, next, &works, list) { | ||
| 757 | list_del_init(&work->list); | ||
| 758 | btrfs_wait_and_free_delalloc_work(work); | ||
| 759 | } | ||
| 760 | mutex_unlock(&root->fs_info->ordered_extent_flush_mutex); | ||
| 761 | return ret; | ||
| 762 | } | ||
| 763 | |||
| 764 | /* | ||
| 765 | * Used to start IO or wait for a given ordered extent to finish. | 678 | * Used to start IO or wait for a given ordered extent to finish. |
| 766 | * | 679 | * |
| 767 | * If wait is one, this effectively waits on page writeback for all the pages | 680 | * If wait is one, this effectively waits on page writeback for all the pages |
| @@ -1120,42 +1033,6 @@ out: | |||
| 1120 | return index; | 1033 | return index; |
| 1121 | } | 1034 | } |
| 1122 | 1035 | ||
| 1123 | |||
| 1124 | /* | ||
| 1125 | * add a given inode to the list of inodes that must be fully on | ||
| 1126 | * disk before a transaction commit finishes. | ||
| 1127 | * | ||
| 1128 | * This basically gives us the ext3 style data=ordered mode, and it is mostly | ||
| 1129 | * used to make sure renamed files are fully on disk. | ||
| 1130 | * | ||
| 1131 | * It is a noop if the inode is already fully on disk. | ||
| 1132 | * | ||
| 1133 | * If trans is not null, we'll do a friendly check for a transaction that | ||
| 1134 | * is already flushing things and force the IO down ourselves. | ||
| 1135 | */ | ||
| 1136 | void btrfs_add_ordered_operation(struct btrfs_trans_handle *trans, | ||
| 1137 | struct btrfs_root *root, struct inode *inode) | ||
| 1138 | { | ||
| 1139 | struct btrfs_transaction *cur_trans = trans->transaction; | ||
| 1140 | u64 last_mod; | ||
| 1141 | |||
| 1142 | last_mod = max(BTRFS_I(inode)->generation, BTRFS_I(inode)->last_trans); | ||
| 1143 | |||
| 1144 | /* | ||
| 1145 | * if this file hasn't been changed since the last transaction | ||
| 1146 | * commit, we can safely return without doing anything | ||
| 1147 | */ | ||
| 1148 | if (last_mod <= root->fs_info->last_trans_committed) | ||
| 1149 | return; | ||
| 1150 | |||
| 1151 | spin_lock(&root->fs_info->ordered_root_lock); | ||
| 1152 | if (list_empty(&BTRFS_I(inode)->ordered_operations)) { | ||
| 1153 | list_add_tail(&BTRFS_I(inode)->ordered_operations, | ||
| 1154 | &cur_trans->ordered_operations); | ||
| 1155 | } | ||
| 1156 | spin_unlock(&root->fs_info->ordered_root_lock); | ||
| 1157 | } | ||
| 1158 | |||
| 1159 | int __init ordered_data_init(void) | 1036 | int __init ordered_data_init(void) |
| 1160 | { | 1037 | { |
| 1161 | btrfs_ordered_extent_cache = kmem_cache_create("btrfs_ordered_extent", | 1038 | btrfs_ordered_extent_cache = kmem_cache_create("btrfs_ordered_extent", |
diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h index 246897058efb..d81a274d621e 100644 --- a/fs/btrfs/ordered-data.h +++ b/fs/btrfs/ordered-data.h | |||
| @@ -190,11 +190,6 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset, | |||
| 190 | struct btrfs_ordered_extent *ordered); | 190 | struct btrfs_ordered_extent *ordered); |
| 191 | int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr, | 191 | int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr, |
| 192 | u32 *sum, int len); | 192 | u32 *sum, int len); |
| 193 | int btrfs_run_ordered_operations(struct btrfs_trans_handle *trans, | ||
| 194 | struct btrfs_root *root, int wait); | ||
| 195 | void btrfs_add_ordered_operation(struct btrfs_trans_handle *trans, | ||
| 196 | struct btrfs_root *root, | ||
| 197 | struct inode *inode); | ||
| 198 | int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr); | 193 | int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr); |
| 199 | void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr); | 194 | void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr); |
| 200 | void btrfs_get_logged_extents(struct inode *inode, | 195 | void btrfs_get_logged_extents(struct inode *inode, |
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index 98cb6b2630f9..b497498484be 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c | |||
| @@ -1201,6 +1201,50 @@ out: | |||
| 1201 | mutex_unlock(&fs_info->qgroup_ioctl_lock); | 1201 | mutex_unlock(&fs_info->qgroup_ioctl_lock); |
| 1202 | return ret; | 1202 | return ret; |
| 1203 | } | 1203 | } |
| 1204 | |||
| 1205 | static int comp_oper_exist(struct btrfs_qgroup_operation *oper1, | ||
| 1206 | struct btrfs_qgroup_operation *oper2) | ||
| 1207 | { | ||
| 1208 | /* | ||
| 1209 | * Ignore seq and type here, we're looking for any operation | ||
| 1210 | * at all related to this extent on that root. | ||
| 1211 | */ | ||
| 1212 | if (oper1->bytenr < oper2->bytenr) | ||
| 1213 | return -1; | ||
| 1214 | if (oper1->bytenr > oper2->bytenr) | ||
| 1215 | return 1; | ||
| 1216 | if (oper1->ref_root < oper2->ref_root) | ||
| 1217 | return -1; | ||
| 1218 | if (oper1->ref_root > oper2->ref_root) | ||
| 1219 | return 1; | ||
| 1220 | return 0; | ||
| 1221 | } | ||
| 1222 | |||
| 1223 | static int qgroup_oper_exists(struct btrfs_fs_info *fs_info, | ||
| 1224 | struct btrfs_qgroup_operation *oper) | ||
| 1225 | { | ||
| 1226 | struct rb_node *n; | ||
| 1227 | struct btrfs_qgroup_operation *cur; | ||
| 1228 | int cmp; | ||
| 1229 | |||
| 1230 | spin_lock(&fs_info->qgroup_op_lock); | ||
| 1231 | n = fs_info->qgroup_op_tree.rb_node; | ||
| 1232 | while (n) { | ||
| 1233 | cur = rb_entry(n, struct btrfs_qgroup_operation, n); | ||
| 1234 | cmp = comp_oper_exist(cur, oper); | ||
| 1235 | if (cmp < 0) { | ||
| 1236 | n = n->rb_right; | ||
| 1237 | } else if (cmp) { | ||
| 1238 | n = n->rb_left; | ||
| 1239 | } else { | ||
| 1240 | spin_unlock(&fs_info->qgroup_op_lock); | ||
| 1241 | return -EEXIST; | ||
| 1242 | } | ||
| 1243 | } | ||
| 1244 | spin_unlock(&fs_info->qgroup_op_lock); | ||
| 1245 | return 0; | ||
| 1246 | } | ||
| 1247 | |||
| 1204 | static int comp_oper(struct btrfs_qgroup_operation *oper1, | 1248 | static int comp_oper(struct btrfs_qgroup_operation *oper1, |
| 1205 | struct btrfs_qgroup_operation *oper2) | 1249 | struct btrfs_qgroup_operation *oper2) |
| 1206 | { | 1250 | { |
| @@ -1290,6 +1334,23 @@ int btrfs_qgroup_record_ref(struct btrfs_trans_handle *trans, | |||
| 1290 | oper->seq = atomic_inc_return(&fs_info->qgroup_op_seq); | 1334 | oper->seq = atomic_inc_return(&fs_info->qgroup_op_seq); |
| 1291 | INIT_LIST_HEAD(&oper->elem.list); | 1335 | INIT_LIST_HEAD(&oper->elem.list); |
| 1292 | oper->elem.seq = 0; | 1336 | oper->elem.seq = 0; |
| 1337 | |||
| 1338 | if (type == BTRFS_QGROUP_OPER_SUB_SUBTREE) { | ||
| 1339 | /* | ||
| 1340 | * If any operation for this bytenr/ref_root combo | ||
| 1341 | * exists, then we know it's not exclusively owned and | ||
| 1342 | * shouldn't be queued up. | ||
| 1343 | * | ||
| 1344 | * This also catches the case where we have a cloned | ||
| 1345 | * extent that gets queued up multiple times during | ||
| 1346 | * drop snapshot. | ||
| 1347 | */ | ||
| 1348 | if (qgroup_oper_exists(fs_info, oper)) { | ||
| 1349 | kfree(oper); | ||
| 1350 | return 0; | ||
| 1351 | } | ||
| 1352 | } | ||
| 1353 | |||
| 1293 | ret = insert_qgroup_oper(fs_info, oper); | 1354 | ret = insert_qgroup_oper(fs_info, oper); |
| 1294 | if (ret) { | 1355 | if (ret) { |
| 1295 | /* Shouldn't happen so have an assert for developers */ | 1356 | /* Shouldn't happen so have an assert for developers */ |
| @@ -1884,6 +1945,111 @@ out: | |||
| 1884 | } | 1945 | } |
| 1885 | 1946 | ||
| 1886 | /* | 1947 | /* |
| 1948 | * Process a reference to a shared subtree. This type of operation is | ||
| 1949 | * queued during snapshot removal when we encounter extents which are | ||
| 1950 | * shared between more than one root. | ||
| 1951 | */ | ||
| 1952 | static int qgroup_subtree_accounting(struct btrfs_trans_handle *trans, | ||
| 1953 | struct btrfs_fs_info *fs_info, | ||
| 1954 | struct btrfs_qgroup_operation *oper) | ||
| 1955 | { | ||
| 1956 | struct ulist *roots = NULL; | ||
| 1957 | struct ulist_node *unode; | ||
| 1958 | struct ulist_iterator uiter; | ||
| 1959 | struct btrfs_qgroup_list *glist; | ||
| 1960 | struct ulist *parents; | ||
| 1961 | int ret = 0; | ||
| 1962 | int err; | ||
| 1963 | struct btrfs_qgroup *qg; | ||
| 1964 | u64 root_obj = 0; | ||
| 1965 | struct seq_list elem = {}; | ||
| 1966 | |||
| 1967 | parents = ulist_alloc(GFP_NOFS); | ||
| 1968 | if (!parents) | ||
| 1969 | return -ENOMEM; | ||
| 1970 | |||
| 1971 | btrfs_get_tree_mod_seq(fs_info, &elem); | ||
| 1972 | ret = btrfs_find_all_roots(trans, fs_info, oper->bytenr, | ||
| 1973 | elem.seq, &roots); | ||
| 1974 | btrfs_put_tree_mod_seq(fs_info, &elem); | ||
| 1975 | if (ret < 0) | ||
| 1976 | return ret; | ||
| 1977 | |||
| 1978 | if (roots->nnodes != 1) | ||
| 1979 | goto out; | ||
| 1980 | |||
| 1981 | ULIST_ITER_INIT(&uiter); | ||
| 1982 | unode = ulist_next(roots, &uiter); /* Only want 1 so no need to loop */ | ||
| 1983 | /* | ||
| 1984 | * If we find our ref root then that means all refs | ||
| 1985 | * this extent has to the root have not yet been | ||
| 1986 | * deleted. In that case, we do nothing and let the | ||
| 1987 | * last ref for this bytenr drive our update. | ||
| 1988 | * | ||
| 1989 | * This can happen for example if an extent is | ||
| 1990 | * referenced multiple times in a snapshot (clone, | ||
| 1991 | * etc). If we are in the middle of snapshot removal, | ||
| 1992 | * queued updates for such an extent will find the | ||
| 1993 | * root if we have not yet finished removing the | ||
| 1994 | * snapshot. | ||
| 1995 | */ | ||
| 1996 | if (unode->val == oper->ref_root) | ||
| 1997 | goto out; | ||
| 1998 | |||
| 1999 | root_obj = unode->val; | ||
| 2000 | BUG_ON(!root_obj); | ||
| 2001 | |||
| 2002 | spin_lock(&fs_info->qgroup_lock); | ||
| 2003 | qg = find_qgroup_rb(fs_info, root_obj); | ||
| 2004 | if (!qg) | ||
| 2005 | goto out_unlock; | ||
| 2006 | |||
| 2007 | qg->excl += oper->num_bytes; | ||
| 2008 | qg->excl_cmpr += oper->num_bytes; | ||
| 2009 | qgroup_dirty(fs_info, qg); | ||
| 2010 | |||
| 2011 | /* | ||
| 2012 | * Adjust counts for parent groups. First we find all | ||
| 2013 | * parents, then in the 2nd loop we do the adjustment | ||
| 2014 | * while adding parents of the parents to our ulist. | ||
| 2015 | */ | ||
| 2016 | list_for_each_entry(glist, &qg->groups, next_group) { | ||
| 2017 | err = ulist_add(parents, glist->group->qgroupid, | ||
| 2018 | ptr_to_u64(glist->group), GFP_ATOMIC); | ||
| 2019 | if (err < 0) { | ||
| 2020 | ret = err; | ||
| 2021 | goto out_unlock; | ||
| 2022 | } | ||
| 2023 | } | ||
| 2024 | |||
| 2025 | ULIST_ITER_INIT(&uiter); | ||
| 2026 | while ((unode = ulist_next(parents, &uiter))) { | ||
| 2027 | qg = u64_to_ptr(unode->aux); | ||
| 2028 | qg->excl += oper->num_bytes; | ||
| 2029 | qg->excl_cmpr += oper->num_bytes; | ||
| 2030 | qgroup_dirty(fs_info, qg); | ||
| 2031 | |||
| 2032 | /* Add any parents of the parents */ | ||
| 2033 | list_for_each_entry(glist, &qg->groups, next_group) { | ||
| 2034 | err = ulist_add(parents, glist->group->qgroupid, | ||
| 2035 | ptr_to_u64(glist->group), GFP_ATOMIC); | ||
| 2036 | if (err < 0) { | ||
| 2037 | ret = err; | ||
| 2038 | goto out_unlock; | ||
| 2039 | } | ||
| 2040 | } | ||
| 2041 | } | ||
| 2042 | |||
| 2043 | out_unlock: | ||
| 2044 | spin_unlock(&fs_info->qgroup_lock); | ||
| 2045 | |||
| 2046 | out: | ||
| 2047 | ulist_free(roots); | ||
| 2048 | ulist_free(parents); | ||
| 2049 | return ret; | ||
| 2050 | } | ||
| 2051 | |||
| 2052 | /* | ||
| 1887 | * btrfs_qgroup_account_ref is called for every ref that is added to or deleted | 2053 | * btrfs_qgroup_account_ref is called for every ref that is added to or deleted |
| 1888 | * from the fs. First, all roots referencing the extent are searched, and | 2054 | * from the fs. First, all roots referencing the extent are searched, and |
| 1889 | * then the space is accounted accordingly to the different roots. The | 2055 | * then the space is accounted accordingly to the different roots. The |
| @@ -1920,6 +2086,9 @@ static int btrfs_qgroup_account(struct btrfs_trans_handle *trans, | |||
| 1920 | case BTRFS_QGROUP_OPER_SUB_SHARED: | 2086 | case BTRFS_QGROUP_OPER_SUB_SHARED: |
| 1921 | ret = qgroup_shared_accounting(trans, fs_info, oper); | 2087 | ret = qgroup_shared_accounting(trans, fs_info, oper); |
| 1922 | break; | 2088 | break; |
| 2089 | case BTRFS_QGROUP_OPER_SUB_SUBTREE: | ||
| 2090 | ret = qgroup_subtree_accounting(trans, fs_info, oper); | ||
| 2091 | break; | ||
| 1923 | default: | 2092 | default: |
| 1924 | ASSERT(0); | 2093 | ASSERT(0); |
| 1925 | } | 2094 | } |
diff --git a/fs/btrfs/qgroup.h b/fs/btrfs/qgroup.h index 5952ff1fbd7a..18cc68ca3090 100644 --- a/fs/btrfs/qgroup.h +++ b/fs/btrfs/qgroup.h | |||
| @@ -44,6 +44,7 @@ enum btrfs_qgroup_operation_type { | |||
| 44 | BTRFS_QGROUP_OPER_ADD_SHARED, | 44 | BTRFS_QGROUP_OPER_ADD_SHARED, |
| 45 | BTRFS_QGROUP_OPER_SUB_EXCL, | 45 | BTRFS_QGROUP_OPER_SUB_EXCL, |
| 46 | BTRFS_QGROUP_OPER_SUB_SHARED, | 46 | BTRFS_QGROUP_OPER_SUB_SHARED, |
| 47 | BTRFS_QGROUP_OPER_SUB_SUBTREE, | ||
| 47 | }; | 48 | }; |
| 48 | 49 | ||
| 49 | struct btrfs_qgroup_operation { | 50 | struct btrfs_qgroup_operation { |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 67b48b9a03e0..c4124de4435b 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
| @@ -1665,6 +1665,21 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes) | |||
| 1665 | return 0; | 1665 | return 0; |
| 1666 | } | 1666 | } |
| 1667 | 1667 | ||
| 1668 | /* | ||
| 1669 | * Calculate numbers for 'df', pessimistic in case of mixed raid profiles. | ||
| 1670 | * | ||
| 1671 | * If there's a redundant raid level at DATA block groups, use the respective | ||
| 1672 | * multiplier to scale the sizes. | ||
| 1673 | * | ||
| 1674 | * Unused device space usage is based on simulating the chunk allocator | ||
| 1675 | * algorithm that respects the device sizes, order of allocations and the | ||
| 1676 | * 'alloc_start' value, this is a close approximation of the actual use but | ||
| 1677 | * there are other factors that may change the result (like a new metadata | ||
| 1678 | * chunk). | ||
| 1679 | * | ||
| 1680 | * FIXME: not accurate for mixed block groups, total and free/used are ok, | ||
| 1681 | * available appears slightly larger. | ||
| 1682 | */ | ||
| 1668 | static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) | 1683 | static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
| 1669 | { | 1684 | { |
| 1670 | struct btrfs_fs_info *fs_info = btrfs_sb(dentry->d_sb); | 1685 | struct btrfs_fs_info *fs_info = btrfs_sb(dentry->d_sb); |
| @@ -1675,6 +1690,8 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
| 1675 | u64 total_free_data = 0; | 1690 | u64 total_free_data = 0; |
| 1676 | int bits = dentry->d_sb->s_blocksize_bits; | 1691 | int bits = dentry->d_sb->s_blocksize_bits; |
| 1677 | __be32 *fsid = (__be32 *)fs_info->fsid; | 1692 | __be32 *fsid = (__be32 *)fs_info->fsid; |
| 1693 | unsigned factor = 1; | ||
| 1694 | struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; | ||
| 1678 | int ret; | 1695 | int ret; |
| 1679 | 1696 | ||
| 1680 | /* holding chunk_muext to avoid allocating new chunks */ | 1697 | /* holding chunk_muext to avoid allocating new chunks */ |
| @@ -1682,30 +1699,52 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
| 1682 | rcu_read_lock(); | 1699 | rcu_read_lock(); |
| 1683 | list_for_each_entry_rcu(found, head, list) { | 1700 | list_for_each_entry_rcu(found, head, list) { |
| 1684 | if (found->flags & BTRFS_BLOCK_GROUP_DATA) { | 1701 | if (found->flags & BTRFS_BLOCK_GROUP_DATA) { |
| 1702 | int i; | ||
| 1703 | |||
| 1685 | total_free_data += found->disk_total - found->disk_used; | 1704 | total_free_data += found->disk_total - found->disk_used; |
| 1686 | total_free_data -= | 1705 | total_free_data -= |
| 1687 | btrfs_account_ro_block_groups_free_space(found); | 1706 | btrfs_account_ro_block_groups_free_space(found); |
| 1707 | |||
| 1708 | for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) { | ||
| 1709 | if (!list_empty(&found->block_groups[i])) { | ||
| 1710 | switch (i) { | ||
| 1711 | case BTRFS_RAID_DUP: | ||
| 1712 | case BTRFS_RAID_RAID1: | ||
| 1713 | case BTRFS_RAID_RAID10: | ||
| 1714 | factor = 2; | ||
| 1715 | } | ||
| 1716 | } | ||
| 1717 | } | ||
| 1688 | } | 1718 | } |
| 1689 | 1719 | ||
| 1690 | total_used += found->disk_used; | 1720 | total_used += found->disk_used; |
| 1691 | } | 1721 | } |
| 1722 | |||
| 1692 | rcu_read_unlock(); | 1723 | rcu_read_unlock(); |
| 1693 | 1724 | ||
| 1694 | buf->f_namelen = BTRFS_NAME_LEN; | 1725 | buf->f_blocks = div_u64(btrfs_super_total_bytes(disk_super), factor); |
| 1695 | buf->f_blocks = btrfs_super_total_bytes(disk_super) >> bits; | 1726 | buf->f_blocks >>= bits; |
| 1696 | buf->f_bfree = buf->f_blocks - (total_used >> bits); | 1727 | buf->f_bfree = buf->f_blocks - (div_u64(total_used, factor) >> bits); |
| 1697 | buf->f_bsize = dentry->d_sb->s_blocksize; | 1728 | |
| 1698 | buf->f_type = BTRFS_SUPER_MAGIC; | 1729 | /* Account global block reserve as used, it's in logical size already */ |
| 1730 | spin_lock(&block_rsv->lock); | ||
| 1731 | buf->f_bfree -= block_rsv->size >> bits; | ||
| 1732 | spin_unlock(&block_rsv->lock); | ||
| 1733 | |||
| 1699 | buf->f_bavail = total_free_data; | 1734 | buf->f_bavail = total_free_data; |
| 1700 | ret = btrfs_calc_avail_data_space(fs_info->tree_root, &total_free_data); | 1735 | ret = btrfs_calc_avail_data_space(fs_info->tree_root, &total_free_data); |
| 1701 | if (ret) { | 1736 | if (ret) { |
| 1702 | mutex_unlock(&fs_info->chunk_mutex); | 1737 | mutex_unlock(&fs_info->chunk_mutex); |
| 1703 | return ret; | 1738 | return ret; |
| 1704 | } | 1739 | } |
| 1705 | buf->f_bavail += total_free_data; | 1740 | buf->f_bavail += div_u64(total_free_data, factor); |
| 1706 | buf->f_bavail = buf->f_bavail >> bits; | 1741 | buf->f_bavail = buf->f_bavail >> bits; |
| 1707 | mutex_unlock(&fs_info->chunk_mutex); | 1742 | mutex_unlock(&fs_info->chunk_mutex); |
| 1708 | 1743 | ||
| 1744 | buf->f_type = BTRFS_SUPER_MAGIC; | ||
| 1745 | buf->f_bsize = dentry->d_sb->s_blocksize; | ||
| 1746 | buf->f_namelen = BTRFS_NAME_LEN; | ||
| 1747 | |||
| 1709 | /* We treat it as constant endianness (it doesn't matter _which_) | 1748 | /* We treat it as constant endianness (it doesn't matter _which_) |
| 1710 | because we want the fsid to come out the same whether mounted | 1749 | because we want the fsid to come out the same whether mounted |
| 1711 | on a big-endian or little-endian host */ | 1750 | on a big-endian or little-endian host */ |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 5f379affdf23..d89c6d3542ca 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
| @@ -218,7 +218,6 @@ loop: | |||
| 218 | spin_lock_init(&cur_trans->delayed_refs.lock); | 218 | spin_lock_init(&cur_trans->delayed_refs.lock); |
| 219 | 219 | ||
| 220 | INIT_LIST_HEAD(&cur_trans->pending_snapshots); | 220 | INIT_LIST_HEAD(&cur_trans->pending_snapshots); |
| 221 | INIT_LIST_HEAD(&cur_trans->ordered_operations); | ||
| 222 | INIT_LIST_HEAD(&cur_trans->pending_chunks); | 221 | INIT_LIST_HEAD(&cur_trans->pending_chunks); |
| 223 | INIT_LIST_HEAD(&cur_trans->switch_commits); | 222 | INIT_LIST_HEAD(&cur_trans->switch_commits); |
| 224 | list_add_tail(&cur_trans->list, &fs_info->trans_list); | 223 | list_add_tail(&cur_trans->list, &fs_info->trans_list); |
| @@ -1612,27 +1611,6 @@ static void cleanup_transaction(struct btrfs_trans_handle *trans, | |||
| 1612 | kmem_cache_free(btrfs_trans_handle_cachep, trans); | 1611 | kmem_cache_free(btrfs_trans_handle_cachep, trans); |
| 1613 | } | 1612 | } |
| 1614 | 1613 | ||
| 1615 | static int btrfs_flush_all_pending_stuffs(struct btrfs_trans_handle *trans, | ||
| 1616 | struct btrfs_root *root) | ||
| 1617 | { | ||
| 1618 | int ret; | ||
| 1619 | |||
| 1620 | ret = btrfs_run_delayed_items(trans, root); | ||
| 1621 | if (ret) | ||
| 1622 | return ret; | ||
| 1623 | |||
| 1624 | /* | ||
| 1625 | * rename don't use btrfs_join_transaction, so, once we | ||
| 1626 | * set the transaction to blocked above, we aren't going | ||
| 1627 | * to get any new ordered operations. We can safely run | ||
| 1628 | * it here and no for sure that nothing new will be added | ||
| 1629 | * to the list | ||
| 1630 | */ | ||
| 1631 | ret = btrfs_run_ordered_operations(trans, root, 1); | ||
| 1632 | |||
| 1633 | return ret; | ||
| 1634 | } | ||
| 1635 | |||
| 1636 | static inline int btrfs_start_delalloc_flush(struct btrfs_fs_info *fs_info) | 1614 | static inline int btrfs_start_delalloc_flush(struct btrfs_fs_info *fs_info) |
| 1637 | { | 1615 | { |
| 1638 | if (btrfs_test_opt(fs_info->tree_root, FLUSHONCOMMIT)) | 1616 | if (btrfs_test_opt(fs_info->tree_root, FLUSHONCOMMIT)) |
| @@ -1653,13 +1631,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 1653 | struct btrfs_transaction *prev_trans = NULL; | 1631 | struct btrfs_transaction *prev_trans = NULL; |
| 1654 | int ret; | 1632 | int ret; |
| 1655 | 1633 | ||
| 1656 | ret = btrfs_run_ordered_operations(trans, root, 0); | ||
| 1657 | if (ret) { | ||
| 1658 | btrfs_abort_transaction(trans, root, ret); | ||
| 1659 | btrfs_end_transaction(trans, root); | ||
| 1660 | return ret; | ||
| 1661 | } | ||
| 1662 | |||
| 1663 | /* Stop the commit early if ->aborted is set */ | 1634 | /* Stop the commit early if ->aborted is set */ |
| 1664 | if (unlikely(ACCESS_ONCE(cur_trans->aborted))) { | 1635 | if (unlikely(ACCESS_ONCE(cur_trans->aborted))) { |
| 1665 | ret = cur_trans->aborted; | 1636 | ret = cur_trans->aborted; |
| @@ -1740,7 +1711,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 1740 | if (ret) | 1711 | if (ret) |
| 1741 | goto cleanup_transaction; | 1712 | goto cleanup_transaction; |
| 1742 | 1713 | ||
| 1743 | ret = btrfs_flush_all_pending_stuffs(trans, root); | 1714 | ret = btrfs_run_delayed_items(trans, root); |
| 1744 | if (ret) | 1715 | if (ret) |
| 1745 | goto cleanup_transaction; | 1716 | goto cleanup_transaction; |
| 1746 | 1717 | ||
| @@ -1748,7 +1719,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 1748 | extwriter_counter_read(cur_trans) == 0); | 1719 | extwriter_counter_read(cur_trans) == 0); |
| 1749 | 1720 | ||
| 1750 | /* some pending stuffs might be added after the previous flush. */ | 1721 | /* some pending stuffs might be added after the previous flush. */ |
| 1751 | ret = btrfs_flush_all_pending_stuffs(trans, root); | 1722 | ret = btrfs_run_delayed_items(trans, root); |
| 1752 | if (ret) | 1723 | if (ret) |
| 1753 | goto cleanup_transaction; | 1724 | goto cleanup_transaction; |
| 1754 | 1725 | ||
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h index 7dd558ed0716..579be51b27e5 100644 --- a/fs/btrfs/transaction.h +++ b/fs/btrfs/transaction.h | |||
| @@ -55,7 +55,6 @@ struct btrfs_transaction { | |||
| 55 | wait_queue_head_t writer_wait; | 55 | wait_queue_head_t writer_wait; |
| 56 | wait_queue_head_t commit_wait; | 56 | wait_queue_head_t commit_wait; |
| 57 | struct list_head pending_snapshots; | 57 | struct list_head pending_snapshots; |
| 58 | struct list_head ordered_operations; | ||
| 59 | struct list_head pending_chunks; | 58 | struct list_head pending_chunks; |
| 60 | struct list_head switch_commits; | 59 | struct list_head switch_commits; |
| 61 | struct btrfs_delayed_ref_root delayed_refs; | 60 | struct btrfs_delayed_ref_root delayed_refs; |
diff --git a/fs/btrfs/ulist.h b/fs/btrfs/ulist.h index 7f78cbf5cf41..4c29db604bbe 100644 --- a/fs/btrfs/ulist.h +++ b/fs/btrfs/ulist.h | |||
| @@ -57,6 +57,21 @@ void ulist_free(struct ulist *ulist); | |||
| 57 | int ulist_add(struct ulist *ulist, u64 val, u64 aux, gfp_t gfp_mask); | 57 | int ulist_add(struct ulist *ulist, u64 val, u64 aux, gfp_t gfp_mask); |
| 58 | int ulist_add_merge(struct ulist *ulist, u64 val, u64 aux, | 58 | int ulist_add_merge(struct ulist *ulist, u64 val, u64 aux, |
| 59 | u64 *old_aux, gfp_t gfp_mask); | 59 | u64 *old_aux, gfp_t gfp_mask); |
| 60 | |||
| 61 | /* just like ulist_add_merge() but take a pointer for the aux data */ | ||
| 62 | static inline int ulist_add_merge_ptr(struct ulist *ulist, u64 val, void *aux, | ||
| 63 | void **old_aux, gfp_t gfp_mask) | ||
| 64 | { | ||
| 65 | #if BITS_PER_LONG == 32 | ||
| 66 | u64 old64 = (uintptr_t)*old_aux; | ||
| 67 | int ret = ulist_add_merge(ulist, val, (uintptr_t)aux, &old64, gfp_mask); | ||
| 68 | *old_aux = (void *)((uintptr_t)old64); | ||
| 69 | return ret; | ||
| 70 | #else | ||
| 71 | return ulist_add_merge(ulist, val, (u64)aux, (u64 *)old_aux, gfp_mask); | ||
| 72 | #endif | ||
| 73 | } | ||
| 74 | |||
| 60 | struct ulist_node *ulist_next(struct ulist *ulist, | 75 | struct ulist_node *ulist_next(struct ulist *ulist, |
| 61 | struct ulist_iterator *uiter); | 76 | struct ulist_iterator *uiter); |
| 62 | 77 | ||
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index ac4f260155c8..889b98455750 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
| @@ -207,6 +207,19 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
| 207 | return 0; | 207 | return 0; |
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | static long cifs_fallocate(struct file *file, int mode, loff_t off, loff_t len) | ||
| 211 | { | ||
| 212 | struct super_block *sb = file->f_path.dentry->d_sb; | ||
| 213 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | ||
| 214 | struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); | ||
| 215 | struct TCP_Server_Info *server = tcon->ses->server; | ||
| 216 | |||
| 217 | if (server->ops->fallocate) | ||
| 218 | return server->ops->fallocate(file, tcon, mode, off, len); | ||
| 219 | |||
| 220 | return -EOPNOTSUPP; | ||
| 221 | } | ||
| 222 | |||
| 210 | static int cifs_permission(struct inode *inode, int mask) | 223 | static int cifs_permission(struct inode *inode, int mask) |
| 211 | { | 224 | { |
| 212 | struct cifs_sb_info *cifs_sb; | 225 | struct cifs_sb_info *cifs_sb; |
| @@ -812,8 +825,9 @@ static int cifs_setlease(struct file *file, long arg, struct file_lock **lease) | |||
| 812 | if (!(S_ISREG(inode->i_mode))) | 825 | if (!(S_ISREG(inode->i_mode))) |
| 813 | return -EINVAL; | 826 | return -EINVAL; |
| 814 | 827 | ||
| 815 | /* check if file is oplocked */ | 828 | /* Check if file is oplocked if this is request for new lease */ |
| 816 | if (((arg == F_RDLCK) && CIFS_CACHE_READ(CIFS_I(inode))) || | 829 | if (arg == F_UNLCK || |
| 830 | ((arg == F_RDLCK) && CIFS_CACHE_READ(CIFS_I(inode))) || | ||
| 817 | ((arg == F_WRLCK) && CIFS_CACHE_WRITE(CIFS_I(inode)))) | 831 | ((arg == F_WRLCK) && CIFS_CACHE_WRITE(CIFS_I(inode)))) |
| 818 | return generic_setlease(file, arg, lease); | 832 | return generic_setlease(file, arg, lease); |
| 819 | else if (tlink_tcon(cfile->tlink)->local_lease && | 833 | else if (tlink_tcon(cfile->tlink)->local_lease && |
| @@ -908,6 +922,7 @@ const struct file_operations cifs_file_ops = { | |||
| 908 | .unlocked_ioctl = cifs_ioctl, | 922 | .unlocked_ioctl = cifs_ioctl, |
| 909 | #endif /* CONFIG_CIFS_POSIX */ | 923 | #endif /* CONFIG_CIFS_POSIX */ |
| 910 | .setlease = cifs_setlease, | 924 | .setlease = cifs_setlease, |
| 925 | .fallocate = cifs_fallocate, | ||
| 911 | }; | 926 | }; |
| 912 | 927 | ||
| 913 | const struct file_operations cifs_file_strict_ops = { | 928 | const struct file_operations cifs_file_strict_ops = { |
| @@ -927,6 +942,7 @@ const struct file_operations cifs_file_strict_ops = { | |||
| 927 | .unlocked_ioctl = cifs_ioctl, | 942 | .unlocked_ioctl = cifs_ioctl, |
| 928 | #endif /* CONFIG_CIFS_POSIX */ | 943 | #endif /* CONFIG_CIFS_POSIX */ |
| 929 | .setlease = cifs_setlease, | 944 | .setlease = cifs_setlease, |
| 945 | .fallocate = cifs_fallocate, | ||
| 930 | }; | 946 | }; |
| 931 | 947 | ||
| 932 | const struct file_operations cifs_file_direct_ops = { | 948 | const struct file_operations cifs_file_direct_ops = { |
| @@ -947,6 +963,7 @@ const struct file_operations cifs_file_direct_ops = { | |||
| 947 | #endif /* CONFIG_CIFS_POSIX */ | 963 | #endif /* CONFIG_CIFS_POSIX */ |
| 948 | .llseek = cifs_llseek, | 964 | .llseek = cifs_llseek, |
| 949 | .setlease = cifs_setlease, | 965 | .setlease = cifs_setlease, |
| 966 | .fallocate = cifs_fallocate, | ||
| 950 | }; | 967 | }; |
| 951 | 968 | ||
| 952 | const struct file_operations cifs_file_nobrl_ops = { | 969 | const struct file_operations cifs_file_nobrl_ops = { |
| @@ -965,6 +982,7 @@ const struct file_operations cifs_file_nobrl_ops = { | |||
| 965 | .unlocked_ioctl = cifs_ioctl, | 982 | .unlocked_ioctl = cifs_ioctl, |
| 966 | #endif /* CONFIG_CIFS_POSIX */ | 983 | #endif /* CONFIG_CIFS_POSIX */ |
| 967 | .setlease = cifs_setlease, | 984 | .setlease = cifs_setlease, |
| 985 | .fallocate = cifs_fallocate, | ||
| 968 | }; | 986 | }; |
| 969 | 987 | ||
| 970 | const struct file_operations cifs_file_strict_nobrl_ops = { | 988 | const struct file_operations cifs_file_strict_nobrl_ops = { |
| @@ -983,6 +1001,7 @@ const struct file_operations cifs_file_strict_nobrl_ops = { | |||
| 983 | .unlocked_ioctl = cifs_ioctl, | 1001 | .unlocked_ioctl = cifs_ioctl, |
| 984 | #endif /* CONFIG_CIFS_POSIX */ | 1002 | #endif /* CONFIG_CIFS_POSIX */ |
| 985 | .setlease = cifs_setlease, | 1003 | .setlease = cifs_setlease, |
| 1004 | .fallocate = cifs_fallocate, | ||
| 986 | }; | 1005 | }; |
| 987 | 1006 | ||
| 988 | const struct file_operations cifs_file_direct_nobrl_ops = { | 1007 | const struct file_operations cifs_file_direct_nobrl_ops = { |
| @@ -1002,6 +1021,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = { | |||
| 1002 | #endif /* CONFIG_CIFS_POSIX */ | 1021 | #endif /* CONFIG_CIFS_POSIX */ |
| 1003 | .llseek = cifs_llseek, | 1022 | .llseek = cifs_llseek, |
| 1004 | .setlease = cifs_setlease, | 1023 | .setlease = cifs_setlease, |
| 1024 | .fallocate = cifs_fallocate, | ||
| 1005 | }; | 1025 | }; |
| 1006 | 1026 | ||
| 1007 | const struct file_operations cifs_dir_ops = { | 1027 | const struct file_operations cifs_dir_ops = { |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 0012e1e291d4..dfc731b02aa9 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
| @@ -409,6 +409,10 @@ struct smb_version_operations { | |||
| 409 | /* get mtu credits */ | 409 | /* get mtu credits */ |
| 410 | int (*wait_mtu_credits)(struct TCP_Server_Info *, unsigned int, | 410 | int (*wait_mtu_credits)(struct TCP_Server_Info *, unsigned int, |
| 411 | unsigned int *, unsigned int *); | 411 | unsigned int *, unsigned int *); |
| 412 | /* check if we need to issue closedir */ | ||
| 413 | bool (*dir_needs_close)(struct cifsFileInfo *); | ||
| 414 | long (*fallocate)(struct file *, struct cifs_tcon *, int, loff_t, | ||
| 415 | loff_t); | ||
| 412 | }; | 416 | }; |
| 413 | 417 | ||
| 414 | struct smb_version_values { | 418 | struct smb_version_values { |
| @@ -883,6 +887,7 @@ struct cifs_tcon { | |||
| 883 | for this mount even if server would support */ | 887 | for this mount even if server would support */ |
| 884 | bool local_lease:1; /* check leases (only) on local system not remote */ | 888 | bool local_lease:1; /* check leases (only) on local system not remote */ |
| 885 | bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */ | 889 | bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */ |
| 890 | bool broken_sparse_sup; /* if server or share does not support sparse */ | ||
| 886 | bool need_reconnect:1; /* connection reset, tid now invalid */ | 891 | bool need_reconnect:1; /* connection reset, tid now invalid */ |
| 887 | #ifdef CONFIG_CIFS_SMB2 | 892 | #ifdef CONFIG_CIFS_SMB2 |
| 888 | bool print:1; /* set if connection to printer share */ | 893 | bool print:1; /* set if connection to printer share */ |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 33df36ef9d52..5f9822ac0245 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
| @@ -2253,6 +2253,29 @@ typedef struct { | |||
| 2253 | /* minimum includes first three fields, and empty FS Name */ | 2253 | /* minimum includes first three fields, and empty FS Name */ |
| 2254 | #define MIN_FS_ATTR_INFO_SIZE 12 | 2254 | #define MIN_FS_ATTR_INFO_SIZE 12 |
| 2255 | 2255 | ||
| 2256 | |||
| 2257 | /* List of FileSystemAttributes - see 2.5.1 of MS-FSCC */ | ||
| 2258 | #define FILE_SUPPORT_INTEGRITY_STREAMS 0x04000000 | ||
| 2259 | #define FILE_SUPPORTS_USN_JOURNAL 0x02000000 | ||
| 2260 | #define FILE_SUPPORTS_OPEN_BY_FILE_ID 0x01000000 | ||
| 2261 | #define FILE_SUPPORTS_EXTENDED_ATTRIBUTES 0x00800000 | ||
| 2262 | #define FILE_SUPPORTS_HARD_LINKS 0x00400000 | ||
| 2263 | #define FILE_SUPPORTS_TRANSACTIONS 0x00200000 | ||
| 2264 | #define FILE_SEQUENTIAL_WRITE_ONCE 0x00100000 | ||
| 2265 | #define FILE_READ_ONLY_VOLUME 0x00080000 | ||
| 2266 | #define FILE_NAMED_STREAMS 0x00040000 | ||
| 2267 | #define FILE_SUPPORTS_ENCRYPTION 0x00020000 | ||
| 2268 | #define FILE_SUPPORTS_OBJECT_IDS 0x00010000 | ||
| 2269 | #define FILE_VOLUME_IS_COMPRESSED 0x00008000 | ||
| 2270 | #define FILE_SUPPORTS_REMOTE_STORAGE 0x00000100 | ||
| 2271 | #define FILE_SUPPORTS_REPARSE_POINTS 0x00000080 | ||
| 2272 | #define FILE_SUPPORTS_SPARSE_FILES 0x00000040 | ||
| 2273 | #define FILE_VOLUME_QUOTAS 0x00000020 | ||
| 2274 | #define FILE_FILE_COMPRESSION 0x00000010 | ||
| 2275 | #define FILE_PERSISTENT_ACLS 0x00000008 | ||
| 2276 | #define FILE_UNICODE_ON_DISK 0x00000004 | ||
| 2277 | #define FILE_CASE_PRESERVED_NAMES 0x00000002 | ||
| 2278 | #define FILE_CASE_SENSITIVE_SEARCH 0x00000001 | ||
| 2256 | typedef struct { | 2279 | typedef struct { |
| 2257 | __le32 Attributes; | 2280 | __le32 Attributes; |
| 2258 | __le32 MaxPathNameComponentLength; | 2281 | __le32 MaxPathNameComponentLength; |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 4ab2f79ffa7a..d5fec92e0360 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -762,7 +762,7 @@ int cifs_closedir(struct inode *inode, struct file *file) | |||
| 762 | 762 | ||
| 763 | cifs_dbg(FYI, "Freeing private data in close dir\n"); | 763 | cifs_dbg(FYI, "Freeing private data in close dir\n"); |
| 764 | spin_lock(&cifs_file_list_lock); | 764 | spin_lock(&cifs_file_list_lock); |
| 765 | if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) { | 765 | if (server->ops->dir_needs_close(cfile)) { |
| 766 | cfile->invalidHandle = true; | 766 | cfile->invalidHandle = true; |
| 767 | spin_unlock(&cifs_file_list_lock); | 767 | spin_unlock(&cifs_file_list_lock); |
| 768 | if (server->ops->close_dir) | 768 | if (server->ops->close_dir) |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 426d6c6ad8bf..949ec909ec9a 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
| @@ -1727,6 +1727,12 @@ unlink_target: | |||
| 1727 | target_dentry, to_name); | 1727 | target_dentry, to_name); |
| 1728 | } | 1728 | } |
| 1729 | 1729 | ||
| 1730 | /* force revalidate to go get info when needed */ | ||
| 1731 | CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0; | ||
| 1732 | |||
| 1733 | source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime = | ||
| 1734 | target_dir->i_mtime = current_fs_time(source_dir->i_sb); | ||
| 1735 | |||
| 1730 | cifs_rename_exit: | 1736 | cifs_rename_exit: |
| 1731 | kfree(info_buf_source); | 1737 | kfree(info_buf_source); |
| 1732 | kfree(from_name); | 1738 | kfree(from_name); |
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 81340c6253eb..b7415d596dbd 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
| @@ -574,13 +574,6 @@ void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock) | |||
| 574 | cinode->oplock = 0; | 574 | cinode->oplock = 0; |
| 575 | } | 575 | } |
| 576 | 576 | ||
| 577 | static int | ||
| 578 | cifs_oplock_break_wait(void *unused) | ||
| 579 | { | ||
| 580 | schedule(); | ||
| 581 | return signal_pending(current) ? -ERESTARTSYS : 0; | ||
| 582 | } | ||
| 583 | |||
| 584 | /* | 577 | /* |
| 585 | * We wait for oplock breaks to be processed before we attempt to perform | 578 | * We wait for oplock breaks to be processed before we attempt to perform |
| 586 | * writes. | 579 | * writes. |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index b15862e0f68c..798c80a41c88 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
| @@ -593,7 +593,7 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos, | |||
| 593 | /* close and restart search */ | 593 | /* close and restart search */ |
| 594 | cifs_dbg(FYI, "search backing up - close and restart search\n"); | 594 | cifs_dbg(FYI, "search backing up - close and restart search\n"); |
| 595 | spin_lock(&cifs_file_list_lock); | 595 | spin_lock(&cifs_file_list_lock); |
| 596 | if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) { | 596 | if (server->ops->dir_needs_close(cfile)) { |
| 597 | cfile->invalidHandle = true; | 597 | cfile->invalidHandle = true; |
| 598 | spin_unlock(&cifs_file_list_lock); | 598 | spin_unlock(&cifs_file_list_lock); |
| 599 | if (server->ops->close) | 599 | if (server->ops->close) |
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index 5e8c22d6c7b9..1a6df4b03f67 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c | |||
| @@ -1015,6 +1015,12 @@ cifs_wp_retry_size(struct inode *inode) | |||
| 1015 | return CIFS_SB(inode->i_sb)->wsize; | 1015 | return CIFS_SB(inode->i_sb)->wsize; |
| 1016 | } | 1016 | } |
| 1017 | 1017 | ||
| 1018 | static bool | ||
| 1019 | cifs_dir_needs_close(struct cifsFileInfo *cfile) | ||
| 1020 | { | ||
| 1021 | return !cfile->srch_inf.endOfSearch && !cfile->invalidHandle; | ||
| 1022 | } | ||
| 1023 | |||
| 1018 | struct smb_version_operations smb1_operations = { | 1024 | struct smb_version_operations smb1_operations = { |
| 1019 | .send_cancel = send_nt_cancel, | 1025 | .send_cancel = send_nt_cancel, |
| 1020 | .compare_fids = cifs_compare_fids, | 1026 | .compare_fids = cifs_compare_fids, |
| @@ -1086,6 +1092,7 @@ struct smb_version_operations smb1_operations = { | |||
| 1086 | .create_mf_symlink = cifs_create_mf_symlink, | 1092 | .create_mf_symlink = cifs_create_mf_symlink, |
| 1087 | .is_read_op = cifs_is_read_op, | 1093 | .is_read_op = cifs_is_read_op, |
| 1088 | .wp_retry_size = cifs_wp_retry_size, | 1094 | .wp_retry_size = cifs_wp_retry_size, |
| 1095 | .dir_needs_close = cifs_dir_needs_close, | ||
| 1089 | #ifdef CONFIG_CIFS_XATTR | 1096 | #ifdef CONFIG_CIFS_XATTR |
| 1090 | .query_all_EAs = CIFSSMBQAllEAs, | 1097 | .query_all_EAs = CIFSSMBQAllEAs, |
| 1091 | .set_EA = CIFSSMBSetEA, | 1098 | .set_EA = CIFSSMBSetEA, |
diff --git a/fs/cifs/smb2maperror.c b/fs/cifs/smb2maperror.c index e31a9dfdcd39..af59d03db492 100644 --- a/fs/cifs/smb2maperror.c +++ b/fs/cifs/smb2maperror.c | |||
| @@ -214,7 +214,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = { | |||
| 214 | {STATUS_BREAKPOINT, -EIO, "STATUS_BREAKPOINT"}, | 214 | {STATUS_BREAKPOINT, -EIO, "STATUS_BREAKPOINT"}, |
| 215 | {STATUS_SINGLE_STEP, -EIO, "STATUS_SINGLE_STEP"}, | 215 | {STATUS_SINGLE_STEP, -EIO, "STATUS_SINGLE_STEP"}, |
| 216 | {STATUS_BUFFER_OVERFLOW, -EIO, "STATUS_BUFFER_OVERFLOW"}, | 216 | {STATUS_BUFFER_OVERFLOW, -EIO, "STATUS_BUFFER_OVERFLOW"}, |
| 217 | {STATUS_NO_MORE_FILES, -EIO, "STATUS_NO_MORE_FILES"}, | 217 | {STATUS_NO_MORE_FILES, -ENODATA, "STATUS_NO_MORE_FILES"}, |
| 218 | {STATUS_WAKE_SYSTEM_DEBUGGER, -EIO, "STATUS_WAKE_SYSTEM_DEBUGGER"}, | 218 | {STATUS_WAKE_SYSTEM_DEBUGGER, -EIO, "STATUS_WAKE_SYSTEM_DEBUGGER"}, |
| 219 | {STATUS_HANDLES_CLOSED, -EIO, "STATUS_HANDLES_CLOSED"}, | 219 | {STATUS_HANDLES_CLOSED, -EIO, "STATUS_HANDLES_CLOSED"}, |
| 220 | {STATUS_NO_INHERITANCE, -EIO, "STATUS_NO_INHERITANCE"}, | 220 | {STATUS_NO_INHERITANCE, -EIO, "STATUS_NO_INHERITANCE"}, |
| @@ -298,7 +298,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = { | |||
| 298 | {STATUS_INVALID_PARAMETER, -EINVAL, "STATUS_INVALID_PARAMETER"}, | 298 | {STATUS_INVALID_PARAMETER, -EINVAL, "STATUS_INVALID_PARAMETER"}, |
| 299 | {STATUS_NO_SUCH_DEVICE, -ENODEV, "STATUS_NO_SUCH_DEVICE"}, | 299 | {STATUS_NO_SUCH_DEVICE, -ENODEV, "STATUS_NO_SUCH_DEVICE"}, |
| 300 | {STATUS_NO_SUCH_FILE, -ENOENT, "STATUS_NO_SUCH_FILE"}, | 300 | {STATUS_NO_SUCH_FILE, -ENOENT, "STATUS_NO_SUCH_FILE"}, |
| 301 | {STATUS_INVALID_DEVICE_REQUEST, -EIO, "STATUS_INVALID_DEVICE_REQUEST"}, | 301 | {STATUS_INVALID_DEVICE_REQUEST, -EOPNOTSUPP, "STATUS_INVALID_DEVICE_REQUEST"}, |
| 302 | {STATUS_END_OF_FILE, -ENODATA, "STATUS_END_OF_FILE"}, | 302 | {STATUS_END_OF_FILE, -ENODATA, "STATUS_END_OF_FILE"}, |
| 303 | {STATUS_WRONG_VOLUME, -EIO, "STATUS_WRONG_VOLUME"}, | 303 | {STATUS_WRONG_VOLUME, -EIO, "STATUS_WRONG_VOLUME"}, |
| 304 | {STATUS_NO_MEDIA_IN_DEVICE, -EIO, "STATUS_NO_MEDIA_IN_DEVICE"}, | 304 | {STATUS_NO_MEDIA_IN_DEVICE, -EIO, "STATUS_NO_MEDIA_IN_DEVICE"}, |
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c index f2e6ac29a8d6..4aa7a0f07d6e 100644 --- a/fs/cifs/smb2misc.c +++ b/fs/cifs/smb2misc.c | |||
| @@ -178,9 +178,24 @@ smb2_check_message(char *buf, unsigned int length) | |||
| 178 | /* Windows 7 server returns 24 bytes more */ | 178 | /* Windows 7 server returns 24 bytes more */ |
| 179 | if (clc_len + 20 == len && command == SMB2_OPLOCK_BREAK_HE) | 179 | if (clc_len + 20 == len && command == SMB2_OPLOCK_BREAK_HE) |
| 180 | return 0; | 180 | return 0; |
| 181 | /* server can return one byte more */ | 181 | /* server can return one byte more due to implied bcc[0] */ |
| 182 | if (clc_len == 4 + len + 1) | 182 | if (clc_len == 4 + len + 1) |
| 183 | return 0; | 183 | return 0; |
| 184 | |||
| 185 | /* | ||
| 186 | * MacOS server pads after SMB2.1 write response with 3 bytes | ||
| 187 | * of junk. Other servers match RFC1001 len to actual | ||
| 188 | * SMB2/SMB3 frame length (header + smb2 response specific data) | ||
| 189 | * Log the server error (once), but allow it and continue | ||
| 190 | * since the frame is parseable. | ||
| 191 | */ | ||
| 192 | if (clc_len < 4 /* RFC1001 header size */ + len) { | ||
| 193 | printk_once(KERN_WARNING | ||
| 194 | "SMB2 server sent bad RFC1001 len %d not %d\n", | ||
| 195 | len, clc_len - 4); | ||
| 196 | return 0; | ||
| 197 | } | ||
| 198 | |||
| 184 | return 1; | 199 | return 1; |
| 185 | } | 200 | } |
| 186 | return 0; | 201 | return 0; |
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 77f8aeb9c2fc..5a48aa290dfe 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
| @@ -731,11 +731,72 @@ smb2_sync_write(const unsigned int xid, struct cifsFileInfo *cfile, | |||
| 731 | return SMB2_write(xid, parms, written, iov, nr_segs); | 731 | return SMB2_write(xid, parms, written, iov, nr_segs); |
| 732 | } | 732 | } |
| 733 | 733 | ||
| 734 | /* Set or clear the SPARSE_FILE attribute based on value passed in setsparse */ | ||
| 735 | static bool smb2_set_sparse(const unsigned int xid, struct cifs_tcon *tcon, | ||
| 736 | struct cifsFileInfo *cfile, struct inode *inode, __u8 setsparse) | ||
| 737 | { | ||
| 738 | struct cifsInodeInfo *cifsi; | ||
| 739 | int rc; | ||
| 740 | |||
| 741 | cifsi = CIFS_I(inode); | ||
| 742 | |||
| 743 | /* if file already sparse don't bother setting sparse again */ | ||
| 744 | if ((cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) && setsparse) | ||
| 745 | return true; /* already sparse */ | ||
| 746 | |||
| 747 | if (!(cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) && !setsparse) | ||
| 748 | return true; /* already not sparse */ | ||
| 749 | |||
| 750 | /* | ||
| 751 | * Can't check for sparse support on share the usual way via the | ||
| 752 | * FS attribute info (FILE_SUPPORTS_SPARSE_FILES) on the share | ||
| 753 | * since Samba server doesn't set the flag on the share, yet | ||
| 754 | * supports the set sparse FSCTL and returns sparse correctly | ||
| 755 | * in the file attributes. If we fail setting sparse though we | ||
| 756 | * mark that server does not support sparse files for this share | ||
| 757 | * to avoid repeatedly sending the unsupported fsctl to server | ||
| 758 | * if the file is repeatedly extended. | ||
| 759 | */ | ||
| 760 | if (tcon->broken_sparse_sup) | ||
| 761 | return false; | ||
| 762 | |||
| 763 | rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, | ||
| 764 | cfile->fid.volatile_fid, FSCTL_SET_SPARSE, | ||
| 765 | true /* is_fctl */, &setsparse, 1, NULL, NULL); | ||
| 766 | if (rc) { | ||
| 767 | tcon->broken_sparse_sup = true; | ||
| 768 | cifs_dbg(FYI, "set sparse rc = %d\n", rc); | ||
| 769 | return false; | ||
| 770 | } | ||
| 771 | |||
| 772 | if (setsparse) | ||
| 773 | cifsi->cifsAttrs |= FILE_ATTRIBUTE_SPARSE_FILE; | ||
| 774 | else | ||
| 775 | cifsi->cifsAttrs &= (~FILE_ATTRIBUTE_SPARSE_FILE); | ||
| 776 | |||
| 777 | return true; | ||
| 778 | } | ||
| 779 | |||
| 734 | static int | 780 | static int |
| 735 | smb2_set_file_size(const unsigned int xid, struct cifs_tcon *tcon, | 781 | smb2_set_file_size(const unsigned int xid, struct cifs_tcon *tcon, |
| 736 | struct cifsFileInfo *cfile, __u64 size, bool set_alloc) | 782 | struct cifsFileInfo *cfile, __u64 size, bool set_alloc) |
| 737 | { | 783 | { |
| 738 | __le64 eof = cpu_to_le64(size); | 784 | __le64 eof = cpu_to_le64(size); |
| 785 | struct inode *inode; | ||
| 786 | |||
| 787 | /* | ||
| 788 | * If extending file more than one page make sparse. Many Linux fs | ||
| 789 | * make files sparse by default when extending via ftruncate | ||
| 790 | */ | ||
| 791 | inode = cfile->dentry->d_inode; | ||
| 792 | |||
| 793 | if (!set_alloc && (size > inode->i_size + 8192)) { | ||
| 794 | __u8 set_sparse = 1; | ||
| 795 | |||
| 796 | /* whether set sparse succeeds or not, extend the file */ | ||
| 797 | smb2_set_sparse(xid, tcon, cfile, inode, set_sparse); | ||
| 798 | } | ||
| 799 | |||
| 739 | return SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid, | 800 | return SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid, |
| 740 | cfile->fid.volatile_fid, cfile->pid, &eof, false); | 801 | cfile->fid.volatile_fid, cfile->pid, &eof, false); |
| 741 | } | 802 | } |
| @@ -954,6 +1015,105 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 954 | return rc; | 1015 | return rc; |
| 955 | } | 1016 | } |
| 956 | 1017 | ||
| 1018 | static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon, | ||
| 1019 | loff_t offset, loff_t len, bool keep_size) | ||
| 1020 | { | ||
| 1021 | struct inode *inode; | ||
| 1022 | struct cifsInodeInfo *cifsi; | ||
| 1023 | struct cifsFileInfo *cfile = file->private_data; | ||
| 1024 | struct file_zero_data_information fsctl_buf; | ||
| 1025 | long rc; | ||
| 1026 | unsigned int xid; | ||
| 1027 | |||
| 1028 | xid = get_xid(); | ||
| 1029 | |||
| 1030 | inode = cfile->dentry->d_inode; | ||
| 1031 | cifsi = CIFS_I(inode); | ||
| 1032 | |||
| 1033 | /* if file not oplocked can't be sure whether asking to extend size */ | ||
| 1034 | if (!CIFS_CACHE_READ(cifsi)) | ||
| 1035 | if (keep_size == false) | ||
| 1036 | return -EOPNOTSUPP; | ||
| 1037 | |||
| 1038 | /* | ||
| 1039 | * Must check if file sparse since fallocate -z (zero range) assumes | ||
| 1040 | * non-sparse allocation | ||
| 1041 | */ | ||
| 1042 | if (!(cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE)) | ||
| 1043 | return -EOPNOTSUPP; | ||
| 1044 | |||
| 1045 | /* | ||
| 1046 | * need to make sure we are not asked to extend the file since the SMB3 | ||
| 1047 | * fsctl does not change the file size. In the future we could change | ||
| 1048 | * this to zero the first part of the range then set the file size | ||
| 1049 | * which for a non sparse file would zero the newly extended range | ||
| 1050 | */ | ||
| 1051 | if (keep_size == false) | ||
| 1052 | if (i_size_read(inode) < offset + len) | ||
| 1053 | return -EOPNOTSUPP; | ||
| 1054 | |||
| 1055 | cifs_dbg(FYI, "offset %lld len %lld", offset, len); | ||
| 1056 | |||
| 1057 | fsctl_buf.FileOffset = cpu_to_le64(offset); | ||
| 1058 | fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len); | ||
| 1059 | |||
| 1060 | rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, | ||
| 1061 | cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA, | ||
| 1062 | true /* is_fctl */, (char *)&fsctl_buf, | ||
| 1063 | sizeof(struct file_zero_data_information), NULL, NULL); | ||
| 1064 | free_xid(xid); | ||
| 1065 | return rc; | ||
| 1066 | } | ||
| 1067 | |||
| 1068 | static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon, | ||
| 1069 | loff_t offset, loff_t len) | ||
| 1070 | { | ||
| 1071 | struct inode *inode; | ||
| 1072 | struct cifsInodeInfo *cifsi; | ||
| 1073 | struct cifsFileInfo *cfile = file->private_data; | ||
| 1074 | struct file_zero_data_information fsctl_buf; | ||
| 1075 | long rc; | ||
| 1076 | unsigned int xid; | ||
| 1077 | __u8 set_sparse = 1; | ||
| 1078 | |||
| 1079 | xid = get_xid(); | ||
| 1080 | |||
| 1081 | inode = cfile->dentry->d_inode; | ||
| 1082 | cifsi = CIFS_I(inode); | ||
| 1083 | |||
| 1084 | /* Need to make file sparse, if not already, before freeing range. */ | ||
| 1085 | /* Consider adding equivalent for compressed since it could also work */ | ||
| 1086 | if (!smb2_set_sparse(xid, tcon, cfile, inode, set_sparse)) | ||
| 1087 | return -EOPNOTSUPP; | ||
| 1088 | |||
| 1089 | cifs_dbg(FYI, "offset %lld len %lld", offset, len); | ||
| 1090 | |||
| 1091 | fsctl_buf.FileOffset = cpu_to_le64(offset); | ||
| 1092 | fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len); | ||
| 1093 | |||
| 1094 | rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, | ||
| 1095 | cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA, | ||
| 1096 | true /* is_fctl */, (char *)&fsctl_buf, | ||
| 1097 | sizeof(struct file_zero_data_information), NULL, NULL); | ||
| 1098 | free_xid(xid); | ||
| 1099 | return rc; | ||
| 1100 | } | ||
| 1101 | |||
| 1102 | static long smb3_fallocate(struct file *file, struct cifs_tcon *tcon, int mode, | ||
| 1103 | loff_t off, loff_t len) | ||
| 1104 | { | ||
| 1105 | /* KEEP_SIZE already checked for by do_fallocate */ | ||
| 1106 | if (mode & FALLOC_FL_PUNCH_HOLE) | ||
| 1107 | return smb3_punch_hole(file, tcon, off, len); | ||
| 1108 | else if (mode & FALLOC_FL_ZERO_RANGE) { | ||
| 1109 | if (mode & FALLOC_FL_KEEP_SIZE) | ||
| 1110 | return smb3_zero_range(file, tcon, off, len, true); | ||
| 1111 | return smb3_zero_range(file, tcon, off, len, false); | ||
| 1112 | } | ||
| 1113 | |||
| 1114 | return -EOPNOTSUPP; | ||
| 1115 | } | ||
| 1116 | |||
| 957 | static void | 1117 | static void |
| 958 | smb2_downgrade_oplock(struct TCP_Server_Info *server, | 1118 | smb2_downgrade_oplock(struct TCP_Server_Info *server, |
| 959 | struct cifsInodeInfo *cinode, bool set_level2) | 1119 | struct cifsInodeInfo *cinode, bool set_level2) |
| @@ -1161,6 +1321,12 @@ smb2_wp_retry_size(struct inode *inode) | |||
| 1161 | SMB2_MAX_BUFFER_SIZE); | 1321 | SMB2_MAX_BUFFER_SIZE); |
| 1162 | } | 1322 | } |
| 1163 | 1323 | ||
| 1324 | static bool | ||
| 1325 | smb2_dir_needs_close(struct cifsFileInfo *cfile) | ||
| 1326 | { | ||
| 1327 | return !cfile->invalidHandle; | ||
| 1328 | } | ||
| 1329 | |||
| 1164 | struct smb_version_operations smb20_operations = { | 1330 | struct smb_version_operations smb20_operations = { |
| 1165 | .compare_fids = smb2_compare_fids, | 1331 | .compare_fids = smb2_compare_fids, |
| 1166 | .setup_request = smb2_setup_request, | 1332 | .setup_request = smb2_setup_request, |
| @@ -1236,6 +1402,7 @@ struct smb_version_operations smb20_operations = { | |||
| 1236 | .parse_lease_buf = smb2_parse_lease_buf, | 1402 | .parse_lease_buf = smb2_parse_lease_buf, |
| 1237 | .clone_range = smb2_clone_range, | 1403 | .clone_range = smb2_clone_range, |
| 1238 | .wp_retry_size = smb2_wp_retry_size, | 1404 | .wp_retry_size = smb2_wp_retry_size, |
| 1405 | .dir_needs_close = smb2_dir_needs_close, | ||
| 1239 | }; | 1406 | }; |
| 1240 | 1407 | ||
| 1241 | struct smb_version_operations smb21_operations = { | 1408 | struct smb_version_operations smb21_operations = { |
| @@ -1313,6 +1480,7 @@ struct smb_version_operations smb21_operations = { | |||
| 1313 | .parse_lease_buf = smb2_parse_lease_buf, | 1480 | .parse_lease_buf = smb2_parse_lease_buf, |
| 1314 | .clone_range = smb2_clone_range, | 1481 | .clone_range = smb2_clone_range, |
| 1315 | .wp_retry_size = smb2_wp_retry_size, | 1482 | .wp_retry_size = smb2_wp_retry_size, |
| 1483 | .dir_needs_close = smb2_dir_needs_close, | ||
| 1316 | }; | 1484 | }; |
| 1317 | 1485 | ||
| 1318 | struct smb_version_operations smb30_operations = { | 1486 | struct smb_version_operations smb30_operations = { |
| @@ -1393,6 +1561,8 @@ struct smb_version_operations smb30_operations = { | |||
| 1393 | .clone_range = smb2_clone_range, | 1561 | .clone_range = smb2_clone_range, |
| 1394 | .validate_negotiate = smb3_validate_negotiate, | 1562 | .validate_negotiate = smb3_validate_negotiate, |
| 1395 | .wp_retry_size = smb2_wp_retry_size, | 1563 | .wp_retry_size = smb2_wp_retry_size, |
| 1564 | .dir_needs_close = smb2_dir_needs_close, | ||
| 1565 | .fallocate = smb3_fallocate, | ||
| 1396 | }; | 1566 | }; |
| 1397 | 1567 | ||
| 1398 | struct smb_version_values smb20_values = { | 1568 | struct smb_version_values smb20_values = { |
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 42ebc1a8be6c..fa0dd044213b 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
| @@ -907,7 +907,8 @@ tcon_exit: | |||
| 907 | tcon_error_exit: | 907 | tcon_error_exit: |
| 908 | if (rsp->hdr.Status == STATUS_BAD_NETWORK_NAME) { | 908 | if (rsp->hdr.Status == STATUS_BAD_NETWORK_NAME) { |
| 909 | cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree); | 909 | cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree); |
| 910 | tcon->bad_network_name = true; | 910 | if (tcon) |
| 911 | tcon->bad_network_name = true; | ||
| 911 | } | 912 | } |
| 912 | goto tcon_exit; | 913 | goto tcon_exit; |
| 913 | } | 914 | } |
| @@ -1224,7 +1225,9 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, | |||
| 1224 | 1225 | ||
| 1225 | cifs_dbg(FYI, "SMB2 IOCTL\n"); | 1226 | cifs_dbg(FYI, "SMB2 IOCTL\n"); |
| 1226 | 1227 | ||
| 1227 | *out_data = NULL; | 1228 | if (out_data != NULL) |
| 1229 | *out_data = NULL; | ||
| 1230 | |||
| 1228 | /* zero out returned data len, in case of error */ | 1231 | /* zero out returned data len, in case of error */ |
| 1229 | if (plen) | 1232 | if (plen) |
| 1230 | *plen = 0; | 1233 | *plen = 0; |
| @@ -2177,6 +2180,10 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 2177 | rsp = (struct smb2_query_directory_rsp *)iov[0].iov_base; | 2180 | rsp = (struct smb2_query_directory_rsp *)iov[0].iov_base; |
| 2178 | 2181 | ||
| 2179 | if (rc) { | 2182 | if (rc) { |
| 2183 | if (rc == -ENODATA && rsp->hdr.Status == STATUS_NO_MORE_FILES) { | ||
| 2184 | srch_inf->endOfSearch = true; | ||
| 2185 | rc = 0; | ||
| 2186 | } | ||
| 2180 | cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE); | 2187 | cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE); |
| 2181 | goto qdir_exit; | 2188 | goto qdir_exit; |
| 2182 | } | 2189 | } |
| @@ -2214,11 +2221,6 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 2214 | else | 2221 | else |
| 2215 | cifs_dbg(VFS, "illegal search buffer type\n"); | 2222 | cifs_dbg(VFS, "illegal search buffer type\n"); |
| 2216 | 2223 | ||
| 2217 | if (rsp->hdr.Status == STATUS_NO_MORE_FILES) | ||
| 2218 | srch_inf->endOfSearch = 1; | ||
| 2219 | else | ||
| 2220 | srch_inf->endOfSearch = 0; | ||
| 2221 | |||
| 2222 | return rc; | 2224 | return rc; |
| 2223 | 2225 | ||
| 2224 | qdir_exit: | 2226 | qdir_exit: |
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index 69f3595d3952..fbe486c285a9 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h | |||
| @@ -573,6 +573,12 @@ struct copychunk_ioctl { | |||
| 573 | __u32 Reserved2; | 573 | __u32 Reserved2; |
| 574 | } __packed; | 574 | } __packed; |
| 575 | 575 | ||
| 576 | /* this goes in the ioctl buffer when doing FSCTL_SET_ZERO_DATA */ | ||
| 577 | struct file_zero_data_information { | ||
| 578 | __le64 FileOffset; | ||
| 579 | __le64 BeyondFinalZero; | ||
| 580 | } __packed; | ||
| 581 | |||
| 576 | struct copychunk_ioctl_rsp { | 582 | struct copychunk_ioctl_rsp { |
| 577 | __le32 ChunksWritten; | 583 | __le32 ChunksWritten; |
| 578 | __le32 ChunkBytesWritten; | 584 | __le32 ChunkBytesWritten; |
diff --git a/fs/cifs/smbfsctl.h b/fs/cifs/smbfsctl.h index 0e538b5c9622..83efa59535be 100644 --- a/fs/cifs/smbfsctl.h +++ b/fs/cifs/smbfsctl.h | |||
| @@ -63,7 +63,7 @@ | |||
| 63 | #define FSCTL_SET_OBJECT_ID_EXTENDED 0x000900BC /* BB add struct */ | 63 | #define FSCTL_SET_OBJECT_ID_EXTENDED 0x000900BC /* BB add struct */ |
| 64 | #define FSCTL_CREATE_OR_GET_OBJECT_ID 0x000900C0 /* BB add struct */ | 64 | #define FSCTL_CREATE_OR_GET_OBJECT_ID 0x000900C0 /* BB add struct */ |
| 65 | #define FSCTL_SET_SPARSE 0x000900C4 /* BB add struct */ | 65 | #define FSCTL_SET_SPARSE 0x000900C4 /* BB add struct */ |
| 66 | #define FSCTL_SET_ZERO_DATA 0x000900C8 /* BB add struct */ | 66 | #define FSCTL_SET_ZERO_DATA 0x000980C8 |
| 67 | #define FSCTL_SET_ENCRYPTION 0x000900D7 /* BB add struct */ | 67 | #define FSCTL_SET_ENCRYPTION 0x000900D7 /* BB add struct */ |
| 68 | #define FSCTL_ENCRYPTION_FSCTL_IO 0x000900DB /* BB add struct */ | 68 | #define FSCTL_ENCRYPTION_FSCTL_IO 0x000900DB /* BB add struct */ |
| 69 | #define FSCTL_WRITE_RAW_ENCRYPTED 0x000900DF /* BB add struct */ | 69 | #define FSCTL_WRITE_RAW_ENCRYPTED 0x000900DF /* BB add struct */ |
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 08cdfe5461e3..622e88249024 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
| @@ -2828,8 +2828,9 @@ static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf) | |||
| 2828 | */ | 2828 | */ |
| 2829 | overhead += ngroups * (2 + sbi->s_itb_per_group); | 2829 | overhead += ngroups * (2 + sbi->s_itb_per_group); |
| 2830 | 2830 | ||
| 2831 | /* Add the journal blocks as well */ | 2831 | /* Add the internal journal blocks as well */ |
| 2832 | overhead += sbi->s_journal->j_maxlen; | 2832 | if (sbi->s_journal && !sbi->journal_bdev) |
| 2833 | overhead += sbi->s_journal->j_maxlen; | ||
| 2833 | 2834 | ||
| 2834 | sbi->s_overhead_last = overhead; | 2835 | sbi->s_overhead_last = overhead; |
| 2835 | smp_wmb(); | 2836 | smp_wmb(); |
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 4556ce1af5b0..5ddaf8625d3b 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c | |||
| @@ -61,7 +61,7 @@ static void isofs_put_super(struct super_block *sb) | |||
| 61 | return; | 61 | return; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | static int isofs_read_inode(struct inode *); | 64 | static int isofs_read_inode(struct inode *, int relocated); |
| 65 | static int isofs_statfs (struct dentry *, struct kstatfs *); | 65 | static int isofs_statfs (struct dentry *, struct kstatfs *); |
| 66 | 66 | ||
| 67 | static struct kmem_cache *isofs_inode_cachep; | 67 | static struct kmem_cache *isofs_inode_cachep; |
| @@ -1259,7 +1259,7 @@ out_toomany: | |||
| 1259 | goto out; | 1259 | goto out; |
| 1260 | } | 1260 | } |
| 1261 | 1261 | ||
| 1262 | static int isofs_read_inode(struct inode *inode) | 1262 | static int isofs_read_inode(struct inode *inode, int relocated) |
| 1263 | { | 1263 | { |
| 1264 | struct super_block *sb = inode->i_sb; | 1264 | struct super_block *sb = inode->i_sb; |
| 1265 | struct isofs_sb_info *sbi = ISOFS_SB(sb); | 1265 | struct isofs_sb_info *sbi = ISOFS_SB(sb); |
| @@ -1404,7 +1404,7 @@ static int isofs_read_inode(struct inode *inode) | |||
| 1404 | */ | 1404 | */ |
| 1405 | 1405 | ||
| 1406 | if (!high_sierra) { | 1406 | if (!high_sierra) { |
| 1407 | parse_rock_ridge_inode(de, inode); | 1407 | parse_rock_ridge_inode(de, inode, relocated); |
| 1408 | /* if we want uid/gid set, override the rock ridge setting */ | 1408 | /* if we want uid/gid set, override the rock ridge setting */ |
| 1409 | if (sbi->s_uid_set) | 1409 | if (sbi->s_uid_set) |
| 1410 | inode->i_uid = sbi->s_uid; | 1410 | inode->i_uid = sbi->s_uid; |
| @@ -1483,9 +1483,10 @@ static int isofs_iget5_set(struct inode *ino, void *data) | |||
| 1483 | * offset that point to the underlying meta-data for the inode. The | 1483 | * offset that point to the underlying meta-data for the inode. The |
| 1484 | * code below is otherwise similar to the iget() code in | 1484 | * code below is otherwise similar to the iget() code in |
| 1485 | * include/linux/fs.h */ | 1485 | * include/linux/fs.h */ |
| 1486 | struct inode *isofs_iget(struct super_block *sb, | 1486 | struct inode *__isofs_iget(struct super_block *sb, |
| 1487 | unsigned long block, | 1487 | unsigned long block, |
| 1488 | unsigned long offset) | 1488 | unsigned long offset, |
| 1489 | int relocated) | ||
| 1489 | { | 1490 | { |
| 1490 | unsigned long hashval; | 1491 | unsigned long hashval; |
| 1491 | struct inode *inode; | 1492 | struct inode *inode; |
| @@ -1507,7 +1508,7 @@ struct inode *isofs_iget(struct super_block *sb, | |||
| 1507 | return ERR_PTR(-ENOMEM); | 1508 | return ERR_PTR(-ENOMEM); |
| 1508 | 1509 | ||
| 1509 | if (inode->i_state & I_NEW) { | 1510 | if (inode->i_state & I_NEW) { |
| 1510 | ret = isofs_read_inode(inode); | 1511 | ret = isofs_read_inode(inode, relocated); |
| 1511 | if (ret < 0) { | 1512 | if (ret < 0) { |
| 1512 | iget_failed(inode); | 1513 | iget_failed(inode); |
| 1513 | inode = ERR_PTR(ret); | 1514 | inode = ERR_PTR(ret); |
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h index 99167238518d..0ac4c1f73fbd 100644 --- a/fs/isofs/isofs.h +++ b/fs/isofs/isofs.h | |||
| @@ -107,7 +107,7 @@ extern int iso_date(char *, int); | |||
| 107 | 107 | ||
| 108 | struct inode; /* To make gcc happy */ | 108 | struct inode; /* To make gcc happy */ |
| 109 | 109 | ||
| 110 | extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *); | 110 | extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *, int relocated); |
| 111 | extern int get_rock_ridge_filename(struct iso_directory_record *, char *, struct inode *); | 111 | extern int get_rock_ridge_filename(struct iso_directory_record *, char *, struct inode *); |
| 112 | extern int isofs_name_translate(struct iso_directory_record *, char *, struct inode *); | 112 | extern int isofs_name_translate(struct iso_directory_record *, char *, struct inode *); |
| 113 | 113 | ||
| @@ -118,9 +118,24 @@ extern struct dentry *isofs_lookup(struct inode *, struct dentry *, unsigned int | |||
| 118 | extern struct buffer_head *isofs_bread(struct inode *, sector_t); | 118 | extern struct buffer_head *isofs_bread(struct inode *, sector_t); |
| 119 | extern int isofs_get_blocks(struct inode *, sector_t, struct buffer_head **, unsigned long); | 119 | extern int isofs_get_blocks(struct inode *, sector_t, struct buffer_head **, unsigned long); |
| 120 | 120 | ||
| 121 | extern struct inode *isofs_iget(struct super_block *sb, | 121 | struct inode *__isofs_iget(struct super_block *sb, |
| 122 | unsigned long block, | 122 | unsigned long block, |
| 123 | unsigned long offset); | 123 | unsigned long offset, |
| 124 | int relocated); | ||
| 125 | |||
| 126 | static inline struct inode *isofs_iget(struct super_block *sb, | ||
| 127 | unsigned long block, | ||
| 128 | unsigned long offset) | ||
| 129 | { | ||
| 130 | return __isofs_iget(sb, block, offset, 0); | ||
| 131 | } | ||
| 132 | |||
| 133 | static inline struct inode *isofs_iget_reloc(struct super_block *sb, | ||
| 134 | unsigned long block, | ||
| 135 | unsigned long offset) | ||
| 136 | { | ||
| 137 | return __isofs_iget(sb, block, offset, 1); | ||
| 138 | } | ||
| 124 | 139 | ||
| 125 | /* Because the inode number is no longer relevant to finding the | 140 | /* Because the inode number is no longer relevant to finding the |
| 126 | * underlying meta-data for an inode, we are free to choose a more | 141 | * underlying meta-data for an inode, we are free to choose a more |
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c index c0bf42472e40..f488bbae541a 100644 --- a/fs/isofs/rock.c +++ b/fs/isofs/rock.c | |||
| @@ -288,12 +288,16 @@ eio: | |||
| 288 | goto out; | 288 | goto out; |
| 289 | } | 289 | } |
| 290 | 290 | ||
| 291 | #define RR_REGARD_XA 1 | ||
| 292 | #define RR_RELOC_DE 2 | ||
| 293 | |||
| 291 | static int | 294 | static int |
| 292 | parse_rock_ridge_inode_internal(struct iso_directory_record *de, | 295 | parse_rock_ridge_inode_internal(struct iso_directory_record *de, |
| 293 | struct inode *inode, int regard_xa) | 296 | struct inode *inode, int flags) |
| 294 | { | 297 | { |
| 295 | int symlink_len = 0; | 298 | int symlink_len = 0; |
| 296 | int cnt, sig; | 299 | int cnt, sig; |
| 300 | unsigned int reloc_block; | ||
| 297 | struct inode *reloc; | 301 | struct inode *reloc; |
| 298 | struct rock_ridge *rr; | 302 | struct rock_ridge *rr; |
| 299 | int rootflag; | 303 | int rootflag; |
| @@ -305,7 +309,7 @@ parse_rock_ridge_inode_internal(struct iso_directory_record *de, | |||
| 305 | 309 | ||
| 306 | init_rock_state(&rs, inode); | 310 | init_rock_state(&rs, inode); |
| 307 | setup_rock_ridge(de, inode, &rs); | 311 | setup_rock_ridge(de, inode, &rs); |
| 308 | if (regard_xa) { | 312 | if (flags & RR_REGARD_XA) { |
| 309 | rs.chr += 14; | 313 | rs.chr += 14; |
| 310 | rs.len -= 14; | 314 | rs.len -= 14; |
| 311 | if (rs.len < 0) | 315 | if (rs.len < 0) |
| @@ -485,12 +489,22 @@ repeat: | |||
| 485 | "relocated directory\n"); | 489 | "relocated directory\n"); |
| 486 | goto out; | 490 | goto out; |
| 487 | case SIG('C', 'L'): | 491 | case SIG('C', 'L'): |
| 488 | ISOFS_I(inode)->i_first_extent = | 492 | if (flags & RR_RELOC_DE) { |
| 489 | isonum_733(rr->u.CL.location); | 493 | printk(KERN_ERR |
| 490 | reloc = | 494 | "ISOFS: Recursive directory relocation " |
| 491 | isofs_iget(inode->i_sb, | 495 | "is not supported\n"); |
| 492 | ISOFS_I(inode)->i_first_extent, | 496 | goto eio; |
| 493 | 0); | 497 | } |
| 498 | reloc_block = isonum_733(rr->u.CL.location); | ||
| 499 | if (reloc_block == ISOFS_I(inode)->i_iget5_block && | ||
| 500 | ISOFS_I(inode)->i_iget5_offset == 0) { | ||
| 501 | printk(KERN_ERR | ||
| 502 | "ISOFS: Directory relocation points to " | ||
| 503 | "itself\n"); | ||
| 504 | goto eio; | ||
| 505 | } | ||
| 506 | ISOFS_I(inode)->i_first_extent = reloc_block; | ||
| 507 | reloc = isofs_iget_reloc(inode->i_sb, reloc_block, 0); | ||
| 494 | if (IS_ERR(reloc)) { | 508 | if (IS_ERR(reloc)) { |
| 495 | ret = PTR_ERR(reloc); | 509 | ret = PTR_ERR(reloc); |
| 496 | goto out; | 510 | goto out; |
| @@ -637,9 +651,11 @@ static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit) | |||
| 637 | return rpnt; | 651 | return rpnt; |
| 638 | } | 652 | } |
| 639 | 653 | ||
| 640 | int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode) | 654 | int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode, |
| 655 | int relocated) | ||
| 641 | { | 656 | { |
| 642 | int result = parse_rock_ridge_inode_internal(de, inode, 0); | 657 | int flags = relocated ? RR_RELOC_DE : 0; |
| 658 | int result = parse_rock_ridge_inode_internal(de, inode, flags); | ||
| 643 | 659 | ||
| 644 | /* | 660 | /* |
| 645 | * if rockridge flag was reset and we didn't look for attributes | 661 | * if rockridge flag was reset and we didn't look for attributes |
| @@ -647,7 +663,8 @@ int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode) | |||
| 647 | */ | 663 | */ |
| 648 | if ((ISOFS_SB(inode->i_sb)->s_rock_offset == -1) | 664 | if ((ISOFS_SB(inode->i_sb)->s_rock_offset == -1) |
| 649 | && (ISOFS_SB(inode->i_sb)->s_rock == 2)) { | 665 | && (ISOFS_SB(inode->i_sb)->s_rock == 2)) { |
| 650 | result = parse_rock_ridge_inode_internal(de, inode, 14); | 666 | result = parse_rock_ridge_inode_internal(de, inode, |
| 667 | flags | RR_REGARD_XA); | ||
| 651 | } | 668 | } |
| 652 | return result; | 669 | return result; |
| 653 | } | 670 | } |
diff --git a/fs/locks.c b/fs/locks.c index a6f54802d277..cb66fb05ad4a 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
| @@ -247,6 +247,18 @@ void locks_free_lock(struct file_lock *fl) | |||
| 247 | } | 247 | } |
| 248 | EXPORT_SYMBOL(locks_free_lock); | 248 | EXPORT_SYMBOL(locks_free_lock); |
| 249 | 249 | ||
| 250 | static void | ||
| 251 | locks_dispose_list(struct list_head *dispose) | ||
| 252 | { | ||
| 253 | struct file_lock *fl; | ||
| 254 | |||
| 255 | while (!list_empty(dispose)) { | ||
| 256 | fl = list_first_entry(dispose, struct file_lock, fl_block); | ||
| 257 | list_del_init(&fl->fl_block); | ||
| 258 | locks_free_lock(fl); | ||
| 259 | } | ||
| 260 | } | ||
| 261 | |||
| 250 | void locks_init_lock(struct file_lock *fl) | 262 | void locks_init_lock(struct file_lock *fl) |
| 251 | { | 263 | { |
| 252 | memset(fl, 0, sizeof(struct file_lock)); | 264 | memset(fl, 0, sizeof(struct file_lock)); |
| @@ -285,7 +297,8 @@ EXPORT_SYMBOL(__locks_copy_lock); | |||
| 285 | 297 | ||
| 286 | void locks_copy_lock(struct file_lock *new, struct file_lock *fl) | 298 | void locks_copy_lock(struct file_lock *new, struct file_lock *fl) |
| 287 | { | 299 | { |
| 288 | locks_release_private(new); | 300 | /* "new" must be a freshly-initialized lock */ |
| 301 | WARN_ON_ONCE(new->fl_ops); | ||
| 289 | 302 | ||
| 290 | __locks_copy_lock(new, fl); | 303 | __locks_copy_lock(new, fl); |
| 291 | new->fl_file = fl->fl_file; | 304 | new->fl_file = fl->fl_file; |
| @@ -650,12 +663,16 @@ static void locks_unlink_lock(struct file_lock **thisfl_p) | |||
| 650 | * | 663 | * |
| 651 | * Must be called with i_lock held! | 664 | * Must be called with i_lock held! |
| 652 | */ | 665 | */ |
| 653 | static void locks_delete_lock(struct file_lock **thisfl_p) | 666 | static void locks_delete_lock(struct file_lock **thisfl_p, |
| 667 | struct list_head *dispose) | ||
| 654 | { | 668 | { |
| 655 | struct file_lock *fl = *thisfl_p; | 669 | struct file_lock *fl = *thisfl_p; |
| 656 | 670 | ||
| 657 | locks_unlink_lock(thisfl_p); | 671 | locks_unlink_lock(thisfl_p); |
| 658 | locks_free_lock(fl); | 672 | if (dispose) |
| 673 | list_add(&fl->fl_block, dispose); | ||
| 674 | else | ||
| 675 | locks_free_lock(fl); | ||
| 659 | } | 676 | } |
| 660 | 677 | ||
| 661 | /* Determine if lock sys_fl blocks lock caller_fl. Common functionality | 678 | /* Determine if lock sys_fl blocks lock caller_fl. Common functionality |
| @@ -811,6 +828,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *request) | |||
| 811 | struct inode * inode = file_inode(filp); | 828 | struct inode * inode = file_inode(filp); |
| 812 | int error = 0; | 829 | int error = 0; |
| 813 | int found = 0; | 830 | int found = 0; |
| 831 | LIST_HEAD(dispose); | ||
| 814 | 832 | ||
| 815 | if (!(request->fl_flags & FL_ACCESS) && (request->fl_type != F_UNLCK)) { | 833 | if (!(request->fl_flags & FL_ACCESS) && (request->fl_type != F_UNLCK)) { |
| 816 | new_fl = locks_alloc_lock(); | 834 | new_fl = locks_alloc_lock(); |
| @@ -833,7 +851,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *request) | |||
| 833 | if (request->fl_type == fl->fl_type) | 851 | if (request->fl_type == fl->fl_type) |
| 834 | goto out; | 852 | goto out; |
| 835 | found = 1; | 853 | found = 1; |
| 836 | locks_delete_lock(before); | 854 | locks_delete_lock(before, &dispose); |
| 837 | break; | 855 | break; |
| 838 | } | 856 | } |
| 839 | 857 | ||
| @@ -880,6 +898,7 @@ out: | |||
| 880 | spin_unlock(&inode->i_lock); | 898 | spin_unlock(&inode->i_lock); |
| 881 | if (new_fl) | 899 | if (new_fl) |
| 882 | locks_free_lock(new_fl); | 900 | locks_free_lock(new_fl); |
| 901 | locks_dispose_list(&dispose); | ||
| 883 | return error; | 902 | return error; |
| 884 | } | 903 | } |
| 885 | 904 | ||
| @@ -893,6 +912,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str | |||
| 893 | struct file_lock **before; | 912 | struct file_lock **before; |
| 894 | int error; | 913 | int error; |
| 895 | bool added = false; | 914 | bool added = false; |
| 915 | LIST_HEAD(dispose); | ||
| 896 | 916 | ||
| 897 | /* | 917 | /* |
| 898 | * We may need two file_lock structures for this operation, | 918 | * We may need two file_lock structures for this operation, |
| @@ -988,7 +1008,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str | |||
| 988 | else | 1008 | else |
| 989 | request->fl_end = fl->fl_end; | 1009 | request->fl_end = fl->fl_end; |
| 990 | if (added) { | 1010 | if (added) { |
| 991 | locks_delete_lock(before); | 1011 | locks_delete_lock(before, &dispose); |
| 992 | continue; | 1012 | continue; |
| 993 | } | 1013 | } |
| 994 | request = fl; | 1014 | request = fl; |
| @@ -1018,21 +1038,24 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str | |||
| 1018 | * one (This may happen several times). | 1038 | * one (This may happen several times). |
| 1019 | */ | 1039 | */ |
| 1020 | if (added) { | 1040 | if (added) { |
| 1021 | locks_delete_lock(before); | 1041 | locks_delete_lock(before, &dispose); |
| 1022 | continue; | 1042 | continue; |
| 1023 | } | 1043 | } |
| 1024 | /* Replace the old lock with the new one. | 1044 | /* |
| 1025 | * Wake up anybody waiting for the old one, | 1045 | * Replace the old lock with new_fl, and |
| 1026 | * as the change in lock type might satisfy | 1046 | * remove the old one. It's safe to do the |
| 1027 | * their needs. | 1047 | * insert here since we know that we won't be |
| 1048 | * using new_fl later, and that the lock is | ||
| 1049 | * just replacing an existing lock. | ||
| 1028 | */ | 1050 | */ |
| 1029 | locks_wake_up_blocks(fl); | 1051 | error = -ENOLCK; |
| 1030 | fl->fl_start = request->fl_start; | 1052 | if (!new_fl) |
| 1031 | fl->fl_end = request->fl_end; | 1053 | goto out; |
| 1032 | fl->fl_type = request->fl_type; | 1054 | locks_copy_lock(new_fl, request); |
| 1033 | locks_release_private(fl); | 1055 | request = new_fl; |
| 1034 | locks_copy_private(fl, request); | 1056 | new_fl = NULL; |
| 1035 | request = fl; | 1057 | locks_delete_lock(before, &dispose); |
| 1058 | locks_insert_lock(before, request); | ||
| 1036 | added = true; | 1059 | added = true; |
| 1037 | } | 1060 | } |
| 1038 | } | 1061 | } |
| @@ -1093,6 +1116,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str | |||
| 1093 | locks_free_lock(new_fl); | 1116 | locks_free_lock(new_fl); |
| 1094 | if (new_fl2) | 1117 | if (new_fl2) |
| 1095 | locks_free_lock(new_fl2); | 1118 | locks_free_lock(new_fl2); |
| 1119 | locks_dispose_list(&dispose); | ||
| 1096 | return error; | 1120 | return error; |
| 1097 | } | 1121 | } |
| 1098 | 1122 | ||
| @@ -1268,7 +1292,7 @@ int lease_modify(struct file_lock **before, int arg) | |||
| 1268 | printk(KERN_ERR "locks_delete_lock: fasync == %p\n", fl->fl_fasync); | 1292 | printk(KERN_ERR "locks_delete_lock: fasync == %p\n", fl->fl_fasync); |
| 1269 | fl->fl_fasync = NULL; | 1293 | fl->fl_fasync = NULL; |
| 1270 | } | 1294 | } |
| 1271 | locks_delete_lock(before); | 1295 | locks_delete_lock(before, NULL); |
| 1272 | } | 1296 | } |
| 1273 | return 0; | 1297 | return 0; |
| 1274 | } | 1298 | } |
| @@ -1737,13 +1761,10 @@ static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg) | |||
| 1737 | ret = fl; | 1761 | ret = fl; |
| 1738 | spin_lock(&inode->i_lock); | 1762 | spin_lock(&inode->i_lock); |
| 1739 | error = __vfs_setlease(filp, arg, &ret); | 1763 | error = __vfs_setlease(filp, arg, &ret); |
| 1740 | if (error) { | 1764 | if (error) |
| 1741 | spin_unlock(&inode->i_lock); | 1765 | goto out_unlock; |
| 1742 | locks_free_lock(fl); | 1766 | if (ret == fl) |
| 1743 | goto out_free_fasync; | 1767 | fl = NULL; |
| 1744 | } | ||
| 1745 | if (ret != fl) | ||
| 1746 | locks_free_lock(fl); | ||
| 1747 | 1768 | ||
| 1748 | /* | 1769 | /* |
| 1749 | * fasync_insert_entry() returns the old entry if any. | 1770 | * fasync_insert_entry() returns the old entry if any. |
| @@ -1755,9 +1776,10 @@ static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg) | |||
| 1755 | new = NULL; | 1776 | new = NULL; |
| 1756 | 1777 | ||
| 1757 | error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0); | 1778 | error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0); |
| 1779 | out_unlock: | ||
| 1758 | spin_unlock(&inode->i_lock); | 1780 | spin_unlock(&inode->i_lock); |
| 1759 | 1781 | if (fl) | |
| 1760 | out_free_fasync: | 1782 | locks_free_lock(fl); |
| 1761 | if (new) | 1783 | if (new) |
| 1762 | fasync_free(new); | 1784 | fasync_free(new); |
| 1763 | return error; | 1785 | return error; |
| @@ -2320,6 +2342,7 @@ void locks_remove_file(struct file *filp) | |||
| 2320 | struct inode * inode = file_inode(filp); | 2342 | struct inode * inode = file_inode(filp); |
| 2321 | struct file_lock *fl; | 2343 | struct file_lock *fl; |
| 2322 | struct file_lock **before; | 2344 | struct file_lock **before; |
| 2345 | LIST_HEAD(dispose); | ||
| 2323 | 2346 | ||
| 2324 | if (!inode->i_flock) | 2347 | if (!inode->i_flock) |
| 2325 | return; | 2348 | return; |
| @@ -2365,12 +2388,13 @@ void locks_remove_file(struct file *filp) | |||
| 2365 | fl->fl_type, fl->fl_flags, | 2388 | fl->fl_type, fl->fl_flags, |
| 2366 | fl->fl_start, fl->fl_end); | 2389 | fl->fl_start, fl->fl_end); |
| 2367 | 2390 | ||
| 2368 | locks_delete_lock(before); | 2391 | locks_delete_lock(before, &dispose); |
| 2369 | continue; | 2392 | continue; |
| 2370 | } | 2393 | } |
| 2371 | before = &fl->fl_next; | 2394 | before = &fl->fl_next; |
| 2372 | } | 2395 | } |
| 2373 | spin_unlock(&inode->i_lock); | 2396 | spin_unlock(&inode->i_lock); |
| 2397 | locks_dispose_list(&dispose); | ||
| 2374 | } | 2398 | } |
| 2375 | 2399 | ||
| 2376 | /** | 2400 | /** |
| @@ -2452,7 +2476,11 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl, | |||
| 2452 | seq_puts(f, "FLOCK ADVISORY "); | 2476 | seq_puts(f, "FLOCK ADVISORY "); |
| 2453 | } | 2477 | } |
| 2454 | } else if (IS_LEASE(fl)) { | 2478 | } else if (IS_LEASE(fl)) { |
| 2455 | seq_puts(f, "LEASE "); | 2479 | if (fl->fl_flags & FL_DELEG) |
| 2480 | seq_puts(f, "DELEG "); | ||
| 2481 | else | ||
| 2482 | seq_puts(f, "LEASE "); | ||
| 2483 | |||
| 2456 | if (lease_breaking(fl)) | 2484 | if (lease_breaking(fl)) |
| 2457 | seq_puts(f, "BREAKING "); | 2485 | seq_puts(f, "BREAKING "); |
| 2458 | else if (fl->fl_file) | 2486 | else if (fl->fl_file) |
diff --git a/fs/udf/namei.c b/fs/udf/namei.c index 9737cba1357d..83a06001742b 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c | |||
| @@ -1014,7 +1014,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, | |||
| 1014 | 1014 | ||
| 1015 | fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); | 1015 | fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); |
| 1016 | if (!fi) | 1016 | if (!fi) |
| 1017 | goto out_no_entry; | 1017 | goto out_fail; |
| 1018 | cfi.icb.extLength = cpu_to_le32(sb->s_blocksize); | 1018 | cfi.icb.extLength = cpu_to_le32(sb->s_blocksize); |
| 1019 | cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location); | 1019 | cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location); |
| 1020 | if (UDF_SB(inode->i_sb)->s_lvid_bh) { | 1020 | if (UDF_SB(inode->i_sb)->s_lvid_bh) { |
| @@ -1036,6 +1036,7 @@ out: | |||
| 1036 | 1036 | ||
| 1037 | out_no_entry: | 1037 | out_no_entry: |
| 1038 | up_write(&iinfo->i_data_sem); | 1038 | up_write(&iinfo->i_data_sem); |
| 1039 | out_fail: | ||
| 1039 | inode_dec_link_count(inode); | 1040 | inode_dec_link_count(inode); |
| 1040 | iput(inode); | 1041 | iput(inode); |
| 1041 | goto out; | 1042 | goto out; |
diff --git a/include/linux/edac.h b/include/linux/edac.h index 8e6c20af11a2..e1e68da6f35c 100644 --- a/include/linux/edac.h +++ b/include/linux/edac.h | |||
| @@ -194,6 +194,9 @@ static inline char *mc_event_error_type(const unsigned int err_type) | |||
| 194 | * @MEM_DDR3: DDR3 RAM | 194 | * @MEM_DDR3: DDR3 RAM |
| 195 | * @MEM_RDDR3: Registered DDR3 RAM | 195 | * @MEM_RDDR3: Registered DDR3 RAM |
| 196 | * This is a variant of the DDR3 memories. | 196 | * This is a variant of the DDR3 memories. |
| 197 | * @MEM_DDR4: DDR4 RAM | ||
| 198 | * @MEM_RDDR4: Registered DDR4 RAM | ||
| 199 | * This is a variant of the DDR4 memories. | ||
| 197 | */ | 200 | */ |
| 198 | enum mem_type { | 201 | enum mem_type { |
| 199 | MEM_EMPTY = 0, | 202 | MEM_EMPTY = 0, |
| @@ -213,6 +216,8 @@ enum mem_type { | |||
| 213 | MEM_XDR, | 216 | MEM_XDR, |
| 214 | MEM_DDR3, | 217 | MEM_DDR3, |
| 215 | MEM_RDDR3, | 218 | MEM_RDDR3, |
| 219 | MEM_DDR4, | ||
| 220 | MEM_RDDR4, | ||
| 216 | }; | 221 | }; |
| 217 | 222 | ||
| 218 | #define MEM_FLAG_EMPTY BIT(MEM_EMPTY) | 223 | #define MEM_FLAG_EMPTY BIT(MEM_EMPTY) |
diff --git a/include/linux/i2c.h b/include/linux/i2c.h index ea507665896c..a95efeb53a8b 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h | |||
| @@ -577,16 +577,20 @@ static inline struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node | |||
| 577 | } | 577 | } |
| 578 | #endif /* CONFIG_OF */ | 578 | #endif /* CONFIG_OF */ |
| 579 | 579 | ||
| 580 | #ifdef CONFIG_I2C_ACPI | 580 | #ifdef CONFIG_ACPI |
| 581 | int acpi_i2c_install_space_handler(struct i2c_adapter *adapter); | ||
| 582 | void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter); | ||
| 583 | void acpi_i2c_register_devices(struct i2c_adapter *adap); | 581 | void acpi_i2c_register_devices(struct i2c_adapter *adap); |
| 584 | #else | 582 | #else |
| 585 | static inline void acpi_i2c_register_devices(struct i2c_adapter *adap) { } | 583 | static inline void acpi_i2c_register_devices(struct i2c_adapter *adap) { } |
| 584 | #endif /* CONFIG_ACPI */ | ||
| 585 | |||
| 586 | #ifdef CONFIG_ACPI_I2C_OPREGION | ||
| 587 | int acpi_i2c_install_space_handler(struct i2c_adapter *adapter); | ||
| 588 | void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter); | ||
| 589 | #else | ||
| 586 | static inline void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter) | 590 | static inline void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter) |
| 587 | { } | 591 | { } |
| 588 | static inline int acpi_i2c_install_space_handler(struct i2c_adapter *adapter) | 592 | static inline int acpi_i2c_install_space_handler(struct i2c_adapter *adapter) |
| 589 | { return 0; } | 593 | { return 0; } |
| 590 | #endif | 594 | #endif /* CONFIG_ACPI_I2C_OPREGION */ |
| 591 | 595 | ||
| 592 | #endif /* _LINUX_I2C_H */ | 596 | #endif /* _LINUX_I2C_H */ |
diff --git a/include/linux/input/mt.h b/include/linux/input/mt.h index 1b1dfa80d9ff..f583ff639776 100644 --- a/include/linux/input/mt.h +++ b/include/linux/input/mt.h | |||
| @@ -105,6 +105,7 @@ void input_mt_report_slot_state(struct input_dev *dev, | |||
| 105 | 105 | ||
| 106 | void input_mt_report_finger_count(struct input_dev *dev, int count); | 106 | void input_mt_report_finger_count(struct input_dev *dev, int count); |
| 107 | void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count); | 107 | void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count); |
| 108 | void input_mt_drop_unused(struct input_dev *dev); | ||
| 108 | 109 | ||
| 109 | void input_mt_sync_frame(struct input_dev *dev); | 110 | void input_mt_sync_frame(struct input_dev *dev); |
| 110 | 111 | ||
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h index fd0421c6d40a..95ed9424a11a 100644 --- a/include/scsi/iscsi_if.h +++ b/include/scsi/iscsi_if.h | |||
| @@ -527,6 +527,7 @@ enum iscsi_err { | |||
| 527 | ISCSI_ERR_XMIT_FAILED = ISCSI_ERR_BASE + 19, | 527 | ISCSI_ERR_XMIT_FAILED = ISCSI_ERR_BASE + 19, |
| 528 | ISCSI_ERR_TCP_CONN_CLOSE = ISCSI_ERR_BASE + 20, | 528 | ISCSI_ERR_TCP_CONN_CLOSE = ISCSI_ERR_BASE + 20, |
| 529 | ISCSI_ERR_SCSI_EH_SESSION_RST = ISCSI_ERR_BASE + 21, | 529 | ISCSI_ERR_SCSI_EH_SESSION_RST = ISCSI_ERR_BASE + 21, |
| 530 | ISCSI_ERR_NOP_TIMEDOUT = ISCSI_ERR_BASE + 22, | ||
| 530 | }; | 531 | }; |
| 531 | 532 | ||
| 532 | /* | 533 | /* |
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h index f1afd607f043..11d11bc5c78f 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h | |||
| @@ -703,9 +703,11 @@ __SYSCALL(__NR_renameat2, sys_renameat2) | |||
| 703 | __SYSCALL(__NR_seccomp, sys_seccomp) | 703 | __SYSCALL(__NR_seccomp, sys_seccomp) |
| 704 | #define __NR_getrandom 278 | 704 | #define __NR_getrandom 278 |
| 705 | __SYSCALL(__NR_getrandom, sys_getrandom) | 705 | __SYSCALL(__NR_getrandom, sys_getrandom) |
| 706 | #define __NR_memfd_create 279 | ||
| 707 | __SYSCALL(__NR_memfd_create, sys_memfd_create) | ||
| 706 | 708 | ||
| 707 | #undef __NR_syscalls | 709 | #undef __NR_syscalls |
| 708 | #define __NR_syscalls 279 | 710 | #define __NR_syscalls 280 |
| 709 | 711 | ||
| 710 | /* | 712 | /* |
| 711 | * All syscalls below here should go away really, | 713 | * All syscalls below here should go away really, |
diff --git a/kernel/module.c b/kernel/module.c index 6f69463f0066..03214bd288e9 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -3304,6 +3304,11 @@ static int load_module(struct load_info *info, const char __user *uargs, | |||
| 3304 | mutex_lock(&module_mutex); | 3304 | mutex_lock(&module_mutex); |
| 3305 | module_bug_cleanup(mod); | 3305 | module_bug_cleanup(mod); |
| 3306 | mutex_unlock(&module_mutex); | 3306 | mutex_unlock(&module_mutex); |
| 3307 | |||
| 3308 | /* we can't deallocate the module until we clear memory protection */ | ||
| 3309 | unset_module_init_ro_nx(mod); | ||
| 3310 | unset_module_core_ro_nx(mod); | ||
| 3311 | |||
| 3307 | ddebug_cleanup: | 3312 | ddebug_cleanup: |
| 3308 | dynamic_debug_remove(info->debug); | 3313 | dynamic_debug_remove(info->debug); |
| 3309 | synchronize_sched(); | 3314 | synchronize_sched(); |
diff --git a/sound/oss/uart401.c b/sound/oss/uart401.c index 62b8869f5a4c..279bc565ac7e 100644 --- a/sound/oss/uart401.c +++ b/sound/oss/uart401.c | |||
| @@ -30,7 +30,7 @@ | |||
| 30 | 30 | ||
| 31 | #include "mpu401.h" | 31 | #include "mpu401.h" |
| 32 | 32 | ||
| 33 | typedef struct uart401_devc | 33 | struct uart401_devc |
| 34 | { | 34 | { |
| 35 | int base; | 35 | int base; |
| 36 | int irq; | 36 | int irq; |
| @@ -41,14 +41,13 @@ typedef struct uart401_devc | |||
| 41 | int my_dev; | 41 | int my_dev; |
| 42 | int share_irq; | 42 | int share_irq; |
| 43 | spinlock_t lock; | 43 | spinlock_t lock; |
| 44 | } | 44 | }; |
| 45 | uart401_devc; | ||
| 46 | 45 | ||
| 47 | #define DATAPORT (devc->base) | 46 | #define DATAPORT (devc->base) |
| 48 | #define COMDPORT (devc->base+1) | 47 | #define COMDPORT (devc->base+1) |
| 49 | #define STATPORT (devc->base+1) | 48 | #define STATPORT (devc->base+1) |
| 50 | 49 | ||
| 51 | static int uart401_status(uart401_devc * devc) | 50 | static int uart401_status(struct uart401_devc *devc) |
| 52 | { | 51 | { |
| 53 | return inb(STATPORT); | 52 | return inb(STATPORT); |
| 54 | } | 53 | } |
| @@ -56,17 +55,17 @@ static int uart401_status(uart401_devc * devc) | |||
| 56 | #define input_avail(devc) (!(uart401_status(devc)&INPUT_AVAIL)) | 55 | #define input_avail(devc) (!(uart401_status(devc)&INPUT_AVAIL)) |
| 57 | #define output_ready(devc) (!(uart401_status(devc)&OUTPUT_READY)) | 56 | #define output_ready(devc) (!(uart401_status(devc)&OUTPUT_READY)) |
| 58 | 57 | ||
| 59 | static void uart401_cmd(uart401_devc * devc, unsigned char cmd) | 58 | static void uart401_cmd(struct uart401_devc *devc, unsigned char cmd) |
| 60 | { | 59 | { |
| 61 | outb((cmd), COMDPORT); | 60 | outb((cmd), COMDPORT); |
| 62 | } | 61 | } |
| 63 | 62 | ||
| 64 | static int uart401_read(uart401_devc * devc) | 63 | static int uart401_read(struct uart401_devc *devc) |
| 65 | { | 64 | { |
| 66 | return inb(DATAPORT); | 65 | return inb(DATAPORT); |
| 67 | } | 66 | } |
| 68 | 67 | ||
| 69 | static void uart401_write(uart401_devc * devc, unsigned char byte) | 68 | static void uart401_write(struct uart401_devc *devc, unsigned char byte) |
| 70 | { | 69 | { |
| 71 | outb((byte), DATAPORT); | 70 | outb((byte), DATAPORT); |
| 72 | } | 71 | } |
| @@ -77,10 +76,10 @@ static void uart401_write(uart401_devc * devc, unsigned char byte) | |||
| 77 | #define MPU_RESET 0xFF | 76 | #define MPU_RESET 0xFF |
| 78 | #define UART_MODE_ON 0x3F | 77 | #define UART_MODE_ON 0x3F |
| 79 | 78 | ||
| 80 | static int reset_uart401(uart401_devc * devc); | 79 | static int reset_uart401(struct uart401_devc *devc); |
| 81 | static void enter_uart_mode(uart401_devc * devc); | 80 | static void enter_uart_mode(struct uart401_devc *devc); |
| 82 | 81 | ||
| 83 | static void uart401_input_loop(uart401_devc * devc) | 82 | static void uart401_input_loop(struct uart401_devc *devc) |
| 84 | { | 83 | { |
| 85 | int work_limit=30000; | 84 | int work_limit=30000; |
| 86 | 85 | ||
| @@ -99,7 +98,7 @@ static void uart401_input_loop(uart401_devc * devc) | |||
| 99 | 98 | ||
| 100 | irqreturn_t uart401intr(int irq, void *dev_id) | 99 | irqreturn_t uart401intr(int irq, void *dev_id) |
| 101 | { | 100 | { |
| 102 | uart401_devc *devc = dev_id; | 101 | struct uart401_devc *devc = dev_id; |
| 103 | 102 | ||
| 104 | if (devc == NULL) | 103 | if (devc == NULL) |
| 105 | { | 104 | { |
| @@ -118,7 +117,8 @@ uart401_open(int dev, int mode, | |||
| 118 | void (*output) (int dev) | 117 | void (*output) (int dev) |
| 119 | ) | 118 | ) |
| 120 | { | 119 | { |
| 121 | uart401_devc *devc = (uart401_devc *) midi_devs[dev]->devc; | 120 | struct uart401_devc *devc = (struct uart401_devc *) |
| 121 | midi_devs[dev]->devc; | ||
| 122 | 122 | ||
| 123 | if (devc->opened) | 123 | if (devc->opened) |
| 124 | return -EBUSY; | 124 | return -EBUSY; |
| @@ -138,7 +138,8 @@ uart401_open(int dev, int mode, | |||
| 138 | 138 | ||
| 139 | static void uart401_close(int dev) | 139 | static void uart401_close(int dev) |
| 140 | { | 140 | { |
| 141 | uart401_devc *devc = (uart401_devc *) midi_devs[dev]->devc; | 141 | struct uart401_devc *devc = (struct uart401_devc *) |
| 142 | midi_devs[dev]->devc; | ||
| 142 | 143 | ||
| 143 | reset_uart401(devc); | 144 | reset_uart401(devc); |
| 144 | devc->opened = 0; | 145 | devc->opened = 0; |
| @@ -148,7 +149,8 @@ static int uart401_out(int dev, unsigned char midi_byte) | |||
| 148 | { | 149 | { |
| 149 | int timeout; | 150 | int timeout; |
| 150 | unsigned long flags; | 151 | unsigned long flags; |
| 151 | uart401_devc *devc = (uart401_devc *) midi_devs[dev]->devc; | 152 | struct uart401_devc *devc = (struct uart401_devc *) |
| 153 | midi_devs[dev]->devc; | ||
| 152 | 154 | ||
| 153 | if (devc->disabled) | 155 | if (devc->disabled) |
| 154 | return 1; | 156 | return 1; |
| @@ -219,7 +221,7 @@ static const struct midi_operations uart401_operations = | |||
| 219 | .buffer_status = uart401_buffer_status, | 221 | .buffer_status = uart401_buffer_status, |
| 220 | }; | 222 | }; |
| 221 | 223 | ||
| 222 | static void enter_uart_mode(uart401_devc * devc) | 224 | static void enter_uart_mode(struct uart401_devc *devc) |
| 223 | { | 225 | { |
| 224 | int ok, timeout; | 226 | int ok, timeout; |
| 225 | unsigned long flags; | 227 | unsigned long flags; |
| @@ -241,7 +243,7 @@ static void enter_uart_mode(uart401_devc * devc) | |||
| 241 | spin_unlock_irqrestore(&devc->lock,flags); | 243 | spin_unlock_irqrestore(&devc->lock,flags); |
| 242 | } | 244 | } |
| 243 | 245 | ||
| 244 | static int reset_uart401(uart401_devc * devc) | 246 | static int reset_uart401(struct uart401_devc *devc) |
| 245 | { | 247 | { |
| 246 | int ok, timeout, n; | 248 | int ok, timeout, n; |
| 247 | 249 | ||
| @@ -285,7 +287,7 @@ static int reset_uart401(uart401_devc * devc) | |||
| 285 | 287 | ||
| 286 | int probe_uart401(struct address_info *hw_config, struct module *owner) | 288 | int probe_uart401(struct address_info *hw_config, struct module *owner) |
| 287 | { | 289 | { |
| 288 | uart401_devc *devc; | 290 | struct uart401_devc *devc; |
| 289 | char *name = "MPU-401 (UART) MIDI"; | 291 | char *name = "MPU-401 (UART) MIDI"; |
| 290 | int ok = 0; | 292 | int ok = 0; |
| 291 | unsigned long flags; | 293 | unsigned long flags; |
| @@ -300,7 +302,7 @@ int probe_uart401(struct address_info *hw_config, struct module *owner) | |||
| 300 | return 0; | 302 | return 0; |
| 301 | } | 303 | } |
| 302 | 304 | ||
| 303 | devc = kmalloc(sizeof(uart401_devc), GFP_KERNEL); | 305 | devc = kmalloc(sizeof(struct uart401_devc), GFP_KERNEL); |
| 304 | if (!devc) { | 306 | if (!devc) { |
| 305 | printk(KERN_WARNING "uart401: Can't allocate memory\n"); | 307 | printk(KERN_WARNING "uart401: Can't allocate memory\n"); |
| 306 | goto cleanup_region; | 308 | goto cleanup_region; |
| @@ -392,7 +394,7 @@ cleanup_region: | |||
| 392 | 394 | ||
| 393 | void unload_uart401(struct address_info *hw_config) | 395 | void unload_uart401(struct address_info *hw_config) |
| 394 | { | 396 | { |
| 395 | uart401_devc *devc; | 397 | struct uart401_devc *devc; |
| 396 | int n=hw_config->slots[4]; | 398 | int n=hw_config->slots[4]; |
| 397 | 399 | ||
| 398 | /* Not set up */ | 400 | /* Not set up */ |
diff --git a/sound/oss/waveartist.c b/sound/oss/waveartist.c index 672af8b56542..b36ea47527e8 100644 --- a/sound/oss/waveartist.c +++ b/sound/oss/waveartist.c | |||
| @@ -92,7 +92,7 @@ static unsigned short levels[SOUND_MIXER_NRDEVICES] = { | |||
| 92 | 0x0000 /* Monitor */ | 92 | 0x0000 /* Monitor */ |
| 93 | }; | 93 | }; |
| 94 | 94 | ||
| 95 | typedef struct { | 95 | struct wavnc_info { |
| 96 | struct address_info hw; /* hardware */ | 96 | struct address_info hw; /* hardware */ |
| 97 | char *chip_name; | 97 | char *chip_name; |
| 98 | 98 | ||
| @@ -119,7 +119,7 @@ typedef struct { | |||
| 119 | unsigned int line_mute_state :1;/* set by ioctl or autoselect */ | 119 | unsigned int line_mute_state :1;/* set by ioctl or autoselect */ |
| 120 | unsigned int use_slider :1;/* use slider setting for o/p vol */ | 120 | unsigned int use_slider :1;/* use slider setting for o/p vol */ |
| 121 | #endif | 121 | #endif |
| 122 | } wavnc_info; | 122 | }; |
| 123 | 123 | ||
| 124 | /* | 124 | /* |
| 125 | * This is the implementation specific mixer information. | 125 | * This is the implementation specific mixer information. |
| @@ -129,29 +129,30 @@ struct waveartist_mixer_info { | |||
| 129 | unsigned int recording_devs; /* Recordable devies */ | 129 | unsigned int recording_devs; /* Recordable devies */ |
| 130 | unsigned int stereo_devs; /* Stereo devices */ | 130 | unsigned int stereo_devs; /* Stereo devices */ |
| 131 | 131 | ||
| 132 | unsigned int (*select_input)(wavnc_info *, unsigned int, | 132 | unsigned int (*select_input)(struct wavnc_info *, unsigned int, |
| 133 | unsigned char *, unsigned char *); | 133 | unsigned char *, unsigned char *); |
| 134 | int (*decode_mixer)(wavnc_info *, int, | 134 | int (*decode_mixer)(struct wavnc_info *, int, |
| 135 | unsigned char, unsigned char); | 135 | unsigned char, unsigned char); |
| 136 | int (*get_mixer)(wavnc_info *, int); | 136 | int (*get_mixer)(struct wavnc_info *, int); |
| 137 | }; | 137 | }; |
| 138 | 138 | ||
| 139 | typedef struct wavnc_port_info { | 139 | struct wavnc_port_info { |
| 140 | int open_mode; | 140 | int open_mode; |
| 141 | int speed; | 141 | int speed; |
| 142 | int channels; | 142 | int channels; |
| 143 | int audio_format; | 143 | int audio_format; |
| 144 | } wavnc_port_info; | 144 | }; |
| 145 | 145 | ||
| 146 | static int nr_waveartist_devs; | 146 | static int nr_waveartist_devs; |
| 147 | static wavnc_info adev_info[MAX_AUDIO_DEV]; | 147 | static struct wavnc_info adev_info[MAX_AUDIO_DEV]; |
| 148 | static DEFINE_SPINLOCK(waveartist_lock); | 148 | static DEFINE_SPINLOCK(waveartist_lock); |
| 149 | 149 | ||
| 150 | #ifndef CONFIG_ARCH_NETWINDER | 150 | #ifndef CONFIG_ARCH_NETWINDER |
| 151 | #define machine_is_netwinder() 0 | 151 | #define machine_is_netwinder() 0 |
| 152 | #else | 152 | #else |
| 153 | static struct timer_list vnc_timer; | 153 | static struct timer_list vnc_timer; |
| 154 | static void vnc_configure_mixer(wavnc_info *devc, unsigned int input_mask); | 154 | static void vnc_configure_mixer(struct wavnc_info *devc, |
| 155 | unsigned int input_mask); | ||
| 155 | static int vnc_private_ioctl(int dev, unsigned int cmd, int __user *arg); | 156 | static int vnc_private_ioctl(int dev, unsigned int cmd, int __user *arg); |
| 156 | static void vnc_slider_tick(unsigned long data); | 157 | static void vnc_slider_tick(unsigned long data); |
| 157 | #endif | 158 | #endif |
| @@ -169,7 +170,7 @@ waveartist_set_ctlr(struct address_info *hw, unsigned char clear, unsigned char | |||
| 169 | /* Toggle IRQ acknowledge line | 170 | /* Toggle IRQ acknowledge line |
| 170 | */ | 171 | */ |
| 171 | static inline void | 172 | static inline void |
| 172 | waveartist_iack(wavnc_info *devc) | 173 | waveartist_iack(struct wavnc_info *devc) |
| 173 | { | 174 | { |
| 174 | unsigned int ctlr_port = devc->hw.io_base + CTLR; | 175 | unsigned int ctlr_port = devc->hw.io_base + CTLR; |
| 175 | int old_ctlr; | 176 | int old_ctlr; |
| @@ -188,7 +189,7 @@ waveartist_sleep(int timeout_ms) | |||
| 188 | } | 189 | } |
| 189 | 190 | ||
| 190 | static int | 191 | static int |
| 191 | waveartist_reset(wavnc_info *devc) | 192 | waveartist_reset(struct wavnc_info *devc) |
| 192 | { | 193 | { |
| 193 | struct address_info *hw = &devc->hw; | 194 | struct address_info *hw = &devc->hw; |
| 194 | unsigned int timeout, res = -1; | 195 | unsigned int timeout, res = -1; |
| @@ -223,7 +224,7 @@ waveartist_reset(wavnc_info *devc) | |||
| 223 | * and can send or receive multiple words. | 224 | * and can send or receive multiple words. |
| 224 | */ | 225 | */ |
| 225 | static int | 226 | static int |
| 226 | waveartist_cmd(wavnc_info *devc, | 227 | waveartist_cmd(struct wavnc_info *devc, |
| 227 | int nr_cmd, unsigned int *cmd, | 228 | int nr_cmd, unsigned int *cmd, |
| 228 | int nr_resp, unsigned int *resp) | 229 | int nr_resp, unsigned int *resp) |
| 229 | { | 230 | { |
| @@ -299,7 +300,7 @@ waveartist_cmd(wavnc_info *devc, | |||
| 299 | * Send one command word | 300 | * Send one command word |
| 300 | */ | 301 | */ |
| 301 | static inline int | 302 | static inline int |
| 302 | waveartist_cmd1(wavnc_info *devc, unsigned int cmd) | 303 | waveartist_cmd1(struct wavnc_info *devc, unsigned int cmd) |
| 303 | { | 304 | { |
| 304 | return waveartist_cmd(devc, 1, &cmd, 0, NULL); | 305 | return waveartist_cmd(devc, 1, &cmd, 0, NULL); |
| 305 | } | 306 | } |
| @@ -308,7 +309,7 @@ waveartist_cmd1(wavnc_info *devc, unsigned int cmd) | |||
| 308 | * Send one command, receive one word | 309 | * Send one command, receive one word |
| 309 | */ | 310 | */ |
| 310 | static inline unsigned int | 311 | static inline unsigned int |
| 311 | waveartist_cmd1_r(wavnc_info *devc, unsigned int cmd) | 312 | waveartist_cmd1_r(struct wavnc_info *devc, unsigned int cmd) |
| 312 | { | 313 | { |
| 313 | unsigned int ret; | 314 | unsigned int ret; |
| 314 | 315 | ||
| @@ -322,7 +323,7 @@ waveartist_cmd1_r(wavnc_info *devc, unsigned int cmd) | |||
| 322 | * word (and throw it away) | 323 | * word (and throw it away) |
| 323 | */ | 324 | */ |
| 324 | static inline int | 325 | static inline int |
| 325 | waveartist_cmd2(wavnc_info *devc, unsigned int cmd, unsigned int arg) | 326 | waveartist_cmd2(struct wavnc_info *devc, unsigned int cmd, unsigned int arg) |
| 326 | { | 327 | { |
| 327 | unsigned int vals[2]; | 328 | unsigned int vals[2]; |
| 328 | 329 | ||
| @@ -336,7 +337,7 @@ waveartist_cmd2(wavnc_info *devc, unsigned int cmd, unsigned int arg) | |||
| 336 | * Send a triple command | 337 | * Send a triple command |
| 337 | */ | 338 | */ |
| 338 | static inline int | 339 | static inline int |
| 339 | waveartist_cmd3(wavnc_info *devc, unsigned int cmd, | 340 | waveartist_cmd3(struct wavnc_info *devc, unsigned int cmd, |
| 340 | unsigned int arg1, unsigned int arg2) | 341 | unsigned int arg1, unsigned int arg2) |
| 341 | { | 342 | { |
| 342 | unsigned int vals[3]; | 343 | unsigned int vals[3]; |
| @@ -349,7 +350,7 @@ waveartist_cmd3(wavnc_info *devc, unsigned int cmd, | |||
| 349 | } | 350 | } |
| 350 | 351 | ||
| 351 | static int | 352 | static int |
| 352 | waveartist_getrev(wavnc_info *devc, char *rev) | 353 | waveartist_getrev(struct wavnc_info *devc, char *rev) |
| 353 | { | 354 | { |
| 354 | unsigned int temp[2]; | 355 | unsigned int temp[2]; |
| 355 | unsigned int cmd = WACMD_GETREV; | 356 | unsigned int cmd = WACMD_GETREV; |
| @@ -371,15 +372,15 @@ static void waveartist_trigger(int dev, int state); | |||
| 371 | static int | 372 | static int |
| 372 | waveartist_open(int dev, int mode) | 373 | waveartist_open(int dev, int mode) |
| 373 | { | 374 | { |
| 374 | wavnc_info *devc; | 375 | struct wavnc_info *devc; |
| 375 | wavnc_port_info *portc; | 376 | struct wavnc_port_info *portc; |
| 376 | unsigned long flags; | 377 | unsigned long flags; |
| 377 | 378 | ||
| 378 | if (dev < 0 || dev >= num_audiodevs) | 379 | if (dev < 0 || dev >= num_audiodevs) |
| 379 | return -ENXIO; | 380 | return -ENXIO; |
| 380 | 381 | ||
| 381 | devc = (wavnc_info *) audio_devs[dev]->devc; | 382 | devc = (struct wavnc_info *) audio_devs[dev]->devc; |
| 382 | portc = (wavnc_port_info *) audio_devs[dev]->portc; | 383 | portc = (struct wavnc_port_info *) audio_devs[dev]->portc; |
| 383 | 384 | ||
| 384 | spin_lock_irqsave(&waveartist_lock, flags); | 385 | spin_lock_irqsave(&waveartist_lock, flags); |
| 385 | if (portc->open_mode || (devc->open_mode & mode)) { | 386 | if (portc->open_mode || (devc->open_mode & mode)) { |
| @@ -404,8 +405,10 @@ waveartist_open(int dev, int mode) | |||
| 404 | static void | 405 | static void |
| 405 | waveartist_close(int dev) | 406 | waveartist_close(int dev) |
| 406 | { | 407 | { |
| 407 | wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc; | 408 | struct wavnc_info *devc = (struct wavnc_info *) |
| 408 | wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; | 409 | audio_devs[dev]->devc; |
| 410 | struct wavnc_port_info *portc = (struct wavnc_port_info *) | ||
| 411 | audio_devs[dev]->portc; | ||
| 409 | unsigned long flags; | 412 | unsigned long flags; |
| 410 | 413 | ||
| 411 | spin_lock_irqsave(&waveartist_lock, flags); | 414 | spin_lock_irqsave(&waveartist_lock, flags); |
| @@ -422,8 +425,10 @@ waveartist_close(int dev) | |||
| 422 | static void | 425 | static void |
| 423 | waveartist_output_block(int dev, unsigned long buf, int __count, int intrflag) | 426 | waveartist_output_block(int dev, unsigned long buf, int __count, int intrflag) |
| 424 | { | 427 | { |
| 425 | wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; | 428 | struct wavnc_port_info *portc = (struct wavnc_port_info *) |
| 426 | wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc; | 429 | audio_devs[dev]->portc; |
| 430 | struct wavnc_info *devc = (struct wavnc_info *) | ||
| 431 | audio_devs[dev]->devc; | ||
| 427 | unsigned long flags; | 432 | unsigned long flags; |
| 428 | unsigned int count = __count; | 433 | unsigned int count = __count; |
| 429 | 434 | ||
| @@ -467,8 +472,10 @@ waveartist_output_block(int dev, unsigned long buf, int __count, int intrflag) | |||
| 467 | static void | 472 | static void |
| 468 | waveartist_start_input(int dev, unsigned long buf, int __count, int intrflag) | 473 | waveartist_start_input(int dev, unsigned long buf, int __count, int intrflag) |
| 469 | { | 474 | { |
| 470 | wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; | 475 | struct wavnc_port_info *portc = (struct wavnc_port_info *) |
| 471 | wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc; | 476 | audio_devs[dev]->portc; |
| 477 | struct wavnc_info *devc = (struct wavnc_info *) | ||
| 478 | audio_devs[dev]->devc; | ||
| 472 | unsigned long flags; | 479 | unsigned long flags; |
| 473 | unsigned int count = __count; | 480 | unsigned int count = __count; |
| 474 | 481 | ||
| @@ -514,7 +521,7 @@ waveartist_ioctl(int dev, unsigned int cmd, void __user * arg) | |||
| 514 | } | 521 | } |
| 515 | 522 | ||
| 516 | static unsigned int | 523 | static unsigned int |
| 517 | waveartist_get_speed(wavnc_port_info *portc) | 524 | waveartist_get_speed(struct wavnc_port_info *portc) |
| 518 | { | 525 | { |
| 519 | unsigned int speed; | 526 | unsigned int speed; |
| 520 | 527 | ||
| @@ -542,7 +549,7 @@ waveartist_get_speed(wavnc_port_info *portc) | |||
| 542 | } | 549 | } |
| 543 | 550 | ||
| 544 | static unsigned int | 551 | static unsigned int |
| 545 | waveartist_get_bits(wavnc_port_info *portc) | 552 | waveartist_get_bits(struct wavnc_port_info *portc) |
| 546 | { | 553 | { |
| 547 | unsigned int bits; | 554 | unsigned int bits; |
| 548 | 555 | ||
| @@ -560,8 +567,10 @@ static int | |||
| 560 | waveartist_prepare_for_input(int dev, int bsize, int bcount) | 567 | waveartist_prepare_for_input(int dev, int bsize, int bcount) |
| 561 | { | 568 | { |
| 562 | unsigned long flags; | 569 | unsigned long flags; |
| 563 | wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc; | 570 | struct wavnc_info *devc = (struct wavnc_info *) |
| 564 | wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; | 571 | audio_devs[dev]->devc; |
| 572 | struct wavnc_port_info *portc = (struct wavnc_port_info *) | ||
| 573 | audio_devs[dev]->portc; | ||
| 565 | unsigned int speed, bits; | 574 | unsigned int speed, bits; |
| 566 | 575 | ||
| 567 | if (devc->audio_mode) | 576 | if (devc->audio_mode) |
| @@ -615,8 +624,10 @@ static int | |||
| 615 | waveartist_prepare_for_output(int dev, int bsize, int bcount) | 624 | waveartist_prepare_for_output(int dev, int bsize, int bcount) |
| 616 | { | 625 | { |
| 617 | unsigned long flags; | 626 | unsigned long flags; |
| 618 | wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc; | 627 | struct wavnc_info *devc = (struct wavnc_info *) |
| 619 | wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; | 628 | audio_devs[dev]->devc; |
| 629 | struct wavnc_port_info *portc = (struct wavnc_port_info *) | ||
| 630 | audio_devs[dev]->portc; | ||
| 620 | unsigned int speed, bits; | 631 | unsigned int speed, bits; |
| 621 | 632 | ||
| 622 | /* | 633 | /* |
| @@ -660,8 +671,9 @@ waveartist_prepare_for_output(int dev, int bsize, int bcount) | |||
| 660 | static void | 671 | static void |
| 661 | waveartist_halt(int dev) | 672 | waveartist_halt(int dev) |
| 662 | { | 673 | { |
| 663 | wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; | 674 | struct wavnc_port_info *portc = (struct wavnc_port_info *) |
| 664 | wavnc_info *devc; | 675 | audio_devs[dev]->portc; |
| 676 | struct wavnc_info *devc; | ||
| 665 | 677 | ||
| 666 | if (portc->open_mode & OPEN_WRITE) | 678 | if (portc->open_mode & OPEN_WRITE) |
| 667 | waveartist_halt_output(dev); | 679 | waveartist_halt_output(dev); |
| @@ -669,14 +681,15 @@ waveartist_halt(int dev) | |||
| 669 | if (portc->open_mode & OPEN_READ) | 681 | if (portc->open_mode & OPEN_READ) |
| 670 | waveartist_halt_input(dev); | 682 | waveartist_halt_input(dev); |
| 671 | 683 | ||
| 672 | devc = (wavnc_info *) audio_devs[dev]->devc; | 684 | devc = (struct wavnc_info *) audio_devs[dev]->devc; |
| 673 | devc->audio_mode = 0; | 685 | devc->audio_mode = 0; |
| 674 | } | 686 | } |
| 675 | 687 | ||
| 676 | static void | 688 | static void |
| 677 | waveartist_halt_input(int dev) | 689 | waveartist_halt_input(int dev) |
| 678 | { | 690 | { |
| 679 | wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc; | 691 | struct wavnc_info *devc = (struct wavnc_info *) |
| 692 | audio_devs[dev]->devc; | ||
| 680 | unsigned long flags; | 693 | unsigned long flags; |
| 681 | 694 | ||
| 682 | spin_lock_irqsave(&waveartist_lock, flags); | 695 | spin_lock_irqsave(&waveartist_lock, flags); |
| @@ -703,7 +716,8 @@ waveartist_halt_input(int dev) | |||
| 703 | static void | 716 | static void |
| 704 | waveartist_halt_output(int dev) | 717 | waveartist_halt_output(int dev) |
| 705 | { | 718 | { |
| 706 | wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc; | 719 | struct wavnc_info *devc = (struct wavnc_info *) |
| 720 | audio_devs[dev]->devc; | ||
| 707 | unsigned long flags; | 721 | unsigned long flags; |
| 708 | 722 | ||
| 709 | spin_lock_irqsave(&waveartist_lock, flags); | 723 | spin_lock_irqsave(&waveartist_lock, flags); |
| @@ -727,8 +741,10 @@ waveartist_halt_output(int dev) | |||
| 727 | static void | 741 | static void |
| 728 | waveartist_trigger(int dev, int state) | 742 | waveartist_trigger(int dev, int state) |
| 729 | { | 743 | { |
| 730 | wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc; | 744 | struct wavnc_info *devc = (struct wavnc_info *) |
| 731 | wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; | 745 | audio_devs[dev]->devc; |
| 746 | struct wavnc_port_info *portc = (struct wavnc_port_info *) | ||
| 747 | audio_devs[dev]->portc; | ||
| 732 | unsigned long flags; | 748 | unsigned long flags; |
| 733 | 749 | ||
| 734 | if (debug_flg & DEBUG_TRIGGER) { | 750 | if (debug_flg & DEBUG_TRIGGER) { |
| @@ -764,7 +780,8 @@ waveartist_trigger(int dev, int state) | |||
| 764 | static int | 780 | static int |
| 765 | waveartist_set_speed(int dev, int arg) | 781 | waveartist_set_speed(int dev, int arg) |
| 766 | { | 782 | { |
| 767 | wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; | 783 | struct wavnc_port_info *portc = (struct wavnc_port_info *) |
| 784 | audio_devs[dev]->portc; | ||
| 768 | 785 | ||
| 769 | if (arg <= 0) | 786 | if (arg <= 0) |
| 770 | return portc->speed; | 787 | return portc->speed; |
| @@ -782,7 +799,8 @@ waveartist_set_speed(int dev, int arg) | |||
| 782 | static short | 799 | static short |
| 783 | waveartist_set_channels(int dev, short arg) | 800 | waveartist_set_channels(int dev, short arg) |
| 784 | { | 801 | { |
| 785 | wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; | 802 | struct wavnc_port_info *portc = (struct wavnc_port_info *) |
| 803 | audio_devs[dev]->portc; | ||
| 786 | 804 | ||
| 787 | if (arg != 1 && arg != 2) | 805 | if (arg != 1 && arg != 2) |
| 788 | return portc->channels; | 806 | return portc->channels; |
| @@ -794,7 +812,8 @@ waveartist_set_channels(int dev, short arg) | |||
| 794 | static unsigned int | 812 | static unsigned int |
| 795 | waveartist_set_bits(int dev, unsigned int arg) | 813 | waveartist_set_bits(int dev, unsigned int arg) |
| 796 | { | 814 | { |
| 797 | wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; | 815 | struct wavnc_port_info *portc = (struct wavnc_port_info *) |
| 816 | audio_devs[dev]->portc; | ||
| 798 | 817 | ||
| 799 | if (arg == 0) | 818 | if (arg == 0) |
| 800 | return portc->audio_format; | 819 | return portc->audio_format; |
| @@ -829,7 +848,7 @@ static struct audio_driver waveartist_audio_driver = { | |||
| 829 | static irqreturn_t | 848 | static irqreturn_t |
| 830 | waveartist_intr(int irq, void *dev_id) | 849 | waveartist_intr(int irq, void *dev_id) |
| 831 | { | 850 | { |
| 832 | wavnc_info *devc = dev_id; | 851 | struct wavnc_info *devc = dev_id; |
| 833 | int irqstatus, status; | 852 | int irqstatus, status; |
| 834 | 853 | ||
| 835 | spin_lock(&waveartist_lock); | 854 | spin_lock(&waveartist_lock); |
| @@ -912,7 +931,7 @@ static const struct mix_ent mix_devs[SOUND_MIXER_NRDEVICES] = { | |||
| 912 | }; | 931 | }; |
| 913 | 932 | ||
| 914 | static void | 933 | static void |
| 915 | waveartist_mixer_update(wavnc_info *devc, int whichDev) | 934 | waveartist_mixer_update(struct wavnc_info *devc, int whichDev) |
| 916 | { | 935 | { |
| 917 | unsigned int lev_left, lev_right; | 936 | unsigned int lev_left, lev_right; |
| 918 | 937 | ||
| @@ -973,7 +992,8 @@ waveartist_mixer_update(wavnc_info *devc, int whichDev) | |||
| 973 | * relevant *_select_input function has done that for us. | 992 | * relevant *_select_input function has done that for us. |
| 974 | */ | 993 | */ |
| 975 | static void | 994 | static void |
| 976 | waveartist_set_adc_mux(wavnc_info *devc, char left_dev, char right_dev) | 995 | waveartist_set_adc_mux(struct wavnc_info *devc, char left_dev, |
| 996 | char right_dev) | ||
| 977 | { | 997 | { |
| 978 | unsigned int reg_08, reg_09; | 998 | unsigned int reg_08, reg_09; |
| 979 | 999 | ||
| @@ -996,7 +1016,7 @@ waveartist_set_adc_mux(wavnc_info *devc, char left_dev, char right_dev) | |||
| 996 | * SOUND_MASK_MIC Mic Microphone | 1016 | * SOUND_MASK_MIC Mic Microphone |
| 997 | */ | 1017 | */ |
| 998 | static unsigned int | 1018 | static unsigned int |
| 999 | waveartist_select_input(wavnc_info *devc, unsigned int recmask, | 1019 | waveartist_select_input(struct wavnc_info *devc, unsigned int recmask, |
| 1000 | unsigned char *dev_l, unsigned char *dev_r) | 1020 | unsigned char *dev_l, unsigned char *dev_r) |
| 1001 | { | 1021 | { |
| 1002 | unsigned int recdev = ADC_MUX_NONE; | 1022 | unsigned int recdev = ADC_MUX_NONE; |
| @@ -1024,7 +1044,8 @@ waveartist_select_input(wavnc_info *devc, unsigned int recmask, | |||
| 1024 | } | 1044 | } |
| 1025 | 1045 | ||
| 1026 | static int | 1046 | static int |
| 1027 | waveartist_decode_mixer(wavnc_info *devc, int dev, unsigned char lev_l, | 1047 | waveartist_decode_mixer(struct wavnc_info *devc, int dev, |
| 1048 | unsigned char lev_l, | ||
| 1028 | unsigned char lev_r) | 1049 | unsigned char lev_r) |
| 1029 | { | 1050 | { |
| 1030 | switch (dev) { | 1051 | switch (dev) { |
| @@ -1050,7 +1071,7 @@ waveartist_decode_mixer(wavnc_info *devc, int dev, unsigned char lev_l, | |||
| 1050 | return dev; | 1071 | return dev; |
| 1051 | } | 1072 | } |
| 1052 | 1073 | ||
| 1053 | static int waveartist_get_mixer(wavnc_info *devc, int dev) | 1074 | static int waveartist_get_mixer(struct wavnc_info *devc, int dev) |
| 1054 | { | 1075 | { |
| 1055 | return devc->levels[dev]; | 1076 | return devc->levels[dev]; |
| 1056 | } | 1077 | } |
| @@ -1068,7 +1089,7 @@ static const struct waveartist_mixer_info waveartist_mixer = { | |||
| 1068 | }; | 1089 | }; |
| 1069 | 1090 | ||
| 1070 | static void | 1091 | static void |
| 1071 | waveartist_set_recmask(wavnc_info *devc, unsigned int recmask) | 1092 | waveartist_set_recmask(struct wavnc_info *devc, unsigned int recmask) |
| 1072 | { | 1093 | { |
| 1073 | unsigned char dev_l, dev_r; | 1094 | unsigned char dev_l, dev_r; |
| 1074 | 1095 | ||
| @@ -1092,7 +1113,7 @@ waveartist_set_recmask(wavnc_info *devc, unsigned int recmask) | |||
| 1092 | } | 1113 | } |
| 1093 | 1114 | ||
| 1094 | static int | 1115 | static int |
| 1095 | waveartist_set_mixer(wavnc_info *devc, int dev, unsigned int level) | 1116 | waveartist_set_mixer(struct wavnc_info *devc, int dev, unsigned int level) |
| 1096 | { | 1117 | { |
| 1097 | unsigned int lev_left = level & 0x00ff; | 1118 | unsigned int lev_left = level & 0x00ff; |
| 1098 | unsigned int lev_right = (level & 0xff00) >> 8; | 1119 | unsigned int lev_right = (level & 0xff00) >> 8; |
| @@ -1120,7 +1141,7 @@ waveartist_set_mixer(wavnc_info *devc, int dev, unsigned int level) | |||
| 1120 | static int | 1141 | static int |
| 1121 | waveartist_mixer_ioctl(int dev, unsigned int cmd, void __user * arg) | 1142 | waveartist_mixer_ioctl(int dev, unsigned int cmd, void __user * arg) |
| 1122 | { | 1143 | { |
| 1123 | wavnc_info *devc = (wavnc_info *)audio_devs[dev]->devc; | 1144 | struct wavnc_info *devc = (struct wavnc_info *)audio_devs[dev]->devc; |
| 1124 | int ret = 0, val, nr; | 1145 | int ret = 0, val, nr; |
| 1125 | 1146 | ||
| 1126 | /* | 1147 | /* |
| @@ -1204,7 +1225,7 @@ static struct mixer_operations waveartist_mixer_operations = | |||
| 1204 | }; | 1225 | }; |
| 1205 | 1226 | ||
| 1206 | static void | 1227 | static void |
| 1207 | waveartist_mixer_reset(wavnc_info *devc) | 1228 | waveartist_mixer_reset(struct wavnc_info *devc) |
| 1208 | { | 1229 | { |
| 1209 | int i; | 1230 | int i; |
| 1210 | 1231 | ||
| @@ -1241,9 +1262,9 @@ waveartist_mixer_reset(wavnc_info *devc) | |||
| 1241 | waveartist_mixer_update(devc, i); | 1262 | waveartist_mixer_update(devc, i); |
| 1242 | } | 1263 | } |
| 1243 | 1264 | ||
| 1244 | static int __init waveartist_init(wavnc_info *devc) | 1265 | static int __init waveartist_init(struct wavnc_info *devc) |
| 1245 | { | 1266 | { |
| 1246 | wavnc_port_info *portc; | 1267 | struct wavnc_port_info *portc; |
| 1247 | char rev[3], dev_name[64]; | 1268 | char rev[3], dev_name[64]; |
| 1248 | int my_dev; | 1269 | int my_dev; |
| 1249 | 1270 | ||
| @@ -1261,7 +1282,7 @@ static int __init waveartist_init(wavnc_info *devc) | |||
| 1261 | conf_printf2(dev_name, devc->hw.io_base, devc->hw.irq, | 1282 | conf_printf2(dev_name, devc->hw.io_base, devc->hw.irq, |
| 1262 | devc->hw.dma, devc->hw.dma2); | 1283 | devc->hw.dma, devc->hw.dma2); |
| 1263 | 1284 | ||
| 1264 | portc = kzalloc(sizeof(wavnc_port_info), GFP_KERNEL); | 1285 | portc = kzalloc(sizeof(struct wavnc_port_info), GFP_KERNEL); |
| 1265 | if (portc == NULL) | 1286 | if (portc == NULL) |
| 1266 | goto nomem; | 1287 | goto nomem; |
| 1267 | 1288 | ||
| @@ -1330,7 +1351,7 @@ nomem: | |||
| 1330 | 1351 | ||
| 1331 | static int __init probe_waveartist(struct address_info *hw_config) | 1352 | static int __init probe_waveartist(struct address_info *hw_config) |
| 1332 | { | 1353 | { |
| 1333 | wavnc_info *devc = &adev_info[nr_waveartist_devs]; | 1354 | struct wavnc_info *devc = &adev_info[nr_waveartist_devs]; |
| 1334 | 1355 | ||
| 1335 | if (nr_waveartist_devs >= MAX_AUDIO_DEV) { | 1356 | if (nr_waveartist_devs >= MAX_AUDIO_DEV) { |
| 1336 | printk(KERN_WARNING "waveartist: too many audio devices\n"); | 1357 | printk(KERN_WARNING "waveartist: too many audio devices\n"); |
| @@ -1367,7 +1388,7 @@ static int __init probe_waveartist(struct address_info *hw_config) | |||
| 1367 | static void __init | 1388 | static void __init |
| 1368 | attach_waveartist(struct address_info *hw, const struct waveartist_mixer_info *mix) | 1389 | attach_waveartist(struct address_info *hw, const struct waveartist_mixer_info *mix) |
| 1369 | { | 1390 | { |
| 1370 | wavnc_info *devc = &adev_info[nr_waveartist_devs]; | 1391 | struct wavnc_info *devc = &adev_info[nr_waveartist_devs]; |
| 1371 | 1392 | ||
| 1372 | /* | 1393 | /* |
| 1373 | * NOTE! If irq < 0, there is another driver which has allocated the | 1394 | * NOTE! If irq < 0, there is another driver which has allocated the |
| @@ -1410,7 +1431,7 @@ attach_waveartist(struct address_info *hw, const struct waveartist_mixer_info *m | |||
| 1410 | 1431 | ||
| 1411 | static void __exit unload_waveartist(struct address_info *hw) | 1432 | static void __exit unload_waveartist(struct address_info *hw) |
| 1412 | { | 1433 | { |
| 1413 | wavnc_info *devc = NULL; | 1434 | struct wavnc_info *devc = NULL; |
| 1414 | int i; | 1435 | int i; |
| 1415 | 1436 | ||
| 1416 | for (i = 0; i < nr_waveartist_devs; i++) | 1437 | for (i = 0; i < nr_waveartist_devs; i++) |
| @@ -1478,7 +1499,7 @@ static void __exit unload_waveartist(struct address_info *hw) | |||
| 1478 | #define VNC_DISABLE_AUTOSWITCH 0x80 | 1499 | #define VNC_DISABLE_AUTOSWITCH 0x80 |
| 1479 | 1500 | ||
| 1480 | static inline void | 1501 | static inline void |
| 1481 | vnc_mute_spkr(wavnc_info *devc) | 1502 | vnc_mute_spkr(struct wavnc_info *devc) |
| 1482 | { | 1503 | { |
| 1483 | unsigned long flags; | 1504 | unsigned long flags; |
| 1484 | 1505 | ||
| @@ -1488,7 +1509,7 @@ vnc_mute_spkr(wavnc_info *devc) | |||
| 1488 | } | 1509 | } |
| 1489 | 1510 | ||
| 1490 | static void | 1511 | static void |
| 1491 | vnc_mute_lout(wavnc_info *devc) | 1512 | vnc_mute_lout(struct wavnc_info *devc) |
| 1492 | { | 1513 | { |
| 1493 | unsigned int left, right; | 1514 | unsigned int left, right; |
| 1494 | 1515 | ||
| @@ -1507,7 +1528,7 @@ vnc_mute_lout(wavnc_info *devc) | |||
| 1507 | } | 1528 | } |
| 1508 | 1529 | ||
| 1509 | static int | 1530 | static int |
| 1510 | vnc_volume_slider(wavnc_info *devc) | 1531 | vnc_volume_slider(struct wavnc_info *devc) |
| 1511 | { | 1532 | { |
| 1512 | static signed int old_slider_volume; | 1533 | static signed int old_slider_volume; |
| 1513 | unsigned long flags; | 1534 | unsigned long flags; |
| @@ -1567,7 +1588,7 @@ vnc_volume_slider(wavnc_info *devc) | |||
| 1567 | * SOUND_MASK_MIC Right Mic Builtin microphone | 1588 | * SOUND_MASK_MIC Right Mic Builtin microphone |
| 1568 | */ | 1589 | */ |
| 1569 | static unsigned int | 1590 | static unsigned int |
| 1570 | netwinder_select_input(wavnc_info *devc, unsigned int recmask, | 1591 | netwinder_select_input(struct wavnc_info *devc, unsigned int recmask, |
| 1571 | unsigned char *dev_l, unsigned char *dev_r) | 1592 | unsigned char *dev_l, unsigned char *dev_r) |
| 1572 | { | 1593 | { |
| 1573 | unsigned int recdev_l = ADC_MUX_NONE, recdev_r = ADC_MUX_NONE; | 1594 | unsigned int recdev_l = ADC_MUX_NONE, recdev_r = ADC_MUX_NONE; |
| @@ -1604,7 +1625,7 @@ netwinder_select_input(wavnc_info *devc, unsigned int recmask, | |||
| 1604 | } | 1625 | } |
| 1605 | 1626 | ||
| 1606 | static int | 1627 | static int |
| 1607 | netwinder_decode_mixer(wavnc_info *devc, int dev, unsigned char lev_l, | 1628 | netwinder_decode_mixer(struct wavnc_info *devc, int dev, unsigned char lev_l, |
| 1608 | unsigned char lev_r) | 1629 | unsigned char lev_r) |
| 1609 | { | 1630 | { |
| 1610 | switch (dev) { | 1631 | switch (dev) { |
| @@ -1643,7 +1664,7 @@ netwinder_decode_mixer(wavnc_info *devc, int dev, unsigned char lev_l, | |||
| 1643 | return dev; | 1664 | return dev; |
| 1644 | } | 1665 | } |
| 1645 | 1666 | ||
| 1646 | static int netwinder_get_mixer(wavnc_info *devc, int dev) | 1667 | static int netwinder_get_mixer(struct wavnc_info *devc, int dev) |
| 1647 | { | 1668 | { |
| 1648 | int levels; | 1669 | int levels; |
| 1649 | 1670 | ||
| @@ -1703,7 +1724,7 @@ static const struct waveartist_mixer_info netwinder_mixer = { | |||
| 1703 | }; | 1724 | }; |
| 1704 | 1725 | ||
| 1705 | static void | 1726 | static void |
| 1706 | vnc_configure_mixer(wavnc_info *devc, unsigned int recmask) | 1727 | vnc_configure_mixer(struct wavnc_info *devc, unsigned int recmask) |
| 1707 | { | 1728 | { |
| 1708 | if (!devc->no_autoselect) { | 1729 | if (!devc->no_autoselect) { |
| 1709 | if (devc->handset_detect) { | 1730 | if (devc->handset_detect) { |
| @@ -1729,7 +1750,7 @@ vnc_configure_mixer(wavnc_info *devc, unsigned int recmask) | |||
| 1729 | } | 1750 | } |
| 1730 | 1751 | ||
| 1731 | static int | 1752 | static int |
| 1732 | vnc_slider(wavnc_info *devc) | 1753 | vnc_slider(struct wavnc_info *devc) |
| 1733 | { | 1754 | { |
| 1734 | signed int slider_volume; | 1755 | signed int slider_volume; |
| 1735 | unsigned int temp, old_hs, old_td; | 1756 | unsigned int temp, old_hs, old_td; |
| @@ -1795,7 +1816,7 @@ vnc_slider_tick(unsigned long data) | |||
| 1795 | static int | 1816 | static int |
| 1796 | vnc_private_ioctl(int dev, unsigned int cmd, int __user * arg) | 1817 | vnc_private_ioctl(int dev, unsigned int cmd, int __user * arg) |
| 1797 | { | 1818 | { |
| 1798 | wavnc_info *devc = (wavnc_info *)audio_devs[dev]->devc; | 1819 | struct wavnc_info *devc = (struct wavnc_info *)audio_devs[dev]->devc; |
| 1799 | int val; | 1820 | int val; |
| 1800 | 1821 | ||
| 1801 | switch (cmd) { | 1822 | switch (cmd) { |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 5db1948699d8..aa302fb03fc5 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
| @@ -265,6 +265,7 @@ enum { | |||
| 265 | AZX_DRIVER_TERA, | 265 | AZX_DRIVER_TERA, |
| 266 | AZX_DRIVER_CTX, | 266 | AZX_DRIVER_CTX, |
| 267 | AZX_DRIVER_CTHDA, | 267 | AZX_DRIVER_CTHDA, |
| 268 | AZX_DRIVER_CMEDIA, | ||
| 268 | AZX_DRIVER_GENERIC, | 269 | AZX_DRIVER_GENERIC, |
| 269 | AZX_NUM_DRIVERS, /* keep this as last entry */ | 270 | AZX_NUM_DRIVERS, /* keep this as last entry */ |
| 270 | }; | 271 | }; |
| @@ -330,6 +331,7 @@ static char *driver_short_names[] = { | |||
| 330 | [AZX_DRIVER_TERA] = "HDA Teradici", | 331 | [AZX_DRIVER_TERA] = "HDA Teradici", |
| 331 | [AZX_DRIVER_CTX] = "HDA Creative", | 332 | [AZX_DRIVER_CTX] = "HDA Creative", |
| 332 | [AZX_DRIVER_CTHDA] = "HDA Creative", | 333 | [AZX_DRIVER_CTHDA] = "HDA Creative", |
| 334 | [AZX_DRIVER_CMEDIA] = "HDA C-Media", | ||
| 333 | [AZX_DRIVER_GENERIC] = "HD-Audio Generic", | 335 | [AZX_DRIVER_GENERIC] = "HD-Audio Generic", |
| 334 | }; | 336 | }; |
| 335 | 337 | ||
| @@ -1373,6 +1375,7 @@ static void azx_check_snoop_available(struct azx *chip) | |||
| 1373 | snoop = false; | 1375 | snoop = false; |
| 1374 | break; | 1376 | break; |
| 1375 | case AZX_DRIVER_CTHDA: | 1377 | case AZX_DRIVER_CTHDA: |
| 1378 | case AZX_DRIVER_CMEDIA: | ||
| 1376 | snoop = false; | 1379 | snoop = false; |
| 1377 | break; | 1380 | break; |
| 1378 | } | 1381 | } |
| @@ -2154,6 +2157,10 @@ static const struct pci_device_id azx_ids[] = { | |||
| 2154 | .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND | | 2157 | .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND | |
| 2155 | AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB }, | 2158 | AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB }, |
| 2156 | #endif | 2159 | #endif |
| 2160 | /* CM8888 */ | ||
| 2161 | { PCI_DEVICE(0x13f6, 0x5011), | ||
| 2162 | .driver_data = AZX_DRIVER_CMEDIA | | ||
| 2163 | AZX_DCAPS_NO_MSI | AZX_DCAPS_POSFIX_LPIB }, | ||
| 2157 | /* Vortex86MX */ | 2164 | /* Vortex86MX */ |
| 2158 | { PCI_DEVICE(0x17f3, 0x3010), .driver_data = AZX_DRIVER_GENERIC }, | 2165 | { PCI_DEVICE(0x17f3, 0x3010), .driver_data = AZX_DRIVER_GENERIC }, |
| 2159 | /* VMware HDAudio */ | 2166 | /* VMware HDAudio */ |
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 4f3aba78f720..5d8455e2dacd 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c | |||
| @@ -4376,6 +4376,9 @@ static void ca0132_download_dsp(struct hda_codec *codec) | |||
| 4376 | return; /* NOP */ | 4376 | return; /* NOP */ |
| 4377 | #endif | 4377 | #endif |
| 4378 | 4378 | ||
| 4379 | if (spec->dsp_state == DSP_DOWNLOAD_FAILED) | ||
| 4380 | return; /* don't retry failures */ | ||
| 4381 | |||
| 4379 | chipio_enable_clocks(codec); | 4382 | chipio_enable_clocks(codec); |
| 4380 | spec->dsp_state = DSP_DOWNLOADING; | 4383 | spec->dsp_state = DSP_DOWNLOADING; |
| 4381 | if (!ca0132_download_dsp_images(codec)) | 4384 | if (!ca0132_download_dsp_images(codec)) |
| @@ -4552,7 +4555,8 @@ static int ca0132_init(struct hda_codec *codec) | |||
| 4552 | struct auto_pin_cfg *cfg = &spec->autocfg; | 4555 | struct auto_pin_cfg *cfg = &spec->autocfg; |
| 4553 | int i; | 4556 | int i; |
| 4554 | 4557 | ||
| 4555 | spec->dsp_state = DSP_DOWNLOAD_INIT; | 4558 | if (spec->dsp_state != DSP_DOWNLOAD_FAILED) |
| 4559 | spec->dsp_state = DSP_DOWNLOAD_INIT; | ||
| 4556 | spec->curr_chip_addx = INVALID_CHIP_ADDRESS; | 4560 | spec->curr_chip_addx = INVALID_CHIP_ADDRESS; |
| 4557 | 4561 | ||
| 4558 | snd_hda_power_up(codec); | 4562 | snd_hda_power_up(codec); |
| @@ -4663,6 +4667,7 @@ static int patch_ca0132(struct hda_codec *codec) | |||
| 4663 | codec->spec = spec; | 4667 | codec->spec = spec; |
| 4664 | spec->codec = codec; | 4668 | spec->codec = codec; |
| 4665 | 4669 | ||
| 4670 | spec->dsp_state = DSP_DOWNLOAD_INIT; | ||
| 4666 | spec->num_mixers = 1; | 4671 | spec->num_mixers = 1; |
| 4667 | spec->mixers[0] = ca0132_mixer; | 4672 | spec->mixers[0] = ca0132_mixer; |
| 4668 | 4673 | ||
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c index ed3d133ffbb6..c895a8f21192 100644 --- a/sound/pci/hda/patch_cmedia.c +++ b/sound/pci/hda/patch_cmedia.c | |||
| @@ -75,15 +75,62 @@ static int patch_cmi9880(struct hda_codec *codec) | |||
| 75 | return err; | 75 | return err; |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | static int patch_cmi8888(struct hda_codec *codec) | ||
| 79 | { | ||
| 80 | struct cmi_spec *spec; | ||
| 81 | struct auto_pin_cfg *cfg; | ||
| 82 | int err; | ||
| 83 | |||
| 84 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
| 85 | if (!spec) | ||
| 86 | return -ENOMEM; | ||
| 87 | |||
| 88 | codec->spec = spec; | ||
| 89 | cfg = &spec->gen.autocfg; | ||
| 90 | snd_hda_gen_spec_init(&spec->gen); | ||
| 91 | |||
| 92 | /* mask NID 0x10 from the playback volume selection; | ||
| 93 | * it's a headphone boost volume handled manually below | ||
| 94 | */ | ||
| 95 | spec->gen.out_vol_mask = (1ULL << 0x10); | ||
| 96 | |||
| 97 | err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0); | ||
| 98 | if (err < 0) | ||
| 99 | goto error; | ||
| 100 | err = snd_hda_gen_parse_auto_config(codec, cfg); | ||
| 101 | if (err < 0) | ||
| 102 | goto error; | ||
| 103 | |||
| 104 | if (get_defcfg_device(snd_hda_codec_get_pincfg(codec, 0x10)) == | ||
| 105 | AC_JACK_HP_OUT) { | ||
| 106 | static const struct snd_kcontrol_new amp_kctl = | ||
| 107 | HDA_CODEC_VOLUME("Headphone Amp Playback Volume", | ||
| 108 | 0x10, 0, HDA_OUTPUT); | ||
| 109 | if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &_kctl)) { | ||
| 110 | err = -ENOMEM; | ||
| 111 | goto error; | ||
| 112 | } | ||
| 113 | } | ||
| 114 | |||
| 115 | codec->patch_ops = cmi_auto_patch_ops; | ||
| 116 | return 0; | ||
| 117 | |||
| 118 | error: | ||
| 119 | snd_hda_gen_free(codec); | ||
| 120 | return err; | ||
| 121 | } | ||
| 122 | |||
| 78 | /* | 123 | /* |
| 79 | * patch entries | 124 | * patch entries |
| 80 | */ | 125 | */ |
| 81 | static const struct hda_codec_preset snd_hda_preset_cmedia[] = { | 126 | static const struct hda_codec_preset snd_hda_preset_cmedia[] = { |
| 127 | { .id = 0x13f68888, .name = "CMI8888", .patch = patch_cmi8888 }, | ||
| 82 | { .id = 0x13f69880, .name = "CMI9880", .patch = patch_cmi9880 }, | 128 | { .id = 0x13f69880, .name = "CMI9880", .patch = patch_cmi9880 }, |
| 83 | { .id = 0x434d4980, .name = "CMI9880", .patch = patch_cmi9880 }, | 129 | { .id = 0x434d4980, .name = "CMI9880", .patch = patch_cmi9880 }, |
| 84 | {} /* terminator */ | 130 | {} /* terminator */ |
| 85 | }; | 131 | }; |
| 86 | 132 | ||
| 133 | MODULE_ALIAS("snd-hda-codec-id:13f68888"); | ||
| 87 | MODULE_ALIAS("snd-hda-codec-id:13f69880"); | 134 | MODULE_ALIAS("snd-hda-codec-id:13f69880"); |
| 88 | MODULE_ALIAS("snd-hda-codec-id:434d4980"); | 135 | MODULE_ALIAS("snd-hda-codec-id:434d4980"); |
| 89 | 136 | ||
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 7627a69ca6d7..6f2fa838b635 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
| 27 | #include <sound/core.h> | 27 | #include <sound/core.h> |
| 28 | #include <sound/jack.h> | 28 | #include <sound/jack.h> |
| 29 | #include <sound/tlv.h> | ||
| 29 | 30 | ||
| 30 | #include "hda_codec.h" | 31 | #include "hda_codec.h" |
| 31 | #include "hda_local.h" | 32 | #include "hda_local.h" |
| @@ -859,6 +860,11 @@ static int patch_conexant_auto(struct hda_codec *codec) | |||
| 859 | if (err < 0) | 860 | if (err < 0) |
| 860 | goto error; | 861 | goto error; |
| 861 | 862 | ||
| 863 | if (codec->vendor_id == 0x14f15051) { | ||
| 864 | /* minimum value is actually mute */ | ||
| 865 | spec->gen.vmaster_tlv[3] |= TLV_DB_SCALE_MUTE; | ||
| 866 | } | ||
| 867 | |||
| 862 | codec->patch_ops = cx_auto_patch_ops; | 868 | codec->patch_ops = cx_auto_patch_ops; |
| 863 | 869 | ||
| 864 | /* Some laptops with Conexant chips show stalls in S3 resume, | 870 | /* Some laptops with Conexant chips show stalls in S3 resume, |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 36badba2dcec..99d7d7fecaad 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
| @@ -50,6 +50,8 @@ MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info"); | |||
| 50 | #define is_haswell_plus(codec) (is_haswell(codec) || is_broadwell(codec)) | 50 | #define is_haswell_plus(codec) (is_haswell(codec) || is_broadwell(codec)) |
| 51 | 51 | ||
| 52 | #define is_valleyview(codec) ((codec)->vendor_id == 0x80862882) | 52 | #define is_valleyview(codec) ((codec)->vendor_id == 0x80862882) |
| 53 | #define is_cherryview(codec) ((codec)->vendor_id == 0x80862883) | ||
| 54 | #define is_valleyview_plus(codec) (is_valleyview(codec) || is_cherryview(codec)) | ||
| 53 | 55 | ||
| 54 | struct hdmi_spec_per_cvt { | 56 | struct hdmi_spec_per_cvt { |
| 55 | hda_nid_t cvt_nid; | 57 | hda_nid_t cvt_nid; |
| @@ -1459,7 +1461,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, | |||
| 1459 | mux_idx); | 1461 | mux_idx); |
| 1460 | 1462 | ||
| 1461 | /* configure unused pins to choose other converters */ | 1463 | /* configure unused pins to choose other converters */ |
| 1462 | if (is_haswell_plus(codec) || is_valleyview(codec)) | 1464 | if (is_haswell_plus(codec) || is_valleyview_plus(codec)) |
| 1463 | intel_not_share_assigned_cvt(codec, per_pin->pin_nid, mux_idx); | 1465 | intel_not_share_assigned_cvt(codec, per_pin->pin_nid, mux_idx); |
| 1464 | 1466 | ||
| 1465 | snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid); | 1467 | snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid); |
| @@ -1598,7 +1600,8 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) | |||
| 1598 | * and this can make HW reset converter selection on a pin. | 1600 | * and this can make HW reset converter selection on a pin. |
| 1599 | */ | 1601 | */ |
| 1600 | if (eld->eld_valid && !old_eld_valid && per_pin->setup) { | 1602 | if (eld->eld_valid && !old_eld_valid && per_pin->setup) { |
| 1601 | if (is_haswell_plus(codec) || is_valleyview(codec)) { | 1603 | if (is_haswell_plus(codec) || |
| 1604 | is_valleyview_plus(codec)) { | ||
| 1602 | intel_verify_pin_cvt_connect(codec, per_pin); | 1605 | intel_verify_pin_cvt_connect(codec, per_pin); |
| 1603 | intel_not_share_assigned_cvt(codec, pin_nid, | 1606 | intel_not_share_assigned_cvt(codec, pin_nid, |
| 1604 | per_pin->mux_idx); | 1607 | per_pin->mux_idx); |
| @@ -1779,7 +1782,7 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
| 1779 | bool non_pcm; | 1782 | bool non_pcm; |
| 1780 | int pinctl; | 1783 | int pinctl; |
| 1781 | 1784 | ||
| 1782 | if (is_haswell_plus(codec) || is_valleyview(codec)) { | 1785 | if (is_haswell_plus(codec) || is_valleyview_plus(codec)) { |
| 1783 | /* Verify pin:cvt selections to avoid silent audio after S3. | 1786 | /* Verify pin:cvt selections to avoid silent audio after S3. |
| 1784 | * After S3, the audio driver restores pin:cvt selections | 1787 | * After S3, the audio driver restores pin:cvt selections |
| 1785 | * but this can happen before gfx is ready and such selection | 1788 | * but this can happen before gfx is ready and such selection |
| @@ -2330,9 +2333,8 @@ static int patch_generic_hdmi(struct hda_codec *codec) | |||
| 2330 | intel_haswell_fixup_enable_dp12(codec); | 2333 | intel_haswell_fixup_enable_dp12(codec); |
| 2331 | } | 2334 | } |
| 2332 | 2335 | ||
| 2333 | if (is_haswell(codec) || is_valleyview(codec)) { | 2336 | if (is_haswell_plus(codec) || is_valleyview_plus(codec)) |
| 2334 | codec->depop_delay = 0; | 2337 | codec->depop_delay = 0; |
| 2335 | } | ||
| 2336 | 2338 | ||
| 2337 | if (hdmi_parse_codec(codec) < 0) { | 2339 | if (hdmi_parse_codec(codec) < 0) { |
| 2338 | codec->spec = NULL; | 2340 | codec->spec = NULL; |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 654c8f16d150..d71270a3f73f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
| @@ -181,6 +181,8 @@ static void alc_fix_pll(struct hda_codec *codec) | |||
| 181 | spec->pll_coef_idx); | 181 | spec->pll_coef_idx); |
| 182 | val = snd_hda_codec_read(codec, spec->pll_nid, 0, | 182 | val = snd_hda_codec_read(codec, spec->pll_nid, 0, |
| 183 | AC_VERB_GET_PROC_COEF, 0); | 183 | AC_VERB_GET_PROC_COEF, 0); |
| 184 | if (val == -1) | ||
| 185 | return; | ||
| 184 | snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX, | 186 | snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX, |
| 185 | spec->pll_coef_idx); | 187 | spec->pll_coef_idx); |
| 186 | snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_PROC_COEF, | 188 | snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_PROC_COEF, |
| @@ -2782,9 +2784,32 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
| 2782 | return alc_parse_auto_config(codec, alc269_ignore, ssids); | 2784 | return alc_parse_auto_config(codec, alc269_ignore, ssids); |
| 2783 | } | 2785 | } |
| 2784 | 2786 | ||
| 2787 | static int find_ext_mic_pin(struct hda_codec *codec); | ||
| 2788 | |||
| 2789 | static void alc286_shutup(struct hda_codec *codec) | ||
| 2790 | { | ||
| 2791 | int i; | ||
| 2792 | int mic_pin = find_ext_mic_pin(codec); | ||
| 2793 | /* don't shut up pins when unloading the driver; otherwise it breaks | ||
| 2794 | * the default pin setup at the next load of the driver | ||
| 2795 | */ | ||
| 2796 | if (codec->bus->shutdown) | ||
| 2797 | return; | ||
| 2798 | for (i = 0; i < codec->init_pins.used; i++) { | ||
| 2799 | struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); | ||
| 2800 | /* use read here for syncing after issuing each verb */ | ||
| 2801 | if (pin->nid != mic_pin) | ||
| 2802 | snd_hda_codec_read(codec, pin->nid, 0, | ||
| 2803 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0); | ||
| 2804 | } | ||
| 2805 | codec->pins_shutup = 1; | ||
| 2806 | } | ||
| 2807 | |||
| 2785 | static void alc269vb_toggle_power_output(struct hda_codec *codec, int power_up) | 2808 | static void alc269vb_toggle_power_output(struct hda_codec *codec, int power_up) |
| 2786 | { | 2809 | { |
| 2787 | int val = alc_read_coef_idx(codec, 0x04); | 2810 | int val = alc_read_coef_idx(codec, 0x04); |
| 2811 | if (val == -1) | ||
| 2812 | return; | ||
| 2788 | if (power_up) | 2813 | if (power_up) |
| 2789 | val |= 1 << 11; | 2814 | val |= 1 << 11; |
| 2790 | else | 2815 | else |
| @@ -3243,6 +3268,15 @@ static int alc269_resume(struct hda_codec *codec) | |||
| 3243 | snd_hda_codec_resume_cache(codec); | 3268 | snd_hda_codec_resume_cache(codec); |
| 3244 | alc_inv_dmic_sync(codec, true); | 3269 | alc_inv_dmic_sync(codec, true); |
| 3245 | hda_call_check_power_status(codec, 0x01); | 3270 | hda_call_check_power_status(codec, 0x01); |
| 3271 | |||
| 3272 | /* on some machine, the BIOS will clear the codec gpio data when enter | ||
| 3273 | * suspend, and won't restore the data after resume, so we restore it | ||
| 3274 | * in the driver. | ||
| 3275 | */ | ||
| 3276 | if (spec->gpio_led) | ||
| 3277 | snd_hda_codec_write(codec, codec->afg, 0, AC_VERB_SET_GPIO_DATA, | ||
| 3278 | spec->gpio_led); | ||
| 3279 | |||
| 3246 | if (spec->has_alc5505_dsp) | 3280 | if (spec->has_alc5505_dsp) |
| 3247 | alc5505_dsp_resume(codec); | 3281 | alc5505_dsp_resume(codec); |
| 3248 | 3282 | ||
| @@ -4072,7 +4106,7 @@ static unsigned int alc_power_filter_xps13(struct hda_codec *codec, | |||
| 4072 | 4106 | ||
| 4073 | /* Avoid pop noises when headphones are plugged in */ | 4107 | /* Avoid pop noises when headphones are plugged in */ |
| 4074 | if (spec->gen.hp_jack_present) | 4108 | if (spec->gen.hp_jack_present) |
| 4075 | if (nid == codec->afg || nid == 0x02) | 4109 | if (nid == codec->afg || nid == 0x02 || nid == 0x15) |
| 4076 | return AC_PWRST_D0; | 4110 | return AC_PWRST_D0; |
| 4077 | return power_state; | 4111 | return power_state; |
| 4078 | } | 4112 | } |
| @@ -4082,8 +4116,19 @@ static void alc_fixup_dell_xps13(struct hda_codec *codec, | |||
| 4082 | { | 4116 | { |
| 4083 | if (action == HDA_FIXUP_ACT_PROBE) { | 4117 | if (action == HDA_FIXUP_ACT_PROBE) { |
| 4084 | struct alc_spec *spec = codec->spec; | 4118 | struct alc_spec *spec = codec->spec; |
| 4119 | struct hda_input_mux *imux = &spec->gen.input_mux; | ||
| 4120 | int i; | ||
| 4121 | |||
| 4085 | spec->shutup = alc_no_shutup; | 4122 | spec->shutup = alc_no_shutup; |
| 4086 | codec->power_filter = alc_power_filter_xps13; | 4123 | codec->power_filter = alc_power_filter_xps13; |
| 4124 | |||
| 4125 | /* Make the internal mic the default input source. */ | ||
| 4126 | for (i = 0; i < imux->num_items; i++) { | ||
| 4127 | if (spec->gen.imux_pins[i] == 0x12) { | ||
| 4128 | spec->gen.cur_mux[0] = i; | ||
| 4129 | break; | ||
| 4130 | } | ||
| 4131 | } | ||
| 4087 | } | 4132 | } |
| 4088 | } | 4133 | } |
| 4089 | 4134 | ||
| @@ -5279,27 +5324,30 @@ static void alc269_fill_coef(struct hda_codec *codec) | |||
| 5279 | if ((alc_get_coef0(codec) & 0x00ff) == 0x017) { | 5324 | if ((alc_get_coef0(codec) & 0x00ff) == 0x017) { |
| 5280 | val = alc_read_coef_idx(codec, 0x04); | 5325 | val = alc_read_coef_idx(codec, 0x04); |
| 5281 | /* Power up output pin */ | 5326 | /* Power up output pin */ |
| 5282 | alc_write_coef_idx(codec, 0x04, val | (1<<11)); | 5327 | if (val != -1) |
| 5328 | alc_write_coef_idx(codec, 0x04, val | (1<<11)); | ||
| 5283 | } | 5329 | } |
| 5284 | 5330 | ||
| 5285 | if ((alc_get_coef0(codec) & 0x00ff) == 0x018) { | 5331 | if ((alc_get_coef0(codec) & 0x00ff) == 0x018) { |
| 5286 | val = alc_read_coef_idx(codec, 0xd); | 5332 | val = alc_read_coef_idx(codec, 0xd); |
| 5287 | if ((val & 0x0c00) >> 10 != 0x1) { | 5333 | if (val != -1 && (val & 0x0c00) >> 10 != 0x1) { |
| 5288 | /* Capless ramp up clock control */ | 5334 | /* Capless ramp up clock control */ |
| 5289 | alc_write_coef_idx(codec, 0xd, val | (1<<10)); | 5335 | alc_write_coef_idx(codec, 0xd, val | (1<<10)); |
| 5290 | } | 5336 | } |
| 5291 | val = alc_read_coef_idx(codec, 0x17); | 5337 | val = alc_read_coef_idx(codec, 0x17); |
| 5292 | if ((val & 0x01c0) >> 6 != 0x4) { | 5338 | if (val != -1 && (val & 0x01c0) >> 6 != 0x4) { |
| 5293 | /* Class D power on reset */ | 5339 | /* Class D power on reset */ |
| 5294 | alc_write_coef_idx(codec, 0x17, val | (1<<7)); | 5340 | alc_write_coef_idx(codec, 0x17, val | (1<<7)); |
| 5295 | } | 5341 | } |
| 5296 | } | 5342 | } |
| 5297 | 5343 | ||
| 5298 | val = alc_read_coef_idx(codec, 0xd); /* Class D */ | 5344 | val = alc_read_coef_idx(codec, 0xd); /* Class D */ |
| 5299 | alc_write_coef_idx(codec, 0xd, val | (1<<14)); | 5345 | if (val != -1) |
| 5346 | alc_write_coef_idx(codec, 0xd, val | (1<<14)); | ||
| 5300 | 5347 | ||
| 5301 | val = alc_read_coef_idx(codec, 0x4); /* HP */ | 5348 | val = alc_read_coef_idx(codec, 0x4); /* HP */ |
| 5302 | alc_write_coef_idx(codec, 0x4, val | (1<<11)); | 5349 | if (val != -1) |
| 5350 | alc_write_coef_idx(codec, 0x4, val | (1<<11)); | ||
| 5303 | } | 5351 | } |
| 5304 | 5352 | ||
| 5305 | /* | 5353 | /* |
| @@ -5384,6 +5432,7 @@ static int patch_alc269(struct hda_codec *codec) | |||
| 5384 | case 0x10ec0286: | 5432 | case 0x10ec0286: |
| 5385 | case 0x10ec0288: | 5433 | case 0x10ec0288: |
| 5386 | spec->codec_variant = ALC269_TYPE_ALC286; | 5434 | spec->codec_variant = ALC269_TYPE_ALC286; |
| 5435 | spec->shutup = alc286_shutup; | ||
| 5387 | break; | 5436 | break; |
| 5388 | case 0x10ec0255: | 5437 | case 0x10ec0255: |
| 5389 | spec->codec_variant = ALC269_TYPE_ALC255; | 5438 | spec->codec_variant = ALC269_TYPE_ALC255; |
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index bd41ee4da078..2c71f16bd661 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c | |||
| @@ -1278,6 +1278,8 @@ static int arizona_hw_params(struct snd_pcm_substream *substream, | |||
| 1278 | else | 1278 | else |
| 1279 | rates = &arizona_48k_bclk_rates[0]; | 1279 | rates = &arizona_48k_bclk_rates[0]; |
| 1280 | 1280 | ||
| 1281 | wl = snd_pcm_format_width(params_format(params)); | ||
| 1282 | |||
| 1281 | if (tdm_slots) { | 1283 | if (tdm_slots) { |
| 1282 | arizona_aif_dbg(dai, "Configuring for %d %d bit TDM slots\n", | 1284 | arizona_aif_dbg(dai, "Configuring for %d %d bit TDM slots\n", |
| 1283 | tdm_slots, tdm_width); | 1285 | tdm_slots, tdm_width); |
| @@ -1285,6 +1287,7 @@ static int arizona_hw_params(struct snd_pcm_substream *substream, | |||
| 1285 | channels = tdm_slots; | 1287 | channels = tdm_slots; |
| 1286 | } else { | 1288 | } else { |
| 1287 | bclk_target = snd_soc_params_to_bclk(params); | 1289 | bclk_target = snd_soc_params_to_bclk(params); |
| 1290 | tdm_width = wl; | ||
| 1288 | } | 1291 | } |
| 1289 | 1292 | ||
| 1290 | if (chan_limit && chan_limit < channels) { | 1293 | if (chan_limit && chan_limit < channels) { |
| @@ -1319,8 +1322,7 @@ static int arizona_hw_params(struct snd_pcm_substream *substream, | |||
| 1319 | arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n", | 1322 | arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n", |
| 1320 | rates[bclk], rates[bclk] / lrclk); | 1323 | rates[bclk], rates[bclk] / lrclk); |
| 1321 | 1324 | ||
| 1322 | wl = snd_pcm_format_width(params_format(params)); | 1325 | frame = wl << ARIZONA_AIF1TX_WL_SHIFT | tdm_width; |
| 1323 | frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl; | ||
| 1324 | 1326 | ||
| 1325 | reconfig = arizona_aif_cfg_changed(codec, base, bclk, lrclk, frame); | 1327 | reconfig = arizona_aif_cfg_changed(codec, base, bclk, lrclk, frame); |
| 1326 | 1328 | ||
diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c index 163ec3855fd4..0c8aefab404c 100644 --- a/sound/soc/codecs/pcm512x.c +++ b/sound/soc/codecs/pcm512x.c | |||
| @@ -259,13 +259,13 @@ static const struct soc_enum pcm512x_veds = | |||
| 259 | pcm512x_ramp_step_text); | 259 | pcm512x_ramp_step_text); |
| 260 | 260 | ||
| 261 | static const struct snd_kcontrol_new pcm512x_controls[] = { | 261 | static const struct snd_kcontrol_new pcm512x_controls[] = { |
| 262 | SOC_DOUBLE_R_TLV("Playback Digital Volume", PCM512x_DIGITAL_VOLUME_2, | 262 | SOC_DOUBLE_R_TLV("Digital Playback Volume", PCM512x_DIGITAL_VOLUME_2, |
| 263 | PCM512x_DIGITAL_VOLUME_3, 0, 255, 1, digital_tlv), | 263 | PCM512x_DIGITAL_VOLUME_3, 0, 255, 1, digital_tlv), |
| 264 | SOC_DOUBLE_TLV("Playback Volume", PCM512x_ANALOG_GAIN_CTRL, | 264 | SOC_DOUBLE_TLV("Playback Volume", PCM512x_ANALOG_GAIN_CTRL, |
| 265 | PCM512x_LAGN_SHIFT, PCM512x_RAGN_SHIFT, 1, 1, analog_tlv), | 265 | PCM512x_LAGN_SHIFT, PCM512x_RAGN_SHIFT, 1, 1, analog_tlv), |
| 266 | SOC_DOUBLE_TLV("Playback Boost Volume", PCM512x_ANALOG_GAIN_BOOST, | 266 | SOC_DOUBLE_TLV("Playback Boost Volume", PCM512x_ANALOG_GAIN_BOOST, |
| 267 | PCM512x_AGBL_SHIFT, PCM512x_AGBR_SHIFT, 1, 0, boost_tlv), | 267 | PCM512x_AGBL_SHIFT, PCM512x_AGBR_SHIFT, 1, 0, boost_tlv), |
| 268 | SOC_DOUBLE("Playback Digital Switch", PCM512x_MUTE, PCM512x_RQML_SHIFT, | 268 | SOC_DOUBLE("Digital Playback Switch", PCM512x_MUTE, PCM512x_RQML_SHIFT, |
| 269 | PCM512x_RQMR_SHIFT, 1, 1), | 269 | PCM512x_RQMR_SHIFT, 1, 1), |
| 270 | 270 | ||
| 271 | SOC_SINGLE("Deemphasis Switch", PCM512x_DSP, PCM512x_DEMP_SHIFT, 1, 1), | 271 | SOC_SINGLE("Deemphasis Switch", PCM512x_DSP, PCM512x_DEMP_SHIFT, 1, 1), |
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index c28508da34cf..6a6b2ff7d7d7 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c | |||
| @@ -403,7 +403,8 @@ out: | |||
| 403 | return ret; | 403 | return ret; |
| 404 | } | 404 | } |
| 405 | 405 | ||
| 406 | static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div) | 406 | static int __davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, |
| 407 | int div, bool explicit) | ||
| 407 | { | 408 | { |
| 408 | struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); | 409 | struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); |
| 409 | 410 | ||
| @@ -420,7 +421,8 @@ static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div | |||
| 420 | ACLKXDIV(div - 1), ACLKXDIV_MASK); | 421 | ACLKXDIV(div - 1), ACLKXDIV_MASK); |
| 421 | mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, | 422 | mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, |
| 422 | ACLKRDIV(div - 1), ACLKRDIV_MASK); | 423 | ACLKRDIV(div - 1), ACLKRDIV_MASK); |
| 423 | mcasp->bclk_div = div; | 424 | if (explicit) |
| 425 | mcasp->bclk_div = div; | ||
| 424 | break; | 426 | break; |
| 425 | 427 | ||
| 426 | case 2: /* BCLK/LRCLK ratio */ | 428 | case 2: /* BCLK/LRCLK ratio */ |
| @@ -434,6 +436,12 @@ static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div | |||
| 434 | return 0; | 436 | return 0; |
| 435 | } | 437 | } |
| 436 | 438 | ||
| 439 | static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, | ||
| 440 | int div) | ||
| 441 | { | ||
| 442 | return __davinci_mcasp_set_clkdiv(dai, div_id, div, 1); | ||
| 443 | } | ||
| 444 | |||
| 437 | static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id, | 445 | static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id, |
| 438 | unsigned int freq, int dir) | 446 | unsigned int freq, int dir) |
| 439 | { | 447 | { |
| @@ -738,7 +746,7 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, | |||
| 738 | "Inaccurate BCLK: %u Hz / %u != %u Hz\n", | 746 | "Inaccurate BCLK: %u Hz / %u != %u Hz\n", |
| 739 | mcasp->sysclk_freq, div, bclk_freq); | 747 | mcasp->sysclk_freq, div, bclk_freq); |
| 740 | } | 748 | } |
| 741 | davinci_mcasp_set_clkdiv(cpu_dai, 1, div); | 749 | __davinci_mcasp_set_clkdiv(cpu_dai, 1, div, 0); |
| 742 | } | 750 | } |
| 743 | 751 | ||
| 744 | ret = mcasp_common_hw_param(mcasp, substream->stream, | 752 | ret = mcasp_common_hw_param(mcasp, substream->stream, |
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index f54a8fc99291..f3012b645b51 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig | |||
| @@ -49,7 +49,6 @@ config SND_SOC_FSL_ESAI | |||
| 49 | tristate "Enhanced Serial Audio Interface (ESAI) module support" | 49 | tristate "Enhanced Serial Audio Interface (ESAI) module support" |
| 50 | select REGMAP_MMIO | 50 | select REGMAP_MMIO |
| 51 | select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n | 51 | select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n |
| 52 | select SND_SOC_FSL_UTILS | ||
| 53 | help | 52 | help |
| 54 | Say Y if you want to add Enhanced Synchronous Audio Interface | 53 | Say Y if you want to add Enhanced Synchronous Audio Interface |
| 55 | (ESAI) support for the Freescale CPUs. | 54 | (ESAI) support for the Freescale CPUs. |
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index 72d154e7dd03..a3b29ed84963 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c | |||
| @@ -18,7 +18,6 @@ | |||
| 18 | 18 | ||
| 19 | #include "fsl_esai.h" | 19 | #include "fsl_esai.h" |
| 20 | #include "imx-pcm.h" | 20 | #include "imx-pcm.h" |
| 21 | #include "fsl_utils.h" | ||
| 22 | 21 | ||
| 23 | #define FSL_ESAI_RATES SNDRV_PCM_RATE_8000_192000 | 22 | #define FSL_ESAI_RATES SNDRV_PCM_RATE_8000_192000 |
| 24 | #define FSL_ESAI_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ | 23 | #define FSL_ESAI_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ |
| @@ -607,7 +606,6 @@ static struct snd_soc_dai_ops fsl_esai_dai_ops = { | |||
| 607 | .hw_params = fsl_esai_hw_params, | 606 | .hw_params = fsl_esai_hw_params, |
| 608 | .set_sysclk = fsl_esai_set_dai_sysclk, | 607 | .set_sysclk = fsl_esai_set_dai_sysclk, |
| 609 | .set_fmt = fsl_esai_set_dai_fmt, | 608 | .set_fmt = fsl_esai_set_dai_fmt, |
| 610 | .xlate_tdm_slot_mask = fsl_asoc_xlate_tdm_slot_mask, | ||
| 611 | .set_tdm_slot = fsl_esai_set_dai_tdm_slot, | 609 | .set_tdm_slot = fsl_esai_set_dai_tdm_slot, |
| 612 | }; | 610 | }; |
| 613 | 611 | ||
diff --git a/sound/soc/intel/sst-acpi.c b/sound/soc/intel/sst-acpi.c index 42edc6f4fc4a..03d0a166b635 100644 --- a/sound/soc/intel/sst-acpi.c +++ b/sound/soc/intel/sst-acpi.c | |||
| @@ -246,8 +246,8 @@ static struct sst_acpi_desc sst_acpi_broadwell_desc = { | |||
| 246 | }; | 246 | }; |
| 247 | 247 | ||
| 248 | static struct sst_acpi_mach baytrail_machines[] = { | 248 | static struct sst_acpi_mach baytrail_machines[] = { |
| 249 | { "10EC5640", "byt-rt5640", "intel/fw_sst_0f28.bin-i2s_master" }, | 249 | { "10EC5640", "byt-rt5640", "intel/fw_sst_0f28.bin-48kHz_i2s_master" }, |
| 250 | { "193C9890", "byt-max98090", "intel/fw_sst_0f28.bin-i2s_master" }, | 250 | { "193C9890", "byt-max98090", "intel/fw_sst_0f28.bin-48kHz_i2s_master" }, |
| 251 | {} | 251 | {} |
| 252 | }; | 252 | }; |
| 253 | 253 | ||
diff --git a/sound/soc/intel/sst-baytrail-ipc.c b/sound/soc/intel/sst-baytrail-ipc.c index 67673a2c0f41..b4ad98c43e5c 100644 --- a/sound/soc/intel/sst-baytrail-ipc.c +++ b/sound/soc/intel/sst-baytrail-ipc.c | |||
| @@ -817,7 +817,7 @@ static struct sst_dsp_device byt_dev = { | |||
| 817 | .ops = &sst_byt_ops, | 817 | .ops = &sst_byt_ops, |
| 818 | }; | 818 | }; |
| 819 | 819 | ||
| 820 | int sst_byt_dsp_suspend_noirq(struct device *dev, struct sst_pdata *pdata) | 820 | int sst_byt_dsp_suspend_late(struct device *dev, struct sst_pdata *pdata) |
| 821 | { | 821 | { |
| 822 | struct sst_byt *byt = pdata->dsp; | 822 | struct sst_byt *byt = pdata->dsp; |
| 823 | 823 | ||
| @@ -826,14 +826,6 @@ int sst_byt_dsp_suspend_noirq(struct device *dev, struct sst_pdata *pdata) | |||
| 826 | sst_byt_drop_all(byt); | 826 | sst_byt_drop_all(byt); |
| 827 | dev_dbg(byt->dev, "dsp in reset\n"); | 827 | dev_dbg(byt->dev, "dsp in reset\n"); |
| 828 | 828 | ||
| 829 | return 0; | ||
| 830 | } | ||
| 831 | EXPORT_SYMBOL_GPL(sst_byt_dsp_suspend_noirq); | ||
| 832 | |||
| 833 | int sst_byt_dsp_suspend_late(struct device *dev, struct sst_pdata *pdata) | ||
| 834 | { | ||
| 835 | struct sst_byt *byt = pdata->dsp; | ||
| 836 | |||
| 837 | dev_dbg(byt->dev, "free all blocks and unload fw\n"); | 829 | dev_dbg(byt->dev, "free all blocks and unload fw\n"); |
| 838 | sst_fw_unload(byt->fw); | 830 | sst_fw_unload(byt->fw); |
| 839 | 831 | ||
diff --git a/sound/soc/intel/sst-baytrail-ipc.h b/sound/soc/intel/sst-baytrail-ipc.h index 06a4d202689b..8faff6dcf25d 100644 --- a/sound/soc/intel/sst-baytrail-ipc.h +++ b/sound/soc/intel/sst-baytrail-ipc.h | |||
| @@ -66,7 +66,6 @@ int sst_byt_get_dsp_position(struct sst_byt *byt, | |||
| 66 | int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata); | 66 | int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata); |
| 67 | void sst_byt_dsp_free(struct device *dev, struct sst_pdata *pdata); | 67 | void sst_byt_dsp_free(struct device *dev, struct sst_pdata *pdata); |
| 68 | struct sst_dsp *sst_byt_get_dsp(struct sst_byt *byt); | 68 | struct sst_dsp *sst_byt_get_dsp(struct sst_byt *byt); |
| 69 | int sst_byt_dsp_suspend_noirq(struct device *dev, struct sst_pdata *pdata); | ||
| 70 | int sst_byt_dsp_suspend_late(struct device *dev, struct sst_pdata *pdata); | 69 | int sst_byt_dsp_suspend_late(struct device *dev, struct sst_pdata *pdata); |
| 71 | int sst_byt_dsp_boot(struct device *dev, struct sst_pdata *pdata); | 70 | int sst_byt_dsp_boot(struct device *dev, struct sst_pdata *pdata); |
| 72 | int sst_byt_dsp_wait_for_ready(struct device *dev, struct sst_pdata *pdata); | 71 | int sst_byt_dsp_wait_for_ready(struct device *dev, struct sst_pdata *pdata); |
diff --git a/sound/soc/intel/sst-baytrail-pcm.c b/sound/soc/intel/sst-baytrail-pcm.c index 599401c0c655..eab1c7d85187 100644 --- a/sound/soc/intel/sst-baytrail-pcm.c +++ b/sound/soc/intel/sst-baytrail-pcm.c | |||
| @@ -59,6 +59,9 @@ struct sst_byt_priv_data { | |||
| 59 | 59 | ||
| 60 | /* DAI data */ | 60 | /* DAI data */ |
| 61 | struct sst_byt_pcm_data pcm[BYT_PCM_COUNT]; | 61 | struct sst_byt_pcm_data pcm[BYT_PCM_COUNT]; |
| 62 | |||
| 63 | /* flag indicating is stream context restore needed after suspend */ | ||
| 64 | bool restore_stream; | ||
| 62 | }; | 65 | }; |
| 63 | 66 | ||
| 64 | /* this may get called several times by oss emulation */ | 67 | /* this may get called several times by oss emulation */ |
| @@ -184,7 +187,10 @@ static int sst_byt_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
| 184 | sst_byt_stream_start(byt, pcm_data->stream, 0); | 187 | sst_byt_stream_start(byt, pcm_data->stream, 0); |
| 185 | break; | 188 | break; |
| 186 | case SNDRV_PCM_TRIGGER_RESUME: | 189 | case SNDRV_PCM_TRIGGER_RESUME: |
| 187 | schedule_work(&pcm_data->work); | 190 | if (pdata->restore_stream == true) |
| 191 | schedule_work(&pcm_data->work); | ||
| 192 | else | ||
| 193 | sst_byt_stream_resume(byt, pcm_data->stream); | ||
| 188 | break; | 194 | break; |
| 189 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 195 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
| 190 | sst_byt_stream_resume(byt, pcm_data->stream); | 196 | sst_byt_stream_resume(byt, pcm_data->stream); |
| @@ -193,6 +199,7 @@ static int sst_byt_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
| 193 | sst_byt_stream_stop(byt, pcm_data->stream); | 199 | sst_byt_stream_stop(byt, pcm_data->stream); |
| 194 | break; | 200 | break; |
| 195 | case SNDRV_PCM_TRIGGER_SUSPEND: | 201 | case SNDRV_PCM_TRIGGER_SUSPEND: |
| 202 | pdata->restore_stream = false; | ||
| 196 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 203 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
| 197 | sst_byt_stream_pause(byt, pcm_data->stream); | 204 | sst_byt_stream_pause(byt, pcm_data->stream); |
| 198 | break; | 205 | break; |
| @@ -404,26 +411,10 @@ static const struct snd_soc_component_driver byt_dai_component = { | |||
| 404 | }; | 411 | }; |
| 405 | 412 | ||
| 406 | #ifdef CONFIG_PM | 413 | #ifdef CONFIG_PM |
| 407 | static int sst_byt_pcm_dev_suspend_noirq(struct device *dev) | ||
| 408 | { | ||
| 409 | struct sst_pdata *sst_pdata = dev_get_platdata(dev); | ||
| 410 | int ret; | ||
| 411 | |||
| 412 | dev_dbg(dev, "suspending noirq\n"); | ||
| 413 | |||
| 414 | /* at this point all streams will be stopped and context saved */ | ||
| 415 | ret = sst_byt_dsp_suspend_noirq(dev, sst_pdata); | ||
| 416 | if (ret < 0) { | ||
| 417 | dev_err(dev, "failed to suspend %d\n", ret); | ||
| 418 | return ret; | ||
| 419 | } | ||
| 420 | |||
| 421 | return ret; | ||
| 422 | } | ||
| 423 | |||
| 424 | static int sst_byt_pcm_dev_suspend_late(struct device *dev) | 414 | static int sst_byt_pcm_dev_suspend_late(struct device *dev) |
| 425 | { | 415 | { |
| 426 | struct sst_pdata *sst_pdata = dev_get_platdata(dev); | 416 | struct sst_pdata *sst_pdata = dev_get_platdata(dev); |
| 417 | struct sst_byt_priv_data *priv_data = dev_get_drvdata(dev); | ||
| 427 | int ret; | 418 | int ret; |
| 428 | 419 | ||
| 429 | dev_dbg(dev, "suspending late\n"); | 420 | dev_dbg(dev, "suspending late\n"); |
| @@ -434,34 +425,30 @@ static int sst_byt_pcm_dev_suspend_late(struct device *dev) | |||
| 434 | return ret; | 425 | return ret; |
| 435 | } | 426 | } |
| 436 | 427 | ||
| 428 | priv_data->restore_stream = true; | ||
| 429 | |||
| 437 | return ret; | 430 | return ret; |
| 438 | } | 431 | } |
| 439 | 432 | ||
| 440 | static int sst_byt_pcm_dev_resume_early(struct device *dev) | 433 | static int sst_byt_pcm_dev_resume_early(struct device *dev) |
| 441 | { | 434 | { |
| 442 | struct sst_pdata *sst_pdata = dev_get_platdata(dev); | 435 | struct sst_pdata *sst_pdata = dev_get_platdata(dev); |
| 436 | int ret; | ||
| 443 | 437 | ||
| 444 | dev_dbg(dev, "resume early\n"); | 438 | dev_dbg(dev, "resume early\n"); |
| 445 | 439 | ||
| 446 | /* load fw and boot DSP */ | 440 | /* load fw and boot DSP */ |
| 447 | return sst_byt_dsp_boot(dev, sst_pdata); | 441 | ret = sst_byt_dsp_boot(dev, sst_pdata); |
| 448 | } | 442 | if (ret) |
| 449 | 443 | return ret; | |
| 450 | static int sst_byt_pcm_dev_resume(struct device *dev) | ||
| 451 | { | ||
| 452 | struct sst_pdata *sst_pdata = dev_get_platdata(dev); | ||
| 453 | |||
| 454 | dev_dbg(dev, "resume\n"); | ||
| 455 | 444 | ||
| 456 | /* wait for FW to finish booting */ | 445 | /* wait for FW to finish booting */ |
| 457 | return sst_byt_dsp_wait_for_ready(dev, sst_pdata); | 446 | return sst_byt_dsp_wait_for_ready(dev, sst_pdata); |
| 458 | } | 447 | } |
| 459 | 448 | ||
| 460 | static const struct dev_pm_ops sst_byt_pm_ops = { | 449 | static const struct dev_pm_ops sst_byt_pm_ops = { |
| 461 | .suspend_noirq = sst_byt_pcm_dev_suspend_noirq, | ||
| 462 | .suspend_late = sst_byt_pcm_dev_suspend_late, | 450 | .suspend_late = sst_byt_pcm_dev_suspend_late, |
| 463 | .resume_early = sst_byt_pcm_dev_resume_early, | 451 | .resume_early = sst_byt_pcm_dev_resume_early, |
| 464 | .resume = sst_byt_pcm_dev_resume, | ||
| 465 | }; | 452 | }; |
| 466 | 453 | ||
| 467 | #define SST_BYT_PM_OPS (&sst_byt_pm_ops) | 454 | #define SST_BYT_PM_OPS (&sst_byt_pm_ops) |
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 0109f6c2334e..a8e097433074 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c | |||
| @@ -765,9 +765,7 @@ static int pxa_ssp_remove(struct snd_soc_dai *dai) | |||
| 765 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \ | 765 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \ |
| 766 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) | 766 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) |
| 767 | 767 | ||
| 768 | #define PXA_SSP_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ | 768 | #define PXA_SSP_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) |
| 769 | SNDRV_PCM_FMTBIT_S24_LE | \ | ||
| 770 | SNDRV_PCM_FMTBIT_S32_LE) | ||
| 771 | 769 | ||
| 772 | static const struct snd_soc_dai_ops pxa_ssp_dai_ops = { | 770 | static const struct snd_soc_dai_ops pxa_ssp_dai_ops = { |
| 773 | .startup = pxa_ssp_startup, | 771 | .startup = pxa_ssp_startup, |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 8348352dc2c6..177bd8639ef9 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
| @@ -2860,12 +2860,14 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, | |||
| 2860 | struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); | 2860 | struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); |
| 2861 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2861 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
| 2862 | unsigned int reg_val, val; | 2862 | unsigned int reg_val, val; |
| 2863 | int ret = 0; | ||
| 2864 | 2863 | ||
| 2865 | if (e->reg != SND_SOC_NOPM) | 2864 | if (e->reg != SND_SOC_NOPM) { |
| 2866 | ret = soc_dapm_read(dapm, e->reg, ®_val); | 2865 | int ret = soc_dapm_read(dapm, e->reg, ®_val); |
| 2867 | else | 2866 | if (ret) |
| 2867 | return ret; | ||
| 2868 | } else { | ||
| 2868 | reg_val = dapm_kcontrol_get_value(kcontrol); | 2869 | reg_val = dapm_kcontrol_get_value(kcontrol); |
| 2870 | } | ||
| 2869 | 2871 | ||
| 2870 | val = (reg_val >> e->shift_l) & e->mask; | 2872 | val = (reg_val >> e->shift_l) & e->mask; |
| 2871 | ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(e, val); | 2873 | ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(e, val); |
| @@ -2875,7 +2877,7 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, | |||
| 2875 | ucontrol->value.enumerated.item[1] = val; | 2877 | ucontrol->value.enumerated.item[1] = val; |
| 2876 | } | 2878 | } |
| 2877 | 2879 | ||
| 2878 | return ret; | 2880 | return 0; |
| 2879 | } | 2881 | } |
| 2880 | EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double); | 2882 | EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double); |
| 2881 | 2883 | ||
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index f652b10ce905..223c47b33ba3 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h | |||
| @@ -1581,6 +1581,35 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
| 1581 | } | 1581 | } |
| 1582 | }, | 1582 | }, |
| 1583 | { | 1583 | { |
| 1584 | /* BOSS ME-25 */ | ||
| 1585 | USB_DEVICE(0x0582, 0x0113), | ||
| 1586 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
| 1587 | .ifnum = QUIRK_ANY_INTERFACE, | ||
| 1588 | .type = QUIRK_COMPOSITE, | ||
| 1589 | .data = (const struct snd_usb_audio_quirk[]) { | ||
| 1590 | { | ||
| 1591 | .ifnum = 0, | ||
| 1592 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
| 1593 | }, | ||
| 1594 | { | ||
| 1595 | .ifnum = 1, | ||
| 1596 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
| 1597 | }, | ||
| 1598 | { | ||
| 1599 | .ifnum = 2, | ||
| 1600 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
| 1601 | .data = & (const struct snd_usb_midi_endpoint_info) { | ||
| 1602 | .out_cables = 0x0001, | ||
| 1603 | .in_cables = 0x0001 | ||
| 1604 | } | ||
| 1605 | }, | ||
| 1606 | { | ||
| 1607 | .ifnum = -1 | ||
| 1608 | } | ||
| 1609 | } | ||
| 1610 | } | ||
| 1611 | }, | ||
| 1612 | { | ||
| 1584 | /* only 44.1 kHz works at the moment */ | 1613 | /* only 44.1 kHz works at the moment */ |
| 1585 | USB_DEVICE(0x0582, 0x0120), | 1614 | USB_DEVICE(0x0582, 0x0120), |
| 1586 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | 1615 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { |
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index d0396af99fa0..5b1b807265a1 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c | |||
| @@ -267,90 +267,90 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr) | |||
| 267 | /* | 267 | /* |
| 268 | * Example Format w/ field column widths: | 268 | * Example Format w/ field column widths: |
| 269 | * | 269 | * |
| 270 | * Package Core CPU Avg_MHz Bzy_MHz TSC_MHz SMI %Busy CPU_%c1 CPU_%c3 CPU_%c6 CPU_%c7 CoreTmp PkgTmp Pkg%pc2 Pkg%pc3 Pkg%pc6 Pkg%pc7 PkgWatt CorWatt GFXWatt | 270 | * Package Core CPU Avg_MHz Bzy_MHz TSC_MHz SMI %Busy CPU_%c1 CPU_%c3 CPU_%c6 CPU_%c7 CoreTmp PkgTmp Pkg%pc2 Pkg%pc3 Pkg%pc6 Pkg%pc7 PkgWatt CorWatt GFXWatt |
| 271 | * 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 | 271 | * 123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678 |
| 272 | */ | 272 | */ |
| 273 | 273 | ||
| 274 | void print_header(void) | 274 | void print_header(void) |
| 275 | { | 275 | { |
| 276 | if (show_pkg) | 276 | if (show_pkg) |
| 277 | outp += sprintf(outp, "Package "); | 277 | outp += sprintf(outp, " Package"); |
| 278 | if (show_core) | 278 | if (show_core) |
| 279 | outp += sprintf(outp, " Core "); | 279 | outp += sprintf(outp, " Core"); |
| 280 | if (show_cpu) | 280 | if (show_cpu) |
| 281 | outp += sprintf(outp, " CPU "); | 281 | outp += sprintf(outp, " CPU"); |
| 282 | if (has_aperf) | 282 | if (has_aperf) |
| 283 | outp += sprintf(outp, "Avg_MHz "); | 283 | outp += sprintf(outp, " Avg_MHz"); |
| 284 | if (do_nhm_cstates) | 284 | if (do_nhm_cstates) |
| 285 | outp += sprintf(outp, " %%Busy "); | 285 | outp += sprintf(outp, " %%Busy"); |
| 286 | if (has_aperf) | 286 | if (has_aperf) |
| 287 | outp += sprintf(outp, "Bzy_MHz "); | 287 | outp += sprintf(outp, " Bzy_MHz"); |
| 288 | outp += sprintf(outp, "TSC_MHz "); | 288 | outp += sprintf(outp, " TSC_MHz"); |
| 289 | if (do_smi) | 289 | if (do_smi) |
| 290 | outp += sprintf(outp, " SMI "); | 290 | outp += sprintf(outp, " SMI"); |
| 291 | if (extra_delta_offset32) | 291 | if (extra_delta_offset32) |
| 292 | outp += sprintf(outp, " count 0x%03X ", extra_delta_offset32); | 292 | outp += sprintf(outp, " count 0x%03X", extra_delta_offset32); |
| 293 | if (extra_delta_offset64) | 293 | if (extra_delta_offset64) |
| 294 | outp += sprintf(outp, " COUNT 0x%03X ", extra_delta_offset64); | 294 | outp += sprintf(outp, " COUNT 0x%03X", extra_delta_offset64); |
| 295 | if (extra_msr_offset32) | 295 | if (extra_msr_offset32) |
| 296 | outp += sprintf(outp, " MSR 0x%03X ", extra_msr_offset32); | 296 | outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset32); |
| 297 | if (extra_msr_offset64) | 297 | if (extra_msr_offset64) |
| 298 | outp += sprintf(outp, " MSR 0x%03X ", extra_msr_offset64); | 298 | outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset64); |
| 299 | if (do_nhm_cstates) | 299 | if (do_nhm_cstates) |
| 300 | outp += sprintf(outp, " CPU%%c1 "); | 300 | outp += sprintf(outp, " CPU%%c1"); |
| 301 | if (do_nhm_cstates && !do_slm_cstates) | 301 | if (do_nhm_cstates && !do_slm_cstates) |
| 302 | outp += sprintf(outp, " CPU%%c3 "); | 302 | outp += sprintf(outp, " CPU%%c3"); |
| 303 | if (do_nhm_cstates) | 303 | if (do_nhm_cstates) |
| 304 | outp += sprintf(outp, " CPU%%c6 "); | 304 | outp += sprintf(outp, " CPU%%c6"); |
| 305 | if (do_snb_cstates) | 305 | if (do_snb_cstates) |
| 306 | outp += sprintf(outp, " CPU%%c7 "); | 306 | outp += sprintf(outp, " CPU%%c7"); |
| 307 | 307 | ||
| 308 | if (do_dts) | 308 | if (do_dts) |
| 309 | outp += sprintf(outp, "CoreTmp "); | 309 | outp += sprintf(outp, " CoreTmp"); |
| 310 | if (do_ptm) | 310 | if (do_ptm) |
| 311 | outp += sprintf(outp, " PkgTmp "); | 311 | outp += sprintf(outp, " PkgTmp"); |
| 312 | 312 | ||
| 313 | if (do_snb_cstates) | 313 | if (do_snb_cstates) |
| 314 | outp += sprintf(outp, "Pkg%%pc2 "); | 314 | outp += sprintf(outp, " Pkg%%pc2"); |
| 315 | if (do_nhm_cstates && !do_slm_cstates) | 315 | if (do_nhm_cstates && !do_slm_cstates) |
| 316 | outp += sprintf(outp, "Pkg%%pc3 "); | 316 | outp += sprintf(outp, " Pkg%%pc3"); |
| 317 | if (do_nhm_cstates && !do_slm_cstates) | 317 | if (do_nhm_cstates && !do_slm_cstates) |
| 318 | outp += sprintf(outp, "Pkg%%pc6 "); | 318 | outp += sprintf(outp, " Pkg%%pc6"); |
| 319 | if (do_snb_cstates) | 319 | if (do_snb_cstates) |
| 320 | outp += sprintf(outp, "Pkg%%pc7 "); | 320 | outp += sprintf(outp, " Pkg%%pc7"); |
| 321 | if (do_c8_c9_c10) { | 321 | if (do_c8_c9_c10) { |
| 322 | outp += sprintf(outp, "Pkg%%pc8 "); | 322 | outp += sprintf(outp, " Pkg%%pc8"); |
| 323 | outp += sprintf(outp, "Pkg%%pc9 "); | 323 | outp += sprintf(outp, " Pkg%%pc9"); |
| 324 | outp += sprintf(outp, "Pk%%pc10 "); | 324 | outp += sprintf(outp, " Pk%%pc10"); |
| 325 | } | 325 | } |
| 326 | 326 | ||
| 327 | if (do_rapl && !rapl_joules) { | 327 | if (do_rapl && !rapl_joules) { |
| 328 | if (do_rapl & RAPL_PKG) | 328 | if (do_rapl & RAPL_PKG) |
| 329 | outp += sprintf(outp, "PkgWatt "); | 329 | outp += sprintf(outp, " PkgWatt"); |
| 330 | if (do_rapl & RAPL_CORES) | 330 | if (do_rapl & RAPL_CORES) |
| 331 | outp += sprintf(outp, "CorWatt "); | 331 | outp += sprintf(outp, " CorWatt"); |
| 332 | if (do_rapl & RAPL_GFX) | 332 | if (do_rapl & RAPL_GFX) |
| 333 | outp += sprintf(outp, "GFXWatt "); | 333 | outp += sprintf(outp, " GFXWatt"); |
| 334 | if (do_rapl & RAPL_DRAM) | 334 | if (do_rapl & RAPL_DRAM) |
| 335 | outp += sprintf(outp, "RAMWatt "); | 335 | outp += sprintf(outp, " RAMWatt"); |
| 336 | if (do_rapl & RAPL_PKG_PERF_STATUS) | 336 | if (do_rapl & RAPL_PKG_PERF_STATUS) |
| 337 | outp += sprintf(outp, " PKG_%% "); | 337 | outp += sprintf(outp, " PKG_%%"); |
| 338 | if (do_rapl & RAPL_DRAM_PERF_STATUS) | 338 | if (do_rapl & RAPL_DRAM_PERF_STATUS) |
| 339 | outp += sprintf(outp, " RAM_%% "); | 339 | outp += sprintf(outp, " RAM_%%"); |
| 340 | } else { | 340 | } else { |
| 341 | if (do_rapl & RAPL_PKG) | 341 | if (do_rapl & RAPL_PKG) |
| 342 | outp += sprintf(outp, " Pkg_J "); | 342 | outp += sprintf(outp, " Pkg_J"); |
| 343 | if (do_rapl & RAPL_CORES) | 343 | if (do_rapl & RAPL_CORES) |
| 344 | outp += sprintf(outp, " Cor_J "); | 344 | outp += sprintf(outp, " Cor_J"); |
| 345 | if (do_rapl & RAPL_GFX) | 345 | if (do_rapl & RAPL_GFX) |
| 346 | outp += sprintf(outp, " GFX_J "); | 346 | outp += sprintf(outp, " GFX_J"); |
| 347 | if (do_rapl & RAPL_DRAM) | 347 | if (do_rapl & RAPL_DRAM) |
| 348 | outp += sprintf(outp, " RAM_W "); | 348 | outp += sprintf(outp, " RAM_W"); |
| 349 | if (do_rapl & RAPL_PKG_PERF_STATUS) | 349 | if (do_rapl & RAPL_PKG_PERF_STATUS) |
| 350 | outp += sprintf(outp, " PKG_%% "); | 350 | outp += sprintf(outp, " PKG_%%"); |
| 351 | if (do_rapl & RAPL_DRAM_PERF_STATUS) | 351 | if (do_rapl & RAPL_DRAM_PERF_STATUS) |
| 352 | outp += sprintf(outp, " RAM_%% "); | 352 | outp += sprintf(outp, " RAM_%%"); |
| 353 | outp += sprintf(outp, " time "); | 353 | outp += sprintf(outp, " time"); |
| 354 | 354 | ||
| 355 | } | 355 | } |
| 356 | outp += sprintf(outp, "\n"); | 356 | outp += sprintf(outp, "\n"); |
diff --git a/virt/kvm/assigned-dev.c b/virt/kvm/assigned-dev.c index bf06577fea51..5819a2708d7e 100644 --- a/virt/kvm/assigned-dev.c +++ b/virt/kvm/assigned-dev.c | |||
| @@ -526,8 +526,10 @@ static int assign_guest_irq(struct kvm *kvm, | |||
| 526 | dev->irq_requested_type |= guest_irq_type; | 526 | dev->irq_requested_type |= guest_irq_type; |
| 527 | if (dev->ack_notifier.gsi != -1) | 527 | if (dev->ack_notifier.gsi != -1) |
| 528 | kvm_register_irq_ack_notifier(kvm, &dev->ack_notifier); | 528 | kvm_register_irq_ack_notifier(kvm, &dev->ack_notifier); |
| 529 | } else | 529 | } else { |
| 530 | kvm_free_irq_source_id(kvm, dev->irq_source_id); | 530 | kvm_free_irq_source_id(kvm, dev->irq_source_id); |
| 531 | dev->irq_source_id = -1; | ||
| 532 | } | ||
| 531 | 533 | ||
| 532 | return r; | 534 | return r; |
| 533 | } | 535 | } |
diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c index 0df7d4b34dfe..714b94932312 100644 --- a/virt/kvm/iommu.c +++ b/virt/kvm/iommu.c | |||
| @@ -61,6 +61,14 @@ static pfn_t kvm_pin_pages(struct kvm_memory_slot *slot, gfn_t gfn, | |||
| 61 | return pfn; | 61 | return pfn; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | static void kvm_unpin_pages(struct kvm *kvm, pfn_t pfn, unsigned long npages) | ||
| 65 | { | ||
| 66 | unsigned long i; | ||
| 67 | |||
| 68 | for (i = 0; i < npages; ++i) | ||
| 69 | kvm_release_pfn_clean(pfn + i); | ||
| 70 | } | ||
| 71 | |||
| 64 | int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot) | 72 | int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot) |
| 65 | { | 73 | { |
| 66 | gfn_t gfn, end_gfn; | 74 | gfn_t gfn, end_gfn; |
| @@ -123,6 +131,7 @@ int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot) | |||
| 123 | if (r) { | 131 | if (r) { |
| 124 | printk(KERN_ERR "kvm_iommu_map_address:" | 132 | printk(KERN_ERR "kvm_iommu_map_address:" |
| 125 | "iommu failed to map pfn=%llx\n", pfn); | 133 | "iommu failed to map pfn=%llx\n", pfn); |
| 134 | kvm_unpin_pages(kvm, pfn, page_size); | ||
| 126 | goto unmap_pages; | 135 | goto unmap_pages; |
| 127 | } | 136 | } |
| 128 | 137 | ||
| @@ -134,7 +143,7 @@ int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot) | |||
| 134 | return 0; | 143 | return 0; |
| 135 | 144 | ||
| 136 | unmap_pages: | 145 | unmap_pages: |
| 137 | kvm_iommu_put_pages(kvm, slot->base_gfn, gfn); | 146 | kvm_iommu_put_pages(kvm, slot->base_gfn, gfn - slot->base_gfn); |
| 138 | return r; | 147 | return r; |
| 139 | } | 148 | } |
| 140 | 149 | ||
| @@ -266,14 +275,6 @@ out_unlock: | |||
| 266 | return r; | 275 | return r; |
| 267 | } | 276 | } |
| 268 | 277 | ||
| 269 | static void kvm_unpin_pages(struct kvm *kvm, pfn_t pfn, unsigned long npages) | ||
| 270 | { | ||
| 271 | unsigned long i; | ||
| 272 | |||
| 273 | for (i = 0; i < npages; ++i) | ||
| 274 | kvm_release_pfn_clean(pfn + i); | ||
| 275 | } | ||
| 276 | |||
| 277 | static void kvm_iommu_put_pages(struct kvm *kvm, | 278 | static void kvm_iommu_put_pages(struct kvm *kvm, |
| 278 | gfn_t base_gfn, unsigned long npages) | 279 | gfn_t base_gfn, unsigned long npages) |
| 279 | { | 280 | { |
