mirror of
https://github.com/Fishwaldo/build.git
synced 2025-05-30 19:01:48 +00:00
Kernel patches for Expresssobin. Not booting via bootscript but manually. Need to dig in deeper.
This commit is contained in:
parent
00fd0770ef
commit
1eb2f2a80b
22 changed files with 39683 additions and 253 deletions
File diff suppressed because it is too large
Load diff
|
@ -7,7 +7,7 @@ BOOTSCRIPT="boot-espressobin.cmd:boot.cmd"
|
|||
|
||||
BOOTSOURCE=$MAINLINE_UBOOT_SOURCE
|
||||
BOOTDIR=$MAINLINE_UBOOT_DIR
|
||||
BOOTBRANCH=tag:v2017.05-rc1
|
||||
BOOTBRANCH=$MAINLINE_UBOOT_BRANCH
|
||||
|
||||
|
||||
BOOTENV_FILE='clearfog-default.txt'
|
||||
|
|
8420
patch/kernel/mvebu64-default/03-patch-4.4.52-53.patch
Normal file
8420
patch/kernel/mvebu64-default/03-patch-4.4.52-53.patch
Normal file
File diff suppressed because it is too large
Load diff
1624
patch/kernel/mvebu64-default/03-patch-4.4.53-54.patch
Normal file
1624
patch/kernel/mvebu64-default/03-patch-4.4.53-54.patch
Normal file
File diff suppressed because it is too large
Load diff
1203
patch/kernel/mvebu64-default/03-patch-4.4.54-55.patch
Normal file
1203
patch/kernel/mvebu64-default/03-patch-4.4.54-55.patch
Normal file
File diff suppressed because it is too large
Load diff
2116
patch/kernel/mvebu64-default/03-patch-4.4.55-56.patch
Normal file
2116
patch/kernel/mvebu64-default/03-patch-4.4.55-56.patch
Normal file
File diff suppressed because it is too large
Load diff
1172
patch/kernel/mvebu64-default/03-patch-4.4.56-57.patch
Normal file
1172
patch/kernel/mvebu64-default/03-patch-4.4.56-57.patch
Normal file
File diff suppressed because it is too large
Load diff
2653
patch/kernel/mvebu64-default/03-patch-4.4.57-58.patch
Normal file
2653
patch/kernel/mvebu64-default/03-patch-4.4.57-58.patch
Normal file
File diff suppressed because it is too large
Load diff
548
patch/kernel/mvebu64-default/03-patch-4.4.58-59.patch
Normal file
548
patch/kernel/mvebu64-default/03-patch-4.4.58-59.patch
Normal file
|
@ -0,0 +1,548 @@
|
|||
diff --git a/Makefile b/Makefile
|
||||
index 3efe2ea99e2d..083724c6ca4d 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -1,6 +1,6 @@
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 4
|
||||
-SUBLEVEL = 58
|
||||
+SUBLEVEL = 59
|
||||
EXTRAVERSION =
|
||||
NAME = Blurry Fish Butt
|
||||
|
||||
diff --git a/arch/c6x/kernel/ptrace.c b/arch/c6x/kernel/ptrace.c
|
||||
index 3c494e84444d..a511ac16a8e3 100644
|
||||
--- a/arch/c6x/kernel/ptrace.c
|
||||
+++ b/arch/c6x/kernel/ptrace.c
|
||||
@@ -69,46 +69,6 @@ static int gpr_get(struct task_struct *target,
|
||||
0, sizeof(*regs));
|
||||
}
|
||||
|
||||
-static int gpr_set(struct task_struct *target,
|
||||
- const struct user_regset *regset,
|
||||
- unsigned int pos, unsigned int count,
|
||||
- const void *kbuf, const void __user *ubuf)
|
||||
-{
|
||||
- int ret;
|
||||
- struct pt_regs *regs = task_pt_regs(target);
|
||||
-
|
||||
- /* Don't copyin TSR or CSR */
|
||||
- ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||
- ®s,
|
||||
- 0, PT_TSR * sizeof(long));
|
||||
- if (ret)
|
||||
- return ret;
|
||||
-
|
||||
- ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
|
||||
- PT_TSR * sizeof(long),
|
||||
- (PT_TSR + 1) * sizeof(long));
|
||||
- if (ret)
|
||||
- return ret;
|
||||
-
|
||||
- ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||
- ®s,
|
||||
- (PT_TSR + 1) * sizeof(long),
|
||||
- PT_CSR * sizeof(long));
|
||||
- if (ret)
|
||||
- return ret;
|
||||
-
|
||||
- ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
|
||||
- PT_CSR * sizeof(long),
|
||||
- (PT_CSR + 1) * sizeof(long));
|
||||
- if (ret)
|
||||
- return ret;
|
||||
-
|
||||
- ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||
- ®s,
|
||||
- (PT_CSR + 1) * sizeof(long), -1);
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
enum c6x_regset {
|
||||
REGSET_GPR,
|
||||
};
|
||||
@@ -120,7 +80,6 @@ static const struct user_regset c6x_regsets[] = {
|
||||
.size = sizeof(u32),
|
||||
.align = sizeof(u32),
|
||||
.get = gpr_get,
|
||||
- .set = gpr_set
|
||||
},
|
||||
};
|
||||
|
||||
diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c
|
||||
index 92075544a19a..0dc1c8f622bc 100644
|
||||
--- a/arch/h8300/kernel/ptrace.c
|
||||
+++ b/arch/h8300/kernel/ptrace.c
|
||||
@@ -95,7 +95,8 @@ static int regs_get(struct task_struct *target,
|
||||
long *reg = (long *)®s;
|
||||
|
||||
/* build user regs in buffer */
|
||||
- for (r = 0; r < ARRAY_SIZE(register_offset); r++)
|
||||
+ BUILD_BUG_ON(sizeof(regs) % sizeof(long) != 0);
|
||||
+ for (r = 0; r < sizeof(regs) / sizeof(long); r++)
|
||||
*reg++ = h8300_get_reg(target, r);
|
||||
|
||||
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
||||
@@ -113,7 +114,8 @@ static int regs_set(struct task_struct *target,
|
||||
long *reg;
|
||||
|
||||
/* build user regs in buffer */
|
||||
- for (reg = (long *)®s, r = 0; r < ARRAY_SIZE(register_offset); r++)
|
||||
+ BUILD_BUG_ON(sizeof(regs) % sizeof(long) != 0);
|
||||
+ for (reg = (long *)®s, r = 0; r < sizeof(regs) / sizeof(long); r++)
|
||||
*reg++ = h8300_get_reg(target, r);
|
||||
|
||||
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||
@@ -122,7 +124,7 @@ static int regs_set(struct task_struct *target,
|
||||
return ret;
|
||||
|
||||
/* write back to pt_regs */
|
||||
- for (reg = (long *)®s, r = 0; r < ARRAY_SIZE(register_offset); r++)
|
||||
+ for (reg = (long *)®s, r = 0; r < sizeof(regs) / sizeof(long); r++)
|
||||
h8300_put_reg(target, r, *reg++);
|
||||
return 0;
|
||||
}
|
||||
diff --git a/arch/metag/kernel/ptrace.c b/arch/metag/kernel/ptrace.c
|
||||
index 7563628822bd..5e2dc7defd2c 100644
|
||||
--- a/arch/metag/kernel/ptrace.c
|
||||
+++ b/arch/metag/kernel/ptrace.c
|
||||
@@ -24,6 +24,16 @@
|
||||
* user_regset definitions.
|
||||
*/
|
||||
|
||||
+static unsigned long user_txstatus(const struct pt_regs *regs)
|
||||
+{
|
||||
+ unsigned long data = (unsigned long)regs->ctx.Flags;
|
||||
+
|
||||
+ if (regs->ctx.SaveMask & TBICTX_CBUF_BIT)
|
||||
+ data |= USER_GP_REGS_STATUS_CATCH_BIT;
|
||||
+
|
||||
+ return data;
|
||||
+}
|
||||
+
|
||||
int metag_gp_regs_copyout(const struct pt_regs *regs,
|
||||
unsigned int pos, unsigned int count,
|
||||
void *kbuf, void __user *ubuf)
|
||||
@@ -62,9 +72,7 @@ int metag_gp_regs_copyout(const struct pt_regs *regs,
|
||||
if (ret)
|
||||
goto out;
|
||||
/* TXSTATUS */
|
||||
- data = (unsigned long)regs->ctx.Flags;
|
||||
- if (regs->ctx.SaveMask & TBICTX_CBUF_BIT)
|
||||
- data |= USER_GP_REGS_STATUS_CATCH_BIT;
|
||||
+ data = user_txstatus(regs);
|
||||
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
||||
&data, 4*25, 4*26);
|
||||
if (ret)
|
||||
@@ -119,6 +127,7 @@ int metag_gp_regs_copyin(struct pt_regs *regs,
|
||||
if (ret)
|
||||
goto out;
|
||||
/* TXSTATUS */
|
||||
+ data = user_txstatus(regs);
|
||||
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||
&data, 4*25, 4*26);
|
||||
if (ret)
|
||||
@@ -244,6 +253,8 @@ int metag_rp_state_copyin(struct pt_regs *regs,
|
||||
unsigned long long *ptr;
|
||||
int ret, i;
|
||||
|
||||
+ if (count < 4*13)
|
||||
+ return -EINVAL;
|
||||
/* Read the entire pipeline before making any changes */
|
||||
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||
&rp, 0, 4*13);
|
||||
@@ -303,7 +314,7 @@ static int metag_tls_set(struct task_struct *target,
|
||||
const void *kbuf, const void __user *ubuf)
|
||||
{
|
||||
int ret;
|
||||
- void __user *tls;
|
||||
+ void __user *tls = target->thread.tls_ptr;
|
||||
|
||||
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1);
|
||||
if (ret)
|
||||
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
|
||||
index 74d581569778..c95bf18260f8 100644
|
||||
--- a/arch/mips/kernel/ptrace.c
|
||||
+++ b/arch/mips/kernel/ptrace.c
|
||||
@@ -485,7 +485,8 @@ static int fpr_set(struct task_struct *target,
|
||||
&target->thread.fpu,
|
||||
0, sizeof(elf_fpregset_t));
|
||||
|
||||
- for (i = 0; i < NUM_FPU_REGS; i++) {
|
||||
+ BUILD_BUG_ON(sizeof(fpr_val) != sizeof(elf_fpreg_t));
|
||||
+ for (i = 0; i < NUM_FPU_REGS && count >= sizeof(elf_fpreg_t); i++) {
|
||||
err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||
&fpr_val, i * sizeof(elf_fpreg_t),
|
||||
(i + 1) * sizeof(elf_fpreg_t));
|
||||
diff --git a/arch/sparc/kernel/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c
|
||||
index 9ddc4928a089..c1566170964f 100644
|
||||
--- a/arch/sparc/kernel/ptrace_64.c
|
||||
+++ b/arch/sparc/kernel/ptrace_64.c
|
||||
@@ -311,7 +311,7 @@ static int genregs64_set(struct task_struct *target,
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
- unsigned long y;
|
||||
+ unsigned long y = regs->y;
|
||||
|
||||
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||
&y,
|
||||
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
|
||||
index 146264a41ec8..9736f9be5447 100644
|
||||
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
|
||||
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
|
||||
@@ -597,10 +597,6 @@ static void msm_gpio_irq_unmask(struct irq_data *d)
|
||||
|
||||
spin_lock_irqsave(&pctrl->lock, flags);
|
||||
|
||||
- val = readl(pctrl->regs + g->intr_status_reg);
|
||||
- val &= ~BIT(g->intr_status_bit);
|
||||
- writel(val, pctrl->regs + g->intr_status_reg);
|
||||
-
|
||||
val = readl(pctrl->regs + g->intr_cfg_reg);
|
||||
val |= BIT(g->intr_enable_bit);
|
||||
writel(val, pctrl->regs + g->intr_cfg_reg);
|
||||
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
|
||||
index 56f7e2521202..01d15dca940e 100644
|
||||
--- a/drivers/virtio/virtio_balloon.c
|
||||
+++ b/drivers/virtio/virtio_balloon.c
|
||||
@@ -416,6 +416,8 @@ static int init_vqs(struct virtio_balloon *vb)
|
||||
* Prime this virtqueue with one buffer so the hypervisor can
|
||||
* use it to signal us later (it can't be broken yet!).
|
||||
*/
|
||||
+ update_balloon_stats(vb);
|
||||
+
|
||||
sg_init_one(&sg, vb->stats, sizeof vb->stats);
|
||||
if (virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, GFP_KERNEL)
|
||||
< 0)
|
||||
diff --git a/fs/ext4/crypto_key.c b/fs/ext4/crypto_key.c
|
||||
index 9a16d1e75a49..505f8afde57c 100644
|
||||
--- a/fs/ext4/crypto_key.c
|
||||
+++ b/fs/ext4/crypto_key.c
|
||||
@@ -88,8 +88,6 @@ void ext4_free_crypt_info(struct ext4_crypt_info *ci)
|
||||
if (!ci)
|
||||
return;
|
||||
|
||||
- if (ci->ci_keyring_key)
|
||||
- key_put(ci->ci_keyring_key);
|
||||
crypto_free_ablkcipher(ci->ci_ctfm);
|
||||
kmem_cache_free(ext4_crypt_info_cachep, ci);
|
||||
}
|
||||
@@ -111,7 +109,7 @@ void ext4_free_encryption_info(struct inode *inode,
|
||||
ext4_free_crypt_info(ci);
|
||||
}
|
||||
|
||||
-int _ext4_get_encryption_info(struct inode *inode)
|
||||
+int ext4_get_encryption_info(struct inode *inode)
|
||||
{
|
||||
struct ext4_inode_info *ei = EXT4_I(inode);
|
||||
struct ext4_crypt_info *crypt_info;
|
||||
@@ -128,22 +126,15 @@ int _ext4_get_encryption_info(struct inode *inode)
|
||||
char mode;
|
||||
int res;
|
||||
|
||||
+ if (ei->i_crypt_info)
|
||||
+ return 0;
|
||||
+
|
||||
if (!ext4_read_workqueue) {
|
||||
res = ext4_init_crypto();
|
||||
if (res)
|
||||
return res;
|
||||
}
|
||||
|
||||
-retry:
|
||||
- crypt_info = ACCESS_ONCE(ei->i_crypt_info);
|
||||
- if (crypt_info) {
|
||||
- if (!crypt_info->ci_keyring_key ||
|
||||
- key_validate(crypt_info->ci_keyring_key) == 0)
|
||||
- return 0;
|
||||
- ext4_free_encryption_info(inode, crypt_info);
|
||||
- goto retry;
|
||||
- }
|
||||
-
|
||||
res = ext4_xattr_get(inode, EXT4_XATTR_INDEX_ENCRYPTION,
|
||||
EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
|
||||
&ctx, sizeof(ctx));
|
||||
@@ -166,7 +157,6 @@ retry:
|
||||
crypt_info->ci_data_mode = ctx.contents_encryption_mode;
|
||||
crypt_info->ci_filename_mode = ctx.filenames_encryption_mode;
|
||||
crypt_info->ci_ctfm = NULL;
|
||||
- crypt_info->ci_keyring_key = NULL;
|
||||
memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor,
|
||||
sizeof(crypt_info->ci_master_key));
|
||||
if (S_ISREG(inode->i_mode))
|
||||
@@ -206,7 +196,6 @@ retry:
|
||||
keyring_key = NULL;
|
||||
goto out;
|
||||
}
|
||||
- crypt_info->ci_keyring_key = keyring_key;
|
||||
if (keyring_key->type != &key_type_logon) {
|
||||
printk_once(KERN_WARNING
|
||||
"ext4: key type must be logon\n");
|
||||
@@ -253,16 +242,13 @@ got_key:
|
||||
ext4_encryption_key_size(mode));
|
||||
if (res)
|
||||
goto out;
|
||||
- memzero_explicit(raw_key, sizeof(raw_key));
|
||||
- if (cmpxchg(&ei->i_crypt_info, NULL, crypt_info) != NULL) {
|
||||
- ext4_free_crypt_info(crypt_info);
|
||||
- goto retry;
|
||||
- }
|
||||
- return 0;
|
||||
|
||||
+ if (cmpxchg(&ei->i_crypt_info, NULL, crypt_info) == NULL)
|
||||
+ crypt_info = NULL;
|
||||
out:
|
||||
if (res == -ENOKEY)
|
||||
res = 0;
|
||||
+ key_put(keyring_key);
|
||||
ext4_free_crypt_info(crypt_info);
|
||||
memzero_explicit(raw_key, sizeof(raw_key));
|
||||
return res;
|
||||
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
|
||||
index cd5914495ad7..362d59b24f1d 100644
|
||||
--- a/fs/ext4/ext4.h
|
||||
+++ b/fs/ext4/ext4.h
|
||||
@@ -2330,23 +2330,11 @@ static inline void ext4_fname_free_filename(struct ext4_filename *fname) { }
|
||||
/* crypto_key.c */
|
||||
void ext4_free_crypt_info(struct ext4_crypt_info *ci);
|
||||
void ext4_free_encryption_info(struct inode *inode, struct ext4_crypt_info *ci);
|
||||
-int _ext4_get_encryption_info(struct inode *inode);
|
||||
|
||||
#ifdef CONFIG_EXT4_FS_ENCRYPTION
|
||||
int ext4_has_encryption_key(struct inode *inode);
|
||||
|
||||
-static inline int ext4_get_encryption_info(struct inode *inode)
|
||||
-{
|
||||
- struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info;
|
||||
-
|
||||
- if (!ci ||
|
||||
- (ci->ci_keyring_key &&
|
||||
- (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) |
|
||||
- (1 << KEY_FLAG_REVOKED) |
|
||||
- (1 << KEY_FLAG_DEAD)))))
|
||||
- return _ext4_get_encryption_info(inode);
|
||||
- return 0;
|
||||
-}
|
||||
+int ext4_get_encryption_info(struct inode *inode);
|
||||
|
||||
static inline struct ext4_crypt_info *ext4_encryption_info(struct inode *inode)
|
||||
{
|
||||
diff --git a/fs/ext4/ext4_crypto.h b/fs/ext4/ext4_crypto.h
|
||||
index ac7d4e813796..1b17b05b9f4d 100644
|
||||
--- a/fs/ext4/ext4_crypto.h
|
||||
+++ b/fs/ext4/ext4_crypto.h
|
||||
@@ -78,7 +78,6 @@ struct ext4_crypt_info {
|
||||
char ci_filename_mode;
|
||||
char ci_flags;
|
||||
struct crypto_ablkcipher *ci_ctfm;
|
||||
- struct key *ci_keyring_key;
|
||||
char ci_master_key[EXT4_KEY_DESCRIPTOR_SIZE];
|
||||
};
|
||||
|
||||
diff --git a/fs/f2fs/crypto_key.c b/fs/f2fs/crypto_key.c
|
||||
index 5de2d866a25c..18595d7a0efc 100644
|
||||
--- a/fs/f2fs/crypto_key.c
|
||||
+++ b/fs/f2fs/crypto_key.c
|
||||
@@ -92,7 +92,6 @@ static void f2fs_free_crypt_info(struct f2fs_crypt_info *ci)
|
||||
if (!ci)
|
||||
return;
|
||||
|
||||
- key_put(ci->ci_keyring_key);
|
||||
crypto_free_ablkcipher(ci->ci_ctfm);
|
||||
kmem_cache_free(f2fs_crypt_info_cachep, ci);
|
||||
}
|
||||
@@ -113,7 +112,7 @@ void f2fs_free_encryption_info(struct inode *inode, struct f2fs_crypt_info *ci)
|
||||
f2fs_free_crypt_info(ci);
|
||||
}
|
||||
|
||||
-int _f2fs_get_encryption_info(struct inode *inode)
|
||||
+int f2fs_get_encryption_info(struct inode *inode)
|
||||
{
|
||||
struct f2fs_inode_info *fi = F2FS_I(inode);
|
||||
struct f2fs_crypt_info *crypt_info;
|
||||
@@ -129,18 +128,12 @@ int _f2fs_get_encryption_info(struct inode *inode)
|
||||
char mode;
|
||||
int res;
|
||||
|
||||
+ if (fi->i_crypt_info)
|
||||
+ return 0;
|
||||
+
|
||||
res = f2fs_crypto_initialize();
|
||||
if (res)
|
||||
return res;
|
||||
-retry:
|
||||
- crypt_info = ACCESS_ONCE(fi->i_crypt_info);
|
||||
- if (crypt_info) {
|
||||
- if (!crypt_info->ci_keyring_key ||
|
||||
- key_validate(crypt_info->ci_keyring_key) == 0)
|
||||
- return 0;
|
||||
- f2fs_free_encryption_info(inode, crypt_info);
|
||||
- goto retry;
|
||||
- }
|
||||
|
||||
res = f2fs_getxattr(inode, F2FS_XATTR_INDEX_ENCRYPTION,
|
||||
F2FS_XATTR_NAME_ENCRYPTION_CONTEXT,
|
||||
@@ -159,7 +152,6 @@ retry:
|
||||
crypt_info->ci_data_mode = ctx.contents_encryption_mode;
|
||||
crypt_info->ci_filename_mode = ctx.filenames_encryption_mode;
|
||||
crypt_info->ci_ctfm = NULL;
|
||||
- crypt_info->ci_keyring_key = NULL;
|
||||
memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor,
|
||||
sizeof(crypt_info->ci_master_key));
|
||||
if (S_ISREG(inode->i_mode))
|
||||
@@ -197,7 +189,6 @@ retry:
|
||||
keyring_key = NULL;
|
||||
goto out;
|
||||
}
|
||||
- crypt_info->ci_keyring_key = keyring_key;
|
||||
BUG_ON(keyring_key->type != &key_type_logon);
|
||||
ukp = user_key_payload(keyring_key);
|
||||
if (ukp->datalen != sizeof(struct f2fs_encryption_key)) {
|
||||
@@ -230,17 +221,12 @@ retry:
|
||||
if (res)
|
||||
goto out;
|
||||
|
||||
- memzero_explicit(raw_key, sizeof(raw_key));
|
||||
- if (cmpxchg(&fi->i_crypt_info, NULL, crypt_info) != NULL) {
|
||||
- f2fs_free_crypt_info(crypt_info);
|
||||
- goto retry;
|
||||
- }
|
||||
- return 0;
|
||||
-
|
||||
+ if (cmpxchg(&fi->i_crypt_info, NULL, crypt_info) == NULL)
|
||||
+ crypt_info = NULL;
|
||||
out:
|
||||
if (res == -ENOKEY && !S_ISREG(inode->i_mode))
|
||||
res = 0;
|
||||
-
|
||||
+ key_put(keyring_key);
|
||||
f2fs_free_crypt_info(crypt_info);
|
||||
memzero_explicit(raw_key, sizeof(raw_key));
|
||||
return res;
|
||||
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
|
||||
index 9db5500d63d9..b1aeca83f4be 100644
|
||||
--- a/fs/f2fs/f2fs.h
|
||||
+++ b/fs/f2fs/f2fs.h
|
||||
@@ -2149,7 +2149,6 @@ void f2fs_end_io_crypto_work(struct f2fs_crypto_ctx *, struct bio *);
|
||||
|
||||
/* crypto_key.c */
|
||||
void f2fs_free_encryption_info(struct inode *, struct f2fs_crypt_info *);
|
||||
-int _f2fs_get_encryption_info(struct inode *inode);
|
||||
|
||||
/* crypto_fname.c */
|
||||
bool f2fs_valid_filenames_enc_mode(uint32_t);
|
||||
@@ -2170,18 +2169,7 @@ void f2fs_exit_crypto(void);
|
||||
|
||||
int f2fs_has_encryption_key(struct inode *);
|
||||
|
||||
-static inline int f2fs_get_encryption_info(struct inode *inode)
|
||||
-{
|
||||
- struct f2fs_crypt_info *ci = F2FS_I(inode)->i_crypt_info;
|
||||
-
|
||||
- if (!ci ||
|
||||
- (ci->ci_keyring_key &&
|
||||
- (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) |
|
||||
- (1 << KEY_FLAG_REVOKED) |
|
||||
- (1 << KEY_FLAG_DEAD)))))
|
||||
- return _f2fs_get_encryption_info(inode);
|
||||
- return 0;
|
||||
-}
|
||||
+int f2fs_get_encryption_info(struct inode *inode);
|
||||
|
||||
void f2fs_fname_crypto_free_buffer(struct f2fs_str *);
|
||||
int f2fs_fname_setup_filename(struct inode *, const struct qstr *,
|
||||
diff --git a/fs/f2fs/f2fs_crypto.h b/fs/f2fs/f2fs_crypto.h
|
||||
index c2c1c2b63b25..f113f1a1e8c1 100644
|
||||
--- a/fs/f2fs/f2fs_crypto.h
|
||||
+++ b/fs/f2fs/f2fs_crypto.h
|
||||
@@ -79,7 +79,6 @@ struct f2fs_crypt_info {
|
||||
char ci_filename_mode;
|
||||
char ci_flags;
|
||||
struct crypto_ablkcipher *ci_ctfm;
|
||||
- struct key *ci_keyring_key;
|
||||
char ci_master_key[F2FS_KEY_DESCRIPTOR_SIZE];
|
||||
};
|
||||
|
||||
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
|
||||
index 8b0a15e285f9..e984f059e5fc 100644
|
||||
--- a/kernel/sched/deadline.c
|
||||
+++ b/kernel/sched/deadline.c
|
||||
@@ -1771,12 +1771,11 @@ static void switched_to_dl(struct rq *rq, struct task_struct *p)
|
||||
#ifdef CONFIG_SMP
|
||||
if (p->nr_cpus_allowed > 1 && rq->dl.overloaded)
|
||||
queue_push_tasks(rq);
|
||||
-#else
|
||||
+#endif
|
||||
if (dl_task(rq->curr))
|
||||
check_preempt_curr_dl(rq, p, 0);
|
||||
else
|
||||
resched_curr(rq);
|
||||
-#endif
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
|
||||
index 8ec86abe0ea1..78ae5c1d9412 100644
|
||||
--- a/kernel/sched/rt.c
|
||||
+++ b/kernel/sched/rt.c
|
||||
@@ -2136,10 +2136,9 @@ static void switched_to_rt(struct rq *rq, struct task_struct *p)
|
||||
#ifdef CONFIG_SMP
|
||||
if (p->nr_cpus_allowed > 1 && rq->rt.overloaded)
|
||||
queue_push_tasks(rq);
|
||||
-#else
|
||||
+#endif /* CONFIG_SMP */
|
||||
if (p->prio < rq->curr->prio)
|
||||
resched_curr(rq);
|
||||
-#endif /* CONFIG_SMP */
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
|
||||
index b5e665b3cfb0..36a50ef9295d 100644
|
||||
--- a/net/xfrm/xfrm_policy.c
|
||||
+++ b/net/xfrm/xfrm_policy.c
|
||||
@@ -3030,6 +3030,11 @@ static int __net_init xfrm_net_init(struct net *net)
|
||||
{
|
||||
int rv;
|
||||
|
||||
+ /* Initialize the per-net locks here */
|
||||
+ spin_lock_init(&net->xfrm.xfrm_state_lock);
|
||||
+ rwlock_init(&net->xfrm.xfrm_policy_lock);
|
||||
+ mutex_init(&net->xfrm.xfrm_cfg_mutex);
|
||||
+
|
||||
rv = xfrm_statistics_init(net);
|
||||
if (rv < 0)
|
||||
goto out_statistics;
|
||||
@@ -3046,11 +3051,6 @@ static int __net_init xfrm_net_init(struct net *net)
|
||||
if (rv < 0)
|
||||
goto out;
|
||||
|
||||
- /* Initialize the per-net locks here */
|
||||
- spin_lock_init(&net->xfrm.xfrm_state_lock);
|
||||
- rwlock_init(&net->xfrm.xfrm_policy_lock);
|
||||
- mutex_init(&net->xfrm.xfrm_cfg_mutex);
|
||||
-
|
||||
return 0;
|
||||
|
||||
out:
|
||||
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
|
||||
index 805681a7d356..7a5a64e70b4d 100644
|
||||
--- a/net/xfrm/xfrm_user.c
|
||||
+++ b/net/xfrm/xfrm_user.c
|
||||
@@ -412,7 +412,14 @@ static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_es
|
||||
up = nla_data(rp);
|
||||
ulen = xfrm_replay_state_esn_len(up);
|
||||
|
||||
- if (nla_len(rp) < ulen || xfrm_replay_state_esn_len(replay_esn) != ulen)
|
||||
+ /* Check the overall length and the internal bitmap length to avoid
|
||||
+ * potential overflow. */
|
||||
+ if (nla_len(rp) < ulen ||
|
||||
+ xfrm_replay_state_esn_len(replay_esn) != ulen ||
|
||||
+ replay_esn->bmp_len != up->bmp_len)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (up->replay_window > up->bmp_len * sizeof(__u32) * 8)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
1175
patch/kernel/mvebu64-default/03-patch-4.4.59-60.patch
Normal file
1175
patch/kernel/mvebu64-default/03-patch-4.4.59-60.patch
Normal file
File diff suppressed because it is too large
Load diff
1527
patch/kernel/mvebu64-default/03-patch-4.4.60-61.patch
Normal file
1527
patch/kernel/mvebu64-default/03-patch-4.4.60-61.patch
Normal file
File diff suppressed because it is too large
Load diff
839
patch/kernel/mvebu64-default/03-patch-4.4.61-62.patch
Normal file
839
patch/kernel/mvebu64-default/03-patch-4.4.61-62.patch
Normal file
|
@ -0,0 +1,839 @@
|
|||
diff --git a/Makefile b/Makefile
|
||||
index ef5045b8201d..0309acc34472 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -1,6 +1,6 @@
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 4
|
||||
-SUBLEVEL = 61
|
||||
+SUBLEVEL = 62
|
||||
EXTRAVERSION =
|
||||
NAME = Blurry Fish Butt
|
||||
|
||||
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
|
||||
index 75bfca69e418..d5cfa937d622 100644
|
||||
--- a/arch/mips/Kconfig
|
||||
+++ b/arch/mips/Kconfig
|
||||
@@ -9,6 +9,7 @@ config MIPS
|
||||
select HAVE_CONTEXT_TRACKING
|
||||
select HAVE_GENERIC_DMA_COHERENT
|
||||
select HAVE_IDE
|
||||
+ select HAVE_IRQ_EXIT_ON_IRQ_STACK
|
||||
select HAVE_OPROFILE
|
||||
select HAVE_PERF_EVENTS
|
||||
select PERF_USE_VMALLOC
|
||||
diff --git a/arch/mips/include/asm/irq.h b/arch/mips/include/asm/irq.h
|
||||
index 15e0fecbc300..ebb9efb02502 100644
|
||||
--- a/arch/mips/include/asm/irq.h
|
||||
+++ b/arch/mips/include/asm/irq.h
|
||||
@@ -17,6 +17,18 @@
|
||||
|
||||
#include <irq.h>
|
||||
|
||||
+#define IRQ_STACK_SIZE THREAD_SIZE
|
||||
+
|
||||
+extern void *irq_stack[NR_CPUS];
|
||||
+
|
||||
+static inline bool on_irq_stack(int cpu, unsigned long sp)
|
||||
+{
|
||||
+ unsigned long low = (unsigned long)irq_stack[cpu];
|
||||
+ unsigned long high = low + IRQ_STACK_SIZE;
|
||||
+
|
||||
+ return (low <= sp && sp <= high);
|
||||
+}
|
||||
+
|
||||
#ifdef CONFIG_I8259
|
||||
static inline int irq_canonicalize(int irq)
|
||||
{
|
||||
diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h
|
||||
index a71da576883c..5347f130f536 100644
|
||||
--- a/arch/mips/include/asm/stackframe.h
|
||||
+++ b/arch/mips/include/asm/stackframe.h
|
||||
@@ -216,12 +216,19 @@
|
||||
LONG_S $25, PT_R25(sp)
|
||||
LONG_S $28, PT_R28(sp)
|
||||
LONG_S $31, PT_R31(sp)
|
||||
+
|
||||
+ /* Set thread_info if we're coming from user mode */
|
||||
+ mfc0 k0, CP0_STATUS
|
||||
+ sll k0, 3 /* extract cu0 bit */
|
||||
+ bltz k0, 9f
|
||||
+
|
||||
ori $28, sp, _THREAD_MASK
|
||||
xori $28, _THREAD_MASK
|
||||
#ifdef CONFIG_CPU_CAVIUM_OCTEON
|
||||
.set mips64
|
||||
pref 0, 0($28) /* Prefetch the current pointer */
|
||||
#endif
|
||||
+9:
|
||||
.set pop
|
||||
.endm
|
||||
|
||||
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
|
||||
index 154e2039ea5e..ec053ce7bb38 100644
|
||||
--- a/arch/mips/kernel/asm-offsets.c
|
||||
+++ b/arch/mips/kernel/asm-offsets.c
|
||||
@@ -101,6 +101,7 @@ void output_thread_info_defines(void)
|
||||
OFFSET(TI_REGS, thread_info, regs);
|
||||
DEFINE(_THREAD_SIZE, THREAD_SIZE);
|
||||
DEFINE(_THREAD_MASK, THREAD_MASK);
|
||||
+ DEFINE(_IRQ_STACK_SIZE, IRQ_STACK_SIZE);
|
||||
BLANK();
|
||||
}
|
||||
|
||||
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
|
||||
index baa7b6fc0a60..619e30e2c4f0 100644
|
||||
--- a/arch/mips/kernel/genex.S
|
||||
+++ b/arch/mips/kernel/genex.S
|
||||
@@ -188,9 +188,44 @@ NESTED(handle_int, PT_SIZE, sp)
|
||||
|
||||
LONG_L s0, TI_REGS($28)
|
||||
LONG_S sp, TI_REGS($28)
|
||||
- PTR_LA ra, ret_from_irq
|
||||
- PTR_LA v0, plat_irq_dispatch
|
||||
- jr v0
|
||||
+
|
||||
+ /*
|
||||
+ * SAVE_ALL ensures we are using a valid kernel stack for the thread.
|
||||
+ * Check if we are already using the IRQ stack.
|
||||
+ */
|
||||
+ move s1, sp # Preserve the sp
|
||||
+
|
||||
+ /* Get IRQ stack for this CPU */
|
||||
+ ASM_CPUID_MFC0 k0, ASM_SMP_CPUID_REG
|
||||
+#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
|
||||
+ lui k1, %hi(irq_stack)
|
||||
+#else
|
||||
+ lui k1, %highest(irq_stack)
|
||||
+ daddiu k1, %higher(irq_stack)
|
||||
+ dsll k1, 16
|
||||
+ daddiu k1, %hi(irq_stack)
|
||||
+ dsll k1, 16
|
||||
+#endif
|
||||
+ LONG_SRL k0, SMP_CPUID_PTRSHIFT
|
||||
+ LONG_ADDU k1, k0
|
||||
+ LONG_L t0, %lo(irq_stack)(k1)
|
||||
+
|
||||
+ # Check if already on IRQ stack
|
||||
+ PTR_LI t1, ~(_THREAD_SIZE-1)
|
||||
+ and t1, t1, sp
|
||||
+ beq t0, t1, 2f
|
||||
+
|
||||
+ /* Switch to IRQ stack */
|
||||
+ li t1, _IRQ_STACK_SIZE
|
||||
+ PTR_ADD sp, t0, t1
|
||||
+
|
||||
+2:
|
||||
+ jal plat_irq_dispatch
|
||||
+
|
||||
+ /* Restore sp */
|
||||
+ move sp, s1
|
||||
+
|
||||
+ j ret_from_irq
|
||||
#ifdef CONFIG_CPU_MICROMIPS
|
||||
nop
|
||||
#endif
|
||||
@@ -263,8 +298,44 @@ NESTED(except_vec_vi_handler, 0, sp)
|
||||
|
||||
LONG_L s0, TI_REGS($28)
|
||||
LONG_S sp, TI_REGS($28)
|
||||
- PTR_LA ra, ret_from_irq
|
||||
- jr v0
|
||||
+
|
||||
+ /*
|
||||
+ * SAVE_ALL ensures we are using a valid kernel stack for the thread.
|
||||
+ * Check if we are already using the IRQ stack.
|
||||
+ */
|
||||
+ move s1, sp # Preserve the sp
|
||||
+
|
||||
+ /* Get IRQ stack for this CPU */
|
||||
+ ASM_CPUID_MFC0 k0, ASM_SMP_CPUID_REG
|
||||
+#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
|
||||
+ lui k1, %hi(irq_stack)
|
||||
+#else
|
||||
+ lui k1, %highest(irq_stack)
|
||||
+ daddiu k1, %higher(irq_stack)
|
||||
+ dsll k1, 16
|
||||
+ daddiu k1, %hi(irq_stack)
|
||||
+ dsll k1, 16
|
||||
+#endif
|
||||
+ LONG_SRL k0, SMP_CPUID_PTRSHIFT
|
||||
+ LONG_ADDU k1, k0
|
||||
+ LONG_L t0, %lo(irq_stack)(k1)
|
||||
+
|
||||
+ # Check if already on IRQ stack
|
||||
+ PTR_LI t1, ~(_THREAD_SIZE-1)
|
||||
+ and t1, t1, sp
|
||||
+ beq t0, t1, 2f
|
||||
+
|
||||
+ /* Switch to IRQ stack */
|
||||
+ li t1, _IRQ_STACK_SIZE
|
||||
+ PTR_ADD sp, t0, t1
|
||||
+
|
||||
+2:
|
||||
+ jalr v0
|
||||
+
|
||||
+ /* Restore sp */
|
||||
+ move sp, s1
|
||||
+
|
||||
+ j ret_from_irq
|
||||
END(except_vec_vi_handler)
|
||||
|
||||
/*
|
||||
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
|
||||
index 8eb5af805964..dc1180a8bfa1 100644
|
||||
--- a/arch/mips/kernel/irq.c
|
||||
+++ b/arch/mips/kernel/irq.c
|
||||
@@ -25,6 +25,8 @@
|
||||
#include <linux/atomic.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
+void *irq_stack[NR_CPUS];
|
||||
+
|
||||
/*
|
||||
* 'what should we do if we get a hw irq event on an illegal vector'.
|
||||
* each architecture has to answer this themselves.
|
||||
@@ -55,6 +57,15 @@ void __init init_IRQ(void)
|
||||
irq_set_noprobe(i);
|
||||
|
||||
arch_init_irq();
|
||||
+
|
||||
+ for_each_possible_cpu(i) {
|
||||
+ int irq_pages = IRQ_STACK_SIZE / PAGE_SIZE;
|
||||
+ void *s = (void *)__get_free_pages(GFP_KERNEL, irq_pages);
|
||||
+
|
||||
+ irq_stack[i] = s;
|
||||
+ pr_debug("CPU%d IRQ stack at 0x%p - 0x%p\n", i,
|
||||
+ irq_stack[i], irq_stack[i] + IRQ_STACK_SIZE);
|
||||
+ }
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_STACKOVERFLOW
|
||||
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
|
||||
index fc537d1b649d..8c26ecac930d 100644
|
||||
--- a/arch/mips/kernel/process.c
|
||||
+++ b/arch/mips/kernel/process.c
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/dsp.h>
|
||||
#include <asm/fpu.h>
|
||||
+#include <asm/irq.h>
|
||||
#include <asm/msa.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/mipsregs.h>
|
||||
@@ -552,7 +553,19 @@ EXPORT_SYMBOL(unwind_stack_by_address);
|
||||
unsigned long unwind_stack(struct task_struct *task, unsigned long *sp,
|
||||
unsigned long pc, unsigned long *ra)
|
||||
{
|
||||
- unsigned long stack_page = (unsigned long)task_stack_page(task);
|
||||
+ unsigned long stack_page = 0;
|
||||
+ int cpu;
|
||||
+
|
||||
+ for_each_possible_cpu(cpu) {
|
||||
+ if (on_irq_stack(cpu, *sp)) {
|
||||
+ stack_page = (unsigned long)irq_stack[cpu];
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!stack_page)
|
||||
+ stack_page = (unsigned long)task_stack_page(task);
|
||||
+
|
||||
return unwind_stack_by_address(stack_page, sp, pc, ra);
|
||||
}
|
||||
#endif
|
||||
diff --git a/block/blk-mq.c b/block/blk-mq.c
|
||||
index d8d63c38bf29..0d1af3e44efb 100644
|
||||
--- a/block/blk-mq.c
|
||||
+++ b/block/blk-mq.c
|
||||
@@ -1470,7 +1470,7 @@ static struct blk_mq_tags *blk_mq_init_rq_map(struct blk_mq_tag_set *set,
|
||||
INIT_LIST_HEAD(&tags->page_list);
|
||||
|
||||
tags->rqs = kzalloc_node(set->queue_depth * sizeof(struct request *),
|
||||
- GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY,
|
||||
+ GFP_NOIO | __GFP_NOWARN | __GFP_NORETRY,
|
||||
set->numa_node);
|
||||
if (!tags->rqs) {
|
||||
blk_mq_free_tags(tags);
|
||||
@@ -1496,7 +1496,7 @@ static struct blk_mq_tags *blk_mq_init_rq_map(struct blk_mq_tag_set *set,
|
||||
|
||||
do {
|
||||
page = alloc_pages_node(set->numa_node,
|
||||
- GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY | __GFP_ZERO,
|
||||
+ GFP_NOIO | __GFP_NOWARN | __GFP_NORETRY | __GFP_ZERO,
|
||||
this_order);
|
||||
if (page)
|
||||
break;
|
||||
@@ -1517,7 +1517,7 @@ static struct blk_mq_tags *blk_mq_init_rq_map(struct blk_mq_tag_set *set,
|
||||
* Allow kmemleak to scan these pages as they contain pointers
|
||||
* to additional allocations like via ops->init_request().
|
||||
*/
|
||||
- kmemleak_alloc(p, order_to_size(this_order), 1, GFP_KERNEL);
|
||||
+ kmemleak_alloc(p, order_to_size(this_order), 1, GFP_NOIO);
|
||||
entries_per_page = order_to_size(this_order) / rq_size;
|
||||
to_do = min(entries_per_page, set->queue_depth - i);
|
||||
left -= to_do * rq_size;
|
||||
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
|
||||
index 69d4a1326fee..53e61459c69f 100644
|
||||
--- a/drivers/crypto/caam/ctrl.c
|
||||
+++ b/drivers/crypto/caam/ctrl.c
|
||||
@@ -278,7 +278,8 @@ static int deinstantiate_rng(struct device *ctrldev, int state_handle_mask)
|
||||
/* Try to run it through DECO0 */
|
||||
ret = run_descriptor_deco0(ctrldev, desc, &status);
|
||||
|
||||
- if (ret || status) {
|
||||
+ if (ret ||
|
||||
+ (status && status != JRSTA_SSRC_JUMP_HALT_CC)) {
|
||||
dev_err(ctrldev,
|
||||
"Failed to deinstantiate RNG4 SH%d\n",
|
||||
sh_idx);
|
||||
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
|
||||
index fb9f647bb5cd..5044f2257e89 100644
|
||||
--- a/drivers/gpu/drm/i915/i915_drv.h
|
||||
+++ b/drivers/gpu/drm/i915/i915_drv.h
|
||||
@@ -1159,7 +1159,7 @@ struct intel_gen6_power_mgmt {
|
||||
struct intel_rps_client semaphores, mmioflips;
|
||||
|
||||
/* manual wa residency calculations */
|
||||
- struct intel_rps_ei up_ei, down_ei;
|
||||
+ struct intel_rps_ei ei;
|
||||
|
||||
/*
|
||||
* Protects RPS/RC6 register access and PCU communication.
|
||||
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
|
||||
index 0f42a2782afc..b7b0a38acd67 100644
|
||||
--- a/drivers/gpu/drm/i915/i915_irq.c
|
||||
+++ b/drivers/gpu/drm/i915/i915_irq.c
|
||||
@@ -994,68 +994,51 @@ static void vlv_c0_read(struct drm_i915_private *dev_priv,
|
||||
ei->media_c0 = I915_READ(VLV_MEDIA_C0_COUNT);
|
||||
}
|
||||
|
||||
-static bool vlv_c0_above(struct drm_i915_private *dev_priv,
|
||||
- const struct intel_rps_ei *old,
|
||||
- const struct intel_rps_ei *now,
|
||||
- int threshold)
|
||||
-{
|
||||
- u64 time, c0;
|
||||
- unsigned int mul = 100;
|
||||
-
|
||||
- if (old->cz_clock == 0)
|
||||
- return false;
|
||||
-
|
||||
- if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
|
||||
- mul <<= 8;
|
||||
-
|
||||
- time = now->cz_clock - old->cz_clock;
|
||||
- time *= threshold * dev_priv->czclk_freq;
|
||||
-
|
||||
- /* Workload can be split between render + media, e.g. SwapBuffers
|
||||
- * being blitted in X after being rendered in mesa. To account for
|
||||
- * this we need to combine both engines into our activity counter.
|
||||
- */
|
||||
- c0 = now->render_c0 - old->render_c0;
|
||||
- c0 += now->media_c0 - old->media_c0;
|
||||
- c0 *= mul * VLV_CZ_CLOCK_TO_MILLI_SEC;
|
||||
-
|
||||
- return c0 >= time;
|
||||
-}
|
||||
-
|
||||
void gen6_rps_reset_ei(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
- vlv_c0_read(dev_priv, &dev_priv->rps.down_ei);
|
||||
- dev_priv->rps.up_ei = dev_priv->rps.down_ei;
|
||||
+ memset(&dev_priv->rps.ei, 0, sizeof(dev_priv->rps.ei));
|
||||
}
|
||||
|
||||
static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir)
|
||||
{
|
||||
+ const struct intel_rps_ei *prev = &dev_priv->rps.ei;
|
||||
struct intel_rps_ei now;
|
||||
u32 events = 0;
|
||||
|
||||
- if ((pm_iir & (GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED)) == 0)
|
||||
+ if ((pm_iir & GEN6_PM_RP_UP_EI_EXPIRED) == 0)
|
||||
return 0;
|
||||
|
||||
vlv_c0_read(dev_priv, &now);
|
||||
if (now.cz_clock == 0)
|
||||
return 0;
|
||||
|
||||
- if (pm_iir & GEN6_PM_RP_DOWN_EI_EXPIRED) {
|
||||
- if (!vlv_c0_above(dev_priv,
|
||||
- &dev_priv->rps.down_ei, &now,
|
||||
- dev_priv->rps.down_threshold))
|
||||
- events |= GEN6_PM_RP_DOWN_THRESHOLD;
|
||||
- dev_priv->rps.down_ei = now;
|
||||
- }
|
||||
+ if (prev->cz_clock) {
|
||||
+ u64 time, c0;
|
||||
+ unsigned int mul;
|
||||
|
||||
- if (pm_iir & GEN6_PM_RP_UP_EI_EXPIRED) {
|
||||
- if (vlv_c0_above(dev_priv,
|
||||
- &dev_priv->rps.up_ei, &now,
|
||||
- dev_priv->rps.up_threshold))
|
||||
- events |= GEN6_PM_RP_UP_THRESHOLD;
|
||||
- dev_priv->rps.up_ei = now;
|
||||
+ mul = VLV_CZ_CLOCK_TO_MILLI_SEC * 100; /* scale to threshold% */
|
||||
+ if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
|
||||
+ mul <<= 8;
|
||||
+
|
||||
+ time = now.cz_clock - prev->cz_clock;
|
||||
+ time *= dev_priv->czclk_freq;
|
||||
+
|
||||
+ /* Workload can be split between render + media,
|
||||
+ * e.g. SwapBuffers being blitted in X after being rendered in
|
||||
+ * mesa. To account for this we need to combine both engines
|
||||
+ * into our activity counter.
|
||||
+ */
|
||||
+ c0 = now.render_c0 - prev->render_c0;
|
||||
+ c0 += now.media_c0 - prev->media_c0;
|
||||
+ c0 *= mul;
|
||||
+
|
||||
+ if (c0 > time * dev_priv->rps.up_threshold)
|
||||
+ events = GEN6_PM_RP_UP_THRESHOLD;
|
||||
+ else if (c0 < time * dev_priv->rps.down_threshold)
|
||||
+ events = GEN6_PM_RP_DOWN_THRESHOLD;
|
||||
}
|
||||
|
||||
+ dev_priv->rps.ei = now;
|
||||
return events;
|
||||
}
|
||||
|
||||
@@ -4390,7 +4373,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
|
||||
/* Let's track the enabled rps events */
|
||||
if (IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv))
|
||||
/* WaGsvRC0ResidencyMethod:vlv */
|
||||
- dev_priv->pm_rps_events = GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED;
|
||||
+ dev_priv->pm_rps_events = GEN6_PM_RP_UP_EI_EXPIRED;
|
||||
else
|
||||
dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS;
|
||||
|
||||
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
|
||||
index e7c18519274a..fd4690ed93c0 100644
|
||||
--- a/drivers/gpu/drm/i915/intel_pm.c
|
||||
+++ b/drivers/gpu/drm/i915/intel_pm.c
|
||||
@@ -4376,6 +4376,12 @@ static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val)
|
||||
break;
|
||||
}
|
||||
|
||||
+ /* When byt can survive without system hang with dynamic
|
||||
+ * sw freq adjustments, this restriction can be lifted.
|
||||
+ */
|
||||
+ if (IS_VALLEYVIEW(dev_priv))
|
||||
+ goto skip_hw_write;
|
||||
+
|
||||
I915_WRITE(GEN6_RP_UP_EI,
|
||||
GT_INTERVAL_FROM_US(dev_priv, ei_up));
|
||||
I915_WRITE(GEN6_RP_UP_THRESHOLD,
|
||||
@@ -4394,6 +4400,7 @@ static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val)
|
||||
GEN6_RP_UP_BUSY_AVG |
|
||||
GEN6_RP_DOWN_IDLE_AVG);
|
||||
|
||||
+skip_hw_write:
|
||||
dev_priv->rps.power = new_power;
|
||||
dev_priv->rps.up_threshold = threshold_up;
|
||||
dev_priv->rps.down_threshold = threshold_down;
|
||||
@@ -4404,8 +4411,9 @@ static u32 gen6_rps_pm_mask(struct drm_i915_private *dev_priv, u8 val)
|
||||
{
|
||||
u32 mask = 0;
|
||||
|
||||
+ /* We use UP_EI_EXPIRED interupts for both up/down in manual mode */
|
||||
if (val > dev_priv->rps.min_freq_softlimit)
|
||||
- mask |= GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_DOWN_THRESHOLD | GEN6_PM_RP_DOWN_TIMEOUT;
|
||||
+ mask |= GEN6_PM_RP_UP_EI_EXPIRED | GEN6_PM_RP_DOWN_THRESHOLD | GEN6_PM_RP_DOWN_TIMEOUT;
|
||||
if (val < dev_priv->rps.max_freq_softlimit)
|
||||
mask |= GEN6_PM_RP_UP_EI_EXPIRED | GEN6_PM_RP_UP_THRESHOLD;
|
||||
|
||||
@@ -4509,7 +4517,7 @@ void gen6_rps_busy(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
mutex_lock(&dev_priv->rps.hw_lock);
|
||||
if (dev_priv->rps.enabled) {
|
||||
- if (dev_priv->pm_rps_events & (GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED))
|
||||
+ if (dev_priv->pm_rps_events & GEN6_PM_RP_UP_EI_EXPIRED)
|
||||
gen6_rps_reset_ei(dev_priv);
|
||||
I915_WRITE(GEN6_PMINTRMSK,
|
||||
gen6_rps_pm_mask(dev_priv, dev_priv->rps.cur_freq));
|
||||
diff --git a/drivers/mtd/bcm47xxpart.c b/drivers/mtd/bcm47xxpart.c
|
||||
index c0720c1ee4c9..5abab8800891 100644
|
||||
--- a/drivers/mtd/bcm47xxpart.c
|
||||
+++ b/drivers/mtd/bcm47xxpart.c
|
||||
@@ -225,12 +225,10 @@ static int bcm47xxpart_parse(struct mtd_info *master,
|
||||
|
||||
last_trx_part = curr_part - 1;
|
||||
|
||||
- /*
|
||||
- * We have whole TRX scanned, skip to the next part. Use
|
||||
- * roundown (not roundup), as the loop will increase
|
||||
- * offset in next step.
|
||||
- */
|
||||
- offset = rounddown(offset + trx->length, blocksize);
|
||||
+ /* Jump to the end of TRX */
|
||||
+ offset = roundup(offset + trx->length, blocksize);
|
||||
+ /* Next loop iteration will increase the offset */
|
||||
+ offset -= blocksize;
|
||||
continue;
|
||||
}
|
||||
|
||||
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
|
||||
index 7af870a3c549..855c43d8f7e0 100644
|
||||
--- a/drivers/net/ethernet/ibm/ibmveth.c
|
||||
+++ b/drivers/net/ethernet/ibm/ibmveth.c
|
||||
@@ -58,7 +58,7 @@ static struct kobj_type ktype_veth_pool;
|
||||
|
||||
static const char ibmveth_driver_name[] = "ibmveth";
|
||||
static const char ibmveth_driver_string[] = "IBM Power Virtual Ethernet Driver";
|
||||
-#define ibmveth_driver_version "1.05"
|
||||
+#define ibmveth_driver_version "1.06"
|
||||
|
||||
MODULE_AUTHOR("Santiago Leon <santil@linux.vnet.ibm.com>");
|
||||
MODULE_DESCRIPTION("IBM Power Virtual Ethernet Driver");
|
||||
@@ -137,6 +137,11 @@ static inline int ibmveth_rxq_frame_offset(struct ibmveth_adapter *adapter)
|
||||
return ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_OFF_MASK;
|
||||
}
|
||||
|
||||
+static inline int ibmveth_rxq_large_packet(struct ibmveth_adapter *adapter)
|
||||
+{
|
||||
+ return ibmveth_rxq_flags(adapter) & IBMVETH_RXQ_LRG_PKT;
|
||||
+}
|
||||
+
|
||||
static inline int ibmveth_rxq_frame_length(struct ibmveth_adapter *adapter)
|
||||
{
|
||||
return be32_to_cpu(adapter->rx_queue.queue_addr[adapter->rx_queue.index].length);
|
||||
@@ -1172,6 +1177,45 @@ map_failed:
|
||||
goto retry_bounce;
|
||||
}
|
||||
|
||||
+static void ibmveth_rx_mss_helper(struct sk_buff *skb, u16 mss, int lrg_pkt)
|
||||
+{
|
||||
+ int offset = 0;
|
||||
+
|
||||
+ /* only TCP packets will be aggregated */
|
||||
+ if (skb->protocol == htons(ETH_P_IP)) {
|
||||
+ struct iphdr *iph = (struct iphdr *)skb->data;
|
||||
+
|
||||
+ if (iph->protocol == IPPROTO_TCP) {
|
||||
+ offset = iph->ihl * 4;
|
||||
+ skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
|
||||
+ } else {
|
||||
+ return;
|
||||
+ }
|
||||
+ } else if (skb->protocol == htons(ETH_P_IPV6)) {
|
||||
+ struct ipv6hdr *iph6 = (struct ipv6hdr *)skb->data;
|
||||
+
|
||||
+ if (iph6->nexthdr == IPPROTO_TCP) {
|
||||
+ offset = sizeof(struct ipv6hdr);
|
||||
+ skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
|
||||
+ } else {
|
||||
+ return;
|
||||
+ }
|
||||
+ } else {
|
||||
+ return;
|
||||
+ }
|
||||
+ /* if mss is not set through Large Packet bit/mss in rx buffer,
|
||||
+ * expect that the mss will be written to the tcp header checksum.
|
||||
+ */
|
||||
+ if (lrg_pkt) {
|
||||
+ skb_shinfo(skb)->gso_size = mss;
|
||||
+ } else if (offset) {
|
||||
+ struct tcphdr *tcph = (struct tcphdr *)(skb->data + offset);
|
||||
+
|
||||
+ skb_shinfo(skb)->gso_size = ntohs(tcph->check);
|
||||
+ tcph->check = 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int ibmveth_poll(struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct ibmveth_adapter *adapter =
|
||||
@@ -1180,6 +1224,7 @@ static int ibmveth_poll(struct napi_struct *napi, int budget)
|
||||
int frames_processed = 0;
|
||||
unsigned long lpar_rc;
|
||||
struct iphdr *iph;
|
||||
+ u16 mss = 0;
|
||||
|
||||
restart_poll:
|
||||
while (frames_processed < budget) {
|
||||
@@ -1197,9 +1242,21 @@ restart_poll:
|
||||
int length = ibmveth_rxq_frame_length(adapter);
|
||||
int offset = ibmveth_rxq_frame_offset(adapter);
|
||||
int csum_good = ibmveth_rxq_csum_good(adapter);
|
||||
+ int lrg_pkt = ibmveth_rxq_large_packet(adapter);
|
||||
|
||||
skb = ibmveth_rxq_get_buffer(adapter);
|
||||
|
||||
+ /* if the large packet bit is set in the rx queue
|
||||
+ * descriptor, the mss will be written by PHYP eight
|
||||
+ * bytes from the start of the rx buffer, which is
|
||||
+ * skb->data at this stage
|
||||
+ */
|
||||
+ if (lrg_pkt) {
|
||||
+ __be64 *rxmss = (__be64 *)(skb->data + 8);
|
||||
+
|
||||
+ mss = (u16)be64_to_cpu(*rxmss);
|
||||
+ }
|
||||
+
|
||||
new_skb = NULL;
|
||||
if (length < rx_copybreak)
|
||||
new_skb = netdev_alloc_skb(netdev, length);
|
||||
@@ -1233,11 +1290,15 @@ restart_poll:
|
||||
if (iph->check == 0xffff) {
|
||||
iph->check = 0;
|
||||
iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
|
||||
- adapter->rx_large_packets++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ if (length > netdev->mtu + ETH_HLEN) {
|
||||
+ ibmveth_rx_mss_helper(skb, mss, lrg_pkt);
|
||||
+ adapter->rx_large_packets++;
|
||||
+ }
|
||||
+
|
||||
napi_gro_receive(napi, skb); /* send it up */
|
||||
|
||||
netdev->stats.rx_packets++;
|
||||
diff --git a/drivers/net/ethernet/ibm/ibmveth.h b/drivers/net/ethernet/ibm/ibmveth.h
|
||||
index 4eade67fe30c..7acda04d034e 100644
|
||||
--- a/drivers/net/ethernet/ibm/ibmveth.h
|
||||
+++ b/drivers/net/ethernet/ibm/ibmveth.h
|
||||
@@ -209,6 +209,7 @@ struct ibmveth_rx_q_entry {
|
||||
#define IBMVETH_RXQ_TOGGLE 0x80000000
|
||||
#define IBMVETH_RXQ_TOGGLE_SHIFT 31
|
||||
#define IBMVETH_RXQ_VALID 0x40000000
|
||||
+#define IBMVETH_RXQ_LRG_PKT 0x04000000
|
||||
#define IBMVETH_RXQ_NO_CSUM 0x02000000
|
||||
#define IBMVETH_RXQ_CSUM_GOOD 0x01000000
|
||||
#define IBMVETH_RXQ_OFF_MASK 0x0000FFFF
|
||||
diff --git a/drivers/net/ethernet/mellanox/mlx4/cq.c b/drivers/net/ethernet/mellanox/mlx4/cq.c
|
||||
index 3348e646db70..6eba58044456 100644
|
||||
--- a/drivers/net/ethernet/mellanox/mlx4/cq.c
|
||||
+++ b/drivers/net/ethernet/mellanox/mlx4/cq.c
|
||||
@@ -101,13 +101,19 @@ void mlx4_cq_completion(struct mlx4_dev *dev, u32 cqn)
|
||||
{
|
||||
struct mlx4_cq *cq;
|
||||
|
||||
+ rcu_read_lock();
|
||||
cq = radix_tree_lookup(&mlx4_priv(dev)->cq_table.tree,
|
||||
cqn & (dev->caps.num_cqs - 1));
|
||||
+ rcu_read_unlock();
|
||||
+
|
||||
if (!cq) {
|
||||
mlx4_dbg(dev, "Completion event for bogus CQ %08x\n", cqn);
|
||||
return;
|
||||
}
|
||||
|
||||
+ /* Acessing the CQ outside of rcu_read_lock is safe, because
|
||||
+ * the CQ is freed only after interrupt handling is completed.
|
||||
+ */
|
||||
++cq->arm_sn;
|
||||
|
||||
cq->comp(cq);
|
||||
@@ -118,23 +124,19 @@ void mlx4_cq_event(struct mlx4_dev *dev, u32 cqn, int event_type)
|
||||
struct mlx4_cq_table *cq_table = &mlx4_priv(dev)->cq_table;
|
||||
struct mlx4_cq *cq;
|
||||
|
||||
- spin_lock(&cq_table->lock);
|
||||
-
|
||||
+ rcu_read_lock();
|
||||
cq = radix_tree_lookup(&cq_table->tree, cqn & (dev->caps.num_cqs - 1));
|
||||
- if (cq)
|
||||
- atomic_inc(&cq->refcount);
|
||||
-
|
||||
- spin_unlock(&cq_table->lock);
|
||||
+ rcu_read_unlock();
|
||||
|
||||
if (!cq) {
|
||||
- mlx4_warn(dev, "Async event for bogus CQ %08x\n", cqn);
|
||||
+ mlx4_dbg(dev, "Async event for bogus CQ %08x\n", cqn);
|
||||
return;
|
||||
}
|
||||
|
||||
+ /* Acessing the CQ outside of rcu_read_lock is safe, because
|
||||
+ * the CQ is freed only after interrupt handling is completed.
|
||||
+ */
|
||||
cq->event(cq, event_type);
|
||||
-
|
||||
- if (atomic_dec_and_test(&cq->refcount))
|
||||
- complete(&cq->free);
|
||||
}
|
||||
|
||||
static int mlx4_SW2HW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
|
||||
@@ -301,9 +303,9 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- spin_lock_irq(&cq_table->lock);
|
||||
+ spin_lock(&cq_table->lock);
|
||||
err = radix_tree_insert(&cq_table->tree, cq->cqn, cq);
|
||||
- spin_unlock_irq(&cq_table->lock);
|
||||
+ spin_unlock(&cq_table->lock);
|
||||
if (err)
|
||||
goto err_icm;
|
||||
|
||||
@@ -347,9 +349,9 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent,
|
||||
return 0;
|
||||
|
||||
err_radix:
|
||||
- spin_lock_irq(&cq_table->lock);
|
||||
+ spin_lock(&cq_table->lock);
|
||||
radix_tree_delete(&cq_table->tree, cq->cqn);
|
||||
- spin_unlock_irq(&cq_table->lock);
|
||||
+ spin_unlock(&cq_table->lock);
|
||||
|
||||
err_icm:
|
||||
mlx4_cq_free_icm(dev, cq->cqn);
|
||||
@@ -368,15 +370,15 @@ void mlx4_cq_free(struct mlx4_dev *dev, struct mlx4_cq *cq)
|
||||
if (err)
|
||||
mlx4_warn(dev, "HW2SW_CQ failed (%d) for CQN %06x\n", err, cq->cqn);
|
||||
|
||||
+ spin_lock(&cq_table->lock);
|
||||
+ radix_tree_delete(&cq_table->tree, cq->cqn);
|
||||
+ spin_unlock(&cq_table->lock);
|
||||
+
|
||||
synchronize_irq(priv->eq_table.eq[MLX4_CQ_TO_EQ_VECTOR(cq->vector)].irq);
|
||||
if (priv->eq_table.eq[MLX4_CQ_TO_EQ_VECTOR(cq->vector)].irq !=
|
||||
priv->eq_table.eq[MLX4_EQ_ASYNC].irq)
|
||||
synchronize_irq(priv->eq_table.eq[MLX4_EQ_ASYNC].irq);
|
||||
|
||||
- spin_lock_irq(&cq_table->lock);
|
||||
- radix_tree_delete(&cq_table->tree, cq->cqn);
|
||||
- spin_unlock_irq(&cq_table->lock);
|
||||
-
|
||||
if (atomic_dec_and_test(&cq->refcount))
|
||||
complete(&cq->free);
|
||||
wait_for_completion(&cq->free);
|
||||
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
|
||||
index 28a4b34310b2..82bf1b539d87 100644
|
||||
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
|
||||
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
|
||||
@@ -439,8 +439,14 @@ int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv)
|
||||
ring->cqn = priv->rx_cq[ring_ind]->mcq.cqn;
|
||||
|
||||
ring->stride = stride;
|
||||
- if (ring->stride <= TXBB_SIZE)
|
||||
+ if (ring->stride <= TXBB_SIZE) {
|
||||
+ /* Stamp first unused send wqe */
|
||||
+ __be32 *ptr = (__be32 *)ring->buf;
|
||||
+ __be32 stamp = cpu_to_be32(1 << STAMP_SHIFT);
|
||||
+ *ptr = stamp;
|
||||
+ /* Move pointer to start of rx section */
|
||||
ring->buf += TXBB_SIZE;
|
||||
+ }
|
||||
|
||||
ring->log_stride = ffs(ring->stride) - 1;
|
||||
ring->buf_size = ring->size * ring->stride;
|
||||
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
|
||||
index d314d96dcb1c..d1fc7fa87b05 100644
|
||||
--- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
|
||||
+++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
|
||||
@@ -2955,6 +2955,9 @@ int mlx4_RST2INIT_QP_wrapper(struct mlx4_dev *dev, int slave,
|
||||
put_res(dev, slave, srqn, RES_SRQ);
|
||||
qp->srq = srq;
|
||||
}
|
||||
+
|
||||
+ /* Save param3 for dynamic changes from VST back to VGT */
|
||||
+ qp->param3 = qpc->param3;
|
||||
put_res(dev, slave, rcqn, RES_CQ);
|
||||
put_res(dev, slave, mtt_base, RES_MTT);
|
||||
res_end_move(dev, slave, RES_QP, qpn);
|
||||
@@ -3747,7 +3750,6 @@ int mlx4_INIT2RTR_QP_wrapper(struct mlx4_dev *dev, int slave,
|
||||
int qpn = vhcr->in_modifier & 0x7fffff;
|
||||
struct res_qp *qp;
|
||||
u8 orig_sched_queue;
|
||||
- __be32 orig_param3 = qpc->param3;
|
||||
u8 orig_vlan_control = qpc->pri_path.vlan_control;
|
||||
u8 orig_fvl_rx = qpc->pri_path.fvl_rx;
|
||||
u8 orig_pri_path_fl = qpc->pri_path.fl;
|
||||
@@ -3789,7 +3791,6 @@ out:
|
||||
*/
|
||||
if (!err) {
|
||||
qp->sched_queue = orig_sched_queue;
|
||||
- qp->param3 = orig_param3;
|
||||
qp->vlan_control = orig_vlan_control;
|
||||
qp->fvl_rx = orig_fvl_rx;
|
||||
qp->pri_path_fl = orig_pri_path_fl;
|
||||
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
|
||||
index 9e62c93af96e..7c2d87befb51 100644
|
||||
--- a/drivers/usb/core/hub.c
|
||||
+++ b/drivers/usb/core/hub.c
|
||||
@@ -2602,8 +2602,15 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
- /* The port state is unknown until the reset completes. */
|
||||
- if (!(portstatus & USB_PORT_STAT_RESET))
|
||||
+ /*
|
||||
+ * The port state is unknown until the reset completes.
|
||||
+ *
|
||||
+ * On top of that, some chips may require additional time
|
||||
+ * to re-establish a connection after the reset is complete,
|
||||
+ * so also wait for the connection to be re-established.
|
||||
+ */
|
||||
+ if (!(portstatus & USB_PORT_STAT_RESET) &&
|
||||
+ (portstatus & USB_PORT_STAT_CONNECTION))
|
||||
break;
|
||||
|
||||
/* switch to the long delay after two short delay failures */
|
||||
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
|
||||
index 210ff64857e1..ec7a50f98f57 100644
|
||||
--- a/drivers/usb/dwc3/gadget.c
|
||||
+++ b/drivers/usb/dwc3/gadget.c
|
||||
@@ -235,6 +235,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
|
||||
int status)
|
||||
{
|
||||
struct dwc3 *dwc = dep->dwc;
|
||||
+ unsigned int unmap_after_complete = false;
|
||||
int i;
|
||||
|
||||
if (req->queued) {
|
||||
@@ -259,11 +260,19 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
|
||||
if (req->request.status == -EINPROGRESS)
|
||||
req->request.status = status;
|
||||
|
||||
- if (dwc->ep0_bounced && dep->number <= 1)
|
||||
+ /*
|
||||
+ * NOTICE we don't want to unmap before calling ->complete() if we're
|
||||
+ * dealing with a bounced ep0 request. If we unmap it here, we would end
|
||||
+ * up overwritting the contents of req->buf and this could confuse the
|
||||
+ * gadget driver.
|
||||
+ */
|
||||
+ if (dwc->ep0_bounced && dep->number <= 1) {
|
||||
dwc->ep0_bounced = false;
|
||||
-
|
||||
- usb_gadget_unmap_request(&dwc->gadget, &req->request,
|
||||
- req->direction);
|
||||
+ unmap_after_complete = true;
|
||||
+ } else {
|
||||
+ usb_gadget_unmap_request(&dwc->gadget,
|
||||
+ &req->request, req->direction);
|
||||
+ }
|
||||
|
||||
dev_dbg(dwc->dev, "request %p from %s completed %d/%d ===> %d\n",
|
||||
req, dep->name, req->request.actual,
|
||||
@@ -282,6 +282,10 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
|
||||
spin_unlock(&dwc->lock);
|
||||
usb_gadget_giveback_request(&dep->endpoint, &req->request);
|
||||
spin_lock(&dwc->lock);
|
||||
+
|
||||
+ if (unmap_after_complete)
|
||||
+ usb_gadget_unmap_request(&dwc->gadget,
|
||||
+ &req->request, req->direction);
|
||||
}
|
||||
|
||||
int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned cmd, u32 param)
|
||||
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
|
||||
index 3975ac809934..d76800108ddb 100644
|
||||
--- a/net/packet/af_packet.c
|
||||
+++ b/net/packet/af_packet.c
|
||||
@@ -4138,8 +4138,8 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
|
||||
if (unlikely(!PAGE_ALIGNED(req->tp_block_size)))
|
||||
goto out;
|
||||
if (po->tp_version >= TPACKET_V3 &&
|
||||
- (int)(req->tp_block_size -
|
||||
- BLK_PLUS_PRIV(req_u->req3.tp_sizeof_priv)) <= 0)
|
||||
+ req->tp_block_size <=
|
||||
+ BLK_PLUS_PRIV((u64)req_u->req3.tp_sizeof_priv))
|
||||
goto out;
|
||||
if (unlikely(req->tp_frame_size < po->tp_hdrlen +
|
||||
po->tp_reserve))
|
1801
patch/kernel/mvebu64-default/03-patch-4.4.62-63.patch
Normal file
1801
patch/kernel/mvebu64-default/03-patch-4.4.62-63.patch
Normal file
File diff suppressed because it is too large
Load diff
1016
patch/kernel/mvebu64-default/03-patch-4.4.63-64.patch
Normal file
1016
patch/kernel/mvebu64-default/03-patch-4.4.63-64.patch
Normal file
File diff suppressed because it is too large
Load diff
920
patch/kernel/mvebu64-default/03-patch-4.4.64-65.patch
Normal file
920
patch/kernel/mvebu64-default/03-patch-4.4.64-65.patch
Normal file
|
@ -0,0 +1,920 @@
|
|||
diff --git a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt
|
||||
index 302b5ed616a6..35e17f748ca7 100644
|
||||
--- a/Documentation/sysctl/fs.txt
|
||||
+++ b/Documentation/sysctl/fs.txt
|
||||
@@ -265,6 +265,13 @@ aio-nr can grow to.
|
||||
|
||||
==============================================================
|
||||
|
||||
+mount-max:
|
||||
+
|
||||
+This denotes the maximum number of mounts that may exist
|
||||
+in a mount namespace.
|
||||
+
|
||||
+==============================================================
|
||||
+
|
||||
|
||||
2. /proc/sys/fs/binfmt_misc
|
||||
----------------------------------------------------------
|
||||
diff --git a/Makefile b/Makefile
|
||||
index 17708f5dc169..ddaef04f528a 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -1,6 +1,6 @@
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 4
|
||||
-SUBLEVEL = 64
|
||||
+SUBLEVEL = 65
|
||||
EXTRAVERSION =
|
||||
NAME = Blurry Fish Butt
|
||||
|
||||
diff --git a/drivers/media/tuners/tuner-xc2028.c b/drivers/media/tuners/tuner-xc2028.c
|
||||
index 4e941f00b600..082ff5608455 100644
|
||||
--- a/drivers/media/tuners/tuner-xc2028.c
|
||||
+++ b/drivers/media/tuners/tuner-xc2028.c
|
||||
@@ -1403,11 +1403,12 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
|
||||
* in order to avoid troubles during device release.
|
||||
*/
|
||||
kfree(priv->ctrl.fname);
|
||||
+ priv->ctrl.fname = NULL;
|
||||
memcpy(&priv->ctrl, p, sizeof(priv->ctrl));
|
||||
if (p->fname) {
|
||||
priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL);
|
||||
if (priv->ctrl.fname == NULL)
|
||||
- rc = -ENOMEM;
|
||||
+ return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
|
||||
index 6df3ee561d52..515aa3f993f3 100644
|
||||
--- a/drivers/net/wireless/hostap/hostap_hw.c
|
||||
+++ b/drivers/net/wireless/hostap/hostap_hw.c
|
||||
@@ -836,25 +836,30 @@ static int hfa384x_get_rid(struct net_device *dev, u16 rid, void *buf, int len,
|
||||
spin_lock_bh(&local->baplock);
|
||||
|
||||
res = hfa384x_setup_bap(dev, BAP0, rid, 0);
|
||||
- if (!res)
|
||||
- res = hfa384x_from_bap(dev, BAP0, &rec, sizeof(rec));
|
||||
+ if (res)
|
||||
+ goto unlock;
|
||||
+
|
||||
+ res = hfa384x_from_bap(dev, BAP0, &rec, sizeof(rec));
|
||||
+ if (res)
|
||||
+ goto unlock;
|
||||
|
||||
if (le16_to_cpu(rec.len) == 0) {
|
||||
/* RID not available */
|
||||
res = -ENODATA;
|
||||
+ goto unlock;
|
||||
}
|
||||
|
||||
rlen = (le16_to_cpu(rec.len) - 1) * 2;
|
||||
- if (!res && exact_len && rlen != len) {
|
||||
+ if (exact_len && rlen != len) {
|
||||
printk(KERN_DEBUG "%s: hfa384x_get_rid - RID len mismatch: "
|
||||
"rid=0x%04x, len=%d (expected %d)\n",
|
||||
dev->name, rid, rlen, len);
|
||||
res = -ENODATA;
|
||||
}
|
||||
|
||||
- if (!res)
|
||||
- res = hfa384x_from_bap(dev, BAP0, buf, len);
|
||||
+ res = hfa384x_from_bap(dev, BAP0, buf, len);
|
||||
|
||||
+unlock:
|
||||
spin_unlock_bh(&local->baplock);
|
||||
mutex_unlock(&local->rid_bap_mtx);
|
||||
|
||||
diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c
|
||||
index 80f9de907563..5cc80b80c82b 100644
|
||||
--- a/drivers/tty/nozomi.c
|
||||
+++ b/drivers/tty/nozomi.c
|
||||
@@ -823,7 +823,7 @@ static int receive_data(enum port_type index, struct nozomi *dc)
|
||||
struct tty_struct *tty = tty_port_tty_get(&port->port);
|
||||
int i, ret;
|
||||
|
||||
- read_mem32((u32 *) &size, addr, 4);
|
||||
+ size = __le32_to_cpu(readl(addr));
|
||||
/* DBG1( "%d bytes port: %d", size, index); */
|
||||
|
||||
if (tty && test_bit(TTY_THROTTLED, &tty->flags)) {
|
||||
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
|
||||
index 9982cb176ce8..830e2fd47642 100644
|
||||
--- a/drivers/vfio/pci/vfio_pci.c
|
||||
+++ b/drivers/vfio/pci/vfio_pci.c
|
||||
@@ -562,8 +562,9 @@ static long vfio_pci_ioctl(void *device_data,
|
||||
|
||||
} else if (cmd == VFIO_DEVICE_SET_IRQS) {
|
||||
struct vfio_irq_set hdr;
|
||||
+ size_t size;
|
||||
u8 *data = NULL;
|
||||
- int ret = 0;
|
||||
+ int max, ret = 0;
|
||||
|
||||
minsz = offsetofend(struct vfio_irq_set, count);
|
||||
|
||||
@@ -571,23 +572,31 @@ static long vfio_pci_ioctl(void *device_data,
|
||||
return -EFAULT;
|
||||
|
||||
if (hdr.argsz < minsz || hdr.index >= VFIO_PCI_NUM_IRQS ||
|
||||
+ hdr.count >= (U32_MAX - hdr.start) ||
|
||||
hdr.flags & ~(VFIO_IRQ_SET_DATA_TYPE_MASK |
|
||||
VFIO_IRQ_SET_ACTION_TYPE_MASK))
|
||||
return -EINVAL;
|
||||
|
||||
- if (!(hdr.flags & VFIO_IRQ_SET_DATA_NONE)) {
|
||||
- size_t size;
|
||||
- int max = vfio_pci_get_irq_count(vdev, hdr.index);
|
||||
+ max = vfio_pci_get_irq_count(vdev, hdr.index);
|
||||
+ if (hdr.start >= max || hdr.start + hdr.count > max)
|
||||
+ return -EINVAL;
|
||||
|
||||
- if (hdr.flags & VFIO_IRQ_SET_DATA_BOOL)
|
||||
- size = sizeof(uint8_t);
|
||||
- else if (hdr.flags & VFIO_IRQ_SET_DATA_EVENTFD)
|
||||
- size = sizeof(int32_t);
|
||||
- else
|
||||
- return -EINVAL;
|
||||
+ switch (hdr.flags & VFIO_IRQ_SET_DATA_TYPE_MASK) {
|
||||
+ case VFIO_IRQ_SET_DATA_NONE:
|
||||
+ size = 0;
|
||||
+ break;
|
||||
+ case VFIO_IRQ_SET_DATA_BOOL:
|
||||
+ size = sizeof(uint8_t);
|
||||
+ break;
|
||||
+ case VFIO_IRQ_SET_DATA_EVENTFD:
|
||||
+ size = sizeof(int32_t);
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
|
||||
- if (hdr.argsz - minsz < hdr.count * size ||
|
||||
- hdr.start >= max || hdr.start + hdr.count > max)
|
||||
+ if (size) {
|
||||
+ if (hdr.argsz - minsz < hdr.count * size)
|
||||
return -EINVAL;
|
||||
|
||||
data = memdup_user((void __user *)(arg + minsz),
|
||||
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
|
||||
index 20e9a86d2dcf..5c8f767b6368 100644
|
||||
--- a/drivers/vfio/pci/vfio_pci_intrs.c
|
||||
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
|
||||
@@ -255,7 +255,7 @@ static int vfio_msi_enable(struct vfio_pci_device *vdev, int nvec, bool msix)
|
||||
if (!is_irq_none(vdev))
|
||||
return -EINVAL;
|
||||
|
||||
- vdev->ctx = kzalloc(nvec * sizeof(struct vfio_pci_irq_ctx), GFP_KERNEL);
|
||||
+ vdev->ctx = kcalloc(nvec, sizeof(struct vfio_pci_irq_ctx), GFP_KERNEL);
|
||||
if (!vdev->ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
|
||||
index ad8a5b757cc7..a443c6e54412 100644
|
||||
--- a/fs/gfs2/dir.c
|
||||
+++ b/fs/gfs2/dir.c
|
||||
@@ -760,7 +760,7 @@ static int get_first_leaf(struct gfs2_inode *dip, u32 index,
|
||||
int error;
|
||||
|
||||
error = get_leaf_nr(dip, index, &leaf_no);
|
||||
- if (!error)
|
||||
+ if (!IS_ERR_VALUE(error))
|
||||
error = get_leaf(dip, leaf_no, bh_out);
|
||||
|
||||
return error;
|
||||
@@ -976,7 +976,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
|
||||
|
||||
index = name->hash >> (32 - dip->i_depth);
|
||||
error = get_leaf_nr(dip, index, &leaf_no);
|
||||
- if (error)
|
||||
+ if (IS_ERR_VALUE(error))
|
||||
return error;
|
||||
|
||||
/* Get the old leaf block */
|
||||
diff --git a/fs/mount.h b/fs/mount.h
|
||||
index 3dc7dea5a357..13a4ebbbaa74 100644
|
||||
--- a/fs/mount.h
|
||||
+++ b/fs/mount.h
|
||||
@@ -13,6 +13,8 @@ struct mnt_namespace {
|
||||
u64 seq; /* Sequence number to prevent loops */
|
||||
wait_queue_head_t poll;
|
||||
u64 event;
|
||||
+ unsigned int mounts; /* # of mounts in the namespace */
|
||||
+ unsigned int pending_mounts;
|
||||
};
|
||||
|
||||
struct mnt_pcp {
|
||||
diff --git a/fs/namespace.c b/fs/namespace.c
|
||||
index 7df3d406d3e0..f26d18d69712 100644
|
||||
--- a/fs/namespace.c
|
||||
+++ b/fs/namespace.c
|
||||
@@ -27,6 +27,9 @@
|
||||
#include "pnode.h"
|
||||
#include "internal.h"
|
||||
|
||||
+/* Maximum number of mounts in a mount namespace */
|
||||
+unsigned int sysctl_mount_max __read_mostly = 100000;
|
||||
+
|
||||
static unsigned int m_hash_mask __read_mostly;
|
||||
static unsigned int m_hash_shift __read_mostly;
|
||||
static unsigned int mp_hash_mask __read_mostly;
|
||||
@@ -925,6 +928,9 @@ static void commit_tree(struct mount *mnt)
|
||||
|
||||
list_splice(&head, n->list.prev);
|
||||
|
||||
+ n->mounts += n->pending_mounts;
|
||||
+ n->pending_mounts = 0;
|
||||
+
|
||||
__attach_mnt(mnt, parent);
|
||||
touch_mnt_namespace(n);
|
||||
}
|
||||
@@ -1445,11 +1451,16 @@ static void umount_tree(struct mount *mnt, enum umount_tree_flags how)
|
||||
propagate_umount(&tmp_list);
|
||||
|
||||
while (!list_empty(&tmp_list)) {
|
||||
+ struct mnt_namespace *ns;
|
||||
bool disconnect;
|
||||
p = list_first_entry(&tmp_list, struct mount, mnt_list);
|
||||
list_del_init(&p->mnt_expire);
|
||||
list_del_init(&p->mnt_list);
|
||||
- __touch_mnt_namespace(p->mnt_ns);
|
||||
+ ns = p->mnt_ns;
|
||||
+ if (ns) {
|
||||
+ ns->mounts--;
|
||||
+ __touch_mnt_namespace(ns);
|
||||
+ }
|
||||
p->mnt_ns = NULL;
|
||||
if (how & UMOUNT_SYNC)
|
||||
p->mnt.mnt_flags |= MNT_SYNC_UMOUNT;
|
||||
@@ -1850,6 +1861,28 @@ static int invent_group_ids(struct mount *mnt, bool recurse)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int count_mounts(struct mnt_namespace *ns, struct mount *mnt)
|
||||
+{
|
||||
+ unsigned int max = READ_ONCE(sysctl_mount_max);
|
||||
+ unsigned int mounts = 0, old, pending, sum;
|
||||
+ struct mount *p;
|
||||
+
|
||||
+ for (p = mnt; p; p = next_mnt(p, mnt))
|
||||
+ mounts++;
|
||||
+
|
||||
+ old = ns->mounts;
|
||||
+ pending = ns->pending_mounts;
|
||||
+ sum = old + pending;
|
||||
+ if ((old > sum) ||
|
||||
+ (pending > sum) ||
|
||||
+ (max < sum) ||
|
||||
+ (mounts > (max - sum)))
|
||||
+ return -ENOSPC;
|
||||
+
|
||||
+ ns->pending_mounts = pending + mounts;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* @source_mnt : mount tree to be attached
|
||||
* @nd : place the mount tree @source_mnt is attached
|
||||
@@ -1919,6 +1952,7 @@ static int attach_recursive_mnt(struct mount *source_mnt,
|
||||
struct path *parent_path)
|
||||
{
|
||||
HLIST_HEAD(tree_list);
|
||||
+ struct mnt_namespace *ns = dest_mnt->mnt_ns;
|
||||
struct mountpoint *smp;
|
||||
struct mount *child, *p;
|
||||
struct hlist_node *n;
|
||||
@@ -1931,6 +1965,13 @@ static int attach_recursive_mnt(struct mount *source_mnt,
|
||||
if (IS_ERR(smp))
|
||||
return PTR_ERR(smp);
|
||||
|
||||
+ /* Is there space to add these mounts to the mount namespace? */
|
||||
+ if (!parent_path) {
|
||||
+ err = count_mounts(ns, source_mnt);
|
||||
+ if (err)
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
if (IS_MNT_SHARED(dest_mnt)) {
|
||||
err = invent_group_ids(source_mnt, true);
|
||||
if (err)
|
||||
@@ -1970,11 +2011,14 @@ static int attach_recursive_mnt(struct mount *source_mnt,
|
||||
out_cleanup_ids:
|
||||
while (!hlist_empty(&tree_list)) {
|
||||
child = hlist_entry(tree_list.first, struct mount, mnt_hash);
|
||||
+ child->mnt_parent->mnt_ns->pending_mounts = 0;
|
||||
umount_tree(child, UMOUNT_SYNC);
|
||||
}
|
||||
unlock_mount_hash();
|
||||
cleanup_group_ids(source_mnt, NULL);
|
||||
out:
|
||||
+ ns->pending_mounts = 0;
|
||||
+
|
||||
read_seqlock_excl(&mount_lock);
|
||||
put_mountpoint(smp);
|
||||
read_sequnlock_excl(&mount_lock);
|
||||
@@ -2804,6 +2848,8 @@ static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns)
|
||||
init_waitqueue_head(&new_ns->poll);
|
||||
new_ns->event = 0;
|
||||
new_ns->user_ns = get_user_ns(user_ns);
|
||||
+ new_ns->mounts = 0;
|
||||
+ new_ns->pending_mounts = 0;
|
||||
return new_ns;
|
||||
}
|
||||
|
||||
@@ -2853,6 +2899,7 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
|
||||
q = new;
|
||||
while (p) {
|
||||
q->mnt_ns = new_ns;
|
||||
+ new_ns->mounts++;
|
||||
if (new_fs) {
|
||||
if (&p->mnt == new_fs->root.mnt) {
|
||||
new_fs->root.mnt = mntget(&q->mnt);
|
||||
@@ -2891,6 +2938,7 @@ static struct mnt_namespace *create_mnt_ns(struct vfsmount *m)
|
||||
struct mount *mnt = real_mount(m);
|
||||
mnt->mnt_ns = new_ns;
|
||||
new_ns->root = mnt;
|
||||
+ new_ns->mounts++;
|
||||
list_add(&mnt->mnt_list, &new_ns->list);
|
||||
} else {
|
||||
mntput(m);
|
||||
diff --git a/fs/pnode.c b/fs/pnode.c
|
||||
index b9f2af59b9a6..b394ca5307ec 100644
|
||||
--- a/fs/pnode.c
|
||||
+++ b/fs/pnode.c
|
||||
@@ -259,7 +259,7 @@ static int propagate_one(struct mount *m)
|
||||
read_sequnlock_excl(&mount_lock);
|
||||
}
|
||||
hlist_add_head(&child->mnt_hash, list);
|
||||
- return 0;
|
||||
+ return count_mounts(m->mnt_ns, child);
|
||||
}
|
||||
|
||||
/*
|
||||
diff --git a/fs/pnode.h b/fs/pnode.h
|
||||
index 623f01772bec..dc87e65becd2 100644
|
||||
--- a/fs/pnode.h
|
||||
+++ b/fs/pnode.h
|
||||
@@ -54,4 +54,5 @@ void mnt_change_mountpoint(struct mount *parent, struct mountpoint *mp,
|
||||
struct mount *copy_tree(struct mount *, struct dentry *, int);
|
||||
bool is_path_reachable(struct mount *, struct dentry *,
|
||||
const struct path *root);
|
||||
+int count_mounts(struct mnt_namespace *ns, struct mount *mnt);
|
||||
#endif /* _LINUX_PNODE_H */
|
||||
diff --git a/include/linux/mount.h b/include/linux/mount.h
|
||||
index f822c3c11377..dc6cd800cd5d 100644
|
||||
--- a/include/linux/mount.h
|
||||
+++ b/include/linux/mount.h
|
||||
@@ -95,4 +95,6 @@ extern void mark_mounts_for_expiry(struct list_head *mounts);
|
||||
|
||||
extern dev_t name_to_dev_t(const char *name);
|
||||
|
||||
+extern unsigned int sysctl_mount_max;
|
||||
+
|
||||
#endif /* _LINUX_MOUNT_H */
|
||||
diff --git a/kernel/events/core.c b/kernel/events/core.c
|
||||
index e4b5494f05f8..784ab8fe8714 100644
|
||||
--- a/kernel/events/core.c
|
||||
+++ b/kernel/events/core.c
|
||||
@@ -8250,6 +8250,37 @@ static int perf_event_set_clock(struct perf_event *event, clockid_t clk_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Variation on perf_event_ctx_lock_nested(), except we take two context
|
||||
+ * mutexes.
|
||||
+ */
|
||||
+static struct perf_event_context *
|
||||
+__perf_event_ctx_lock_double(struct perf_event *group_leader,
|
||||
+ struct perf_event_context *ctx)
|
||||
+{
|
||||
+ struct perf_event_context *gctx;
|
||||
+
|
||||
+again:
|
||||
+ rcu_read_lock();
|
||||
+ gctx = READ_ONCE(group_leader->ctx);
|
||||
+ if (!atomic_inc_not_zero(&gctx->refcount)) {
|
||||
+ rcu_read_unlock();
|
||||
+ goto again;
|
||||
+ }
|
||||
+ rcu_read_unlock();
|
||||
+
|
||||
+ mutex_lock_double(&gctx->mutex, &ctx->mutex);
|
||||
+
|
||||
+ if (group_leader->ctx != gctx) {
|
||||
+ mutex_unlock(&ctx->mutex);
|
||||
+ mutex_unlock(&gctx->mutex);
|
||||
+ put_ctx(gctx);
|
||||
+ goto again;
|
||||
+ }
|
||||
+
|
||||
+ return gctx;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* sys_perf_event_open - open a performance event, associate it to a task/cpu
|
||||
*
|
||||
@@ -8486,8 +8517,26 @@ SYSCALL_DEFINE5(perf_event_open,
|
||||
}
|
||||
|
||||
if (move_group) {
|
||||
- gctx = group_leader->ctx;
|
||||
- mutex_lock_double(&gctx->mutex, &ctx->mutex);
|
||||
+ gctx = __perf_event_ctx_lock_double(group_leader, ctx);
|
||||
+
|
||||
+ /*
|
||||
+ * Check if we raced against another sys_perf_event_open() call
|
||||
+ * moving the software group underneath us.
|
||||
+ */
|
||||
+ if (!(group_leader->group_flags & PERF_GROUP_SOFTWARE)) {
|
||||
+ /*
|
||||
+ * If someone moved the group out from under us, check
|
||||
+ * if this new event wound up on the same ctx, if so
|
||||
+ * its the regular !move_group case, otherwise fail.
|
||||
+ */
|
||||
+ if (gctx != ctx) {
|
||||
+ err = -EINVAL;
|
||||
+ goto err_locked;
|
||||
+ } else {
|
||||
+ perf_event_ctx_unlock(group_leader, gctx);
|
||||
+ move_group = 0;
|
||||
+ }
|
||||
+ }
|
||||
} else {
|
||||
mutex_lock(&ctx->mutex);
|
||||
}
|
||||
@@ -8582,7 +8631,7 @@ SYSCALL_DEFINE5(perf_event_open,
|
||||
perf_unpin_context(ctx);
|
||||
|
||||
if (move_group)
|
||||
- mutex_unlock(&gctx->mutex);
|
||||
+ perf_event_ctx_unlock(group_leader, gctx);
|
||||
mutex_unlock(&ctx->mutex);
|
||||
|
||||
if (task) {
|
||||
@@ -8610,7 +8659,7 @@ SYSCALL_DEFINE5(perf_event_open,
|
||||
|
||||
err_locked:
|
||||
if (move_group)
|
||||
- mutex_unlock(&gctx->mutex);
|
||||
+ perf_event_ctx_unlock(group_leader, gctx);
|
||||
mutex_unlock(&ctx->mutex);
|
||||
/* err_file: */
|
||||
fput(event_file);
|
||||
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
|
||||
index 2f0d157258a2..300d64162aff 100644
|
||||
--- a/kernel/sysctl.c
|
||||
+++ b/kernel/sysctl.c
|
||||
@@ -65,6 +65,7 @@
|
||||
#include <linux/sched/sysctl.h>
|
||||
#include <linux/kexec.h>
|
||||
#include <linux/bpf.h>
|
||||
+#include <linux/mount.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/processor.h>
|
||||
@@ -1749,6 +1750,14 @@ static struct ctl_table fs_table[] = {
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_doulongvec_minmax,
|
||||
},
|
||||
+ {
|
||||
+ .procname = "mount-max",
|
||||
+ .data = &sysctl_mount_max,
|
||||
+ .maxlen = sizeof(unsigned int),
|
||||
+ .mode = 0644,
|
||||
+ .proc_handler = proc_dointvec_minmax,
|
||||
+ .extra1 = &one,
|
||||
+ },
|
||||
{ }
|
||||
};
|
||||
|
||||
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
|
||||
index 3a00512addbc..37a3b05d175c 100644
|
||||
--- a/net/ipv4/ping.c
|
||||
+++ b/net/ipv4/ping.c
|
||||
@@ -154,17 +154,18 @@ void ping_hash(struct sock *sk)
|
||||
void ping_unhash(struct sock *sk)
|
||||
{
|
||||
struct inet_sock *isk = inet_sk(sk);
|
||||
+
|
||||
pr_debug("ping_unhash(isk=%p,isk->num=%u)\n", isk, isk->inet_num);
|
||||
+ write_lock_bh(&ping_table.lock);
|
||||
if (sk_hashed(sk)) {
|
||||
- write_lock_bh(&ping_table.lock);
|
||||
hlist_nulls_del(&sk->sk_nulls_node);
|
||||
sk_nulls_node_init(&sk->sk_nulls_node);
|
||||
sock_put(sk);
|
||||
isk->inet_num = 0;
|
||||
isk->inet_sport = 0;
|
||||
sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
|
||||
- write_unlock_bh(&ping_table.lock);
|
||||
}
|
||||
+ write_unlock_bh(&ping_table.lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ping_unhash);
|
||||
|
||||
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
|
||||
index 77afe913d03d..9adedba78eea 100644
|
||||
--- a/net/netfilter/nfnetlink.c
|
||||
+++ b/net/netfilter/nfnetlink.c
|
||||
@@ -326,10 +326,12 @@ replay:
|
||||
nlh = nlmsg_hdr(skb);
|
||||
err = 0;
|
||||
|
||||
- if (nlmsg_len(nlh) < sizeof(struct nfgenmsg) ||
|
||||
- skb->len < nlh->nlmsg_len) {
|
||||
- err = -EINVAL;
|
||||
- goto ack;
|
||||
+ if (nlh->nlmsg_len < NLMSG_HDRLEN ||
|
||||
+ skb->len < nlh->nlmsg_len ||
|
||||
+ nlmsg_len(nlh) < sizeof(struct nfgenmsg)) {
|
||||
+ nfnl_err_reset(&err_list);
|
||||
+ status |= NFNL_BATCH_FAILURE;
|
||||
+ goto done;
|
||||
}
|
||||
|
||||
/* Only requests are handled by the kernel */
|
||||
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
|
||||
index 648f2a67f314..cb1381513c82 100644
|
||||
--- a/net/tipc/bearer.c
|
||||
+++ b/net/tipc/bearer.c
|
||||
@@ -381,6 +381,10 @@ int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b,
|
||||
dev = dev_get_by_name(net, driver_name);
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
+ if (tipc_mtu_bad(dev, 0)) {
|
||||
+ dev_put(dev);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
|
||||
/* Associate TIPC bearer with L2 bearer */
|
||||
rcu_assign_pointer(b->media_ptr, dev);
|
||||
@@ -570,14 +574,19 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt,
|
||||
if (!b_ptr)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
- b_ptr->mtu = dev->mtu;
|
||||
-
|
||||
switch (evt) {
|
||||
case NETDEV_CHANGE:
|
||||
if (netif_carrier_ok(dev))
|
||||
break;
|
||||
case NETDEV_GOING_DOWN:
|
||||
+ tipc_reset_bearer(net, b_ptr);
|
||||
+ break;
|
||||
case NETDEV_CHANGEMTU:
|
||||
+ if (tipc_mtu_bad(dev, 0)) {
|
||||
+ bearer_disable(net, b_ptr);
|
||||
+ break;
|
||||
+ }
|
||||
+ b_ptr->mtu = dev->mtu;
|
||||
tipc_reset_bearer(net, b_ptr);
|
||||
break;
|
||||
case NETDEV_CHANGEADDR:
|
||||
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
|
||||
index 552185bc4773..5f11e18b1fa1 100644
|
||||
--- a/net/tipc/bearer.h
|
||||
+++ b/net/tipc/bearer.h
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
#include "netlink.h"
|
||||
#include "core.h"
|
||||
+#include "msg.h"
|
||||
#include <net/genetlink.h>
|
||||
|
||||
#define MAX_MEDIA 3
|
||||
@@ -61,6 +62,9 @@
|
||||
#define TIPC_MEDIA_TYPE_IB 2
|
||||
#define TIPC_MEDIA_TYPE_UDP 3
|
||||
|
||||
+/* minimum bearer MTU */
|
||||
+#define TIPC_MIN_BEARER_MTU (MAX_H_SIZE + INT_H_SIZE)
|
||||
+
|
||||
/**
|
||||
* struct tipc_node_map - set of node identifiers
|
||||
* @count: # of nodes in set
|
||||
@@ -226,4 +230,13 @@ void tipc_bearer_xmit(struct net *net, u32 bearer_id,
|
||||
void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id,
|
||||
struct sk_buff_head *xmitq);
|
||||
|
||||
+/* check if device MTU is too low for tipc headers */
|
||||
+static inline bool tipc_mtu_bad(struct net_device *dev, unsigned int reserve)
|
||||
+{
|
||||
+ if (dev->mtu >= TIPC_MIN_BEARER_MTU + reserve)
|
||||
+ return false;
|
||||
+ netdev_warn(dev, "MTU too low for tipc bearer\n");
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
#endif /* _TIPC_BEARER_H */
|
||||
diff --git a/net/tipc/core.c b/net/tipc/core.c
|
||||
index 03a842870c52..e2bdb07a49a2 100644
|
||||
--- a/net/tipc/core.c
|
||||
+++ b/net/tipc/core.c
|
||||
@@ -69,6 +69,7 @@ static int __net_init tipc_init_net(struct net *net)
|
||||
if (err)
|
||||
goto out_nametbl;
|
||||
|
||||
+ INIT_LIST_HEAD(&tn->dist_queue);
|
||||
err = tipc_topsrv_start(net);
|
||||
if (err)
|
||||
goto out_subscr;
|
||||
diff --git a/net/tipc/core.h b/net/tipc/core.h
|
||||
index 18e95a8020cd..fe3b89e9cde4 100644
|
||||
--- a/net/tipc/core.h
|
||||
+++ b/net/tipc/core.h
|
||||
@@ -103,6 +103,9 @@ struct tipc_net {
|
||||
spinlock_t nametbl_lock;
|
||||
struct name_table *nametbl;
|
||||
|
||||
+ /* Name dist queue */
|
||||
+ struct list_head dist_queue;
|
||||
+
|
||||
/* Topology subscription server */
|
||||
struct tipc_server *topsrv;
|
||||
atomic_t subscription_count;
|
||||
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
|
||||
index f51c8bdbea1c..c4c151bc000c 100644
|
||||
--- a/net/tipc/name_distr.c
|
||||
+++ b/net/tipc/name_distr.c
|
||||
@@ -40,11 +40,6 @@
|
||||
|
||||
int sysctl_tipc_named_timeout __read_mostly = 2000;
|
||||
|
||||
-/**
|
||||
- * struct tipc_dist_queue - queue holding deferred name table updates
|
||||
- */
|
||||
-static struct list_head tipc_dist_queue = LIST_HEAD_INIT(tipc_dist_queue);
|
||||
-
|
||||
struct distr_queue_item {
|
||||
struct distr_item i;
|
||||
u32 dtype;
|
||||
@@ -67,6 +62,8 @@ static void publ_to_item(struct distr_item *i, struct publication *p)
|
||||
|
||||
/**
|
||||
* named_prepare_buf - allocate & initialize a publication message
|
||||
+ *
|
||||
+ * The buffer returned is of size INT_H_SIZE + payload size
|
||||
*/
|
||||
static struct sk_buff *named_prepare_buf(struct net *net, u32 type, u32 size,
|
||||
u32 dest)
|
||||
@@ -171,9 +168,9 @@ static void named_distribute(struct net *net, struct sk_buff_head *list,
|
||||
struct publication *publ;
|
||||
struct sk_buff *skb = NULL;
|
||||
struct distr_item *item = NULL;
|
||||
- uint msg_dsz = (tipc_node_get_mtu(net, dnode, 0) / ITEM_SIZE) *
|
||||
- ITEM_SIZE;
|
||||
- uint msg_rem = msg_dsz;
|
||||
+ u32 msg_dsz = ((tipc_node_get_mtu(net, dnode, 0) - INT_H_SIZE) /
|
||||
+ ITEM_SIZE) * ITEM_SIZE;
|
||||
+ u32 msg_rem = msg_dsz;
|
||||
|
||||
list_for_each_entry(publ, pls, local_list) {
|
||||
/* Prepare next buffer: */
|
||||
@@ -340,9 +337,11 @@ static bool tipc_update_nametbl(struct net *net, struct distr_item *i,
|
||||
* tipc_named_add_backlog - add a failed name table update to the backlog
|
||||
*
|
||||
*/
|
||||
-static void tipc_named_add_backlog(struct distr_item *i, u32 type, u32 node)
|
||||
+static void tipc_named_add_backlog(struct net *net, struct distr_item *i,
|
||||
+ u32 type, u32 node)
|
||||
{
|
||||
struct distr_queue_item *e;
|
||||
+ struct tipc_net *tn = net_generic(net, tipc_net_id);
|
||||
unsigned long now = get_jiffies_64();
|
||||
|
||||
e = kzalloc(sizeof(*e), GFP_ATOMIC);
|
||||
@@ -352,7 +351,7 @@ static void tipc_named_add_backlog(struct distr_item *i, u32 type, u32 node)
|
||||
e->node = node;
|
||||
e->expires = now + msecs_to_jiffies(sysctl_tipc_named_timeout);
|
||||
memcpy(e, i, sizeof(*i));
|
||||
- list_add_tail(&e->next, &tipc_dist_queue);
|
||||
+ list_add_tail(&e->next, &tn->dist_queue);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -362,10 +361,11 @@ static void tipc_named_add_backlog(struct distr_item *i, u32 type, u32 node)
|
||||
void tipc_named_process_backlog(struct net *net)
|
||||
{
|
||||
struct distr_queue_item *e, *tmp;
|
||||
+ struct tipc_net *tn = net_generic(net, tipc_net_id);
|
||||
char addr[16];
|
||||
unsigned long now = get_jiffies_64();
|
||||
|
||||
- list_for_each_entry_safe(e, tmp, &tipc_dist_queue, next) {
|
||||
+ list_for_each_entry_safe(e, tmp, &tn->dist_queue, next) {
|
||||
if (time_after(e->expires, now)) {
|
||||
if (!tipc_update_nametbl(net, &e->i, e->node, e->dtype))
|
||||
continue;
|
||||
@@ -405,7 +405,7 @@ void tipc_named_rcv(struct net *net, struct sk_buff_head *inputq)
|
||||
node = msg_orignode(msg);
|
||||
while (count--) {
|
||||
if (!tipc_update_nametbl(net, item, node, mtype))
|
||||
- tipc_named_add_backlog(item, mtype, node);
|
||||
+ tipc_named_add_backlog(net, item, mtype, node);
|
||||
item++;
|
||||
}
|
||||
kfree_skb(skb);
|
||||
diff --git a/net/tipc/node.c b/net/tipc/node.c
|
||||
index d468aad6163e..2df0b98d4a32 100644
|
||||
--- a/net/tipc/node.c
|
||||
+++ b/net/tipc/node.c
|
||||
@@ -728,7 +728,7 @@ static void tipc_node_fsm_evt(struct tipc_node *n, int evt)
|
||||
state = SELF_UP_PEER_UP;
|
||||
break;
|
||||
case SELF_LOST_CONTACT_EVT:
|
||||
- state = SELF_DOWN_PEER_LEAVING;
|
||||
+ state = SELF_DOWN_PEER_DOWN;
|
||||
break;
|
||||
case SELF_ESTABL_CONTACT_EVT:
|
||||
case PEER_LOST_CONTACT_EVT:
|
||||
@@ -747,7 +747,7 @@ static void tipc_node_fsm_evt(struct tipc_node *n, int evt)
|
||||
state = SELF_UP_PEER_UP;
|
||||
break;
|
||||
case PEER_LOST_CONTACT_EVT:
|
||||
- state = SELF_LEAVING_PEER_DOWN;
|
||||
+ state = SELF_DOWN_PEER_DOWN;
|
||||
break;
|
||||
case SELF_LOST_CONTACT_EVT:
|
||||
case PEER_ESTABL_CONTACT_EVT:
|
||||
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
|
||||
index b26b7a127773..65171f8e8c45 100644
|
||||
--- a/net/tipc/socket.c
|
||||
+++ b/net/tipc/socket.c
|
||||
@@ -777,9 +777,11 @@ void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq,
|
||||
* @tsk: receiving socket
|
||||
* @skb: pointer to message buffer.
|
||||
*/
|
||||
-static void tipc_sk_proto_rcv(struct tipc_sock *tsk, struct sk_buff *skb)
|
||||
+static void tipc_sk_proto_rcv(struct tipc_sock *tsk, struct sk_buff *skb,
|
||||
+ struct sk_buff_head *xmitq)
|
||||
{
|
||||
struct sock *sk = &tsk->sk;
|
||||
+ u32 onode = tsk_own_node(tsk);
|
||||
struct tipc_msg *hdr = buf_msg(skb);
|
||||
int mtyp = msg_type(hdr);
|
||||
int conn_cong;
|
||||
@@ -792,7 +794,8 @@ static void tipc_sk_proto_rcv(struct tipc_sock *tsk, struct sk_buff *skb)
|
||||
|
||||
if (mtyp == CONN_PROBE) {
|
||||
msg_set_type(hdr, CONN_PROBE_REPLY);
|
||||
- tipc_sk_respond(sk, skb, TIPC_OK);
|
||||
+ if (tipc_msg_reverse(onode, &skb, TIPC_OK))
|
||||
+ __skb_queue_tail(xmitq, skb);
|
||||
return;
|
||||
} else if (mtyp == CONN_ACK) {
|
||||
conn_cong = tsk_conn_cong(tsk);
|
||||
@@ -1647,7 +1650,8 @@ static unsigned int rcvbuf_limit(struct sock *sk, struct sk_buff *buf)
|
||||
*
|
||||
* Returns true if message was added to socket receive queue, otherwise false
|
||||
*/
|
||||
-static bool filter_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
+static bool filter_rcv(struct sock *sk, struct sk_buff *skb,
|
||||
+ struct sk_buff_head *xmitq)
|
||||
{
|
||||
struct socket *sock = sk->sk_socket;
|
||||
struct tipc_sock *tsk = tipc_sk(sk);
|
||||
@@ -1657,7 +1661,7 @@ static bool filter_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
int usr = msg_user(hdr);
|
||||
|
||||
if (unlikely(msg_user(hdr) == CONN_MANAGER)) {
|
||||
- tipc_sk_proto_rcv(tsk, skb);
|
||||
+ tipc_sk_proto_rcv(tsk, skb, xmitq);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1700,7 +1704,8 @@ static bool filter_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
return true;
|
||||
|
||||
reject:
|
||||
- tipc_sk_respond(sk, skb, err);
|
||||
+ if (tipc_msg_reverse(tsk_own_node(tsk), &skb, err))
|
||||
+ __skb_queue_tail(xmitq, skb);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1716,9 +1721,24 @@ reject:
|
||||
static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
unsigned int truesize = skb->truesize;
|
||||
+ struct sk_buff_head xmitq;
|
||||
+ u32 dnode, selector;
|
||||
|
||||
- if (likely(filter_rcv(sk, skb)))
|
||||
+ __skb_queue_head_init(&xmitq);
|
||||
+
|
||||
+ if (likely(filter_rcv(sk, skb, &xmitq))) {
|
||||
atomic_add(truesize, &tipc_sk(sk)->dupl_rcvcnt);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (skb_queue_empty(&xmitq))
|
||||
+ return 0;
|
||||
+
|
||||
+ /* Send response/rejected message */
|
||||
+ skb = __skb_dequeue(&xmitq);
|
||||
+ dnode = msg_destnode(buf_msg(skb));
|
||||
+ selector = msg_origport(buf_msg(skb));
|
||||
+ tipc_node_xmit_skb(sock_net(sk), skb, dnode, selector);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1732,12 +1752,13 @@ static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
* Caller must hold socket lock
|
||||
*/
|
||||
static void tipc_sk_enqueue(struct sk_buff_head *inputq, struct sock *sk,
|
||||
- u32 dport)
|
||||
+ u32 dport, struct sk_buff_head *xmitq)
|
||||
{
|
||||
+ unsigned long time_limit = jiffies + 2;
|
||||
+ struct sk_buff *skb;
|
||||
unsigned int lim;
|
||||
atomic_t *dcnt;
|
||||
- struct sk_buff *skb;
|
||||
- unsigned long time_limit = jiffies + 2;
|
||||
+ u32 onode;
|
||||
|
||||
while (skb_queue_len(inputq)) {
|
||||
if (unlikely(time_after_eq(jiffies, time_limit)))
|
||||
@@ -1749,20 +1770,22 @@ static void tipc_sk_enqueue(struct sk_buff_head *inputq, struct sock *sk,
|
||||
|
||||
/* Add message directly to receive queue if possible */
|
||||
if (!sock_owned_by_user(sk)) {
|
||||
- filter_rcv(sk, skb);
|
||||
+ filter_rcv(sk, skb, xmitq);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Try backlog, compensating for double-counted bytes */
|
||||
dcnt = &tipc_sk(sk)->dupl_rcvcnt;
|
||||
- if (sk->sk_backlog.len)
|
||||
+ if (!sk->sk_backlog.len)
|
||||
atomic_set(dcnt, 0);
|
||||
lim = rcvbuf_limit(sk, skb) + atomic_read(dcnt);
|
||||
if (likely(!sk_add_backlog(sk, skb, lim)))
|
||||
continue;
|
||||
|
||||
/* Overload => reject message back to sender */
|
||||
- tipc_sk_respond(sk, skb, TIPC_ERR_OVERLOAD);
|
||||
+ onode = tipc_own_addr(sock_net(sk));
|
||||
+ if (tipc_msg_reverse(onode, &skb, TIPC_ERR_OVERLOAD))
|
||||
+ __skb_queue_tail(xmitq, skb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1775,12 +1798,14 @@ static void tipc_sk_enqueue(struct sk_buff_head *inputq, struct sock *sk,
|
||||
*/
|
||||
void tipc_sk_rcv(struct net *net, struct sk_buff_head *inputq)
|
||||
{
|
||||
+ struct sk_buff_head xmitq;
|
||||
u32 dnode, dport = 0;
|
||||
int err;
|
||||
struct tipc_sock *tsk;
|
||||
struct sock *sk;
|
||||
struct sk_buff *skb;
|
||||
|
||||
+ __skb_queue_head_init(&xmitq);
|
||||
while (skb_queue_len(inputq)) {
|
||||
dport = tipc_skb_peek_port(inputq, dport);
|
||||
tsk = tipc_sk_lookup(net, dport);
|
||||
@@ -1788,9 +1813,14 @@ void tipc_sk_rcv(struct net *net, struct sk_buff_head *inputq)
|
||||
if (likely(tsk)) {
|
||||
sk = &tsk->sk;
|
||||
if (likely(spin_trylock_bh(&sk->sk_lock.slock))) {
|
||||
- tipc_sk_enqueue(inputq, sk, dport);
|
||||
+ tipc_sk_enqueue(inputq, sk, dport, &xmitq);
|
||||
spin_unlock_bh(&sk->sk_lock.slock);
|
||||
}
|
||||
+ /* Send pending response/rejected messages, if any */
|
||||
+ while ((skb = __skb_dequeue(&xmitq))) {
|
||||
+ dnode = msg_destnode(buf_msg(skb));
|
||||
+ tipc_node_xmit_skb(net, skb, dnode, dport);
|
||||
+ }
|
||||
sock_put(sk);
|
||||
continue;
|
||||
}
|
||||
diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c
|
||||
index 6af78c6276b4..78d6b78de29d 100644
|
||||
--- a/net/tipc/udp_media.c
|
||||
+++ b/net/tipc/udp_media.c
|
||||
@@ -52,7 +52,7 @@
|
||||
/* IANA assigned UDP port */
|
||||
#define UDP_PORT_DEFAULT 6118
|
||||
|
||||
-#define UDP_MIN_HEADROOM 28
|
||||
+#define UDP_MIN_HEADROOM 48
|
||||
|
||||
static const struct nla_policy tipc_nl_udp_policy[TIPC_NLA_UDP_MAX + 1] = {
|
||||
[TIPC_NLA_UDP_UNSPEC] = {.type = NLA_UNSPEC},
|
||||
@@ -376,6 +376,11 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b,
|
||||
udp_conf.local_ip.s_addr = htonl(INADDR_ANY);
|
||||
udp_conf.use_udp_checksums = false;
|
||||
ub->ifindex = dev->ifindex;
|
||||
+ if (tipc_mtu_bad(dev, sizeof(struct iphdr) +
|
||||
+ sizeof(struct udphdr))) {
|
||||
+ err = -EINVAL;
|
||||
+ goto err;
|
||||
+ }
|
||||
b->mtu = dev->mtu - sizeof(struct iphdr)
|
||||
- sizeof(struct udphdr);
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
1309
patch/kernel/mvebu64-default/03-patch-4.4.65-66.patch
Normal file
1309
patch/kernel/mvebu64-default/03-patch-4.4.65-66.patch
Normal file
File diff suppressed because it is too large
Load diff
948
patch/kernel/mvebu64-default/03-patch-4.4.66-67.patch
Normal file
948
patch/kernel/mvebu64-default/03-patch-4.4.66-67.patch
Normal file
|
@ -0,0 +1,948 @@
|
|||
diff --git a/Makefile b/Makefile
|
||||
index 1cd052823c03..c987902ae1ee 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -1,6 +1,6 @@
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 4
|
||||
-SUBLEVEL = 66
|
||||
+SUBLEVEL = 67
|
||||
EXTRAVERSION =
|
||||
NAME = Blurry Fish Butt
|
||||
|
||||
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
|
||||
index 9462d2752850..8bdc34dbaedf 100644
|
||||
--- a/drivers/block/drbd/drbd_bitmap.c
|
||||
+++ b/drivers/block/drbd/drbd_bitmap.c
|
||||
@@ -479,8 +479,14 @@ void drbd_bm_cleanup(struct drbd_device *device)
|
||||
* this masks out the remaining bits.
|
||||
* Returns the number of bits cleared.
|
||||
*/
|
||||
+#ifndef BITS_PER_PAGE
|
||||
#define BITS_PER_PAGE (1UL << (PAGE_SHIFT + 3))
|
||||
#define BITS_PER_PAGE_MASK (BITS_PER_PAGE - 1)
|
||||
+#else
|
||||
+# if BITS_PER_PAGE != (1UL << (PAGE_SHIFT + 3))
|
||||
+# error "ambiguous BITS_PER_PAGE"
|
||||
+# endif
|
||||
+#endif
|
||||
#define BITS_PER_LONG_MASK (BITS_PER_LONG - 1)
|
||||
static int bm_clear_surplus(struct drbd_bitmap *b)
|
||||
{
|
||||
diff --git a/drivers/infiniband/hw/qib/qib_qp.c b/drivers/infiniband/hw/qib/qib_qp.c
|
||||
index 3eff35c2d453..2684605fe67f 100644
|
||||
--- a/drivers/infiniband/hw/qib/qib_qp.c
|
||||
+++ b/drivers/infiniband/hw/qib/qib_qp.c
|
||||
@@ -41,13 +41,13 @@
|
||||
|
||||
#include "qib.h"
|
||||
|
||||
-#define BITS_PER_PAGE (PAGE_SIZE*BITS_PER_BYTE)
|
||||
-#define BITS_PER_PAGE_MASK (BITS_PER_PAGE-1)
|
||||
+#define RVT_BITS_PER_PAGE (PAGE_SIZE*BITS_PER_BYTE)
|
||||
+#define RVT_BITS_PER_PAGE_MASK (RVT_BITS_PER_PAGE-1)
|
||||
|
||||
static inline unsigned mk_qpn(struct qib_qpn_table *qpt,
|
||||
struct qpn_map *map, unsigned off)
|
||||
{
|
||||
- return (map - qpt->map) * BITS_PER_PAGE + off;
|
||||
+ return (map - qpt->map) * RVT_BITS_PER_PAGE + off;
|
||||
}
|
||||
|
||||
static inline unsigned find_next_offset(struct qib_qpn_table *qpt,
|
||||
@@ -59,7 +59,7 @@ static inline unsigned find_next_offset(struct qib_qpn_table *qpt,
|
||||
if (((off & qpt->mask) >> 1) >= n)
|
||||
off = (off | qpt->mask) + 2;
|
||||
} else
|
||||
- off = find_next_zero_bit(map->page, BITS_PER_PAGE, off);
|
||||
+ off = find_next_zero_bit(map->page, RVT_BITS_PER_PAGE, off);
|
||||
return off;
|
||||
}
|
||||
|
||||
@@ -147,8 +147,8 @@ static int alloc_qpn(struct qib_devdata *dd, struct qib_qpn_table *qpt,
|
||||
qpn = 2;
|
||||
if (qpt->mask && ((qpn & qpt->mask) >> 1) >= dd->n_krcv_queues)
|
||||
qpn = (qpn | qpt->mask) + 2;
|
||||
- offset = qpn & BITS_PER_PAGE_MASK;
|
||||
- map = &qpt->map[qpn / BITS_PER_PAGE];
|
||||
+ offset = qpn & RVT_BITS_PER_PAGE_MASK;
|
||||
+ map = &qpt->map[qpn / RVT_BITS_PER_PAGE];
|
||||
max_scan = qpt->nmaps - !offset;
|
||||
for (i = 0;;) {
|
||||
if (unlikely(!map->page)) {
|
||||
@@ -173,7 +173,7 @@ static int alloc_qpn(struct qib_devdata *dd, struct qib_qpn_table *qpt,
|
||||
* We just need to be sure we don't loop
|
||||
* forever.
|
||||
*/
|
||||
- } while (offset < BITS_PER_PAGE && qpn < QPN_MAX);
|
||||
+ } while (offset < RVT_BITS_PER_PAGE && qpn < QPN_MAX);
|
||||
/*
|
||||
* In order to keep the number of pages allocated to a
|
||||
* minimum, we scan the all existing pages before increasing
|
||||
@@ -204,9 +204,9 @@ static void free_qpn(struct qib_qpn_table *qpt, u32 qpn)
|
||||
{
|
||||
struct qpn_map *map;
|
||||
|
||||
- map = qpt->map + qpn / BITS_PER_PAGE;
|
||||
+ map = qpt->map + qpn / RVT_BITS_PER_PAGE;
|
||||
if (map->page)
|
||||
- clear_bit(qpn & BITS_PER_PAGE_MASK, map->page);
|
||||
+ clear_bit(qpn & RVT_BITS_PER_PAGE_MASK, map->page);
|
||||
}
|
||||
|
||||
static inline unsigned qpn_hash(struct qib_ibdev *dev, u32 qpn)
|
||||
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
|
||||
index 80a439543259..e503279c34fc 100644
|
||||
--- a/drivers/md/dm-ioctl.c
|
||||
+++ b/drivers/md/dm-ioctl.c
|
||||
@@ -1843,7 +1843,7 @@ static int ctl_ioctl(uint command, struct dm_ioctl __user *user)
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
- param->data_size = sizeof(*param);
|
||||
+ param->data_size = offsetof(struct dm_ioctl, data);
|
||||
r = fn(param, input_param_size);
|
||||
|
||||
if (unlikely(param->flags & DM_BUFFER_FULL_FLAG) &&
|
||||
diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig
|
||||
index 54479c481a7a..8a25adced79f 100644
|
||||
--- a/drivers/mtd/chips/Kconfig
|
||||
+++ b/drivers/mtd/chips/Kconfig
|
||||
@@ -111,6 +111,7 @@ config MTD_MAP_BANK_WIDTH_16
|
||||
|
||||
config MTD_MAP_BANK_WIDTH_32
|
||||
bool "Support 256-bit buswidth" if MTD_CFI_GEOMETRY
|
||||
+ select MTD_COMPLEX_MAPPINGS if HAS_IOMEM
|
||||
default n
|
||||
help
|
||||
If you wish to support CFI devices on a physical bus which is
|
||||
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
|
||||
index 49056c33be74..21e5b9ed1ead 100644
|
||||
--- a/drivers/net/ethernet/broadcom/tg3.c
|
||||
+++ b/drivers/net/ethernet/broadcom/tg3.c
|
||||
@@ -12031,7 +12031,7 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
|
||||
int ret;
|
||||
u32 offset, len, b_offset, odd_len;
|
||||
u8 *buf;
|
||||
- __be32 start, end;
|
||||
+ __be32 start = 0, end;
|
||||
|
||||
if (tg3_flag(tp, NO_NVRAM) ||
|
||||
eeprom->magic != TG3_EEPROM_MAGIC)
|
||||
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
|
||||
index 2882bcac918a..0b096730c72a 100644
|
||||
--- a/drivers/scsi/cxlflash/main.c
|
||||
+++ b/drivers/scsi/cxlflash/main.c
|
||||
@@ -996,6 +996,8 @@ static int wait_port_online(__be64 __iomem *fc_regs, u32 delay_us, u32 nretry)
|
||||
do {
|
||||
msleep(delay_us / 1000);
|
||||
status = readq_be(&fc_regs[FC_MTIP_STATUS / 8]);
|
||||
+ if (status == U64_MAX)
|
||||
+ nretry /= 2;
|
||||
} while ((status & FC_MTIP_STATUS_MASK) != FC_MTIP_STATUS_ONLINE &&
|
||||
nretry--);
|
||||
|
||||
@@ -1027,6 +1029,8 @@ static int wait_port_offline(__be64 __iomem *fc_regs, u32 delay_us, u32 nretry)
|
||||
do {
|
||||
msleep(delay_us / 1000);
|
||||
status = readq_be(&fc_regs[FC_MTIP_STATUS / 8]);
|
||||
+ if (status == U64_MAX)
|
||||
+ nretry /= 2;
|
||||
} while ((status & FC_MTIP_STATUS_MASK) != FC_MTIP_STATUS_OFFLINE &&
|
||||
nretry--);
|
||||
|
||||
@@ -1137,7 +1141,7 @@ static const struct asyc_intr_info ainfo[] = {
|
||||
{SISL_ASTATUS_FC0_LOGI_F, "login failed", 0, CLR_FC_ERROR},
|
||||
{SISL_ASTATUS_FC0_LOGI_S, "login succeeded", 0, SCAN_HOST},
|
||||
{SISL_ASTATUS_FC0_LINK_DN, "link down", 0, 0},
|
||||
- {SISL_ASTATUS_FC0_LINK_UP, "link up", 0, SCAN_HOST},
|
||||
+ {SISL_ASTATUS_FC0_LINK_UP, "link up", 0, 0},
|
||||
{SISL_ASTATUS_FC1_OTHER, "other error", 1, CLR_FC_ERROR | LINK_RESET},
|
||||
{SISL_ASTATUS_FC1_LOGO, "target initiated LOGO", 1, 0},
|
||||
{SISL_ASTATUS_FC1_CRC_T, "CRC threshold exceeded", 1, LINK_RESET},
|
||||
@@ -1145,7 +1149,7 @@ static const struct asyc_intr_info ainfo[] = {
|
||||
{SISL_ASTATUS_FC1_LOGI_F, "login failed", 1, CLR_FC_ERROR},
|
||||
{SISL_ASTATUS_FC1_LOGI_S, "login succeeded", 1, SCAN_HOST},
|
||||
{SISL_ASTATUS_FC1_LINK_DN, "link down", 1, 0},
|
||||
- {SISL_ASTATUS_FC1_LINK_UP, "link up", 1, SCAN_HOST},
|
||||
+ {SISL_ASTATUS_FC1_LINK_UP, "link up", 1, 0},
|
||||
{0x0, "", 0, 0} /* terminator */
|
||||
};
|
||||
|
||||
@@ -1962,6 +1966,11 @@ retry:
|
||||
* cxlflash_eh_host_reset_handler() - reset the host adapter
|
||||
* @scp: SCSI command from stack identifying host.
|
||||
*
|
||||
+ * Following a reset, the state is evaluated again in case an EEH occurred
|
||||
+ * during the reset. In such a scenario, the host reset will either yield
|
||||
+ * until the EEH recovery is complete or return success or failure based
|
||||
+ * upon the current device state.
|
||||
+ *
|
||||
* Return:
|
||||
* SUCCESS as defined in scsi/scsi.h
|
||||
* FAILED as defined in scsi/scsi.h
|
||||
@@ -1993,7 +2002,8 @@ static int cxlflash_eh_host_reset_handler(struct scsi_cmnd *scp)
|
||||
} else
|
||||
cfg->state = STATE_NORMAL;
|
||||
wake_up_all(&cfg->reset_waitq);
|
||||
- break;
|
||||
+ ssleep(1);
|
||||
+ /* fall through */
|
||||
case STATE_RESET:
|
||||
wait_event(cfg->reset_waitq, cfg->state != STATE_RESET);
|
||||
if (cfg->state == STATE_NORMAL)
|
||||
@@ -2534,6 +2544,9 @@ static void drain_ioctls(struct cxlflash_cfg *cfg)
|
||||
* @pdev: PCI device struct.
|
||||
* @state: PCI channel state.
|
||||
*
|
||||
+ * When an EEH occurs during an active reset, wait until the reset is
|
||||
+ * complete and then take action based upon the device state.
|
||||
+ *
|
||||
* Return: PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT
|
||||
*/
|
||||
static pci_ers_result_t cxlflash_pci_error_detected(struct pci_dev *pdev,
|
||||
@@ -2547,6 +2560,10 @@ static pci_ers_result_t cxlflash_pci_error_detected(struct pci_dev *pdev,
|
||||
|
||||
switch (state) {
|
||||
case pci_channel_io_frozen:
|
||||
+ wait_event(cfg->reset_waitq, cfg->state != STATE_RESET);
|
||||
+ if (cfg->state == STATE_FAILTERM)
|
||||
+ return PCI_ERS_RESULT_DISCONNECT;
|
||||
+
|
||||
cfg->state = STATE_RESET;
|
||||
scsi_block_requests(cfg->host);
|
||||
drain_ioctls(cfg);
|
||||
diff --git a/drivers/staging/rdma/ehca/ehca_mrmw.c b/drivers/staging/rdma/ehca/ehca_mrmw.c
|
||||
index f914b30999f8..4d52ca42644a 100644
|
||||
--- a/drivers/staging/rdma/ehca/ehca_mrmw.c
|
||||
+++ b/drivers/staging/rdma/ehca/ehca_mrmw.c
|
||||
@@ -1921,7 +1921,7 @@ static int ehca_set_pagebuf_user2(struct ehca_mr_pginfo *pginfo,
|
||||
u64 *kpage)
|
||||
{
|
||||
int ret = 0;
|
||||
- u64 pgaddr, prev_pgaddr;
|
||||
+ u64 pgaddr, prev_pgaddr = 0;
|
||||
u32 j = 0;
|
||||
int kpages_per_hwpage = pginfo->hwpage_size / PAGE_SIZE;
|
||||
int nr_kpages = kpages_per_hwpage;
|
||||
@@ -2417,6 +2417,7 @@ static int ehca_reg_bmap_mr_rpages(struct ehca_shca *shca,
|
||||
ehca_err(&shca->ib_device, "kpage alloc failed");
|
||||
return -ENOMEM;
|
||||
}
|
||||
+ hret = H_SUCCESS;
|
||||
for (top = 0; top < EHCA_MAP_ENTRIES; top++) {
|
||||
if (!ehca_bmap_valid(ehca_bmap->top[top]))
|
||||
continue;
|
||||
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
|
||||
index 83ff1724ec79..cf3da51a3536 100644
|
||||
--- a/drivers/tty/serial/8250/8250_pci.c
|
||||
+++ b/drivers/tty/serial/8250/8250_pci.c
|
||||
@@ -5850,17 +5850,15 @@ static pci_ers_result_t serial8250_io_slot_reset(struct pci_dev *dev)
|
||||
static void serial8250_io_resume(struct pci_dev *dev)
|
||||
{
|
||||
struct serial_private *priv = pci_get_drvdata(dev);
|
||||
- const struct pciserial_board *board;
|
||||
+ struct serial_private *new;
|
||||
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
- board = priv->board;
|
||||
- kfree(priv);
|
||||
- priv = pciserial_init_ports(dev, board);
|
||||
-
|
||||
- if (!IS_ERR(priv)) {
|
||||
- pci_set_drvdata(dev, priv);
|
||||
+ new = pciserial_init_ports(dev, priv->board);
|
||||
+ if (!IS_ERR(new)) {
|
||||
+ pci_set_drvdata(dev, new);
|
||||
+ kfree(priv);
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
|
||||
index 94906aaa9b7c..e2f6a79e9b01 100644
|
||||
--- a/fs/cifs/cifsglob.h
|
||||
+++ b/fs/cifs/cifsglob.h
|
||||
@@ -227,6 +227,7 @@ struct smb_version_operations {
|
||||
/* verify the message */
|
||||
int (*check_message)(char *, unsigned int);
|
||||
bool (*is_oplock_break)(char *, struct TCP_Server_Info *);
|
||||
+ int (*handle_cancelled_mid)(char *, struct TCP_Server_Info *);
|
||||
void (*downgrade_oplock)(struct TCP_Server_Info *,
|
||||
struct cifsInodeInfo *, bool);
|
||||
/* process transaction2 response */
|
||||
@@ -1289,12 +1290,19 @@ struct mid_q_entry {
|
||||
void *callback_data; /* general purpose pointer for callback */
|
||||
void *resp_buf; /* pointer to received SMB header */
|
||||
int mid_state; /* wish this were enum but can not pass to wait_event */
|
||||
+ unsigned int mid_flags;
|
||||
__le16 command; /* smb command code */
|
||||
bool large_buf:1; /* if valid response, is pointer to large buf */
|
||||
bool multiRsp:1; /* multiple trans2 responses for one request */
|
||||
bool multiEnd:1; /* both received */
|
||||
};
|
||||
|
||||
+struct close_cancelled_open {
|
||||
+ struct cifs_fid fid;
|
||||
+ struct cifs_tcon *tcon;
|
||||
+ struct work_struct work;
|
||||
+};
|
||||
+
|
||||
/* Make code in transport.c a little cleaner by moving
|
||||
update of optional stats into function below */
|
||||
#ifdef CONFIG_CIFS_STATS2
|
||||
@@ -1426,6 +1434,9 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param,
|
||||
#define MID_RESPONSE_MALFORMED 0x10
|
||||
#define MID_SHUTDOWN 0x20
|
||||
|
||||
+/* Flags */
|
||||
+#define MID_WAIT_CANCELLED 1 /* Cancelled while waiting for response */
|
||||
+
|
||||
/* Types of response buffer returned from SendReceive2 */
|
||||
#define CIFS_NO_BUFFER 0 /* Response buffer not returned */
|
||||
#define CIFS_SMALL_BUFFER 1
|
||||
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
|
||||
index b1104ed8f54c..5e2f8b8ca08a 100644
|
||||
--- a/fs/cifs/cifssmb.c
|
||||
+++ b/fs/cifs/cifssmb.c
|
||||
@@ -1424,6 +1424,8 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
||||
|
||||
length = discard_remaining_data(server);
|
||||
dequeue_mid(mid, rdata->result);
|
||||
+ mid->resp_buf = server->smallbuf;
|
||||
+ server->smallbuf = NULL;
|
||||
return length;
|
||||
}
|
||||
|
||||
@@ -1538,6 +1540,8 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
||||
return cifs_readv_discard(server, mid);
|
||||
|
||||
dequeue_mid(mid, false);
|
||||
+ mid->resp_buf = server->smallbuf;
|
||||
+ server->smallbuf = NULL;
|
||||
return length;
|
||||
}
|
||||
|
||||
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
|
||||
index 5d59f25521ce..156bc18eac69 100644
|
||||
--- a/fs/cifs/connect.c
|
||||
+++ b/fs/cifs/connect.c
|
||||
@@ -924,10 +924,19 @@ cifs_demultiplex_thread(void *p)
|
||||
|
||||
server->lstrp = jiffies;
|
||||
if (mid_entry != NULL) {
|
||||
+ if ((mid_entry->mid_flags & MID_WAIT_CANCELLED) &&
|
||||
+ mid_entry->mid_state == MID_RESPONSE_RECEIVED &&
|
||||
+ server->ops->handle_cancelled_mid)
|
||||
+ server->ops->handle_cancelled_mid(
|
||||
+ mid_entry->resp_buf,
|
||||
+ server);
|
||||
+
|
||||
if (!mid_entry->multiRsp || mid_entry->multiEnd)
|
||||
mid_entry->callback(mid_entry);
|
||||
- } else if (!server->ops->is_oplock_break ||
|
||||
- !server->ops->is_oplock_break(buf, server)) {
|
||||
+ } else if (server->ops->is_oplock_break &&
|
||||
+ server->ops->is_oplock_break(buf, server)) {
|
||||
+ cifs_dbg(FYI, "Received oplock break\n");
|
||||
+ } else {
|
||||
cifs_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n",
|
||||
atomic_read(&midCount));
|
||||
cifs_dump_mem("Received Data is: ", buf,
|
||||
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
|
||||
index e5bc85e49be7..76ccf20fbfb7 100644
|
||||
--- a/fs/cifs/smb2misc.c
|
||||
+++ b/fs/cifs/smb2misc.c
|
||||
@@ -630,3 +630,47 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
|
||||
cifs_dbg(FYI, "Can not process oplock break for non-existent connection\n");
|
||||
return false;
|
||||
}
|
||||
+
|
||||
+void
|
||||
+smb2_cancelled_close_fid(struct work_struct *work)
|
||||
+{
|
||||
+ struct close_cancelled_open *cancelled = container_of(work,
|
||||
+ struct close_cancelled_open, work);
|
||||
+
|
||||
+ cifs_dbg(VFS, "Close unmatched open\n");
|
||||
+
|
||||
+ SMB2_close(0, cancelled->tcon, cancelled->fid.persistent_fid,
|
||||
+ cancelled->fid.volatile_fid);
|
||||
+ cifs_put_tcon(cancelled->tcon);
|
||||
+ kfree(cancelled);
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info *server)
|
||||
+{
|
||||
+ struct smb2_hdr *hdr = (struct smb2_hdr *)buffer;
|
||||
+ struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)buffer;
|
||||
+ struct cifs_tcon *tcon;
|
||||
+ struct close_cancelled_open *cancelled;
|
||||
+
|
||||
+ if (hdr->Command != SMB2_CREATE || hdr->Status != STATUS_SUCCESS)
|
||||
+ return 0;
|
||||
+
|
||||
+ cancelled = kzalloc(sizeof(*cancelled), GFP_KERNEL);
|
||||
+ if (!cancelled)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ tcon = smb2_find_smb_tcon(server, hdr->SessionId, hdr->TreeId);
|
||||
+ if (!tcon) {
|
||||
+ kfree(cancelled);
|
||||
+ return -ENOENT;
|
||||
+ }
|
||||
+
|
||||
+ cancelled->fid.persistent_fid = rsp->PersistentFileId;
|
||||
+ cancelled->fid.volatile_fid = rsp->VolatileFileId;
|
||||
+ cancelled->tcon = tcon;
|
||||
+ INIT_WORK(&cancelled->work, smb2_cancelled_close_fid);
|
||||
+ queue_work(cifsiod_wq, &cancelled->work);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
|
||||
index be34b4860675..087918c4612a 100644
|
||||
--- a/fs/cifs/smb2ops.c
|
||||
+++ b/fs/cifs/smb2ops.c
|
||||
@@ -1511,6 +1511,7 @@ struct smb_version_operations smb20_operations = {
|
||||
.clear_stats = smb2_clear_stats,
|
||||
.print_stats = smb2_print_stats,
|
||||
.is_oplock_break = smb2_is_valid_oplock_break,
|
||||
+ .handle_cancelled_mid = smb2_handle_cancelled_mid,
|
||||
.downgrade_oplock = smb2_downgrade_oplock,
|
||||
.need_neg = smb2_need_neg,
|
||||
.negotiate = smb2_negotiate,
|
||||
@@ -1589,6 +1590,7 @@ struct smb_version_operations smb21_operations = {
|
||||
.clear_stats = smb2_clear_stats,
|
||||
.print_stats = smb2_print_stats,
|
||||
.is_oplock_break = smb2_is_valid_oplock_break,
|
||||
+ .handle_cancelled_mid = smb2_handle_cancelled_mid,
|
||||
.downgrade_oplock = smb2_downgrade_oplock,
|
||||
.need_neg = smb2_need_neg,
|
||||
.negotiate = smb2_negotiate,
|
||||
@@ -1670,6 +1672,7 @@ struct smb_version_operations smb30_operations = {
|
||||
.print_stats = smb2_print_stats,
|
||||
.dump_share_caps = smb2_dump_share_caps,
|
||||
.is_oplock_break = smb2_is_valid_oplock_break,
|
||||
+ .handle_cancelled_mid = smb2_handle_cancelled_mid,
|
||||
.downgrade_oplock = smb2_downgrade_oplock,
|
||||
.need_neg = smb2_need_neg,
|
||||
.negotiate = smb2_negotiate,
|
||||
@@ -1757,6 +1760,7 @@ struct smb_version_operations smb311_operations = {
|
||||
.print_stats = smb2_print_stats,
|
||||
.dump_share_caps = smb2_dump_share_caps,
|
||||
.is_oplock_break = smb2_is_valid_oplock_break,
|
||||
+ .handle_cancelled_mid = smb2_handle_cancelled_mid,
|
||||
.downgrade_oplock = smb2_downgrade_oplock,
|
||||
.need_neg = smb2_need_neg,
|
||||
.negotiate = smb2_negotiate,
|
||||
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
|
||||
index 0a406ae78129..adc5234486c3 100644
|
||||
--- a/fs/cifs/smb2proto.h
|
||||
+++ b/fs/cifs/smb2proto.h
|
||||
@@ -47,6 +47,10 @@ extern struct mid_q_entry *smb2_setup_request(struct cifs_ses *ses,
|
||||
struct smb_rqst *rqst);
|
||||
extern struct mid_q_entry *smb2_setup_async_request(
|
||||
struct TCP_Server_Info *server, struct smb_rqst *rqst);
|
||||
+extern struct cifs_ses *smb2_find_smb_ses(struct TCP_Server_Info *server,
|
||||
+ __u64 ses_id);
|
||||
+extern struct cifs_tcon *smb2_find_smb_tcon(struct TCP_Server_Info *server,
|
||||
+ __u64 ses_id, __u32 tid);
|
||||
extern int smb2_calc_signature(struct smb_rqst *rqst,
|
||||
struct TCP_Server_Info *server);
|
||||
extern int smb3_calc_signature(struct smb_rqst *rqst,
|
||||
@@ -157,6 +161,9 @@ extern int SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
extern int SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const u64 persistent_fid, const u64 volatile_fid,
|
||||
const __u8 oplock_level);
|
||||
+extern int smb2_handle_cancelled_mid(char *buffer,
|
||||
+ struct TCP_Server_Info *server);
|
||||
+void smb2_cancelled_close_fid(struct work_struct *work);
|
||||
extern int SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
u64 persistent_file_id, u64 volatile_file_id,
|
||||
struct kstatfs *FSData);
|
||||
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
|
||||
index d4c5b6f109a7..69e3b322bbfe 100644
|
||||
--- a/fs/cifs/smb2transport.c
|
||||
+++ b/fs/cifs/smb2transport.c
|
||||
@@ -115,22 +115,68 @@ smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
|
||||
}
|
||||
|
||||
static struct cifs_ses *
|
||||
-smb2_find_smb_ses(struct smb2_hdr *smb2hdr, struct TCP_Server_Info *server)
|
||||
+smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id)
|
||||
{
|
||||
struct cifs_ses *ses;
|
||||
|
||||
- spin_lock(&cifs_tcp_ses_lock);
|
||||
list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
|
||||
- if (ses->Suid != smb2hdr->SessionId)
|
||||
+ if (ses->Suid != ses_id)
|
||||
continue;
|
||||
- spin_unlock(&cifs_tcp_ses_lock);
|
||||
return ses;
|
||||
}
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+struct cifs_ses *
|
||||
+smb2_find_smb_ses(struct TCP_Server_Info *server, __u64 ses_id)
|
||||
+{
|
||||
+ struct cifs_ses *ses;
|
||||
+
|
||||
+ spin_lock(&cifs_tcp_ses_lock);
|
||||
+ ses = smb2_find_smb_ses_unlocked(server, ses_id);
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
+ return ses;
|
||||
+}
|
||||
+
|
||||
+static struct cifs_tcon *
|
||||
+smb2_find_smb_sess_tcon_unlocked(struct cifs_ses *ses, __u32 tid)
|
||||
+{
|
||||
+ struct cifs_tcon *tcon;
|
||||
+
|
||||
+ list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
|
||||
+ if (tcon->tid != tid)
|
||||
+ continue;
|
||||
+ ++tcon->tc_count;
|
||||
+ return tcon;
|
||||
+ }
|
||||
+
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Obtain tcon corresponding to the tid in the given
|
||||
+ * cifs_ses
|
||||
+ */
|
||||
+
|
||||
+struct cifs_tcon *
|
||||
+smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id, __u32 tid)
|
||||
+{
|
||||
+ struct cifs_ses *ses;
|
||||
+ struct cifs_tcon *tcon;
|
||||
+
|
||||
+ spin_lock(&cifs_tcp_ses_lock);
|
||||
+ ses = smb2_find_smb_ses_unlocked(server, ses_id);
|
||||
+ if (!ses) {
|
||||
+ spin_unlock(&cifs_tcp_ses_lock);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ tcon = smb2_find_smb_sess_tcon_unlocked(ses, tid);
|
||||
+ spin_unlock(&cifs_tcp_ses_lock);
|
||||
+
|
||||
+ return tcon;
|
||||
+}
|
||||
|
||||
int
|
||||
smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
|
||||
@@ -143,7 +189,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
|
||||
struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base;
|
||||
struct cifs_ses *ses;
|
||||
|
||||
- ses = smb2_find_smb_ses(smb2_pdu, server);
|
||||
+ ses = smb2_find_smb_ses(server, smb2_pdu->SessionId);
|
||||
if (!ses) {
|
||||
cifs_dbg(VFS, "%s: Could not find session\n", __func__);
|
||||
return 0;
|
||||
@@ -314,7 +360,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
|
||||
struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base;
|
||||
struct cifs_ses *ses;
|
||||
|
||||
- ses = smb2_find_smb_ses(smb2_pdu, server);
|
||||
+ ses = smb2_find_smb_ses(server, smb2_pdu->SessionId);
|
||||
if (!ses) {
|
||||
cifs_dbg(VFS, "%s: Could not find session\n", __func__);
|
||||
return 0;
|
||||
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
|
||||
index 87abe8ed074c..54af10204e83 100644
|
||||
--- a/fs/cifs/transport.c
|
||||
+++ b/fs/cifs/transport.c
|
||||
@@ -786,9 +786,11 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
|
||||
|
||||
rc = wait_for_response(ses->server, midQ);
|
||||
if (rc != 0) {
|
||||
+ cifs_dbg(FYI, "Cancelling wait for mid %llu\n", midQ->mid);
|
||||
send_cancel(ses->server, buf, midQ);
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
|
||||
+ midQ->mid_flags |= MID_WAIT_CANCELLED;
|
||||
midQ->callback = DeleteMidQEntry;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
cifs_small_buf_release(buf);
|
||||
diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c
|
||||
index 1a0835073663..9d6c2dcf1bd0 100644
|
||||
--- a/fs/ext4/crypto.c
|
||||
+++ b/fs/ext4/crypto.c
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <linux/random.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/spinlock_types.h>
|
||||
+#include <linux/namei.h>
|
||||
|
||||
#include "ext4_extents.h"
|
||||
#include "xattr.h"
|
||||
@@ -469,3 +470,61 @@ uint32_t ext4_validate_encryption_key_size(uint32_t mode, uint32_t size)
|
||||
return size;
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+/*
|
||||
+ * Validate dentries for encrypted directories to make sure we aren't
|
||||
+ * potentially caching stale data after a key has been added or
|
||||
+ * removed.
|
||||
+ */
|
||||
+static int ext4_d_revalidate(struct dentry *dentry, unsigned int flags)
|
||||
+{
|
||||
+ struct dentry *dir;
|
||||
+ struct ext4_crypt_info *ci;
|
||||
+ int dir_has_key, cached_with_key;
|
||||
+
|
||||
+ if (flags & LOOKUP_RCU)
|
||||
+ return -ECHILD;
|
||||
+
|
||||
+ dir = dget_parent(dentry);
|
||||
+ if (!ext4_encrypted_inode(d_inode(dir))) {
|
||||
+ dput(dir);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ ci = EXT4_I(d_inode(dir))->i_crypt_info;
|
||||
+
|
||||
+ /* this should eventually be an flag in d_flags */
|
||||
+ cached_with_key = dentry->d_fsdata != NULL;
|
||||
+ dir_has_key = (ci != NULL);
|
||||
+ dput(dir);
|
||||
+
|
||||
+ /*
|
||||
+ * If the dentry was cached without the key, and it is a
|
||||
+ * negative dentry, it might be a valid name. We can't check
|
||||
+ * if the key has since been made available due to locking
|
||||
+ * reasons, so we fail the validation so ext4_lookup() can do
|
||||
+ * this check.
|
||||
+ *
|
||||
+ * We also fail the validation if the dentry was created with
|
||||
+ * the key present, but we no longer have the key, or vice versa.
|
||||
+ */
|
||||
+ if ((!cached_with_key && d_is_negative(dentry)) ||
|
||||
+ (!cached_with_key && dir_has_key) ||
|
||||
+ (cached_with_key && !dir_has_key)) {
|
||||
+#if 0 /* Revalidation debug */
|
||||
+ char buf[80];
|
||||
+ char *cp = simple_dname(dentry, buf, sizeof(buf));
|
||||
+
|
||||
+ if (IS_ERR(cp))
|
||||
+ cp = (char *) "???";
|
||||
+ pr_err("revalidate: %s %p %d %d %d\n", cp, dentry->d_fsdata,
|
||||
+ cached_with_key, d_is_negative(dentry),
|
||||
+ dir_has_key);
|
||||
+#endif
|
||||
+ return 0;
|
||||
+ }
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+const struct dentry_operations ext4_encrypted_d_ops = {
|
||||
+ .d_revalidate = ext4_d_revalidate,
|
||||
+};
|
||||
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
|
||||
index 1d1bca74f844..6d17f31a31d7 100644
|
||||
--- a/fs/ext4/dir.c
|
||||
+++ b/fs/ext4/dir.c
|
||||
@@ -111,6 +111,12 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
|
||||
int dir_has_error = 0;
|
||||
struct ext4_str fname_crypto_str = {.name = NULL, .len = 0};
|
||||
|
||||
+ if (ext4_encrypted_inode(inode)) {
|
||||
+ err = ext4_get_encryption_info(inode);
|
||||
+ if (err && err != -ENOKEY)
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
if (is_dx_dir(inode)) {
|
||||
err = ext4_dx_readdir(file, ctx);
|
||||
if (err != ERR_BAD_DX_DIR) {
|
||||
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
|
||||
index 362d59b24f1d..3de9bb357b4f 100644
|
||||
--- a/fs/ext4/ext4.h
|
||||
+++ b/fs/ext4/ext4.h
|
||||
@@ -2268,6 +2268,7 @@ struct page *ext4_encrypt(struct inode *inode,
|
||||
struct page *plaintext_page);
|
||||
int ext4_decrypt(struct page *page);
|
||||
int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex);
|
||||
+extern const struct dentry_operations ext4_encrypted_d_ops;
|
||||
|
||||
#ifdef CONFIG_EXT4_FS_ENCRYPTION
|
||||
int ext4_init_crypto(void);
|
||||
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
|
||||
index 789e2d6724a9..bcd7c4788903 100644
|
||||
--- a/fs/ext4/ioctl.c
|
||||
+++ b/fs/ext4/ioctl.c
|
||||
@@ -622,6 +622,9 @@ resizefs_out:
|
||||
struct ext4_encryption_policy policy;
|
||||
int err = 0;
|
||||
|
||||
+ if (!ext4_has_feature_encrypt(sb))
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
if (copy_from_user(&policy,
|
||||
(struct ext4_encryption_policy __user *)arg,
|
||||
sizeof(policy))) {
|
||||
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
|
||||
index 573b4cbb0cb9..fafa903ab3c0 100644
|
||||
--- a/fs/ext4/namei.c
|
||||
+++ b/fs/ext4/namei.c
|
||||
@@ -1557,6 +1557,24 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
|
||||
struct ext4_dir_entry_2 *de;
|
||||
struct buffer_head *bh;
|
||||
|
||||
+ if (ext4_encrypted_inode(dir)) {
|
||||
+ int res = ext4_get_encryption_info(dir);
|
||||
+
|
||||
+ /*
|
||||
+ * This should be a properly defined flag for
|
||||
+ * dentry->d_flags when we uplift this to the VFS.
|
||||
+ * d_fsdata is set to (void *) 1 if if the dentry is
|
||||
+ * created while the directory was encrypted and we
|
||||
+ * don't have access to the key.
|
||||
+ */
|
||||
+ dentry->d_fsdata = NULL;
|
||||
+ if (ext4_encryption_info(dir))
|
||||
+ dentry->d_fsdata = (void *) 1;
|
||||
+ d_set_d_op(dentry, &ext4_encrypted_d_ops);
|
||||
+ if (res && res != -ENOKEY)
|
||||
+ return ERR_PTR(res);
|
||||
+ }
|
||||
+
|
||||
if (dentry->d_name.len > EXT4_NAME_LEN)
|
||||
return ERR_PTR(-ENAMETOOLONG);
|
||||
|
||||
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
|
||||
index 00575d776d91..7162ab7bc093 100644
|
||||
--- a/fs/nfsd/nfs3xdr.c
|
||||
+++ b/fs/nfsd/nfs3xdr.c
|
||||
@@ -358,6 +358,7 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
|
||||
{
|
||||
unsigned int len, v, hdr, dlen;
|
||||
u32 max_blocksize = svc_max_payload(rqstp);
|
||||
+ struct kvec *head = rqstp->rq_arg.head;
|
||||
|
||||
p = decode_fh(p, &args->fh);
|
||||
if (!p)
|
||||
@@ -367,6 +368,8 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
|
||||
args->count = ntohl(*p++);
|
||||
args->stable = ntohl(*p++);
|
||||
len = args->len = ntohl(*p++);
|
||||
+ if ((void *)p > head->iov_base + head->iov_len)
|
||||
+ return 0;
|
||||
/*
|
||||
* The count must equal the amount of data passed.
|
||||
*/
|
||||
@@ -377,9 +380,8 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
|
||||
* Check to make sure that we got the right number of
|
||||
* bytes.
|
||||
*/
|
||||
- hdr = (void*)p - rqstp->rq_arg.head[0].iov_base;
|
||||
- dlen = rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len
|
||||
- - hdr;
|
||||
+ hdr = (void*)p - head->iov_base;
|
||||
+ dlen = head->iov_len + rqstp->rq_arg.page_len - hdr;
|
||||
/*
|
||||
* Round the length of the data which was specified up to
|
||||
* the next multiple of XDR units and then compare that
|
||||
@@ -396,7 +398,7 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
|
||||
len = args->len = max_blocksize;
|
||||
}
|
||||
rqstp->rq_vec[0].iov_base = (void*)p;
|
||||
- rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr;
|
||||
+ rqstp->rq_vec[0].iov_len = head->iov_len - hdr;
|
||||
v = 0;
|
||||
while (len > rqstp->rq_vec[v].iov_len) {
|
||||
len -= rqstp->rq_vec[v].iov_len;
|
||||
@@ -471,6 +473,8 @@ nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p,
|
||||
/* first copy and check from the first page */
|
||||
old = (char*)p;
|
||||
vec = &rqstp->rq_arg.head[0];
|
||||
+ if ((void *)old > vec->iov_base + vec->iov_len)
|
||||
+ return 0;
|
||||
avail = vec->iov_len - (old - (char*)vec->iov_base);
|
||||
while (len && avail && *old) {
|
||||
*new++ = *old++;
|
||||
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
|
||||
index 79d964aa8079..bf913201a6ad 100644
|
||||
--- a/fs/nfsd/nfsxdr.c
|
||||
+++ b/fs/nfsd/nfsxdr.c
|
||||
@@ -280,6 +280,7 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
|
||||
struct nfsd_writeargs *args)
|
||||
{
|
||||
unsigned int len, hdr, dlen;
|
||||
+ struct kvec *head = rqstp->rq_arg.head;
|
||||
int v;
|
||||
|
||||
p = decode_fh(p, &args->fh);
|
||||
@@ -300,9 +301,10 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
|
||||
* Check to make sure that we got the right number of
|
||||
* bytes.
|
||||
*/
|
||||
- hdr = (void*)p - rqstp->rq_arg.head[0].iov_base;
|
||||
- dlen = rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len
|
||||
- - hdr;
|
||||
+ hdr = (void*)p - head->iov_base;
|
||||
+ if (hdr > head->iov_len)
|
||||
+ return 0;
|
||||
+ dlen = head->iov_len + rqstp->rq_arg.page_len - hdr;
|
||||
|
||||
/*
|
||||
* Round the length of the data which was specified up to
|
||||
@@ -316,7 +318,7 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
|
||||
return 0;
|
||||
|
||||
rqstp->rq_vec[0].iov_base = (void*)p;
|
||||
- rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr;
|
||||
+ rqstp->rq_vec[0].iov_len = head->iov_len - hdr;
|
||||
v = 0;
|
||||
while (len > rqstp->rq_vec[v].iov_len) {
|
||||
len -= rqstp->rq_vec[v].iov_len;
|
||||
diff --git a/fs/timerfd.c b/fs/timerfd.c
|
||||
index 053818dd6c18..1327a02ec778 100644
|
||||
--- a/fs/timerfd.c
|
||||
+++ b/fs/timerfd.c
|
||||
@@ -40,6 +40,7 @@ struct timerfd_ctx {
|
||||
short unsigned settime_flags; /* to show in fdinfo */
|
||||
struct rcu_head rcu;
|
||||
struct list_head clist;
|
||||
+ spinlock_t cancel_lock;
|
||||
bool might_cancel;
|
||||
};
|
||||
|
||||
@@ -112,7 +113,7 @@ void timerfd_clock_was_set(void)
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
-static void timerfd_remove_cancel(struct timerfd_ctx *ctx)
|
||||
+static void __timerfd_remove_cancel(struct timerfd_ctx *ctx)
|
||||
{
|
||||
if (ctx->might_cancel) {
|
||||
ctx->might_cancel = false;
|
||||
@@ -122,6 +123,13 @@ static void timerfd_remove_cancel(struct timerfd_ctx *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
+static void timerfd_remove_cancel(struct timerfd_ctx *ctx)
|
||||
+{
|
||||
+ spin_lock(&ctx->cancel_lock);
|
||||
+ __timerfd_remove_cancel(ctx);
|
||||
+ spin_unlock(&ctx->cancel_lock);
|
||||
+}
|
||||
+
|
||||
static bool timerfd_canceled(struct timerfd_ctx *ctx)
|
||||
{
|
||||
if (!ctx->might_cancel || ctx->moffs.tv64 != KTIME_MAX)
|
||||
@@ -132,6 +140,7 @@ static bool timerfd_canceled(struct timerfd_ctx *ctx)
|
||||
|
||||
static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags)
|
||||
{
|
||||
+ spin_lock(&ctx->cancel_lock);
|
||||
if ((ctx->clockid == CLOCK_REALTIME ||
|
||||
ctx->clockid == CLOCK_REALTIME_ALARM) &&
|
||||
(flags & TFD_TIMER_ABSTIME) && (flags & TFD_TIMER_CANCEL_ON_SET)) {
|
||||
@@ -141,9 +150,10 @@ static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags)
|
||||
list_add_rcu(&ctx->clist, &cancel_list);
|
||||
spin_unlock(&cancel_lock);
|
||||
}
|
||||
- } else if (ctx->might_cancel) {
|
||||
- timerfd_remove_cancel(ctx);
|
||||
+ } else {
|
||||
+ __timerfd_remove_cancel(ctx);
|
||||
}
|
||||
+ spin_unlock(&ctx->cancel_lock);
|
||||
}
|
||||
|
||||
static ktime_t timerfd_get_remaining(struct timerfd_ctx *ctx)
|
||||
@@ -395,6 +405,7 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
|
||||
return -ENOMEM;
|
||||
|
||||
init_waitqueue_head(&ctx->wqh);
|
||||
+ spin_lock_init(&ctx->cancel_lock);
|
||||
ctx->clockid = clockid;
|
||||
|
||||
if (isalarm(ctx))
|
||||
diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h
|
||||
index 366cf77953b5..806d0ab845e0 100644
|
||||
--- a/include/linux/mtd/map.h
|
||||
+++ b/include/linux/mtd/map.h
|
||||
@@ -122,18 +122,13 @@
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MTD_MAP_BANK_WIDTH_32
|
||||
-# ifdef map_bankwidth
|
||||
-# undef map_bankwidth
|
||||
-# define map_bankwidth(map) ((map)->bankwidth)
|
||||
-# undef map_bankwidth_is_large
|
||||
-# define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8)
|
||||
-# undef map_words
|
||||
-# define map_words(map) map_calc_words(map)
|
||||
-# else
|
||||
-# define map_bankwidth(map) 32
|
||||
-# define map_bankwidth_is_large(map) (1)
|
||||
-# define map_words(map) map_calc_words(map)
|
||||
-# endif
|
||||
+/* always use indirect access for 256-bit to preserve kernel stack */
|
||||
+# undef map_bankwidth
|
||||
+# define map_bankwidth(map) ((map)->bankwidth)
|
||||
+# undef map_bankwidth_is_large
|
||||
+# define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8)
|
||||
+# undef map_words
|
||||
+# define map_words(map) map_calc_words(map)
|
||||
#define map_bankwidth_is_32(map) (map_bankwidth(map) == 32)
|
||||
#undef MAX_MAP_BANKWIDTH
|
||||
#define MAX_MAP_BANKWIDTH 32
|
||||
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
|
||||
index 8e33019d8e7b..acfb16fdcd55 100644
|
||||
--- a/net/netlink/af_netlink.c
|
||||
+++ b/net/netlink/af_netlink.c
|
||||
@@ -2107,7 +2107,7 @@ static int netlink_dump(struct sock *sk)
|
||||
if (!skb) {
|
||||
alloc_size = alloc_min_size;
|
||||
skb = netlink_alloc_skb(sk, alloc_size, nlk->portid,
|
||||
- (GFP_KERNEL & ~__GFP_DIRECT_RECLAIM));
|
||||
+ GFP_KERNEL);
|
||||
}
|
||||
if (!skb)
|
||||
goto errout_skb;
|
||||
diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c
|
||||
index 09da7b52bc2e..1468e4b7bf93 100644
|
||||
--- a/sound/ppc/awacs.c
|
||||
+++ b/sound/ppc/awacs.c
|
||||
@@ -991,6 +991,7 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
+ master_vol = NULL;
|
||||
if (pm7500)
|
||||
err = build_mixers(chip,
|
||||
ARRAY_SIZE(snd_pmac_awacs_mixers_pmac7500),
|
||||
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
|
||||
index 7a5c9a36c1db..daba8c56b43b 100644
|
||||
--- a/sound/soc/intel/boards/bytcr_rt5640.c
|
||||
+++ b/sound/soc/intel/boards/bytcr_rt5640.c
|
||||
@@ -139,7 +139,7 @@ static struct snd_soc_dai_link byt_dailink[] = {
|
||||
.codec_dai_name = "snd-soc-dummy-dai",
|
||||
.codec_name = "snd-soc-dummy",
|
||||
.platform_name = "sst-mfld-platform",
|
||||
- .ignore_suspend = 1,
|
||||
+ .nonatomic = true,
|
||||
.dynamic = 1,
|
||||
.dpcm_playback = 1,
|
||||
.dpcm_capture = 1,
|
||||
@@ -166,6 +166,7 @@ static struct snd_soc_dai_link byt_dailink[] = {
|
||||
| SND_SOC_DAIFMT_CBS_CFS,
|
||||
.be_hw_params_fixup = byt_codec_fixup,
|
||||
.ignore_suspend = 1,
|
||||
+ .nonatomic = true,
|
||||
.dpcm_playback = 1,
|
||||
.dpcm_capture = 1,
|
||||
.ops = &byt_be_ssp2_ops,
|
2093
patch/kernel/mvebu64-default/03-patch-4.4.67-68.patch
Normal file
2093
patch/kernel/mvebu64-default/03-patch-4.4.67-68.patch
Normal file
File diff suppressed because it is too large
Load diff
2955
patch/kernel/mvebu64-default/03-patch-4.4.68-69.patch
Normal file
2955
patch/kernel/mvebu64-default/03-patch-4.4.68-69.patch
Normal file
File diff suppressed because it is too large
Load diff
3739
patch/kernel/mvebu64-default/03-patch-4.4.69-70.patch
Normal file
3739
patch/kernel/mvebu64-default/03-patch-4.4.69-70.patch
Normal file
File diff suppressed because it is too large
Load diff
2203
patch/kernel/mvebu64-default/03-patch-4.4.70-71.patch
Normal file
2203
patch/kernel/mvebu64-default/03-patch-4.4.70-71.patch
Normal file
File diff suppressed because it is too large
Load diff
7
patch/kernel/mvebu64-default/remove_devel_version.patch
Normal file
7
patch/kernel/mvebu64-default/remove_devel_version.patch
Normal file
|
@ -0,0 +1,7 @@
|
|||
diff --git a/localversion b/localversion
|
||||
deleted file mode 100644
|
||||
index 649559a..0000000
|
||||
--- a/localversion
|
||||
+++ /dev/null
|
||||
@@ -1 +0,0 @@
|
||||
--devel-17.04.2
|
Loading…
Add table
Reference in a new issue