summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pagano <mpagano@gentoo.org>2017-09-07 18:44:59 -0400
committerMike Pagano <mpagano@gentoo.org>2017-09-07 18:44:59 -0400
commitb3689468077d82446d7542c21032fc93b7d30202 (patch)
treed25a3a3e8d08d8df97bc79e7d59f1d28863bcfe8
parentLinux patch 4.12.10 (diff)
downloadlinux-patches-b3689468077d82446d7542c21032fc93b7d30202.tar.gz
linux-patches-b3689468077d82446d7542c21032fc93b7d30202.tar.bz2
linux-patches-b3689468077d82446d7542c21032fc93b7d30202.zip
Linux patch 4.12.114.12-12
-rw-r--r--0000_README4
-rw-r--r--1010_linux-4.12.11.patch1009
2 files changed, 1013 insertions, 0 deletions
diff --git a/0000_README b/0000_README
index a64a189e..dd06605d 100644
--- a/0000_README
+++ b/0000_README
@@ -83,6 +83,10 @@ Patch: 1009_linux-4.12.10.patch
From: http://www.kernel.org
Desc: Linux 4.12.10
+Patch: 1010_linux-4.12.11.patch
+From: http://www.kernel.org
+Desc: Linux 4.12.11
+
Patch: 1500_XATTR_USER_PREFIX.patch
From: https://bugs.gentoo.org/show_bug.cgi?id=470644
Desc: Support for namespace user.pax.* on tmpfs.
diff --git a/1010_linux-4.12.11.patch b/1010_linux-4.12.11.patch
new file mode 100644
index 00000000..b43b1605
--- /dev/null
+++ b/1010_linux-4.12.11.patch
@@ -0,0 +1,1009 @@
+diff --git a/Makefile b/Makefile
+index 6889ec6a091d..e7b2b54b032c 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,6 +1,6 @@
+ VERSION = 4
+ PATCHLEVEL = 12
+-SUBLEVEL = 10
++SUBLEVEL = 11
+ EXTRAVERSION =
+ NAME = Fearless Coyote
+
+diff --git a/arch/alpha/include/asm/types.h b/arch/alpha/include/asm/types.h
+index 4cb4b6d3452c..0bc66e1d3a7e 100644
+--- a/arch/alpha/include/asm/types.h
++++ b/arch/alpha/include/asm/types.h
+@@ -1,6 +1,6 @@
+ #ifndef _ALPHA_TYPES_H
+ #define _ALPHA_TYPES_H
+
+-#include <asm-generic/int-ll64.h>
++#include <uapi/asm/types.h>
+
+ #endif /* _ALPHA_TYPES_H */
+diff --git a/arch/alpha/include/uapi/asm/types.h b/arch/alpha/include/uapi/asm/types.h
+index 9fd3cd459777..8d1024d7be05 100644
+--- a/arch/alpha/include/uapi/asm/types.h
++++ b/arch/alpha/include/uapi/asm/types.h
+@@ -9,8 +9,18 @@
+ * need to be careful to avoid a name clashes.
+ */
+
+-#ifndef __KERNEL__
++/*
++ * This is here because we used to use l64 for alpha
++ * and we don't want to impact user mode with our change to ll64
++ * in the kernel.
++ *
++ * However, some user programs are fine with this. They can
++ * flag __SANE_USERSPACE_TYPES__ to get int-ll64.h here.
++ */
++#if !defined(__SANE_USERSPACE_TYPES__) && !defined(__KERNEL__)
+ #include <asm-generic/int-l64.h>
++#else
++#include <asm-generic/int-ll64.h>
+ #endif
+
+ #endif /* _UAPI_ALPHA_TYPES_H */
+diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
+index 37b95dff0b07..3952d5ef8a7a 100644
+--- a/arch/arm64/mm/fault.c
++++ b/arch/arm64/mm/fault.c
+@@ -397,8 +397,11 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
+ * signal first. We do not need to release the mmap_sem because it
+ * would already be released in __lock_page_or_retry in mm/filemap.c.
+ */
+- if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
++ if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) {
++ if (!user_mode(regs))
++ goto no_context;
+ return 0;
++ }
+
+ /*
+ * Major/minor page fault accounting is only done on the initial
+diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
+index 7afb0e2f07f4..48febf07e828 100644
+--- a/arch/x86/include/asm/io.h
++++ b/arch/x86/include/asm/io.h
+@@ -328,13 +328,13 @@ static inline unsigned type in##bwl##_p(int port) \
+ static inline void outs##bwl(int port, const void *addr, unsigned long count) \
+ { \
+ asm volatile("rep; outs" #bwl \
+- : "+S"(addr), "+c"(count) : "d"(port)); \
++ : "+S"(addr), "+c"(count) : "d"(port) : "memory"); \
+ } \
+ \
+ static inline void ins##bwl(int port, void *addr, unsigned long count) \
+ { \
+ asm volatile("rep; ins" #bwl \
+- : "+D"(addr), "+c"(count) : "d"(port)); \
++ : "+D"(addr), "+c"(count) : "d"(port) : "memory"); \
+ }
+
+ BUILDIO(b, b, char)
+diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
+index 43839b00fe6c..903605dbc1a5 100644
+--- a/crypto/algif_skcipher.c
++++ b/crypto/algif_skcipher.c
+@@ -87,8 +87,13 @@ static void skcipher_free_async_sgls(struct skcipher_async_req *sreq)
+ }
+ sgl = sreq->tsg;
+ n = sg_nents(sgl);
+- for_each_sg(sgl, sg, n, i)
+- put_page(sg_page(sg));
++ for_each_sg(sgl, sg, n, i) {
++ struct page *page = sg_page(sg);
++
++ /* some SGs may not have a page mapped */
++ if (page && page_ref_count(page))
++ put_page(page);
++ }
+
+ kfree(sreq->tsg);
+ }
+diff --git a/crypto/chacha20_generic.c b/crypto/chacha20_generic.c
+index 8b3c04d625c3..4a45fa4890c0 100644
+--- a/crypto/chacha20_generic.c
++++ b/crypto/chacha20_generic.c
+@@ -91,9 +91,14 @@ int crypto_chacha20_crypt(struct skcipher_request *req)
+ crypto_chacha20_init(state, ctx, walk.iv);
+
+ while (walk.nbytes > 0) {
++ unsigned int nbytes = walk.nbytes;
++
++ if (nbytes < walk.total)
++ nbytes = round_down(nbytes, walk.stride);
++
+ chacha20_docrypt(state, walk.dst.virt.addr, walk.src.virt.addr,
+- walk.nbytes);
+- err = skcipher_walk_done(&walk, 0);
++ nbytes);
++ err = skcipher_walk_done(&walk, walk.nbytes - nbytes);
+ }
+
+ return err;
+diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
+index f802bcd94457..de30a822ccab 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
++++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
+@@ -1155,8 +1155,6 @@ nouveau_connector_aux_xfer(struct drm_dp_aux *obj, struct drm_dp_aux_msg *msg)
+ return -ENODEV;
+ if (WARN_ON(msg->size > 16))
+ return -E2BIG;
+- if (msg->size == 0)
+- return msg->size;
+
+ ret = nvkm_i2c_aux_acquire(aux);
+ if (ret)
+diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
+index 06e564a9ccb2..70ab2eee9b04 100644
+--- a/drivers/gpu/drm/nouveau/nv50_display.c
++++ b/drivers/gpu/drm/nouveau/nv50_display.c
+@@ -3618,15 +3618,24 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe)
+ drm_mode_connector_attach_encoder(connector, encoder);
+
+ if (dcbe->type == DCB_OUTPUT_DP) {
++ struct nv50_disp *disp = nv50_disp(encoder->dev);
+ struct nvkm_i2c_aux *aux =
+ nvkm_i2c_aux_find(i2c, dcbe->i2c_index);
+ if (aux) {
+- nv_encoder->i2c = &nv_connector->aux.ddc;
++ if (disp->disp->oclass < GF110_DISP) {
++ /* HW has no support for address-only
++ * transactions, so we're required to
++ * use custom I2C-over-AUX code.
++ */
++ nv_encoder->i2c = &aux->i2c;
++ } else {
++ nv_encoder->i2c = &nv_connector->aux.ddc;
++ }
+ nv_encoder->aux = aux;
+ }
+
+ /*TODO: Use DP Info Table to check for support. */
+- if (nv50_disp(encoder->dev)->disp->oclass >= GF110_DISP) {
++ if (disp->disp->oclass >= GF110_DISP) {
+ ret = nv50_mstm_new(nv_encoder, &nv_connector->aux, 16,
+ nv_connector->base.base.id,
+ &nv_encoder->dp.mstm);
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/Kbuild
+index 48f01e40b8fc..b768e66a472b 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/Kbuild
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/Kbuild
+@@ -25,6 +25,7 @@ nvkm-y += nvkm/subdev/i2c/bit.o
+
+ nvkm-y += nvkm/subdev/i2c/aux.o
+ nvkm-y += nvkm/subdev/i2c/auxg94.o
++nvkm-y += nvkm/subdev/i2c/auxgf119.o
+ nvkm-y += nvkm/subdev/i2c/auxgm200.o
+
+ nvkm-y += nvkm/subdev/i2c/anx9805.o
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c
+index d172e42dd228..4c1f547da463 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c
+@@ -117,6 +117,10 @@ int
+ nvkm_i2c_aux_xfer(struct nvkm_i2c_aux *aux, bool retry, u8 type,
+ u32 addr, u8 *data, u8 *size)
+ {
++ if (!*size && !aux->func->address_only) {
++ AUX_ERR(aux, "address-only transaction dropped");
++ return -ENOSYS;
++ }
+ return aux->func->xfer(aux, retry, type, addr, data, size);
+ }
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h
+index 27a4a39c87f0..9587ab456d9e 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h
+@@ -3,6 +3,7 @@
+ #include "pad.h"
+
+ struct nvkm_i2c_aux_func {
++ bool address_only;
+ int (*xfer)(struct nvkm_i2c_aux *, bool retry, u8 type,
+ u32 addr, u8 *data, u8 *size);
+ int (*lnk_ctl)(struct nvkm_i2c_aux *, int link_nr, int link_bw,
+@@ -17,7 +18,12 @@ void nvkm_i2c_aux_del(struct nvkm_i2c_aux **);
+ int nvkm_i2c_aux_xfer(struct nvkm_i2c_aux *, bool retry, u8 type,
+ u32 addr, u8 *data, u8 *size);
+
++int g94_i2c_aux_new_(const struct nvkm_i2c_aux_func *, struct nvkm_i2c_pad *,
++ int, u8, struct nvkm_i2c_aux **);
++
+ int g94_i2c_aux_new(struct nvkm_i2c_pad *, int, u8, struct nvkm_i2c_aux **);
++int g94_i2c_aux_xfer(struct nvkm_i2c_aux *, bool, u8, u32, u8 *, u8 *);
++int gf119_i2c_aux_new(struct nvkm_i2c_pad *, int, u8, struct nvkm_i2c_aux **);
+ int gm200_i2c_aux_new(struct nvkm_i2c_pad *, int, u8, struct nvkm_i2c_aux **);
+
+ #define AUX_MSG(b,l,f,a...) do { \
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c
+index ab8cb196c34e..c8ab1b5741a3 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c
+@@ -72,7 +72,7 @@ g94_i2c_aux_init(struct g94_i2c_aux *aux)
+ return 0;
+ }
+
+-static int
++int
+ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
+ u8 type, u32 addr, u8 *data, u8 *size)
+ {
+@@ -105,9 +105,9 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
+ }
+
+ ctrl = nvkm_rd32(device, 0x00e4e4 + base);
+- ctrl &= ~0x0001f0ff;
++ ctrl &= ~0x0001f1ff;
+ ctrl |= type << 12;
+- ctrl |= *size - 1;
++ ctrl |= (*size ? (*size - 1) : 0x00000100);
+ nvkm_wr32(device, 0x00e4e0 + base, addr);
+
+ /* (maybe) retry transaction a number of times on failure... */
+@@ -160,14 +160,10 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
+ return ret < 0 ? ret : (stat & 0x000f0000) >> 16;
+ }
+
+-static const struct nvkm_i2c_aux_func
+-g94_i2c_aux_func = {
+- .xfer = g94_i2c_aux_xfer,
+-};
+-
+ int
+-g94_i2c_aux_new(struct nvkm_i2c_pad *pad, int index, u8 drive,
+- struct nvkm_i2c_aux **paux)
++g94_i2c_aux_new_(const struct nvkm_i2c_aux_func *func,
++ struct nvkm_i2c_pad *pad, int index, u8 drive,
++ struct nvkm_i2c_aux **paux)
+ {
+ struct g94_i2c_aux *aux;
+
+@@ -175,8 +171,20 @@ g94_i2c_aux_new(struct nvkm_i2c_pad *pad, int index, u8 drive,
+ return -ENOMEM;
+ *paux = &aux->base;
+
+- nvkm_i2c_aux_ctor(&g94_i2c_aux_func, pad, index, &aux->base);
++ nvkm_i2c_aux_ctor(func, pad, index, &aux->base);
+ aux->ch = drive;
+ aux->base.intr = 1 << aux->ch;
+ return 0;
+ }
++
++static const struct nvkm_i2c_aux_func
++g94_i2c_aux = {
++ .xfer = g94_i2c_aux_xfer,
++};
++
++int
++g94_i2c_aux_new(struct nvkm_i2c_pad *pad, int index, u8 drive,
++ struct nvkm_i2c_aux **paux)
++{
++ return g94_i2c_aux_new_(&g94_i2c_aux, pad, index, drive, paux);
++}
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgf119.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgf119.c
+new file mode 100644
+index 000000000000..dab40cd8fe3a
+--- /dev/null
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgf119.c
+@@ -0,0 +1,35 @@
++/*
++ * Copyright 2017 Red Hat Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ */
++#include "aux.h"
++
++static const struct nvkm_i2c_aux_func
++gf119_i2c_aux = {
++ .address_only = true,
++ .xfer = g94_i2c_aux_xfer,
++};
++
++int
++gf119_i2c_aux_new(struct nvkm_i2c_pad *pad, int index, u8 drive,
++ struct nvkm_i2c_aux **paux)
++{
++ return g94_i2c_aux_new_(&gf119_i2c_aux, pad, index, drive, paux);
++}
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c
+index ee091fa79628..7ef60895f43a 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c
+@@ -105,9 +105,9 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
+ }
+
+ ctrl = nvkm_rd32(device, 0x00d954 + base);
+- ctrl &= ~0x0001f0ff;
++ ctrl &= ~0x0001f1ff;
+ ctrl |= type << 12;
+- ctrl |= *size - 1;
++ ctrl |= (*size ? (*size - 1) : 0x00000100);
+ nvkm_wr32(device, 0x00d950 + base, addr);
+
+ /* (maybe) retry transaction a number of times on failure... */
+@@ -162,6 +162,7 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
+
+ static const struct nvkm_i2c_aux_func
+ gm200_i2c_aux_func = {
++ .address_only = true,
+ .xfer = gm200_i2c_aux_xfer,
+ };
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgf119.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgf119.c
+index d53212f1aa52..3bc4d0310076 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgf119.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgf119.c
+@@ -28,7 +28,7 @@
+ static const struct nvkm_i2c_pad_func
+ gf119_i2c_pad_s_func = {
+ .bus_new_4 = gf119_i2c_bus_new,
+- .aux_new_6 = g94_i2c_aux_new,
++ .aux_new_6 = gf119_i2c_aux_new,
+ .mode = g94_i2c_pad_mode,
+ };
+
+@@ -41,7 +41,7 @@ gf119_i2c_pad_s_new(struct nvkm_i2c *i2c, int id, struct nvkm_i2c_pad **ppad)
+ static const struct nvkm_i2c_pad_func
+ gf119_i2c_pad_x_func = {
+ .bus_new_4 = gf119_i2c_bus_new,
+- .aux_new_6 = g94_i2c_aux_new,
++ .aux_new_6 = gf119_i2c_aux_new,
+ };
+
+ int
+diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c
+index eeddc1e48409..871599826773 100644
+--- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
++++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
+@@ -615,7 +615,7 @@ static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool,
+ } else {
+ pr_err("Failed to fill pool (%p)\n", pool);
+ /* If we have any pages left put them to the pool. */
+- list_for_each_entry(p, &pool->list, lru) {
++ list_for_each_entry(p, &new_pages, lru) {
+ ++cpages;
+ }
+ list_splice(&new_pages, &pool->list);
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+index f8a977f86ec7..a17478028649 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+@@ -1567,10 +1567,34 @@ vmw_kms_atomic_check_modeset(struct drm_device *dev,
+ }
+
+
++/**
++ * vmw_kms_atomic_commit - Perform an atomic state commit
++ *
++ * @dev: DRM device
++ * @state: the driver state object
++ * @nonblock: Whether nonblocking behaviour is requested
++ *
++ * This is a simple wrapper around drm_atomic_helper_commit() for
++ * us to clear the nonblocking value.
++ *
++ * Nonblocking commits currently cause synchronization issues
++ * for vmwgfx.
++ *
++ * RETURNS
++ * Zero for success or negative error code on failure.
++ */
++int vmw_kms_atomic_commit(struct drm_device *dev,
++ struct drm_atomic_state *state,
++ bool nonblock)
++{
++ return drm_atomic_helper_commit(dev, state, false);
++}
++
++
+ static const struct drm_mode_config_funcs vmw_kms_funcs = {
+ .fb_create = vmw_kms_fb_create,
+ .atomic_check = vmw_kms_atomic_check_modeset,
+- .atomic_commit = drm_atomic_helper_commit,
++ .atomic_commit = vmw_kms_atomic_commit,
+ };
+
+ static int vmw_kms_generic_present(struct vmw_private *dev_priv,
+diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c
+index e98e44e584a4..22ffcb73c185 100644
+--- a/drivers/i2c/busses/i2c-ismt.c
++++ b/drivers/i2c/busses/i2c-ismt.c
+@@ -341,8 +341,10 @@ static int ismt_process_desc(const struct ismt_desc *desc,
+ break;
+ case I2C_SMBUS_BLOCK_DATA:
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+- memcpy(&data->block[1], dma_buffer, desc->rxbytes);
+- data->block[0] = desc->rxbytes;
++ if (desc->rxbytes != dma_buffer[0] + 1)
++ return -EMSGSIZE;
++
++ memcpy(data->block, dma_buffer, desc->rxbytes);
+ break;
+ }
+ return 0;
+diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
+index def96cd2479b..68894f7ccb54 100644
+--- a/drivers/input/joystick/xpad.c
++++ b/drivers/input/joystick/xpad.c
+@@ -389,10 +389,21 @@ static const u8 xboxone_hori_init[] = {
+ };
+
+ /*
+- * A rumble packet is required for some PowerA pads to start
++ * A specific rumble packet is required for some PowerA pads to start
+ * sending input reports. One of those pads is (0x24c6:0x543a).
+ */
+-static const u8 xboxone_zerorumble_init[] = {
++static const u8 xboxone_rumblebegin_init[] = {
++ 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00,
++ 0x1D, 0x1D, 0xFF, 0x00, 0x00
++};
++
++/*
++ * A rumble packet with zero FF intensity will immediately
++ * terminate the rumbling required to init PowerA pads.
++ * This should happen fast enough that the motors don't
++ * spin up to enough speed to actually vibrate the gamepad.
++ */
++static const u8 xboxone_rumbleend_init[] = {
+ 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+@@ -407,9 +418,12 @@ static const struct xboxone_init_packet xboxone_init_packets[] = {
+ XBOXONE_INIT_PKT(0x0e6f, 0x0165, xboxone_hori_init),
+ XBOXONE_INIT_PKT(0x0f0d, 0x0067, xboxone_hori_init),
+ XBOXONE_INIT_PKT(0x0000, 0x0000, xboxone_fw2015_init),
+- XBOXONE_INIT_PKT(0x24c6, 0x541a, xboxone_zerorumble_init),
+- XBOXONE_INIT_PKT(0x24c6, 0x542a, xboxone_zerorumble_init),
+- XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_zerorumble_init),
++ XBOXONE_INIT_PKT(0x24c6, 0x541a, xboxone_rumblebegin_init),
++ XBOXONE_INIT_PKT(0x24c6, 0x542a, xboxone_rumblebegin_init),
++ XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_rumblebegin_init),
++ XBOXONE_INIT_PKT(0x24c6, 0x541a, xboxone_rumbleend_init),
++ XBOXONE_INIT_PKT(0x24c6, 0x542a, xboxone_rumbleend_init),
++ XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_rumbleend_init),
+ };
+
+ struct xpad_output_packet {
+diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
+index 16c30460ef04..5af0b7d200bc 100644
+--- a/drivers/input/mouse/synaptics.c
++++ b/drivers/input/mouse/synaptics.c
+@@ -535,16 +535,17 @@ static void synaptics_apply_quirks(struct psmouse *psmouse,
+ }
+ }
+
++static bool synaptics_has_agm(struct synaptics_data *priv)
++{
++ return (SYN_CAP_ADV_GESTURE(priv->info.ext_cap_0c) ||
++ SYN_CAP_IMAGE_SENSOR(priv->info.ext_cap_0c));
++}
++
+ static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse)
+ {
+ static u8 param = 0xc8;
+- struct synaptics_data *priv = psmouse->private;
+ int error;
+
+- if (!(SYN_CAP_ADV_GESTURE(priv->info.ext_cap_0c) ||
+- SYN_CAP_IMAGE_SENSOR(priv->info.ext_cap_0c)))
+- return 0;
+-
+ error = psmouse_sliced_command(psmouse, SYN_QUE_MODEL);
+ if (error)
+ return error;
+@@ -553,9 +554,6 @@ static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse)
+ if (error)
+ return error;
+
+- /* Advanced gesture mode also sends multi finger data */
+- priv->info.capabilities |= BIT(1);
+-
+ return 0;
+ }
+
+@@ -578,7 +576,7 @@ static int synaptics_set_mode(struct psmouse *psmouse)
+ if (error)
+ return error;
+
+- if (priv->absolute_mode) {
++ if (priv->absolute_mode && synaptics_has_agm(priv)) {
+ error = synaptics_set_advanced_gesture_mode(psmouse);
+ if (error) {
+ psmouse_err(psmouse,
+@@ -766,9 +764,7 @@ static int synaptics_parse_hw_state(const u8 buf[],
+ ((buf[0] & 0x04) >> 1) |
+ ((buf[3] & 0x04) >> 2));
+
+- if ((SYN_CAP_ADV_GESTURE(priv->info.ext_cap_0c) ||
+- SYN_CAP_IMAGE_SENSOR(priv->info.ext_cap_0c)) &&
+- hw->w == 2) {
++ if (synaptics_has_agm(priv) && hw->w == 2) {
+ synaptics_parse_agm(buf, priv, hw);
+ return 1;
+ }
+@@ -1033,6 +1029,15 @@ static void synaptics_image_sensor_process(struct psmouse *psmouse,
+ synaptics_report_mt_data(psmouse, sgm, num_fingers);
+ }
+
++static bool synaptics_has_multifinger(struct synaptics_data *priv)
++{
++ if (SYN_CAP_MULTIFINGER(priv->info.capabilities))
++ return true;
++
++ /* Advanced gesture mode also sends multi finger data */
++ return synaptics_has_agm(priv);
++}
++
+ /*
+ * called for each full received packet from the touchpad
+ */
+@@ -1079,7 +1084,7 @@ static void synaptics_process_packet(struct psmouse *psmouse)
+ if (SYN_CAP_EXTENDED(info->capabilities)) {
+ switch (hw.w) {
+ case 0 ... 1:
+- if (SYN_CAP_MULTIFINGER(info->capabilities))
++ if (synaptics_has_multifinger(priv))
+ num_fingers = hw.w + 2;
+ break;
+ case 2:
+@@ -1123,7 +1128,7 @@ static void synaptics_process_packet(struct psmouse *psmouse)
+ input_report_abs(dev, ABS_TOOL_WIDTH, finger_width);
+
+ input_report_key(dev, BTN_TOOL_FINGER, num_fingers == 1);
+- if (SYN_CAP_MULTIFINGER(info->capabilities)) {
++ if (synaptics_has_multifinger(priv)) {
+ input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2);
+ input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3);
+ }
+@@ -1283,7 +1288,7 @@ static void set_input_params(struct psmouse *psmouse,
+ __set_bit(BTN_TOUCH, dev->keybit);
+ __set_bit(BTN_TOOL_FINGER, dev->keybit);
+
+- if (SYN_CAP_MULTIFINGER(info->capabilities)) {
++ if (synaptics_has_multifinger(priv)) {
+ __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit);
+ __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit);
+ }
+diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
+index 929f8558bf1c..90e74f9f5f9c 100644
+--- a/drivers/irqchip/irq-mips-gic.c
++++ b/drivers/irqchip/irq-mips-gic.c
+@@ -1022,8 +1022,11 @@ static int __init gic_of_init(struct device_node *node,
+ gic_len = resource_size(&res);
+ }
+
+- if (mips_cm_present())
++ if (mips_cm_present()) {
+ write_gcr_gic_base(gic_base | CM_GCR_GIC_BASE_GICEN_MSK);
++ /* Ensure GIC region is enabled before trying to access it */
++ __sync();
++ }
+ gic_present = true;
+
+ __gic_init(gic_base, gic_len, cpu_vec, 0, node);
+diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
+index 3df056b73b66..fa0df4a3e1be 100644
+--- a/drivers/md/dm-mpath.c
++++ b/drivers/md/dm-mpath.c
+@@ -504,7 +504,6 @@ static int multipath_clone_and_map(struct dm_target *ti, struct request *rq,
+ if (queue_dying) {
+ atomic_inc(&m->pg_init_in_progress);
+ activate_or_offline_path(pgpath);
+- return DM_MAPIO_REQUEUE;
+ }
+ return DM_MAPIO_DELAY_REQUEUE;
+ }
+diff --git a/drivers/mmc/host/sdhci-xenon.c b/drivers/mmc/host/sdhci-xenon.c
+index bc1781bb070b..c580af05b033 100644
+--- a/drivers/mmc/host/sdhci-xenon.c
++++ b/drivers/mmc/host/sdhci-xenon.c
+@@ -210,8 +210,27 @@ static void xenon_set_uhs_signaling(struct sdhci_host *host,
+ sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
+ }
+
++static void xenon_set_power(struct sdhci_host *host, unsigned char mode,
++ unsigned short vdd)
++{
++ struct mmc_host *mmc = host->mmc;
++ u8 pwr = host->pwr;
++
++ sdhci_set_power_noreg(host, mode, vdd);
++
++ if (host->pwr == pwr)
++ return;
++
++ if (host->pwr == 0)
++ vdd = 0;
++
++ if (!IS_ERR(mmc->supply.vmmc))
++ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
++}
++
+ static const struct sdhci_ops sdhci_xenon_ops = {
+ .set_clock = sdhci_set_clock,
++ .set_power = xenon_set_power,
+ .set_bus_width = sdhci_set_bus_width,
+ .reset = xenon_reset,
+ .set_uhs_signaling = xenon_set_uhs_signaling,
+diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
+index bbf7604889b7..1c539c83e8cf 100644
+--- a/drivers/net/wireless/ti/wl1251/main.c
++++ b/drivers/net/wireless/ti/wl1251/main.c
+@@ -1571,6 +1571,7 @@ struct ieee80211_hw *wl1251_alloc_hw(void)
+
+ wl->state = WL1251_STATE_OFF;
+ mutex_init(&wl->mutex);
++ spin_lock_init(&wl->wl_lock);
+
+ wl->tx_mgmt_frm_rate = DEFAULT_HW_GEN_TX_RATE;
+ wl->tx_mgmt_frm_mod = DEFAULT_HW_GEN_MODULATION_TYPE;
+diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
+index 1e71e6ca5ddf..8e03c9ae0bf0 100644
+--- a/fs/ceph/addr.c
++++ b/fs/ceph/addr.c
+@@ -189,7 +189,7 @@ static int ceph_releasepage(struct page *page, gfp_t g)
+ /*
+ * read a single page, without unlocking it.
+ */
+-static int readpage_nounlock(struct file *filp, struct page *page)
++static int ceph_do_readpage(struct file *filp, struct page *page)
+ {
+ struct inode *inode = file_inode(filp);
+ struct ceph_inode_info *ci = ceph_inode(inode);
+@@ -219,7 +219,7 @@ static int readpage_nounlock(struct file *filp, struct page *page)
+
+ err = ceph_readpage_from_fscache(inode, page);
+ if (err == 0)
+- goto out;
++ return -EINPROGRESS;
+
+ dout("readpage inode %p file %p page %p index %lu\n",
+ inode, filp, page, page->index);
+@@ -249,8 +249,11 @@ static int readpage_nounlock(struct file *filp, struct page *page)
+
+ static int ceph_readpage(struct file *filp, struct page *page)
+ {
+- int r = readpage_nounlock(filp, page);
+- unlock_page(page);
++ int r = ceph_do_readpage(filp, page);
++ if (r != -EINPROGRESS)
++ unlock_page(page);
++ else
++ r = 0;
+ return r;
+ }
+
+@@ -1240,7 +1243,7 @@ static int ceph_update_writeable_page(struct file *file,
+ goto retry_locked;
+ r = writepage_nounlock(page, NULL);
+ if (r < 0)
+- goto fail_nosnap;
++ goto fail_unlock;
+ goto retry_locked;
+ }
+
+@@ -1268,11 +1271,14 @@ static int ceph_update_writeable_page(struct file *file,
+ }
+
+ /* we need to read it. */
+- r = readpage_nounlock(file, page);
+- if (r < 0)
+- goto fail_nosnap;
++ r = ceph_do_readpage(file, page);
++ if (r < 0) {
++ if (r == -EINPROGRESS)
++ return -EAGAIN;
++ goto fail_unlock;
++ }
+ goto retry_locked;
+-fail_nosnap:
++fail_unlock:
+ unlock_page(page);
+ return r;
+ }
+diff --git a/fs/ceph/cache.c b/fs/ceph/cache.c
+index 4e7421caf380..bf56392ecec2 100644
+--- a/fs/ceph/cache.c
++++ b/fs/ceph/cache.c
+@@ -240,13 +240,7 @@ void ceph_fscache_file_set_cookie(struct inode *inode, struct file *filp)
+ }
+ }
+
+-static void ceph_vfs_readpage_complete(struct page *page, void *data, int error)
+-{
+- if (!error)
+- SetPageUptodate(page);
+-}
+-
+-static void ceph_vfs_readpage_complete_unlock(struct page *page, void *data, int error)
++static void ceph_readpage_from_fscache_complete(struct page *page, void *data, int error)
+ {
+ if (!error)
+ SetPageUptodate(page);
+@@ -274,7 +268,7 @@ int ceph_readpage_from_fscache(struct inode *inode, struct page *page)
+ return -ENOBUFS;
+
+ ret = fscache_read_or_alloc_page(ci->fscache, page,
+- ceph_vfs_readpage_complete, NULL,
++ ceph_readpage_from_fscache_complete, NULL,
+ GFP_KERNEL);
+
+ switch (ret) {
+@@ -303,7 +297,7 @@ int ceph_readpages_from_fscache(struct inode *inode,
+ return -ENOBUFS;
+
+ ret = fscache_read_or_alloc_pages(ci->fscache, mapping, pages, nr_pages,
+- ceph_vfs_readpage_complete_unlock,
++ ceph_readpage_from_fscache_complete,
+ NULL, mapping_gfp_mask(mapping));
+
+ switch (ret) {
+diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
+index 569d3fb736be..e702d48bd023 100644
+--- a/fs/cifs/dir.c
++++ b/fs/cifs/dir.c
+@@ -205,7 +205,7 @@ check_name(struct dentry *direntry, struct cifs_tcon *tcon)
+ int i;
+
+ if (unlikely(direntry->d_name.len >
+- tcon->fsAttrInfo.MaxPathNameComponentLength))
++ le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength)))
+ return -ENAMETOOLONG;
+
+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
+diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
+index 18700fd25a0b..2826882c81d1 100644
+--- a/fs/cifs/smb2pdu.h
++++ b/fs/cifs/smb2pdu.h
+@@ -84,8 +84,8 @@
+
+ #define NUMBER_OF_SMB2_COMMANDS 0x0013
+
+-/* BB FIXME - analyze following length BB */
+-#define MAX_SMB2_HDR_SIZE 0x78 /* 4 len + 64 hdr + (2*24 wct) + 2 bct + 2 pad */
++/* 4 len + 52 transform hdr + 64 hdr + 56 create rsp */
++#define MAX_SMB2_HDR_SIZE 0x00b0
+
+ #define SMB2_PROTO_NUMBER cpu_to_le32(0x424d53fe)
+ #define SMB2_TRANSFORM_PROTO_NUM cpu_to_le32(0x424d53fd)
+diff --git a/fs/eventpoll.c b/fs/eventpoll.c
+index 5420767c9b68..2ca248425e5d 100644
+--- a/fs/eventpoll.c
++++ b/fs/eventpoll.c
+@@ -600,8 +600,13 @@ static void ep_remove_wait_queue(struct eppoll_entry *pwq)
+ wait_queue_head_t *whead;
+
+ rcu_read_lock();
+- /* If it is cleared by POLLFREE, it should be rcu-safe */
+- whead = rcu_dereference(pwq->whead);
++ /*
++ * If it is cleared by POLLFREE, it should be rcu-safe.
++ * If we read NULL we need a barrier paired with
++ * smp_store_release() in ep_poll_callback(), otherwise
++ * we rely on whead->lock.
++ */
++ whead = smp_load_acquire(&pwq->whead);
+ if (whead)
+ remove_wait_queue(whead, &pwq->wait);
+ rcu_read_unlock();
+@@ -1086,17 +1091,6 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k
+ struct eventpoll *ep = epi->ep;
+ int ewake = 0;
+
+- if ((unsigned long)key & POLLFREE) {
+- ep_pwq_from_wait(wait)->whead = NULL;
+- /*
+- * whead = NULL above can race with ep_remove_wait_queue()
+- * which can do another remove_wait_queue() after us, so we
+- * can't use __remove_wait_queue(). whead->lock is held by
+- * the caller.
+- */
+- list_del_init(&wait->task_list);
+- }
+-
+ spin_lock_irqsave(&ep->lock, flags);
+
+ ep_set_busy_poll_napi_id(epi);
+@@ -1180,10 +1174,26 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k
+ if (pwake)
+ ep_poll_safewake(&ep->poll_wait);
+
+- if (epi->event.events & EPOLLEXCLUSIVE)
+- return ewake;
++ if (!(epi->event.events & EPOLLEXCLUSIVE))
++ ewake = 1;
++
++ if ((unsigned long)key & POLLFREE) {
++ /*
++ * If we race with ep_remove_wait_queue() it can miss
++ * ->whead = NULL and do another remove_wait_queue() after
++ * us, so we can't use __remove_wait_queue().
++ */
++ list_del_init(&wait->task_list);
++ /*
++ * ->whead != NULL protects us from the race with ep_free()
++ * or ep_remove(), ep_remove_wait_queue() takes whead->lock
++ * held by the caller. Once we nullify it, nothing protects
++ * ep/epi or even wait.
++ */
++ smp_store_release(&ep_pwq_from_wait(wait)->whead, NULL);
++ }
+
+- return 1;
++ return ewake;
+ }
+
+ /*
+diff --git a/include/asm-generic/topology.h b/include/asm-generic/topology.h
+index fc824e2828f3..5d2add1a6c96 100644
+--- a/include/asm-generic/topology.h
++++ b/include/asm-generic/topology.h
+@@ -48,7 +48,11 @@
+ #define parent_node(node) ((void)(node),0)
+ #endif
+ #ifndef cpumask_of_node
+-#define cpumask_of_node(node) ((void)node, cpu_online_mask)
++ #ifdef CONFIG_NEED_MULTIPLE_NODES
++ #define cpumask_of_node(node) ((node) == 0 ? cpu_online_mask : cpu_none_mask)
++ #else
++ #define cpumask_of_node(node) ((void)node, cpu_online_mask)
++ #endif
+ #endif
+ #ifndef pcibus_to_node
+ #define pcibus_to_node(bus) ((void)(bus), -1)
+diff --git a/include/linux/nvme.h b/include/linux/nvme.h
+index b625bacf37ef..f4f9481a0c8a 100644
+--- a/include/linux/nvme.h
++++ b/include/linux/nvme.h
+@@ -245,7 +245,7 @@ enum {
+ NVME_CTRL_ONCS_WRITE_ZEROES = 1 << 3,
+ NVME_CTRL_VWC_PRESENT = 1 << 0,
+ NVME_CTRL_OACS_SEC_SUPP = 1 << 0,
+- NVME_CTRL_OACS_DBBUF_SUPP = 1 << 7,
++ NVME_CTRL_OACS_DBBUF_SUPP = 1 << 8,
+ };
+
+ struct nvme_lbaf {
+diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
+index 8f26927f16a1..0e2fe5eb6c30 100644
+--- a/kernel/cgroup/cpuset.c
++++ b/kernel/cgroup/cpuset.c
+@@ -1907,6 +1907,7 @@ static struct cftype files[] = {
+ {
+ .name = "memory_pressure",
+ .read_u64 = cpuset_read_u64,
++ .private = FILE_MEMORY_PRESSURE,
+ },
+
+ {
+diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
+index 0e137f98a50c..267f6ef91d97 100644
+--- a/kernel/events/uprobes.c
++++ b/kernel/events/uprobes.c
+@@ -1262,8 +1262,6 @@ void uprobe_end_dup_mmap(void)
+
+ void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm)
+ {
+- newmm->uprobes_state.xol_area = NULL;
+-
+ if (test_bit(MMF_HAS_UPROBES, &oldmm->flags)) {
+ set_bit(MMF_HAS_UPROBES, &newmm->flags);
+ /* unconditionally, dup_mmap() skips VM_DONTCOPY vmas */
+diff --git a/kernel/fork.c b/kernel/fork.c
+index 9a2b4b4f13b4..31d2b97a792d 100644
+--- a/kernel/fork.c
++++ b/kernel/fork.c
+@@ -781,6 +781,13 @@ static void mm_init_owner(struct mm_struct *mm, struct task_struct *p)
+ #endif
+ }
+
++static void mm_init_uprobes_state(struct mm_struct *mm)
++{
++#ifdef CONFIG_UPROBES
++ mm->uprobes_state.xol_area = NULL;
++#endif
++}
++
+ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p,
+ struct user_namespace *user_ns)
+ {
+@@ -808,6 +815,7 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p,
+ #if defined(CONFIG_TRANSPARENT_HUGEPAGE) && !USE_SPLIT_PMD_PTLOCKS
+ mm->pmd_huge_pte = NULL;
+ #endif
++ mm_init_uprobes_state(mm);
+
+ if (current->mm) {
+ mm->flags = current->mm->flags & MMF_INIT_MASK;
+diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c
+index 5a0f75a3bf01..eead4b339466 100644
+--- a/lib/mpi/mpicoder.c
++++ b/lib/mpi/mpicoder.c
+@@ -364,11 +364,11 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes)
+ }
+
+ miter.consumed = lzeros;
+- sg_miter_stop(&miter);
+
+ nbytes -= lzeros;
+ nbits = nbytes * 8;
+ if (nbits > MAX_EXTERN_MPI_BITS) {
++ sg_miter_stop(&miter);
+ pr_info("MPI: mpi too large (%u bits)\n", nbits);
+ return NULL;
+ }
+@@ -376,6 +376,8 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes)
+ if (nbytes > 0)
+ nbits -= count_leading_zeros(*buff) - (BITS_PER_LONG - 8);
+
++ sg_miter_stop(&miter);
++
+ nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB);
+ val = mpi_alloc(nlimbs);
+ if (!val)
+diff --git a/mm/madvise.c b/mm/madvise.c
+index fc6bfbe19a16..738066502ffa 100644
+--- a/mm/madvise.c
++++ b/mm/madvise.c
+@@ -610,6 +610,7 @@ static int madvise_inject_error(int behavior,
+ unsigned long start, unsigned long end)
+ {
+ struct page *page;
++ struct zone *zone;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+@@ -643,6 +644,11 @@ static int madvise_inject_error(int behavior,
+ if (ret)
+ return ret;
+ }
++
++ /* Ensure that all poisoned pages are removed from per-cpu lists */
++ for_each_populated_zone(zone)
++ drain_all_pages(zone);
++
+ return 0;
+ }
+ #endif
+diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
+index 643a18f72032..4ba6513e21fc 100644
+--- a/net/xfrm/xfrm_policy.c
++++ b/net/xfrm/xfrm_policy.c
+@@ -3301,9 +3301,15 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
+ struct xfrm_state *x_new[XFRM_MAX_DEPTH];
+ struct xfrm_migrate *mp;
+
++ /* Stage 0 - sanity checks */
+ if ((err = xfrm_migrate_check(m, num_migrate)) < 0)
+ goto out;
+
++ if (dir >= XFRM_POLICY_MAX) {
++ err = -EINVAL;
++ goto out;
++ }
++
+ /* Stage 1 - find policy */
+ if ((pol = xfrm_migrate_policy_find(sel, dir, type, net)) == NULL) {
+ err = -ENOENT;