This is the 4.4.5 stable release

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQIcBAABCAAGBQJW4LNjAAoJEDjbvchgkmk+XfUP/R7mD1vHLjLRVMKfbwlIEqOv
 pisPGxmxzZwHYUeMkIyU0a4i6jd3COEJDSIpHOhGVbCRs/1wdYYzMEnT6TyvpDup
 dWrIkr+zlT9NGg3Gh5MIpjDNnEml8xQT1GdLX1+fqmiCXM7N9/XnecSa7n6hut7k
 GzR3N/3FTUrqz65mcuUm1b2VJkLWSyMxjX/QpVXnJnLyTqpdzCMglA0fMkUaGk7H
 emcc9JpFXn4yPWZ/WY1WrVWF3CGTFg5PUIaIZJ19iyNKNlS8mXovh6VNy4E7Jter
 BOeaR+e+ZPvptg0YbApVV5dRzQ0sFJKW74b3XGGV31La85vqeX43WJcX98SBoGI0
 A/qaz87fkuSKfaMrtwuy4vnTZCGNtrFNcBtovm6DqFBBo5jOtHphf8ShJ7k4IVYK
 c9g2k31OSJM9RGraNMNFMvH7DZr1/Ib8pHcGnr6DnVK2N+gnBDvbhPOcBM10RRtI
 Q35y3Y1Mdg2ssnFIO3qtewMlptdME5z76zkCfUwtG4nVqExMlA4qvrPhculK/Jn/
 mEjLW2QCIIu1weFsSLc/2vCZ+9pguh+yudr0fk0unlHxUdJ2fMAY4SarFu8zLlBe
 /VJwdjbYOSKTE6Mdcn0Zdwyv6OPmMLc4MGimBdC7JIV5EH0gOpu3nsDdOY3KsQYT
 5nhZDVB18+M8+hfag+aL
 =9ghs
 -----END PGP SIGNATURE-----

Merge tag 'v4.4.5' into linux-linaro-lsk-v4.4

This is the 4.4.5 stable release

# gpg: Signature made Wed 09 Mar 2016 23:36:03 GMT using RSA key ID 6092693E
# gpg: Good signature from "Greg Kroah-Hartman (Linux kernel stable release signing key) <greg@kroah.com>"
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 647F 2865 4894 E3BD 4571  99BE 38DB BDC8 6092 693E
This commit is contained in:
Mark Brown 2016-03-18 09:45:54 +00:00
commit ddbcfcba5f
651 changed files with 7598 additions and 3136 deletions

View File

@ -14,3 +14,10 @@ filesystem.
efivarfs is typically mounted like this,
mount -t efivarfs none /sys/firmware/efi/efivars
Due to the presence of numerous firmware bugs where removing non-standard
UEFI variables causes the system firmware to fail to POST, efivarfs
files that are not well-known standardized variables are created
as immutable files. This doesn't prevent removal - "chattr -i" will work -
but it does prevent this kind of failure from being accomplished
accidentally.

View File

@ -10289,9 +10289,11 @@ S: Maintained
F: drivers/net/ethernet/dlink/sundance.c
SUPERH
M: Yoshinori Sato <ysato@users.sourceforge.jp>
M: Rich Felker <dalias@libc.org>
L: linux-sh@vger.kernel.org
Q: http://patchwork.kernel.org/project/linux-sh/list/
S: Orphan
S: Maintained
F: Documentation/sh/
F: arch/sh/
F: drivers/sh/

View File

@ -1,6 +1,6 @@
VERSION = 4
PATCHLEVEL = 4
SUBLEVEL = 1
SUBLEVEL = 5
EXTRAVERSION =
NAME = Blurry Fish Butt

View File

@ -22,6 +22,7 @@
#define AUX_IRQ_CTRL 0x00E
#define AUX_IRQ_ACT 0x043 /* Active Intr across all levels */
#define AUX_IRQ_LVL_PEND 0x200 /* Pending Intr across all levels */
#define AUX_IRQ_HINT 0x201 /* For generating Soft Interrupts */
#define AUX_IRQ_PRIORITY 0x206
#define ICAUSE 0x40a
#define AUX_IRQ_SELECT 0x40b
@ -112,6 +113,16 @@ static inline int arch_irqs_disabled(void)
return arch_irqs_disabled_flags(arch_local_save_flags());
}
static inline void arc_softirq_trigger(int irq)
{
write_aux_reg(AUX_IRQ_HINT, irq);
}
static inline void arc_softirq_clear(int irq)
{
write_aux_reg(AUX_IRQ_HINT, 0);
}
#else
.macro IRQ_DISABLE scratch

View File

@ -45,11 +45,12 @@ VECTOR reserved ; Reserved slots
VECTOR handle_interrupt ; (16) Timer0
VECTOR handle_interrupt ; unused (Timer1)
VECTOR handle_interrupt ; unused (WDT)
VECTOR handle_interrupt ; (19) ICI (inter core interrupt)
VECTOR handle_interrupt
VECTOR handle_interrupt
VECTOR handle_interrupt
VECTOR handle_interrupt ; (23) End of fixed IRQs
VECTOR handle_interrupt ; (19) Inter core Interrupt (IPI)
VECTOR handle_interrupt ; (20) perf Interrupt
VECTOR handle_interrupt ; (21) Software Triggered Intr (Self IPI)
VECTOR handle_interrupt ; unused
VECTOR handle_interrupt ; (23) unused
# End of fixed IRQs
.rept CONFIG_ARC_NUMBER_OF_INTERRUPTS - 8
VECTOR handle_interrupt
@ -211,7 +212,11 @@ debug_marker_syscall:
; (since IRQ NOT allowed in DS in ARCv2, this can only happen if orig
; entry was via Exception in DS which got preempted in kernel).
;
; IRQ RTIE won't reliably restore DE bit and/or BTA, needs handling
; IRQ RTIE won't reliably restore DE bit and/or BTA, needs workaround
;
; Solution is return from Intr w/o any delay slot quirks into a kernel trampoline
; and from pure kernel mode return to delay slot which handles DS bit/BTA correctly
.Lintr_ret_to_delay_slot:
debug_marker_ds:
@ -222,18 +227,23 @@ debug_marker_ds:
ld r2, [sp, PT_ret]
ld r3, [sp, PT_status32]
; STAT32 for Int return created from scratch
; (No delay dlot, disable Further intr in trampoline)
bic r0, r3, STATUS_U_MASK|STATUS_DE_MASK|STATUS_IE_MASK|STATUS_L_MASK
st r0, [sp, PT_status32]
mov r1, .Lintr_ret_to_delay_slot_2
st r1, [sp, PT_ret]
; Orig exception PC/STAT32 safekept @orig_r0 and @event stack slots
st r2, [sp, 0]
st r3, [sp, 4]
b .Lisr_ret_fast_path
.Lintr_ret_to_delay_slot_2:
; Trampoline to restore orig exception PC/STAT32/BTA/AUX_USER_SP
sub sp, sp, SZ_PT_REGS
st r9, [sp, -4]
@ -243,11 +253,19 @@ debug_marker_ds:
ld r9, [sp, 4]
sr r9, [erstatus]
; restore AUX_USER_SP if returning to U mode
bbit0 r9, STATUS_U_BIT, 1f
ld r9, [sp, PT_sp]
sr r9, [AUX_USER_SP]
1:
ld r9, [sp, 8]
sr r9, [erbta]
ld r9, [sp, -4]
add sp, sp, SZ_PT_REGS
; return from pure kernel mode to delay slot
rtie
END(ret_from_exception)

View File

@ -11,9 +11,12 @@
#include <linux/smp.h>
#include <linux/irq.h>
#include <linux/spinlock.h>
#include <asm/irqflags-arcv2.h>
#include <asm/mcip.h>
#include <asm/setup.h>
#define SOFTIRQ_IRQ 21
static char smp_cpuinfo_buf[128];
static int idu_detected;
@ -22,6 +25,7 @@ static DEFINE_RAW_SPINLOCK(mcip_lock);
static void mcip_setup_per_cpu(int cpu)
{
smp_ipi_irq_setup(cpu, IPI_IRQ);
smp_ipi_irq_setup(cpu, SOFTIRQ_IRQ);
}
static void mcip_ipi_send(int cpu)
@ -29,6 +33,12 @@ static void mcip_ipi_send(int cpu)
unsigned long flags;
int ipi_was_pending;
/* ARConnect can only send IPI to others */
if (unlikely(cpu == raw_smp_processor_id())) {
arc_softirq_trigger(SOFTIRQ_IRQ);
return;
}
/*
* NOTE: We must spin here if the other cpu hasn't yet
* serviced a previous message. This can burn lots
@ -63,6 +73,11 @@ static void mcip_ipi_clear(int irq)
unsigned long flags;
unsigned int __maybe_unused copy;
if (unlikely(irq == SOFTIRQ_IRQ)) {
arc_softirq_clear(irq);
return;
}
raw_spin_lock_irqsave(&mcip_lock, flags);
/* Who sent the IPI */

View File

@ -162,10 +162,9 @@ choice
mobile SoCs in the Kona family of chips (e.g. bcm28155,
bcm11351, etc...)
config DEBUG_BCM63XX
config DEBUG_BCM63XX_UART
bool "Kernel low-level debugging on BCM63XX UART"
depends on ARCH_BCM_63XX
select DEBUG_UART_BCM63XX
config DEBUG_BERLIN_UART
bool "Marvell Berlin SoC Debug UART"
@ -1348,7 +1347,7 @@ config DEBUG_LL_INCLUDE
default "debug/vf.S" if DEBUG_VF_UART
default "debug/vt8500.S" if DEBUG_VT8500_UART0
default "debug/zynq.S" if DEBUG_ZYNQ_UART0 || DEBUG_ZYNQ_UART1
default "debug/bcm63xx.S" if DEBUG_UART_BCM63XX
default "debug/bcm63xx.S" if DEBUG_BCM63XX_UART
default "debug/digicolor.S" if DEBUG_DIGICOLOR_UA0
default "mach/debug-macro.S"
@ -1364,10 +1363,6 @@ config DEBUG_UART_8250
ARCH_IOP33X || ARCH_IXP4XX || \
ARCH_LPC32XX || ARCH_MV78XX0 || ARCH_ORION5X || ARCH_RPC
# Compatibility options for BCM63xx
config DEBUG_UART_BCM63XX
def_bool ARCH_BCM_63XX
config DEBUG_UART_PHYS
hex "Physical base address of debug UART"
default 0x00100a00 if DEBUG_NETX_UART
@ -1462,7 +1457,7 @@ config DEBUG_UART_PHYS
default 0xfffb0000 if DEBUG_OMAP1UART1 || DEBUG_OMAP7XXUART1
default 0xfffb0800 if DEBUG_OMAP1UART2 || DEBUG_OMAP7XXUART2
default 0xfffb9800 if DEBUG_OMAP1UART3 || DEBUG_OMAP7XXUART3
default 0xfffe8600 if DEBUG_UART_BCM63XX
default 0xfffe8600 if DEBUG_BCM63XX_UART
default 0xfffff700 if ARCH_IOP33X
depends on ARCH_EP93XX || \
DEBUG_LL_UART_8250 || DEBUG_LL_UART_PL01X || \
@ -1474,7 +1469,7 @@ config DEBUG_UART_PHYS
DEBUG_RCAR_GEN2_SCIF0 || DEBUG_RCAR_GEN2_SCIF2 || \
DEBUG_RMOBILE_SCIFA0 || DEBUG_RMOBILE_SCIFA1 || \
DEBUG_RMOBILE_SCIFA4 || DEBUG_S3C24XX_UART || \
DEBUG_UART_BCM63XX || DEBUG_ASM9260_UART || \
DEBUG_BCM63XX_UART || DEBUG_ASM9260_UART || \
DEBUG_SIRFSOC_UART || DEBUG_DIGICOLOR_UA0 || \
DEBUG_AT91_UART
@ -1515,7 +1510,7 @@ config DEBUG_UART_VIRT
default 0xfb10c000 if DEBUG_REALVIEW_PB1176_PORT
default 0xfc40ab00 if DEBUG_BRCMSTB_UART
default 0xfc705000 if DEBUG_ZTE_ZX
default 0xfcfe8600 if DEBUG_UART_BCM63XX
default 0xfcfe8600 if DEBUG_BCM63XX_UART
default 0xfd000000 if ARCH_SPEAR3XX || ARCH_SPEAR6XX
default 0xfd000000 if ARCH_SPEAR13XX
default 0xfd012000 if ARCH_MV78XX0
@ -1566,7 +1561,7 @@ config DEBUG_UART_VIRT
DEBUG_UART_8250 || DEBUG_UART_PL01X || DEBUG_MESON_UARTAO || \
DEBUG_NETX_UART || \
DEBUG_QCOM_UARTDM || DEBUG_S3C24XX_UART || \
DEBUG_UART_BCM63XX || DEBUG_ASM9260_UART || \
DEBUG_BCM63XX_UART || DEBUG_ASM9260_UART || \
DEBUG_SIRFSOC_UART || DEBUG_DIGICOLOR_UA0
config DEBUG_UART_8250_SHIFT

View File

@ -303,16 +303,6 @@ reg_usb2_1_vbus: v5-vbus1 {
gpio = <&expander0 4 GPIO_ACTIVE_HIGH>;
};
reg_usb2_1_vbus: v5-vbus1 {
compatible = "regulator-fixed";
regulator-name = "v5.0-vbus1";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
enable-active-high;
regulator-always-on;
gpio = <&expander0 4 GPIO_ACTIVE_HIGH>;
};
reg_sata0: pwr-sata0 {
compatible = "regulator-fixed";
regulator-name = "pwr_en_sata0";

View File

@ -86,10 +86,12 @@ i2c0: i2c@f8014000 {
macb0: ethernet@f8020000 {
phy-mode = "rmii";
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_macb0_rmii &pinctrl_macb0_phy_irq>;
phy0: ethernet-phy@1 {
interrupt-parent = <&pioE>;
interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
reg = <1>;
};
};
@ -152,6 +154,10 @@ pinctrl_key_gpio: key_gpio_0 {
atmel,pins =
<AT91_PIOE 8 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>;
};
pinctrl_macb0_phy_irq: macb0_phy_irq_0 {
atmel,pins =
<AT91_PIOE 1 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>;
};
};
};
};

View File

@ -160,8 +160,15 @@ atmel_mxt_ts@4c {
};
macb0: ethernet@f8020000 {
pinctrl-0 = <&pinctrl_macb0_rmii &pinctrl_macb0_phy_irq>;
phy-mode = "rmii";
status = "okay";
ethernet-phy@1 {
reg = <0x1>;
interrupt-parent = <&pioE>;
interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
};
};
mmc1: mmc@fc000000 {
@ -193,6 +200,10 @@ watchdog@fc068640 {
pinctrl@fc06a000 {
board {
pinctrl_macb0_phy_irq: macb0_phy_irq {
atmel,pins =
<AT91_PIOE 1 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
};
pinctrl_mmc0_cd: mmc0_cd {
atmel,pins =
<AT91_PIOE 5 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>;

View File

@ -122,6 +122,7 @@ wlcore: wlcore@2 {
interrupt-parent = <&gpio5>;
interrupts = <24 IRQ_TYPE_LEVEL_HIGH>; /* gpio 152 */
ref-clock-frequency = <26000000>;
tcxo-clock-frequency = <26000000>;
};
};

View File

@ -130,6 +130,16 @@ sound: sound {
};
};
&gpio8 {
/* TI trees use GPIO instead of msecure, see also muxing */
p234 {
gpio-hog;
gpios = <10 GPIO_ACTIVE_HIGH>;
output-high;
line-name = "gpio8_234/msecure";
};
};
&omap5_pmx_core {
pinctrl-names = "default";
pinctrl-0 = <
@ -213,6 +223,13 @@ OMAP5_IOPAD(0x1bc, PIN_OUTPUT | MUX_MODE6) /* mcspi1_clk.gpio5_140 */
>;
};
/* TI trees use GPIO mode; msecure mode does not work reliably? */
palmas_msecure_pins: palmas_msecure_pins {
pinctrl-single,pins = <
OMAP5_IOPAD(0x180, PIN_OUTPUT | MUX_MODE6) /* gpio8_234 */
>;
};
usbhost_pins: pinmux_usbhost_pins {
pinctrl-single,pins = <
0x84 (PIN_INPUT | MUX_MODE0) /* usbb2_hsic_strobe */
@ -278,6 +295,12 @@ &omap5_pmx_wkup {
&usbhost_wkup_pins
>;
palmas_sys_nirq_pins: pinmux_palmas_sys_nirq_pins {
pinctrl-single,pins = <
OMAP5_IOPAD(0x068, PIN_INPUT_PULLUP | MUX_MODE0) /* sys_nirq1 */
>;
};
usbhost_wkup_pins: pinmux_usbhost_wkup_pins {
pinctrl-single,pins = <
0x1A (PIN_OUTPUT | MUX_MODE0) /* fref_clk1_out, USB hub clk */
@ -345,6 +368,8 @@ palmas: palmas@48 {
interrupt-controller;
#interrupt-cells = <2>;
ti,system-power-controller;
pinctrl-names = "default";
pinctrl-0 = <&palmas_sys_nirq_pins &palmas_msecure_pins>;
extcon_usb3: palmas_usb {
compatible = "ti,palmas-usb-vid";
@ -358,6 +383,14 @@ clk32kgaudio: palmas_clk32k@1 {
#clock-cells = <0>;
};
rtc {
compatible = "ti,palmas-rtc";
interrupt-parent = <&palmas>;
interrupts = <8 IRQ_TYPE_NONE>;
ti,backup-battery-chargeable;
ti,backup-battery-charge-high-current;
};
palmas_pmic {
compatible = "ti,palmas-pmic";
interrupt-parent = <&palmas>;

View File

@ -90,7 +90,7 @@
#define PIN_PA14__I2SC1_MCK PINMUX_PIN(PIN_PA14, 4, 2)
#define PIN_PA14__FLEXCOM3_IO2 PINMUX_PIN(PIN_PA14, 5, 1)
#define PIN_PA14__D9 PINMUX_PIN(PIN_PA14, 6, 2)
#define PIN_PA15 14
#define PIN_PA15 15
#define PIN_PA15__GPIO PINMUX_PIN(PIN_PA15, 0, 0)
#define PIN_PA15__SPI0_MOSI PINMUX_PIN(PIN_PA15, 1, 1)
#define PIN_PA15__TF1 PINMUX_PIN(PIN_PA15, 2, 1)

View File

@ -1342,7 +1342,7 @@ rtc@fc0686b0 {
dbgu: serial@fc069000 {
compatible = "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
reg = <0xfc069000 0x200>;
interrupts = <2 IRQ_TYPE_LEVEL_HIGH 7>;
interrupts = <45 IRQ_TYPE_LEVEL_HIGH 7>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_dbgu>;
clocks = <&dbgu_clk>;

View File

@ -127,22 +127,14 @@ mmcsd_default_mux {
};
mmcsd_default_mode: mmcsd_default {
mmcsd_default_cfg1 {
/* MCCLK */
pins = "GPIO8_B10";
ste,output = <0>;
};
mmcsd_default_cfg2 {
/* MCCMDDIR, MCDAT0DIR, MCDAT31DIR, MCDATDIR2 */
pins = "GPIO10_C11", "GPIO15_A12",
"GPIO16_C13", "GPIO23_D15";
ste,output = <1>;
};
mmcsd_default_cfg3 {
/* MCCMD, MCDAT3-0, MCMSFBCLK */
pins = "GPIO9_A10", "GPIO11_B11",
"GPIO12_A11", "GPIO13_C12",
"GPIO14_B12", "GPIO24_C15";
ste,input = <1>;
/*
* MCCLK, MCCMDDIR, MCDAT0DIR, MCDAT31DIR, MCDATDIR2
* MCCMD, MCDAT3-0, MCMSFBCLK
*/
pins = "GPIO8_B10", "GPIO9_A10", "GPIO10_C11", "GPIO11_B11",
"GPIO12_A11", "GPIO13_C12", "GPIO14_B12", "GPIO15_A12",
"GPIO16_C13", "GPIO23_D15", "GPIO24_C15";
ste,output = <2>;
};
};
};
@ -802,10 +794,21 @@ mmcsd: sdi@101f6000 {
clock-names = "mclk", "apb_pclk";
interrupt-parent = <&vica>;
interrupts = <22>;
max-frequency = <48000000>;
max-frequency = <400000>;
bus-width = <4>;
cap-mmc-highspeed;
cap-sd-highspeed;
full-pwr-cycle;
/*
* The STw4811 circuit used with the Nomadik strictly
* requires that all of these signal direction pins be
* routed and used for its 4-bit levelshifter.
*/
st,sig-dir-dat0;
st,sig-dir-dat2;
st,sig-dir-dat31;
st,sig-dir-cmd;
st,sig-pin-fbclk;
pinctrl-names = "default";
pinctrl-0 = <&mmcsd_default_mux>, <&mmcsd_default_mode>;
vmmc-supply = <&vmmc_regulator>;

View File

@ -16,7 +16,7 @@
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/div64.h>
#include <asm/hardware/icst.h>
/*
@ -29,7 +29,11 @@ EXPORT_SYMBOL(icst525_s2div);
unsigned long icst_hz(const struct icst_params *p, struct icst_vco vco)
{
return p->ref * 2 * (vco.v + 8) / ((vco.r + 2) * p->s2div[vco.s]);
u64 dividend = p->ref * 2 * (u64)(vco.v + 8);
u32 divisor = (vco.r + 2) * p->s2div[vco.s];
do_div(dividend, divisor);
return (unsigned long)dividend;
}
EXPORT_SYMBOL(icst_hz);
@ -58,6 +62,7 @@ icst_hz_to_vco(const struct icst_params *p, unsigned long freq)
if (f > p->vco_min && f <= p->vco_max)
break;
i++;
} while (i < 8);
if (i >= 8)

View File

@ -16,7 +16,7 @@
extern struct smp_operations psci_smp_ops;
#ifdef CONFIG_ARM_PSCI
#if defined(CONFIG_SMP) && defined(CONFIG_ARM_PSCI)
bool psci_smp_available(void);
#else
static inline bool psci_smp_available(void) { return false; }

View File

@ -35,14 +35,21 @@ static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
dma_addr_t dev_addr, unsigned long offset, size_t size,
enum dma_data_direction dir, struct dma_attrs *attrs)
{
bool local = XEN_PFN_DOWN(dev_addr) == page_to_xen_pfn(page);
unsigned long page_pfn = page_to_xen_pfn(page);
unsigned long dev_pfn = XEN_PFN_DOWN(dev_addr);
unsigned long compound_pages =
(1<<compound_order(page)) * XEN_PFN_PER_PAGE;
bool local = (page_pfn <= dev_pfn) &&
(dev_pfn - page_pfn < compound_pages);
/*
* Dom0 is mapped 1:1, while the Linux page can be spanned accross
* multiple Xen page, it's not possible to have a mix of local and
* foreign Xen page. So if the first xen_pfn == mfn the page is local
* otherwise it's a foreign page grant-mapped in dom0. If the page is
* local we can safely call the native dma_ops function, otherwise we
* call the xen specific function.
* Dom0 is mapped 1:1, while the Linux page can span across
* multiple Xen pages, it's not possible for it to contain a
* mix of local and foreign Xen pages. So if the first xen_pfn
* == mfn the page is local otherwise it's a foreign page
* grant-mapped in dom0. If the page is local we can safely
* call the native dma_ops function, otherwise we call the xen
* specific function.
*/
if (local)
__generic_dma_ops(hwdev)->map_page(hwdev, page, offset, size, dir, attrs);

View File

@ -155,7 +155,7 @@ static int get_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
u64 val;
val = kvm_arm_timer_get_reg(vcpu, reg->id);
return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id));
return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)) ? -EFAULT : 0;
}
static unsigned long num_core_regs(void)

View File

@ -101,10 +101,8 @@ static void omap2_onenand_set_async_mode(void __iomem *onenand_base)
static void set_onenand_cfg(void __iomem *onenand_base)
{
u32 reg;
u32 reg = ONENAND_SYS_CFG1_RDY | ONENAND_SYS_CFG1_INT;
reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
reg &= ~((0x7 << ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 << 9));
reg |= (latency << ONENAND_SYS_CFG1_BRL_SHIFT) |
ONENAND_SYS_CFG1_BL_16;
if (onenand_flags & ONENAND_FLAG_SYNCREAD)
@ -123,6 +121,7 @@ static void set_onenand_cfg(void __iomem *onenand_base)
reg |= ONENAND_SYS_CFG1_VHF;
else
reg &= ~ONENAND_SYS_CFG1_VHF;
writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
}
@ -289,6 +288,7 @@ static int omap2_onenand_setup_async(void __iomem *onenand_base)
}
}
onenand_async.sync_write = true;
omap2_onenand_calc_async_timings(&t);
ret = gpmc_cs_program_settings(gpmc_onenand_data->cs, &onenand_async);

View File

@ -86,13 +86,18 @@ ENTRY(enable_omap3630_toggle_l2_on_restore)
stmfd sp!, {lr} @ save registers on stack
/* Setup so that we will disable and enable l2 */
mov r1, #0x1
adrl r2, l2dis_3630 @ may be too distant for plain adr
str r1, [r2]
adrl r3, l2dis_3630_offset @ may be too distant for plain adr
ldr r2, [r3] @ value for offset
str r1, [r2, r3] @ write to l2dis_3630
ldmfd sp!, {pc} @ restore regs and return
ENDPROC(enable_omap3630_toggle_l2_on_restore)
.text
/* Function to call rom code to save secure ram context */
/*
* Function to call rom code to save secure ram context. This gets
* relocated to SRAM, so it can be all in .data section. Otherwise
* we need to initialize api_params separately.
*/
.data
.align 3
ENTRY(save_secure_ram_context)
stmfd sp!, {r4 - r11, lr} @ save registers on stack
@ -126,6 +131,8 @@ ENDPROC(save_secure_ram_context)
ENTRY(save_secure_ram_context_sz)
.word . - save_secure_ram_context
.text
/*
* ======================
* == Idle entry point ==
@ -289,12 +296,6 @@ wait_sdrc_ready:
bic r5, r5, #0x40
str r5, [r4]
/*
* PC-relative stores lead to undefined behaviour in Thumb-2: use a r7 as a
* base instead.
* Be careful not to clobber r7 when maintaing this code.
*/
is_dll_in_lock_mode:
/* Is dll in lock mode? */
ldr r4, sdrc_dlla_ctrl
@ -302,11 +303,7 @@ is_dll_in_lock_mode:
tst r5, #0x4
bne exit_nonoff_modes @ Return if locked
/* wait till dll locks */
adr r7, kick_counter
wait_dll_lock_timed:
ldr r4, wait_dll_lock_counter
add r4, r4, #1
str r4, [r7, #wait_dll_lock_counter - kick_counter]
ldr r4, sdrc_dlla_status
/* Wait 20uS for lock */
mov r6, #8
@ -330,9 +327,6 @@ kick_dll:
orr r6, r6, #(1<<3) @ enable dll
str r6, [r4]
dsb
ldr r4, kick_counter
add r4, r4, #1
str r4, [r7] @ kick_counter
b wait_dll_lock_timed
exit_nonoff_modes:
@ -360,15 +354,6 @@ sdrc_dlla_status:
.word SDRC_DLLA_STATUS_V
sdrc_dlla_ctrl:
.word SDRC_DLLA_CTRL_V
/*
* When exporting to userspace while the counters are in SRAM,
* these 2 words need to be at the end to facilitate retrival!
*/
kick_counter:
.word 0
wait_dll_lock_counter:
.word 0
ENTRY(omap3_do_wfi_sz)
.word . - omap3_do_wfi
@ -437,7 +422,9 @@ ENTRY(omap3_restore)
cmp r2, #0x0 @ Check if target power state was OFF or RET
bne logic_l1_restore
ldr r0, l2dis_3630
adr r1, l2dis_3630_offset @ address for offset
ldr r0, [r1] @ value for offset
ldr r0, [r1, r0] @ value at l2dis_3630
cmp r0, #0x1 @ should we disable L2 on 3630?
bne skipl2dis
mrc p15, 0, r0, c1, c0, 1
@ -449,12 +436,14 @@ skipl2dis:
and r1, #0x700
cmp r1, #0x300
beq l2_inv_gp
adr r0, l2_inv_api_params_offset
ldr r3, [r0]
add r3, r3, r0 @ r3 points to dummy parameters
mov r0, #40 @ set service ID for PPA
mov r12, r0 @ copy secure Service ID in r12
mov r1, #0 @ set task id for ROM code in r1
mov r2, #4 @ set some flags in r2, r6
mov r6, #0xff
adr r3, l2_inv_api_params @ r3 points to dummy parameters
dsb @ data write barrier
dmb @ data memory barrier
smc #1 @ call SMI monitor (smi #1)
@ -488,8 +477,8 @@ skipl2dis:
b logic_l1_restore
.align
l2_inv_api_params:
.word 0x1, 0x00
l2_inv_api_params_offset:
.long l2_inv_api_params - .
l2_inv_gp:
/* Execute smi to invalidate L2 cache */
mov r12, #0x1 @ set up to invalidate L2
@ -506,7 +495,9 @@ l2_inv_gp:
mov r12, #0x2
smc #0 @ Call SMI monitor (smieq)
logic_l1_restore:
ldr r1, l2dis_3630
adr r0, l2dis_3630_offset @ adress for offset
ldr r1, [r0] @ value for offset
ldr r1, [r0, r1] @ value at l2dis_3630
cmp r1, #0x1 @ Test if L2 re-enable needed on 3630
bne skipl2reen
mrc p15, 0, r1, c1, c0, 1
@ -535,9 +526,17 @@ control_stat:
.word CONTROL_STAT
control_mem_rta:
.word CONTROL_MEM_RTA_CTRL
l2dis_3630_offset:
.long l2dis_3630 - .
.data
l2dis_3630:
.word 0
.data
l2_inv_api_params:
.word 0x1, 0x00
/*
* Internal functions
*/

View File

@ -29,12 +29,6 @@
dsb
.endm
ppa_zero_params:
.word 0x0
ppa_por_params:
.word 1, 0
#ifdef CONFIG_ARCH_OMAP4
/*
@ -266,7 +260,9 @@ ENTRY(omap4_cpu_resume)
beq skip_ns_smp_enable
ppa_actrl_retry:
mov r0, #OMAP4_PPA_CPU_ACTRL_SMP_INDEX
adr r3, ppa_zero_params @ Pointer to parameters
adr r1, ppa_zero_params_offset
ldr r3, [r1]
add r3, r3, r1 @ Pointer to ppa_zero_params
mov r1, #0x0 @ Process ID
mov r2, #0x4 @ Flag
mov r6, #0xff
@ -303,7 +299,9 @@ skip_ns_smp_enable:
ldr r0, =OMAP4_PPA_L2_POR_INDEX
ldr r1, =OMAP44XX_SAR_RAM_BASE
ldr r4, [r1, #L2X0_PREFETCH_CTRL_OFFSET]
adr r3, ppa_por_params
adr r1, ppa_por_params_offset
ldr r3, [r1]
add r3, r3, r1 @ Pointer to ppa_por_params
str r4, [r3, #0x04]
mov r1, #0x0 @ Process ID
mov r2, #0x4 @ Flag
@ -328,6 +326,8 @@ skip_l2en:
#endif
b cpu_resume @ Jump to generic resume
ppa_por_params_offset:
.long ppa_por_params - .
ENDPROC(omap4_cpu_resume)
#endif /* CONFIG_ARCH_OMAP4 */
@ -380,4 +380,13 @@ ENTRY(omap_do_wfi)
nop
ldmfd sp!, {pc}
ppa_zero_params_offset:
.long ppa_zero_params - .
ENDPROC(omap_do_wfi)
.data
ppa_zero_params:
.word 0
ppa_por_params:
.word 1, 0

View File

@ -27,6 +27,7 @@ $(warning LSE atomics not supported by binutils)
endif
KBUILD_CFLAGS += -mgeneral-regs-only $(lseinstr)
KBUILD_CFLAGS += $(call cc-option, -mpc-relative-literal-loads)
KBUILD_AFLAGS += $(lseinstr)
ifeq ($(CONFIG_CPU_BIG_ENDIAN), y)

View File

@ -34,13 +34,13 @@
/*
* VMALLOC and SPARSEMEM_VMEMMAP ranges.
*
* VMEMAP_SIZE: allows the whole VA space to be covered by a struct page array
* VMEMAP_SIZE: allows the whole linear region to be covered by a struct page array
* (rounded up to PUD_SIZE).
* VMALLOC_START: beginning of the kernel VA space
* VMALLOC_END: extends to the available space below vmmemmap, PCI I/O space,
* fixed mappings and modules
*/
#define VMEMMAP_SIZE ALIGN((1UL << (VA_BITS - PAGE_SHIFT)) * sizeof(struct page), PUD_SIZE)
#define VMEMMAP_SIZE ALIGN((1UL << (VA_BITS - PAGE_SHIFT - 1)) * sizeof(struct page), PUD_SIZE)
#ifndef CONFIG_KASAN
#define VMALLOC_START (VA_START)
@ -51,7 +51,8 @@
#define VMALLOC_END (PAGE_OFFSET - PUD_SIZE - VMEMMAP_SIZE - SZ_64K)
#define vmemmap ((struct page *)(VMALLOC_END + SZ_64K))
#define VMEMMAP_START (VMALLOC_END + SZ_64K)
#define vmemmap ((struct page *)VMEMMAP_START - (memstart_addr >> PAGE_SHIFT))
#define FIRST_USER_ADDRESS 0UL

View File

@ -186,7 +186,7 @@ static int get_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
u64 val;
val = kvm_arm_timer_get_reg(vcpu, reg->id);
return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id));
return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)) ? -EFAULT : 0;
}
/**

View File

@ -933,6 +933,10 @@ static int __init __iommu_dma_init(void)
ret = register_iommu_dma_ops_notifier(&platform_bus_type);
if (!ret)
ret = register_iommu_dma_ops_notifier(&amba_bustype);
/* handle devices queued before this arch_initcall */
if (!ret)
__iommu_attach_notifier(NULL, BUS_NOTIFY_ADD_DEVICE, NULL);
return ret;
}
arch_initcall(__iommu_dma_init);

View File

@ -319,8 +319,8 @@ void __init mem_init(void)
#endif
MLG(VMALLOC_START, VMALLOC_END),
#ifdef CONFIG_SPARSEMEM_VMEMMAP
MLG((unsigned long)vmemmap,
(unsigned long)vmemmap + VMEMMAP_SIZE),
MLG(VMEMMAP_START,
VMEMMAP_START + VMEMMAP_SIZE),
MLM((unsigned long)virt_to_page(PAGE_OFFSET),
(unsigned long)virt_to_page(high_memory)),
#endif

View File

@ -57,6 +57,9 @@ static int change_memory_common(unsigned long addr, int numpages,
if (end < MODULES_VADDR || end >= MODULES_END)
return -EINVAL;
if (!numpages)
return 0;
data.set_mask = set_mask;
data.clear_mask = clear_mask;

View File

@ -81,7 +81,10 @@ static struct resource code_resource = {
};
unsigned long memory_start;
EXPORT_SYMBOL(memory_start);
unsigned long memory_end;
EXPORT_SYMBOL(memory_end);
void __init setup_arch(char **);
int get_cpuinfo(char *);

View File

@ -33,7 +33,7 @@
#define PAGE_SHIFT 16
#endif
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE - 1))
#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1))
/*
* This is used for calculating the real page sizes

View File

@ -353,7 +353,7 @@ static inline pte_t pte_mkdirty(pte_t pte)
static inline pte_t pte_mkyoung(pte_t pte)
{
pte_val(pte) |= _PAGE_ACCESSED;
#ifdef CONFIG_CPU_MIPSR2
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
if (!(pte_val(pte) & _PAGE_NO_READ))
pte_val(pte) |= _PAGE_SILENT_READ;
else
@ -560,7 +560,7 @@ static inline pmd_t pmd_mkyoung(pmd_t pmd)
{
pmd_val(pmd) |= _PAGE_ACCESSED;
#ifdef CONFIG_CPU_MIPSR2
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
if (!(pmd_val(pmd) & _PAGE_NO_READ))
pmd_val(pmd) |= _PAGE_SILENT_READ;
else

View File

@ -101,10 +101,8 @@ static inline void syscall_get_arguments(struct task_struct *task,
/* O32 ABI syscall() - Either 64-bit with O32 or 32-bit */
if ((config_enabled(CONFIG_32BIT) ||
test_tsk_thread_flag(task, TIF_32BIT_REGS)) &&
(regs->regs[2] == __NR_syscall)) {
(regs->regs[2] == __NR_syscall))
i++;
n++;
}
while (n--)
ret |= mips_get_syscall_arg(args++, task, regs, i++);

View File

@ -690,15 +690,15 @@ static int simulate_sync(struct pt_regs *regs, unsigned int opcode)
asmlinkage void do_ov(struct pt_regs *regs)
{
enum ctx_state prev_state;
siginfo_t info;
siginfo_t info = {
.si_signo = SIGFPE,
.si_code = FPE_INTOVF,
.si_addr = (void __user *)regs->cp0_epc,
};
prev_state = exception_enter();
die_if_kernel("Integer overflow", regs);
info.si_code = FPE_INTOVF;
info.si_signo = SIGFPE;
info.si_errno = 0;
info.si_addr = (void __user *) regs->cp0_epc;
force_sig_info(SIGFPE, &info, current);
exception_exit(prev_state);
}
@ -874,7 +874,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
const char *str)
{
siginfo_t info;
siginfo_t info = { 0 };
char b[40];
#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
@ -903,7 +903,6 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
else
info.si_code = FPE_INTOVF;
info.si_signo = SIGFPE;
info.si_errno = 0;
info.si_addr = (void __user *) regs->cp0_epc;
force_sig_info(SIGFPE, &info, current);
break;

View File

@ -702,7 +702,7 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu,
} else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U128) {
void __user *uaddr = (void __user *)(long)reg->addr;
return copy_to_user(uaddr, vs, 16);
return copy_to_user(uaddr, vs, 16) ? -EFAULT : 0;
} else {
return -EINVAL;
}
@ -732,7 +732,7 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu,
} else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U128) {
void __user *uaddr = (void __user *)(long)reg->addr;
return copy_from_user(vs, uaddr, 16);
return copy_from_user(vs, uaddr, 16) ? -EFAULT : 0;
} else {
return -EINVAL;
}

View File

@ -13,6 +13,9 @@
#define SMBUS_PCI_REG64 0x64
#define SMBUS_PCI_REGB4 0xb4
#define HPET_MIN_CYCLES 64
#define HPET_MIN_PROG_DELTA (HPET_MIN_CYCLES + (HPET_MIN_CYCLES >> 1))
static DEFINE_SPINLOCK(hpet_lock);
DEFINE_PER_CPU(struct clock_event_device, hpet_clockevent_device);
@ -161,8 +164,9 @@ static int hpet_next_event(unsigned long delta,
cnt += delta;
hpet_write(HPET_T0_CMP, cnt);
res = ((int)(hpet_read(HPET_COUNTER) - cnt) > 0) ? -ETIME : 0;
return res;
res = (int)(cnt - hpet_read(HPET_COUNTER));
return res < HPET_MIN_CYCLES ? -ETIME : 0;
}
static irqreturn_t hpet_irq_handler(int irq, void *data)
@ -237,7 +241,7 @@ void __init setup_hpet_timer(void)
cd->cpumask = cpumask_of(cpu);
clockevent_set_clock(cd, HPET_FREQ);
cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
cd->min_delta_ns = 5000;
cd->min_delta_ns = clockevent_delta2ns(HPET_MIN_PROG_DELTA, cd);
clockevents_register_device(cd);
setup_irq(HPET_T0_IRQ, &hpet_irq);

View File

@ -30,13 +30,13 @@
#include "smp.h"
DEFINE_PER_CPU(int, cpu_state);
DEFINE_PER_CPU(uint32_t, core0_c0count);
static void *ipi_set0_regs[16];
static void *ipi_clear0_regs[16];
static void *ipi_status0_regs[16];
static void *ipi_en0_regs[16];
static void *ipi_mailbox_buf[16];
static uint32_t core0_c0count[NR_CPUS];
/* read a 32bit value from ipi register */
#define loongson3_ipi_read32(addr) readl(addr)
@ -275,12 +275,14 @@ void loongson3_ipi_interrupt(struct pt_regs *regs)
if (action & SMP_ASK_C0COUNT) {
BUG_ON(cpu != 0);
c0count = read_c0_count();
for (i = 1; i < num_possible_cpus(); i++)
per_cpu(core0_c0count, i) = c0count;
c0count = c0count ? c0count : 1;
for (i = 1; i < nr_cpu_ids; i++)
core0_c0count[i] = c0count;
__wbflush(); /* Let others see the result ASAP */
}
}
#define MAX_LOOPS 1111
#define MAX_LOOPS 800
/*
* SMP init and finish on secondary CPUs
*/
@ -305,16 +307,20 @@ static void loongson3_init_secondary(void)
cpu_logical_map(cpu) / loongson_sysconf.cores_per_package;
i = 0;
__this_cpu_write(core0_c0count, 0);
core0_c0count[cpu] = 0;
loongson3_send_ipi_single(0, SMP_ASK_C0COUNT);
while (!__this_cpu_read(core0_c0count)) {
while (!core0_c0count[cpu]) {
i++;
cpu_relax();
}
if (i > MAX_LOOPS)
i = MAX_LOOPS;
initcount = __this_cpu_read(core0_c0count) + i;
if (cpu_data[cpu].package)
initcount = core0_c0count[cpu] + i;
else /* Local access is faster for loops */
initcount = core0_c0count[cpu] + i/2;
write_c0_count(initcount);
}

View File

@ -164,11 +164,13 @@ static int __init mips_sc_probe_cm3(void)
sets = cfg & CM_GCR_L2_CONFIG_SET_SIZE_MSK;
sets >>= CM_GCR_L2_CONFIG_SET_SIZE_SHF;
c->scache.sets = 64 << sets;
if (sets)
c->scache.sets = 64 << sets;
line_sz = cfg & CM_GCR_L2_CONFIG_LINE_SIZE_MSK;
line_sz >>= CM_GCR_L2_CONFIG_LINE_SIZE_SHF;
c->scache.linesz = 2 << line_sz;
if (line_sz)
c->scache.linesz = 2 << line_sz;
assoc = cfg & CM_GCR_L2_CONFIG_ASSOC_MSK;
assoc >>= CM_GCR_L2_CONFIG_ASSOC_SHF;
@ -176,9 +178,12 @@ static int __init mips_sc_probe_cm3(void)
c->scache.waysize = c->scache.sets * c->scache.linesz;
c->scache.waybit = __ffs(c->scache.waysize);
c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
if (c->scache.linesz) {
c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
return 1;
}
return 1;
return 0;
}
void __weak platform_early_l2_init(void)

View File

@ -242,7 +242,7 @@ static void output_pgtable_bits_defines(void)
pr_define("_PAGE_HUGE_SHIFT %d\n", _PAGE_HUGE_SHIFT);
pr_define("_PAGE_SPLITTING_SHIFT %d\n", _PAGE_SPLITTING_SHIFT);
#endif
#ifdef CONFIG_CPU_MIPSR2
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
if (cpu_has_rixi) {
#ifdef _PAGE_NO_EXEC_SHIFT
pr_define("_PAGE_NO_EXEC_SHIFT %d\n", _PAGE_NO_EXEC_SHIFT);

View File

@ -54,24 +54,12 @@ static inline pte_t huge_pte_wrprotect(pte_t pte)
return pte_wrprotect(pte);
}
static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
unsigned long addr, pte_t *ptep)
{
pte_t old_pte = *ptep;
set_huge_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
}
void huge_ptep_set_wrprotect(struct mm_struct *mm,
unsigned long addr, pte_t *ptep);
static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
int huge_ptep_set_access_flags(struct vm_area_struct *vma,
unsigned long addr, pte_t *ptep,
pte_t pte, int dirty)
{
int changed = !pte_same(*ptep, pte);
if (changed) {
set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
flush_tlb_page(vma, addr);
}
return changed;
}
pte_t pte, int dirty);
static inline pte_t huge_ptep_get(pte_t *ptep)
{

View File

@ -1,6 +1,10 @@
#ifndef _PARISC_SIGINFO_H
#define _PARISC_SIGINFO_H
#if defined(__LP64__)
#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))
#endif
#include <asm-generic/siginfo.h>
#undef NSIGTRAP

View File

@ -269,14 +269,19 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
long do_syscall_trace_enter(struct pt_regs *regs)
{
long ret = 0;
/* Do the secure computing check first. */
secure_computing_strict(regs->gr[20]);
if (test_thread_flag(TIF_SYSCALL_TRACE) &&
tracehook_report_syscall_entry(regs))
ret = -1L;
tracehook_report_syscall_entry(regs)) {
/*
* Tracing decided this syscall should not happen or the
* debugger stored an invalid system call number. Skip
* the system call and the system call restart handling.
*/
regs->gr[20] = -1UL;
goto out;
}
#ifdef CONFIG_64BIT
if (!is_compat_task())
@ -290,7 +295,8 @@ long do_syscall_trace_enter(struct pt_regs *regs)
regs->gr[24] & 0xffffffff,
regs->gr[23] & 0xffffffff);
return ret ? : regs->gr[20];
out:
return regs->gr[20];
}
void do_syscall_trace_exit(struct pt_regs *regs)

View File

@ -343,7 +343,7 @@ tracesys_next:
#endif
comiclr,>>= __NR_Linux_syscalls, %r20, %r0
b,n .Lsyscall_nosys
b,n .Ltracesys_nosys
LDREGX %r20(%r19), %r19
@ -359,6 +359,9 @@ tracesys_next:
be 0(%sr7,%r19)
ldo R%tracesys_exit(%r2),%r2
.Ltracesys_nosys:
ldo -ENOSYS(%r0),%r28 /* set errno */
/* Do *not* call this function on the gateway page, because it
makes a direct call to syscall_trace. */

View File

@ -105,15 +105,13 @@ static inline void purge_tlb_entries_huge(struct mm_struct *mm, unsigned long ad
addr |= _HUGE_PAGE_SIZE_ENCODING_DEFAULT;
for (i = 0; i < (1 << (HPAGE_SHIFT-REAL_HPAGE_SHIFT)); i++) {
mtsp(mm->context, 1);
pdtlb(addr);
if (unlikely(split_tlb))
pitlb(addr);
purge_tlb_entries(mm, addr);
addr += (1UL << REAL_HPAGE_SHIFT);
}
}
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
/* __set_huge_pte_at() must be called holding the pa_tlb_lock. */
static void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t entry)
{
unsigned long addr_start;
@ -123,14 +121,9 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
addr_start = addr;
for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
/* Directly write pte entry. We could call set_pte_at(mm, addr, ptep, entry)
* instead, but then we get double locking on pa_tlb_lock. */
*ptep = entry;
set_pte(ptep, entry);
ptep++;
/* Drop the PAGE_SIZE/non-huge tlb entry */
purge_tlb_entries(mm, addr);
addr += PAGE_SIZE;
pte_val(entry) += PAGE_SIZE;
}
@ -138,18 +131,61 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
purge_tlb_entries_huge(mm, addr_start);
}
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t entry)
{
unsigned long flags;
purge_tlb_start(flags);
__set_huge_pte_at(mm, addr, ptep, entry);
purge_tlb_end(flags);
}
pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
pte_t *ptep)
{
unsigned long flags;
pte_t entry;
purge_tlb_start(flags);
entry = *ptep;
set_huge_pte_at(mm, addr, ptep, __pte(0));
__set_huge_pte_at(mm, addr, ptep, __pte(0));
purge_tlb_end(flags);
return entry;
}
void huge_ptep_set_wrprotect(struct mm_struct *mm,
unsigned long addr, pte_t *ptep)
{
unsigned long flags;
pte_t old_pte;
purge_tlb_start(flags);
old_pte = *ptep;
__set_huge_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
purge_tlb_end(flags);
}
int huge_ptep_set_access_flags(struct vm_area_struct *vma,
unsigned long addr, pte_t *ptep,
pte_t pte, int dirty)
{
unsigned long flags;
int changed;
purge_tlb_start(flags);
changed = !pte_same(*ptep, pte);
if (changed) {
__set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
}
purge_tlb_end(flags);
return changed;
}
int pmd_huge(pmd_t pmd)
{
return 0;

View File

@ -81,6 +81,7 @@ struct pci_dn;
#define EEH_PE_KEEP (1 << 8) /* Keep PE on hotplug */
#define EEH_PE_CFG_RESTRICTED (1 << 9) /* Block config on error */
#define EEH_PE_REMOVED (1 << 10) /* Removed permanently */
#define EEH_PE_PRI_BUS (1 << 11) /* Cached primary bus */
struct eeh_pe {
int type; /* PE type: PHB/Bus/Device */

View File

@ -418,8 +418,7 @@ static void *eeh_rmv_device(void *data, void *userdata)
eeh_pcid_put(dev);
if (driver->err_handler &&
driver->err_handler->error_detected &&
driver->err_handler->slot_reset &&
driver->err_handler->resume)
driver->err_handler->slot_reset)
return NULL;
}
@ -564,6 +563,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
*/
eeh_pe_state_mark(pe, EEH_PE_KEEP);
if (bus) {
eeh_pe_state_clear(pe, EEH_PE_PRI_BUS);
pci_lock_rescan_remove();
pcibios_remove_pci_devices(bus);
pci_unlock_rescan_remove();
@ -803,6 +803,7 @@ static void eeh_handle_normal_event(struct eeh_pe *pe)
* the their PCI config any more.
*/
if (frozen_bus) {
eeh_pe_state_clear(pe, EEH_PE_PRI_BUS);
eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED);
pci_lock_rescan_remove();
@ -886,6 +887,7 @@ static void eeh_handle_special_event(void)
continue;
/* Notify all devices to be down */
eeh_pe_state_clear(pe, EEH_PE_PRI_BUS);
bus = eeh_pe_bus_get(phb_pe);
eeh_pe_dev_traverse(pe,
eeh_report_failure, NULL);

View File

@ -883,32 +883,29 @@ void eeh_pe_restore_bars(struct eeh_pe *pe)
const char *eeh_pe_loc_get(struct eeh_pe *pe)
{
struct pci_bus *bus = eeh_pe_bus_get(pe);
struct device_node *dn = pci_bus_to_OF_node(bus);
struct device_node *dn;
const char *loc = NULL;
if (!dn)
goto out;
while (bus) {
dn = pci_bus_to_OF_node(bus);
if (!dn) {
bus = bus->parent;
continue;
}
/* PHB PE or root PE ? */
if (pci_is_root_bus(bus)) {
loc = of_get_property(dn, "ibm,loc-code", NULL);
if (!loc)
if (pci_is_root_bus(bus))
loc = of_get_property(dn, "ibm,io-base-loc-code", NULL);
if (loc)
goto out;
else
loc = of_get_property(dn, "ibm,slot-location-code",
NULL);
/* Check the root port */
dn = dn->child;
if (!dn)
goto out;
if (loc)
return loc;
bus = bus->parent;
}
loc = of_get_property(dn, "ibm,loc-code", NULL);
if (!loc)
loc = of_get_property(dn, "ibm,slot-location-code", NULL);
out:
return loc ? loc : "N/A";
return "N/A";
}
/**
@ -931,7 +928,7 @@ struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe)
bus = pe->phb->bus;
} else if (pe->type & EEH_PE_BUS ||
pe->type & EEH_PE_DEVICE) {
if (pe->bus) {
if (pe->state & EEH_PE_PRI_BUS) {
bus = pe->bus;
goto out;
}

View File

@ -2153,7 +2153,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
/* Emulate H_SET_DABR/X on P8 for the sake of compat mode guests */
2: rlwimi r5, r4, 5, DAWRX_DR | DAWRX_DW
rlwimi r5, r4, 1, DAWRX_WT
rlwimi r5, r4, 2, DAWRX_WT
clrrdi r4, r4, 3
std r4, VCPU_DAWR(r3)
std r5, VCPU_DAWRX(r3)

View File

@ -919,21 +919,17 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
r = -ENXIO;
break;
}
vcpu->arch.vr.vr[reg->id - KVM_REG_PPC_VR0] = val.vval;
val.vval = vcpu->arch.vr.vr[reg->id - KVM_REG_PPC_VR0];
break;
case KVM_REG_PPC_VSCR:
if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
r = -ENXIO;
break;
}
vcpu->arch.vr.vscr.u[3] = set_reg_val(reg->id, val);
val = get_reg_val(reg->id, vcpu->arch.vr.vscr.u[3]);
break;
case KVM_REG_PPC_VRSAVE:
if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
r = -ENXIO;
break;
}
vcpu->arch.vrsave = set_reg_val(reg->id, val);
val = get_reg_val(reg->id, vcpu->arch.vrsave);
break;
#endif /* CONFIG_ALTIVEC */
default:
@ -974,17 +970,21 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
r = -ENXIO;
break;
}
val.vval = vcpu->arch.vr.vr[reg->id - KVM_REG_PPC_VR0];
vcpu->arch.vr.vr[reg->id - KVM_REG_PPC_VR0] = val.vval;
break;
case KVM_REG_PPC_VSCR:
if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
r = -ENXIO;
break;
}
val = get_reg_val(reg->id, vcpu->arch.vr.vscr.u[3]);
vcpu->arch.vr.vscr.u[3] = set_reg_val(reg->id, val);
break;
case KVM_REG_PPC_VRSAVE:
val = get_reg_val(reg->id, vcpu->arch.vrsave);
if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
r = -ENXIO;
break;
}
vcpu->arch.vrsave = set_reg_val(reg->id, val);
break;
#endif /* CONFIG_ALTIVEC */
default:

View File

@ -444,9 +444,12 @@ static void *pnv_eeh_probe(struct pci_dn *pdn, void *data)
* PCI devices of the PE are expected to be removed prior
* to PE reset.
*/
if (!edev->pe->bus)
if (!(edev->pe->state & EEH_PE_PRI_BUS)) {
edev->pe->bus = pci_find_bus(hose->global_number,
pdn->busno);
if (edev->pe->bus)
edev->pe->state |= EEH_PE_PRI_BUS;
}
/*
* Enable EEH explicitly so that we will do EEH check

View File

@ -3034,6 +3034,7 @@ static void pnv_pci_ioda_shutdown(struct pci_controller *hose)
static const struct pci_controller_ops pnv_pci_ioda_controller_ops = {
.dma_dev_setup = pnv_pci_dma_dev_setup,
.dma_bus_setup = pnv_pci_dma_bus_setup,
#ifdef CONFIG_PCI_MSI
.setup_msi_irqs = pnv_setup_msi_irqs,
.teardown_msi_irqs = pnv_teardown_msi_irqs,

View File

@ -601,6 +601,9 @@ int pnv_tce_build(struct iommu_table *tbl, long index, long npages,
u64 rpn = __pa(uaddr) >> tbl->it_page_shift;
long i;
if (proto_tce & TCE_PCI_WRITE)
proto_tce |= TCE_PCI_READ;
for (i = 0; i < npages; i++) {
unsigned long newtce = proto_tce |
((rpn + i) << tbl->it_page_shift);
@ -622,6 +625,9 @@ int pnv_tce_xchg(struct iommu_table *tbl, long index,
BUG_ON(*hpa & ~IOMMU_PAGE_MASK(tbl));
if (newtce & TCE_PCI_WRITE)
newtce |= TCE_PCI_READ;
oldtce = xchg(pnv_tce(tbl, idx), cpu_to_be64(newtce));
*hpa = be64_to_cpu(oldtce) & ~(TCE_PCI_READ | TCE_PCI_WRITE);
*direction = iommu_tce_direction(oldtce);
@ -762,6 +768,26 @@ void pnv_pci_dma_dev_setup(struct pci_dev *pdev)
phb->dma_dev_setup(phb, pdev);
}
void pnv_pci_dma_bus_setup(struct pci_bus *bus)
{
struct pci_controller *hose = bus->sysdata;
struct pnv_phb *phb = hose->private_data;
struct pnv_ioda_pe *pe;
list_for_each_entry(pe, &phb->ioda.pe_list, list) {
if (!(pe->flags & (PNV_IODA_PE_BUS | PNV_IODA_PE_BUS_ALL)))
continue;
if (!pe->pbus)
continue;
if (bus->number == ((pe->rid >> 8) & 0xFF)) {
pe->pbus = bus;
break;
}
}
}
void pnv_pci_shutdown(void)
{
struct pci_controller *hose;

View File

@ -235,6 +235,7 @@ extern void pnv_pci_reset_secondary_bus(struct pci_dev *dev);
extern int pnv_eeh_phb_reset(struct pci_controller *hose, int option);
extern void pnv_pci_dma_dev_setup(struct pci_dev *pdev);
extern void pnv_pci_dma_bus_setup(struct pci_bus *bus);
extern int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type);
extern void pnv_teardown_msi_irqs(struct pci_dev *pdev);

View File

@ -48,6 +48,7 @@ static inline void convert_fp_to_vx(__vector128 *vxrs, freg_t *fprs)
static inline void fpregs_store(_s390_fp_regs *fpregs, struct fpu *fpu)
{
fpregs->pad = 0;
fpregs->fpc = fpu->fpc;
if (MACHINE_HAS_VX)
convert_vx_to_fp((freg_t *)&fpregs->fprs, fpu->vxrs);
else
@ -57,6 +58,7 @@ static inline void fpregs_store(_s390_fp_regs *fpregs, struct fpu *fpu)
static inline void fpregs_load(_s390_fp_regs *fpregs, struct fpu *fpu)
{
fpu->fpc = fpregs->fpc;
if (MACHINE_HAS_VX)
convert_fp_to_vx(fpu->vxrs, (freg_t *)&fpregs->fprs);
else

View File

@ -506,7 +506,6 @@ struct kvm_vcpu_arch {
struct kvm_s390_sie_block *sie_block;
unsigned int host_acrs[NUM_ACRS];
struct fpu host_fpregs;
struct fpu guest_fpregs;
struct kvm_s390_local_interrupt local_int;
struct hrtimer ckc_timer;
struct kvm_s390_pgm_info pgm;

View File

@ -181,6 +181,7 @@ int main(void)
OFFSET(__LC_PSW_SAVE_AREA, _lowcore, psw_save_area);
OFFSET(__LC_PREFIX_SAVE_AREA, _lowcore, prefixreg_save_area);
OFFSET(__LC_FP_CREG_SAVE_AREA, _lowcore, fpt_creg_save_area);
OFFSET(__LC_TOD_PROGREG_SAVE_AREA, _lowcore, tod_progreg_save_area);
OFFSET(__LC_CPU_TIMER_SAVE_AREA, _lowcore, cpu_timer_save_area);
OFFSET(__LC_CLOCK_COMP_SAVE_AREA, _lowcore, clock_comp_save_area);
OFFSET(__LC_AREGS_SAVE_AREA, _lowcore, access_regs_save_area);

View File

@ -271,7 +271,7 @@ static int restore_sigregs_ext32(struct pt_regs *regs,
/* Restore high gprs from signal stack */
if (__copy_from_user(&gprs_high, &sregs_ext->gprs_high,
sizeof(&sregs_ext->gprs_high)))
sizeof(sregs_ext->gprs_high)))
return -EFAULT;
for (i = 0; i < NUM_GPRS; i++)
*(__u32 *)&regs->gprs[i] = gprs_high[i];

View File

@ -1268,44 +1268,18 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
return 0;
}
/*
* Backs up the current FP/VX register save area on a particular
* destination. Used to switch between different register save
* areas.
*/
static inline void save_fpu_to(struct fpu *dst)
{
dst->fpc = current->thread.fpu.fpc;
dst->regs = current->thread.fpu.regs;
}
/*
* Switches the FP/VX register save area from which to lazy
* restore register contents.
*/
static inline void load_fpu_from(struct fpu *from)
{
current->thread.fpu.fpc = from->fpc;
current->thread.fpu.regs = from->regs;
}
void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
{
/* Save host register state */
save_fpu_regs();
save_fpu_to(&vcpu->arch.host_fpregs);
if (test_kvm_facility(vcpu->kvm, 129)) {
current->thread.fpu.fpc = vcpu->run->s.regs.fpc;
/*
* Use the register save area in the SIE-control block
* for register restore and save in kvm_arch_vcpu_put()
*/
current->thread.fpu.vxrs =
(__vector128 *)&vcpu->run->s.regs.vrs;
} else
load_fpu_from(&vcpu->arch.guest_fpregs);
vcpu->arch.host_fpregs.fpc = current->thread.fpu.fpc;
vcpu->arch.host_fpregs.regs = current->thread.fpu.regs;
/* Depending on MACHINE_HAS_VX, data stored to vrs either
* has vector register or floating point register format.
*/
current->thread.fpu.regs = vcpu->run->s.regs.vrs;
current->thread.fpu.fpc = vcpu->run->s.regs.fpc;
if (test_fp_ctl(current->thread.fpu.fpc))
/* User space provided an invalid FPC, let's clear it */
current->thread.fpu.fpc = 0;
@ -1321,19 +1295,13 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
atomic_andnot(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
gmap_disable(vcpu->arch.gmap);
/* Save guest register state */
save_fpu_regs();
vcpu->run->s.regs.fpc = current->thread.fpu.fpc;
if (test_kvm_facility(vcpu->kvm, 129))
/*
* kvm_arch_vcpu_load() set up the register save area to
* the &vcpu->run->s.regs.vrs and, thus, the vector registers
* are already saved. Only the floating-point control must be
* copied.
*/
vcpu->run->s.regs.fpc = current->thread.fpu.fpc;
else
save_fpu_to(&vcpu->arch.guest_fpregs);
load_fpu_from(&vcpu->arch.host_fpregs);
/* Restore host register state */
current->thread.fpu.fpc = vcpu->arch.host_fpregs.fpc;
current->thread.fpu.regs = vcpu->arch.host_fpregs.regs;
save_access_regs(vcpu->run->s.regs.acrs);
restore_access_regs(vcpu->arch.host_acrs);
@ -1351,8 +1319,9 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
memset(vcpu->arch.sie_block->gcr, 0, 16 * sizeof(__u64));
vcpu->arch.sie_block->gcr[0] = 0xE0UL;
vcpu->arch.sie_block->gcr[14] = 0xC2000000UL;
vcpu->arch.guest_fpregs.fpc = 0;
asm volatile("lfpc %0" : : "Q" (vcpu->arch.guest_fpregs.fpc));
/* make sure the new fpc will be lazily loaded */
save_fpu_regs();
current->thread.fpu.fpc = 0;
vcpu->arch.sie_block->gbea = 1;
vcpu->arch.sie_block->pp = 0;
vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID;
@ -1501,19 +1470,6 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
vcpu->arch.local_int.wq = &vcpu->wq;
vcpu->arch.local_int.cpuflags = &vcpu->arch.sie_block->cpuflags;
/*
* Allocate a save area for floating-point registers. If the vector
* extension is available, register contents are saved in the SIE
* control block. The allocated save area is still required in
* particular places, for example, in kvm_s390_vcpu_store_status().
*/
vcpu->arch.guest_fpregs.fprs = kzalloc(sizeof(freg_t) * __NUM_FPRS,
GFP_KERNEL);
if (!vcpu->arch.guest_fpregs.fprs) {
rc = -ENOMEM;
goto out_free_sie_block;
}
rc = kvm_vcpu_init(vcpu, kvm, id);
if (rc)
goto out_free_sie_block;
@ -1734,19 +1690,27 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
{
/* make sure the new values will be lazily loaded */
save_fpu_regs();
if (test_fp_ctl(fpu->fpc))
return -EINVAL;
memcpy(vcpu->arch.guest_fpregs.fprs, &fpu->fprs, sizeof(fpu->fprs));
vcpu->arch.guest_fpregs.fpc = fpu->fpc;
save_fpu_regs();
load_fpu_from(&vcpu->arch.guest_fpregs);
current->thread.fpu.fpc = fpu->fpc;
if (MACHINE_HAS_VX)
convert_fp_to_vx(current->thread.fpu.vxrs, (freg_t *)fpu->fprs);
else
memcpy(current->thread.fpu.fprs, &fpu->fprs, sizeof(fpu->fprs));
return 0;
}
int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
{
memcpy(&fpu->fprs, vcpu->arch.guest_fpregs.fprs, sizeof(fpu->fprs));
fpu->fpc = vcpu->arch.guest_fpregs.fpc;
/* make sure we have the latest values */
save_fpu_regs();
if (MACHINE_HAS_VX)
convert_vx_to_fp((freg_t *)fpu->fprs, current->thread.fpu.vxrs);
else
memcpy(fpu->fprs, current->thread.fpu.fprs, sizeof(fpu->fprs));
fpu->fpc = current->thread.fpu.fpc;
return 0;
}
@ -2266,41 +2230,50 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long gpa)
{
unsigned char archmode = 1;
freg_t fprs[NUM_FPRS];
unsigned int px;
u64 clkcomp;
int rc;
px = kvm_s390_get_prefix(vcpu);
if (gpa == KVM_S390_STORE_STATUS_NOADDR) {
if (write_guest_abs(vcpu, 163, &archmode, 1))
return -EFAULT;
gpa = SAVE_AREA_BASE;
gpa = 0;
} else if (gpa == KVM_S390_STORE_STATUS_PREFIXED) {
if (write_guest_real(vcpu, 163, &archmode, 1))
return -EFAULT;
gpa = kvm_s390_real_to_abs(vcpu, SAVE_AREA_BASE);
gpa = px;
} else
gpa -= __LC_FPREGS_SAVE_AREA;
/* manually convert vector registers if necessary */
if (MACHINE_HAS_VX) {
convert_vx_to_fp(fprs, current->thread.fpu.vxrs);
rc = write_guest_abs(vcpu, gpa + __LC_FPREGS_SAVE_AREA,
fprs, 128);
} else {
rc = write_guest_abs(vcpu, gpa + __LC_FPREGS_SAVE_AREA,
vcpu->run->s.regs.vrs, 128);
}
rc = write_guest_abs(vcpu, gpa + offsetof(struct save_area, fp_regs),
vcpu->arch.guest_fpregs.fprs, 128);
rc |= write_guest_abs(vcpu, gpa + offsetof(struct save_area, gp_regs),
rc |= write_guest_abs(vcpu, gpa + __LC_GPREGS_SAVE_AREA,
vcpu->run->s.regs.gprs, 128);
rc |= write_guest_abs(vcpu, gpa + offsetof(struct save_area, psw),
rc |= write_guest_abs(vcpu, gpa + __LC_PSW_SAVE_AREA,
&vcpu->arch.sie_block->gpsw, 16);
px = kvm_s390_get_prefix(vcpu);
rc |= write_guest_abs(vcpu, gpa + offsetof(struct save_area, pref_reg),
rc |= write_guest_abs(vcpu, gpa + __LC_PREFIX_SAVE_AREA,
&px, 4);
rc |= write_guest_abs(vcpu,
gpa + offsetof(struct save_area, fp_ctrl_reg),
&vcpu->arch.guest_fpregs.fpc, 4);
rc |= write_guest_abs(vcpu, gpa + offsetof(struct save_area, tod_reg),
rc |= write_guest_abs(vcpu, gpa + __LC_FP_CREG_SAVE_AREA,
&vcpu->run->s.regs.fpc, 4);
rc |= write_guest_abs(vcpu, gpa + __LC_TOD_PROGREG_SAVE_AREA,
&vcpu->arch.sie_block->todpr, 4);
rc |= write_guest_abs(vcpu, gpa + offsetof(struct save_area, timer),
rc |= write_guest_abs(vcpu, gpa + __LC_CPU_TIMER_SAVE_AREA,
&vcpu->arch.sie_block->cputm, 8);
clkcomp = vcpu->arch.sie_block->ckc >> 8;
rc |= write_guest_abs(vcpu, gpa + offsetof(struct save_area, clk_cmp),
rc |= write_guest_abs(vcpu, gpa + __LC_CLOCK_COMP_SAVE_AREA,
&clkcomp, 8);
rc |= write_guest_abs(vcpu, gpa + offsetof(struct save_area, acc_regs),
rc |= write_guest_abs(vcpu, gpa + __LC_AREGS_SAVE_AREA,
&vcpu->run->s.regs.acrs, 64);
rc |= write_guest_abs(vcpu, gpa + offsetof(struct save_area, ctrl_regs),
rc |= write_guest_abs(vcpu, gpa + __LC_CREGS_SAVE_AREA,
&vcpu->arch.sie_block->gcr, 128);
return rc ? -EFAULT : 0;
}
@ -2313,19 +2286,7 @@ int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
* it into the save area
*/
save_fpu_regs();
if (test_kvm_facility(vcpu->kvm, 129)) {
/*
* If the vector extension is available, the vector registers
* which overlaps with floating-point registers are saved in
* the SIE-control block. Hence, extract the floating-point
* registers and the FPC value and store them in the
* guest_fpregs structure.
*/
vcpu->arch.guest_fpregs.fpc = current->thread.fpu.fpc;
convert_vx_to_fp(vcpu->arch.guest_fpregs.fprs,
current->thread.fpu.vxrs);
} else
save_fpu_to(&vcpu->arch.guest_fpregs);
vcpu->run->s.regs.fpc = current->thread.fpu.fpc;
save_access_regs(vcpu->run->s.regs.acrs);
return kvm_s390_store_status_unloaded(vcpu, addr);

View File

@ -52,12 +52,16 @@ void sort_extable(struct exception_table_entry *start,
int i;
/* Normalize entries to being relative to the start of the section */
for (p = start, i = 0; p < finish; p++, i += 8)
for (p = start, i = 0; p < finish; p++, i += 8) {
p->insn += i;
p->fixup += i + 4;
}
sort(start, finish - start, sizeof(*start), cmp_ex, NULL);
/* Denormalize all entries */
for (p = start, i = 0; p < finish; p++, i += 8)
for (p = start, i = 0; p < finish; p++, i += 8) {
p->insn -= i;
p->fixup -= i + 4;
}
}
#ifdef CONFIG_MODULES

View File

@ -413,7 +413,7 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second
SYSCALL_DEFINE1(sparc64_personality, unsigned long, personality)
{
int ret;
long ret;
if (personality(current->personality) == PER_LINUX32 &&
personality(personality) == PER_LINUX)

View File

@ -94,6 +94,8 @@ static int start_ptraced_child(void)
{
int pid, n, status;
fflush(stdout);
pid = fork();
if (pid == 0)
ptrace_child();

View File

@ -157,7 +157,9 @@ ENTRY(chacha20_4block_xor_ssse3)
# done with the slightly better performing SSSE3 byte shuffling,
# 7/12-bit word rotation uses traditional shift+OR.
sub $0x40,%rsp
mov %rsp,%r11
sub $0x80,%rsp
and $~63,%rsp
# x0..15[0-3] = s0..3[0..3]
movq 0x00(%rdi),%xmm1
@ -620,6 +622,6 @@ ENTRY(chacha20_4block_xor_ssse3)
pxor %xmm1,%xmm15
movdqu %xmm15,0xf0(%rsi)
add $0x40,%rsp
mov %r11,%rsp
ret
ENDPROC(chacha20_4block_xor_ssse3)

View File

@ -267,6 +267,7 @@ ENTRY(entry_INT80_compat)
* Interrupts are off on entry.
*/
PARAVIRT_ADJUST_EXCEPTION_FRAME
ASM_CLAC /* Do this early to minimize exposure */
SWAPGS
/*

View File

@ -23,11 +23,13 @@ extern void irq_ctx_init(int cpu);
#define __ARCH_HAS_DO_SOFTIRQ
struct irq_desc;
#ifdef CONFIG_HOTPLUG_CPU
#include <linux/cpumask.h>
extern int check_irq_vectors_for_cpu_disable(void);
extern void fixup_irqs(void);
extern void irq_force_complete_move(int);
extern void irq_force_complete_move(struct irq_desc *desc);
#endif
#ifdef CONFIG_HAVE_KVM
@ -37,7 +39,6 @@ extern void kvm_set_posted_intr_wakeup_handler(void (*handler)(void));
extern void (*x86_platform_ipi_callback)(void);
extern void native_init_IRQ(void);
struct irq_desc;
extern bool handle_irq(struct irq_desc *desc, struct pt_regs *regs);
extern __visible unsigned int do_IRQ(struct pt_regs *regs);

View File

@ -363,20 +363,18 @@ static inline enum page_cache_mode pgprot2cachemode(pgprot_t pgprot)
}
static inline pgprot_t pgprot_4k_2_large(pgprot_t pgprot)
{
pgprotval_t val = pgprot_val(pgprot);
pgprot_t new;
unsigned long val;
val = pgprot_val(pgprot);
pgprot_val(new) = (val & ~(_PAGE_PAT | _PAGE_PAT_LARGE)) |
((val & _PAGE_PAT) << (_PAGE_BIT_PAT_LARGE - _PAGE_BIT_PAT));
return new;
}
static inline pgprot_t pgprot_large_2_4k(pgprot_t pgprot)
{
pgprotval_t val = pgprot_val(pgprot);
pgprot_t new;
unsigned long val;
val = pgprot_val(pgprot);
pgprot_val(new) = (val & ~(_PAGE_PAT | _PAGE_PAT_LARGE)) |
((val & _PAGE_PAT_LARGE) >>
(_PAGE_BIT_PAT_LARGE - _PAGE_BIT_PAT));

View File

@ -16,6 +16,7 @@
#include <asm/cacheflush.h>
#include <asm/realmode.h>
#include <linux/ftrace.h>
#include "../../realmode/rm/wakeup.h"
#include "sleep.h"
@ -107,7 +108,13 @@ int x86_acpi_suspend_lowlevel(void)
saved_magic = 0x123456789abcdef0L;
#endif /* CONFIG_64BIT */
/*
* Pause/unpause graph tracing around do_suspend_lowlevel as it has
* inconsistent call/return info after it jumps to the wakeup vector.
*/
pause_graph_tracing();
do_suspend_lowlevel();
unpause_graph_tracing();
return 0;
}

View File

@ -2521,6 +2521,7 @@ void __init setup_ioapic_dest(void)
{
int pin, ioapic, irq, irq_entry;
const struct cpumask *mask;
struct irq_desc *desc;
struct irq_data *idata;
struct irq_chip *chip;
@ -2536,7 +2537,9 @@ void __init setup_ioapic_dest(void)
if (irq < 0 || !mp_init_irq_at_boot(ioapic, irq))
continue;
idata = irq_get_irq_data(irq);
desc = irq_to_desc(irq);
raw_spin_lock_irq(&desc->lock);
idata = irq_desc_get_irq_data(desc);
/*
* Honour affinities which have been set in early boot
@ -2550,6 +2553,7 @@ void __init setup_ioapic_dest(void)
/* Might be lapic_chip for irq 0 */
if (chip->irq_set_affinity)
chip->irq_set_affinity(idata, mask, false);
raw_spin_unlock_irq(&desc->lock);
}
}
#endif

View File

@ -30,7 +30,7 @@ struct apic_chip_data {
struct irq_domain *x86_vector_domain;
static DEFINE_RAW_SPINLOCK(vector_lock);
static cpumask_var_t vector_cpumask;
static cpumask_var_t vector_cpumask, vector_searchmask, searched_cpumask;
static struct irq_chip lapic_controller;
#ifdef CONFIG_X86_IO_APIC
static struct apic_chip_data *legacy_irq_data[NR_IRQS_LEGACY];
@ -116,35 +116,47 @@ static int __assign_irq_vector(int irq, struct apic_chip_data *d,
*/
static int current_vector = FIRST_EXTERNAL_VECTOR + VECTOR_OFFSET_START;
static int current_offset = VECTOR_OFFSET_START % 16;
int cpu, err;
int cpu, vector;
if (d->move_in_progress)
/*
* If there is still a move in progress or the previous move has not
* been cleaned up completely, tell the caller to come back later.
*/
if (d->move_in_progress ||
cpumask_intersects(d->old_domain, cpu_online_mask))
return -EBUSY;
/* Only try and allocate irqs on cpus that are present */
err = -ENOSPC;
cpumask_clear(d->old_domain);
cpumask_clear(searched_cpumask);
cpu = cpumask_first_and(mask, cpu_online_mask);
while (cpu < nr_cpu_ids) {
int new_cpu, vector, offset;
int new_cpu, offset;
/* Get the possible target cpus for @mask/@cpu from the apic */
apic->vector_allocation_domain(cpu, vector_cpumask, mask);
/*
* Clear the offline cpus from @vector_cpumask for searching
* and verify whether the result overlaps with @mask. If true,
* then the call to apic->cpu_mask_to_apicid_and() will
* succeed as well. If not, no point in trying to find a
* vector in this mask.
*/
cpumask_and(vector_searchmask, vector_cpumask, cpu_online_mask);
if (!cpumask_intersects(vector_searchmask, mask))
goto next_cpu;
if (cpumask_subset(vector_cpumask, d->domain)) {
err = 0;
if (cpumask_equal(vector_cpumask, d->domain))
break;
goto success;
/*
* New cpumask using the vector is a proper subset of
* the current in use mask. So cleanup the vector
* allocation for the members that are not used anymore.
* Mark the cpus which are not longer in the mask for
* cleanup.
*/
cpumask_andnot(d->old_domain, d->domain,
vector_cpumask);
d->move_in_progress =
cpumask_intersects(d->old_domain, cpu_online_mask);
cpumask_and(d->domain, d->domain, vector_cpumask);
break;
cpumask_andnot(d->old_domain, d->domain, vector_cpumask);
vector = d->cfg.vector;
goto update;
}
vector = current_vector;
@ -156,45 +168,60 @@ static int __assign_irq_vector(int irq, struct apic_chip_data *d,
vector = FIRST_EXTERNAL_VECTOR + offset;
}
if (unlikely(current_vector == vector)) {
cpumask_or(d->old_domain, d->old_domain,
vector_cpumask);
cpumask_andnot(vector_cpumask, mask, d->old_domain);
cpu = cpumask_first_and(vector_cpumask,
cpu_online_mask);
continue;
}
/* If the search wrapped around, try the next cpu */
if (unlikely(current_vector == vector))
goto next_cpu;
if (test_bit(vector, used_vectors))
goto next;
for_each_cpu_and(new_cpu, vector_cpumask, cpu_online_mask) {
for_each_cpu(new_cpu, vector_searchmask) {
if (!IS_ERR_OR_NULL(per_cpu(vector_irq, new_cpu)[vector]))
goto next;
}
/* Found one! */
current_vector = vector;
current_offset = offset;
if (d->cfg.vector) {
/* Schedule the old vector for cleanup on all cpus */
if (d->cfg.vector)
cpumask_copy(d->old_domain, d->domain);
d->move_in_progress =
cpumask_intersects(d->old_domain, cpu_online_mask);
}
for_each_cpu_and(new_cpu, vector_cpumask, cpu_online_mask)
for_each_cpu(new_cpu, vector_searchmask)
per_cpu(vector_irq, new_cpu)[vector] = irq_to_desc(irq);
d->cfg.vector = vector;
cpumask_copy(d->domain, vector_cpumask);
err = 0;
break;
}
goto update;
if (!err) {
/* cache destination APIC IDs into cfg->dest_apicid */
err = apic->cpu_mask_to_apicid_and(mask, d->domain,
&d->cfg.dest_apicid);
next_cpu:
/*
* We exclude the current @vector_cpumask from the requested
* @mask and try again with the next online cpu in the
* result. We cannot modify @mask, so we use @vector_cpumask
* as a temporary buffer here as it will be reassigned when
* calling apic->vector_allocation_domain() above.
*/
cpumask_or(searched_cpumask, searched_cpumask, vector_cpumask);
cpumask_andnot(vector_cpumask, mask, searched_cpumask);
cpu = cpumask_first_and(vector_cpumask, cpu_online_mask);
continue;
}
return -ENOSPC;
return err;
update:
/*
* Exclude offline cpus from the cleanup mask and set the
* move_in_progress flag when the result is not empty.
*/
cpumask_and(d->old_domain, d->old_domain, cpu_online_mask);
d->move_in_progress = !cpumask_empty(d->old_domain);
d->cfg.vector = vector;
cpumask_copy(d->domain, vector_cpumask);
success:
/*
* Cache destination APIC IDs into cfg->dest_apicid. This cannot fail
* as we already established, that mask & d->domain & cpu_online_mask
* is not empty.
*/
BUG_ON(apic->cpu_mask_to_apicid_and(mask, d->domain,
&d->cfg.dest_apicid));
return 0;
}
static int assign_irq_vector(int irq, struct apic_chip_data *data,
@ -224,10 +251,8 @@ static int assign_irq_vector_policy(int irq, int node,
static void clear_irq_vector(int irq, struct apic_chip_data *data)
{
struct irq_desc *desc;
unsigned long flags;
int cpu, vector;
raw_spin_lock_irqsave(&vector_lock, flags);
BUG_ON(!data->cfg.vector);
vector = data->cfg.vector;
@ -237,10 +262,13 @@ static void clear_irq_vector(int irq, struct apic_chip_data *data)
data->cfg.vector = 0;
cpumask_clear(data->domain);
if (likely(!data->move_in_progress)) {
raw_spin_unlock_irqrestore(&vector_lock, flags);
/*
* If move is in progress or the old_domain mask is not empty,
* i.e. the cleanup IPI has not been processed yet, we need to remove
* the old references to desc from all cpus vector tables.
*/
if (!data->move_in_progress && cpumask_empty(data->old_domain))
return;
}
desc = irq_to_desc(irq);
for_each_cpu_and(cpu, data->old_domain, cpu_online_mask) {
@ -253,7 +281,6 @@ static void clear_irq_vector(int irq, struct apic_chip_data *data)
}
}
data->move_in_progress = 0;
raw_spin_unlock_irqrestore(&vector_lock, flags);
}
void init_irq_alloc_info(struct irq_alloc_info *info,
@ -274,19 +301,24 @@ void copy_irq_alloc_info(struct irq_alloc_info *dst, struct irq_alloc_info *src)
static void x86_vector_free_irqs(struct irq_domain *domain,
unsigned int virq, unsigned int nr_irqs)
{
struct apic_chip_data *apic_data;
struct irq_data *irq_data;
unsigned long flags;
int i;
for (i = 0; i < nr_irqs; i++) {
irq_data = irq_domain_get_irq_data(x86_vector_domain, virq + i);
if (irq_data && irq_data->chip_data) {
raw_spin_lock_irqsave(&vector_lock, flags);
clear_irq_vector(virq + i, irq_data->chip_data);
free_apic_chip_data(irq_data->chip_data);
apic_data = irq_data->chip_data;
irq_domain_reset_irq_data(irq_data);
raw_spin_unlock_irqrestore(&vector_lock, flags);
free_apic_chip_data(apic_data);
#ifdef CONFIG_X86_IO_APIC
if (virq + i < nr_legacy_irqs())
legacy_irq_data[virq + i] = NULL;
#endif
irq_domain_reset_irq_data(irq_data);
}
}
}
@ -404,6 +436,8 @@ int __init arch_early_irq_init(void)
arch_init_htirq_domain(x86_vector_domain);
BUG_ON(!alloc_cpumask_var(&vector_cpumask, GFP_KERNEL));
BUG_ON(!alloc_cpumask_var(&vector_searchmask, GFP_KERNEL));
BUG_ON(!alloc_cpumask_var(&searched_cpumask, GFP_KERNEL));
return arch_early_ioapic_init();
}
@ -492,14 +526,7 @@ static int apic_set_affinity(struct irq_data *irq_data,
return -EINVAL;
err = assign_irq_vector(irq, data, dest);
if (err) {
if (assign_irq_vector(irq, data,
irq_data_get_affinity_mask(irq_data)))
pr_err("Failed to recover vector for irq %d\n", irq);
return err;
}
return IRQ_SET_MASK_OK;
return err ? err : IRQ_SET_MASK_OK;
}
static struct irq_chip lapic_controller = {
@ -511,20 +538,12 @@ static struct irq_chip lapic_controller = {
#ifdef CONFIG_SMP
static void __send_cleanup_vector(struct apic_chip_data *data)
{
cpumask_var_t cleanup_mask;
if (unlikely(!alloc_cpumask_var(&cleanup_mask, GFP_ATOMIC))) {
unsigned int i;
for_each_cpu_and(i, data->old_domain, cpu_online_mask)
apic->send_IPI_mask(cpumask_of(i),
IRQ_MOVE_CLEANUP_VECTOR);
} else {
cpumask_and(cleanup_mask, data->old_domain, cpu_online_mask);
apic->send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
free_cpumask_var(cleanup_mask);
}
raw_spin_lock(&vector_lock);
cpumask_and(data->old_domain, data->old_domain, cpu_online_mask);
data->move_in_progress = 0;
if (!cpumask_empty(data->old_domain))
apic->send_IPI_mask(data->old_domain, IRQ_MOVE_CLEANUP_VECTOR);
raw_spin_unlock(&vector_lock);
}
void send_cleanup_vector(struct irq_cfg *cfg)
@ -568,12 +587,25 @@ asmlinkage __visible void smp_irq_move_cleanup_interrupt(void)
goto unlock;
/*
* Check if the irq migration is in progress. If so, we
* haven't received the cleanup request yet for this irq.
* Nothing to cleanup if irq migration is in progress
* or this cpu is not set in the cleanup mask.
*/
if (data->move_in_progress)
if (data->move_in_progress ||
!cpumask_test_cpu(me, data->old_domain))
goto unlock;
/*
* We have two cases to handle here:
* 1) vector is unchanged but the target mask got reduced
* 2) vector and the target mask has changed
*
* #1 is obvious, but in #2 we have two vectors with the same
* irq descriptor: the old and the new vector. So we need to
* make sure that we only cleanup the old vector. The new
* vector has the current @vector number in the config and
* this cpu is part of the target mask. We better leave that
* one alone.
*/
if (vector == data->cfg.vector &&
cpumask_test_cpu(me, data->domain))
goto unlock;
@ -591,6 +623,7 @@ asmlinkage __visible void smp_irq_move_cleanup_interrupt(void)
goto unlock;
}
__this_cpu_write(vector_irq[vector], VECTOR_UNUSED);
cpumask_clear_cpu(me, data->old_domain);
unlock:
raw_spin_unlock(&desc->lock);
}
@ -619,12 +652,48 @@ void irq_complete_move(struct irq_cfg *cfg)
__irq_complete_move(cfg, ~get_irq_regs()->orig_ax);
}
void irq_force_complete_move(int irq)
/*
* Called with @desc->lock held and interrupts disabled.
*/
void irq_force_complete_move(struct irq_desc *desc)
{
struct irq_cfg *cfg = irq_cfg(irq);
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;
if (cfg)
__irq_complete_move(cfg, cfg->vector);
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.
*/
raw_spin_lock(&vector_lock);
/* Clean out all offline cpus (including ourself) first. */
cpumask_and(data->old_domain, data->old_domain, cpu_online_mask);
while (!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);
}
raw_spin_unlock(&vector_lock);
}
#endif

View File

@ -462,7 +462,7 @@ void fixup_irqs(void)
* non intr-remapping case, we can't wait till this interrupt
* arrives at this cpu before completing the irq move.
*/
irq_force_complete_move(irq);
irq_force_complete_move(desc);
if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
break_affinity = 1;
@ -470,6 +470,15 @@ void fixup_irqs(void)
}
chip = irq_data_get_irq_chip(data);
/*
* The interrupt descriptor might have been cleaned up
* already, but it is not yet removed from the radix tree
*/
if (!chip) {
raw_spin_unlock(&desc->lock);
continue;
}
if (!irqd_can_move_in_process_context(data) && chip->irq_mask)
chip->irq_mask(data);

View File

@ -650,10 +650,10 @@ static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt,
u16 sel;
la = seg_base(ctxt, addr.seg) + addr.ea;
*linear = la;
*max_size = 0;
switch (mode) {
case X86EMUL_MODE_PROT64:
*linear = la;
if (is_noncanonical_address(la))
goto bad;
@ -662,6 +662,7 @@ static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt,
goto bad;
break;
default:
*linear = la = (u32)la;
usable = ctxt->ops->get_segment(ctxt, &sel, &desc, NULL,
addr.seg);
if (!usable)
@ -689,7 +690,6 @@ static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt,
if (size > *max_size)
goto bad;
}
la &= (u32)-1;
break;
}
if (insn_aligned(ctxt, size) && ((la & (size - 1)) != 0))

View File

@ -249,7 +249,7 @@ static int FNAME(update_accessed_dirty_bits)(struct kvm_vcpu *vcpu,
return ret;
kvm_vcpu_mark_page_dirty(vcpu, table_gfn);
walker->ptes[level] = pte;
walker->ptes[level - 1] = pte;
}
return 0;
}

View File

@ -595,6 +595,8 @@ struct vcpu_vmx {
/* Support for PML */
#define PML_ENTITY_NUM 512
struct page *pml_pg;
u64 current_tsc_ratio;
};
enum segment_cache_field {
@ -2062,14 +2064,16 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
rdmsrl(MSR_IA32_SYSENTER_ESP, sysenter_esp);
vmcs_writel(HOST_IA32_SYSENTER_ESP, sysenter_esp); /* 22.2.3 */
/* Setup TSC multiplier */
if (cpu_has_vmx_tsc_scaling())
vmcs_write64(TSC_MULTIPLIER,
vcpu->arch.tsc_scaling_ratio);
vmx->loaded_vmcs->cpu = cpu;
}
/* Setup TSC multiplier */
if (kvm_has_tsc_control &&
vmx->current_tsc_ratio != vcpu->arch.tsc_scaling_ratio) {
vmx->current_tsc_ratio = vcpu->arch.tsc_scaling_ratio;
vmcs_write64(TSC_MULTIPLIER, vmx->current_tsc_ratio);
}
vmx_vcpu_pi_load(vcpu, cpu);
}

View File

@ -6544,12 +6544,12 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
* KVM_DEBUGREG_WONT_EXIT again.
*/
if (unlikely(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT)) {
int i;
WARN_ON(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP);
kvm_x86_ops->sync_dirty_debug_regs(vcpu);
for (i = 0; i < KVM_NR_DB_REGS; i++)
vcpu->arch.eff_db[i] = vcpu->arch.db[i];
kvm_update_dr0123(vcpu);
kvm_update_dr6(vcpu);
kvm_update_dr7(vcpu);
vcpu->arch.switch_db_regs &= ~KVM_DEBUGREG_RELOAD;
}
/*

View File

@ -232,17 +232,31 @@ ENDPROC(copy_user_enhanced_fast_string)
/*
* copy_user_nocache - Uncached memory copy with exception handling
* This will force destination/source out of cache for more performance.
* This will force destination out of cache for more performance.
*
* Note: Cached memory copy is used when destination or size is not
* naturally aligned. That is:
* - Require 8-byte alignment when size is 8 bytes or larger.
* - Require 4-byte alignment when size is 4 bytes.
*/
ENTRY(__copy_user_nocache)
ASM_STAC
/* If size is less than 8 bytes, go to 4-byte copy */
cmpl $8,%edx
jb 20f /* less then 8 bytes, go to byte copy loop */
jb .L_4b_nocache_copy_entry
/* If destination is not 8-byte aligned, "cache" copy to align it */
ALIGN_DESTINATION
/* Set 4x8-byte copy count and remainder */
movl %edx,%ecx
andl $63,%edx
shrl $6,%ecx
jz 17f
jz .L_8b_nocache_copy_entry /* jump if count is 0 */
/* Perform 4x8-byte nocache loop-copy */
.L_4x8b_nocache_copy_loop:
1: movq (%rsi),%r8
2: movq 1*8(%rsi),%r9
3: movq 2*8(%rsi),%r10
@ -262,60 +276,106 @@ ENTRY(__copy_user_nocache)
leaq 64(%rsi),%rsi
leaq 64(%rdi),%rdi
decl %ecx
jnz 1b
17: movl %edx,%ecx
jnz .L_4x8b_nocache_copy_loop
/* Set 8-byte copy count and remainder */
.L_8b_nocache_copy_entry:
movl %edx,%ecx
andl $7,%edx
shrl $3,%ecx
jz 20f
18: movq (%rsi),%r8
19: movnti %r8,(%rdi)
jz .L_4b_nocache_copy_entry /* jump if count is 0 */
/* Perform 8-byte nocache loop-copy */
.L_8b_nocache_copy_loop:
20: movq (%rsi),%r8
21: movnti %r8,(%rdi)
leaq 8(%rsi),%rsi
leaq 8(%rdi),%rdi
decl %ecx
jnz 18b
20: andl %edx,%edx
jz 23f
jnz .L_8b_nocache_copy_loop
/* If no byte left, we're done */
.L_4b_nocache_copy_entry:
andl %edx,%edx
jz .L_finish_copy
/* If destination is not 4-byte aligned, go to byte copy: */
movl %edi,%ecx
andl $3,%ecx
jnz .L_1b_cache_copy_entry
/* Set 4-byte copy count (1 or 0) and remainder */
movl %edx,%ecx
21: movb (%rsi),%al
22: movb %al,(%rdi)
andl $3,%edx
shrl $2,%ecx
jz .L_1b_cache_copy_entry /* jump if count is 0 */
/* Perform 4-byte nocache copy: */
30: movl (%rsi),%r8d
31: movnti %r8d,(%rdi)
leaq 4(%rsi),%rsi
leaq 4(%rdi),%rdi
/* If no bytes left, we're done: */
andl %edx,%edx
jz .L_finish_copy
/* Perform byte "cache" loop-copy for the remainder */
.L_1b_cache_copy_entry:
movl %edx,%ecx
.L_1b_cache_copy_loop:
40: movb (%rsi),%al
41: movb %al,(%rdi)
incq %rsi
incq %rdi
decl %ecx
jnz 21b
23: xorl %eax,%eax
jnz .L_1b_cache_copy_loop
/* Finished copying; fence the prior stores */
.L_finish_copy:
xorl %eax,%eax
ASM_CLAC
sfence
ret
.section .fixup,"ax"
30: shll $6,%ecx
.L_fixup_4x8b_copy:
shll $6,%ecx
addl %ecx,%edx
jmp 60f
40: lea (%rdx,%rcx,8),%rdx
jmp 60f
50: movl %ecx,%edx
60: sfence
jmp .L_fixup_handle_tail
.L_fixup_8b_copy:
lea (%rdx,%rcx,8),%rdx
jmp .L_fixup_handle_tail
.L_fixup_4b_copy:
lea (%rdx,%rcx,4),%rdx
jmp .L_fixup_handle_tail
.L_fixup_1b_copy:
movl %ecx,%edx
.L_fixup_handle_tail:
sfence
jmp copy_user_handle_tail
.previous
_ASM_EXTABLE(1b,30b)
_ASM_EXTABLE(2b,30b)
_ASM_EXTABLE(3b,30b)
_ASM_EXTABLE(4b,30b)
_ASM_EXTABLE(5b,30b)
_ASM_EXTABLE(6b,30b)
_ASM_EXTABLE(7b,30b)
_ASM_EXTABLE(8b,30b)
_ASM_EXTABLE(9b,30b)
_ASM_EXTABLE(10b,30b)
_ASM_EXTABLE(11b,30b)
_ASM_EXTABLE(12b,30b)
_ASM_EXTABLE(13b,30b)
_ASM_EXTABLE(14b,30b)
_ASM_EXTABLE(15b,30b)
_ASM_EXTABLE(16b,30b)
_ASM_EXTABLE(18b,40b)
_ASM_EXTABLE(19b,40b)
_ASM_EXTABLE(21b,50b)
_ASM_EXTABLE(22b,50b)
_ASM_EXTABLE(1b,.L_fixup_4x8b_copy)
_ASM_EXTABLE(2b,.L_fixup_4x8b_copy)
_ASM_EXTABLE(3b,.L_fixup_4x8b_copy)
_ASM_EXTABLE(4b,.L_fixup_4x8b_copy)
_ASM_EXTABLE(5b,.L_fixup_4x8b_copy)
_ASM_EXTABLE(6b,.L_fixup_4x8b_copy)
_ASM_EXTABLE(7b,.L_fixup_4x8b_copy)
_ASM_EXTABLE(8b,.L_fixup_4x8b_copy)
_ASM_EXTABLE(9b,.L_fixup_4x8b_copy)
_ASM_EXTABLE(10b,.L_fixup_4x8b_copy)
_ASM_EXTABLE(11b,.L_fixup_4x8b_copy)
_ASM_EXTABLE(12b,.L_fixup_4x8b_copy)
_ASM_EXTABLE(13b,.L_fixup_4x8b_copy)
_ASM_EXTABLE(14b,.L_fixup_4x8b_copy)
_ASM_EXTABLE(15b,.L_fixup_4x8b_copy)
_ASM_EXTABLE(16b,.L_fixup_4x8b_copy)
_ASM_EXTABLE(20b,.L_fixup_8b_copy)
_ASM_EXTABLE(21b,.L_fixup_8b_copy)
_ASM_EXTABLE(30b,.L_fixup_4b_copy)
_ASM_EXTABLE(31b,.L_fixup_4b_copy)
_ASM_EXTABLE(40b,.L_fixup_1b_copy)
_ASM_EXTABLE(41b,.L_fixup_1b_copy)
ENDPROC(__copy_user_nocache)

View File

@ -287,6 +287,9 @@ static noinline int vmalloc_fault(unsigned long address)
if (!pmd_k)
return -1;
if (pmd_huge(*pmd_k))
return 0;
pte_k = pte_offset_kernel(pmd_k, address);
if (!pte_present(*pte_k))
return -1;
@ -360,8 +363,6 @@ void vmalloc_sync_all(void)
* 64-bit:
*
* Handle a fault on the vmalloc area
*
* This assumes no large pages in there.
*/
static noinline int vmalloc_fault(unsigned long address)
{
@ -403,17 +404,23 @@ static noinline int vmalloc_fault(unsigned long address)
if (pud_none(*pud_ref))
return -1;
if (pud_none(*pud) || pud_page_vaddr(*pud) != pud_page_vaddr(*pud_ref))
if (pud_none(*pud) || pud_pfn(*pud) != pud_pfn(*pud_ref))
BUG();
if (pud_huge(*pud))
return 0;
pmd = pmd_offset(pud, address);
pmd_ref = pmd_offset(pud_ref, address);
if (pmd_none(*pmd_ref))
return -1;
if (pmd_none(*pmd) || pmd_page(*pmd) != pmd_page(*pmd_ref))
if (pmd_none(*pmd) || pmd_pfn(*pmd) != pmd_pfn(*pmd_ref))
BUG();
if (pmd_huge(*pmd))
return 0;
pte_ref = pte_offset_kernel(pmd_ref, address);
if (!pte_present(*pte_ref))
return -1;

View File

@ -123,7 +123,7 @@ static int get_reg_offset(struct insn *insn, struct pt_regs *regs,
break;
}
if (regno > nr_registers) {
if (regno >= nr_registers) {
WARN_ONCE(1, "decoded an instruction with an invalid register");
return -EINVAL;
}

View File

@ -33,7 +33,7 @@ struct cpa_data {
pgd_t *pgd;
pgprot_t mask_set;
pgprot_t mask_clr;
int numpages;
unsigned long numpages;
int flags;
unsigned long pfn;
unsigned force_split : 1;
@ -1345,7 +1345,7 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias)
* CPA operation. Either a large page has been
* preserved or a single page update happened.
*/
BUG_ON(cpa->numpages > numpages);
BUG_ON(cpa->numpages > numpages || !cpa->numpages);
numpages -= cpa->numpages;
if (cpa->flags & (CPA_PAGES_ARRAY | CPA_ARRAY))
cpa->curpage++;

View File

@ -1090,9 +1090,12 @@ int bio_uncopy_user(struct bio *bio)
if (!bio_flagged(bio, BIO_NULL_MAPPED)) {
/*
* if we're in a workqueue, the request is orphaned, so
* don't copy into a random user address space, just free.
* don't copy into a random user address space, just free
* and return -EINTR so user space doesn't expect any data.
*/
if (current->mm && bio_data_dir(bio) == READ)
if (!current->mm)
ret = -EINTR;
else if (bio_data_dir(bio) == READ)
ret = bio_copy_to_iter(bio, bmd->iter);
if (bmd->is_our_pages)
bio_free_pages(bio);

View File

@ -68,6 +68,18 @@ static struct bio *blk_bio_write_same_split(struct request_queue *q,
return bio_split(bio, q->limits.max_write_same_sectors, GFP_NOIO, bs);
}
static inline unsigned get_max_io_size(struct request_queue *q,
struct bio *bio)
{
unsigned sectors = blk_max_size_offset(q, bio->bi_iter.bi_sector);
unsigned mask = queue_logical_block_size(q) - 1;
/* aligned to logical block size */
sectors &= ~(mask >> 9);
return sectors;
}
static struct bio *blk_bio_segment_split(struct request_queue *q,
struct bio *bio,
struct bio_set *bs,
@ -79,11 +91,9 @@ static struct bio *blk_bio_segment_split(struct request_queue *q,
unsigned front_seg_size = bio->bi_seg_front_size;
bool do_split = true;
struct bio *new = NULL;
const unsigned max_sectors = get_max_io_size(q, bio);
bio_for_each_segment(bv, bio, iter) {
if (sectors + (bv.bv_len >> 9) > queue_max_sectors(q))
goto split;
/*
* If the queue doesn't support SG gaps and adding this
* offset would create a gap, disallow it.
@ -91,6 +101,21 @@ static struct bio *blk_bio_segment_split(struct request_queue *q,
if (bvprvp && bvec_gap_to_prev(q, bvprvp, bv.bv_offset))
goto split;
if (sectors + (bv.bv_len >> 9) > max_sectors) {
/*
* Consider this a new segment if we're splitting in
* the middle of this vector.
*/
if (nsegs < queue_max_segments(q) &&
sectors < max_sectors) {
nsegs++;
sectors = max_sectors;
}
if (sectors)
goto split;
/* Make this single bvec as the 1st segment */
}
if (bvprvp && blk_queue_cluster(q)) {
if (seg_size + bv.bv_len > queue_max_segment_size(q))
goto new_segment;

View File

@ -91,8 +91,8 @@ void blk_set_default_limits(struct queue_limits *lim)
lim->seg_boundary_mask = BLK_SEG_BOUNDARY_MASK;
lim->virt_boundary_mask = 0;
lim->max_segment_size = BLK_MAX_SEGMENT_SIZE;
lim->max_sectors = lim->max_dev_sectors = lim->max_hw_sectors =
BLK_SAFE_MAX_SECTORS;
lim->max_sectors = lim->max_hw_sectors = BLK_SAFE_MAX_SECTORS;
lim->max_dev_sectors = 0;
lim->chunk_sectors = 0;
lim->max_write_same_sectors = 0;
lim->max_discard_sectors = 0;

View File

@ -76,6 +76,8 @@ int af_alg_register_type(const struct af_alg_type *type)
goto unlock;
type->ops->owner = THIS_MODULE;
if (type->ops_nokey)
type->ops_nokey->owner = THIS_MODULE;
node->type = type;
list_add(&node->list, &alg_types);
err = 0;
@ -125,6 +127,26 @@ int af_alg_release(struct socket *sock)
}
EXPORT_SYMBOL_GPL(af_alg_release);
void af_alg_release_parent(struct sock *sk)
{
struct alg_sock *ask = alg_sk(sk);
unsigned int nokey = ask->nokey_refcnt;
bool last = nokey && !ask->refcnt;
sk = ask->parent;
ask = alg_sk(sk);
lock_sock(sk);
ask->nokey_refcnt -= nokey;
if (!last)
last = !--ask->refcnt;
release_sock(sk);
if (last)
sock_put(sk);
}
EXPORT_SYMBOL_GPL(af_alg_release_parent);
static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
const u32 forbidden = CRYPTO_ALG_INTERNAL;
@ -133,6 +155,7 @@ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
struct sockaddr_alg *sa = (void *)uaddr;
const struct af_alg_type *type;
void *private;
int err;
if (sock->state == SS_CONNECTED)
return -EINVAL;
@ -160,16 +183,22 @@ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
return PTR_ERR(private);
}
err = -EBUSY;
lock_sock(sk);
if (ask->refcnt | ask->nokey_refcnt)
goto unlock;
swap(ask->type, type);
swap(ask->private, private);
err = 0;
unlock:
release_sock(sk);
alg_do_release(type, private);
return 0;
return err;
}
static int alg_setkey(struct sock *sk, char __user *ukey,
@ -202,11 +231,15 @@ static int alg_setsockopt(struct socket *sock, int level, int optname,
struct sock *sk = sock->sk;
struct alg_sock *ask = alg_sk(sk);
const struct af_alg_type *type;
int err = -ENOPROTOOPT;
int err = -EBUSY;
lock_sock(sk);
if (ask->refcnt)
goto unlock;
type = ask->type;
err = -ENOPROTOOPT;
if (level != SOL_ALG || !type)
goto unlock;
@ -238,6 +271,7 @@ int af_alg_accept(struct sock *sk, struct socket *newsock)
struct alg_sock *ask = alg_sk(sk);
const struct af_alg_type *type;
struct sock *sk2;
unsigned int nokey;
int err;
lock_sock(sk);
@ -257,20 +291,29 @@ int af_alg_accept(struct sock *sk, struct socket *newsock)
security_sk_clone(sk, sk2);
err = type->accept(ask->private, sk2);
if (err) {
sk_free(sk2);
nokey = err == -ENOKEY;
if (nokey && type->accept_nokey)
err = type->accept_nokey(ask->private, sk2);
if (err)
goto unlock;
}
sk2->sk_family = PF_ALG;
sock_hold(sk);
if (nokey || !ask->refcnt++)
sock_hold(sk);
ask->nokey_refcnt += nokey;
alg_sk(sk2)->parent = sk;
alg_sk(sk2)->type = type;
alg_sk(sk2)->nokey_refcnt = nokey;
newsock->ops = type->ops;
newsock->state = SS_CONNECTED;
if (nokey)
newsock->ops = type->ops_nokey;
err = 0;
unlock:

View File

@ -451,6 +451,7 @@ static int crypto_ahash_init_tfm(struct crypto_tfm *tfm)
struct ahash_alg *alg = crypto_ahash_alg(hash);
hash->setkey = ahash_nosetkey;
hash->has_setkey = false;
hash->export = ahash_no_export;
hash->import = ahash_no_import;
@ -463,8 +464,10 @@ static int crypto_ahash_init_tfm(struct crypto_tfm *tfm)
hash->finup = alg->finup ?: ahash_def_finup;
hash->digest = alg->digest;
if (alg->setkey)
if (alg->setkey) {
hash->setkey = alg->setkey;
hash->has_setkey = true;
}
if (alg->export)
hash->export = alg->export;
if (alg->import)

View File

@ -34,6 +34,11 @@ struct hash_ctx {
struct ahash_request req;
};
struct algif_hash_tfm {
struct crypto_ahash *hash;
bool has_key;
};
static int hash_sendmsg(struct socket *sock, struct msghdr *msg,
size_t ignored)
{
@ -49,7 +54,8 @@ static int hash_sendmsg(struct socket *sock, struct msghdr *msg,
lock_sock(sk);
if (!ctx->more) {
err = crypto_ahash_init(&ctx->req);
err = af_alg_wait_for_completion(crypto_ahash_init(&ctx->req),
&ctx->completion);
if (err)
goto unlock;
}
@ -120,6 +126,7 @@ static ssize_t hash_sendpage(struct socket *sock, struct page *page,
} else {
if (!ctx->more) {
err = crypto_ahash_init(&ctx->req);
err = af_alg_wait_for_completion(err, &ctx->completion);
if (err)
goto unlock;
}
@ -235,19 +242,151 @@ static struct proto_ops algif_hash_ops = {
.accept = hash_accept,
};
static int hash_check_key(struct socket *sock)
{
int err = 0;
struct sock *psk;
struct alg_sock *pask;
struct algif_hash_tfm *tfm;
struct sock *sk = sock->sk;
struct alg_sock *ask = alg_sk(sk);
lock_sock(sk);
if (ask->refcnt)
goto unlock_child;
psk = ask->parent;
pask = alg_sk(ask->parent);
tfm = pask->private;
err = -ENOKEY;
lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
if (!tfm->has_key)
goto unlock;
if (!pask->refcnt++)
sock_hold(psk);
ask->refcnt = 1;
sock_put(psk);
err = 0;
unlock:
release_sock(psk);
unlock_child:
release_sock(sk);
return err;
}
static int hash_sendmsg_nokey(struct socket *sock, struct msghdr *msg,
size_t size)
{
int err;
err = hash_check_key(sock);
if (err)
return err;
return hash_sendmsg(sock, msg, size);
}
static ssize_t hash_sendpage_nokey(struct socket *sock, struct page *page,
int offset, size_t size, int flags)
{
int err;
err = hash_check_key(sock);
if (err)
return err;
return hash_sendpage(sock, page, offset, size, flags);
}
static int hash_recvmsg_nokey(struct socket *sock, struct msghdr *msg,
size_t ignored, int flags)
{
int err;
err = hash_check_key(sock);
if (err)
return err;
return hash_recvmsg(sock, msg, ignored, flags);
}
static int hash_accept_nokey(struct socket *sock, struct socket *newsock,
int flags)
{
int err;
err = hash_check_key(sock);
if (err)
return err;
return hash_accept(sock, newsock, flags);
}
static struct proto_ops algif_hash_ops_nokey = {
.family = PF_ALG,
.connect = sock_no_connect,
.socketpair = sock_no_socketpair,
.getname = sock_no_getname,
.ioctl = sock_no_ioctl,
.listen = sock_no_listen,
.shutdown = sock_no_shutdown,
.getsockopt = sock_no_getsockopt,
.mmap = sock_no_mmap,
.bind = sock_no_bind,
.setsockopt = sock_no_setsockopt,
.poll = sock_no_poll,
.release = af_alg_release,
.sendmsg = hash_sendmsg_nokey,
.sendpage = hash_sendpage_nokey,
.recvmsg = hash_recvmsg_nokey,
.accept = hash_accept_nokey,
};
static void *hash_bind(const char *name, u32 type, u32 mask)
{
return crypto_alloc_ahash(name, type, mask);
struct algif_hash_tfm *tfm;
struct crypto_ahash *hash;
tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
if (!tfm)
return ERR_PTR(-ENOMEM);
hash = crypto_alloc_ahash(name, type, mask);
if (IS_ERR(hash)) {
kfree(tfm);
return ERR_CAST(hash);
}
tfm->hash = hash;
return tfm;
}
static void hash_release(void *private)
{
crypto_free_ahash(private);
struct algif_hash_tfm *tfm = private;
crypto_free_ahash(tfm->hash);
kfree(tfm);
}
static int hash_setkey(void *private, const u8 *key, unsigned int keylen)
{
return crypto_ahash_setkey(private, key, keylen);
struct algif_hash_tfm *tfm = private;
int err;
err = crypto_ahash_setkey(tfm->hash, key, keylen);
tfm->has_key = !err;
return err;
}
static void hash_sock_destruct(struct sock *sk)
@ -261,12 +400,14 @@ static void hash_sock_destruct(struct sock *sk)
af_alg_release_parent(sk);
}
static int hash_accept_parent(void *private, struct sock *sk)
static int hash_accept_parent_nokey(void *private, struct sock *sk)
{
struct hash_ctx *ctx;
struct alg_sock *ask = alg_sk(sk);
unsigned len = sizeof(*ctx) + crypto_ahash_reqsize(private);
unsigned ds = crypto_ahash_digestsize(private);
struct algif_hash_tfm *tfm = private;
struct crypto_ahash *hash = tfm->hash;
unsigned len = sizeof(*ctx) + crypto_ahash_reqsize(hash);
unsigned ds = crypto_ahash_digestsize(hash);
ctx = sock_kmalloc(sk, len, GFP_KERNEL);
if (!ctx)
@ -286,7 +427,7 @@ static int hash_accept_parent(void *private, struct sock *sk)
ask->private = ctx;
ahash_request_set_tfm(&ctx->req, private);
ahash_request_set_tfm(&ctx->req, hash);
ahash_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
af_alg_complete, &ctx->completion);
@ -295,12 +436,24 @@ static int hash_accept_parent(void *private, struct sock *sk)
return 0;
}
static int hash_accept_parent(void *private, struct sock *sk)
{
struct algif_hash_tfm *tfm = private;
if (!tfm->has_key && crypto_ahash_has_setkey(tfm->hash))
return -ENOKEY;
return hash_accept_parent_nokey(private, sk);
}
static const struct af_alg_type algif_type_hash = {
.bind = hash_bind,
.release = hash_release,
.setkey = hash_setkey,
.accept = hash_accept_parent,
.accept_nokey = hash_accept_parent_nokey,
.ops = &algif_hash_ops,
.ops_nokey = &algif_hash_ops_nokey,
.name = "hash",
.owner = THIS_MODULE
};

View File

@ -31,6 +31,11 @@ struct skcipher_sg_list {
struct scatterlist sg[0];
};
struct skcipher_tfm {
struct crypto_skcipher *skcipher;
bool has_key;
};
struct skcipher_ctx {
struct list_head tsgl;
struct af_alg_sgl rsgl;
@ -60,18 +65,10 @@ struct skcipher_async_req {
struct skcipher_async_rsgl first_sgl;
struct list_head list;
struct scatterlist *tsg;
char iv[];
atomic_t *inflight;
struct skcipher_request req;
};
#define GET_SREQ(areq, ctx) (struct skcipher_async_req *)((char *)areq + \
crypto_skcipher_reqsize(crypto_skcipher_reqtfm(&ctx->req)))
#define GET_REQ_SIZE(ctx) \
crypto_skcipher_reqsize(crypto_skcipher_reqtfm(&ctx->req))
#define GET_IV_SIZE(ctx) \
crypto_skcipher_ivsize(crypto_skcipher_reqtfm(&ctx->req))
#define MAX_SGL_ENTS ((4096 - sizeof(struct skcipher_sg_list)) / \
sizeof(struct scatterlist) - 1)
@ -97,15 +94,12 @@ static void skcipher_free_async_sgls(struct skcipher_async_req *sreq)
static void skcipher_async_cb(struct crypto_async_request *req, int err)
{
struct sock *sk = req->data;
struct alg_sock *ask = alg_sk(sk);
struct skcipher_ctx *ctx = ask->private;
struct skcipher_async_req *sreq = GET_SREQ(req, ctx);
struct skcipher_async_req *sreq = req->data;
struct kiocb *iocb = sreq->iocb;
atomic_dec(&ctx->inflight);
atomic_dec(sreq->inflight);
skcipher_free_async_sgls(sreq);
kfree(req);
kzfree(sreq);
iocb->ki_complete(iocb, err, err);
}
@ -301,8 +295,11 @@ static int skcipher_sendmsg(struct socket *sock, struct msghdr *msg,
{
struct sock *sk = sock->sk;
struct alg_sock *ask = alg_sk(sk);
struct sock *psk = ask->parent;
struct alg_sock *pask = alg_sk(psk);
struct skcipher_ctx *ctx = ask->private;
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(&ctx->req);
struct skcipher_tfm *skc = pask->private;
struct crypto_skcipher *tfm = skc->skcipher;
unsigned ivsize = crypto_skcipher_ivsize(tfm);
struct skcipher_sg_list *sgl;
struct af_alg_control con = {};
@ -387,7 +384,8 @@ static int skcipher_sendmsg(struct socket *sock, struct msghdr *msg,
sgl = list_entry(ctx->tsgl.prev, struct skcipher_sg_list, list);
sg = sgl->sg;
sg_unmark_end(sg + sgl->cur);
if (sgl->cur)
sg_unmark_end(sg + sgl->cur - 1);
do {
i = sgl->cur;
plen = min_t(int, len, PAGE_SIZE);
@ -503,37 +501,43 @@ static int skcipher_recvmsg_async(struct socket *sock, struct msghdr *msg,
{
struct sock *sk = sock->sk;
struct alg_sock *ask = alg_sk(sk);
struct sock *psk = ask->parent;
struct alg_sock *pask = alg_sk(psk);
struct skcipher_ctx *ctx = ask->private;
struct skcipher_tfm *skc = pask->private;
struct crypto_skcipher *tfm = skc->skcipher;
struct skcipher_sg_list *sgl;
struct scatterlist *sg;
struct skcipher_async_req *sreq;
struct skcipher_request *req;
struct skcipher_async_rsgl *last_rsgl = NULL;
unsigned int txbufs = 0, len = 0, tx_nents = skcipher_all_sg_nents(ctx);
unsigned int reqlen = sizeof(struct skcipher_async_req) +
GET_REQ_SIZE(ctx) + GET_IV_SIZE(ctx);
unsigned int txbufs = 0, len = 0, tx_nents;
unsigned int reqsize = crypto_skcipher_reqsize(tfm);
unsigned int ivsize = crypto_skcipher_ivsize(tfm);
int err = -ENOMEM;
bool mark = false;
char *iv;
sreq = kzalloc(sizeof(*sreq) + reqsize + ivsize, GFP_KERNEL);
if (unlikely(!sreq))
goto out;
req = &sreq->req;
iv = (char *)(req + 1) + reqsize;
sreq->iocb = msg->msg_iocb;
INIT_LIST_HEAD(&sreq->list);
sreq->inflight = &ctx->inflight;
lock_sock(sk);
req = kmalloc(reqlen, GFP_KERNEL);
if (unlikely(!req))
goto unlock;
sreq = GET_SREQ(req, ctx);
sreq->iocb = msg->msg_iocb;
memset(&sreq->first_sgl, '\0', sizeof(struct skcipher_async_rsgl));
INIT_LIST_HEAD(&sreq->list);
tx_nents = skcipher_all_sg_nents(ctx);
sreq->tsg = kcalloc(tx_nents, sizeof(*sg), GFP_KERNEL);
if (unlikely(!sreq->tsg)) {
kfree(req);
if (unlikely(!sreq->tsg))
goto unlock;
}
sg_init_table(sreq->tsg, tx_nents);
memcpy(sreq->iv, ctx->iv, GET_IV_SIZE(ctx));
skcipher_request_set_tfm(req, crypto_skcipher_reqtfm(&ctx->req));
skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
skcipher_async_cb, sk);
memcpy(iv, ctx->iv, ivsize);
skcipher_request_set_tfm(req, tfm);
skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP,
skcipher_async_cb, sreq);
while (iov_iter_count(&msg->msg_iter)) {
struct skcipher_async_rsgl *rsgl;
@ -609,20 +613,22 @@ static int skcipher_recvmsg_async(struct socket *sock, struct msghdr *msg,
sg_mark_end(sreq->tsg + txbufs - 1);
skcipher_request_set_crypt(req, sreq->tsg, sreq->first_sgl.sgl.sg,
len, sreq->iv);
len, iv);
err = ctx->enc ? crypto_skcipher_encrypt(req) :
crypto_skcipher_decrypt(req);
if (err == -EINPROGRESS) {
atomic_inc(&ctx->inflight);
err = -EIOCBQUEUED;
sreq = NULL;
goto unlock;
}
free:
skcipher_free_async_sgls(sreq);
kfree(req);
unlock:
skcipher_wmem_wakeup(sk);
release_sock(sk);
kzfree(sreq);
out:
return err;
}
@ -631,9 +637,12 @@ static int skcipher_recvmsg_sync(struct socket *sock, struct msghdr *msg,
{
struct sock *sk = sock->sk;
struct alg_sock *ask = alg_sk(sk);
struct sock *psk = ask->parent;
struct alg_sock *pask = alg_sk(psk);
struct skcipher_ctx *ctx = ask->private;
unsigned bs = crypto_skcipher_blocksize(crypto_skcipher_reqtfm(
&ctx->req));
struct skcipher_tfm *skc = pask->private;
struct crypto_skcipher *tfm = skc->skcipher;
unsigned bs = crypto_skcipher_blocksize(tfm);
struct skcipher_sg_list *sgl;
struct scatterlist *sg;
int err = -EAGAIN;
@ -642,13 +651,6 @@ static int skcipher_recvmsg_sync(struct socket *sock, struct msghdr *msg,
lock_sock(sk);
while (msg_data_left(msg)) {
sgl = list_first_entry(&ctx->tsgl,
struct skcipher_sg_list, list);
sg = sgl->sg;
while (!sg->length)
sg++;
if (!ctx->used) {
err = skcipher_wait_for_data(sk, flags);
if (err)
@ -669,6 +671,13 @@ static int skcipher_recvmsg_sync(struct socket *sock, struct msghdr *msg,
if (!used)
goto free;
sgl = list_first_entry(&ctx->tsgl,
struct skcipher_sg_list, list);
sg = sgl->sg;
while (!sg->length)
sg++;
skcipher_request_set_crypt(&ctx->req, sg, ctx->rsgl.sg, used,
ctx->iv);
@ -748,19 +757,139 @@ static struct proto_ops algif_skcipher_ops = {
.poll = skcipher_poll,
};
static int skcipher_check_key(struct socket *sock)
{
int err = 0;
struct sock *psk;
struct alg_sock *pask;
struct skcipher_tfm *tfm;
struct sock *sk = sock->sk;
struct alg_sock *ask = alg_sk(sk);
lock_sock(sk);
if (ask->refcnt)
goto unlock_child;
psk = ask->parent;
pask = alg_sk(ask->parent);
tfm = pask->private;
err = -ENOKEY;
lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
if (!tfm->has_key)
goto unlock;
if (!pask->refcnt++)
sock_hold(psk);
ask->refcnt = 1;
sock_put(psk);
err = 0;
unlock:
release_sock(psk);
unlock_child:
release_sock(sk);
return err;
}
static int skcipher_sendmsg_nokey(struct socket *sock, struct msghdr *msg,
size_t size)
{
int err;
err = skcipher_check_key(sock);
if (err)
return err;
return skcipher_sendmsg(sock, msg, size);
}
static ssize_t skcipher_sendpage_nokey(struct socket *sock, struct page *page,
int offset, size_t size, int flags)
{
int err;
err = skcipher_check_key(sock);
if (err)
return err;
return skcipher_sendpage(sock, page, offset, size, flags);
}
static int skcipher_recvmsg_nokey(struct socket *sock, struct msghdr *msg,
size_t ignored, int flags)
{
int err;
err = skcipher_check_key(sock);
if (err)
return err;
return skcipher_recvmsg(sock, msg, ignored, flags);
}
static struct proto_ops algif_skcipher_ops_nokey = {
.family = PF_ALG,
.connect = sock_no_connect,
.socketpair = sock_no_socketpair,
.getname = sock_no_getname,
.ioctl = sock_no_ioctl,
.listen = sock_no_listen,
.shutdown = sock_no_shutdown,
.getsockopt = sock_no_getsockopt,
.mmap = sock_no_mmap,
.bind = sock_no_bind,
.accept = sock_no_accept,
.setsockopt = sock_no_setsockopt,
.release = af_alg_release,
.sendmsg = skcipher_sendmsg_nokey,
.sendpage = skcipher_sendpage_nokey,
.recvmsg = skcipher_recvmsg_nokey,
.poll = skcipher_poll,
};
static void *skcipher_bind(const char *name, u32 type, u32 mask)
{
return crypto_alloc_skcipher(name, type, mask);
struct skcipher_tfm *tfm;
struct crypto_skcipher *skcipher;
tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
if (!tfm)
return ERR_PTR(-ENOMEM);
skcipher = crypto_alloc_skcipher(name, type, mask);
if (IS_ERR(skcipher)) {
kfree(tfm);
return ERR_CAST(skcipher);
}
tfm->skcipher = skcipher;
return tfm;
}
static void skcipher_release(void *private)
{
crypto_free_skcipher(private);
struct skcipher_tfm *tfm = private;
crypto_free_skcipher(tfm->skcipher);
kfree(tfm);
}
static int skcipher_setkey(void *private, const u8 *key, unsigned int keylen)
{
return crypto_skcipher_setkey(private, key, keylen);
struct skcipher_tfm *tfm = private;
int err;
err = crypto_skcipher_setkey(tfm->skcipher, key, keylen);
tfm->has_key = !err;
return err;
}
static void skcipher_wait(struct sock *sk)
@ -788,24 +917,26 @@ static void skcipher_sock_destruct(struct sock *sk)
af_alg_release_parent(sk);
}
static int skcipher_accept_parent(void *private, struct sock *sk)
static int skcipher_accept_parent_nokey(void *private, struct sock *sk)
{
struct skcipher_ctx *ctx;
struct alg_sock *ask = alg_sk(sk);
unsigned int len = sizeof(*ctx) + crypto_skcipher_reqsize(private);
struct skcipher_tfm *tfm = private;
struct crypto_skcipher *skcipher = tfm->skcipher;
unsigned int len = sizeof(*ctx) + crypto_skcipher_reqsize(skcipher);
ctx = sock_kmalloc(sk, len, GFP_KERNEL);
if (!ctx)
return -ENOMEM;
ctx->iv = sock_kmalloc(sk, crypto_skcipher_ivsize(private),
ctx->iv = sock_kmalloc(sk, crypto_skcipher_ivsize(skcipher),
GFP_KERNEL);
if (!ctx->iv) {
sock_kfree_s(sk, ctx, len);
return -ENOMEM;
}
memset(ctx->iv, 0, crypto_skcipher_ivsize(private));
memset(ctx->iv, 0, crypto_skcipher_ivsize(skcipher));
INIT_LIST_HEAD(&ctx->tsgl);
ctx->len = len;
@ -818,8 +949,9 @@ static int skcipher_accept_parent(void *private, struct sock *sk)
ask->private = ctx;
skcipher_request_set_tfm(&ctx->req, private);
skcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
skcipher_request_set_tfm(&ctx->req, skcipher);
skcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_SLEEP |
CRYPTO_TFM_REQ_MAY_BACKLOG,
af_alg_complete, &ctx->completion);
sk->sk_destruct = skcipher_sock_destruct;
@ -827,12 +959,24 @@ static int skcipher_accept_parent(void *private, struct sock *sk)
return 0;
}
static int skcipher_accept_parent(void *private, struct sock *sk)
{
struct skcipher_tfm *tfm = private;
if (!tfm->has_key && crypto_skcipher_has_setkey(tfm->skcipher))
return -ENOKEY;
return skcipher_accept_parent_nokey(private, sk);
}
static const struct af_alg_type algif_type_skcipher = {
.bind = skcipher_bind,
.release = skcipher_release,
.setkey = skcipher_setkey,
.accept = skcipher_accept_parent,
.accept_nokey = skcipher_accept_parent_nokey,
.ops = &algif_skcipher_ops,
.ops_nokey = &algif_skcipher_ops_nokey,
.name = "skcipher",
.owner = THIS_MODULE
};

View File

@ -172,4 +172,3 @@ MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations wrapper for lib/crc32c");
MODULE_LICENSE("GPL");
MODULE_ALIAS_CRYPTO("crc32c");
MODULE_ALIAS_CRYPTO("crc32c-generic");
MODULE_SOFTDEP("pre: crc32c");

View File

@ -499,6 +499,7 @@ static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
if (link->dump == NULL)
return -EINVAL;
down_read(&crypto_alg_sem);
list_for_each_entry(alg, &crypto_alg_list, cra_list)
dump_alloc += CRYPTO_REPORT_MAXSIZE;
@ -508,8 +509,11 @@ static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
.done = link->done,
.min_dump_alloc = dump_alloc,
};
return netlink_dump_start(crypto_nlsk, skb, nlh, &c);
err = netlink_dump_start(crypto_nlsk, skb, nlh, &c);
}
up_read(&crypto_alg_sem);
return err;
}
err = nlmsg_parse(nlh, crypto_msg_min[type], attrs, CRYPTOCFGA_MAX,

View File

@ -354,9 +354,10 @@ int crypto_init_shash_ops_async(struct crypto_tfm *tfm)
crt->final = shash_async_final;
crt->finup = shash_async_finup;
crt->digest = shash_async_digest;
crt->setkey = shash_async_setkey;
crt->has_setkey = alg->setkey != shash_no_setkey;
if (alg->setkey)
crt->setkey = shash_async_setkey;
if (alg->export)
crt->export = shash_async_export;
if (alg->import)

View File

@ -118,6 +118,7 @@ static int crypto_init_skcipher_ops_blkcipher(struct crypto_tfm *tfm)
skcipher->decrypt = skcipher_decrypt_blkcipher;
skcipher->ivsize = crypto_blkcipher_ivsize(blkcipher);
skcipher->has_setkey = calg->cra_blkcipher.max_keysize;
return 0;
}
@ -210,6 +211,7 @@ static int crypto_init_skcipher_ops_ablkcipher(struct crypto_tfm *tfm)
skcipher->ivsize = crypto_ablkcipher_ivsize(ablkcipher);
skcipher->reqsize = crypto_ablkcipher_reqsize(ablkcipher) +
sizeof(struct ablkcipher_request);
skcipher->has_setkey = calg->cra_ablkcipher.max_keysize;
return 0;
}

View File

@ -464,6 +464,15 @@ static struct dmi_system_id video_dmi_table[] = {
* control on these systems, but do not register a backlight sysfs
* as brightness control does not work.
*/
{
/* https://bugzilla.kernel.org/show_bug.cgi?id=21012 */
.callback = video_disable_backlight_sysfs_if,
.ident = "Toshiba Portege R700",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE R700"),
},
},
{
/* https://bugs.freedesktop.org/show_bug.cgi?id=82634 */
.callback = video_disable_backlight_sysfs_if,
@ -473,6 +482,15 @@ static struct dmi_system_id video_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE R830"),
},
},
{
/* https://bugzilla.kernel.org/show_bug.cgi?id=21012 */
.callback = video_disable_backlight_sysfs_if,
.ident = "Toshiba Satellite R830",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE R830"),
},
},
/*
* Some machine's _DOD IDs don't have bit 31(Device ID Scheme) set
* but the IDs actually follow the Device ID Scheme.

View File

@ -468,37 +468,16 @@ static void nfit_mem_find_spa_bdw(struct acpi_nfit_desc *acpi_desc,
nfit_mem->bdw = NULL;
}
static int nfit_mem_add(struct acpi_nfit_desc *acpi_desc,
static void nfit_mem_init_bdw(struct acpi_nfit_desc *acpi_desc,
struct nfit_mem *nfit_mem, struct acpi_nfit_system_address *spa)
{
u16 dcr = __to_nfit_memdev(nfit_mem)->region_index;
struct nfit_memdev *nfit_memdev;
struct nfit_flush *nfit_flush;
struct nfit_dcr *nfit_dcr;
struct nfit_bdw *nfit_bdw;
struct nfit_idt *nfit_idt;
u16 idt_idx, range_index;
list_for_each_entry(nfit_dcr, &acpi_desc->dcrs, list) {
if (nfit_dcr->dcr->region_index != dcr)
continue;
nfit_mem->dcr = nfit_dcr->dcr;
break;
}
if (!nfit_mem->dcr) {
dev_dbg(acpi_desc->dev, "SPA %d missing:%s%s\n",
spa->range_index, __to_nfit_memdev(nfit_mem)
? "" : " MEMDEV", nfit_mem->dcr ? "" : " DCR");
return -ENODEV;
}
/*
* We've found enough to create an nvdimm, optionally
* find an associated BDW
*/
list_add(&nfit_mem->list, &acpi_desc->dimms);
list_for_each_entry(nfit_bdw, &acpi_desc->bdws, list) {
if (nfit_bdw->bdw->region_index != dcr)
continue;
@ -507,12 +486,12 @@ static int nfit_mem_add(struct acpi_nfit_desc *acpi_desc,
}
if (!nfit_mem->bdw)
return 0;
return;
nfit_mem_find_spa_bdw(acpi_desc, nfit_mem);
if (!nfit_mem->spa_bdw)
return 0;
return;
range_index = nfit_mem->spa_bdw->range_index;
list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) {
@ -537,8 +516,6 @@ static int nfit_mem_add(struct acpi_nfit_desc *acpi_desc,
}
break;
}
return 0;
}
static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc,
@ -547,7 +524,6 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc,
struct nfit_mem *nfit_mem, *found;
struct nfit_memdev *nfit_memdev;
int type = nfit_spa_type(spa);
u16 dcr;
switch (type) {
case NFIT_SPA_DCR:
@ -558,14 +534,18 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc,
}
list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) {
int rc;
struct nfit_dcr *nfit_dcr;
u32 device_handle;
u16 dcr;
if (nfit_memdev->memdev->range_index != spa->range_index)
continue;
found = NULL;
dcr = nfit_memdev->memdev->region_index;
device_handle = nfit_memdev->memdev->device_handle;
list_for_each_entry(nfit_mem, &acpi_desc->dimms, list)
if (__to_nfit_memdev(nfit_mem)->region_index == dcr) {
if (__to_nfit_memdev(nfit_mem)->device_handle
== device_handle) {
found = nfit_mem;
break;
}
@ -578,6 +558,31 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc,
if (!nfit_mem)
return -ENOMEM;
INIT_LIST_HEAD(&nfit_mem->list);
list_add(&nfit_mem->list, &acpi_desc->dimms);
}
list_for_each_entry(nfit_dcr, &acpi_desc->dcrs, list) {
if (nfit_dcr->dcr->region_index != dcr)
continue;
/*
* Record the control region for the dimm. For
* the ACPI 6.1 case, where there are separate
* control regions for the pmem vs blk
* interfaces, be sure to record the extended
* blk details.
*/
if (!nfit_mem->dcr)
nfit_mem->dcr = nfit_dcr->dcr;
else if (nfit_mem->dcr->windows == 0
&& nfit_dcr->dcr->windows)
nfit_mem->dcr = nfit_dcr->dcr;
break;
}
if (dcr && !nfit_mem->dcr) {
dev_err(acpi_desc->dev, "SPA %d missing DCR %d\n",
spa->range_index, dcr);
return -ENODEV;
}
if (type == NFIT_SPA_DCR) {
@ -594,6 +599,7 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc,
nfit_mem->idt_dcr = nfit_idt->idt;
break;
}
nfit_mem_init_bdw(acpi_desc, nfit_mem, spa);
} else {
/*
* A single dimm may belong to multiple SPA-PM
@ -602,13 +608,6 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc,
*/
nfit_mem->memdev_pmem = nfit_memdev->memdev;
}
if (found)
continue;
rc = nfit_mem_add(acpi_desc, nfit_mem, spa);
if (rc)
return rc;
}
return 0;

View File

@ -135,14 +135,6 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"),
},
},
{
.callback = video_detect_force_vendor,
.ident = "Dell Inspiron 5737",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5737"),
},
},
/*
* These models have a working acpi_video backlight control, and using

View File

@ -2074,7 +2074,7 @@ static int binder_thread_write(struct binder_proc *proc,
if (get_user(cookie, (binder_uintptr_t __user *)ptr))
return -EFAULT;
ptr += sizeof(void *);
ptr += sizeof(cookie);
list_for_each_entry(w, &proc->delivered_death, entry) {
struct binder_ref_death *tmp_death = container_of(w, struct binder_ref_death, work);

View File

@ -264,6 +264,26 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
{ PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
{ PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
{ PCI_VDEVICE(INTEL, 0x19b0), board_ahci }, /* DNV AHCI */
{ PCI_VDEVICE(INTEL, 0x19b1), board_ahci }, /* DNV AHCI */
{ PCI_VDEVICE(INTEL, 0x19b2), board_ahci }, /* DNV AHCI */
{ PCI_VDEVICE(INTEL, 0x19b3), board_ahci }, /* DNV AHCI */
{ PCI_VDEVICE(INTEL, 0x19b4), board_ahci }, /* DNV AHCI */
{ PCI_VDEVICE(INTEL, 0x19b5), board_ahci }, /* DNV AHCI */
{ PCI_VDEVICE(INTEL, 0x19b6), board_ahci }, /* DNV AHCI */
{ PCI_VDEVICE(INTEL, 0x19b7), board_ahci }, /* DNV AHCI */
{ PCI_VDEVICE(INTEL, 0x19bE), board_ahci }, /* DNV AHCI */
{ PCI_VDEVICE(INTEL, 0x19bF), board_ahci }, /* DNV AHCI */
{ PCI_VDEVICE(INTEL, 0x19c0), board_ahci }, /* DNV AHCI */
{ PCI_VDEVICE(INTEL, 0x19c1), board_ahci }, /* DNV AHCI */
{ PCI_VDEVICE(INTEL, 0x19c2), board_ahci }, /* DNV AHCI */
{ PCI_VDEVICE(INTEL, 0x19c3), board_ahci }, /* DNV AHCI */
{ PCI_VDEVICE(INTEL, 0x19c4), board_ahci }, /* DNV AHCI */
{ PCI_VDEVICE(INTEL, 0x19c5), board_ahci }, /* DNV AHCI */
{ PCI_VDEVICE(INTEL, 0x19c6), board_ahci }, /* DNV AHCI */
{ PCI_VDEVICE(INTEL, 0x19c7), board_ahci }, /* DNV AHCI */
{ PCI_VDEVICE(INTEL, 0x19cE), board_ahci }, /* DNV AHCI */
{ PCI_VDEVICE(INTEL, 0x19cF), board_ahci }, /* DNV AHCI */
{ PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */
{ PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */
{ PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */
@ -347,15 +367,21 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H RAID */
{ PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */
{ PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Lewisburg AHCI*/
{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0xa182), board_ahci }, /* Lewisburg AHCI*/
{ PCI_VDEVICE(INTEL, 0xa184), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0xa186), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0xa18e), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0xa1d2), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0xa1d6), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0xa202), board_ahci }, /* Lewisburg AHCI*/
{ PCI_VDEVICE(INTEL, 0xa204), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0xa20e), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/
/* JMicron 360/1/3/5/6, match class to avoid IDE function */
{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,

View File

@ -495,8 +495,8 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
}
}
/* fabricate port_map from cap.nr_ports */
if (!port_map) {
/* fabricate port_map from cap.nr_ports for < AHCI 1.3 */
if (!port_map && vers < 0x10300) {
port_map = (1 << ahci_nr_ports(cap)) - 1;
dev_warn(dev, "forcing PORTS_IMPL to 0x%x\n", port_map);
@ -1142,8 +1142,7 @@ static void ahci_port_init(struct device *dev, struct ata_port *ap,
/* mark esata ports */
tmp = readl(port_mmio + PORT_CMD);
if ((tmp & PORT_CMD_HPCP) ||
((tmp & PORT_CMD_ESP) && (hpriv->cap & HOST_CAP_SXS)))
if ((tmp & PORT_CMD_ESP) && (hpriv->cap & HOST_CAP_SXS))
ap->pflags |= ATA_PFLAG_EXTERNAL;
}

View File

@ -675,19 +675,18 @@ static int ata_ioc32(struct ata_port *ap)
int ata_sas_scsi_ioctl(struct ata_port *ap, struct scsi_device *scsidev,
int cmd, void __user *arg)
{
int val = -EINVAL, rc = -EINVAL;
unsigned long val;
int rc = -EINVAL;
unsigned long flags;
switch (cmd) {
case ATA_IOC_GET_IO32:
case HDIO_GET_32BIT:
spin_lock_irqsave(ap->lock, flags);
val = ata_ioc32(ap);
spin_unlock_irqrestore(ap->lock, flags);
if (copy_to_user(arg, &val, 1))
return -EFAULT;
return 0;
return put_user(val, (unsigned long __user *)arg);
case ATA_IOC_SET_IO32:
case HDIO_SET_32BIT:
val = (unsigned long) arg;
rc = 0;
spin_lock_irqsave(ap->lock, flags);

View File

@ -997,12 +997,9 @@ static inline int ata_hsm_ok_in_wq(struct ata_port *ap,
static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
{
struct ata_port *ap = qc->ap;
unsigned long flags;
if (ap->ops->error_handler) {
if (in_wq) {
spin_lock_irqsave(ap->lock, flags);
/* EH might have kicked in while host lock is
* released.
*/
@ -1014,8 +1011,6 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
} else
ata_port_freeze(ap);
}
spin_unlock_irqrestore(ap->lock, flags);
} else {
if (likely(!(qc->err_mask & AC_ERR_HSM)))
ata_qc_complete(qc);
@ -1024,10 +1019,8 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
}
} else {
if (in_wq) {
spin_lock_irqsave(ap->lock, flags);
ata_sff_irq_on(ap);
ata_qc_complete(qc);
spin_unlock_irqrestore(ap->lock, flags);
} else
ata_qc_complete(qc);
}
@ -1048,9 +1041,10 @@ int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
{
struct ata_link *link = qc->dev->link;
struct ata_eh_info *ehi = &link->eh_info;
unsigned long flags = 0;
int poll_next;
lockdep_assert_held(ap->lock);
WARN_ON_ONCE((qc->flags & ATA_QCFLAG_ACTIVE) == 0);
/* Make sure ata_sff_qc_issue() does not throw things
@ -1112,14 +1106,6 @@ int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
}
}
/* Send the CDB (atapi) or the first data block (ata pio out).
* During the state transition, interrupt handler shouldn't
* be invoked before the data transfer is complete and
* hsm_task_state is changed. Hence, the following locking.
*/
if (in_wq)
spin_lock_irqsave(ap->lock, flags);
if (qc->tf.protocol == ATA_PROT_PIO) {
/* PIO data out protocol.
* send first data block.
@ -1135,9 +1121,6 @@ int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
/* send CDB */
atapi_send_cdb(ap, qc);
if (in_wq)
spin_unlock_irqrestore(ap->lock, flags);
/* if polling, ata_sff_pio_task() handles the rest.
* otherwise, interrupt handler takes over from here.
*/
@ -1361,12 +1344,14 @@ static void ata_sff_pio_task(struct work_struct *work)
u8 status;
int poll_next;
spin_lock_irq(ap->lock);
BUG_ON(ap->sff_pio_task_link == NULL);
/* qc can be NULL if timeout occurred */
qc = ata_qc_from_tag(ap, link->active_tag);
if (!qc) {
ap->sff_pio_task_link = NULL;
return;
goto out_unlock;
}
fsm_start:
@ -1381,11 +1366,14 @@ static void ata_sff_pio_task(struct work_struct *work)
*/
status = ata_sff_busy_wait(ap, ATA_BUSY, 5);
if (status & ATA_BUSY) {
spin_unlock_irq(ap->lock);
ata_msleep(ap, 2);
spin_lock_irq(ap->lock);
status = ata_sff_busy_wait(ap, ATA_BUSY, 10);
if (status & ATA_BUSY) {
ata_sff_queue_pio_task(link, ATA_SHORT_PAUSE);
return;
goto out_unlock;
}
}
@ -1402,6 +1390,8 @@ static void ata_sff_pio_task(struct work_struct *work)
*/
if (poll_next)
goto fsm_start;
out_unlock:
spin_unlock_irq(ap->lock);
}
/**

View File

@ -32,6 +32,8 @@
#include <linux/libata.h>
#include <scsi/scsi_host.h>
#include <asm/mach-rc32434/rb.h>
#define DRV_NAME "pata-rb532-cf"
#define DRV_VERSION "0.1.0"
#define DRV_DESC "PATA driver for RouterBOARD 532 Compact Flash"
@ -107,6 +109,7 @@ static int rb532_pata_driver_probe(struct platform_device *pdev)
int gpio;
struct resource *res;
struct ata_host *ah;
struct cf_device *pdata;
struct rb532_cf_info *info;
int ret;
@ -122,7 +125,13 @@ static int rb532_pata_driver_probe(struct platform_device *pdev)
return -ENOENT;
}
gpio = irq_to_gpio(irq);
pdata = dev_get_platdata(&pdev->dev);
if (!pdata) {
dev_err(&pdev->dev, "no platform data specified\n");
return -EINVAL;
}
gpio = pdata->gpio_pin;
if (gpio < 0) {
dev_err(&pdev->dev, "no GPIO found for irq%d\n", irq);
return -ENOENT;

View File

@ -513,10 +513,15 @@ static int platform_drv_probe(struct device *_dev)
return ret;
ret = dev_pm_domain_attach(_dev, true);
if (ret != -EPROBE_DEFER && drv->probe) {
ret = drv->probe(dev);
if (ret)
dev_pm_domain_detach(_dev, true);
if (ret != -EPROBE_DEFER) {
if (drv->probe) {
ret = drv->probe(dev);
if (ret)
dev_pm_domain_detach(_dev, true);
} else {
/* don't fail if just dev_pm_domain_attach failed */
ret = 0;
}
}
if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) {

View File

@ -76,7 +76,7 @@ static void zcomp_strm_free(struct zcomp *comp, struct zcomp_strm *zstrm)
*/
static struct zcomp_strm *zcomp_strm_alloc(struct zcomp *comp)
{
struct zcomp_strm *zstrm = kmalloc(sizeof(*zstrm), GFP_KERNEL);
struct zcomp_strm *zstrm = kmalloc(sizeof(*zstrm), GFP_NOIO);
if (!zstrm)
return NULL;
@ -85,7 +85,7 @@ static struct zcomp_strm *zcomp_strm_alloc(struct zcomp *comp)
* allocate 2 pages. 1 for compressed data, plus 1 extra for the
* case when compressed size is larger than the original one
*/
zstrm->buffer = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 1);
zstrm->buffer = (void *)__get_free_pages(GFP_NOIO | __GFP_ZERO, 1);
if (!zstrm->private || !zstrm->buffer) {
zcomp_strm_free(comp, zstrm);
zstrm = NULL;

View File

@ -10,17 +10,36 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/lz4.h>
#include <linux/vmalloc.h>
#include <linux/mm.h>
#include "zcomp_lz4.h"
static void *zcomp_lz4_create(void)
{
return kzalloc(LZ4_MEM_COMPRESS, GFP_KERNEL);
void *ret;
/*
* This function can be called in swapout/fs write path
* so we can't use GFP_FS|IO. And it assumes we already
* have at least one stream in zram initialization so we
* don't do best effort to allocate more stream in here.
* A default stream will work well without further multiple
* streams. That's why we use NORETRY | NOWARN.
*/
ret = kzalloc(LZ4_MEM_COMPRESS, GFP_NOIO | __GFP_NORETRY |
__GFP_NOWARN);
if (!ret)
ret = __vmalloc(LZ4_MEM_COMPRESS,
GFP_NOIO | __GFP_NORETRY | __GFP_NOWARN |
__GFP_ZERO | __GFP_HIGHMEM,
PAGE_KERNEL);
return ret;
}
static void zcomp_lz4_destroy(void *private)
{
kfree(private);
kvfree(private);
}
static int zcomp_lz4_compress(const unsigned char *src, unsigned char *dst,

View File

@ -10,17 +10,36 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/lzo.h>
#include <linux/vmalloc.h>
#include <linux/mm.h>
#include "zcomp_lzo.h"
static void *lzo_create(void)
{
return kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
void *ret;
/*
* This function can be called in swapout/fs write path
* so we can't use GFP_FS|IO. And it assumes we already
* have at least one stream in zram initialization so we
* don't do best effort to allocate more stream in here.
* A default stream will work well without further multiple
* streams. That's why we use NORETRY | NOWARN.
*/
ret = kzalloc(LZO1X_MEM_COMPRESS, GFP_NOIO | __GFP_NORETRY |
__GFP_NOWARN);
if (!ret)
ret = __vmalloc(LZO1X_MEM_COMPRESS,
GFP_NOIO | __GFP_NORETRY | __GFP_NOWARN |
__GFP_ZERO | __GFP_HIGHMEM,
PAGE_KERNEL);
return ret;
}
static void lzo_destroy(void *private)
{
kfree(private);
kvfree(private);
}
static int lzo_compress(const unsigned char *src, unsigned char *dst,

Some files were not shown because too many files have changed in this diff Show More