mirror of
https://github.com/torvalds/linux.git
synced 2026-06-08 14:42:37 +02:00
Merge branch 'linux-linaro-lsk-v4.4' into linux-linaro-lsk-v4.4-android
This commit is contained in:
commit
08562bfcb8
96
MAINTAINERS
96
MAINTAINERS
|
|
@ -230,13 +230,13 @@ F: kernel/sys_ni.c
|
|||
|
||||
ABIT UGURU 1,2 HARDWARE MONITOR DRIVER
|
||||
M: Hans de Goede <hdegoede@redhat.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/hwmon/abituguru.c
|
||||
|
||||
ABIT UGURU 3 HARDWARE MONITOR DRIVER
|
||||
M: Alistair John Strachan <alistair@devzero.co.uk>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/hwmon/abituguru3.c
|
||||
|
||||
|
|
@ -373,14 +373,14 @@ S: Maintained
|
|||
|
||||
ADM1025 HARDWARE MONITOR DRIVER
|
||||
M: Jean Delvare <jdelvare@suse.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/adm1025
|
||||
F: drivers/hwmon/adm1025.c
|
||||
|
||||
ADM1029 HARDWARE MONITOR DRIVER
|
||||
M: Corentin Labbe <clabbe.montjoie@gmail.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/hwmon/adm1029.c
|
||||
|
||||
|
|
@ -425,7 +425,7 @@ F: drivers/video/backlight/adp8860_bl.c
|
|||
|
||||
ADS1015 HARDWARE MONITOR DRIVER
|
||||
M: Dirk Eibach <eibach@gdsys.de>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/ads1015
|
||||
F: drivers/hwmon/ads1015.c
|
||||
|
|
@ -438,7 +438,7 @@ F: drivers/macintosh/therm_adt746x.c
|
|||
|
||||
ADT7475 HARDWARE MONITOR DRIVER
|
||||
M: Jean Delvare <jdelvare@suse.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/adt7475
|
||||
F: drivers/hwmon/adt7475.c
|
||||
|
|
@ -615,7 +615,7 @@ F: include/linux/ccp.h
|
|||
|
||||
AMD FAM15H PROCESSOR POWER MONITORING DRIVER
|
||||
M: Andreas Herrmann <herrmann.der.user@googlemail.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/fam15h_power
|
||||
F: drivers/hwmon/fam15h_power.c
|
||||
|
|
@ -779,7 +779,7 @@ F: drivers/input/mouse/bcm5974.c
|
|||
|
||||
APPLE SMC DRIVER
|
||||
M: Henrik Rydberg <rydberg@bitmath.org>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Odd fixes
|
||||
F: drivers/hwmon/applesmc.c
|
||||
|
||||
|
|
@ -1777,7 +1777,7 @@ F: include/media/as3645a.h
|
|||
|
||||
ASC7621 HARDWARE MONITOR DRIVER
|
||||
M: George Joseph <george.joseph@fairview5.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/asc7621
|
||||
F: drivers/hwmon/asc7621.c
|
||||
|
|
@ -1864,7 +1864,7 @@ F: drivers/net/wireless/ath/carl9170/
|
|||
|
||||
ATK0110 HWMON DRIVER
|
||||
M: Luca Tettamanti <kronos.it@gmail.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/hwmon/asus_atk0110.c
|
||||
|
||||
|
|
@ -2984,7 +2984,7 @@ F: mm/swap_cgroup.c
|
|||
|
||||
CORETEMP HARDWARE MONITORING DRIVER
|
||||
M: Fenghua Yu <fenghua.yu@intel.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/coretemp
|
||||
F: drivers/hwmon/coretemp.c
|
||||
|
|
@ -3549,7 +3549,7 @@ T: git git://git.infradead.org/users/vkoul/slave-dma.git
|
|||
|
||||
DME1737 HARDWARE MONITOR DRIVER
|
||||
M: Juerg Haefliger <juergh@gmail.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/dme1737
|
||||
F: drivers/hwmon/dme1737.c
|
||||
|
|
@ -4262,7 +4262,7 @@ F: include/video/exynos_mipi*
|
|||
|
||||
F71805F HARDWARE MONITORING DRIVER
|
||||
M: Jean Delvare <jdelvare@suse.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/f71805f
|
||||
F: drivers/hwmon/f71805f.c
|
||||
|
|
@ -4341,7 +4341,7 @@ F: fs/*
|
|||
|
||||
FINTEK F75375S HARDWARE MONITOR AND FAN CONTROLLER DRIVER
|
||||
M: Riku Voipio <riku.voipio@iki.fi>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/hwmon/f75375s.c
|
||||
F: include/linux/f75375s.h
|
||||
|
|
@ -4883,8 +4883,8 @@ F: drivers/media/usb/hackrf/
|
|||
HARDWARE MONITORING
|
||||
M: Jean Delvare <jdelvare@suse.com>
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
W: http://www.lm-sensors.org/
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
W: http://hwmon.wiki.kernel.org/
|
||||
T: quilt http://jdelvare.nerim.net/devel/linux/jdelvare-hwmon/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
|
||||
S: Maintained
|
||||
|
|
@ -5393,7 +5393,7 @@ F: drivers/usb/atm/ueagle-atm.c
|
|||
|
||||
INA209 HARDWARE MONITOR DRIVER
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/ina209
|
||||
F: Documentation/devicetree/bindings/i2c/ina209.txt
|
||||
|
|
@ -5401,7 +5401,7 @@ F: drivers/hwmon/ina209.c
|
|||
|
||||
INA2XX HARDWARE MONITOR DRIVER
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/ina2xx
|
||||
F: drivers/hwmon/ina2xx.c
|
||||
|
|
@ -5884,7 +5884,7 @@ F: drivers/isdn/hardware/eicon/
|
|||
|
||||
IT87 HARDWARE MONITORING DRIVER
|
||||
M: Jean Delvare <jdelvare@suse.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/it87
|
||||
F: drivers/hwmon/it87.c
|
||||
|
|
@ -5920,7 +5920,7 @@ F: drivers/media/dvb-frontends/ix2505v*
|
|||
|
||||
JC42.4 TEMPERATURE SENSOR DRIVER
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/hwmon/jc42.c
|
||||
F: Documentation/hwmon/jc42
|
||||
|
|
@ -5970,14 +5970,14 @@ F: drivers/tty/serial/jsm/
|
|||
|
||||
K10TEMP HARDWARE MONITORING DRIVER
|
||||
M: Clemens Ladisch <clemens@ladisch.de>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/k10temp
|
||||
F: drivers/hwmon/k10temp.c
|
||||
|
||||
K8TEMP HARDWARE MONITORING DRIVER
|
||||
M: Rudolf Marek <r.marek@assembler.cz>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/k8temp
|
||||
F: drivers/hwmon/k8temp.c
|
||||
|
|
@ -6485,27 +6485,27 @@ F: net/llc/
|
|||
|
||||
LM73 HARDWARE MONITOR DRIVER
|
||||
M: Guillaume Ligneul <guillaume.ligneul@gmail.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/hwmon/lm73.c
|
||||
|
||||
LM78 HARDWARE MONITOR DRIVER
|
||||
M: Jean Delvare <jdelvare@suse.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/lm78
|
||||
F: drivers/hwmon/lm78.c
|
||||
|
||||
LM83 HARDWARE MONITOR DRIVER
|
||||
M: Jean Delvare <jdelvare@suse.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/lm83
|
||||
F: drivers/hwmon/lm83.c
|
||||
|
||||
LM90 HARDWARE MONITOR DRIVER
|
||||
M: Jean Delvare <jdelvare@suse.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/lm90
|
||||
F: Documentation/devicetree/bindings/hwmon/lm90.txt
|
||||
|
|
@ -6513,7 +6513,7 @@ F: drivers/hwmon/lm90.c
|
|||
|
||||
LM95234 HARDWARE MONITOR DRIVER
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/lm95234
|
||||
F: drivers/hwmon/lm95234.c
|
||||
|
|
@ -6580,7 +6580,7 @@ F: drivers/scsi/sym53c8xx_2/
|
|||
|
||||
LTC4261 HARDWARE MONITOR DRIVER
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/ltc4261
|
||||
F: drivers/hwmon/ltc4261.c
|
||||
|
|
@ -6749,28 +6749,28 @@ F: include/uapi/linux/matroxfb.h
|
|||
|
||||
MAX16065 HARDWARE MONITOR DRIVER
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/max16065
|
||||
F: drivers/hwmon/max16065.c
|
||||
|
||||
MAX20751 HARDWARE MONITOR DRIVER
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/max20751
|
||||
F: drivers/hwmon/max20751.c
|
||||
|
||||
MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER
|
||||
M: "Hans J. Koch" <hjk@hansjkoch.de>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/max6650
|
||||
F: drivers/hwmon/max6650.c
|
||||
|
||||
MAX6697 HARDWARE MONITOR DRIVER
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/max6697
|
||||
F: Documentation/devicetree/bindings/i2c/max6697.txt
|
||||
|
|
@ -7303,7 +7303,7 @@ F: drivers/scsi/NCR_D700.*
|
|||
|
||||
NCT6775 HARDWARE MONITOR DRIVER
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/nct6775
|
||||
F: drivers/hwmon/nct6775.c
|
||||
|
|
@ -8064,7 +8064,7 @@ F: drivers/video/logo/logo_parisc*
|
|||
|
||||
PC87360 HARDWARE MONITORING DRIVER
|
||||
M: Jim Cromie <jim.cromie@gmail.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/pc87360
|
||||
F: drivers/hwmon/pc87360.c
|
||||
|
|
@ -8076,7 +8076,7 @@ F: drivers/char/pc8736x_gpio.c
|
|||
|
||||
PC87427 HARDWARE MONITORING DRIVER
|
||||
M: Jean Delvare <jdelvare@suse.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/pc87427
|
||||
F: drivers/hwmon/pc87427.c
|
||||
|
|
@ -8415,8 +8415,8 @@ F: drivers/rtc/rtc-puv3.c
|
|||
|
||||
PMBUS HARDWARE MONITORING DRIVERS
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
W: http://www.lm-sensors.org/
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
W: http://hwmon.wiki.kernel.org/
|
||||
W: http://www.roeck-us.net/linux/drivers/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
|
||||
S: Maintained
|
||||
|
|
@ -8610,7 +8610,7 @@ F: drivers/media/usb/pwc/*
|
|||
|
||||
PWM FAN DRIVER
|
||||
M: Kamil Debski <k.debski@samsung.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/hwmon/pwm-fan.txt
|
||||
F: Documentation/hwmon/pwm-fan
|
||||
|
|
@ -9882,28 +9882,28 @@ F: Documentation/devicetree/bindings/media/i2c/nokia,smia.txt
|
|||
|
||||
SMM665 HARDWARE MONITOR DRIVER
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/smm665
|
||||
F: drivers/hwmon/smm665.c
|
||||
|
||||
SMSC EMC2103 HARDWARE MONITOR DRIVER
|
||||
M: Steve Glendinning <steve.glendinning@shawell.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/emc2103
|
||||
F: drivers/hwmon/emc2103.c
|
||||
|
||||
SMSC SCH5627 HARDWARE MONITOR DRIVER
|
||||
M: Hans de Goede <hdegoede@redhat.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/hwmon/sch5627
|
||||
F: drivers/hwmon/sch5627.c
|
||||
|
||||
SMSC47B397 HARDWARE MONITOR DRIVER
|
||||
M: Jean Delvare <jdelvare@suse.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/smsc47b397
|
||||
F: drivers/hwmon/smsc47b397.c
|
||||
|
|
@ -10830,7 +10830,7 @@ F: include/linux/mmc/sh_mobile_sdhi.h
|
|||
|
||||
TMP401 HARDWARE MONITOR DRIVER
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/tmp401
|
||||
F: drivers/hwmon/tmp401.c
|
||||
|
|
@ -11564,14 +11564,14 @@ F: Documentation/networking/vrf.txt
|
|||
|
||||
VT1211 HARDWARE MONITOR DRIVER
|
||||
M: Juerg Haefliger <juergh@gmail.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/vt1211
|
||||
F: drivers/hwmon/vt1211.c
|
||||
|
||||
VT8231 HARDWARE MONITOR DRIVER
|
||||
M: Roger Lucas <vt8231@hiddenengine.co.uk>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/hwmon/vt8231.c
|
||||
|
||||
|
|
@ -11590,21 +11590,21 @@ F: drivers/w1/
|
|||
|
||||
W83791D HARDWARE MONITORING DRIVER
|
||||
M: Marc Hulsman <m.hulsman@tudelft.nl>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/w83791d
|
||||
F: drivers/hwmon/w83791d.c
|
||||
|
||||
W83793 HARDWARE MONITORING DRIVER
|
||||
M: Rudolf Marek <r.marek@assembler.cz>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/w83793
|
||||
F: drivers/hwmon/w83793.c
|
||||
|
||||
W83795 HARDWARE MONITORING DRIVER
|
||||
M: Jean Delvare <jdelvare@suse.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/hwmon/w83795.c
|
||||
|
||||
|
|
|
|||
2
Makefile
2
Makefile
|
|
@ -1,6 +1,6 @@
|
|||
VERSION = 4
|
||||
PATCHLEVEL = 4
|
||||
SUBLEVEL = 6
|
||||
SUBLEVEL = 7
|
||||
EXTRAVERSION =
|
||||
NAME = Blurry Fish Butt
|
||||
|
||||
|
|
|
|||
|
|
@ -35,21 +35,6 @@ static inline void op##_bit(unsigned long nr, volatile unsigned long *m)\
|
|||
\
|
||||
m += nr >> 5; \
|
||||
\
|
||||
/* \
|
||||
* ARC ISA micro-optimization: \
|
||||
* \
|
||||
* Instructions dealing with bitpos only consider lower 5 bits \
|
||||
* e.g (x << 33) is handled like (x << 1) by ASL instruction \
|
||||
* (mem pointer still needs adjustment to point to next word) \
|
||||
* \
|
||||
* Hence the masking to clamp @nr arg can be elided in general. \
|
||||
* \
|
||||
* However if @nr is a constant (above assumed in a register), \
|
||||
* and greater than 31, gcc can optimize away (x << 33) to 0, \
|
||||
* as overflow, given the 32-bit ISA. Thus masking needs to be \
|
||||
* done for const @nr, but no code is generated due to gcc \
|
||||
* const prop. \
|
||||
*/ \
|
||||
nr &= 0x1f; \
|
||||
\
|
||||
__asm__ __volatile__( \
|
||||
|
|
|
|||
|
|
@ -129,15 +129,23 @@ static inline void __raw_writel(u32 w, volatile void __iomem *addr)
|
|||
#define writel(v,c) ({ __iowmb(); writel_relaxed(v,c); })
|
||||
|
||||
/*
|
||||
* Relaxed API for drivers which can handle any ordering themselves
|
||||
* Relaxed API for drivers which can handle barrier ordering themselves
|
||||
*
|
||||
* Also these are defined to perform little endian accesses.
|
||||
* To provide the typical device register semantics of fixed endian,
|
||||
* swap the byte order for Big Endian
|
||||
*
|
||||
* http://lkml.kernel.org/r/201603100845.30602.arnd@arndb.de
|
||||
*/
|
||||
#define readb_relaxed(c) __raw_readb(c)
|
||||
#define readw_relaxed(c) __raw_readw(c)
|
||||
#define readl_relaxed(c) __raw_readl(c)
|
||||
#define readw_relaxed(c) ({ u16 __r = le16_to_cpu((__force __le16) \
|
||||
__raw_readw(c)); __r; })
|
||||
#define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \
|
||||
__raw_readl(c)); __r; })
|
||||
|
||||
#define writeb_relaxed(v,c) __raw_writeb(v,c)
|
||||
#define writew_relaxed(v,c) __raw_writew(v,c)
|
||||
#define writel_relaxed(v,c) __raw_writel(v,c)
|
||||
#define writew_relaxed(v,c) __raw_writew((__force u16) cpu_to_le16(v),c)
|
||||
#define writel_relaxed(v,c) __raw_writel((__force u32) cpu_to_le32(v),c)
|
||||
|
||||
#include <asm-generic/io.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -303,6 +303,7 @@ vcc_mmc0_reg: fixedregulator@0 {
|
|||
regulator-name = "mmc0-card-supply";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
gpio_keys {
|
||||
|
|
|
|||
|
|
@ -268,5 +268,6 @@ vcc_mmc1_reg: fixedregulator@1 {
|
|||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
vin-supply = <&vcc_3v3_reg>;
|
||||
regulator-always-on;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -54,12 +54,12 @@ static int s3c64xx_i2s_cfg_gpio(struct platform_device *pdev)
|
|||
|
||||
static struct resource s3c64xx_iis0_resource[] = {
|
||||
[0] = DEFINE_RES_MEM(S3C64XX_PA_IIS0, SZ_256),
|
||||
[1] = DEFINE_RES_DMA(DMACH_I2S0_OUT),
|
||||
[2] = DEFINE_RES_DMA(DMACH_I2S0_IN),
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata i2sv3_pdata = {
|
||||
static struct s3c_audio_pdata i2s0_pdata = {
|
||||
.cfg_gpio = s3c64xx_i2s_cfg_gpio,
|
||||
.dma_playback = DMACH_I2S0_OUT,
|
||||
.dma_capture = DMACH_I2S0_IN,
|
||||
};
|
||||
|
||||
struct platform_device s3c64xx_device_iis0 = {
|
||||
|
|
@ -68,15 +68,19 @@ struct platform_device s3c64xx_device_iis0 = {
|
|||
.num_resources = ARRAY_SIZE(s3c64xx_iis0_resource),
|
||||
.resource = s3c64xx_iis0_resource,
|
||||
.dev = {
|
||||
.platform_data = &i2sv3_pdata,
|
||||
.platform_data = &i2s0_pdata,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(s3c64xx_device_iis0);
|
||||
|
||||
static struct resource s3c64xx_iis1_resource[] = {
|
||||
[0] = DEFINE_RES_MEM(S3C64XX_PA_IIS1, SZ_256),
|
||||
[1] = DEFINE_RES_DMA(DMACH_I2S1_OUT),
|
||||
[2] = DEFINE_RES_DMA(DMACH_I2S1_IN),
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata i2s1_pdata = {
|
||||
.cfg_gpio = s3c64xx_i2s_cfg_gpio,
|
||||
.dma_playback = DMACH_I2S1_OUT,
|
||||
.dma_capture = DMACH_I2S1_IN,
|
||||
};
|
||||
|
||||
struct platform_device s3c64xx_device_iis1 = {
|
||||
|
|
@ -85,19 +89,19 @@ struct platform_device s3c64xx_device_iis1 = {
|
|||
.num_resources = ARRAY_SIZE(s3c64xx_iis1_resource),
|
||||
.resource = s3c64xx_iis1_resource,
|
||||
.dev = {
|
||||
.platform_data = &i2sv3_pdata,
|
||||
.platform_data = &i2s1_pdata,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(s3c64xx_device_iis1);
|
||||
|
||||
static struct resource s3c64xx_iisv4_resource[] = {
|
||||
[0] = DEFINE_RES_MEM(S3C64XX_PA_IISV4, SZ_256),
|
||||
[1] = DEFINE_RES_DMA(DMACH_HSI_I2SV40_TX),
|
||||
[2] = DEFINE_RES_DMA(DMACH_HSI_I2SV40_RX),
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata i2sv4_pdata = {
|
||||
.cfg_gpio = s3c64xx_i2s_cfg_gpio,
|
||||
.dma_playback = DMACH_HSI_I2SV40_TX,
|
||||
.dma_capture = DMACH_HSI_I2SV40_RX,
|
||||
.type = {
|
||||
.i2s = {
|
||||
.quirks = QUIRK_PRI_6CHAN,
|
||||
|
|
@ -142,12 +146,12 @@ static int s3c64xx_pcm_cfg_gpio(struct platform_device *pdev)
|
|||
|
||||
static struct resource s3c64xx_pcm0_resource[] = {
|
||||
[0] = DEFINE_RES_MEM(S3C64XX_PA_PCM0, SZ_256),
|
||||
[1] = DEFINE_RES_DMA(DMACH_PCM0_TX),
|
||||
[2] = DEFINE_RES_DMA(DMACH_PCM0_RX),
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata s3c_pcm0_pdata = {
|
||||
.cfg_gpio = s3c64xx_pcm_cfg_gpio,
|
||||
.dma_capture = DMACH_PCM0_RX,
|
||||
.dma_playback = DMACH_PCM0_TX,
|
||||
};
|
||||
|
||||
struct platform_device s3c64xx_device_pcm0 = {
|
||||
|
|
@ -163,12 +167,12 @@ EXPORT_SYMBOL(s3c64xx_device_pcm0);
|
|||
|
||||
static struct resource s3c64xx_pcm1_resource[] = {
|
||||
[0] = DEFINE_RES_MEM(S3C64XX_PA_PCM1, SZ_256),
|
||||
[1] = DEFINE_RES_DMA(DMACH_PCM1_TX),
|
||||
[2] = DEFINE_RES_DMA(DMACH_PCM1_RX),
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata s3c_pcm1_pdata = {
|
||||
.cfg_gpio = s3c64xx_pcm_cfg_gpio,
|
||||
.dma_playback = DMACH_PCM1_TX,
|
||||
.dma_capture = DMACH_PCM1_RX,
|
||||
};
|
||||
|
||||
struct platform_device s3c64xx_device_pcm1 = {
|
||||
|
|
@ -196,13 +200,14 @@ static int s3c64xx_ac97_cfg_gpe(struct platform_device *pdev)
|
|||
|
||||
static struct resource s3c64xx_ac97_resource[] = {
|
||||
[0] = DEFINE_RES_MEM(S3C64XX_PA_AC97, SZ_256),
|
||||
[1] = DEFINE_RES_DMA(DMACH_AC97_PCMOUT),
|
||||
[2] = DEFINE_RES_DMA(DMACH_AC97_PCMIN),
|
||||
[3] = DEFINE_RES_DMA(DMACH_AC97_MICIN),
|
||||
[4] = DEFINE_RES_IRQ(IRQ_AC97),
|
||||
[1] = DEFINE_RES_IRQ(IRQ_AC97),
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata s3c_ac97_pdata;
|
||||
static struct s3c_audio_pdata s3c_ac97_pdata = {
|
||||
.dma_playback = DMACH_AC97_PCMOUT,
|
||||
.dma_capture = DMACH_AC97_PCMIN,
|
||||
.dma_capture_mic = DMACH_AC97_MICIN,
|
||||
};
|
||||
|
||||
static u64 s3c64xx_ac97_dmamask = DMA_BIT_MASK(32);
|
||||
|
||||
|
|
|
|||
|
|
@ -14,38 +14,38 @@
|
|||
#define S3C64XX_DMA_CHAN(name) ((unsigned long)(name))
|
||||
|
||||
/* DMA0/SDMA0 */
|
||||
#define DMACH_UART0 S3C64XX_DMA_CHAN("uart0_tx")
|
||||
#define DMACH_UART0_SRC2 S3C64XX_DMA_CHAN("uart0_rx")
|
||||
#define DMACH_UART1 S3C64XX_DMA_CHAN("uart1_tx")
|
||||
#define DMACH_UART1_SRC2 S3C64XX_DMA_CHAN("uart1_rx")
|
||||
#define DMACH_UART2 S3C64XX_DMA_CHAN("uart2_tx")
|
||||
#define DMACH_UART2_SRC2 S3C64XX_DMA_CHAN("uart2_rx")
|
||||
#define DMACH_UART3 S3C64XX_DMA_CHAN("uart3_tx")
|
||||
#define DMACH_UART3_SRC2 S3C64XX_DMA_CHAN("uart3_rx")
|
||||
#define DMACH_PCM0_TX S3C64XX_DMA_CHAN("pcm0_tx")
|
||||
#define DMACH_PCM0_RX S3C64XX_DMA_CHAN("pcm0_rx")
|
||||
#define DMACH_I2S0_OUT S3C64XX_DMA_CHAN("i2s0_tx")
|
||||
#define DMACH_I2S0_IN S3C64XX_DMA_CHAN("i2s0_rx")
|
||||
#define DMACH_UART0 "uart0_tx"
|
||||
#define DMACH_UART0_SRC2 "uart0_rx"
|
||||
#define DMACH_UART1 "uart1_tx"
|
||||
#define DMACH_UART1_SRC2 "uart1_rx"
|
||||
#define DMACH_UART2 "uart2_tx"
|
||||
#define DMACH_UART2_SRC2 "uart2_rx"
|
||||
#define DMACH_UART3 "uart3_tx"
|
||||
#define DMACH_UART3_SRC2 "uart3_rx"
|
||||
#define DMACH_PCM0_TX "pcm0_tx"
|
||||
#define DMACH_PCM0_RX "pcm0_rx"
|
||||
#define DMACH_I2S0_OUT "i2s0_tx"
|
||||
#define DMACH_I2S0_IN "i2s0_rx"
|
||||
#define DMACH_SPI0_TX S3C64XX_DMA_CHAN("spi0_tx")
|
||||
#define DMACH_SPI0_RX S3C64XX_DMA_CHAN("spi0_rx")
|
||||
#define DMACH_HSI_I2SV40_TX S3C64XX_DMA_CHAN("i2s2_tx")
|
||||
#define DMACH_HSI_I2SV40_RX S3C64XX_DMA_CHAN("i2s2_rx")
|
||||
#define DMACH_HSI_I2SV40_TX "i2s2_tx"
|
||||
#define DMACH_HSI_I2SV40_RX "i2s2_rx"
|
||||
|
||||
/* DMA1/SDMA1 */
|
||||
#define DMACH_PCM1_TX S3C64XX_DMA_CHAN("pcm1_tx")
|
||||
#define DMACH_PCM1_RX S3C64XX_DMA_CHAN("pcm1_rx")
|
||||
#define DMACH_I2S1_OUT S3C64XX_DMA_CHAN("i2s1_tx")
|
||||
#define DMACH_I2S1_IN S3C64XX_DMA_CHAN("i2s1_rx")
|
||||
#define DMACH_PCM1_TX "pcm1_tx"
|
||||
#define DMACH_PCM1_RX "pcm1_rx"
|
||||
#define DMACH_I2S1_OUT "i2s1_tx"
|
||||
#define DMACH_I2S1_IN "i2s1_rx"
|
||||
#define DMACH_SPI1_TX S3C64XX_DMA_CHAN("spi1_tx")
|
||||
#define DMACH_SPI1_RX S3C64XX_DMA_CHAN("spi1_rx")
|
||||
#define DMACH_AC97_PCMOUT S3C64XX_DMA_CHAN("ac97_out")
|
||||
#define DMACH_AC97_PCMIN S3C64XX_DMA_CHAN("ac97_in")
|
||||
#define DMACH_AC97_MICIN S3C64XX_DMA_CHAN("ac97_mic")
|
||||
#define DMACH_PWM S3C64XX_DMA_CHAN("pwm")
|
||||
#define DMACH_IRDA S3C64XX_DMA_CHAN("irda")
|
||||
#define DMACH_EXTERNAL S3C64XX_DMA_CHAN("external")
|
||||
#define DMACH_SECURITY_RX S3C64XX_DMA_CHAN("sec_rx")
|
||||
#define DMACH_SECURITY_TX S3C64XX_DMA_CHAN("sec_tx")
|
||||
#define DMACH_AC97_PCMOUT "ac97_out"
|
||||
#define DMACH_AC97_PCMIN "ac97_in"
|
||||
#define DMACH_AC97_MICIN "ac97_mic"
|
||||
#define DMACH_PWM "pwm"
|
||||
#define DMACH_IRDA "irda"
|
||||
#define DMACH_EXTERNAL "external"
|
||||
#define DMACH_SECURITY_RX "sec_rx"
|
||||
#define DMACH_SECURITY_TX "sec_tx"
|
||||
|
||||
enum dma_ch {
|
||||
DMACH_MAX = 32
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@
|
|||
#include <linux/platform_data/usb-ohci-s3c2410.h>
|
||||
#include <plat/usb-phy.h>
|
||||
#include <plat/regs-spi.h>
|
||||
#include <linux/platform_data/asoc-s3c.h>
|
||||
#include <linux/platform_data/spi-s3c64xx.h>
|
||||
|
||||
static u64 samsung_device_dma_mask = DMA_BIT_MASK(32);
|
||||
|
|
@ -74,9 +75,12 @@ static u64 samsung_device_dma_mask = DMA_BIT_MASK(32);
|
|||
static struct resource s3c_ac97_resource[] = {
|
||||
[0] = DEFINE_RES_MEM(S3C2440_PA_AC97, S3C2440_SZ_AC97),
|
||||
[1] = DEFINE_RES_IRQ(IRQ_S3C244X_AC97),
|
||||
[2] = DEFINE_RES_DMA_NAMED(DMACH_PCM_OUT, "PCM out"),
|
||||
[3] = DEFINE_RES_DMA_NAMED(DMACH_PCM_IN, "PCM in"),
|
||||
[4] = DEFINE_RES_DMA_NAMED(DMACH_MIC_IN, "Mic in"),
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata s3c_ac97_pdata = {
|
||||
.dma_playback = (void *)DMACH_PCM_OUT,
|
||||
.dma_capture = (void *)DMACH_PCM_IN,
|
||||
.dma_capture_mic = (void *)DMACH_MIC_IN,
|
||||
};
|
||||
|
||||
struct platform_device s3c_device_ac97 = {
|
||||
|
|
@ -87,6 +91,7 @@ struct platform_device s3c_device_ac97 = {
|
|||
.dev = {
|
||||
.dma_mask = &samsung_device_dma_mask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.platform_data = &s3c_ac97_pdata,
|
||||
}
|
||||
};
|
||||
#endif /* CONFIG_CPU_S3C2440 */
|
||||
|
|
|
|||
|
|
@ -436,6 +436,7 @@ static inline void __iomem * ioremap_cache (unsigned long phys_addr, unsigned lo
|
|||
return ioremap(phys_addr, size);
|
||||
}
|
||||
#define ioremap_cache ioremap_cache
|
||||
#define ioremap_uc ioremap_nocache
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ struct zpci_fmb {
|
|||
u64 rpcit_ops;
|
||||
u64 dma_rbytes;
|
||||
u64 dma_wbytes;
|
||||
} __packed __aligned(16);
|
||||
} __packed __aligned(64);
|
||||
|
||||
enum zpci_state {
|
||||
ZPCI_FN_STATE_RESERVED,
|
||||
|
|
|
|||
|
|
@ -1197,114 +1197,12 @@ cleanup_critical:
|
|||
.quad .Lpsw_idle_lpsw
|
||||
|
||||
.Lcleanup_save_fpu_regs:
|
||||
TSTMSK __LC_CPU_FLAGS,_CIF_FPU
|
||||
bor %r14
|
||||
clg %r9,BASED(.Lcleanup_save_fpu_regs_done)
|
||||
jhe 5f
|
||||
clg %r9,BASED(.Lcleanup_save_fpu_regs_fp)
|
||||
jhe 4f
|
||||
clg %r9,BASED(.Lcleanup_save_fpu_regs_vx_high)
|
||||
jhe 3f
|
||||
clg %r9,BASED(.Lcleanup_save_fpu_regs_vx_low)
|
||||
jhe 2f
|
||||
clg %r9,BASED(.Lcleanup_save_fpu_fpc_end)
|
||||
jhe 1f
|
||||
lg %r2,__LC_CURRENT
|
||||
aghi %r2,__TASK_thread
|
||||
0: # Store floating-point controls
|
||||
stfpc __THREAD_FPU_fpc(%r2)
|
||||
1: # Load register save area and check if VX is active
|
||||
lg %r3,__THREAD_FPU_regs(%r2)
|
||||
TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_VX
|
||||
jz 4f # no VX -> store FP regs
|
||||
2: # Store vector registers (V0-V15)
|
||||
VSTM %v0,%v15,0,%r3 # vstm 0,15,0(3)
|
||||
3: # Store vector registers (V16-V31)
|
||||
VSTM %v16,%v31,256,%r3 # vstm 16,31,256(3)
|
||||
j 5f # -> done, set CIF_FPU flag
|
||||
4: # Store floating-point registers
|
||||
std 0,0(%r3)
|
||||
std 1,8(%r3)
|
||||
std 2,16(%r3)
|
||||
std 3,24(%r3)
|
||||
std 4,32(%r3)
|
||||
std 5,40(%r3)
|
||||
std 6,48(%r3)
|
||||
std 7,56(%r3)
|
||||
std 8,64(%r3)
|
||||
std 9,72(%r3)
|
||||
std 10,80(%r3)
|
||||
std 11,88(%r3)
|
||||
std 12,96(%r3)
|
||||
std 13,104(%r3)
|
||||
std 14,112(%r3)
|
||||
std 15,120(%r3)
|
||||
5: # Set CIF_FPU flag
|
||||
oi __LC_CPU_FLAGS+7,_CIF_FPU
|
||||
lg %r9,48(%r11) # return from save_fpu_regs
|
||||
larl %r9,save_fpu_regs
|
||||
br %r14
|
||||
.Lcleanup_save_fpu_fpc_end:
|
||||
.quad .Lsave_fpu_regs_fpc_end
|
||||
.Lcleanup_save_fpu_regs_vx_low:
|
||||
.quad .Lsave_fpu_regs_vx_low
|
||||
.Lcleanup_save_fpu_regs_vx_high:
|
||||
.quad .Lsave_fpu_regs_vx_high
|
||||
.Lcleanup_save_fpu_regs_fp:
|
||||
.quad .Lsave_fpu_regs_fp
|
||||
.Lcleanup_save_fpu_regs_done:
|
||||
.quad .Lsave_fpu_regs_done
|
||||
|
||||
.Lcleanup_load_fpu_regs:
|
||||
TSTMSK __LC_CPU_FLAGS,_CIF_FPU
|
||||
bnor %r14
|
||||
clg %r9,BASED(.Lcleanup_load_fpu_regs_done)
|
||||
jhe 1f
|
||||
clg %r9,BASED(.Lcleanup_load_fpu_regs_fp)
|
||||
jhe 2f
|
||||
clg %r9,BASED(.Lcleanup_load_fpu_regs_vx_high)
|
||||
jhe 3f
|
||||
clg %r9,BASED(.Lcleanup_load_fpu_regs_vx)
|
||||
jhe 4f
|
||||
lg %r4,__LC_CURRENT
|
||||
aghi %r4,__TASK_thread
|
||||
lfpc __THREAD_FPU_fpc(%r4)
|
||||
TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_VX
|
||||
lg %r4,__THREAD_FPU_regs(%r4) # %r4 <- reg save area
|
||||
jz 2f # -> no VX, load FP regs
|
||||
4: # Load V0 ..V15 registers
|
||||
VLM %v0,%v15,0,%r4
|
||||
3: # Load V16..V31 registers
|
||||
VLM %v16,%v31,256,%r4
|
||||
j 1f
|
||||
2: # Load floating-point registers
|
||||
ld 0,0(%r4)
|
||||
ld 1,8(%r4)
|
||||
ld 2,16(%r4)
|
||||
ld 3,24(%r4)
|
||||
ld 4,32(%r4)
|
||||
ld 5,40(%r4)
|
||||
ld 6,48(%r4)
|
||||
ld 7,56(%r4)
|
||||
ld 8,64(%r4)
|
||||
ld 9,72(%r4)
|
||||
ld 10,80(%r4)
|
||||
ld 11,88(%r4)
|
||||
ld 12,96(%r4)
|
||||
ld 13,104(%r4)
|
||||
ld 14,112(%r4)
|
||||
ld 15,120(%r4)
|
||||
1: # Clear CIF_FPU bit
|
||||
ni __LC_CPU_FLAGS+7,255-_CIF_FPU
|
||||
lg %r9,48(%r11) # return from load_fpu_regs
|
||||
larl %r9,load_fpu_regs
|
||||
br %r14
|
||||
.Lcleanup_load_fpu_regs_vx:
|
||||
.quad .Lload_fpu_regs_vx
|
||||
.Lcleanup_load_fpu_regs_vx_high:
|
||||
.quad .Lload_fpu_regs_vx_high
|
||||
.Lcleanup_load_fpu_regs_fp:
|
||||
.quad .Lload_fpu_regs_fp
|
||||
.Lcleanup_load_fpu_regs_done:
|
||||
.quad .Lload_fpu_regs_done
|
||||
|
||||
/*
|
||||
* Integer constants
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
__HEAD
|
||||
ENTRY(startup_continue)
|
||||
tm __LC_STFL_FAC_LIST+6,0x80 # LPP available ?
|
||||
tm __LC_STFL_FAC_LIST+5,0x80 # LPP available ?
|
||||
jz 0f
|
||||
xc __LC_LPP+1(7,0),__LC_LPP+1 # clear lpp and current_pid
|
||||
mvi __LC_LPP,0x80 # and set LPP_MAGIC
|
||||
|
|
|
|||
|
|
@ -329,6 +329,7 @@ static void __init setup_lowcore(void)
|
|||
+ PAGE_SIZE - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);
|
||||
lc->current_task = (unsigned long) init_thread_union.thread_info.task;
|
||||
lc->thread_info = (unsigned long) &init_thread_union;
|
||||
lc->lpp = LPP_MAGIC;
|
||||
lc->machine_flags = S390_lowcore.machine_flags;
|
||||
lc->stfl_fac_list = S390_lowcore.stfl_fac_list;
|
||||
memcpy(lc->stfle_fac_list, S390_lowcore.stfle_fac_list,
|
||||
|
|
|
|||
|
|
@ -871,8 +871,11 @@ static inline int barsize(u8 size)
|
|||
|
||||
static int zpci_mem_init(void)
|
||||
{
|
||||
BUILD_BUG_ON(!is_power_of_2(__alignof__(struct zpci_fmb)) ||
|
||||
__alignof__(struct zpci_fmb) < sizeof(struct zpci_fmb));
|
||||
|
||||
zdev_fmb_cache = kmem_cache_create("PCI_FMB_cache", sizeof(struct zpci_fmb),
|
||||
16, 0, NULL);
|
||||
__alignof__(struct zpci_fmb), 0, NULL);
|
||||
if (!zdev_fmb_cache)
|
||||
goto error_zdev;
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ void *kmap_coherent(struct page *page, unsigned long addr)
|
|||
|
||||
BUG_ON(!test_bit(PG_dcache_clean, &page->flags));
|
||||
|
||||
preempt_disable();
|
||||
pagefault_disable();
|
||||
|
||||
idx = FIX_CMAP_END -
|
||||
|
|
@ -64,4 +65,5 @@ void kunmap_coherent(void *kvaddr)
|
|||
}
|
||||
|
||||
pagefault_enable();
|
||||
preempt_enable();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ void mconsole_proc(struct mc_request *req)
|
|||
ptr += strlen("proc");
|
||||
ptr = skip_spaces(ptr);
|
||||
|
||||
file = file_open_root(mnt->mnt_root, mnt, ptr, O_RDONLY);
|
||||
file = file_open_root(mnt->mnt_root, mnt, ptr, O_RDONLY, 0);
|
||||
if (IS_ERR(file)) {
|
||||
mconsole_reply(req, "Failed to open file", 1, 0);
|
||||
printk(KERN_ERR "open /proc/%s: %ld\n", ptr, PTR_ERR(file));
|
||||
|
|
|
|||
|
|
@ -1145,22 +1145,23 @@ config MICROCODE
|
|||
bool "CPU microcode loading support"
|
||||
default y
|
||||
depends on CPU_SUP_AMD || CPU_SUP_INTEL
|
||||
depends on BLK_DEV_INITRD
|
||||
select FW_LOADER
|
||||
---help---
|
||||
|
||||
If you say Y here, you will be able to update the microcode on
|
||||
certain Intel and AMD processors. The Intel support is for the
|
||||
IA32 family, e.g. Pentium Pro, Pentium II, Pentium III, Pentium 4,
|
||||
Xeon etc. The AMD support is for families 0x10 and later. You will
|
||||
obviously need the actual microcode binary data itself which is not
|
||||
shipped with the Linux kernel.
|
||||
Intel and AMD processors. The Intel support is for the IA32 family,
|
||||
e.g. Pentium Pro, Pentium II, Pentium III, Pentium 4, Xeon etc. The
|
||||
AMD support is for families 0x10 and later. You will obviously need
|
||||
the actual microcode binary data itself which is not shipped with
|
||||
the Linux kernel.
|
||||
|
||||
This option selects the general module only, you need to select
|
||||
at least one vendor specific module as well.
|
||||
The preferred method to load microcode from a detached initrd is described
|
||||
in Documentation/x86/early-microcode.txt. For that you need to enable
|
||||
CONFIG_BLK_DEV_INITRD in order for the loader to be able to scan the
|
||||
initrd for microcode blobs.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called microcode.
|
||||
In addition, you can build-in the microcode into the kernel. For that you
|
||||
need to enable FIRMWARE_IN_KERNEL and add the vendor-supplied microcode
|
||||
to the CONFIG_EXTRA_FIRMWARE config option.
|
||||
|
||||
config MICROCODE_INTEL
|
||||
bool "Intel microcode loading support"
|
||||
|
|
|
|||
|
|
@ -268,6 +268,7 @@ static void exit_to_usermode_loop(struct pt_regs *regs, u32 cached_flags)
|
|||
/* Called with IRQs disabled. */
|
||||
__visible inline void prepare_exit_to_usermode(struct pt_regs *regs)
|
||||
{
|
||||
struct thread_info *ti = pt_regs_to_thread_info(regs);
|
||||
u32 cached_flags;
|
||||
|
||||
if (IS_ENABLED(CONFIG_PROVE_LOCKING) && WARN_ON(!irqs_disabled()))
|
||||
|
|
@ -275,12 +276,22 @@ __visible inline void prepare_exit_to_usermode(struct pt_regs *regs)
|
|||
|
||||
lockdep_sys_exit();
|
||||
|
||||
cached_flags =
|
||||
READ_ONCE(pt_regs_to_thread_info(regs)->flags);
|
||||
cached_flags = READ_ONCE(ti->flags);
|
||||
|
||||
if (unlikely(cached_flags & EXIT_TO_USERMODE_LOOP_FLAGS))
|
||||
exit_to_usermode_loop(regs, cached_flags);
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
/*
|
||||
* Compat syscalls set TS_COMPAT. Make sure we clear it before
|
||||
* returning to user mode. We need to clear it *after* signal
|
||||
* handling, because syscall restart has a fixup for compat
|
||||
* syscalls. The fixup is exercised by the ptrace_syscall_32
|
||||
* selftest.
|
||||
*/
|
||||
ti->status &= ~TS_COMPAT;
|
||||
#endif
|
||||
|
||||
user_enter();
|
||||
}
|
||||
|
||||
|
|
@ -332,14 +343,6 @@ __visible inline void syscall_return_slowpath(struct pt_regs *regs)
|
|||
if (unlikely(cached_flags & SYSCALL_EXIT_WORK_FLAGS))
|
||||
syscall_slow_exit_work(regs, cached_flags);
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
/*
|
||||
* Compat syscalls set TS_COMPAT. Make sure we clear it before
|
||||
* returning to user mode.
|
||||
*/
|
||||
ti->status &= ~TS_COMPAT;
|
||||
#endif
|
||||
|
||||
local_irq_disable();
|
||||
prepare_exit_to_usermode(regs);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -638,8 +638,8 @@ static inline void entering_irq(void)
|
|||
|
||||
static inline void entering_ack_irq(void)
|
||||
{
|
||||
ack_APIC_irq();
|
||||
entering_irq();
|
||||
ack_APIC_irq();
|
||||
}
|
||||
|
||||
static inline void ipi_entering_ack_irq(void)
|
||||
|
|
|
|||
|
|
@ -136,6 +136,7 @@ struct irq_alloc_info {
|
|||
struct irq_cfg {
|
||||
unsigned int dest_apicid;
|
||||
u8 vector;
|
||||
u8 old_vector;
|
||||
};
|
||||
|
||||
extern struct irq_cfg *irq_cfg(unsigned int irq);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#define _ASM_X86_MICROCODE_H
|
||||
|
||||
#include <linux/earlycpio.h>
|
||||
#include <linux/initrd.h>
|
||||
|
||||
#define native_rdmsr(msr, val1, val2) \
|
||||
do { \
|
||||
|
|
@ -168,4 +169,29 @@ static inline void reload_early_microcode(void) { }
|
|||
static inline bool
|
||||
get_builtin_firmware(struct cpio_data *cd, const char *name) { return false; }
|
||||
#endif
|
||||
|
||||
static inline unsigned long get_initrd_start(void)
|
||||
{
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
return initrd_start;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline unsigned long get_initrd_start_addr(void)
|
||||
{
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
#ifdef CONFIG_X86_32
|
||||
unsigned long *initrd_start_p = (unsigned long *)__pa_nodebug(&initrd_start);
|
||||
|
||||
return (unsigned long)__pa_nodebug(*initrd_start_p);
|
||||
#else
|
||||
return get_initrd_start();
|
||||
#endif
|
||||
#else /* CONFIG_BLK_DEV_INITRD */
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* _ASM_X86_MICROCODE_H */
|
||||
|
|
|
|||
|
|
@ -165,6 +165,7 @@ struct x86_pmu_capability {
|
|||
#define GLOBAL_STATUS_ASIF BIT_ULL(60)
|
||||
#define GLOBAL_STATUS_COUNTERS_FROZEN BIT_ULL(59)
|
||||
#define GLOBAL_STATUS_LBRS_FROZEN BIT_ULL(58)
|
||||
#define GLOBAL_STATUS_TRACE_TOPAPMI BIT_ULL(55)
|
||||
|
||||
/*
|
||||
* IBS cpuid feature detection
|
||||
|
|
|
|||
|
|
@ -62,4 +62,6 @@ void xen_arch_register_cpu(int num);
|
|||
void xen_arch_unregister_cpu(int num);
|
||||
#endif
|
||||
|
||||
extern void xen_set_iopl_mask(unsigned mask);
|
||||
|
||||
#endif /* _ASM_X86_XEN_HYPERVISOR_H */
|
||||
|
|
|
|||
|
|
@ -211,6 +211,7 @@ static int __assign_irq_vector(int irq, struct apic_chip_data *d,
|
|||
*/
|
||||
cpumask_and(d->old_domain, d->old_domain, cpu_online_mask);
|
||||
d->move_in_progress = !cpumask_empty(d->old_domain);
|
||||
d->cfg.old_vector = d->move_in_progress ? d->cfg.vector : 0;
|
||||
d->cfg.vector = vector;
|
||||
cpumask_copy(d->domain, vector_cpumask);
|
||||
success:
|
||||
|
|
@ -653,46 +654,97 @@ void irq_complete_move(struct irq_cfg *cfg)
|
|||
}
|
||||
|
||||
/*
|
||||
* Called with @desc->lock held and interrupts disabled.
|
||||
* Called from fixup_irqs() with @desc->lock held and interrupts disabled.
|
||||
*/
|
||||
void irq_force_complete_move(struct irq_desc *desc)
|
||||
{
|
||||
struct irq_data *irqdata = irq_desc_get_irq_data(desc);
|
||||
struct apic_chip_data *data = apic_chip_data(irqdata);
|
||||
struct irq_cfg *cfg = data ? &data->cfg : NULL;
|
||||
unsigned int cpu;
|
||||
|
||||
if (!cfg)
|
||||
return;
|
||||
|
||||
__irq_complete_move(cfg, cfg->vector);
|
||||
|
||||
/*
|
||||
* This is tricky. If the cleanup of @data->old_domain has not been
|
||||
* done yet, then the following setaffinity call will fail with
|
||||
* -EBUSY. This can leave the interrupt in a stale state.
|
||||
*
|
||||
* The cleanup cannot make progress because we hold @desc->lock. So in
|
||||
* case @data->old_domain is not yet cleaned up, we need to drop the
|
||||
* lock and acquire it again. @desc cannot go away, because the
|
||||
* hotplug code holds the sparse irq lock.
|
||||
* All CPUs are stuck in stop machine with interrupts disabled so
|
||||
* calling __irq_complete_move() would be completely pointless.
|
||||
*/
|
||||
raw_spin_lock(&vector_lock);
|
||||
/* Clean out all offline cpus (including ourself) first. */
|
||||
/*
|
||||
* Clean out all offline cpus (including the outgoing one) from the
|
||||
* old_domain mask.
|
||||
*/
|
||||
cpumask_and(data->old_domain, data->old_domain, cpu_online_mask);
|
||||
while (!cpumask_empty(data->old_domain)) {
|
||||
|
||||
/*
|
||||
* If move_in_progress is cleared and the old_domain mask is empty,
|
||||
* then there is nothing to cleanup. fixup_irqs() will take care of
|
||||
* the stale vectors on the outgoing cpu.
|
||||
*/
|
||||
if (!data->move_in_progress && cpumask_empty(data->old_domain)) {
|
||||
raw_spin_unlock(&vector_lock);
|
||||
raw_spin_unlock(&desc->lock);
|
||||
cpu_relax();
|
||||
raw_spin_lock(&desc->lock);
|
||||
/*
|
||||
* Reevaluate apic_chip_data. It might have been cleared after
|
||||
* we dropped @desc->lock.
|
||||
*/
|
||||
data = apic_chip_data(irqdata);
|
||||
if (!data)
|
||||
return;
|
||||
raw_spin_lock(&vector_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* 1) The interrupt is in move_in_progress state. That means that we
|
||||
* have not seen an interrupt since the io_apic was reprogrammed to
|
||||
* the new vector.
|
||||
*
|
||||
* 2) The interrupt has fired on the new vector, but the cleanup IPIs
|
||||
* have not been processed yet.
|
||||
*/
|
||||
if (data->move_in_progress) {
|
||||
/*
|
||||
* In theory there is a race:
|
||||
*
|
||||
* set_ioapic(new_vector) <-- Interrupt is raised before update
|
||||
* is effective, i.e. it's raised on
|
||||
* the old vector.
|
||||
*
|
||||
* So if the target cpu cannot handle that interrupt before
|
||||
* the old vector is cleaned up, we get a spurious interrupt
|
||||
* and in the worst case the ioapic irq line becomes stale.
|
||||
*
|
||||
* But in case of cpu hotplug this should be a non issue
|
||||
* because if the affinity update happens right before all
|
||||
* cpus rendevouz in stop machine, there is no way that the
|
||||
* interrupt can be blocked on the target cpu because all cpus
|
||||
* loops first with interrupts enabled in stop machine, so the
|
||||
* old vector is not yet cleaned up when the interrupt fires.
|
||||
*
|
||||
* So the only way to run into this issue is if the delivery
|
||||
* of the interrupt on the apic/system bus would be delayed
|
||||
* beyond the point where the target cpu disables interrupts
|
||||
* in stop machine. I doubt that it can happen, but at least
|
||||
* there is a theroretical chance. Virtualization might be
|
||||
* able to expose this, but AFAICT the IOAPIC emulation is not
|
||||
* as stupid as the real hardware.
|
||||
*
|
||||
* Anyway, there is nothing we can do about that at this point
|
||||
* w/o refactoring the whole fixup_irq() business completely.
|
||||
* We print at least the irq number and the old vector number,
|
||||
* so we have the necessary information when a problem in that
|
||||
* area arises.
|
||||
*/
|
||||
pr_warn("IRQ fixup: irq %d move in progress, old vector %d\n",
|
||||
irqdata->irq, cfg->old_vector);
|
||||
}
|
||||
/*
|
||||
* If old_domain is not empty, then other cpus still have the irq
|
||||
* descriptor set in their vector array. Clean it up.
|
||||
*/
|
||||
for_each_cpu(cpu, data->old_domain)
|
||||
per_cpu(vector_irq, cpu)[cfg->old_vector] = VECTOR_UNUSED;
|
||||
|
||||
/* Cleanup the left overs of the (half finished) move */
|
||||
cpumask_clear(data->old_domain);
|
||||
data->move_in_progress = 0;
|
||||
raw_spin_unlock(&vector_lock);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -555,10 +555,14 @@ scan_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd,
|
|||
cd.data = NULL;
|
||||
cd.size = 0;
|
||||
|
||||
cd = find_cpio_data(p, (void *)start, size, &offset);
|
||||
if (!cd.data) {
|
||||
/* try built-in microcode if no initrd */
|
||||
if (!size) {
|
||||
if (!load_builtin_intel_microcode(&cd))
|
||||
return UCODE_ERROR;
|
||||
} else {
|
||||
cd = find_cpio_data(p, (void *)start, size, &offset);
|
||||
if (!cd.data)
|
||||
return UCODE_ERROR;
|
||||
}
|
||||
|
||||
return get_matching_model_microcode(0, start, cd.data, cd.size,
|
||||
|
|
@ -694,7 +698,7 @@ int __init save_microcode_in_initrd_intel(void)
|
|||
if (count == 0)
|
||||
return ret;
|
||||
|
||||
copy_initrd_ptrs(mc_saved, mc_saved_in_initrd, initrd_start, count);
|
||||
copy_initrd_ptrs(mc_saved, mc_saved_in_initrd, get_initrd_start(), count);
|
||||
ret = save_microcode(&mc_saved_data, mc_saved, count);
|
||||
if (ret)
|
||||
pr_err("Cannot save microcode patches from initrd.\n");
|
||||
|
|
@ -732,16 +736,20 @@ void __init load_ucode_intel_bsp(void)
|
|||
struct boot_params *p;
|
||||
|
||||
p = (struct boot_params *)__pa_nodebug(&boot_params);
|
||||
start = p->hdr.ramdisk_image;
|
||||
size = p->hdr.ramdisk_size;
|
||||
|
||||
_load_ucode_intel_bsp(
|
||||
(struct mc_saved_data *)__pa_nodebug(&mc_saved_data),
|
||||
(unsigned long *)__pa_nodebug(&mc_saved_in_initrd),
|
||||
start, size);
|
||||
/*
|
||||
* Set start only if we have an initrd image. We cannot use initrd_start
|
||||
* because it is not set that early yet.
|
||||
*/
|
||||
start = (size ? p->hdr.ramdisk_image : 0);
|
||||
|
||||
_load_ucode_intel_bsp((struct mc_saved_data *)__pa_nodebug(&mc_saved_data),
|
||||
(unsigned long *)__pa_nodebug(&mc_saved_in_initrd),
|
||||
start, size);
|
||||
#else
|
||||
start = boot_params.hdr.ramdisk_image + PAGE_OFFSET;
|
||||
size = boot_params.hdr.ramdisk_size;
|
||||
start = (size ? boot_params.hdr.ramdisk_image + PAGE_OFFSET : 0);
|
||||
|
||||
_load_ucode_intel_bsp(&mc_saved_data, mc_saved_in_initrd, start, size);
|
||||
#endif
|
||||
|
|
@ -752,20 +760,14 @@ void load_ucode_intel_ap(void)
|
|||
struct mc_saved_data *mc_saved_data_p;
|
||||
struct ucode_cpu_info uci;
|
||||
unsigned long *mc_saved_in_initrd_p;
|
||||
unsigned long initrd_start_addr;
|
||||
enum ucode_state ret;
|
||||
#ifdef CONFIG_X86_32
|
||||
unsigned long *initrd_start_p;
|
||||
|
||||
mc_saved_in_initrd_p =
|
||||
(unsigned long *)__pa_nodebug(mc_saved_in_initrd);
|
||||
mc_saved_in_initrd_p = (unsigned long *)__pa_nodebug(mc_saved_in_initrd);
|
||||
mc_saved_data_p = (struct mc_saved_data *)__pa_nodebug(&mc_saved_data);
|
||||
initrd_start_p = (unsigned long *)__pa_nodebug(&initrd_start);
|
||||
initrd_start_addr = (unsigned long)__pa_nodebug(*initrd_start_p);
|
||||
#else
|
||||
mc_saved_data_p = &mc_saved_data;
|
||||
mc_saved_in_initrd_p = mc_saved_in_initrd;
|
||||
initrd_start_addr = initrd_start;
|
||||
mc_saved_data_p = &mc_saved_data;
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -777,7 +779,7 @@ void load_ucode_intel_ap(void)
|
|||
|
||||
collect_cpu_info_early(&uci);
|
||||
ret = load_microcode(mc_saved_data_p, mc_saved_in_initrd_p,
|
||||
initrd_start_addr, &uci);
|
||||
get_initrd_start_addr(), &uci);
|
||||
|
||||
if (ret != UCODE_OK)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -593,6 +593,19 @@ void x86_pmu_disable_all(void)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* There may be PMI landing after enabled=0. The PMI hitting could be before or
|
||||
* after disable_all.
|
||||
*
|
||||
* If PMI hits before disable_all, the PMU will be disabled in the NMI handler.
|
||||
* It will not be re-enabled in the NMI handler again, because enabled=0. After
|
||||
* handling the NMI, disable_all will be called, which will not change the
|
||||
* state either. If PMI hits after disable_all, the PMU is already disabled
|
||||
* before entering NMI handler. The NMI handler will not change the state
|
||||
* either.
|
||||
*
|
||||
* So either situation is harmless.
|
||||
*/
|
||||
static void x86_pmu_disable(struct pmu *pmu)
|
||||
{
|
||||
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
|
||||
|
|
|
|||
|
|
@ -591,6 +591,7 @@ struct x86_pmu {
|
|||
pebs_active :1,
|
||||
pebs_broken :1;
|
||||
int pebs_record_size;
|
||||
int pebs_buffer_size;
|
||||
void (*drain_pebs)(struct pt_regs *regs);
|
||||
struct event_constraint *pebs_constraints;
|
||||
void (*pebs_aliases)(struct perf_event *event);
|
||||
|
|
@ -907,6 +908,8 @@ void intel_pmu_lbr_init_hsw(void);
|
|||
|
||||
void intel_pmu_lbr_init_skl(void);
|
||||
|
||||
void intel_pmu_pebs_data_source_nhm(void);
|
||||
|
||||
int intel_pmu_setup_lbr_filter(struct perf_event *event);
|
||||
|
||||
void intel_pt_interrupt(void);
|
||||
|
|
|
|||
|
|
@ -1458,7 +1458,15 @@ static __initconst const u64 slm_hw_cache_event_ids
|
|||
};
|
||||
|
||||
/*
|
||||
* Use from PMIs where the LBRs are already disabled.
|
||||
* Used from PMIs where the LBRs are already disabled.
|
||||
*
|
||||
* This function could be called consecutively. It is required to remain in
|
||||
* disabled state if called consecutively.
|
||||
*
|
||||
* During consecutive calls, the same disable value will be written to related
|
||||
* registers, so the PMU state remains unchanged. hw.state in
|
||||
* intel_bts_disable_local will remain PERF_HES_STOPPED too in consecutive
|
||||
* calls.
|
||||
*/
|
||||
static void __intel_pmu_disable_all(void)
|
||||
{
|
||||
|
|
@ -1840,6 +1848,16 @@ static int intel_pmu_handle_irq(struct pt_regs *regs)
|
|||
if (__test_and_clear_bit(62, (unsigned long *)&status)) {
|
||||
handled++;
|
||||
x86_pmu.drain_pebs(regs);
|
||||
/*
|
||||
* There are cases where, even though, the PEBS ovfl bit is set
|
||||
* in GLOBAL_OVF_STATUS, the PEBS events may also have their
|
||||
* overflow bits set for their counters. We must clear them
|
||||
* here because they have been processed as exact samples in
|
||||
* the drain_pebs() routine. They must not be processed again
|
||||
* in the for_each_bit_set() loop for regular samples below.
|
||||
*/
|
||||
status &= ~cpuc->pebs_enabled;
|
||||
status &= x86_pmu.intel_ctrl | GLOBAL_STATUS_TRACE_TOPAPMI;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1885,7 +1903,10 @@ static int intel_pmu_handle_irq(struct pt_regs *regs)
|
|||
goto again;
|
||||
|
||||
done:
|
||||
__intel_pmu_enable_all(0, true);
|
||||
/* Only restore PMU state when it's active. See x86_pmu_disable(). */
|
||||
if (cpuc->enabled)
|
||||
__intel_pmu_enable_all(0, true);
|
||||
|
||||
/*
|
||||
* Only unmask the NMI after the overflow counters
|
||||
* have been reset. This avoids spurious NMIs on
|
||||
|
|
@ -3315,6 +3336,7 @@ __init int intel_pmu_init(void)
|
|||
intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] =
|
||||
X86_CONFIG(.event=0xb1, .umask=0x3f, .inv=1, .cmask=1);
|
||||
|
||||
intel_pmu_pebs_data_source_nhm();
|
||||
x86_add_quirk(intel_nehalem_quirk);
|
||||
|
||||
pr_cont("Nehalem events, ");
|
||||
|
|
@ -3377,6 +3399,7 @@ __init int intel_pmu_init(void)
|
|||
intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] =
|
||||
X86_CONFIG(.event=0xb1, .umask=0x3f, .inv=1, .cmask=1);
|
||||
|
||||
intel_pmu_pebs_data_source_nhm();
|
||||
pr_cont("Westmere events, ");
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,8 @@ union intel_x86_pebs_dse {
|
|||
#define OP_LH (P(OP, LOAD) | P(LVL, HIT))
|
||||
#define SNOOP_NONE_MISS (P(SNOOP, NONE) | P(SNOOP, MISS))
|
||||
|
||||
static const u64 pebs_data_source[] = {
|
||||
/* Version for Sandy Bridge and later */
|
||||
static u64 pebs_data_source[] = {
|
||||
P(OP, LOAD) | P(LVL, MISS) | P(LVL, L3) | P(SNOOP, NA),/* 0x00:ukn L3 */
|
||||
OP_LH | P(LVL, L1) | P(SNOOP, NONE), /* 0x01: L1 local */
|
||||
OP_LH | P(LVL, LFB) | P(SNOOP, NONE), /* 0x02: LFB hit */
|
||||
|
|
@ -70,6 +71,14 @@ static const u64 pebs_data_source[] = {
|
|||
OP_LH | P(LVL, UNC) | P(SNOOP, NONE), /* 0x0f: uncached */
|
||||
};
|
||||
|
||||
/* Patch up minor differences in the bits */
|
||||
void __init intel_pmu_pebs_data_source_nhm(void)
|
||||
{
|
||||
pebs_data_source[0x05] = OP_LH | P(LVL, L3) | P(SNOOP, HIT);
|
||||
pebs_data_source[0x06] = OP_LH | P(LVL, L3) | P(SNOOP, HITM);
|
||||
pebs_data_source[0x07] = OP_LH | P(LVL, L3) | P(SNOOP, HITM);
|
||||
}
|
||||
|
||||
static u64 precise_store_data(u64 status)
|
||||
{
|
||||
union intel_x86_pebs_dse dse;
|
||||
|
|
@ -269,7 +278,7 @@ static int alloc_pebs_buffer(int cpu)
|
|||
if (!x86_pmu.pebs)
|
||||
return 0;
|
||||
|
||||
buffer = kzalloc_node(PEBS_BUFFER_SIZE, GFP_KERNEL, node);
|
||||
buffer = kzalloc_node(x86_pmu.pebs_buffer_size, GFP_KERNEL, node);
|
||||
if (unlikely(!buffer))
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -286,7 +295,7 @@ static int alloc_pebs_buffer(int cpu)
|
|||
per_cpu(insn_buffer, cpu) = ibuffer;
|
||||
}
|
||||
|
||||
max = PEBS_BUFFER_SIZE / x86_pmu.pebs_record_size;
|
||||
max = x86_pmu.pebs_buffer_size / x86_pmu.pebs_record_size;
|
||||
|
||||
ds->pebs_buffer_base = (u64)(unsigned long)buffer;
|
||||
ds->pebs_index = ds->pebs_buffer_base;
|
||||
|
|
@ -1296,6 +1305,7 @@ void __init intel_ds_init(void)
|
|||
|
||||
x86_pmu.bts = boot_cpu_has(X86_FEATURE_BTS);
|
||||
x86_pmu.pebs = boot_cpu_has(X86_FEATURE_PEBS);
|
||||
x86_pmu.pebs_buffer_size = PEBS_BUFFER_SIZE;
|
||||
if (x86_pmu.pebs) {
|
||||
char pebs_type = x86_pmu.intel_cap.pebs_trap ? '+' : '-';
|
||||
int format = x86_pmu.intel_cap.pebs_format;
|
||||
|
|
@ -1304,6 +1314,14 @@ void __init intel_ds_init(void)
|
|||
case 0:
|
||||
printk(KERN_CONT "PEBS fmt0%c, ", pebs_type);
|
||||
x86_pmu.pebs_record_size = sizeof(struct pebs_record_core);
|
||||
/*
|
||||
* Using >PAGE_SIZE buffers makes the WRMSR to
|
||||
* PERF_GLOBAL_CTRL in intel_pmu_enable_all()
|
||||
* mysteriously hang on Core2.
|
||||
*
|
||||
* As a workaround, we don't do this.
|
||||
*/
|
||||
x86_pmu.pebs_buffer_size = PAGE_SIZE;
|
||||
x86_pmu.drain_pebs = intel_pmu_drain_pebs_core;
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -263,7 +263,9 @@ static int knc_pmu_handle_irq(struct pt_regs *regs)
|
|||
goto again;
|
||||
|
||||
done:
|
||||
knc_pmu_enable_all(0);
|
||||
/* Only restore PMU state when it's active. See x86_pmu_disable(). */
|
||||
if (cpuc->enabled)
|
||||
knc_pmu_enable_all(0);
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,9 +96,14 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
|
|||
SYSCALL_DEFINE1(iopl, unsigned int, level)
|
||||
{
|
||||
struct pt_regs *regs = current_pt_regs();
|
||||
unsigned int old = (regs->flags >> 12) & 3;
|
||||
struct thread_struct *t = ¤t->thread;
|
||||
|
||||
/*
|
||||
* Careful: the IOPL bits in regs->flags are undefined under Xen PV
|
||||
* and changing them has no effect.
|
||||
*/
|
||||
unsigned int old = t->iopl >> X86_EFLAGS_IOPL_BIT;
|
||||
|
||||
if (level > 3)
|
||||
return -EINVAL;
|
||||
/* Trying to gain more privileges? */
|
||||
|
|
@ -106,8 +111,9 @@ SYSCALL_DEFINE1(iopl, unsigned int, level)
|
|||
if (!capable(CAP_SYS_RAWIO))
|
||||
return -EPERM;
|
||||
}
|
||||
regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12);
|
||||
t->iopl = level << 12;
|
||||
regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) |
|
||||
(level << X86_EFLAGS_IOPL_BIT);
|
||||
t->iopl = level << X86_EFLAGS_IOPL_BIT;
|
||||
set_iopl_mask(t->iopl);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
#include <asm/syscalls.h>
|
||||
#include <asm/debugreg.h>
|
||||
#include <asm/switch_to.h>
|
||||
#include <asm/xen/hypervisor.h>
|
||||
|
||||
asmlinkage extern void ret_from_fork(void);
|
||||
|
||||
|
|
@ -411,6 +412,17 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
|
|||
task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV))
|
||||
__switch_to_xtra(prev_p, next_p, tss);
|
||||
|
||||
#ifdef CONFIG_XEN
|
||||
/*
|
||||
* On Xen PV, IOPL bits in pt_regs->flags have no effect, and
|
||||
* current_pt_regs()->flags may not match the current task's
|
||||
* intended IOPL. We need to switch it manually.
|
||||
*/
|
||||
if (unlikely(static_cpu_has(X86_FEATURE_XENPV) &&
|
||||
prev->iopl != next->iopl))
|
||||
xen_set_iopl_mask(next->iopl);
|
||||
#endif
|
||||
|
||||
if (static_cpu_has_bug(X86_BUG_SYSRET_SS_ATTRS)) {
|
||||
/*
|
||||
* AMD CPUs have a misfeature: SYSRET sets the SS selector but
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ static void kvm_pit_ack_irq(struct kvm_irq_ack_notifier *kian)
|
|||
* PIC is being reset. Handle it gracefully here
|
||||
*/
|
||||
atomic_inc(&ps->pending);
|
||||
else if (value > 0)
|
||||
else if (value > 0 && ps->reinject)
|
||||
/* in this case, we had multiple outstanding pit interrupts
|
||||
* that we needed to inject. Reinject
|
||||
*/
|
||||
|
|
@ -288,7 +288,9 @@ static void pit_do_work(struct kthread_work *work)
|
|||
* last one has been acked.
|
||||
*/
|
||||
spin_lock(&ps->inject_lock);
|
||||
if (ps->irq_ack) {
|
||||
if (!ps->reinject)
|
||||
inject = 1;
|
||||
else if (ps->irq_ack) {
|
||||
ps->irq_ack = 0;
|
||||
inject = 1;
|
||||
}
|
||||
|
|
@ -317,10 +319,10 @@ static enum hrtimer_restart pit_timer_fn(struct hrtimer *data)
|
|||
struct kvm_kpit_state *ps = container_of(data, struct kvm_kpit_state, timer);
|
||||
struct kvm_pit *pt = ps->kvm->arch.vpit;
|
||||
|
||||
if (ps->reinject || !atomic_read(&ps->pending)) {
|
||||
if (ps->reinject)
|
||||
atomic_inc(&ps->pending);
|
||||
queue_kthread_work(&pt->worker, &pt->expired);
|
||||
}
|
||||
|
||||
queue_kthread_work(&pt->worker, &pt->expired);
|
||||
|
||||
if (ps->is_periodic) {
|
||||
hrtimer_add_expires_ns(&ps->timer, ps->period);
|
||||
|
|
|
|||
|
|
@ -2637,8 +2637,15 @@ static void nested_vmx_setup_ctls_msrs(struct vcpu_vmx *vmx)
|
|||
} else
|
||||
vmx->nested.nested_vmx_ept_caps = 0;
|
||||
|
||||
/*
|
||||
* Old versions of KVM use the single-context version without
|
||||
* checking for support, so declare that it is supported even
|
||||
* though it is treated as global context. The alternative is
|
||||
* not failing the single-context invvpid, and it is worse.
|
||||
*/
|
||||
if (enable_vpid)
|
||||
vmx->nested.nested_vmx_vpid_caps = VMX_VPID_INVVPID_BIT |
|
||||
VMX_VPID_EXTENT_SINGLE_CONTEXT_BIT |
|
||||
VMX_VPID_EXTENT_GLOBAL_CONTEXT_BIT;
|
||||
else
|
||||
vmx->nested.nested_vmx_vpid_caps = 0;
|
||||
|
|
@ -7340,6 +7347,7 @@ static int handle_invept(struct kvm_vcpu *vcpu)
|
|||
if (!(types & (1UL << type))) {
|
||||
nested_vmx_failValid(vcpu,
|
||||
VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
|
||||
skip_emulated_instruction(vcpu);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -7398,6 +7406,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)
|
|||
if (!(types & (1UL << type))) {
|
||||
nested_vmx_failValid(vcpu,
|
||||
VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
|
||||
skip_emulated_instruction(vcpu);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -7414,12 +7423,17 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)
|
|||
}
|
||||
|
||||
switch (type) {
|
||||
case VMX_VPID_EXTENT_SINGLE_CONTEXT:
|
||||
/*
|
||||
* Old versions of KVM use the single-context version so we
|
||||
* have to support it; just treat it the same as all-context.
|
||||
*/
|
||||
case VMX_VPID_EXTENT_ALL_CONTEXT:
|
||||
__vmx_flush_tlb(vcpu, to_vmx(vcpu)->nested.vpid02);
|
||||
nested_vmx_succeed(vcpu);
|
||||
break;
|
||||
default:
|
||||
/* Trap single context invalidation invvpid calls */
|
||||
/* Trap individual address invalidation invvpid calls */
|
||||
BUG_ON(1);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2736,6 +2736,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
|
|||
}
|
||||
|
||||
kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu);
|
||||
vcpu->arch.switch_db_regs |= KVM_DEBUGREG_RELOAD;
|
||||
}
|
||||
|
||||
void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
|
||||
|
|
|
|||
|
|
@ -106,8 +106,6 @@ static void flush_tlb_func(void *info)
|
|||
|
||||
if (f->flush_mm != this_cpu_read(cpu_tlbstate.active_mm))
|
||||
return;
|
||||
if (!f->flush_end)
|
||||
f->flush_end = f->flush_start + PAGE_SIZE;
|
||||
|
||||
count_vm_tlb_event(NR_TLB_REMOTE_FLUSH_RECEIVED);
|
||||
if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK) {
|
||||
|
|
@ -135,12 +133,20 @@ void native_flush_tlb_others(const struct cpumask *cpumask,
|
|||
unsigned long end)
|
||||
{
|
||||
struct flush_tlb_info info;
|
||||
|
||||
if (end == 0)
|
||||
end = start + PAGE_SIZE;
|
||||
info.flush_mm = mm;
|
||||
info.flush_start = start;
|
||||
info.flush_end = end;
|
||||
|
||||
count_vm_tlb_event(NR_TLB_REMOTE_FLUSH);
|
||||
trace_tlb_flush(TLB_REMOTE_SEND_IPI, end - start);
|
||||
if (end == TLB_FLUSH_ALL)
|
||||
trace_tlb_flush(TLB_REMOTE_SEND_IPI, TLB_FLUSH_ALL);
|
||||
else
|
||||
trace_tlb_flush(TLB_REMOTE_SEND_IPI,
|
||||
(end - start) >> PAGE_SHIFT);
|
||||
|
||||
if (is_uv_system()) {
|
||||
unsigned int cpu;
|
||||
|
||||
|
|
|
|||
|
|
@ -540,3 +540,10 @@ static void twinhead_reserve_killing_zone(struct pci_dev *dev)
|
|||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x27B9, twinhead_reserve_killing_zone);
|
||||
|
||||
static void pci_bdwep_bar(struct pci_dev *dev)
|
||||
{
|
||||
dev->non_compliant_bars = 1;
|
||||
}
|
||||
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fa0, pci_bdwep_bar);
|
||||
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fc0, pci_bdwep_bar);
|
||||
|
|
|
|||
|
|
@ -961,7 +961,7 @@ static void xen_load_sp0(struct tss_struct *tss,
|
|||
tss->x86_tss.sp0 = thread->sp0;
|
||||
}
|
||||
|
||||
static void xen_set_iopl_mask(unsigned mask)
|
||||
void xen_set_iopl_mask(unsigned mask)
|
||||
{
|
||||
struct physdev_set_iopl set_iopl;
|
||||
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ ENTRY(_startup)
|
|||
wsr a0, icountlevel
|
||||
|
||||
.set _index, 0
|
||||
.rept XCHAL_NUM_DBREAK - 1
|
||||
.rept XCHAL_NUM_DBREAK
|
||||
wsr a0, SREG_DBREAKC + _index
|
||||
.set _index, _index + 1
|
||||
.endr
|
||||
|
|
|
|||
|
|
@ -97,11 +97,11 @@ void clear_user_highpage(struct page *page, unsigned long vaddr)
|
|||
unsigned long paddr;
|
||||
void *kvaddr = coherent_kvaddr(page, TLBTEMP_BASE_1, vaddr, &paddr);
|
||||
|
||||
pagefault_disable();
|
||||
preempt_disable();
|
||||
kmap_invalidate_coherent(page, vaddr);
|
||||
set_bit(PG_arch_1, &page->flags);
|
||||
clear_page_alias(kvaddr, paddr);
|
||||
pagefault_enable();
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
void copy_user_highpage(struct page *dst, struct page *src,
|
||||
|
|
@ -113,11 +113,11 @@ void copy_user_highpage(struct page *dst, struct page *src,
|
|||
void *src_vaddr = coherent_kvaddr(src, TLBTEMP_BASE_2, vaddr,
|
||||
&src_paddr);
|
||||
|
||||
pagefault_disable();
|
||||
preempt_disable();
|
||||
kmap_invalidate_coherent(dst, vaddr);
|
||||
set_bit(PG_arch_1, &dst->flags);
|
||||
copy_page_alias(dst_vaddr, src_vaddr, dst_paddr, src_paddr);
|
||||
pagefault_enable();
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
#endif /* DCACHE_WAY_SIZE > PAGE_SIZE */
|
||||
|
|
|
|||
|
|
@ -100,21 +100,23 @@ static void rs_poll(unsigned long priv)
|
|||
{
|
||||
struct tty_port *port = (struct tty_port *)priv;
|
||||
int i = 0;
|
||||
int rd = 1;
|
||||
unsigned char c;
|
||||
|
||||
spin_lock(&timer_lock);
|
||||
|
||||
while (simc_poll(0)) {
|
||||
simc_read(0, &c, 1);
|
||||
rd = simc_read(0, &c, 1);
|
||||
if (rd <= 0)
|
||||
break;
|
||||
tty_insert_flip_char(port, c, TTY_NORMAL);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i)
|
||||
tty_flip_buffer_push(port);
|
||||
|
||||
|
||||
mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE);
|
||||
if (rd)
|
||||
mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE);
|
||||
spin_unlock(&timer_lock);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2189,7 +2189,7 @@ int blk_insert_cloned_request(struct request_queue *q, struct request *rq)
|
|||
if (q->mq_ops) {
|
||||
if (blk_queue_io_stat(q))
|
||||
blk_account_io_start(rq, true);
|
||||
blk_mq_insert_request(rq, false, true, true);
|
||||
blk_mq_insert_request(rq, false, true, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -494,7 +494,7 @@ int x509_decode_time(time64_t *_t, size_t hdrlen,
|
|||
unsigned char tag,
|
||||
const unsigned char *value, size_t vlen)
|
||||
{
|
||||
static const unsigned char month_lengths[] = { 31, 29, 31, 30, 31, 30,
|
||||
static const unsigned char month_lengths[] = { 31, 28, 31, 30, 31, 30,
|
||||
31, 31, 30, 31, 30, 31 };
|
||||
const unsigned char *p = value;
|
||||
unsigned year, mon, day, hour, min, sec, mon_len;
|
||||
|
|
@ -540,9 +540,9 @@ int x509_decode_time(time64_t *_t, size_t hdrlen,
|
|||
if (year % 4 == 0) {
|
||||
mon_len = 29;
|
||||
if (year % 100 == 0) {
|
||||
year /= 100;
|
||||
if (year % 4 != 0)
|
||||
mon_len = 28;
|
||||
mon_len = 28;
|
||||
if (year % 400 == 0)
|
||||
mon_len = 29;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ static int crypto_kw_decrypt(struct blkcipher_desc *desc,
|
|||
SEMIBSIZE))
|
||||
ret = -EBADMSG;
|
||||
|
||||
memzero_explicit(&block, sizeof(struct crypto_kw_block));
|
||||
memzero_explicit(block, sizeof(struct crypto_kw_block));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -297,7 +297,7 @@ static int crypto_kw_encrypt(struct blkcipher_desc *desc,
|
|||
/* establish the IV for the caller to pick up */
|
||||
memcpy(desc->info, block->A, SEMIBSIZE);
|
||||
|
||||
memzero_explicit(&block, sizeof(struct crypto_kw_block));
|
||||
memzero_explicit(block, sizeof(struct crypto_kw_block));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,8 +26,20 @@
|
|||
|
||||
#ifdef CONFIG_X86
|
||||
#define valid_IRQ(i) (((i) != 0) && ((i) != 2))
|
||||
static inline bool acpi_iospace_resource_valid(struct resource *res)
|
||||
{
|
||||
/* On X86 IO space is limited to the [0 - 64K] IO port range */
|
||||
return res->end < 0x10003;
|
||||
}
|
||||
#else
|
||||
#define valid_IRQ(i) (true)
|
||||
/*
|
||||
* ACPI IO descriptors on arches other than X86 contain MMIO CPU physical
|
||||
* addresses mapping IO space in CPU physical address space, IO space
|
||||
* resources can be placed anywhere in the 64-bit physical address space.
|
||||
*/
|
||||
static inline bool
|
||||
acpi_iospace_resource_valid(struct resource *res) { return true; }
|
||||
#endif
|
||||
|
||||
static bool acpi_dev_resource_len_valid(u64 start, u64 end, u64 len, bool io)
|
||||
|
|
@ -126,7 +138,7 @@ static void acpi_dev_ioresource_flags(struct resource *res, u64 len,
|
|||
if (!acpi_dev_resource_len_valid(res->start, res->end, len, true))
|
||||
res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET;
|
||||
|
||||
if (res->end >= 0x10003)
|
||||
if (!acpi_iospace_resource_valid(res))
|
||||
res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET;
|
||||
|
||||
if (io_decode == ACPI_DECODE_16)
|
||||
|
|
|
|||
|
|
@ -714,6 +714,7 @@ static int acpi_hibernation_enter(void)
|
|||
|
||||
static void acpi_hibernation_leave(void)
|
||||
{
|
||||
pm_set_resume_via_firmware();
|
||||
/*
|
||||
* If ACPI is not enabled by the BIOS and the boot kernel, we need to
|
||||
* enable it here.
|
||||
|
|
|
|||
|
|
@ -338,7 +338,7 @@ static blk_qc_t brd_make_request(struct request_queue *q, struct bio *bio)
|
|||
|
||||
if (unlikely(bio->bi_rw & REQ_DISCARD)) {
|
||||
if (sector & ((PAGE_SIZE >> SECTOR_SHIFT) - 1) ||
|
||||
bio->bi_iter.bi_size & PAGE_MASK)
|
||||
bio->bi_iter.bi_size & ~PAGE_MASK)
|
||||
goto io_error;
|
||||
discard_from_brd(brd, sector, bio->bi_iter.bi_size);
|
||||
goto out;
|
||||
|
|
|
|||
|
|
@ -173,7 +173,13 @@ static struct mtip_cmd *mtip_get_int_command(struct driver_data *dd)
|
|||
{
|
||||
struct request *rq;
|
||||
|
||||
if (mtip_check_surprise_removal(dd->pdev))
|
||||
return NULL;
|
||||
|
||||
rq = blk_mq_alloc_request(dd->queue, 0, __GFP_RECLAIM, true);
|
||||
if (IS_ERR(rq))
|
||||
return NULL;
|
||||
|
||||
return blk_mq_rq_to_pdu(rq);
|
||||
}
|
||||
|
||||
|
|
@ -233,15 +239,9 @@ static void mtip_async_complete(struct mtip_port *port,
|
|||
"Command tag %d failed due to TFE\n", tag);
|
||||
}
|
||||
|
||||
/* Unmap the DMA scatter list entries */
|
||||
dma_unmap_sg(&dd->pdev->dev, cmd->sg, cmd->scatter_ents, cmd->direction);
|
||||
|
||||
rq = mtip_rq_from_tag(dd, tag);
|
||||
|
||||
if (unlikely(cmd->unaligned))
|
||||
up(&port->cmd_slot_unal);
|
||||
|
||||
blk_mq_end_request(rq, status ? -EIO : 0);
|
||||
blk_mq_complete_request(rq, status);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -581,6 +581,8 @@ static void mtip_completion(struct mtip_port *port,
|
|||
dev_warn(&port->dd->pdev->dev,
|
||||
"Internal command %d completed with TFE\n", tag);
|
||||
|
||||
command->comp_func = NULL;
|
||||
command->comp_data = NULL;
|
||||
complete(waiting);
|
||||
}
|
||||
|
||||
|
|
@ -618,8 +620,6 @@ static void mtip_handle_tfe(struct driver_data *dd)
|
|||
|
||||
port = dd->port;
|
||||
|
||||
set_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags);
|
||||
|
||||
if (test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) {
|
||||
cmd = mtip_cmd_from_tag(dd, MTIP_TAG_INTERNAL);
|
||||
dbg_printk(MTIP_DRV_NAME " TFE for the internal command\n");
|
||||
|
|
@ -628,7 +628,7 @@ static void mtip_handle_tfe(struct driver_data *dd)
|
|||
cmd->comp_func(port, MTIP_TAG_INTERNAL,
|
||||
cmd, PORT_IRQ_TF_ERR);
|
||||
}
|
||||
goto handle_tfe_exit;
|
||||
return;
|
||||
}
|
||||
|
||||
/* clear the tag accumulator */
|
||||
|
|
@ -701,7 +701,7 @@ static void mtip_handle_tfe(struct driver_data *dd)
|
|||
fail_reason = "thermal shutdown";
|
||||
}
|
||||
if (buf[288] == 0xBF) {
|
||||
set_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag);
|
||||
set_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag);
|
||||
dev_info(&dd->pdev->dev,
|
||||
"Drive indicates rebuild has failed. Secure erase required.\n");
|
||||
fail_all_ncq_cmds = 1;
|
||||
|
|
@ -771,11 +771,6 @@ static void mtip_handle_tfe(struct driver_data *dd)
|
|||
}
|
||||
}
|
||||
print_tags(dd, "reissued (TFE)", tagaccum, cmd_cnt);
|
||||
|
||||
handle_tfe_exit:
|
||||
/* clear eh_active */
|
||||
clear_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags);
|
||||
wake_up_interruptible(&port->svc_wait);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1007,6 +1002,7 @@ static bool mtip_pause_ncq(struct mtip_port *port,
|
|||
(fis->features == 0x27 || fis->features == 0x72 ||
|
||||
fis->features == 0x62 || fis->features == 0x26))) {
|
||||
clear_bit(MTIP_DDF_SEC_LOCK_BIT, &port->dd->dd_flag);
|
||||
clear_bit(MTIP_DDF_REBUILD_FAILED_BIT, &port->dd->dd_flag);
|
||||
/* Com reset after secure erase or lowlevel format */
|
||||
mtip_restart_port(port);
|
||||
clear_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags);
|
||||
|
|
@ -1021,12 +1017,14 @@ static bool mtip_pause_ncq(struct mtip_port *port,
|
|||
*
|
||||
* @port Pointer to port data structure
|
||||
* @timeout Max duration to wait (ms)
|
||||
* @atomic gfp_t flag to indicate blockable context or not
|
||||
*
|
||||
* return value
|
||||
* 0 Success
|
||||
* -EBUSY Commands still active
|
||||
*/
|
||||
static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout)
|
||||
static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout,
|
||||
gfp_t atomic)
|
||||
{
|
||||
unsigned long to;
|
||||
unsigned int n;
|
||||
|
|
@ -1037,16 +1035,21 @@ static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout)
|
|||
to = jiffies + msecs_to_jiffies(timeout);
|
||||
do {
|
||||
if (test_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags) &&
|
||||
test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags)) {
|
||||
test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags) &&
|
||||
atomic == GFP_KERNEL) {
|
||||
msleep(20);
|
||||
continue; /* svc thd is actively issuing commands */
|
||||
}
|
||||
|
||||
msleep(100);
|
||||
if (atomic == GFP_KERNEL)
|
||||
msleep(100);
|
||||
else {
|
||||
cpu_relax();
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
if (mtip_check_surprise_removal(port->dd->pdev))
|
||||
goto err_fault;
|
||||
if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &port->dd->dd_flag))
|
||||
goto err_fault;
|
||||
|
||||
/*
|
||||
* Ignore s_active bit 0 of array element 0.
|
||||
|
|
@ -1099,6 +1102,7 @@ static int mtip_exec_internal_command(struct mtip_port *port,
|
|||
struct mtip_cmd *int_cmd;
|
||||
struct driver_data *dd = port->dd;
|
||||
int rv = 0;
|
||||
unsigned long start;
|
||||
|
||||
/* Make sure the buffer is 8 byte aligned. This is asic specific. */
|
||||
if (buffer & 0x00000007) {
|
||||
|
|
@ -1107,6 +1111,10 @@ static int mtip_exec_internal_command(struct mtip_port *port,
|
|||
}
|
||||
|
||||
int_cmd = mtip_get_int_command(dd);
|
||||
if (!int_cmd) {
|
||||
dbg_printk(MTIP_DRV_NAME "Unable to allocate tag for PIO cmd\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
set_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags);
|
||||
|
||||
|
|
@ -1119,7 +1127,7 @@ static int mtip_exec_internal_command(struct mtip_port *port,
|
|||
if (fis->command != ATA_CMD_STANDBYNOW1) {
|
||||
/* wait for io to complete if non atomic */
|
||||
if (mtip_quiesce_io(port,
|
||||
MTIP_QUIESCE_IO_TIMEOUT_MS) < 0) {
|
||||
MTIP_QUIESCE_IO_TIMEOUT_MS, atomic) < 0) {
|
||||
dev_warn(&dd->pdev->dev,
|
||||
"Failed to quiesce IO\n");
|
||||
mtip_put_int_command(dd, int_cmd);
|
||||
|
|
@ -1162,6 +1170,8 @@ static int mtip_exec_internal_command(struct mtip_port *port,
|
|||
/* Populate the command header */
|
||||
int_cmd->command_header->byte_count = 0;
|
||||
|
||||
start = jiffies;
|
||||
|
||||
/* Issue the command to the hardware */
|
||||
mtip_issue_non_ncq_command(port, MTIP_TAG_INTERNAL);
|
||||
|
||||
|
|
@ -1170,10 +1180,12 @@ static int mtip_exec_internal_command(struct mtip_port *port,
|
|||
if ((rv = wait_for_completion_interruptible_timeout(
|
||||
&wait,
|
||||
msecs_to_jiffies(timeout))) <= 0) {
|
||||
|
||||
if (rv == -ERESTARTSYS) { /* interrupted */
|
||||
dev_err(&dd->pdev->dev,
|
||||
"Internal command [%02X] was interrupted after %lu ms\n",
|
||||
fis->command, timeout);
|
||||
"Internal command [%02X] was interrupted after %u ms\n",
|
||||
fis->command,
|
||||
jiffies_to_msecs(jiffies - start));
|
||||
rv = -EINTR;
|
||||
goto exec_ic_exit;
|
||||
} else if (rv == 0) /* timeout */
|
||||
|
|
@ -2897,6 +2909,42 @@ static int mtip_ftl_rebuild_poll(struct driver_data *dd)
|
|||
return -EFAULT;
|
||||
}
|
||||
|
||||
static void mtip_softirq_done_fn(struct request *rq)
|
||||
{
|
||||
struct mtip_cmd *cmd = blk_mq_rq_to_pdu(rq);
|
||||
struct driver_data *dd = rq->q->queuedata;
|
||||
|
||||
/* Unmap the DMA scatter list entries */
|
||||
dma_unmap_sg(&dd->pdev->dev, cmd->sg, cmd->scatter_ents,
|
||||
cmd->direction);
|
||||
|
||||
if (unlikely(cmd->unaligned))
|
||||
up(&dd->port->cmd_slot_unal);
|
||||
|
||||
blk_mq_end_request(rq, rq->errors);
|
||||
}
|
||||
|
||||
static void mtip_abort_cmd(struct request *req, void *data,
|
||||
bool reserved)
|
||||
{
|
||||
struct driver_data *dd = data;
|
||||
|
||||
dbg_printk(MTIP_DRV_NAME " Aborting request, tag = %d\n", req->tag);
|
||||
|
||||
clear_bit(req->tag, dd->port->cmds_to_issue);
|
||||
req->errors = -EIO;
|
||||
mtip_softirq_done_fn(req);
|
||||
}
|
||||
|
||||
static void mtip_queue_cmd(struct request *req, void *data,
|
||||
bool reserved)
|
||||
{
|
||||
struct driver_data *dd = data;
|
||||
|
||||
set_bit(req->tag, dd->port->cmds_to_issue);
|
||||
blk_abort_request(req);
|
||||
}
|
||||
|
||||
/*
|
||||
* service thread to issue queued commands
|
||||
*
|
||||
|
|
@ -2909,7 +2957,7 @@ static int mtip_ftl_rebuild_poll(struct driver_data *dd)
|
|||
static int mtip_service_thread(void *data)
|
||||
{
|
||||
struct driver_data *dd = (struct driver_data *)data;
|
||||
unsigned long slot, slot_start, slot_wrap;
|
||||
unsigned long slot, slot_start, slot_wrap, to;
|
||||
unsigned int num_cmd_slots = dd->slot_groups * 32;
|
||||
struct mtip_port *port = dd->port;
|
||||
|
||||
|
|
@ -2924,9 +2972,7 @@ static int mtip_service_thread(void *data)
|
|||
* is in progress nor error handling is active
|
||||
*/
|
||||
wait_event_interruptible(port->svc_wait, (port->flags) &&
|
||||
!(port->flags & MTIP_PF_PAUSE_IO));
|
||||
|
||||
set_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags);
|
||||
(port->flags & MTIP_PF_SVC_THD_WORK));
|
||||
|
||||
if (kthread_should_stop() ||
|
||||
test_bit(MTIP_PF_SVC_THD_STOP_BIT, &port->flags))
|
||||
|
|
@ -2936,6 +2982,8 @@ static int mtip_service_thread(void *data)
|
|||
&dd->dd_flag)))
|
||||
goto st_out;
|
||||
|
||||
set_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags);
|
||||
|
||||
restart_eh:
|
||||
/* Demux bits: start with error handling */
|
||||
if (test_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags)) {
|
||||
|
|
@ -2946,6 +2994,32 @@ static int mtip_service_thread(void *data)
|
|||
if (test_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags))
|
||||
goto restart_eh;
|
||||
|
||||
if (test_bit(MTIP_PF_TO_ACTIVE_BIT, &port->flags)) {
|
||||
to = jiffies + msecs_to_jiffies(5000);
|
||||
|
||||
do {
|
||||
mdelay(100);
|
||||
} while (atomic_read(&dd->irq_workers_active) != 0 &&
|
||||
time_before(jiffies, to));
|
||||
|
||||
if (atomic_read(&dd->irq_workers_active) != 0)
|
||||
dev_warn(&dd->pdev->dev,
|
||||
"Completion workers still active!");
|
||||
|
||||
spin_lock(dd->queue->queue_lock);
|
||||
blk_mq_all_tag_busy_iter(*dd->tags.tags,
|
||||
mtip_queue_cmd, dd);
|
||||
spin_unlock(dd->queue->queue_lock);
|
||||
|
||||
set_bit(MTIP_PF_ISSUE_CMDS_BIT, &dd->port->flags);
|
||||
|
||||
if (mtip_device_reset(dd))
|
||||
blk_mq_all_tag_busy_iter(*dd->tags.tags,
|
||||
mtip_abort_cmd, dd);
|
||||
|
||||
clear_bit(MTIP_PF_TO_ACTIVE_BIT, &dd->port->flags);
|
||||
}
|
||||
|
||||
if (test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags)) {
|
||||
slot = 1;
|
||||
/* used to restrict the loop to one iteration */
|
||||
|
|
@ -2978,10 +3052,8 @@ static int mtip_service_thread(void *data)
|
|||
}
|
||||
|
||||
if (test_bit(MTIP_PF_REBUILD_BIT, &port->flags)) {
|
||||
if (mtip_ftl_rebuild_poll(dd) < 0)
|
||||
set_bit(MTIP_DDF_REBUILD_FAILED_BIT,
|
||||
&dd->dd_flag);
|
||||
clear_bit(MTIP_PF_REBUILD_BIT, &port->flags);
|
||||
if (mtip_ftl_rebuild_poll(dd) == 0)
|
||||
clear_bit(MTIP_PF_REBUILD_BIT, &port->flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3096,7 +3168,7 @@ static int mtip_hw_get_identify(struct driver_data *dd)
|
|||
if (buf[288] == 0xBF) {
|
||||
dev_info(&dd->pdev->dev,
|
||||
"Drive indicates rebuild has failed.\n");
|
||||
/* TODO */
|
||||
set_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3270,20 +3342,25 @@ static int mtip_hw_init(struct driver_data *dd)
|
|||
return rv;
|
||||
}
|
||||
|
||||
static void mtip_standby_drive(struct driver_data *dd)
|
||||
static int mtip_standby_drive(struct driver_data *dd)
|
||||
{
|
||||
if (dd->sr)
|
||||
return;
|
||||
int rv = 0;
|
||||
|
||||
if (dd->sr || !dd->port)
|
||||
return -ENODEV;
|
||||
/*
|
||||
* Send standby immediate (E0h) to the drive so that it
|
||||
* saves its state.
|
||||
*/
|
||||
if (!test_bit(MTIP_PF_REBUILD_BIT, &dd->port->flags) &&
|
||||
!test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag))
|
||||
if (mtip_standby_immediate(dd->port))
|
||||
!test_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag) &&
|
||||
!test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag)) {
|
||||
rv = mtip_standby_immediate(dd->port);
|
||||
if (rv)
|
||||
dev_warn(&dd->pdev->dev,
|
||||
"STANDBY IMMEDIATE failed\n");
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -3296,10 +3373,6 @@ static void mtip_standby_drive(struct driver_data *dd)
|
|||
*/
|
||||
static int mtip_hw_exit(struct driver_data *dd)
|
||||
{
|
||||
/*
|
||||
* Send standby immediate (E0h) to the drive so that it
|
||||
* saves its state.
|
||||
*/
|
||||
if (!dd->sr) {
|
||||
/* de-initialize the port. */
|
||||
mtip_deinit_port(dd->port);
|
||||
|
|
@ -3341,8 +3414,7 @@ static int mtip_hw_shutdown(struct driver_data *dd)
|
|||
* Send standby immediate (E0h) to the drive so that it
|
||||
* saves its state.
|
||||
*/
|
||||
if (!dd->sr && dd->port)
|
||||
mtip_standby_immediate(dd->port);
|
||||
mtip_standby_drive(dd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -3365,7 +3437,7 @@ static int mtip_hw_suspend(struct driver_data *dd)
|
|||
* Send standby immediate (E0h) to the drive
|
||||
* so that it saves its state.
|
||||
*/
|
||||
if (mtip_standby_immediate(dd->port) != 0) {
|
||||
if (mtip_standby_drive(dd) != 0) {
|
||||
dev_err(&dd->pdev->dev,
|
||||
"Failed standby-immediate command\n");
|
||||
return -EFAULT;
|
||||
|
|
@ -3603,6 +3675,28 @@ static int mtip_block_getgeo(struct block_device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mtip_block_open(struct block_device *dev, fmode_t mode)
|
||||
{
|
||||
struct driver_data *dd;
|
||||
|
||||
if (dev && dev->bd_disk) {
|
||||
dd = (struct driver_data *) dev->bd_disk->private_data;
|
||||
|
||||
if (dd) {
|
||||
if (test_bit(MTIP_DDF_REMOVAL_BIT,
|
||||
&dd->dd_flag)) {
|
||||
return -ENODEV;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
void mtip_block_release(struct gendisk *disk, fmode_t mode)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Block device operation function.
|
||||
*
|
||||
|
|
@ -3610,6 +3704,8 @@ static int mtip_block_getgeo(struct block_device *dev,
|
|||
* layer.
|
||||
*/
|
||||
static const struct block_device_operations mtip_block_ops = {
|
||||
.open = mtip_block_open,
|
||||
.release = mtip_block_release,
|
||||
.ioctl = mtip_block_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = mtip_block_compat_ioctl,
|
||||
|
|
@ -3671,10 +3767,9 @@ static int mtip_submit_request(struct blk_mq_hw_ctx *hctx, struct request *rq)
|
|||
rq_data_dir(rq))) {
|
||||
return -ENODATA;
|
||||
}
|
||||
if (unlikely(test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag)))
|
||||
if (unlikely(test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag) ||
|
||||
test_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag)))
|
||||
return -ENODATA;
|
||||
if (test_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag))
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
if (rq->cmd_flags & REQ_DISCARD) {
|
||||
|
|
@ -3786,11 +3881,33 @@ static int mtip_init_cmd(void *data, struct request *rq, unsigned int hctx_idx,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static enum blk_eh_timer_return mtip_cmd_timeout(struct request *req,
|
||||
bool reserved)
|
||||
{
|
||||
struct driver_data *dd = req->q->queuedata;
|
||||
int ret = BLK_EH_RESET_TIMER;
|
||||
|
||||
if (reserved)
|
||||
goto exit_handler;
|
||||
|
||||
if (test_bit(req->tag, dd->port->cmds_to_issue))
|
||||
goto exit_handler;
|
||||
|
||||
if (test_and_set_bit(MTIP_PF_TO_ACTIVE_BIT, &dd->port->flags))
|
||||
goto exit_handler;
|
||||
|
||||
wake_up_interruptible(&dd->port->svc_wait);
|
||||
exit_handler:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct blk_mq_ops mtip_mq_ops = {
|
||||
.queue_rq = mtip_queue_rq,
|
||||
.map_queue = blk_mq_map_queue,
|
||||
.init_request = mtip_init_cmd,
|
||||
.exit_request = mtip_free_cmd,
|
||||
.complete = mtip_softirq_done_fn,
|
||||
.timeout = mtip_cmd_timeout,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -3857,7 +3974,6 @@ static int mtip_block_initialize(struct driver_data *dd)
|
|||
|
||||
mtip_hw_debugfs_init(dd);
|
||||
|
||||
skip_create_disk:
|
||||
memset(&dd->tags, 0, sizeof(dd->tags));
|
||||
dd->tags.ops = &mtip_mq_ops;
|
||||
dd->tags.nr_hw_queues = 1;
|
||||
|
|
@ -3867,12 +3983,13 @@ static int mtip_block_initialize(struct driver_data *dd)
|
|||
dd->tags.numa_node = dd->numa_node;
|
||||
dd->tags.flags = BLK_MQ_F_SHOULD_MERGE;
|
||||
dd->tags.driver_data = dd;
|
||||
dd->tags.timeout = MTIP_NCQ_CMD_TIMEOUT_MS;
|
||||
|
||||
rv = blk_mq_alloc_tag_set(&dd->tags);
|
||||
if (rv) {
|
||||
dev_err(&dd->pdev->dev,
|
||||
"Unable to allocate request queue\n");
|
||||
goto block_queue_alloc_init_error;
|
||||
goto block_queue_alloc_tag_error;
|
||||
}
|
||||
|
||||
/* Allocate the request queue. */
|
||||
|
|
@ -3887,6 +4004,7 @@ static int mtip_block_initialize(struct driver_data *dd)
|
|||
dd->disk->queue = dd->queue;
|
||||
dd->queue->queuedata = dd;
|
||||
|
||||
skip_create_disk:
|
||||
/* Initialize the protocol layer. */
|
||||
wait_for_rebuild = mtip_hw_get_identify(dd);
|
||||
if (wait_for_rebuild < 0) {
|
||||
|
|
@ -3983,8 +4101,9 @@ static int mtip_block_initialize(struct driver_data *dd)
|
|||
read_capacity_error:
|
||||
init_hw_cmds_error:
|
||||
blk_cleanup_queue(dd->queue);
|
||||
blk_mq_free_tag_set(&dd->tags);
|
||||
block_queue_alloc_init_error:
|
||||
blk_mq_free_tag_set(&dd->tags);
|
||||
block_queue_alloc_tag_error:
|
||||
mtip_hw_debugfs_exit(dd);
|
||||
disk_index_error:
|
||||
spin_lock(&rssd_index_lock);
|
||||
|
|
@ -4001,6 +4120,22 @@ static int mtip_block_initialize(struct driver_data *dd)
|
|||
return rv;
|
||||
}
|
||||
|
||||
static void mtip_no_dev_cleanup(struct request *rq, void *data, bool reserv)
|
||||
{
|
||||
struct driver_data *dd = (struct driver_data *)data;
|
||||
struct mtip_cmd *cmd;
|
||||
|
||||
if (likely(!reserv))
|
||||
blk_mq_complete_request(rq, -ENODEV);
|
||||
else if (test_bit(MTIP_PF_IC_ACTIVE_BIT, &dd->port->flags)) {
|
||||
|
||||
cmd = mtip_cmd_from_tag(dd, MTIP_TAG_INTERNAL);
|
||||
if (cmd->comp_func)
|
||||
cmd->comp_func(dd->port, MTIP_TAG_INTERNAL,
|
||||
cmd, -ENODEV);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Block layer deinitialization function.
|
||||
*
|
||||
|
|
@ -4032,12 +4167,23 @@ static int mtip_block_remove(struct driver_data *dd)
|
|||
}
|
||||
}
|
||||
|
||||
if (!dd->sr)
|
||||
mtip_standby_drive(dd);
|
||||
if (!dd->sr) {
|
||||
/*
|
||||
* Explicitly wait here for IOs to quiesce,
|
||||
* as mtip_standby_drive usually won't wait for IOs.
|
||||
*/
|
||||
if (!mtip_quiesce_io(dd->port, MTIP_QUIESCE_IO_TIMEOUT_MS,
|
||||
GFP_KERNEL))
|
||||
mtip_standby_drive(dd);
|
||||
}
|
||||
else
|
||||
dev_info(&dd->pdev->dev, "device %s surprise removal\n",
|
||||
dd->disk->disk_name);
|
||||
|
||||
blk_mq_freeze_queue_start(dd->queue);
|
||||
blk_mq_stop_hw_queues(dd->queue);
|
||||
blk_mq_all_tag_busy_iter(dd->tags.tags[0], mtip_no_dev_cleanup, dd);
|
||||
|
||||
/*
|
||||
* Delete our gendisk structure. This also removes the device
|
||||
* from /dev
|
||||
|
|
@ -4047,7 +4193,8 @@ static int mtip_block_remove(struct driver_data *dd)
|
|||
dd->bdev = NULL;
|
||||
}
|
||||
if (dd->disk) {
|
||||
del_gendisk(dd->disk);
|
||||
if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag))
|
||||
del_gendisk(dd->disk);
|
||||
if (dd->disk->queue) {
|
||||
blk_cleanup_queue(dd->queue);
|
||||
blk_mq_free_tag_set(&dd->tags);
|
||||
|
|
@ -4088,7 +4235,8 @@ static int mtip_block_shutdown(struct driver_data *dd)
|
|||
dev_info(&dd->pdev->dev,
|
||||
"Shutting down %s ...\n", dd->disk->disk_name);
|
||||
|
||||
del_gendisk(dd->disk);
|
||||
if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag))
|
||||
del_gendisk(dd->disk);
|
||||
if (dd->disk->queue) {
|
||||
blk_cleanup_queue(dd->queue);
|
||||
blk_mq_free_tag_set(&dd->tags);
|
||||
|
|
@ -4433,7 +4581,7 @@ static void mtip_pci_remove(struct pci_dev *pdev)
|
|||
struct driver_data *dd = pci_get_drvdata(pdev);
|
||||
unsigned long flags, to;
|
||||
|
||||
set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag);
|
||||
set_bit(MTIP_DDF_REMOVAL_BIT, &dd->dd_flag);
|
||||
|
||||
spin_lock_irqsave(&dev_lock, flags);
|
||||
list_del_init(&dd->online_list);
|
||||
|
|
@ -4450,12 +4598,17 @@ static void mtip_pci_remove(struct pci_dev *pdev)
|
|||
} while (atomic_read(&dd->irq_workers_active) != 0 &&
|
||||
time_before(jiffies, to));
|
||||
|
||||
if (!dd->sr)
|
||||
fsync_bdev(dd->bdev);
|
||||
|
||||
if (atomic_read(&dd->irq_workers_active) != 0) {
|
||||
dev_warn(&dd->pdev->dev,
|
||||
"Completion workers still active!\n");
|
||||
}
|
||||
|
||||
blk_mq_stop_hw_queues(dd->queue);
|
||||
blk_set_queue_dying(dd->queue);
|
||||
set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag);
|
||||
|
||||
/* Clean up the block layer. */
|
||||
mtip_block_remove(dd);
|
||||
|
||||
|
|
|
|||
|
|
@ -134,16 +134,24 @@ enum {
|
|||
MTIP_PF_EH_ACTIVE_BIT = 1, /* error handling */
|
||||
MTIP_PF_SE_ACTIVE_BIT = 2, /* secure erase */
|
||||
MTIP_PF_DM_ACTIVE_BIT = 3, /* download microcde */
|
||||
MTIP_PF_TO_ACTIVE_BIT = 9, /* timeout handling */
|
||||
MTIP_PF_PAUSE_IO = ((1 << MTIP_PF_IC_ACTIVE_BIT) |
|
||||
(1 << MTIP_PF_EH_ACTIVE_BIT) |
|
||||
(1 << MTIP_PF_SE_ACTIVE_BIT) |
|
||||
(1 << MTIP_PF_DM_ACTIVE_BIT)),
|
||||
(1 << MTIP_PF_DM_ACTIVE_BIT) |
|
||||
(1 << MTIP_PF_TO_ACTIVE_BIT)),
|
||||
|
||||
MTIP_PF_SVC_THD_ACTIVE_BIT = 4,
|
||||
MTIP_PF_ISSUE_CMDS_BIT = 5,
|
||||
MTIP_PF_REBUILD_BIT = 6,
|
||||
MTIP_PF_SVC_THD_STOP_BIT = 8,
|
||||
|
||||
MTIP_PF_SVC_THD_WORK = ((1 << MTIP_PF_EH_ACTIVE_BIT) |
|
||||
(1 << MTIP_PF_ISSUE_CMDS_BIT) |
|
||||
(1 << MTIP_PF_REBUILD_BIT) |
|
||||
(1 << MTIP_PF_SVC_THD_STOP_BIT) |
|
||||
(1 << MTIP_PF_TO_ACTIVE_BIT)),
|
||||
|
||||
/* below are bit numbers in 'dd_flag' defined in driver_data */
|
||||
MTIP_DDF_SEC_LOCK_BIT = 0,
|
||||
MTIP_DDF_REMOVE_PENDING_BIT = 1,
|
||||
|
|
@ -153,6 +161,7 @@ enum {
|
|||
MTIP_DDF_RESUME_BIT = 6,
|
||||
MTIP_DDF_INIT_DONE_BIT = 7,
|
||||
MTIP_DDF_REBUILD_FAILED_BIT = 8,
|
||||
MTIP_DDF_REMOVAL_BIT = 9,
|
||||
|
||||
MTIP_DDF_STOP_IO = ((1 << MTIP_DDF_REMOVE_PENDING_BIT) |
|
||||
(1 << MTIP_DDF_SEC_LOCK_BIT) |
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ static const struct usb_device_id ath3k_table[] = {
|
|||
{ USB_DEVICE(0x0489, 0xe05f) },
|
||||
{ USB_DEVICE(0x0489, 0xe076) },
|
||||
{ USB_DEVICE(0x0489, 0xe078) },
|
||||
{ USB_DEVICE(0x0489, 0xe095) },
|
||||
{ USB_DEVICE(0x04c5, 0x1330) },
|
||||
{ USB_DEVICE(0x04CA, 0x3004) },
|
||||
{ USB_DEVICE(0x04CA, 0x3005) },
|
||||
|
|
@ -92,6 +93,7 @@ static const struct usb_device_id ath3k_table[] = {
|
|||
{ USB_DEVICE(0x04CA, 0x300d) },
|
||||
{ USB_DEVICE(0x04CA, 0x300f) },
|
||||
{ USB_DEVICE(0x04CA, 0x3010) },
|
||||
{ USB_DEVICE(0x04CA, 0x3014) },
|
||||
{ USB_DEVICE(0x0930, 0x0219) },
|
||||
{ USB_DEVICE(0x0930, 0x021c) },
|
||||
{ USB_DEVICE(0x0930, 0x0220) },
|
||||
|
|
@ -113,10 +115,12 @@ static const struct usb_device_id ath3k_table[] = {
|
|||
{ USB_DEVICE(0x13d3, 0x3362) },
|
||||
{ USB_DEVICE(0x13d3, 0x3375) },
|
||||
{ USB_DEVICE(0x13d3, 0x3393) },
|
||||
{ USB_DEVICE(0x13d3, 0x3395) },
|
||||
{ USB_DEVICE(0x13d3, 0x3402) },
|
||||
{ USB_DEVICE(0x13d3, 0x3408) },
|
||||
{ USB_DEVICE(0x13d3, 0x3423) },
|
||||
{ USB_DEVICE(0x13d3, 0x3432) },
|
||||
{ USB_DEVICE(0x13d3, 0x3472) },
|
||||
{ USB_DEVICE(0x13d3, 0x3474) },
|
||||
|
||||
/* Atheros AR5BBU12 with sflash firmware */
|
||||
|
|
@ -144,6 +148,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
|
|||
{ USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe076), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe095), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
|
||||
|
|
@ -154,6 +159,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
|
|||
{ USB_DEVICE(0x04ca, 0x300d), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3014), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
|
||||
|
|
@ -175,10 +181,12 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
|
|||
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3395), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3423), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3472), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3474), .driver_info = BTUSB_ATH3012 },
|
||||
|
||||
/* Atheros AR5BBU22 with sflash firmware */
|
||||
|
|
|
|||
|
|
@ -196,6 +196,7 @@ static const struct usb_device_id blacklist_table[] = {
|
|||
{ USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe076), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe095), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
|
||||
|
|
@ -206,6 +207,7 @@ static const struct usb_device_id blacklist_table[] = {
|
|||
{ USB_DEVICE(0x04ca, 0x300d), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3014), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
|
||||
|
|
@ -227,10 +229,12 @@ static const struct usb_device_id blacklist_table[] = {
|
|||
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3395), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3423), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3472), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3474), .driver_info = BTUSB_ATH3012 },
|
||||
|
||||
/* Atheros AR5BBU12 with sflash firmware */
|
||||
|
|
|
|||
|
|
@ -136,11 +136,13 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev,
|
|||
chip->cdev.owner = chip->pdev->driver->owner;
|
||||
chip->cdev.kobj.parent = &chip->dev.kobj;
|
||||
|
||||
devm_add_action(dev, (void (*)(void *)) put_device, &chip->dev);
|
||||
|
||||
return chip;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tpmm_chip_alloc);
|
||||
|
||||
static int tpm_dev_add_device(struct tpm_chip *chip)
|
||||
static int tpm_add_char_device(struct tpm_chip *chip)
|
||||
{
|
||||
int rc;
|
||||
|
||||
|
|
@ -151,7 +153,6 @@ static int tpm_dev_add_device(struct tpm_chip *chip)
|
|||
chip->devname, MAJOR(chip->dev.devt),
|
||||
MINOR(chip->dev.devt), rc);
|
||||
|
||||
device_unregister(&chip->dev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -162,16 +163,17 @@ static int tpm_dev_add_device(struct tpm_chip *chip)
|
|||
chip->devname, MAJOR(chip->dev.devt),
|
||||
MINOR(chip->dev.devt), rc);
|
||||
|
||||
cdev_del(&chip->cdev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void tpm_dev_del_device(struct tpm_chip *chip)
|
||||
static void tpm_del_char_device(struct tpm_chip *chip)
|
||||
{
|
||||
cdev_del(&chip->cdev);
|
||||
device_unregister(&chip->dev);
|
||||
device_del(&chip->dev);
|
||||
}
|
||||
|
||||
static int tpm1_chip_register(struct tpm_chip *chip)
|
||||
|
|
@ -222,7 +224,7 @@ int tpm_chip_register(struct tpm_chip *chip)
|
|||
|
||||
tpm_add_ppi(chip);
|
||||
|
||||
rc = tpm_dev_add_device(chip);
|
||||
rc = tpm_add_char_device(chip);
|
||||
if (rc)
|
||||
goto out_err;
|
||||
|
||||
|
|
@ -274,6 +276,6 @@ void tpm_chip_unregister(struct tpm_chip *chip)
|
|||
sysfs_remove_link(&chip->pdev->kobj, "ppi");
|
||||
|
||||
tpm1_chip_unregister(chip);
|
||||
tpm_dev_del_device(chip);
|
||||
tpm_del_char_device(chip);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tpm_chip_unregister);
|
||||
|
|
|
|||
|
|
@ -310,11 +310,11 @@ static int crb_acpi_remove(struct acpi_device *device)
|
|||
struct device *dev = &device->dev;
|
||||
struct tpm_chip *chip = dev_get_drvdata(dev);
|
||||
|
||||
tpm_chip_unregister(chip);
|
||||
|
||||
if (chip->flags & TPM_CHIP_FLAG_TPM2)
|
||||
tpm2_shutdown(chip, TPM2_SU_CLEAR);
|
||||
|
||||
tpm_chip_unregister(chip);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
|
|||
{
|
||||
struct tcpa_event *event = v;
|
||||
struct tcpa_event temp_event;
|
||||
char *tempPtr;
|
||||
char *temp_ptr;
|
||||
int i;
|
||||
|
||||
memcpy(&temp_event, event, sizeof(struct tcpa_event));
|
||||
|
|
@ -242,10 +242,16 @@ static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
|
|||
temp_event.event_type = do_endian_conversion(event->event_type);
|
||||
temp_event.event_size = do_endian_conversion(event->event_size);
|
||||
|
||||
tempPtr = (char *)&temp_event;
|
||||
temp_ptr = (char *) &temp_event;
|
||||
|
||||
for (i = 0; i < sizeof(struct tcpa_event) + temp_event.event_size; i++)
|
||||
seq_putc(m, tempPtr[i]);
|
||||
for (i = 0; i < (sizeof(struct tcpa_event) - 1) ; i++)
|
||||
seq_putc(m, temp_ptr[i]);
|
||||
|
||||
temp_ptr = (char *) v;
|
||||
|
||||
for (i = (sizeof(struct tcpa_event) - 1);
|
||||
i < (sizeof(struct tcpa_event) + temp_event.event_size); i++)
|
||||
seq_putc(m, temp_ptr[i]);
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -1097,13 +1097,15 @@ static int bcm2835_pll_divider_set_rate(struct clk_hw *hw,
|
|||
struct bcm2835_pll_divider *divider = bcm2835_pll_divider_from_hw(hw);
|
||||
struct bcm2835_cprman *cprman = divider->cprman;
|
||||
const struct bcm2835_pll_divider_data *data = divider->data;
|
||||
u32 cm;
|
||||
int ret;
|
||||
u32 cm, div, max_div = 1 << A2W_PLL_DIV_BITS;
|
||||
|
||||
ret = clk_divider_ops.set_rate(hw, rate, parent_rate);
|
||||
if (ret)
|
||||
return ret;
|
||||
div = DIV_ROUND_UP_ULL(parent_rate, rate);
|
||||
|
||||
div = min(div, max_div);
|
||||
if (div == max_div)
|
||||
div = 0;
|
||||
|
||||
cprman_write(cprman, data->a2w_reg, div);
|
||||
cm = cprman_read(cprman, data->cm_reg);
|
||||
cprman_write(cprman, data->cm_reg, cm | data->load_mask);
|
||||
cprman_write(cprman, data->cm_reg, cm & ~data->load_mask);
|
||||
|
|
|
|||
|
|
@ -718,6 +718,7 @@ static const char *const rk3188_critical_clocks[] __initconst = {
|
|||
"hclk_peri",
|
||||
"pclk_cpu",
|
||||
"pclk_peri",
|
||||
"hclk_cpubus"
|
||||
};
|
||||
|
||||
static void __init rk3188_common_clk_init(struct device_node *np)
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ static const struct rockchip_cpuclk_reg_data rk3368_cpuclkb_data = {
|
|||
.core_reg = RK3368_CLKSEL_CON(0),
|
||||
.div_core_shift = 0,
|
||||
.div_core_mask = 0x1f,
|
||||
.mux_core_shift = 15,
|
||||
.mux_core_shift = 7,
|
||||
};
|
||||
|
||||
static const struct rockchip_cpuclk_reg_data rk3368_cpuclkl_data = {
|
||||
|
|
@ -218,29 +218,29 @@ static const struct rockchip_cpuclk_reg_data rk3368_cpuclkl_data = {
|
|||
}
|
||||
|
||||
static struct rockchip_cpuclk_rate_table rk3368_cpuclkb_rates[] __initdata = {
|
||||
RK3368_CPUCLKB_RATE(1512000000, 2, 6, 6),
|
||||
RK3368_CPUCLKB_RATE(1488000000, 2, 5, 5),
|
||||
RK3368_CPUCLKB_RATE(1416000000, 2, 5, 5),
|
||||
RK3368_CPUCLKB_RATE(1200000000, 2, 4, 4),
|
||||
RK3368_CPUCLKB_RATE(1008000000, 2, 4, 4),
|
||||
RK3368_CPUCLKB_RATE( 816000000, 2, 3, 3),
|
||||
RK3368_CPUCLKB_RATE( 696000000, 2, 3, 3),
|
||||
RK3368_CPUCLKB_RATE( 600000000, 2, 2, 2),
|
||||
RK3368_CPUCLKB_RATE( 408000000, 2, 2, 2),
|
||||
RK3368_CPUCLKB_RATE( 312000000, 2, 2, 2),
|
||||
RK3368_CPUCLKB_RATE(1512000000, 1, 5, 5),
|
||||
RK3368_CPUCLKB_RATE(1488000000, 1, 4, 4),
|
||||
RK3368_CPUCLKB_RATE(1416000000, 1, 4, 4),
|
||||
RK3368_CPUCLKB_RATE(1200000000, 1, 3, 3),
|
||||
RK3368_CPUCLKB_RATE(1008000000, 1, 3, 3),
|
||||
RK3368_CPUCLKB_RATE( 816000000, 1, 2, 2),
|
||||
RK3368_CPUCLKB_RATE( 696000000, 1, 2, 2),
|
||||
RK3368_CPUCLKB_RATE( 600000000, 1, 1, 1),
|
||||
RK3368_CPUCLKB_RATE( 408000000, 1, 1, 1),
|
||||
RK3368_CPUCLKB_RATE( 312000000, 1, 1, 1),
|
||||
};
|
||||
|
||||
static struct rockchip_cpuclk_rate_table rk3368_cpuclkl_rates[] __initdata = {
|
||||
RK3368_CPUCLKL_RATE(1512000000, 2, 7, 7),
|
||||
RK3368_CPUCLKL_RATE(1488000000, 2, 6, 6),
|
||||
RK3368_CPUCLKL_RATE(1416000000, 2, 6, 6),
|
||||
RK3368_CPUCLKL_RATE(1200000000, 2, 5, 5),
|
||||
RK3368_CPUCLKL_RATE(1008000000, 2, 5, 5),
|
||||
RK3368_CPUCLKL_RATE( 816000000, 2, 4, 4),
|
||||
RK3368_CPUCLKL_RATE( 696000000, 2, 3, 3),
|
||||
RK3368_CPUCLKL_RATE( 600000000, 2, 3, 3),
|
||||
RK3368_CPUCLKL_RATE( 408000000, 2, 2, 2),
|
||||
RK3368_CPUCLKL_RATE( 312000000, 2, 2, 2),
|
||||
RK3368_CPUCLKL_RATE(1512000000, 1, 6, 6),
|
||||
RK3368_CPUCLKL_RATE(1488000000, 1, 5, 5),
|
||||
RK3368_CPUCLKL_RATE(1416000000, 1, 5, 5),
|
||||
RK3368_CPUCLKL_RATE(1200000000, 1, 4, 4),
|
||||
RK3368_CPUCLKL_RATE(1008000000, 1, 4, 4),
|
||||
RK3368_CPUCLKL_RATE( 816000000, 1, 3, 3),
|
||||
RK3368_CPUCLKL_RATE( 696000000, 1, 2, 2),
|
||||
RK3368_CPUCLKL_RATE( 600000000, 1, 2, 2),
|
||||
RK3368_CPUCLKL_RATE( 408000000, 1, 1, 1),
|
||||
RK3368_CPUCLKL_RATE( 312000000, 1, 1, 1),
|
||||
};
|
||||
|
||||
static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = {
|
||||
|
|
@ -384,10 +384,10 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = {
|
|||
* Clock-Architecture Diagram 3
|
||||
*/
|
||||
|
||||
COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_usb_p, 0,
|
||||
COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_npll_usb_p, 0,
|
||||
RK3368_CLKSEL_CON(15), 6, 2, MFLAGS, 0, 5, DFLAGS,
|
||||
RK3368_CLKGATE_CON(4), 6, GFLAGS),
|
||||
COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_usb_p, 0,
|
||||
COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_npll_usb_p, 0,
|
||||
RK3368_CLKSEL_CON(15), 14, 2, MFLAGS, 8, 5, DFLAGS,
|
||||
RK3368_CLKGATE_CON(4), 7, GFLAGS),
|
||||
|
||||
|
|
@ -442,7 +442,7 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = {
|
|||
GATE(SCLK_HDMI_HDCP, "sclk_hdmi_hdcp", "xin24m", 0,
|
||||
RK3368_CLKGATE_CON(4), 13, GFLAGS),
|
||||
GATE(SCLK_HDMI_CEC, "sclk_hdmi_cec", "xin32k", 0,
|
||||
RK3368_CLKGATE_CON(5), 12, GFLAGS),
|
||||
RK3368_CLKGATE_CON(4), 12, GFLAGS),
|
||||
|
||||
COMPOSITE_NODIV(0, "vip_src", mux_pll_src_cpll_gpll_p, 0,
|
||||
RK3368_CLKSEL_CON(21), 15, 1, MFLAGS,
|
||||
|
|
|
|||
|
|
@ -1396,9 +1396,9 @@ static int atmel_aes_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
aes_dd->io_base = devm_ioremap_resource(&pdev->dev, aes_res);
|
||||
if (!aes_dd->io_base) {
|
||||
if (IS_ERR(aes_dd->io_base)) {
|
||||
dev_err(dev, "can't ioremap\n");
|
||||
err = -ENOMEM;
|
||||
err = PTR_ERR(aes_dd->io_base);
|
||||
goto res_err;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1405,9 +1405,9 @@ static int atmel_sha_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
sha_dd->io_base = devm_ioremap_resource(&pdev->dev, sha_res);
|
||||
if (!sha_dd->io_base) {
|
||||
if (IS_ERR(sha_dd->io_base)) {
|
||||
dev_err(dev, "can't ioremap\n");
|
||||
err = -ENOMEM;
|
||||
err = PTR_ERR(sha_dd->io_base);
|
||||
goto res_err;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1417,9 +1417,9 @@ static int atmel_tdes_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
tdes_dd->io_base = devm_ioremap_resource(&pdev->dev, tdes_res);
|
||||
if (!tdes_dd->io_base) {
|
||||
if (IS_ERR(tdes_dd->io_base)) {
|
||||
dev_err(dev, "can't ioremap\n");
|
||||
err = -ENOMEM;
|
||||
err = PTR_ERR(tdes_dd->io_base);
|
||||
goto res_err;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -220,6 +220,39 @@ static int ccp_aes_cmac_digest(struct ahash_request *req)
|
|||
return ccp_aes_cmac_finup(req);
|
||||
}
|
||||
|
||||
static int ccp_aes_cmac_export(struct ahash_request *req, void *out)
|
||||
{
|
||||
struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req);
|
||||
struct ccp_aes_cmac_exp_ctx state;
|
||||
|
||||
state.null_msg = rctx->null_msg;
|
||||
memcpy(state.iv, rctx->iv, sizeof(state.iv));
|
||||
state.buf_count = rctx->buf_count;
|
||||
memcpy(state.buf, rctx->buf, sizeof(state.buf));
|
||||
|
||||
/* 'out' may not be aligned so memcpy from local variable */
|
||||
memcpy(out, &state, sizeof(state));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ccp_aes_cmac_import(struct ahash_request *req, const void *in)
|
||||
{
|
||||
struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req);
|
||||
struct ccp_aes_cmac_exp_ctx state;
|
||||
|
||||
/* 'in' may not be aligned so memcpy to local variable */
|
||||
memcpy(&state, in, sizeof(state));
|
||||
|
||||
memset(rctx, 0, sizeof(*rctx));
|
||||
rctx->null_msg = state.null_msg;
|
||||
memcpy(rctx->iv, state.iv, sizeof(rctx->iv));
|
||||
rctx->buf_count = state.buf_count;
|
||||
memcpy(rctx->buf, state.buf, sizeof(rctx->buf));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ccp_aes_cmac_setkey(struct crypto_ahash *tfm, const u8 *key,
|
||||
unsigned int key_len)
|
||||
{
|
||||
|
|
@ -352,10 +385,13 @@ int ccp_register_aes_cmac_algs(struct list_head *head)
|
|||
alg->final = ccp_aes_cmac_final;
|
||||
alg->finup = ccp_aes_cmac_finup;
|
||||
alg->digest = ccp_aes_cmac_digest;
|
||||
alg->export = ccp_aes_cmac_export;
|
||||
alg->import = ccp_aes_cmac_import;
|
||||
alg->setkey = ccp_aes_cmac_setkey;
|
||||
|
||||
halg = &alg->halg;
|
||||
halg->digestsize = AES_BLOCK_SIZE;
|
||||
halg->statesize = sizeof(struct ccp_aes_cmac_exp_ctx);
|
||||
|
||||
base = &halg->base;
|
||||
snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "cmac(aes)");
|
||||
|
|
|
|||
|
|
@ -207,6 +207,43 @@ static int ccp_sha_digest(struct ahash_request *req)
|
|||
return ccp_sha_finup(req);
|
||||
}
|
||||
|
||||
static int ccp_sha_export(struct ahash_request *req, void *out)
|
||||
{
|
||||
struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req);
|
||||
struct ccp_sha_exp_ctx state;
|
||||
|
||||
state.type = rctx->type;
|
||||
state.msg_bits = rctx->msg_bits;
|
||||
state.first = rctx->first;
|
||||
memcpy(state.ctx, rctx->ctx, sizeof(state.ctx));
|
||||
state.buf_count = rctx->buf_count;
|
||||
memcpy(state.buf, rctx->buf, sizeof(state.buf));
|
||||
|
||||
/* 'out' may not be aligned so memcpy from local variable */
|
||||
memcpy(out, &state, sizeof(state));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ccp_sha_import(struct ahash_request *req, const void *in)
|
||||
{
|
||||
struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req);
|
||||
struct ccp_sha_exp_ctx state;
|
||||
|
||||
/* 'in' may not be aligned so memcpy to local variable */
|
||||
memcpy(&state, in, sizeof(state));
|
||||
|
||||
memset(rctx, 0, sizeof(*rctx));
|
||||
rctx->type = state.type;
|
||||
rctx->msg_bits = state.msg_bits;
|
||||
rctx->first = state.first;
|
||||
memcpy(rctx->ctx, state.ctx, sizeof(rctx->ctx));
|
||||
rctx->buf_count = state.buf_count;
|
||||
memcpy(rctx->buf, state.buf, sizeof(rctx->buf));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ccp_sha_setkey(struct crypto_ahash *tfm, const u8 *key,
|
||||
unsigned int key_len)
|
||||
{
|
||||
|
|
@ -403,9 +440,12 @@ static int ccp_register_sha_alg(struct list_head *head,
|
|||
alg->final = ccp_sha_final;
|
||||
alg->finup = ccp_sha_finup;
|
||||
alg->digest = ccp_sha_digest;
|
||||
alg->export = ccp_sha_export;
|
||||
alg->import = ccp_sha_import;
|
||||
|
||||
halg = &alg->halg;
|
||||
halg->digestsize = def->digest_size;
|
||||
halg->statesize = sizeof(struct ccp_sha_exp_ctx);
|
||||
|
||||
base = &halg->base;
|
||||
snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name);
|
||||
|
|
|
|||
|
|
@ -129,6 +129,15 @@ struct ccp_aes_cmac_req_ctx {
|
|||
struct ccp_cmd cmd;
|
||||
};
|
||||
|
||||
struct ccp_aes_cmac_exp_ctx {
|
||||
unsigned int null_msg;
|
||||
|
||||
u8 iv[AES_BLOCK_SIZE];
|
||||
|
||||
unsigned int buf_count;
|
||||
u8 buf[AES_BLOCK_SIZE];
|
||||
};
|
||||
|
||||
/***** SHA related defines *****/
|
||||
#define MAX_SHA_CONTEXT_SIZE SHA256_DIGEST_SIZE
|
||||
#define MAX_SHA_BLOCK_SIZE SHA256_BLOCK_SIZE
|
||||
|
|
@ -171,6 +180,19 @@ struct ccp_sha_req_ctx {
|
|||
struct ccp_cmd cmd;
|
||||
};
|
||||
|
||||
struct ccp_sha_exp_ctx {
|
||||
enum ccp_sha_type type;
|
||||
|
||||
u64 msg_bits;
|
||||
|
||||
unsigned int first;
|
||||
|
||||
u8 ctx[MAX_SHA_CONTEXT_SIZE];
|
||||
|
||||
unsigned int buf_count;
|
||||
u8 buf[MAX_SHA_BLOCK_SIZE];
|
||||
};
|
||||
|
||||
/***** Common Context Structure *****/
|
||||
struct ccp_ctx {
|
||||
int (*complete)(struct crypto_async_request *req, int ret);
|
||||
|
|
|
|||
|
|
@ -420,7 +420,7 @@ static int mv_cesa_probe(struct platform_device *pdev)
|
|||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
|
||||
cesa->regs = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(cesa->regs))
|
||||
return -ENOMEM;
|
||||
return PTR_ERR(cesa->regs);
|
||||
|
||||
ret = mv_cesa_dev_dma_init(cesa);
|
||||
if (ret)
|
||||
|
|
|
|||
|
|
@ -1440,9 +1440,9 @@ static int ux500_cryp_probe(struct platform_device *pdev)
|
|||
|
||||
device_data->phybase = res->start;
|
||||
device_data->base = devm_ioremap_resource(dev, res);
|
||||
if (!device_data->base) {
|
||||
if (IS_ERR(device_data->base)) {
|
||||
dev_err(dev, "[%s]: ioremap failed!", __func__);
|
||||
ret = -ENOMEM;
|
||||
ret = PTR_ERR(device_data->base);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1675,9 +1675,9 @@ static int ux500_hash_probe(struct platform_device *pdev)
|
|||
|
||||
device_data->phybase = res->start;
|
||||
device_data->base = devm_ioremap_resource(dev, res);
|
||||
if (!device_data->base) {
|
||||
if (IS_ERR(device_data->base)) {
|
||||
dev_err(dev, "%s: ioremap() failed!\n", __func__);
|
||||
ret = -ENOMEM;
|
||||
ret = PTR_ERR(device_data->base);
|
||||
goto out;
|
||||
}
|
||||
spin_lock_init(&device_data->ctx_lock);
|
||||
|
|
|
|||
|
|
@ -1452,7 +1452,7 @@ static u64 f1x_get_norm_dct_addr(struct amd64_pvt *pvt, u8 range,
|
|||
u64 chan_off;
|
||||
u64 dram_base = get_dram_base(pvt, range);
|
||||
u64 hole_off = f10_dhar_offset(pvt);
|
||||
u64 dct_sel_base_off = (pvt->dct_sel_hi & 0xFFFFFC00) << 16;
|
||||
u64 dct_sel_base_off = (u64)(pvt->dct_sel_hi & 0xFFFFFC00) << 16;
|
||||
|
||||
if (hi_rng) {
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1117,8 +1117,8 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
|
|||
edac_dbg(0, "TAD#%d: up to %u.%03u GB (0x%016Lx), socket interleave %d, memory interleave %d, TGT: %d, %d, %d, %d, reg=0x%08x\n",
|
||||
n_tads, gb, (mb*1000)/1024,
|
||||
((u64)tmp_mb) << 20L,
|
||||
(u32)TAD_SOCK(reg),
|
||||
(u32)TAD_CH(reg),
|
||||
(u32)(1 << TAD_SOCK(reg)),
|
||||
(u32)TAD_CH(reg) + 1,
|
||||
(u32)TAD_TGT0(reg),
|
||||
(u32)TAD_TGT1(reg),
|
||||
(u32)TAD_TGT2(reg),
|
||||
|
|
@ -1396,7 +1396,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
|
|||
}
|
||||
|
||||
ch_way = TAD_CH(reg) + 1;
|
||||
sck_way = TAD_SOCK(reg) + 1;
|
||||
sck_way = 1 << TAD_SOCK(reg);
|
||||
|
||||
if (ch_way == 3)
|
||||
idx = addr >> 6;
|
||||
|
|
@ -1453,7 +1453,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
|
|||
n_tads,
|
||||
addr,
|
||||
limit,
|
||||
(u32)TAD_SOCK(reg),
|
||||
sck_way,
|
||||
ch_way,
|
||||
offset,
|
||||
idx,
|
||||
|
|
@ -1468,18 +1468,12 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
|
|||
offset, addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
addr -= offset;
|
||||
/* Store the low bits [0:6] of the addr */
|
||||
ch_addr = addr & 0x7f;
|
||||
/* Remove socket wayness and remove 6 bits */
|
||||
addr >>= 6;
|
||||
addr = div_u64(addr, sck_xch);
|
||||
#if 0
|
||||
/* Divide by channel way */
|
||||
addr = addr / ch_way;
|
||||
#endif
|
||||
/* Recover the last 6 bits */
|
||||
ch_addr |= addr << 6;
|
||||
|
||||
ch_addr = addr - offset;
|
||||
ch_addr >>= (6 + shiftup);
|
||||
ch_addr /= ch_way * sck_way;
|
||||
ch_addr <<= (6 + shiftup);
|
||||
ch_addr |= addr & ((1 << (6 + shiftup)) - 1);
|
||||
|
||||
/*
|
||||
* Step 3) Decode rank
|
||||
|
|
|
|||
|
|
@ -63,6 +63,10 @@ bool amdgpu_has_atpx(void) {
|
|||
return amdgpu_atpx_priv.atpx_detected;
|
||||
}
|
||||
|
||||
bool amdgpu_has_atpx_dgpu_power_cntl(void) {
|
||||
return amdgpu_atpx_priv.atpx.functions.power_cntl;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_atpx_call - call an ATPX method
|
||||
*
|
||||
|
|
@ -142,10 +146,6 @@ static void amdgpu_atpx_parse_functions(struct amdgpu_atpx_functions *f, u32 mas
|
|||
*/
|
||||
static int amdgpu_atpx_validate(struct amdgpu_atpx *atpx)
|
||||
{
|
||||
/* make sure required functions are enabled */
|
||||
/* dGPU power control is required */
|
||||
atpx->functions.power_cntl = true;
|
||||
|
||||
if (atpx->functions.px_params) {
|
||||
union acpi_object *info;
|
||||
struct atpx_px_params output;
|
||||
|
|
|
|||
|
|
@ -61,6 +61,12 @@ static const char *amdgpu_asic_name[] = {
|
|||
"LAST",
|
||||
};
|
||||
|
||||
#if defined(CONFIG_VGA_SWITCHEROO)
|
||||
bool amdgpu_has_atpx_dgpu_power_cntl(void);
|
||||
#else
|
||||
static inline bool amdgpu_has_atpx_dgpu_power_cntl(void) { return false; }
|
||||
#endif
|
||||
|
||||
bool amdgpu_device_is_px(struct drm_device *dev)
|
||||
{
|
||||
struct amdgpu_device *adev = dev->dev_private;
|
||||
|
|
@ -1469,7 +1475,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
|||
|
||||
if (amdgpu_runtime_pm == 1)
|
||||
runtime = true;
|
||||
if (amdgpu_device_is_px(ddev))
|
||||
if (amdgpu_device_is_px(ddev) && amdgpu_has_atpx_dgpu_power_cntl())
|
||||
runtime = true;
|
||||
vga_switcheroo_register_client(adev->pdev, &amdgpu_switcheroo_ops, runtime);
|
||||
if (runtime)
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@
|
|||
#include "oss/oss_2_4_d.h"
|
||||
#include "oss/oss_2_4_sh_mask.h"
|
||||
|
||||
#include "gmc/gmc_8_1_d.h"
|
||||
#include "gmc/gmc_8_1_sh_mask.h"
|
||||
#include "gmc/gmc_7_1_d.h"
|
||||
#include "gmc/gmc_7_1_sh_mask.h"
|
||||
|
||||
#include "gca/gfx_8_0_d.h"
|
||||
#include "gca/gfx_8_0_enum.h"
|
||||
|
|
|
|||
|
|
@ -892,8 +892,6 @@ atombios_dig_encoder_setup2(struct drm_encoder *encoder, int action, int panel_m
|
|||
else
|
||||
args.v1.ucLaneNum = 4;
|
||||
|
||||
if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode) && (dp_clock == 270000))
|
||||
args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
|
||||
switch (radeon_encoder->encoder_id) {
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
|
||||
args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
|
||||
|
|
@ -910,6 +908,10 @@ atombios_dig_encoder_setup2(struct drm_encoder *encoder, int action, int panel_m
|
|||
args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
|
||||
else
|
||||
args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
|
||||
|
||||
if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode) && (dp_clock == 270000))
|
||||
args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
|
||||
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
|
|
|
|||
|
|
@ -62,6 +62,10 @@ bool radeon_has_atpx(void) {
|
|||
return radeon_atpx_priv.atpx_detected;
|
||||
}
|
||||
|
||||
bool radeon_has_atpx_dgpu_power_cntl(void) {
|
||||
return radeon_atpx_priv.atpx.functions.power_cntl;
|
||||
}
|
||||
|
||||
/**
|
||||
* radeon_atpx_call - call an ATPX method
|
||||
*
|
||||
|
|
@ -141,10 +145,6 @@ static void radeon_atpx_parse_functions(struct radeon_atpx_functions *f, u32 mas
|
|||
*/
|
||||
static int radeon_atpx_validate(struct radeon_atpx *atpx)
|
||||
{
|
||||
/* make sure required functions are enabled */
|
||||
/* dGPU power control is required */
|
||||
atpx->functions.power_cntl = true;
|
||||
|
||||
if (atpx->functions.px_params) {
|
||||
union acpi_object *info;
|
||||
struct atpx_px_params output;
|
||||
|
|
|
|||
|
|
@ -103,6 +103,12 @@ static const char radeon_family_name[][16] = {
|
|||
"LAST",
|
||||
};
|
||||
|
||||
#if defined(CONFIG_VGA_SWITCHEROO)
|
||||
bool radeon_has_atpx_dgpu_power_cntl(void);
|
||||
#else
|
||||
static inline bool radeon_has_atpx_dgpu_power_cntl(void) { return false; }
|
||||
#endif
|
||||
|
||||
#define RADEON_PX_QUIRK_DISABLE_PX (1 << 0)
|
||||
#define RADEON_PX_QUIRK_LONG_WAKEUP (1 << 1)
|
||||
|
||||
|
|
@ -1433,7 +1439,7 @@ int radeon_device_init(struct radeon_device *rdev,
|
|||
* ignore it */
|
||||
vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode);
|
||||
|
||||
if (rdev->flags & RADEON_IS_PX)
|
||||
if ((rdev->flags & RADEON_IS_PX) && radeon_has_atpx_dgpu_power_cntl())
|
||||
runtime = true;
|
||||
vga_switcheroo_register_client(rdev->pdev, &radeon_switcheroo_ops, runtime);
|
||||
if (runtime)
|
||||
|
|
|
|||
|
|
@ -1897,6 +1897,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DUAL_ACTION) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) },
|
||||
|
|
@ -2615,9 +2616,10 @@ int hid_add_device(struct hid_device *hdev)
|
|||
/*
|
||||
* Scan generic devices for group information
|
||||
*/
|
||||
if (hid_ignore_special_drivers ||
|
||||
(!hdev->group &&
|
||||
!hid_match_id(hdev, hid_have_special_driver))) {
|
||||
if (hid_ignore_special_drivers) {
|
||||
hdev->group = HID_GROUP_GENERIC;
|
||||
} else if (!hdev->group &&
|
||||
!hid_match_id(hdev, hid_have_special_driver)) {
|
||||
ret = hid_scan_report(hdev);
|
||||
if (ret)
|
||||
hid_warn(hdev, "bad device descriptor (%d)\n", ret);
|
||||
|
|
|
|||
|
|
@ -396,6 +396,11 @@ static void mt_feature_mapping(struct hid_device *hdev,
|
|||
td->is_buttonpad = true;
|
||||
|
||||
break;
|
||||
case 0xff0000c5:
|
||||
/* Retrieve the Win8 blob once to enable some devices */
|
||||
if (usage->usage_index == 0)
|
||||
mt_get_feature(hdev, field->report);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -282,18 +282,22 @@ static int i2c_hid_set_or_send_report(struct i2c_client *client, u8 reportType,
|
|||
u16 dataRegister = le16_to_cpu(ihid->hdesc.wDataRegister);
|
||||
u16 outputRegister = le16_to_cpu(ihid->hdesc.wOutputRegister);
|
||||
u16 maxOutputLength = le16_to_cpu(ihid->hdesc.wMaxOutputLength);
|
||||
|
||||
/* hid_hw_* already checked that data_len < HID_MAX_BUFFER_SIZE */
|
||||
u16 size = 2 /* size */ +
|
||||
(reportID ? 1 : 0) /* reportID */ +
|
||||
data_len /* buf */;
|
||||
int args_len = (reportID >= 0x0F ? 1 : 0) /* optional third byte */ +
|
||||
2 /* dataRegister */ +
|
||||
size /* args */;
|
||||
u16 size;
|
||||
int args_len;
|
||||
int index = 0;
|
||||
|
||||
i2c_hid_dbg(ihid, "%s\n", __func__);
|
||||
|
||||
if (data_len > ihid->bufsize)
|
||||
return -EINVAL;
|
||||
|
||||
size = 2 /* size */ +
|
||||
(reportID ? 1 : 0) /* reportID */ +
|
||||
data_len /* buf */;
|
||||
args_len = (reportID >= 0x0F ? 1 : 0) /* optional third byte */ +
|
||||
2 /* dataRegister */ +
|
||||
size /* args */;
|
||||
|
||||
if (!use_data && maxOutputLength == 0)
|
||||
return -ENOSYS;
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@
|
|||
#include <asm/mwait.h>
|
||||
#include <asm/msr.h>
|
||||
|
||||
#define INTEL_IDLE_VERSION "0.4"
|
||||
#define INTEL_IDLE_VERSION "0.4.1"
|
||||
#define PREFIX "intel_idle: "
|
||||
|
||||
static struct cpuidle_driver intel_idle_driver = {
|
||||
|
|
@ -993,37 +993,93 @@ static void intel_idle_cpuidle_devices_uninit(void)
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* ivt_idle_state_table_update(void)
|
||||
*
|
||||
* Tune IVT multi-socket targets
|
||||
* Assumption: num_sockets == (max_package_num + 1)
|
||||
*/
|
||||
static void ivt_idle_state_table_update(void)
|
||||
{
|
||||
/* IVT uses a different table for 1-2, 3-4, and > 4 sockets */
|
||||
int cpu, package_num, num_sockets = 1;
|
||||
|
||||
for_each_online_cpu(cpu) {
|
||||
package_num = topology_physical_package_id(cpu);
|
||||
if (package_num + 1 > num_sockets) {
|
||||
num_sockets = package_num + 1;
|
||||
|
||||
if (num_sockets > 4) {
|
||||
cpuidle_state_table = ivt_cstates_8s;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (num_sockets > 2)
|
||||
cpuidle_state_table = ivt_cstates_4s;
|
||||
|
||||
/* else, 1 and 2 socket systems use default ivt_cstates */
|
||||
}
|
||||
/*
|
||||
* sklh_idle_state_table_update(void)
|
||||
*
|
||||
* On SKL-H (model 0x5e) disable C8 and C9 if:
|
||||
* C10 is enabled and SGX disabled
|
||||
*/
|
||||
static void sklh_idle_state_table_update(void)
|
||||
{
|
||||
unsigned long long msr;
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
|
||||
|
||||
/* if PC10 disabled via cmdline intel_idle.max_cstate=7 or shallower */
|
||||
if (max_cstate <= 7)
|
||||
return;
|
||||
|
||||
/* if PC10 not present in CPUID.MWAIT.EDX */
|
||||
if ((mwait_substates & (0xF << 28)) == 0)
|
||||
return;
|
||||
|
||||
rdmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr);
|
||||
|
||||
/* PC10 is not enabled in PKG C-state limit */
|
||||
if ((msr & 0xF) != 8)
|
||||
return;
|
||||
|
||||
ecx = 0;
|
||||
cpuid(7, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
/* if SGX is present */
|
||||
if (ebx & (1 << 2)) {
|
||||
|
||||
rdmsrl(MSR_IA32_FEATURE_CONTROL, msr);
|
||||
|
||||
/* if SGX is enabled */
|
||||
if (msr & (1 << 18))
|
||||
return;
|
||||
}
|
||||
|
||||
skl_cstates[5].disabled = 1; /* C8-SKL */
|
||||
skl_cstates[6].disabled = 1; /* C9-SKL */
|
||||
}
|
||||
/*
|
||||
* intel_idle_state_table_update()
|
||||
*
|
||||
* Update the default state_table for this CPU-id
|
||||
*
|
||||
* Currently used to access tuned IVT multi-socket targets
|
||||
* Assumption: num_sockets == (max_package_num + 1)
|
||||
*/
|
||||
void intel_idle_state_table_update(void)
|
||||
|
||||
static void intel_idle_state_table_update(void)
|
||||
{
|
||||
/* IVT uses a different table for 1-2, 3-4, and > 4 sockets */
|
||||
if (boot_cpu_data.x86_model == 0x3e) { /* IVT */
|
||||
int cpu, package_num, num_sockets = 1;
|
||||
switch (boot_cpu_data.x86_model) {
|
||||
|
||||
for_each_online_cpu(cpu) {
|
||||
package_num = topology_physical_package_id(cpu);
|
||||
if (package_num + 1 > num_sockets) {
|
||||
num_sockets = package_num + 1;
|
||||
|
||||
if (num_sockets > 4) {
|
||||
cpuidle_state_table = ivt_cstates_8s;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (num_sockets > 2)
|
||||
cpuidle_state_table = ivt_cstates_4s;
|
||||
/* else, 1 and 2 socket systems use default ivt_cstates */
|
||||
case 0x3e: /* IVT */
|
||||
ivt_idle_state_table_update();
|
||||
break;
|
||||
case 0x5e: /* SKL-H */
|
||||
sklh_idle_state_table_update();
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1063,6 +1119,14 @@ static int __init intel_idle_cpuidle_driver_init(void)
|
|||
if (num_substates == 0)
|
||||
continue;
|
||||
|
||||
/* if state marked as disabled, skip it */
|
||||
if (cpuidle_state_table[cstate].disabled != 0) {
|
||||
pr_debug(PREFIX "state %s is disabled",
|
||||
cpuidle_state_table[cstate].name);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (((mwait_cstate + 1) > 2) &&
|
||||
!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
|
||||
mark_tsc_unstable("TSC halts in idle"
|
||||
|
|
|
|||
|
|
@ -456,7 +456,10 @@ static int ipoib_mcast_join_complete(int status,
|
|||
return status;
|
||||
}
|
||||
|
||||
static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast)
|
||||
/*
|
||||
* Caller must hold 'priv->lock'
|
||||
*/
|
||||
static int ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast)
|
||||
{
|
||||
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
||||
struct ib_sa_multicast *multicast;
|
||||
|
|
@ -466,6 +469,10 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast)
|
|||
ib_sa_comp_mask comp_mask;
|
||||
int ret = 0;
|
||||
|
||||
if (!priv->broadcast ||
|
||||
!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
|
||||
return -EINVAL;
|
||||
|
||||
ipoib_dbg_mcast(priv, "joining MGID %pI6\n", mcast->mcmember.mgid.raw);
|
||||
|
||||
rec.mgid = mcast->mcmember.mgid;
|
||||
|
|
@ -525,20 +532,23 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast)
|
|||
rec.join_state = 4;
|
||||
#endif
|
||||
}
|
||||
spin_unlock_irq(&priv->lock);
|
||||
|
||||
multicast = ib_sa_join_multicast(&ipoib_sa_client, priv->ca, priv->port,
|
||||
&rec, comp_mask, GFP_KERNEL,
|
||||
ipoib_mcast_join_complete, mcast);
|
||||
spin_lock_irq(&priv->lock);
|
||||
if (IS_ERR(multicast)) {
|
||||
ret = PTR_ERR(multicast);
|
||||
ipoib_warn(priv, "ib_sa_join_multicast failed, status %d\n", ret);
|
||||
spin_lock_irq(&priv->lock);
|
||||
/* Requeue this join task with a backoff delay */
|
||||
__ipoib_mcast_schedule_join_thread(priv, mcast, 1);
|
||||
clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
|
||||
spin_unlock_irq(&priv->lock);
|
||||
complete(&mcast->done);
|
||||
spin_lock_irq(&priv->lock);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ipoib_mcast_join_task(struct work_struct *work)
|
||||
|
|
@ -620,9 +630,10 @@ void ipoib_mcast_join_task(struct work_struct *work)
|
|||
/* Found the next unjoined group */
|
||||
init_completion(&mcast->done);
|
||||
set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
|
||||
spin_unlock_irq(&priv->lock);
|
||||
ipoib_mcast_join(dev, mcast);
|
||||
spin_lock_irq(&priv->lock);
|
||||
if (ipoib_mcast_join(dev, mcast)) {
|
||||
spin_unlock_irq(&priv->lock);
|
||||
return;
|
||||
}
|
||||
} else if (!delay_until ||
|
||||
time_before(mcast->delay_until, delay_until))
|
||||
delay_until = mcast->delay_until;
|
||||
|
|
@ -641,10 +652,9 @@ void ipoib_mcast_join_task(struct work_struct *work)
|
|||
if (mcast) {
|
||||
init_completion(&mcast->done);
|
||||
set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
|
||||
ipoib_mcast_join(dev, mcast);
|
||||
}
|
||||
spin_unlock_irq(&priv->lock);
|
||||
if (mcast)
|
||||
ipoib_mcast_join(dev, mcast);
|
||||
}
|
||||
|
||||
int ipoib_mcast_start_thread(struct net_device *dev)
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ isert_rdma_accept(struct isert_conn *isert_conn);
|
|||
struct rdma_cm_id *isert_setup_id(struct isert_np *isert_np);
|
||||
|
||||
static void isert_release_work(struct work_struct *work);
|
||||
static void isert_wait4flush(struct isert_conn *isert_conn);
|
||||
|
||||
static inline bool
|
||||
isert_prot_cmd(struct isert_conn *conn, struct se_cmd *cmd)
|
||||
|
|
@ -815,12 +816,31 @@ isert_put_conn(struct isert_conn *isert_conn)
|
|||
kref_put(&isert_conn->kref, isert_release_kref);
|
||||
}
|
||||
|
||||
static void
|
||||
isert_handle_unbound_conn(struct isert_conn *isert_conn)
|
||||
{
|
||||
struct isert_np *isert_np = isert_conn->cm_id->context;
|
||||
|
||||
mutex_lock(&isert_np->mutex);
|
||||
if (!list_empty(&isert_conn->node)) {
|
||||
/*
|
||||
* This means iscsi doesn't know this connection
|
||||
* so schedule a cleanup ourselves
|
||||
*/
|
||||
list_del_init(&isert_conn->node);
|
||||
isert_put_conn(isert_conn);
|
||||
complete(&isert_conn->wait);
|
||||
queue_work(isert_release_wq, &isert_conn->release_work);
|
||||
}
|
||||
mutex_unlock(&isert_np->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* isert_conn_terminate() - Initiate connection termination
|
||||
* @isert_conn: isert connection struct
|
||||
*
|
||||
* Notes:
|
||||
* In case the connection state is FULL_FEATURE, move state
|
||||
* In case the connection state is BOUND, move state
|
||||
* to TEMINATING and start teardown sequence (rdma_disconnect).
|
||||
* In case the connection state is UP, complete flush as well.
|
||||
*
|
||||
|
|
@ -832,23 +852,19 @@ isert_conn_terminate(struct isert_conn *isert_conn)
|
|||
{
|
||||
int err;
|
||||
|
||||
switch (isert_conn->state) {
|
||||
case ISER_CONN_TERMINATING:
|
||||
break;
|
||||
case ISER_CONN_UP:
|
||||
case ISER_CONN_FULL_FEATURE: /* FALLTHRU */
|
||||
isert_info("Terminating conn %p state %d\n",
|
||||
isert_conn, isert_conn->state);
|
||||
isert_conn->state = ISER_CONN_TERMINATING;
|
||||
err = rdma_disconnect(isert_conn->cm_id);
|
||||
if (err)
|
||||
isert_warn("Failed rdma_disconnect isert_conn %p\n",
|
||||
isert_conn);
|
||||
break;
|
||||
default:
|
||||
isert_warn("conn %p teminating in state %d\n",
|
||||
isert_conn, isert_conn->state);
|
||||
}
|
||||
if (isert_conn->state >= ISER_CONN_TERMINATING)
|
||||
return;
|
||||
|
||||
isert_info("Terminating conn %p state %d\n",
|
||||
isert_conn, isert_conn->state);
|
||||
isert_conn->state = ISER_CONN_TERMINATING;
|
||||
err = rdma_disconnect(isert_conn->cm_id);
|
||||
if (err)
|
||||
isert_warn("Failed rdma_disconnect isert_conn %p\n",
|
||||
isert_conn);
|
||||
|
||||
isert_info("conn %p completing wait\n", isert_conn);
|
||||
complete(&isert_conn->wait);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -882,35 +898,27 @@ static int
|
|||
isert_disconnected_handler(struct rdma_cm_id *cma_id,
|
||||
enum rdma_cm_event_type event)
|
||||
{
|
||||
struct isert_np *isert_np = cma_id->context;
|
||||
struct isert_conn *isert_conn;
|
||||
bool terminating = false;
|
||||
|
||||
if (isert_np->cm_id == cma_id)
|
||||
return isert_np_cma_handler(cma_id->context, event);
|
||||
|
||||
isert_conn = cma_id->qp->qp_context;
|
||||
struct isert_conn *isert_conn = cma_id->qp->qp_context;
|
||||
|
||||
mutex_lock(&isert_conn->mutex);
|
||||
terminating = (isert_conn->state == ISER_CONN_TERMINATING);
|
||||
isert_conn_terminate(isert_conn);
|
||||
switch (isert_conn->state) {
|
||||
case ISER_CONN_TERMINATING:
|
||||
break;
|
||||
case ISER_CONN_UP:
|
||||
isert_conn_terminate(isert_conn);
|
||||
isert_wait4flush(isert_conn);
|
||||
isert_handle_unbound_conn(isert_conn);
|
||||
break;
|
||||
case ISER_CONN_BOUND:
|
||||
case ISER_CONN_FULL_FEATURE: /* FALLTHRU */
|
||||
iscsit_cause_connection_reinstatement(isert_conn->conn, 0);
|
||||
break;
|
||||
default:
|
||||
isert_warn("conn %p teminating in state %d\n",
|
||||
isert_conn, isert_conn->state);
|
||||
}
|
||||
mutex_unlock(&isert_conn->mutex);
|
||||
|
||||
isert_info("conn %p completing wait\n", isert_conn);
|
||||
complete(&isert_conn->wait);
|
||||
|
||||
if (terminating)
|
||||
goto out;
|
||||
|
||||
mutex_lock(&isert_np->mutex);
|
||||
if (!list_empty(&isert_conn->node)) {
|
||||
list_del_init(&isert_conn->node);
|
||||
isert_put_conn(isert_conn);
|
||||
queue_work(isert_release_wq, &isert_conn->release_work);
|
||||
}
|
||||
mutex_unlock(&isert_np->mutex);
|
||||
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -929,12 +937,16 @@ isert_connect_error(struct rdma_cm_id *cma_id)
|
|||
static int
|
||||
isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
|
||||
{
|
||||
struct isert_np *isert_np = cma_id->context;
|
||||
int ret = 0;
|
||||
|
||||
isert_info("%s (%d): status %d id %p np %p\n",
|
||||
rdma_event_msg(event->event), event->event,
|
||||
event->status, cma_id, cma_id->context);
|
||||
|
||||
if (isert_np->cm_id == cma_id)
|
||||
return isert_np_cma_handler(cma_id->context, event->event);
|
||||
|
||||
switch (event->event) {
|
||||
case RDMA_CM_EVENT_CONNECT_REQUEST:
|
||||
ret = isert_connect_request(cma_id, event);
|
||||
|
|
@ -980,13 +992,10 @@ isert_post_recvm(struct isert_conn *isert_conn, u32 count)
|
|||
rx_wr--;
|
||||
rx_wr->next = NULL; /* mark end of work requests list */
|
||||
|
||||
isert_conn->post_recv_buf_count += count;
|
||||
ret = ib_post_recv(isert_conn->qp, isert_conn->rx_wr,
|
||||
&rx_wr_failed);
|
||||
if (ret) {
|
||||
if (ret)
|
||||
isert_err("ib_post_recv() failed with ret: %d\n", ret);
|
||||
isert_conn->post_recv_buf_count -= count;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1002,12 +1011,9 @@ isert_post_recv(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc)
|
|||
rx_wr.num_sge = 1;
|
||||
rx_wr.next = NULL;
|
||||
|
||||
isert_conn->post_recv_buf_count++;
|
||||
ret = ib_post_recv(isert_conn->qp, &rx_wr, &rx_wr_failed);
|
||||
if (ret) {
|
||||
if (ret)
|
||||
isert_err("ib_post_recv() failed with ret: %d\n", ret);
|
||||
isert_conn->post_recv_buf_count--;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1120,12 +1126,9 @@ isert_rdma_post_recvl(struct isert_conn *isert_conn)
|
|||
rx_wr.sg_list = &sge;
|
||||
rx_wr.num_sge = 1;
|
||||
|
||||
isert_conn->post_recv_buf_count++;
|
||||
ret = ib_post_recv(isert_conn->qp, &rx_wr, &rx_wr_fail);
|
||||
if (ret) {
|
||||
if (ret)
|
||||
isert_err("ib_post_recv() failed: %d\n", ret);
|
||||
isert_conn->post_recv_buf_count--;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1620,7 +1623,6 @@ isert_rcv_completion(struct iser_rx_desc *desc,
|
|||
ib_dma_sync_single_for_device(ib_dev, rx_dma, rx_buflen,
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
isert_conn->post_recv_buf_count--;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -2035,7 +2037,8 @@ is_isert_tx_desc(struct isert_conn *isert_conn, void *wr_id)
|
|||
void *start = isert_conn->rx_descs;
|
||||
int len = ISERT_QP_MAX_RECV_DTOS * sizeof(*isert_conn->rx_descs);
|
||||
|
||||
if (wr_id >= start && wr_id < start + len)
|
||||
if ((wr_id >= start && wr_id < start + len) ||
|
||||
(wr_id == isert_conn->login_req_buf))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
|
@ -2059,10 +2062,6 @@ isert_cq_comp_err(struct isert_conn *isert_conn, struct ib_wc *wc)
|
|||
isert_unmap_tx_desc(desc, ib_dev);
|
||||
else
|
||||
isert_completion_put(desc, isert_cmd, ib_dev, true);
|
||||
} else {
|
||||
isert_conn->post_recv_buf_count--;
|
||||
if (!isert_conn->post_recv_buf_count)
|
||||
iscsit_cause_connection_reinstatement(isert_conn->conn, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3193,6 +3192,7 @@ isert_accept_np(struct iscsi_np *np, struct iscsi_conn *conn)
|
|||
|
||||
conn->context = isert_conn;
|
||||
isert_conn->conn = conn;
|
||||
isert_conn->state = ISER_CONN_BOUND;
|
||||
|
||||
isert_set_conn_info(np, conn, isert_conn);
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ enum iser_ib_op_code {
|
|||
enum iser_conn_state {
|
||||
ISER_CONN_INIT,
|
||||
ISER_CONN_UP,
|
||||
ISER_CONN_BOUND,
|
||||
ISER_CONN_FULL_FEATURE,
|
||||
ISER_CONN_TERMINATING,
|
||||
ISER_CONN_DOWN,
|
||||
|
|
@ -144,7 +145,6 @@ struct isert_device;
|
|||
|
||||
struct isert_conn {
|
||||
enum iser_conn_state state;
|
||||
int post_recv_buf_count;
|
||||
u32 responder_resources;
|
||||
u32 initiator_depth;
|
||||
bool pi_support;
|
||||
|
|
|
|||
|
|
@ -1737,47 +1737,6 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch,
|
|||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* srpt_rx_mgmt_fn_tag() - Process a task management function by tag.
|
||||
* @ch: RDMA channel of the task management request.
|
||||
* @fn: Task management function to perform.
|
||||
* @req_tag: Tag of the SRP task management request.
|
||||
* @mgmt_ioctx: I/O context of the task management request.
|
||||
*
|
||||
* Returns zero if the target core will process the task management
|
||||
* request asynchronously.
|
||||
*
|
||||
* Note: It is assumed that the initiator serializes tag-based task management
|
||||
* requests.
|
||||
*/
|
||||
static int srpt_rx_mgmt_fn_tag(struct srpt_send_ioctx *ioctx, u64 tag)
|
||||
{
|
||||
struct srpt_device *sdev;
|
||||
struct srpt_rdma_ch *ch;
|
||||
struct srpt_send_ioctx *target;
|
||||
int ret, i;
|
||||
|
||||
ret = -EINVAL;
|
||||
ch = ioctx->ch;
|
||||
BUG_ON(!ch);
|
||||
BUG_ON(!ch->sport);
|
||||
sdev = ch->sport->sdev;
|
||||
BUG_ON(!sdev);
|
||||
spin_lock_irq(&sdev->spinlock);
|
||||
for (i = 0; i < ch->rq_size; ++i) {
|
||||
target = ch->ioctx_ring[i];
|
||||
if (target->cmd.se_lun == ioctx->cmd.se_lun &&
|
||||
target->cmd.tag == tag &&
|
||||
srpt_get_cmd_state(target) != SRPT_STATE_DONE) {
|
||||
ret = 0;
|
||||
/* now let the target core abort &target->cmd; */
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_irq(&sdev->spinlock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int srp_tmr_to_tcm(int fn)
|
||||
{
|
||||
switch (fn) {
|
||||
|
|
@ -1812,7 +1771,6 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
|
|||
struct se_cmd *cmd;
|
||||
struct se_session *sess = ch->sess;
|
||||
uint64_t unpacked_lun;
|
||||
uint32_t tag = 0;
|
||||
int tcm_tmr;
|
||||
int rc;
|
||||
|
||||
|
|
@ -1828,25 +1786,10 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
|
|||
srpt_set_cmd_state(send_ioctx, SRPT_STATE_MGMT);
|
||||
send_ioctx->cmd.tag = srp_tsk->tag;
|
||||
tcm_tmr = srp_tmr_to_tcm(srp_tsk->tsk_mgmt_func);
|
||||
if (tcm_tmr < 0) {
|
||||
send_ioctx->cmd.se_tmr_req->response =
|
||||
TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED;
|
||||
goto fail;
|
||||
}
|
||||
unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_tsk->lun,
|
||||
sizeof(srp_tsk->lun));
|
||||
|
||||
if (srp_tsk->tsk_mgmt_func == SRP_TSK_ABORT_TASK) {
|
||||
rc = srpt_rx_mgmt_fn_tag(send_ioctx, srp_tsk->task_tag);
|
||||
if (rc < 0) {
|
||||
send_ioctx->cmd.se_tmr_req->response =
|
||||
TMR_TASK_DOES_NOT_EXIST;
|
||||
goto fail;
|
||||
}
|
||||
tag = srp_tsk->task_tag;
|
||||
}
|
||||
rc = target_submit_tmr(&send_ioctx->cmd, sess, NULL, unpacked_lun,
|
||||
srp_tsk, tcm_tmr, GFP_KERNEL, tag,
|
||||
srp_tsk, tcm_tmr, GFP_KERNEL, srp_tsk->task_tag,
|
||||
TARGET_SCF_ACK_KREF);
|
||||
if (rc != 0) {
|
||||
send_ioctx->cmd.se_tmr_req->response = TMR_FUNCTION_REJECTED;
|
||||
|
|
|
|||
|
|
@ -817,26 +817,49 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d
|
|||
|
||||
ar2->udev = udev;
|
||||
|
||||
/* Sanity check, first interface must have an endpoint */
|
||||
if (alt->desc.bNumEndpoints < 1 || !alt->endpoint) {
|
||||
dev_err(&interface->dev,
|
||||
"%s(): interface 0 must have an endpoint\n", __func__);
|
||||
r = -ENODEV;
|
||||
goto fail1;
|
||||
}
|
||||
ar2->intf[0] = interface;
|
||||
ar2->ep[0] = &alt->endpoint[0].desc;
|
||||
|
||||
/* Sanity check, the device must have two interfaces */
|
||||
ar2->intf[1] = usb_ifnum_to_if(udev, 1);
|
||||
if ((udev->actconfig->desc.bNumInterfaces < 2) || !ar2->intf[1]) {
|
||||
dev_err(&interface->dev, "%s(): need 2 interfaces, found %d\n",
|
||||
__func__, udev->actconfig->desc.bNumInterfaces);
|
||||
r = -ENODEV;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
r = usb_driver_claim_interface(&ati_remote2_driver, ar2->intf[1], ar2);
|
||||
if (r)
|
||||
goto fail1;
|
||||
|
||||
/* Sanity check, second interface must have an endpoint */
|
||||
alt = ar2->intf[1]->cur_altsetting;
|
||||
if (alt->desc.bNumEndpoints < 1 || !alt->endpoint) {
|
||||
dev_err(&interface->dev,
|
||||
"%s(): interface 1 must have an endpoint\n", __func__);
|
||||
r = -ENODEV;
|
||||
goto fail2;
|
||||
}
|
||||
ar2->ep[1] = &alt->endpoint[0].desc;
|
||||
|
||||
r = ati_remote2_urb_init(ar2);
|
||||
if (r)
|
||||
goto fail2;
|
||||
goto fail3;
|
||||
|
||||
ar2->channel_mask = channel_mask;
|
||||
ar2->mode_mask = mode_mask;
|
||||
|
||||
r = ati_remote2_setup(ar2, ar2->channel_mask);
|
||||
if (r)
|
||||
goto fail2;
|
||||
goto fail3;
|
||||
|
||||
usb_make_path(udev, ar2->phys, sizeof(ar2->phys));
|
||||
strlcat(ar2->phys, "/input0", sizeof(ar2->phys));
|
||||
|
|
@ -845,11 +868,11 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d
|
|||
|
||||
r = sysfs_create_group(&udev->dev.kobj, &ati_remote2_attr_group);
|
||||
if (r)
|
||||
goto fail2;
|
||||
goto fail3;
|
||||
|
||||
r = ati_remote2_input_init(ar2);
|
||||
if (r)
|
||||
goto fail3;
|
||||
goto fail4;
|
||||
|
||||
usb_set_intfdata(interface, ar2);
|
||||
|
||||
|
|
@ -857,10 +880,11 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d
|
|||
|
||||
return 0;
|
||||
|
||||
fail3:
|
||||
fail4:
|
||||
sysfs_remove_group(&udev->dev.kobj, &ati_remote2_attr_group);
|
||||
fail2:
|
||||
fail3:
|
||||
ati_remote2_urb_cleanup(ar2);
|
||||
fail2:
|
||||
usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]);
|
||||
fail1:
|
||||
kfree(ar2);
|
||||
|
|
|
|||
|
|
@ -1663,6 +1663,8 @@ static int ims_pcu_parse_cdc_data(struct usb_interface *intf, struct ims_pcu *pc
|
|||
|
||||
pcu->ctrl_intf = usb_ifnum_to_if(pcu->udev,
|
||||
union_desc->bMasterInterface0);
|
||||
if (!pcu->ctrl_intf)
|
||||
return -EINVAL;
|
||||
|
||||
alt = pcu->ctrl_intf->cur_altsetting;
|
||||
pcu->ep_ctrl = &alt->endpoint[0].desc;
|
||||
|
|
@ -1670,6 +1672,8 @@ static int ims_pcu_parse_cdc_data(struct usb_interface *intf, struct ims_pcu *pc
|
|||
|
||||
pcu->data_intf = usb_ifnum_to_if(pcu->udev,
|
||||
union_desc->bSlaveInterface0);
|
||||
if (!pcu->data_intf)
|
||||
return -EINVAL;
|
||||
|
||||
alt = pcu->data_intf->cur_altsetting;
|
||||
if (alt->desc.bNumEndpoints != 2) {
|
||||
|
|
|
|||
|
|
@ -307,6 +307,9 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
|
|||
int error = -ENOMEM;
|
||||
|
||||
interface = intf->cur_altsetting;
|
||||
if (interface->desc.bNumEndpoints < 1)
|
||||
return -EINVAL;
|
||||
|
||||
endpoint = &interface->endpoint[0].desc;
|
||||
if (!usb_endpoint_is_int_in(endpoint))
|
||||
return -EIO;
|
||||
|
|
|
|||
|
|
@ -862,8 +862,9 @@ static void synaptics_report_ext_buttons(struct psmouse *psmouse,
|
|||
if (!SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap))
|
||||
return;
|
||||
|
||||
/* Bug in FW 8.1, buttons are reported only when ExtBit is 1 */
|
||||
if (SYN_ID_FULL(priv->identity) == 0x801 &&
|
||||
/* Bug in FW 8.1 & 8.2, buttons are reported only when ExtBit is 1 */
|
||||
if ((SYN_ID_FULL(priv->identity) == 0x801 ||
|
||||
SYN_ID_FULL(priv->identity) == 0x802) &&
|
||||
!((psmouse->packet[0] ^ psmouse->packet[3]) & 0x02))
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -1015,8 +1015,12 @@ int bch_cached_dev_attach(struct cached_dev *dc, struct cache_set *c)
|
|||
*/
|
||||
atomic_set(&dc->count, 1);
|
||||
|
||||
if (bch_cached_dev_writeback_start(dc))
|
||||
/* Block writeback thread, but spawn it */
|
||||
down_write(&dc->writeback_lock);
|
||||
if (bch_cached_dev_writeback_start(dc)) {
|
||||
up_write(&dc->writeback_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (BDEV_STATE(&dc->sb) == BDEV_STATE_DIRTY) {
|
||||
bch_sectors_dirty_init(dc);
|
||||
|
|
@ -1028,6 +1032,9 @@ int bch_cached_dev_attach(struct cached_dev *dc, struct cache_set *c)
|
|||
bch_cached_dev_run(dc);
|
||||
bcache_device_link(&dc->disk, c, "bdev");
|
||||
|
||||
/* Allow the writeback thread to proceed */
|
||||
up_write(&dc->writeback_lock);
|
||||
|
||||
pr_info("Caching %s as %s on set %pU",
|
||||
bdevname(dc->bdev, buf), dc->disk.disk->disk_name,
|
||||
dc->disk.c->sb.set_uuid);
|
||||
|
|
@ -1366,6 +1373,9 @@ static void cache_set_flush(struct closure *cl)
|
|||
struct btree *b;
|
||||
unsigned i;
|
||||
|
||||
if (!c)
|
||||
closure_return(cl);
|
||||
|
||||
bch_cache_accounting_destroy(&c->accounting);
|
||||
|
||||
kobject_put(&c->internal);
|
||||
|
|
@ -1828,11 +1838,12 @@ static int cache_alloc(struct cache_sb *sb, struct cache *ca)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void register_cache(struct cache_sb *sb, struct page *sb_page,
|
||||
static int register_cache(struct cache_sb *sb, struct page *sb_page,
|
||||
struct block_device *bdev, struct cache *ca)
|
||||
{
|
||||
char name[BDEVNAME_SIZE];
|
||||
const char *err = "cannot allocate memory";
|
||||
const char *err = NULL;
|
||||
int ret = 0;
|
||||
|
||||
memcpy(&ca->sb, sb, sizeof(struct cache_sb));
|
||||
ca->bdev = bdev;
|
||||
|
|
@ -1847,27 +1858,35 @@ static void register_cache(struct cache_sb *sb, struct page *sb_page,
|
|||
if (blk_queue_discard(bdev_get_queue(ca->bdev)))
|
||||
ca->discard = CACHE_DISCARD(&ca->sb);
|
||||
|
||||
if (cache_alloc(sb, ca) != 0)
|
||||
ret = cache_alloc(sb, ca);
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
|
||||
err = "error creating kobject";
|
||||
if (kobject_add(&ca->kobj, &part_to_dev(bdev->bd_part)->kobj, "bcache"))
|
||||
goto err;
|
||||
if (kobject_add(&ca->kobj, &part_to_dev(bdev->bd_part)->kobj, "bcache")) {
|
||||
err = "error calling kobject_add";
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mutex_lock(&bch_register_lock);
|
||||
err = register_cache_set(ca);
|
||||
mutex_unlock(&bch_register_lock);
|
||||
|
||||
if (err)
|
||||
goto err;
|
||||
if (err) {
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pr_info("registered cache device %s", bdevname(bdev, name));
|
||||
|
||||
out:
|
||||
kobject_put(&ca->kobj);
|
||||
return;
|
||||
|
||||
err:
|
||||
pr_notice("error opening %s: %s", bdevname(bdev, name), err);
|
||||
goto out;
|
||||
if (err)
|
||||
pr_notice("error opening %s: %s", bdevname(bdev, name), err);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Global interfaces/init */
|
||||
|
|
@ -1965,7 +1984,8 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
|
|||
if (!ca)
|
||||
goto err_close;
|
||||
|
||||
register_cache(sb, sb_page, bdev, ca);
|
||||
if (register_cache(sb, sb_page, bdev, ca) != 0)
|
||||
goto err_close;
|
||||
}
|
||||
out:
|
||||
if (sb_page)
|
||||
|
|
|
|||
|
|
@ -867,19 +867,40 @@ static int blocks_are_unmapped_or_clean(struct dm_cache_metadata *cmd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define WRITE_LOCK(cmd) \
|
||||
if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) \
|
||||
#define WRITE_LOCK(cmd) \
|
||||
down_write(&cmd->root_lock); \
|
||||
if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) { \
|
||||
up_write(&cmd->root_lock); \
|
||||
return -EINVAL; \
|
||||
down_write(&cmd->root_lock)
|
||||
}
|
||||
|
||||
#define WRITE_LOCK_VOID(cmd) \
|
||||
if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) \
|
||||
down_write(&cmd->root_lock); \
|
||||
if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) { \
|
||||
up_write(&cmd->root_lock); \
|
||||
return; \
|
||||
down_write(&cmd->root_lock)
|
||||
}
|
||||
|
||||
#define WRITE_UNLOCK(cmd) \
|
||||
up_write(&cmd->root_lock)
|
||||
|
||||
#define READ_LOCK(cmd) \
|
||||
down_read(&cmd->root_lock); \
|
||||
if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) { \
|
||||
up_read(&cmd->root_lock); \
|
||||
return -EINVAL; \
|
||||
}
|
||||
|
||||
#define READ_LOCK_VOID(cmd) \
|
||||
down_read(&cmd->root_lock); \
|
||||
if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) { \
|
||||
up_read(&cmd->root_lock); \
|
||||
return; \
|
||||
}
|
||||
|
||||
#define READ_UNLOCK(cmd) \
|
||||
up_read(&cmd->root_lock)
|
||||
|
||||
int dm_cache_resize(struct dm_cache_metadata *cmd, dm_cblock_t new_cache_size)
|
||||
{
|
||||
int r;
|
||||
|
|
@ -1015,22 +1036,20 @@ int dm_cache_load_discards(struct dm_cache_metadata *cmd,
|
|||
{
|
||||
int r;
|
||||
|
||||
down_read(&cmd->root_lock);
|
||||
READ_LOCK(cmd);
|
||||
r = __load_discards(cmd, fn, context);
|
||||
up_read(&cmd->root_lock);
|
||||
READ_UNLOCK(cmd);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
dm_cblock_t dm_cache_size(struct dm_cache_metadata *cmd)
|
||||
int dm_cache_size(struct dm_cache_metadata *cmd, dm_cblock_t *result)
|
||||
{
|
||||
dm_cblock_t r;
|
||||
READ_LOCK(cmd);
|
||||
*result = cmd->cache_blocks;
|
||||
READ_UNLOCK(cmd);
|
||||
|
||||
down_read(&cmd->root_lock);
|
||||
r = cmd->cache_blocks;
|
||||
up_read(&cmd->root_lock);
|
||||
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __remove(struct dm_cache_metadata *cmd, dm_cblock_t cblock)
|
||||
|
|
@ -1188,9 +1207,9 @@ int dm_cache_load_mappings(struct dm_cache_metadata *cmd,
|
|||
{
|
||||
int r;
|
||||
|
||||
down_read(&cmd->root_lock);
|
||||
READ_LOCK(cmd);
|
||||
r = __load_mappings(cmd, policy, fn, context);
|
||||
up_read(&cmd->root_lock);
|
||||
READ_UNLOCK(cmd);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
@ -1215,18 +1234,18 @@ static int __dump_mappings(struct dm_cache_metadata *cmd)
|
|||
|
||||
void dm_cache_dump(struct dm_cache_metadata *cmd)
|
||||
{
|
||||
down_read(&cmd->root_lock);
|
||||
READ_LOCK_VOID(cmd);
|
||||
__dump_mappings(cmd);
|
||||
up_read(&cmd->root_lock);
|
||||
READ_UNLOCK(cmd);
|
||||
}
|
||||
|
||||
int dm_cache_changed_this_transaction(struct dm_cache_metadata *cmd)
|
||||
{
|
||||
int r;
|
||||
|
||||
down_read(&cmd->root_lock);
|
||||
READ_LOCK(cmd);
|
||||
r = cmd->changed;
|
||||
up_read(&cmd->root_lock);
|
||||
READ_UNLOCK(cmd);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
@ -1276,9 +1295,9 @@ int dm_cache_set_dirty(struct dm_cache_metadata *cmd,
|
|||
void dm_cache_metadata_get_stats(struct dm_cache_metadata *cmd,
|
||||
struct dm_cache_statistics *stats)
|
||||
{
|
||||
down_read(&cmd->root_lock);
|
||||
READ_LOCK_VOID(cmd);
|
||||
*stats = cmd->stats;
|
||||
up_read(&cmd->root_lock);
|
||||
READ_UNLOCK(cmd);
|
||||
}
|
||||
|
||||
void dm_cache_metadata_set_stats(struct dm_cache_metadata *cmd,
|
||||
|
|
@ -1312,9 +1331,9 @@ int dm_cache_get_free_metadata_block_count(struct dm_cache_metadata *cmd,
|
|||
{
|
||||
int r = -EINVAL;
|
||||
|
||||
down_read(&cmd->root_lock);
|
||||
READ_LOCK(cmd);
|
||||
r = dm_sm_get_nr_free(cmd->metadata_sm, result);
|
||||
up_read(&cmd->root_lock);
|
||||
READ_UNLOCK(cmd);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
@ -1324,9 +1343,9 @@ int dm_cache_get_metadata_dev_size(struct dm_cache_metadata *cmd,
|
|||
{
|
||||
int r = -EINVAL;
|
||||
|
||||
down_read(&cmd->root_lock);
|
||||
READ_LOCK(cmd);
|
||||
r = dm_sm_get_nr_blocks(cmd->metadata_sm, result);
|
||||
up_read(&cmd->root_lock);
|
||||
READ_UNLOCK(cmd);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
@ -1417,7 +1436,13 @@ int dm_cache_write_hints(struct dm_cache_metadata *cmd, struct dm_cache_policy *
|
|||
|
||||
int dm_cache_metadata_all_clean(struct dm_cache_metadata *cmd, bool *result)
|
||||
{
|
||||
return blocks_are_unmapped_or_clean(cmd, 0, cmd->cache_blocks, result);
|
||||
int r;
|
||||
|
||||
READ_LOCK(cmd);
|
||||
r = blocks_are_unmapped_or_clean(cmd, 0, cmd->cache_blocks, result);
|
||||
READ_UNLOCK(cmd);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void dm_cache_metadata_set_read_only(struct dm_cache_metadata *cmd)
|
||||
|
|
@ -1440,10 +1465,7 @@ int dm_cache_metadata_set_needs_check(struct dm_cache_metadata *cmd)
|
|||
struct dm_block *sblock;
|
||||
struct cache_disk_superblock *disk_super;
|
||||
|
||||
/*
|
||||
* We ignore fail_io for this function.
|
||||
*/
|
||||
down_write(&cmd->root_lock);
|
||||
WRITE_LOCK(cmd);
|
||||
set_bit(NEEDS_CHECK, &cmd->flags);
|
||||
|
||||
r = superblock_lock(cmd, &sblock);
|
||||
|
|
@ -1458,19 +1480,17 @@ int dm_cache_metadata_set_needs_check(struct dm_cache_metadata *cmd)
|
|||
dm_bm_unlock(sblock);
|
||||
|
||||
out:
|
||||
up_write(&cmd->root_lock);
|
||||
WRITE_UNLOCK(cmd);
|
||||
return r;
|
||||
}
|
||||
|
||||
bool dm_cache_metadata_needs_check(struct dm_cache_metadata *cmd)
|
||||
int dm_cache_metadata_needs_check(struct dm_cache_metadata *cmd, bool *result)
|
||||
{
|
||||
bool needs_check;
|
||||
READ_LOCK(cmd);
|
||||
*result = !!test_bit(NEEDS_CHECK, &cmd->flags);
|
||||
READ_UNLOCK(cmd);
|
||||
|
||||
down_read(&cmd->root_lock);
|
||||
needs_check = !!test_bit(NEEDS_CHECK, &cmd->flags);
|
||||
up_read(&cmd->root_lock);
|
||||
|
||||
return needs_check;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dm_cache_metadata_abort(struct dm_cache_metadata *cmd)
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ void dm_cache_metadata_close(struct dm_cache_metadata *cmd);
|
|||
* origin blocks to map to.
|
||||
*/
|
||||
int dm_cache_resize(struct dm_cache_metadata *cmd, dm_cblock_t new_cache_size);
|
||||
dm_cblock_t dm_cache_size(struct dm_cache_metadata *cmd);
|
||||
int dm_cache_size(struct dm_cache_metadata *cmd, dm_cblock_t *result);
|
||||
|
||||
int dm_cache_discard_bitset_resize(struct dm_cache_metadata *cmd,
|
||||
sector_t discard_block_size,
|
||||
|
|
@ -137,7 +137,7 @@ int dm_cache_write_hints(struct dm_cache_metadata *cmd, struct dm_cache_policy *
|
|||
*/
|
||||
int dm_cache_metadata_all_clean(struct dm_cache_metadata *cmd, bool *result);
|
||||
|
||||
bool dm_cache_metadata_needs_check(struct dm_cache_metadata *cmd);
|
||||
int dm_cache_metadata_needs_check(struct dm_cache_metadata *cmd, bool *result);
|
||||
int dm_cache_metadata_set_needs_check(struct dm_cache_metadata *cmd);
|
||||
void dm_cache_metadata_set_read_only(struct dm_cache_metadata *cmd);
|
||||
void dm_cache_metadata_set_read_write(struct dm_cache_metadata *cmd);
|
||||
|
|
|
|||
|
|
@ -984,9 +984,14 @@ static void notify_mode_switch(struct cache *cache, enum cache_metadata_mode mod
|
|||
|
||||
static void set_cache_mode(struct cache *cache, enum cache_metadata_mode new_mode)
|
||||
{
|
||||
bool needs_check = dm_cache_metadata_needs_check(cache->cmd);
|
||||
bool needs_check;
|
||||
enum cache_metadata_mode old_mode = get_cache_mode(cache);
|
||||
|
||||
if (dm_cache_metadata_needs_check(cache->cmd, &needs_check)) {
|
||||
DMERR("unable to read needs_check flag, setting failure mode");
|
||||
new_mode = CM_FAIL;
|
||||
}
|
||||
|
||||
if (new_mode == CM_WRITE && needs_check) {
|
||||
DMERR("%s: unable to switch cache to write mode until repaired.",
|
||||
cache_device_name(cache));
|
||||
|
|
@ -3510,6 +3515,7 @@ static void cache_status(struct dm_target *ti, status_type_t type,
|
|||
char buf[BDEVNAME_SIZE];
|
||||
struct cache *cache = ti->private;
|
||||
dm_cblock_t residency;
|
||||
bool needs_check;
|
||||
|
||||
switch (type) {
|
||||
case STATUSTYPE_INFO:
|
||||
|
|
@ -3583,7 +3589,9 @@ static void cache_status(struct dm_target *ti, status_type_t type,
|
|||
else
|
||||
DMEMIT("rw ");
|
||||
|
||||
if (dm_cache_metadata_needs_check(cache->cmd))
|
||||
r = dm_cache_metadata_needs_check(cache->cmd, &needs_check);
|
||||
|
||||
if (r || needs_check)
|
||||
DMEMIT("needs_check ");
|
||||
else
|
||||
DMEMIT("- ");
|
||||
|
|
|
|||
|
|
@ -1105,6 +1105,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
|
|||
int i;
|
||||
int r = -EINVAL;
|
||||
char *origin_path, *cow_path;
|
||||
dev_t origin_dev, cow_dev;
|
||||
unsigned args_used, num_flush_bios = 1;
|
||||
fmode_t origin_mode = FMODE_READ;
|
||||
|
||||
|
|
@ -1135,11 +1136,19 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
|
|||
ti->error = "Cannot get origin device";
|
||||
goto bad_origin;
|
||||
}
|
||||
origin_dev = s->origin->bdev->bd_dev;
|
||||
|
||||
cow_path = argv[0];
|
||||
argv++;
|
||||
argc--;
|
||||
|
||||
cow_dev = dm_get_dev_t(cow_path);
|
||||
if (cow_dev && cow_dev == origin_dev) {
|
||||
ti->error = "COW device cannot be the same as origin device";
|
||||
r = -EINVAL;
|
||||
goto bad_cow;
|
||||
}
|
||||
|
||||
r = dm_get_device(ti, cow_path, dm_table_get_mode(ti->table), &s->cow);
|
||||
if (r) {
|
||||
ti->error = "Cannot get COW device";
|
||||
|
|
|
|||
|
|
@ -364,6 +364,26 @@ static int upgrade_mode(struct dm_dev_internal *dd, fmode_t new_mode,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the path to a device
|
||||
*/
|
||||
dev_t dm_get_dev_t(const char *path)
|
||||
{
|
||||
dev_t uninitialized_var(dev);
|
||||
struct block_device *bdev;
|
||||
|
||||
bdev = lookup_bdev(path);
|
||||
if (IS_ERR(bdev))
|
||||
dev = name_to_dev_t(path);
|
||||
else {
|
||||
dev = bdev->bd_dev;
|
||||
bdput(bdev);
|
||||
}
|
||||
|
||||
return dev;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dm_get_dev_t);
|
||||
|
||||
/*
|
||||
* Add a device to the list, or just increment the usage count if
|
||||
* it's already present.
|
||||
|
|
@ -372,23 +392,15 @@ int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode,
|
|||
struct dm_dev **result)
|
||||
{
|
||||
int r;
|
||||
dev_t uninitialized_var(dev);
|
||||
dev_t dev;
|
||||
struct dm_dev_internal *dd;
|
||||
struct dm_table *t = ti->table;
|
||||
struct block_device *bdev;
|
||||
|
||||
BUG_ON(!t);
|
||||
|
||||
/* convert the path to a device */
|
||||
bdev = lookup_bdev(path);
|
||||
if (IS_ERR(bdev)) {
|
||||
dev = name_to_dev_t(path);
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
} else {
|
||||
dev = bdev->bd_dev;
|
||||
bdput(bdev);
|
||||
}
|
||||
dev = dm_get_dev_t(path);
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
dd = find_device(&t->devices, dev);
|
||||
if (!dd) {
|
||||
|
|
|
|||
|
|
@ -1943,5 +1943,8 @@ bool dm_pool_metadata_needs_check(struct dm_pool_metadata *pmd)
|
|||
|
||||
void dm_pool_issue_prefetches(struct dm_pool_metadata *pmd)
|
||||
{
|
||||
dm_tm_issue_prefetches(pmd->tm);
|
||||
down_read(&pmd->root_lock);
|
||||
if (!pmd->fail_io)
|
||||
dm_tm_issue_prefetches(pmd->tm);
|
||||
up_read(&pmd->root_lock);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1109,12 +1109,8 @@ static void rq_completed(struct mapped_device *md, int rw, bool run_queue)
|
|||
* back into ->request_fn() could deadlock attempting to grab the
|
||||
* queue lock again.
|
||||
*/
|
||||
if (run_queue) {
|
||||
if (md->queue->mq_ops)
|
||||
blk_mq_run_hw_queues(md->queue, true);
|
||||
else
|
||||
blk_run_queue_async(md->queue);
|
||||
}
|
||||
if (!md->queue->mq_ops && run_queue)
|
||||
blk_run_queue_async(md->queue);
|
||||
|
||||
/*
|
||||
* dm_put() must be at the end of this function. See the comment above
|
||||
|
|
@ -1214,9 +1210,9 @@ static void dm_requeue_original_request(struct mapped_device *md,
|
|||
{
|
||||
int rw = rq_data_dir(rq);
|
||||
|
||||
rq_end_stats(md, rq);
|
||||
dm_unprep_request(rq);
|
||||
|
||||
rq_end_stats(md, rq);
|
||||
if (!rq->q->mq_ops)
|
||||
old_requeue_request(rq);
|
||||
else {
|
||||
|
|
@ -1336,7 +1332,10 @@ static void dm_complete_request(struct request *rq, int error)
|
|||
struct dm_rq_target_io *tio = tio_from_request(rq);
|
||||
|
||||
tio->error = error;
|
||||
blk_complete_request(rq);
|
||||
if (!rq->q->mq_ops)
|
||||
blk_complete_request(rq);
|
||||
else
|
||||
blk_mq_complete_request(rq, error);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -129,7 +129,9 @@ static void multipath_make_request(struct mddev *mddev, struct bio * bio)
|
|||
}
|
||||
multipath = conf->multipaths + mp_bh->path;
|
||||
|
||||
mp_bh->bio = *bio;
|
||||
bio_init(&mp_bh->bio);
|
||||
__bio_clone_fast(&mp_bh->bio, bio);
|
||||
|
||||
mp_bh->bio.bi_iter.bi_sector += multipath->rdev->data_offset;
|
||||
mp_bh->bio.bi_bdev = multipath->rdev->bdev;
|
||||
mp_bh->bio.bi_rw |= REQ_FAILFAST_TRANSPORT;
|
||||
|
|
|
|||
|
|
@ -2274,6 +2274,7 @@ static void handle_write_finished(struct r1conf *conf, struct r1bio *r1_bio)
|
|||
if (fail) {
|
||||
spin_lock_irq(&conf->device_lock);
|
||||
list_add(&r1_bio->retry_list, &conf->bio_end_io_list);
|
||||
conf->nr_queued++;
|
||||
spin_unlock_irq(&conf->device_lock);
|
||||
md_wakeup_thread(conf->mddev->thread);
|
||||
} else {
|
||||
|
|
@ -2391,8 +2392,10 @@ static void raid1d(struct md_thread *thread)
|
|||
LIST_HEAD(tmp);
|
||||
spin_lock_irqsave(&conf->device_lock, flags);
|
||||
if (!test_bit(MD_CHANGE_PENDING, &mddev->flags)) {
|
||||
list_add(&tmp, &conf->bio_end_io_list);
|
||||
list_del_init(&conf->bio_end_io_list);
|
||||
while (!list_empty(&conf->bio_end_io_list)) {
|
||||
list_move(conf->bio_end_io_list.prev, &tmp);
|
||||
conf->nr_queued--;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&conf->device_lock, flags);
|
||||
while (!list_empty(&tmp)) {
|
||||
|
|
|
|||
|
|
@ -2664,6 +2664,7 @@ static void handle_write_completed(struct r10conf *conf, struct r10bio *r10_bio)
|
|||
if (fail) {
|
||||
spin_lock_irq(&conf->device_lock);
|
||||
list_add(&r10_bio->retry_list, &conf->bio_end_io_list);
|
||||
conf->nr_queued++;
|
||||
spin_unlock_irq(&conf->device_lock);
|
||||
md_wakeup_thread(conf->mddev->thread);
|
||||
} else {
|
||||
|
|
@ -2691,8 +2692,10 @@ static void raid10d(struct md_thread *thread)
|
|||
LIST_HEAD(tmp);
|
||||
spin_lock_irqsave(&conf->device_lock, flags);
|
||||
if (!test_bit(MD_CHANGE_PENDING, &mddev->flags)) {
|
||||
list_add(&tmp, &conf->bio_end_io_list);
|
||||
list_del_init(&conf->bio_end_io_list);
|
||||
while (!list_empty(&conf->bio_end_io_list)) {
|
||||
list_move(conf->bio_end_io_list.prev, &tmp);
|
||||
conf->nr_queued--;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&conf->device_lock, flags);
|
||||
while (!list_empty(&tmp)) {
|
||||
|
|
|
|||
|
|
@ -340,8 +340,7 @@ static void release_inactive_stripe_list(struct r5conf *conf,
|
|||
int hash)
|
||||
{
|
||||
int size;
|
||||
unsigned long do_wakeup = 0;
|
||||
int i = 0;
|
||||
bool do_wakeup = false;
|
||||
unsigned long flags;
|
||||
|
||||
if (hash == NR_STRIPE_HASH_LOCKS) {
|
||||
|
|
@ -362,19 +361,15 @@ static void release_inactive_stripe_list(struct r5conf *conf,
|
|||
!list_empty(list))
|
||||
atomic_dec(&conf->empty_inactive_list_nr);
|
||||
list_splice_tail_init(list, conf->inactive_list + hash);
|
||||
do_wakeup |= 1 << hash;
|
||||
do_wakeup = true;
|
||||
spin_unlock_irqrestore(conf->hash_locks + hash, flags);
|
||||
}
|
||||
size--;
|
||||
hash--;
|
||||
}
|
||||
|
||||
for (i = 0; i < NR_STRIPE_HASH_LOCKS; i++) {
|
||||
if (do_wakeup & (1 << i))
|
||||
wake_up(&conf->wait_for_stripe[i]);
|
||||
}
|
||||
|
||||
if (do_wakeup) {
|
||||
wake_up(&conf->wait_for_stripe);
|
||||
if (atomic_read(&conf->active_stripes) == 0)
|
||||
wake_up(&conf->wait_for_quiescent);
|
||||
if (conf->retry_read_aligned)
|
||||
|
|
@ -687,15 +682,14 @@ raid5_get_active_stripe(struct r5conf *conf, sector_t sector,
|
|||
if (!sh) {
|
||||
set_bit(R5_INACTIVE_BLOCKED,
|
||||
&conf->cache_state);
|
||||
wait_event_exclusive_cmd(
|
||||
conf->wait_for_stripe[hash],
|
||||
wait_event_lock_irq(
|
||||
conf->wait_for_stripe,
|
||||
!list_empty(conf->inactive_list + hash) &&
|
||||
(atomic_read(&conf->active_stripes)
|
||||
< (conf->max_nr_stripes * 3 / 4)
|
||||
|| !test_bit(R5_INACTIVE_BLOCKED,
|
||||
&conf->cache_state)),
|
||||
spin_unlock_irq(conf->hash_locks + hash),
|
||||
spin_lock_irq(conf->hash_locks + hash));
|
||||
*(conf->hash_locks + hash));
|
||||
clear_bit(R5_INACTIVE_BLOCKED,
|
||||
&conf->cache_state);
|
||||
} else {
|
||||
|
|
@ -720,9 +714,6 @@ raid5_get_active_stripe(struct r5conf *conf, sector_t sector,
|
|||
}
|
||||
} while (sh == NULL);
|
||||
|
||||
if (!list_empty(conf->inactive_list + hash))
|
||||
wake_up(&conf->wait_for_stripe[hash]);
|
||||
|
||||
spin_unlock_irq(conf->hash_locks + hash);
|
||||
return sh;
|
||||
}
|
||||
|
|
@ -2091,6 +2082,14 @@ static int resize_chunks(struct r5conf *conf, int new_disks, int new_sectors)
|
|||
unsigned long cpu;
|
||||
int err = 0;
|
||||
|
||||
/*
|
||||
* Never shrink. And mddev_suspend() could deadlock if this is called
|
||||
* from raid5d. In that case, scribble_disks and scribble_sectors
|
||||
* should equal to new_disks and new_sectors
|
||||
*/
|
||||
if (conf->scribble_disks >= new_disks &&
|
||||
conf->scribble_sectors >= new_sectors)
|
||||
return 0;
|
||||
mddev_suspend(conf->mddev);
|
||||
get_online_cpus();
|
||||
for_each_present_cpu(cpu) {
|
||||
|
|
@ -2112,6 +2111,10 @@ static int resize_chunks(struct r5conf *conf, int new_disks, int new_sectors)
|
|||
}
|
||||
put_online_cpus();
|
||||
mddev_resume(conf->mddev);
|
||||
if (!err) {
|
||||
conf->scribble_disks = new_disks;
|
||||
conf->scribble_sectors = new_sectors;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -2192,7 +2195,7 @@ static int resize_stripes(struct r5conf *conf, int newsize)
|
|||
cnt = 0;
|
||||
list_for_each_entry(nsh, &newstripes, lru) {
|
||||
lock_device_hash_lock(conf, hash);
|
||||
wait_event_exclusive_cmd(conf->wait_for_stripe[hash],
|
||||
wait_event_cmd(conf->wait_for_stripe,
|
||||
!list_empty(conf->inactive_list + hash),
|
||||
unlock_device_hash_lock(conf, hash),
|
||||
lock_device_hash_lock(conf, hash));
|
||||
|
|
@ -4238,7 +4241,6 @@ static void break_stripe_batch_list(struct stripe_head *head_sh,
|
|||
WARN_ON_ONCE(sh->state & ((1 << STRIPE_ACTIVE) |
|
||||
(1 << STRIPE_SYNCING) |
|
||||
(1 << STRIPE_REPLACED) |
|
||||
(1 << STRIPE_PREREAD_ACTIVE) |
|
||||
(1 << STRIPE_DELAYED) |
|
||||
(1 << STRIPE_BIT_DELAY) |
|
||||
(1 << STRIPE_FULL_WRITE) |
|
||||
|
|
@ -4253,6 +4255,7 @@ static void break_stripe_batch_list(struct stripe_head *head_sh,
|
|||
(1 << STRIPE_REPLACED)));
|
||||
|
||||
set_mask_bits(&sh->state, ~(STRIPE_EXPAND_SYNC_FLAGS |
|
||||
(1 << STRIPE_PREREAD_ACTIVE) |
|
||||
(1 << STRIPE_DEGRADED)),
|
||||
head_sh->state & (1 << STRIPE_INSYNC));
|
||||
|
||||
|
|
@ -6414,6 +6417,12 @@ static int raid5_alloc_percpu(struct r5conf *conf)
|
|||
}
|
||||
put_online_cpus();
|
||||
|
||||
if (!err) {
|
||||
conf->scribble_disks = max(conf->raid_disks,
|
||||
conf->previous_raid_disks);
|
||||
conf->scribble_sectors = max(conf->chunk_sectors,
|
||||
conf->prev_chunk_sectors);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -6504,9 +6513,7 @@ static struct r5conf *setup_conf(struct mddev *mddev)
|
|||
seqcount_init(&conf->gen_lock);
|
||||
mutex_init(&conf->cache_size_mutex);
|
||||
init_waitqueue_head(&conf->wait_for_quiescent);
|
||||
for (i = 0; i < NR_STRIPE_HASH_LOCKS; i++) {
|
||||
init_waitqueue_head(&conf->wait_for_stripe[i]);
|
||||
}
|
||||
init_waitqueue_head(&conf->wait_for_stripe);
|
||||
init_waitqueue_head(&conf->wait_for_overlap);
|
||||
INIT_LIST_HEAD(&conf->handle_list);
|
||||
INIT_LIST_HEAD(&conf->hold_list);
|
||||
|
|
@ -7015,8 +7022,8 @@ static int run(struct mddev *mddev)
|
|||
}
|
||||
|
||||
if (discard_supported &&
|
||||
mddev->queue->limits.max_discard_sectors >= stripe &&
|
||||
mddev->queue->limits.discard_granularity >= stripe)
|
||||
mddev->queue->limits.max_discard_sectors >= (stripe >> 9) &&
|
||||
mddev->queue->limits.discard_granularity >= stripe)
|
||||
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD,
|
||||
mddev->queue);
|
||||
else
|
||||
|
|
|
|||
|
|
@ -510,6 +510,8 @@ struct r5conf {
|
|||
* conversions
|
||||
*/
|
||||
} __percpu *percpu;
|
||||
int scribble_disks;
|
||||
int scribble_sectors;
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
struct notifier_block cpu_notify;
|
||||
#endif
|
||||
|
|
@ -522,7 +524,7 @@ struct r5conf {
|
|||
atomic_t empty_inactive_list_nr;
|
||||
struct llist_head released_stripes;
|
||||
wait_queue_head_t wait_for_quiescent;
|
||||
wait_queue_head_t wait_for_stripe[NR_STRIPE_HASH_LOCKS];
|
||||
wait_queue_head_t wait_for_stripe;
|
||||
wait_queue_head_t wait_for_overlap;
|
||||
unsigned long cache_state;
|
||||
#define R5_INACTIVE_BLOCKED 1 /* release of inactive stripes blocked,
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user