diff options
Diffstat (limited to '4.7.4/1003_linux-4.7.4.patch')
-rw-r--r-- | 4.7.4/1003_linux-4.7.4.patch | 2424 |
1 files changed, 2424 insertions, 0 deletions
diff --git a/4.7.4/1003_linux-4.7.4.patch b/4.7.4/1003_linux-4.7.4.patch new file mode 100644 index 0000000..af6c1d4 --- /dev/null +++ b/4.7.4/1003_linux-4.7.4.patch @@ -0,0 +1,2424 @@ +diff --git a/Makefile b/Makefile +index 4afff18..ec3bd11 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 4 + PATCHLEVEL = 7 +-SUBLEVEL = 3 ++SUBLEVEL = 4 + EXTRAVERSION = + NAME = Psychotic Stoned Sheep + +diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c +index 60078a6..b15e1c1 100644 +--- a/arch/x86/kernel/apic/apic.c ++++ b/arch/x86/kernel/apic/apic.c +@@ -1597,6 +1597,9 @@ void __init enable_IR_x2apic(void) + unsigned long flags; + int ret, ir_stat; + ++ if (skip_ioapic_setup) ++ return; ++ + ir_stat = irq_remapping_prepare(); + if (ir_stat < 0 && !x2apic_supported()) + return; +diff --git a/block/blk-core.c b/block/blk-core.c +index 2475b1c7..b993f88 100644 +--- a/block/blk-core.c ++++ b/block/blk-core.c +@@ -515,7 +515,9 @@ EXPORT_SYMBOL_GPL(blk_queue_bypass_end); + + void blk_set_queue_dying(struct request_queue *q) + { +- queue_flag_set_unlocked(QUEUE_FLAG_DYING, q); ++ spin_lock_irq(q->queue_lock); ++ queue_flag_set(QUEUE_FLAG_DYING, q); ++ spin_unlock_irq(q->queue_lock); + + if (q->mq_ops) + blk_mq_wake_waiters(q); +diff --git a/block/blk-merge.c b/block/blk-merge.c +index 2613531..bea9344 100644 +--- a/block/blk-merge.c ++++ b/block/blk-merge.c +@@ -94,9 +94,31 @@ static struct bio *blk_bio_segment_split(struct request_queue *q, + bool do_split = true; + struct bio *new = NULL; + const unsigned max_sectors = get_max_io_size(q, bio); ++ unsigned bvecs = 0; + + bio_for_each_segment(bv, bio, iter) { + /* ++ * With arbitrary bio size, the incoming bio may be very ++ * big. We have to split the bio into small bios so that ++ * each holds at most BIO_MAX_PAGES bvecs because ++ * bio_clone() can fail to allocate big bvecs. ++ * ++ * It should have been better to apply the limit per ++ * request queue in which bio_clone() is involved, ++ * instead of globally. The biggest blocker is the ++ * bio_clone() in bio bounce. ++ * ++ * If bio is splitted by this reason, we should have ++ * allowed to continue bios merging, but don't do ++ * that now for making the change simple. ++ * ++ * TODO: deal with bio bounce's bio_clone() gracefully ++ * and convert the global limit into per-queue limit. ++ */ ++ if (bvecs++ >= BIO_MAX_PAGES) ++ goto split; ++ ++ /* + * If the queue doesn't support SG gaps and adding this + * offset would create a gap, disallow it. + */ +diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c +index 84708a5..b206115 100644 +--- a/drivers/block/floppy.c ++++ b/drivers/block/floppy.c +@@ -3663,11 +3663,6 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) + + opened_bdev[drive] = bdev; + +- if (!(mode & (FMODE_READ|FMODE_WRITE))) { +- res = -EINVAL; +- goto out; +- } +- + res = -ENXIO; + + if (!floppy_track_buffer) { +@@ -3711,20 +3706,21 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) + if (UFDCS->rawcmd == 1) + UFDCS->rawcmd = 2; + +- UDRS->last_checked = 0; +- clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags); +- check_disk_change(bdev); +- if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags)) +- goto out; +- if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags)) +- goto out; +- +- res = -EROFS; +- +- if ((mode & FMODE_WRITE) && +- !test_bit(FD_DISK_WRITABLE_BIT, &UDRS->flags)) +- goto out; +- ++ if (!(mode & FMODE_NDELAY)) { ++ if (mode & (FMODE_READ|FMODE_WRITE)) { ++ UDRS->last_checked = 0; ++ clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags); ++ check_disk_change(bdev); ++ if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags)) ++ goto out; ++ if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags)) ++ goto out; ++ } ++ res = -EROFS; ++ if ((mode & FMODE_WRITE) && ++ !test_bit(FD_DISK_WRITABLE_BIT, &UDRS->flags)) ++ goto out; ++ } + mutex_unlock(&open_lock); + mutex_unlock(&floppy_mutex); + return 0; +diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c +index 0bb44d5..2ee40fd 100644 +--- a/drivers/cpufreq/cpufreq-dt-platdev.c ++++ b/drivers/cpufreq/cpufreq-dt-platdev.c +@@ -74,6 +74,8 @@ static const struct of_device_id machines[] __initconst = { + { .compatible = "ti,omap5", }, + + { .compatible = "xlnx,zynq-7000", }, ++ ++ { } + }; + + static int __init cpufreq_dt_platdev_init(void) +diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c +index 6dc5971..b304421 100644 +--- a/drivers/crypto/caam/caamalg.c ++++ b/drivers/crypto/caam/caamalg.c +@@ -556,7 +556,10 @@ skip_enc: + + /* Read and write assoclen bytes */ + append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ); +- append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ); ++ if (alg->caam.geniv) ++ append_math_add_imm_u32(desc, VARSEQOUTLEN, REG3, IMM, ivsize); ++ else ++ append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ); + + /* Skip assoc data */ + append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF); +@@ -565,6 +568,14 @@ skip_enc: + append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG | + KEY_VLF); + ++ if (alg->caam.geniv) { ++ append_seq_load(desc, ivsize, LDST_CLASS_1_CCB | ++ LDST_SRCDST_BYTE_CONTEXT | ++ (ctx1_iv_off << LDST_OFFSET_SHIFT)); ++ append_move(desc, MOVE_SRC_CLASS1CTX | MOVE_DEST_CLASS2INFIFO | ++ (ctx1_iv_off << MOVE_OFFSET_SHIFT) | ivsize); ++ } ++ + /* Load Counter into CONTEXT1 reg */ + if (is_rfc3686) + append_load_imm_u32(desc, be32_to_cpu(1), LDST_IMM | +@@ -2150,7 +2161,7 @@ static void init_authenc_job(struct aead_request *req, + + init_aead_job(req, edesc, all_contig, encrypt); + +- if (ivsize && (is_rfc3686 || !(alg->caam.geniv && encrypt))) ++ if (ivsize && ((is_rfc3686 && encrypt) || !alg->caam.geniv)) + append_load_as_imm(desc, req->iv, ivsize, + LDST_CLASS_1_CCB | + LDST_SRCDST_BYTE_CONTEXT | +@@ -2537,20 +2548,6 @@ static int aead_decrypt(struct aead_request *req) + return ret; + } + +-static int aead_givdecrypt(struct aead_request *req) +-{ +- struct crypto_aead *aead = crypto_aead_reqtfm(req); +- unsigned int ivsize = crypto_aead_ivsize(aead); +- +- if (req->cryptlen < ivsize) +- return -EINVAL; +- +- req->cryptlen -= ivsize; +- req->assoclen += ivsize; +- +- return aead_decrypt(req); +-} +- + /* + * allocate and map the ablkcipher extended descriptor for ablkcipher + */ +@@ -3210,7 +3207,7 @@ static struct caam_aead_alg driver_aeads[] = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, +- .decrypt = aead_givdecrypt, ++ .decrypt = aead_decrypt, + .ivsize = AES_BLOCK_SIZE, + .maxauthsize = MD5_DIGEST_SIZE, + }, +@@ -3256,7 +3253,7 @@ static struct caam_aead_alg driver_aeads[] = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, +- .decrypt = aead_givdecrypt, ++ .decrypt = aead_decrypt, + .ivsize = AES_BLOCK_SIZE, + .maxauthsize = SHA1_DIGEST_SIZE, + }, +@@ -3302,7 +3299,7 @@ static struct caam_aead_alg driver_aeads[] = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, +- .decrypt = aead_givdecrypt, ++ .decrypt = aead_decrypt, + .ivsize = AES_BLOCK_SIZE, + .maxauthsize = SHA224_DIGEST_SIZE, + }, +@@ -3348,7 +3345,7 @@ static struct caam_aead_alg driver_aeads[] = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, +- .decrypt = aead_givdecrypt, ++ .decrypt = aead_decrypt, + .ivsize = AES_BLOCK_SIZE, + .maxauthsize = SHA256_DIGEST_SIZE, + }, +@@ -3394,7 +3391,7 @@ static struct caam_aead_alg driver_aeads[] = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, +- .decrypt = aead_givdecrypt, ++ .decrypt = aead_decrypt, + .ivsize = AES_BLOCK_SIZE, + .maxauthsize = SHA384_DIGEST_SIZE, + }, +@@ -3440,7 +3437,7 @@ static struct caam_aead_alg driver_aeads[] = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, +- .decrypt = aead_givdecrypt, ++ .decrypt = aead_decrypt, + .ivsize = AES_BLOCK_SIZE, + .maxauthsize = SHA512_DIGEST_SIZE, + }, +@@ -3486,7 +3483,7 @@ static struct caam_aead_alg driver_aeads[] = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, +- .decrypt = aead_givdecrypt, ++ .decrypt = aead_decrypt, + .ivsize = DES3_EDE_BLOCK_SIZE, + .maxauthsize = MD5_DIGEST_SIZE, + }, +@@ -3534,7 +3531,7 @@ static struct caam_aead_alg driver_aeads[] = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, +- .decrypt = aead_givdecrypt, ++ .decrypt = aead_decrypt, + .ivsize = DES3_EDE_BLOCK_SIZE, + .maxauthsize = SHA1_DIGEST_SIZE, + }, +@@ -3582,7 +3579,7 @@ static struct caam_aead_alg driver_aeads[] = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, +- .decrypt = aead_givdecrypt, ++ .decrypt = aead_decrypt, + .ivsize = DES3_EDE_BLOCK_SIZE, + .maxauthsize = SHA224_DIGEST_SIZE, + }, +@@ -3630,7 +3627,7 @@ static struct caam_aead_alg driver_aeads[] = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, +- .decrypt = aead_givdecrypt, ++ .decrypt = aead_decrypt, + .ivsize = DES3_EDE_BLOCK_SIZE, + .maxauthsize = SHA256_DIGEST_SIZE, + }, +@@ -3678,7 +3675,7 @@ static struct caam_aead_alg driver_aeads[] = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, +- .decrypt = aead_givdecrypt, ++ .decrypt = aead_decrypt, + .ivsize = DES3_EDE_BLOCK_SIZE, + .maxauthsize = SHA384_DIGEST_SIZE, + }, +@@ -3726,7 +3723,7 @@ static struct caam_aead_alg driver_aeads[] = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, +- .decrypt = aead_givdecrypt, ++ .decrypt = aead_decrypt, + .ivsize = DES3_EDE_BLOCK_SIZE, + .maxauthsize = SHA512_DIGEST_SIZE, + }, +@@ -3772,7 +3769,7 @@ static struct caam_aead_alg driver_aeads[] = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, +- .decrypt = aead_givdecrypt, ++ .decrypt = aead_decrypt, + .ivsize = DES_BLOCK_SIZE, + .maxauthsize = MD5_DIGEST_SIZE, + }, +@@ -3818,7 +3815,7 @@ static struct caam_aead_alg driver_aeads[] = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, +- .decrypt = aead_givdecrypt, ++ .decrypt = aead_decrypt, + .ivsize = DES_BLOCK_SIZE, + .maxauthsize = SHA1_DIGEST_SIZE, + }, +@@ -3864,7 +3861,7 @@ static struct caam_aead_alg driver_aeads[] = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, +- .decrypt = aead_givdecrypt, ++ .decrypt = aead_decrypt, + .ivsize = DES_BLOCK_SIZE, + .maxauthsize = SHA224_DIGEST_SIZE, + }, +@@ -3910,7 +3907,7 @@ static struct caam_aead_alg driver_aeads[] = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, +- .decrypt = aead_givdecrypt, ++ .decrypt = aead_decrypt, + .ivsize = DES_BLOCK_SIZE, + .maxauthsize = SHA256_DIGEST_SIZE, + }, +@@ -3956,7 +3953,7 @@ static struct caam_aead_alg driver_aeads[] = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, +- .decrypt = aead_givdecrypt, ++ .decrypt = aead_decrypt, + .ivsize = DES_BLOCK_SIZE, + .maxauthsize = SHA384_DIGEST_SIZE, + }, +@@ -4002,7 +3999,7 @@ static struct caam_aead_alg driver_aeads[] = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, +- .decrypt = aead_givdecrypt, ++ .decrypt = aead_decrypt, + .ivsize = DES_BLOCK_SIZE, + .maxauthsize = SHA512_DIGEST_SIZE, + }, +@@ -4051,7 +4048,7 @@ static struct caam_aead_alg driver_aeads[] = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, +- .decrypt = aead_givdecrypt, ++ .decrypt = aead_decrypt, + .ivsize = CTR_RFC3686_IV_SIZE, + .maxauthsize = MD5_DIGEST_SIZE, + }, +@@ -4102,7 +4099,7 @@ static struct caam_aead_alg driver_aeads[] = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, +- .decrypt = aead_givdecrypt, ++ .decrypt = aead_decrypt, + .ivsize = CTR_RFC3686_IV_SIZE, + .maxauthsize = SHA1_DIGEST_SIZE, + }, +@@ -4153,7 +4150,7 @@ static struct caam_aead_alg driver_aeads[] = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, +- .decrypt = aead_givdecrypt, ++ .decrypt = aead_decrypt, + .ivsize = CTR_RFC3686_IV_SIZE, + .maxauthsize = SHA224_DIGEST_SIZE, + }, +@@ -4204,7 +4201,7 @@ static struct caam_aead_alg driver_aeads[] = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, +- .decrypt = aead_givdecrypt, ++ .decrypt = aead_decrypt, + .ivsize = CTR_RFC3686_IV_SIZE, + .maxauthsize = SHA256_DIGEST_SIZE, + }, +@@ -4255,7 +4252,7 @@ static struct caam_aead_alg driver_aeads[] = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, +- .decrypt = aead_givdecrypt, ++ .decrypt = aead_decrypt, + .ivsize = CTR_RFC3686_IV_SIZE, + .maxauthsize = SHA384_DIGEST_SIZE, + }, +@@ -4306,7 +4303,7 @@ static struct caam_aead_alg driver_aeads[] = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, +- .decrypt = aead_givdecrypt, ++ .decrypt = aead_decrypt, + .ivsize = CTR_RFC3686_IV_SIZE, + .maxauthsize = SHA512_DIGEST_SIZE, + }, +diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c +index 9bb99e2..79a05a3 100644 +--- a/drivers/gpu/drm/drm_atomic.c ++++ b/drivers/gpu/drm/drm_atomic.c +@@ -465,7 +465,7 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc, + val, + -1, + &replaced); +- state->color_mgmt_changed = replaced; ++ state->color_mgmt_changed |= replaced; + return ret; + } else if (property == config->ctm_property) { + ret = drm_atomic_replace_property_blob_from_id(crtc, +@@ -473,7 +473,7 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc, + val, + sizeof(struct drm_color_ctm), + &replaced); +- state->color_mgmt_changed = replaced; ++ state->color_mgmt_changed |= replaced; + return ret; + } else if (property == config->gamma_lut_property) { + ret = drm_atomic_replace_property_blob_from_id(crtc, +@@ -481,7 +481,7 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc, + val, + -1, + &replaced); +- state->color_mgmt_changed = replaced; ++ state->color_mgmt_changed |= replaced; + return ret; + } else if (crtc->funcs->atomic_set_property) + return crtc->funcs->atomic_set_property(crtc, state, property, val); +diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c +index 0e3cc66..a5cae1b 100644 +--- a/drivers/gpu/drm/drm_crtc.c ++++ b/drivers/gpu/drm/drm_crtc.c +@@ -5312,6 +5312,9 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, + struct drm_pending_vblank_event *e = NULL; + int ret = -EINVAL; + ++ if (!drm_core_check_feature(dev, DRIVER_MODESET)) ++ return -EINVAL; ++ + if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS || + page_flip->reserved != 0) + return -EINVAL; +diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c +index eb4bb8b..eb515f0 100644 +--- a/drivers/gpu/drm/msm/msm_gem_submit.c ++++ b/drivers/gpu/drm/msm/msm_gem_submit.c +@@ -62,6 +62,14 @@ void msm_gem_submit_free(struct msm_gem_submit *submit) + kfree(submit); + } + ++static inline unsigned long __must_check ++copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) ++{ ++ if (access_ok(VERIFY_READ, from, n)) ++ return __copy_from_user_inatomic(to, from, n); ++ return -EFAULT; ++} ++ + static int submit_lookup_objects(struct msm_gem_submit *submit, + struct drm_msm_gem_submit *args, struct drm_file *file) + { +@@ -69,6 +77,7 @@ static int submit_lookup_objects(struct msm_gem_submit *submit, + int ret = 0; + + spin_lock(&file->table_lock); ++ pagefault_disable(); + + for (i = 0; i < args->nr_bos; i++) { + struct drm_msm_gem_submit_bo submit_bo; +@@ -82,10 +91,15 @@ static int submit_lookup_objects(struct msm_gem_submit *submit, + */ + submit->bos[i].flags = 0; + +- ret = copy_from_user(&submit_bo, userptr, sizeof(submit_bo)); +- if (ret) { +- ret = -EFAULT; +- goto out_unlock; ++ ret = copy_from_user_inatomic(&submit_bo, userptr, sizeof(submit_bo)); ++ if (unlikely(ret)) { ++ pagefault_enable(); ++ spin_unlock(&file->table_lock); ++ ret = copy_from_user(&submit_bo, userptr, sizeof(submit_bo)); ++ if (ret) ++ goto out; ++ spin_lock(&file->table_lock); ++ pagefault_disable(); + } + + if (submit_bo.flags & ~MSM_SUBMIT_BO_FLAGS) { +@@ -125,9 +139,12 @@ static int submit_lookup_objects(struct msm_gem_submit *submit, + } + + out_unlock: +- submit->nr_bos = i; ++ pagefault_enable(); + spin_unlock(&file->table_lock); + ++out: ++ submit->nr_bos = i; ++ + return ret; + } + +diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c +index 259cd6e..17e3454 100644 +--- a/drivers/gpu/drm/radeon/atombios_crtc.c ++++ b/drivers/gpu/drm/radeon/atombios_crtc.c +@@ -627,7 +627,9 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, + if (radeon_crtc->ss.refdiv) { + radeon_crtc->pll_flags |= RADEON_PLL_USE_REF_DIV; + radeon_crtc->pll_reference_div = radeon_crtc->ss.refdiv; +- if (rdev->family >= CHIP_RV770) ++ if (ASIC_IS_AVIVO(rdev) && ++ rdev->family != CHIP_RS780 && ++ rdev->family != CHIP_RS880) + radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV; + } + } +diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c +index 590b037..0ab76dd 100644 +--- a/drivers/gpu/drm/radeon/radeon_ttm.c ++++ b/drivers/gpu/drm/radeon/radeon_ttm.c +@@ -263,8 +263,8 @@ static int radeon_move_blit(struct ttm_buffer_object *bo, + + rdev = radeon_get_rdev(bo->bdev); + ridx = radeon_copy_ring_index(rdev); +- old_start = old_mem->start << PAGE_SHIFT; +- new_start = new_mem->start << PAGE_SHIFT; ++ old_start = (u64)old_mem->start << PAGE_SHIFT; ++ new_start = (u64)new_mem->start << PAGE_SHIFT; + + switch (old_mem->mem_type) { + case TTM_PL_VRAM: +diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h +index 37cac59..2e24616 100644 +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -321,6 +321,15 @@ vc4_first_render_job(struct vc4_dev *vc4) + struct vc4_exec_info, head); + } + ++static inline struct vc4_exec_info * ++vc4_last_render_job(struct vc4_dev *vc4) ++{ ++ if (list_empty(&vc4->render_job_list)) ++ return NULL; ++ return list_last_entry(&vc4->render_job_list, ++ struct vc4_exec_info, head); ++} ++ + /** + * struct vc4_texture_sample_info - saves the offsets into the UBO for texture + * setup parameters. +diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c +index 46899d6..78ab08e 100644 +--- a/drivers/gpu/drm/vc4/vc4_gem.c ++++ b/drivers/gpu/drm/vc4/vc4_gem.c +@@ -574,8 +574,8 @@ vc4_cl_lookup_bos(struct drm_device *dev, + spin_unlock(&file_priv->table_lock); + + fail: +- kfree(handles); +- return 0; ++ drm_free_large(handles); ++ return ret; + } + + static int +diff --git a/drivers/gpu/drm/vc4/vc4_irq.c b/drivers/gpu/drm/vc4/vc4_irq.c +index b0104a34..094bc6a 100644 +--- a/drivers/gpu/drm/vc4/vc4_irq.c ++++ b/drivers/gpu/drm/vc4/vc4_irq.c +@@ -83,8 +83,10 @@ vc4_overflow_mem_work(struct work_struct *work) + + spin_lock_irqsave(&vc4->job_lock, irqflags); + current_exec = vc4_first_bin_job(vc4); ++ if (!current_exec) ++ current_exec = vc4_last_render_job(vc4); + if (current_exec) { +- vc4->overflow_mem->seqno = vc4->finished_seqno + 1; ++ vc4->overflow_mem->seqno = current_exec->seqno; + list_add_tail(&vc4->overflow_mem->unref_head, + ¤t_exec->unref_list); + vc4->overflow_mem = NULL; +diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c +index 70ed1d0..d3ef0fc 100644 +--- a/drivers/irqchip/irq-mips-gic.c ++++ b/drivers/irqchip/irq-mips-gic.c +@@ -713,9 +713,6 @@ static int gic_shared_irq_domain_map(struct irq_domain *d, unsigned int virq, + unsigned long flags; + int i; + +- irq_set_chip_and_handler(virq, &gic_level_irq_controller, +- handle_level_irq); +- + spin_lock_irqsave(&gic_lock, flags); + gic_map_to_pin(intr, gic_cpu_pin); + gic_map_to_vpe(intr, mips_cm_vp_id(vpe)); +@@ -732,6 +729,10 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq, + { + if (GIC_HWIRQ_TO_LOCAL(hw) < GIC_NUM_LOCAL_INTRS) + return gic_local_irq_domain_map(d, virq, hw); ++ ++ irq_set_chip_and_handler(virq, &gic_level_irq_controller, ++ handle_level_irq); ++ + return gic_shared_irq_domain_map(d, virq, hw, 0); + } + +@@ -771,11 +772,13 @@ static int gic_irq_domain_alloc(struct irq_domain *d, unsigned int virq, + hwirq = GIC_SHARED_TO_HWIRQ(base_hwirq + i); + + ret = irq_domain_set_hwirq_and_chip(d, virq + i, hwirq, +- &gic_edge_irq_controller, ++ &gic_level_irq_controller, + NULL); + if (ret) + goto error; + ++ irq_set_handler(virq + i, handle_level_irq); ++ + ret = gic_shared_irq_domain_map(d, virq + i, hwirq, cpu); + if (ret) + goto error; +@@ -890,10 +893,17 @@ void gic_dev_domain_free(struct irq_domain *d, unsigned int virq, + return; + } + ++static void gic_dev_domain_activate(struct irq_domain *domain, ++ struct irq_data *d) ++{ ++ gic_shared_irq_domain_map(domain, d->irq, d->hwirq, 0); ++} ++ + static struct irq_domain_ops gic_dev_domain_ops = { + .xlate = gic_dev_domain_xlate, + .alloc = gic_dev_domain_alloc, + .free = gic_dev_domain_free, ++ .activate = gic_dev_domain_activate, + }; + + static int gic_ipi_domain_xlate(struct irq_domain *d, struct device_node *ctrlr, +diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c +index f5dbb4e..5d3b231 100644 +--- a/drivers/md/bcache/super.c ++++ b/drivers/md/bcache/super.c +@@ -1818,7 +1818,7 @@ static int cache_alloc(struct cache_sb *sb, struct cache *ca) + free = roundup_pow_of_two(ca->sb.nbuckets) >> 10; + + if (!init_fifo(&ca->free[RESERVE_BTREE], 8, GFP_KERNEL) || +- !init_fifo(&ca->free[RESERVE_PRIO], prio_buckets(ca), GFP_KERNEL) || ++ !init_fifo_exact(&ca->free[RESERVE_PRIO], prio_buckets(ca), GFP_KERNEL) || + !init_fifo(&ca->free[RESERVE_MOVINGGC], free, GFP_KERNEL) || + !init_fifo(&ca->free[RESERVE_NONE], free, GFP_KERNEL) || + !init_fifo(&ca->free_inc, free << 2, GFP_KERNEL) || +diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c +index e2fb44c..dc3a854 100644 +--- a/drivers/misc/mei/hw-me.c ++++ b/drivers/misc/mei/hw-me.c +@@ -1263,8 +1263,14 @@ static bool mei_me_fw_type_nm(struct pci_dev *pdev) + static bool mei_me_fw_type_sps(struct pci_dev *pdev) + { + u32 reg; +- /* Read ME FW Status check for SPS Firmware */ +- pci_read_config_dword(pdev, PCI_CFG_HFS_1, ®); ++ unsigned int devfn; ++ ++ /* ++ * Read ME FW Status register to check for SPS Firmware ++ * The SPS FW is only signaled in pci function 0 ++ */ ++ devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0); ++ pci_bus_read_config_dword(pdev->bus, devfn, PCI_CFG_HFS_1, ®); + trace_mei_pci_cfg_read(&pdev->dev, "PCI_CFG_HFS_1", PCI_CFG_HFS_1, reg); + /* if bits [19:16] = 15, running SPS Firmware */ + return (reg & 0xf0000) == 0xf0000; +diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c +index 64e64da..71cea9b 100644 +--- a/drivers/misc/mei/pci-me.c ++++ b/drivers/misc/mei/pci-me.c +@@ -85,8 +85,8 @@ static const struct pci_device_id mei_me_pci_tbl[] = { + + {MEI_PCI_DEVICE(MEI_DEV_ID_SPT, mei_me_pch8_cfg)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_2, mei_me_pch8_cfg)}, +- {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, mei_me_pch8_cfg)}, +- {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, mei_me_pch8_cfg)}, ++ {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, mei_me_pch8_sps_cfg)}, ++ {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, mei_me_pch8_sps_cfg)}, + + {MEI_PCI_DEVICE(MEI_DEV_ID_BXT_M, mei_me_pch8_cfg)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_APL_I, mei_me_pch8_cfg)}, +diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c +index 83458f7..6dc96c8 100644 +--- a/drivers/scsi/constants.c ++++ b/drivers/scsi/constants.c +@@ -361,8 +361,9 @@ static const char * const snstext[] = { + + /* Get sense key string or NULL if not available */ + const char * +-scsi_sense_key_string(unsigned char key) { +- if (key <= 0xE) ++scsi_sense_key_string(unsigned char key) ++{ ++ if (key < ARRAY_SIZE(snstext)) + return snstext[key]; + return NULL; + } +diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c +index 0a4d54a..591e520 100644 +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -1196,6 +1196,8 @@ static int acm_probe(struct usb_interface *intf, + } + + if (!buflen) { ++ if (!intf->cur_altsetting || !intf->cur_altsetting->endpoint) ++ return -EINVAL; + if (intf->cur_altsetting->endpoint && + intf->cur_altsetting->endpoint->extralen && + intf->cur_altsetting->endpoint->extra) { +@@ -1276,6 +1278,8 @@ next_desc: + data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = call_interface_num)); + control_interface = intf; + } else { ++ if (!intf->cur_altsetting) ++ return -ENODEV; + if (intf->cur_altsetting->desc.bNumEndpoints != 3) { + dev_dbg(&intf->dev,"No union descriptor, giving up\n"); + return -ENODEV; +@@ -1305,15 +1309,22 @@ next_desc: + combined_interfaces = 1; + /* a popular other OS doesn't use it */ + quirks |= NO_CAP_LINE; ++ if (!data_interface->cur_altsetting) ++ return -EINVAL; + if (data_interface->cur_altsetting->desc.bNumEndpoints != 3) { + dev_err(&intf->dev, "This needs exactly 3 endpoints\n"); + return -EINVAL; + } + look_for_collapsed_interface: ++ if (!data_interface->cur_altsetting) ++ return -EINVAL; + for (i = 0; i < 3; i++) { + struct usb_endpoint_descriptor *ep; + ep = &data_interface->cur_altsetting->endpoint[i].desc; + ++ if (!ep) ++ return -ENODEV; ++ + if (usb_endpoint_is_int_in(ep)) + epctrl = ep; + else if (usb_endpoint_is_bulk_out(ep)) +@@ -1332,8 +1343,12 @@ look_for_collapsed_interface: + skip_normal_probe: + + /*workaround for switched interfaces */ ++ if (!data_interface->cur_altsetting) ++ return -EINVAL; + if (data_interface->cur_altsetting->desc.bInterfaceClass + != CDC_DATA_INTERFACE_TYPE) { ++ if (!control_interface->cur_altsetting) ++ return -EINVAL; + if (control_interface->cur_altsetting->desc.bInterfaceClass + == CDC_DATA_INTERFACE_TYPE) { + dev_dbg(&intf->dev, +@@ -1356,6 +1371,7 @@ skip_normal_probe: + + + if (data_interface->cur_altsetting->desc.bNumEndpoints < 2 || ++ !control_interface->cur_altsetting || + control_interface->cur_altsetting->desc.bNumEndpoints == 0) + return -EINVAL; + +@@ -1363,6 +1379,8 @@ skip_normal_probe: + epread = &data_interface->cur_altsetting->endpoint[0].desc; + epwrite = &data_interface->cur_altsetting->endpoint[1].desc; + ++ if (!epctrl || !epread || !epwrite) ++ return -ENODEV; + + /* workaround for switched endpoints */ + if (!usb_endpoint_dir_in(epread)) { +diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c +index 9d6320e..6e29d05 100644 +--- a/drivers/vhost/scsi.c ++++ b/drivers/vhost/scsi.c +@@ -88,7 +88,7 @@ struct vhost_scsi_cmd { + struct scatterlist *tvc_prot_sgl; + struct page **tvc_upages; + /* Pointer to response header iovec */ +- struct iovec *tvc_resp_iov; ++ struct iovec tvc_resp_iov; + /* Pointer to vhost_scsi for our device */ + struct vhost_scsi *tvc_vhost; + /* Pointer to vhost_virtqueue for the cmd */ +@@ -547,7 +547,7 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work) + memcpy(v_rsp.sense, cmd->tvc_sense_buf, + se_cmd->scsi_sense_length); + +- iov_iter_init(&iov_iter, READ, cmd->tvc_resp_iov, ++ iov_iter_init(&iov_iter, READ, &cmd->tvc_resp_iov, + cmd->tvc_in_iovs, sizeof(v_rsp)); + ret = copy_to_iter(&v_rsp, sizeof(v_rsp), &iov_iter); + if (likely(ret == sizeof(v_rsp))) { +@@ -1044,7 +1044,7 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) + } + cmd->tvc_vhost = vs; + cmd->tvc_vq = vq; +- cmd->tvc_resp_iov = &vq->iov[out]; ++ cmd->tvc_resp_iov = vq->iov[out]; + cmd->tvc_in_iovs = in; + + pr_debug("vhost_scsi got command opcode: %#02x, lun: %d\n", +diff --git a/drivers/xen/xenbus/xenbus_dev_frontend.c b/drivers/xen/xenbus/xenbus_dev_frontend.c +index 7487971..c1010f01 100644 +--- a/drivers/xen/xenbus/xenbus_dev_frontend.c ++++ b/drivers/xen/xenbus/xenbus_dev_frontend.c +@@ -316,7 +316,7 @@ static int xenbus_write_transaction(unsigned msg_type, + rc = -ENOMEM; + goto out; + } +- } else { ++ } else if (msg_type == XS_TRANSACTION_END) { + list_for_each_entry(trans, &u->transactions, list) + if (trans->handle.id == u->u.msg.tx_id) + break; +diff --git a/fs/block_dev.c b/fs/block_dev.c +index 71ccab1..b1495fa 100644 +--- a/fs/block_dev.c ++++ b/fs/block_dev.c +@@ -659,7 +659,7 @@ static struct dentry *bd_mount(struct file_system_type *fs_type, + { + struct dentry *dent; + dent = mount_pseudo(fs_type, "bdev:", &bdev_sops, NULL, BDEVFS_MAGIC); +- if (dent) ++ if (!IS_ERR(dent)) + dent->d_sb->s_iflags |= SB_I_CGROUPWB; + return dent; + } +diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c +index 0f9961e..f96547f 100644 +--- a/fs/crypto/policy.c ++++ b/fs/crypto/policy.c +@@ -95,10 +95,15 @@ static int create_encryption_context_from_policy(struct inode *inode, + int fscrypt_process_policy(struct inode *inode, + const struct fscrypt_policy *policy) + { ++ if (!inode_owner_or_capable(inode)) ++ return -EACCES; ++ + if (policy->version != 0) + return -EINVAL; + + if (!inode_has_encryption_context(inode)) { ++ if (!S_ISDIR(inode->i_mode)) ++ return -EINVAL; + if (!inode->i_sb->s_cop->empty_dir) + return -EOPNOTSUPP; + if (!inode->i_sb->s_cop->empty_dir(inode)) +diff --git a/fs/ext4/crypto_policy.c b/fs/ext4/crypto_policy.c +index ad05069..8a9feb3 100644 +--- a/fs/ext4/crypto_policy.c ++++ b/fs/ext4/crypto_policy.c +@@ -102,6 +102,9 @@ static int ext4_create_encryption_context_from_policy( + int ext4_process_policy(const struct ext4_encryption_policy *policy, + struct inode *inode) + { ++ if (!inode_owner_or_capable(inode)) ++ return -EACCES; ++ + if (policy->version != 0) + return -EINVAL; + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index b747ec0..ea628af 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -51,25 +51,31 @@ static __u32 ext4_inode_csum(struct inode *inode, struct ext4_inode *raw, + struct ext4_inode_info *ei) + { + struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); +- __u16 csum_lo; +- __u16 csum_hi = 0; + __u32 csum; ++ __u16 dummy_csum = 0; ++ int offset = offsetof(struct ext4_inode, i_checksum_lo); ++ unsigned int csum_size = sizeof(dummy_csum); + +- csum_lo = le16_to_cpu(raw->i_checksum_lo); +- raw->i_checksum_lo = 0; +- if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE && +- EXT4_FITS_IN_INODE(raw, ei, i_checksum_hi)) { +- csum_hi = le16_to_cpu(raw->i_checksum_hi); +- raw->i_checksum_hi = 0; +- } ++ csum = ext4_chksum(sbi, ei->i_csum_seed, (__u8 *)raw, offset); ++ csum = ext4_chksum(sbi, csum, (__u8 *)&dummy_csum, csum_size); ++ offset += csum_size; ++ csum = ext4_chksum(sbi, csum, (__u8 *)raw + offset, ++ EXT4_GOOD_OLD_INODE_SIZE - offset); + +- csum = ext4_chksum(sbi, ei->i_csum_seed, (__u8 *)raw, +- EXT4_INODE_SIZE(inode->i_sb)); +- +- raw->i_checksum_lo = cpu_to_le16(csum_lo); +- if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE && +- EXT4_FITS_IN_INODE(raw, ei, i_checksum_hi)) +- raw->i_checksum_hi = cpu_to_le16(csum_hi); ++ if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) { ++ offset = offsetof(struct ext4_inode, i_checksum_hi); ++ csum = ext4_chksum(sbi, csum, (__u8 *)raw + ++ EXT4_GOOD_OLD_INODE_SIZE, ++ offset - EXT4_GOOD_OLD_INODE_SIZE); ++ if (EXT4_FITS_IN_INODE(raw, ei, i_checksum_hi)) { ++ csum = ext4_chksum(sbi, csum, (__u8 *)&dummy_csum, ++ csum_size); ++ offset += csum_size; ++ csum = ext4_chksum(sbi, csum, (__u8 *)raw + offset, ++ EXT4_INODE_SIZE(inode->i_sb) - ++ offset); ++ } ++ } + + return csum; + } +@@ -5460,8 +5466,6 @@ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode) + sbi->s_want_extra_isize, + iloc, handle); + if (ret) { +- ext4_set_inode_state(inode, +- EXT4_STATE_NO_EXPAND); + if (mnt_count != + le16_to_cpu(sbi->s_es->s_mnt_count)) { + ext4_warning(inode->i_sb, +diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c +index ec4c399..5bb46b6 100644 +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -420,15 +420,14 @@ static __le32 ext4_dx_csum(struct inode *inode, struct ext4_dir_entry *dirent, + struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); + struct ext4_inode_info *ei = EXT4_I(inode); + __u32 csum; +- __le32 save_csum; + int size; ++ __u32 dummy_csum = 0; ++ int offset = offsetof(struct dx_tail, dt_checksum); + + size = count_offset + (count * sizeof(struct dx_entry)); +- save_csum = t->dt_checksum; +- t->dt_checksum = 0; + csum = ext4_chksum(sbi, ei->i_csum_seed, (__u8 *)dirent, size); +- csum = ext4_chksum(sbi, csum, (__u8 *)t, sizeof(struct dx_tail)); +- t->dt_checksum = save_csum; ++ csum = ext4_chksum(sbi, csum, (__u8 *)t, offset); ++ csum = ext4_chksum(sbi, csum, (__u8 *)&dummy_csum, sizeof(dummy_csum)); + + return cpu_to_le32(csum); + } +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index 639bd756..d4505f8 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -2068,23 +2068,25 @@ failed: + static __le16 ext4_group_desc_csum(struct super_block *sb, __u32 block_group, + struct ext4_group_desc *gdp) + { +- int offset; ++ int offset = offsetof(struct ext4_group_desc, bg_checksum); + __u16 crc = 0; + __le32 le_group = cpu_to_le32(block_group); + struct ext4_sb_info *sbi = EXT4_SB(sb); + + if (ext4_has_metadata_csum(sbi->s_sb)) { + /* Use new metadata_csum algorithm */ +- __le16 save_csum; + __u32 csum32; ++ __u16 dummy_csum = 0; + +- save_csum = gdp->bg_checksum; +- gdp->bg_checksum = 0; + csum32 = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&le_group, + sizeof(le_group)); +- csum32 = ext4_chksum(sbi, csum32, (__u8 *)gdp, +- sbi->s_desc_size); +- gdp->bg_checksum = save_csum; ++ csum32 = ext4_chksum(sbi, csum32, (__u8 *)gdp, offset); ++ csum32 = ext4_chksum(sbi, csum32, (__u8 *)&dummy_csum, ++ sizeof(dummy_csum)); ++ offset += sizeof(dummy_csum); ++ if (offset < sbi->s_desc_size) ++ csum32 = ext4_chksum(sbi, csum32, (__u8 *)gdp + offset, ++ sbi->s_desc_size - offset); + + crc = csum32 & 0xFFFF; + goto out; +@@ -2094,8 +2096,6 @@ static __le16 ext4_group_desc_csum(struct super_block *sb, __u32 block_group, + if (!ext4_has_feature_gdt_csum(sb)) + return 0; + +- offset = offsetof(struct ext4_group_desc, bg_checksum); +- + crc = crc16(~0, sbi->s_es->s_uuid, sizeof(sbi->s_es->s_uuid)); + crc = crc16(crc, (__u8 *)&le_group, sizeof(le_group)); + crc = crc16(crc, (__u8 *)gdp, offset); +@@ -2131,6 +2131,7 @@ void ext4_group_desc_csum_set(struct super_block *sb, __u32 block_group, + + /* Called at mount-time, super-block is locked */ + static int ext4_check_descriptors(struct super_block *sb, ++ ext4_fsblk_t sb_block, + ext4_group_t *first_not_zeroed) + { + struct ext4_sb_info *sbi = EXT4_SB(sb); +@@ -2161,6 +2162,11 @@ static int ext4_check_descriptors(struct super_block *sb, + grp = i; + + block_bitmap = ext4_block_bitmap(sb, gdp); ++ if (block_bitmap == sb_block) { ++ ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " ++ "Block bitmap for group %u overlaps " ++ "superblock", i); ++ } + if (block_bitmap < first_block || block_bitmap > last_block) { + ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " + "Block bitmap for group %u not in group " +@@ -2168,6 +2174,11 @@ static int ext4_check_descriptors(struct super_block *sb, + return 0; + } + inode_bitmap = ext4_inode_bitmap(sb, gdp); ++ if (inode_bitmap == sb_block) { ++ ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " ++ "Inode bitmap for group %u overlaps " ++ "superblock", i); ++ } + if (inode_bitmap < first_block || inode_bitmap > last_block) { + ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " + "Inode bitmap for group %u not in group " +@@ -2175,6 +2186,11 @@ static int ext4_check_descriptors(struct super_block *sb, + return 0; + } + inode_table = ext4_inode_table(sb, gdp); ++ if (inode_table == sb_block) { ++ ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " ++ "Inode table for group %u overlaps " ++ "superblock", i); ++ } + if (inode_table < first_block || + inode_table + sbi->s_itb_per_group - 1 > last_block) { + ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " +@@ -3677,7 +3693,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) + goto failed_mount2; + } + } +- if (!ext4_check_descriptors(sb, &first_not_zeroed)) { ++ if (!ext4_check_descriptors(sb, logical_sb_block, &first_not_zeroed)) { + ext4_msg(sb, KERN_ERR, "group descriptors corrupted!"); + ret = -EFSCORRUPTED; + goto failed_mount2; +diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c +index e79bd32..2eb935c 100644 +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -121,17 +121,18 @@ static __le32 ext4_xattr_block_csum(struct inode *inode, + { + struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); + __u32 csum; +- __le32 save_csum; + __le64 dsk_block_nr = cpu_to_le64(block_nr); ++ __u32 dummy_csum = 0; ++ int offset = offsetof(struct ext4_xattr_header, h_checksum); + +- save_csum = hdr->h_checksum; +- hdr->h_checksum = 0; + csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&dsk_block_nr, + sizeof(dsk_block_nr)); +- csum = ext4_chksum(sbi, csum, (__u8 *)hdr, +- EXT4_BLOCK_SIZE(inode->i_sb)); ++ csum = ext4_chksum(sbi, csum, (__u8 *)hdr, offset); ++ csum = ext4_chksum(sbi, csum, (__u8 *)&dummy_csum, sizeof(dummy_csum)); ++ offset += sizeof(dummy_csum); ++ csum = ext4_chksum(sbi, csum, (__u8 *)hdr + offset, ++ EXT4_BLOCK_SIZE(inode->i_sb) - offset); + +- hdr->h_checksum = save_csum; + return cpu_to_le32(csum); + } + +@@ -1352,15 +1353,19 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, + size_t min_offs, free; + int total_ino; + void *base, *start, *end; +- int extra_isize = 0, error = 0, tried_min_extra_isize = 0; ++ int error = 0, tried_min_extra_isize = 0; + int s_min_extra_isize = le16_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_min_extra_isize); ++ int isize_diff; /* How much do we need to grow i_extra_isize */ + + down_write(&EXT4_I(inode)->xattr_sem); ++ /* ++ * Set EXT4_STATE_NO_EXPAND to avoid recursion when marking inode dirty ++ */ ++ ext4_set_inode_state(inode, EXT4_STATE_NO_EXPAND); + retry: +- if (EXT4_I(inode)->i_extra_isize >= new_extra_isize) { +- up_write(&EXT4_I(inode)->xattr_sem); +- return 0; +- } ++ isize_diff = new_extra_isize - EXT4_I(inode)->i_extra_isize; ++ if (EXT4_I(inode)->i_extra_isize >= new_extra_isize) ++ goto out; + + header = IHDR(inode, raw_inode); + entry = IFIRST(header); +@@ -1381,7 +1386,7 @@ retry: + goto cleanup; + + free = ext4_xattr_free_space(last, &min_offs, base, &total_ino); +- if (free >= new_extra_isize) { ++ if (free >= isize_diff) { + entry = IFIRST(header); + ext4_xattr_shift_entries(entry, EXT4_I(inode)->i_extra_isize + - new_extra_isize, (void *)raw_inode + +@@ -1389,8 +1394,7 @@ retry: + (void *)header, total_ino, + inode->i_sb->s_blocksize); + EXT4_I(inode)->i_extra_isize = new_extra_isize; +- error = 0; +- goto cleanup; ++ goto out; + } + + /* +@@ -1413,7 +1417,7 @@ retry: + end = bh->b_data + bh->b_size; + min_offs = end - base; + free = ext4_xattr_free_space(first, &min_offs, base, NULL); +- if (free < new_extra_isize) { ++ if (free < isize_diff) { + if (!tried_min_extra_isize && s_min_extra_isize) { + tried_min_extra_isize++; + new_extra_isize = s_min_extra_isize; +@@ -1427,7 +1431,7 @@ retry: + free = inode->i_sb->s_blocksize; + } + +- while (new_extra_isize > 0) { ++ while (isize_diff > 0) { + size_t offs, size, entry_size; + struct ext4_xattr_entry *small_entry = NULL; + struct ext4_xattr_info i = { +@@ -1458,7 +1462,7 @@ retry: + EXT4_XATTR_SIZE(le32_to_cpu(last->e_value_size)) + + EXT4_XATTR_LEN(last->e_name_len); + if (total_size <= free && total_size < min_total_size) { +- if (total_size < new_extra_isize) { ++ if (total_size < isize_diff) { + small_entry = last; + } else { + entry = last; +@@ -1513,22 +1517,22 @@ retry: + error = ext4_xattr_ibody_set(handle, inode, &i, is); + if (error) + goto cleanup; ++ total_ino -= entry_size; + + entry = IFIRST(header); +- if (entry_size + EXT4_XATTR_SIZE(size) >= new_extra_isize) +- shift_bytes = new_extra_isize; ++ if (entry_size + EXT4_XATTR_SIZE(size) >= isize_diff) ++ shift_bytes = isize_diff; + else +- shift_bytes = entry_size + size; ++ shift_bytes = entry_size + EXT4_XATTR_SIZE(size); + /* Adjust the offsets and shift the remaining entries ahead */ +- ext4_xattr_shift_entries(entry, EXT4_I(inode)->i_extra_isize - +- shift_bytes, (void *)raw_inode + +- EXT4_GOOD_OLD_INODE_SIZE + extra_isize + shift_bytes, +- (void *)header, total_ino - entry_size, +- inode->i_sb->s_blocksize); ++ ext4_xattr_shift_entries(entry, -shift_bytes, ++ (void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE + ++ EXT4_I(inode)->i_extra_isize + shift_bytes, ++ (void *)header, total_ino, inode->i_sb->s_blocksize); + +- extra_isize += shift_bytes; +- new_extra_isize -= shift_bytes; +- EXT4_I(inode)->i_extra_isize = extra_isize; ++ isize_diff -= shift_bytes; ++ EXT4_I(inode)->i_extra_isize += shift_bytes; ++ header = IHDR(inode, raw_inode); + + i.name = b_entry_name; + i.value = buffer; +@@ -1550,6 +1554,8 @@ retry: + kfree(bs); + } + brelse(bh); ++out: ++ ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND); + up_write(&EXT4_I(inode)->xattr_sem); + return 0; + +@@ -1561,6 +1567,10 @@ cleanup: + kfree(is); + kfree(bs); + brelse(bh); ++ /* ++ * We deliberately leave EXT4_STATE_NO_EXPAND set here since inode ++ * size expansion failed. ++ */ + up_write(&EXT4_I(inode)->xattr_sem); + return error; + } +diff --git a/fs/namei.c b/fs/namei.c +index 70580ab..9281b2b 100644 +--- a/fs/namei.c ++++ b/fs/namei.c +@@ -901,6 +901,7 @@ static inline int may_follow_link(struct nameidata *nd) + { + const struct inode *inode; + const struct inode *parent; ++ kuid_t puid; + + if (!sysctl_protected_symlinks) + return 0; +@@ -916,7 +917,8 @@ static inline int may_follow_link(struct nameidata *nd) + return 0; + + /* Allowed if parent directory and link owner match. */ +- if (uid_eq(parent->i_uid, inode->i_uid)) ++ puid = parent->i_uid; ++ if (uid_valid(puid) && uid_eq(puid, inode->i_uid)) + return 0; + + if (nd->flags & LOOKUP_RCU) +diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c +index 80aa6f1..4133aa7 100644 +--- a/fs/overlayfs/copy_up.c ++++ b/fs/overlayfs/copy_up.c +@@ -80,6 +80,8 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new) + } + + for (name = buf; name < (buf + list_size); name += strlen(name) + 1) { ++ if (ovl_is_private_xattr(name)) ++ continue; + retry: + size = vfs_getxattr(old, name, value, value_size); + if (size == -ERANGE) +diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c +index d1cdc60..ac98a71 100644 +--- a/fs/overlayfs/inode.c ++++ b/fs/overlayfs/inode.c +@@ -231,7 +231,7 @@ static int ovl_readlink(struct dentry *dentry, char __user *buf, int bufsiz) + } + + +-static bool ovl_is_private_xattr(const char *name) ++bool ovl_is_private_xattr(const char *name) + { + return strncmp(name, OVL_XATTR_PRE_NAME, OVL_XATTR_PRE_LEN) == 0; + } +@@ -279,24 +279,27 @@ ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) + { + struct dentry *realdentry = ovl_dentry_real(dentry); + ssize_t res; +- int off; ++ size_t len; ++ char *s; + + res = vfs_listxattr(realdentry, list, size); + if (res <= 0 || size == 0) + return res; + + /* filter out private xattrs */ +- for (off = 0; off < res;) { +- char *s = list + off; +- size_t slen = strlen(s) + 1; ++ for (s = list, len = res; len;) { ++ size_t slen = strnlen(s, len) + 1; + +- BUG_ON(off + slen > res); ++ /* underlying fs providing us with an broken xattr list? */ ++ if (WARN_ON(slen > len)) ++ return -EIO; + ++ len -= slen; + if (ovl_is_private_xattr(s)) { + res -= slen; +- memmove(s, s + slen, res - off); ++ memmove(s, s + slen, len); + } else { +- off += slen; ++ s += slen; + } + } + +diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h +index cfbca53..d8ddc31 100644 +--- a/fs/overlayfs/overlayfs.h ++++ b/fs/overlayfs/overlayfs.h +@@ -168,6 +168,8 @@ int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list); + void ovl_cleanup_whiteouts(struct dentry *upper, struct list_head *list); + void ovl_cache_free(struct list_head *list); + int ovl_check_d_type_supported(struct path *realpath); ++void ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt, ++ struct dentry *dentry, int level); + + /* inode.c */ + int ovl_setattr(struct dentry *dentry, struct iattr *attr); +@@ -180,6 +182,7 @@ ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode, + ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size); + int ovl_removexattr(struct dentry *dentry, const char *name); + struct inode *ovl_d_select_inode(struct dentry *dentry, unsigned file_flags); ++bool ovl_is_private_xattr(const char *name); + + struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, + struct ovl_entry *oe); +diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c +index cf37fc7..f241b4e 100644 +--- a/fs/overlayfs/readdir.c ++++ b/fs/overlayfs/readdir.c +@@ -248,7 +248,7 @@ static inline int ovl_dir_read(struct path *realpath, + err = rdd->err; + } while (!err && rdd->count); + +- if (!err && rdd->first_maybe_whiteout) ++ if (!err && rdd->first_maybe_whiteout && rdd->dentry) + err = ovl_check_whiteouts(realpath->dentry, rdd); + + fput(realfile); +@@ -606,3 +606,64 @@ int ovl_check_d_type_supported(struct path *realpath) + + return rdd.d_type_supported; + } ++ ++static void ovl_workdir_cleanup_recurse(struct path *path, int level) ++{ ++ int err; ++ struct inode *dir = path->dentry->d_inode; ++ LIST_HEAD(list); ++ struct ovl_cache_entry *p; ++ struct ovl_readdir_data rdd = { ++ .ctx.actor = ovl_fill_merge, ++ .dentry = NULL, ++ .list = &list, ++ .root = RB_ROOT, ++ .is_lowest = false, ++ }; ++ ++ err = ovl_dir_read(path, &rdd); ++ if (err) ++ goto out; ++ ++ inode_lock_nested(dir, I_MUTEX_PARENT); ++ list_for_each_entry(p, &list, l_node) { ++ struct dentry *dentry; ++ ++ if (p->name[0] == '.') { ++ if (p->len == 1) ++ continue; ++ if (p->len == 2 && p->name[1] == '.') ++ continue; ++ } ++ dentry = lookup_one_len(p->name, path->dentry, p->len); ++ if (IS_ERR(dentry)) ++ continue; ++ if (dentry->d_inode) ++ ovl_workdir_cleanup(dir, path->mnt, dentry, level); ++ dput(dentry); ++ } ++ inode_unlock(dir); ++out: ++ ovl_cache_free(&list); ++} ++ ++void ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt, ++ struct dentry *dentry, int level) ++{ ++ int err; ++ ++ if (!d_is_dir(dentry) || level > 1) { ++ ovl_cleanup(dir, dentry); ++ return; ++ } ++ ++ err = ovl_do_rmdir(dir, dentry); ++ if (err) { ++ struct path path = { .mnt = mnt, .dentry = dentry }; ++ ++ inode_unlock(dir); ++ ovl_workdir_cleanup_recurse(&path, level + 1); ++ inode_lock_nested(dir, I_MUTEX_PARENT); ++ ovl_cleanup(dir, dentry); ++ } ++} +diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c +index 6db75cb..86f2025 100644 +--- a/fs/overlayfs/super.c ++++ b/fs/overlayfs/super.c +@@ -798,6 +798,10 @@ retry: + struct kstat stat = { + .mode = S_IFDIR | 0, + }; ++ struct iattr attr = { ++ .ia_valid = ATTR_MODE, ++ .ia_mode = stat.mode, ++ }; + + if (work->d_inode) { + err = -EEXIST; +@@ -805,7 +809,7 @@ retry: + goto out_dput; + + retried = true; +- ovl_cleanup(dir, work); ++ ovl_workdir_cleanup(dir, mnt, work, 0); + dput(work); + goto retry; + } +@@ -813,6 +817,21 @@ retry: + err = ovl_create_real(dir, work, &stat, NULL, NULL, true); + if (err) + goto out_dput; ++ ++ err = vfs_removexattr(work, XATTR_NAME_POSIX_ACL_DEFAULT); ++ if (err && err != -ENODATA && err != -EOPNOTSUPP) ++ goto out_dput; ++ ++ err = vfs_removexattr(work, XATTR_NAME_POSIX_ACL_ACCESS); ++ if (err && err != -ENODATA && err != -EOPNOTSUPP) ++ goto out_dput; ++ ++ /* Clear any inherited mode bits */ ++ inode_lock(work->d_inode); ++ err = notify_change(work, &attr, NULL); ++ inode_unlock(work->d_inode); ++ if (err) ++ goto out_dput; + } + out_unlock: + inode_unlock(dir); +diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c +index b45345d..51157da 100644 +--- a/fs/ubifs/tnc_commit.c ++++ b/fs/ubifs/tnc_commit.c +@@ -370,7 +370,7 @@ static int layout_in_gaps(struct ubifs_info *c, int cnt) + + p = c->gap_lebs; + do { +- ubifs_assert(p < c->gap_lebs + sizeof(int) * c->lst.idx_lebs); ++ ubifs_assert(p < c->gap_lebs + c->lst.idx_lebs); + written = layout_leb_in_gaps(c, p); + if (written < 0) { + err = written; +diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c +index b5fc279..c63710f 100644 +--- a/fs/ubifs/xattr.c ++++ b/fs/ubifs/xattr.c +@@ -575,7 +575,8 @@ static int ubifs_xattr_get(const struct xattr_handler *handler, + dbg_gen("xattr '%s', ino %lu ('%pd'), buf size %zd", name, + inode->i_ino, dentry, size); + +- return __ubifs_getxattr(inode, name, buffer, size); ++ name = xattr_full_name(handler, name); ++ return __ubifs_getxattr(inode, name, buffer, size); + } + + static int ubifs_xattr_set(const struct xattr_handler *handler, +@@ -586,6 +587,8 @@ static int ubifs_xattr_set(const struct xattr_handler *handler, + dbg_gen("xattr '%s', host ino %lu ('%pd'), size %zd", + name, inode->i_ino, dentry, size); + ++ name = xattr_full_name(handler, name); ++ + if (value) + return __ubifs_setxattr(inode, name, value, size, flags); + else +diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c +index 12ca867..85bdf3d 100644 +--- a/fs/xfs/libxfs/xfs_sb.c ++++ b/fs/xfs/libxfs/xfs_sb.c +@@ -581,7 +581,8 @@ xfs_sb_verify( + * Only check the in progress field for the primary superblock as + * mkfs.xfs doesn't clear it from secondary superblocks. + */ +- return xfs_mount_validate_sb(mp, &sb, bp->b_bn == XFS_SB_DADDR, ++ return xfs_mount_validate_sb(mp, &sb, ++ bp->b_maps[0].bm_bn == XFS_SB_DADDR, + check_version); + } + +diff --git a/include/linux/capability.h b/include/linux/capability.h +index 00690ff..5f3c63d 100644 +--- a/include/linux/capability.h ++++ b/include/linux/capability.h +@@ -206,6 +206,7 @@ extern bool has_ns_capability_noaudit(struct task_struct *t, + struct user_namespace *ns, int cap); + extern bool capable(int cap); + extern bool ns_capable(struct user_namespace *ns, int cap); ++extern bool ns_capable_noaudit(struct user_namespace *ns, int cap); + #else + static inline bool has_capability(struct task_struct *t, int cap) + { +@@ -233,6 +234,10 @@ static inline bool ns_capable(struct user_namespace *ns, int cap) + { + return true; + } ++static inline bool ns_capable_noaudit(struct user_namespace *ns, int cap) ++{ ++ return true; ++} + #endif /* CONFIG_MULTIUSER */ + extern bool capable_wrt_inode_uidgid(const struct inode *inode, int cap); + extern bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap); +diff --git a/kernel/capability.c b/kernel/capability.c +index 45432b5..00411c8 100644 +--- a/kernel/capability.c ++++ b/kernel/capability.c +@@ -361,6 +361,24 @@ bool has_capability_noaudit(struct task_struct *t, int cap) + return has_ns_capability_noaudit(t, &init_user_ns, cap); + } + ++static bool ns_capable_common(struct user_namespace *ns, int cap, bool audit) ++{ ++ int capable; ++ ++ if (unlikely(!cap_valid(cap))) { ++ pr_crit("capable() called with invalid cap=%u\n", cap); ++ BUG(); ++ } ++ ++ capable = audit ? security_capable(current_cred(), ns, cap) : ++ security_capable_noaudit(current_cred(), ns, cap); ++ if (capable == 0) { ++ current->flags |= PF_SUPERPRIV; ++ return true; ++ } ++ return false; ++} ++ + /** + * ns_capable - Determine if the current task has a superior capability in effect + * @ns: The usernamespace we want the capability in +@@ -374,19 +392,27 @@ bool has_capability_noaudit(struct task_struct *t, int cap) + */ + bool ns_capable(struct user_namespace *ns, int cap) + { +- if (unlikely(!cap_valid(cap))) { +- pr_crit("capable() called with invalid cap=%u\n", cap); +- BUG(); +- } +- +- if (security_capable(current_cred(), ns, cap) == 0) { +- current->flags |= PF_SUPERPRIV; +- return true; +- } +- return false; ++ return ns_capable_common(ns, cap, true); + } + EXPORT_SYMBOL(ns_capable); + ++/** ++ * ns_capable_noaudit - Determine if the current task has a superior capability ++ * (unaudited) in effect ++ * @ns: The usernamespace we want the capability in ++ * @cap: The capability to be tested for ++ * ++ * Return true if the current task has the given superior capability currently ++ * available for use, false if not. ++ * ++ * This sets PF_SUPERPRIV on the task if the capability is available on the ++ * assumption that it's about to be used. ++ */ ++bool ns_capable_noaudit(struct user_namespace *ns, int cap) ++{ ++ return ns_capable_common(ns, cap, false); ++} ++EXPORT_SYMBOL(ns_capable_noaudit); + + /** + * capable - Determine if the current task has a superior capability in effect +diff --git a/kernel/cred.c b/kernel/cred.c +index 0c0cd8a..5f264fb 100644 +--- a/kernel/cred.c ++++ b/kernel/cred.c +@@ -689,6 +689,8 @@ EXPORT_SYMBOL(set_security_override_from_ctx); + */ + int set_create_files_as(struct cred *new, struct inode *inode) + { ++ if (!uid_valid(inode->i_uid) || !gid_valid(inode->i_gid)) ++ return -EINVAL; + new->fsuid = inode->i_uid; + new->fsgid = inode->i_gid; + return security_kernel_create_files_as(new, inode); +diff --git a/kernel/fork.c b/kernel/fork.c +index 4a7ec0c..aea4f4d 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -1406,7 +1406,6 @@ static struct task_struct *copy_process(unsigned long clone_flags, + p->real_start_time = ktime_get_boot_ns(); + p->io_context = NULL; + p->audit_context = NULL; +- threadgroup_change_begin(current); + cgroup_fork(p); + #ifdef CONFIG_NUMA + p->mempolicy = mpol_dup(p->mempolicy); +@@ -1558,6 +1557,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, + INIT_LIST_HEAD(&p->thread_group); + p->task_works = NULL; + ++ threadgroup_change_begin(current); + /* + * Ensure that the cgroup subsystem policies allow the new process to be + * forked. It should be noted the the new process's css_set can be changed +@@ -1658,6 +1658,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, + bad_fork_cancel_cgroup: + cgroup_cancel_fork(p); + bad_fork_free_pid: ++ threadgroup_change_end(current); + if (pid != &init_struct_pid) + free_pid(pid); + bad_fork_cleanup_thread: +@@ -1690,7 +1691,6 @@ bad_fork_cleanup_policy: + mpol_put(p->mempolicy); + bad_fork_cleanup_threadgroup_lock: + #endif +- threadgroup_change_end(current); + delayacct_tsk_free(p); + bad_fork_cleanup_count: + atomic_dec(&p->cred->user->processes); +diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c +index 479d25c..b6c3945 100644 +--- a/kernel/time/timekeeping.c ++++ b/kernel/time/timekeeping.c +@@ -401,7 +401,10 @@ static __always_inline u64 __ktime_get_fast_ns(struct tk_fast *tkf) + do { + seq = raw_read_seqcount_latch(&tkf->seq); + tkr = tkf->base + (seq & 0x01); +- now = ktime_to_ns(tkr->base) + timekeeping_get_ns(tkr); ++ now = ktime_to_ns(tkr->base); ++ ++ now += clocksource_delta(tkr->read(tkr->clock), ++ tkr->cycle_last, tkr->mask); + } while (read_seqcount_retry(&tkf->seq, seq)); + + return now; +diff --git a/kernel/time/timekeeping_debug.c b/kernel/time/timekeeping_debug.c +index f6bd652..107310a 100644 +--- a/kernel/time/timekeeping_debug.c ++++ b/kernel/time/timekeeping_debug.c +@@ -23,7 +23,9 @@ + + #include "timekeeping_internal.h" + +-static unsigned int sleep_time_bin[32] = {0}; ++#define NUM_BINS 32 ++ ++static unsigned int sleep_time_bin[NUM_BINS] = {0}; + + static int tk_debug_show_sleep_time(struct seq_file *s, void *data) + { +@@ -69,6 +71,9 @@ late_initcall(tk_debug_sleep_time_init); + + void tk_debug_account_sleep_time(struct timespec64 *t) + { +- sleep_time_bin[fls(t->tv_sec)]++; ++ /* Cap bin index so we don't overflow the array */ ++ int bin = min(fls(t->tv_sec), NUM_BINS-1); ++ ++ sleep_time_bin[bin]++; + } + +diff --git a/net/sunrpc/xprtrdma/frwr_ops.c b/net/sunrpc/xprtrdma/frwr_ops.c +index c094754..f02ab80 100644 +--- a/net/sunrpc/xprtrdma/frwr_ops.c ++++ b/net/sunrpc/xprtrdma/frwr_ops.c +@@ -125,17 +125,16 @@ __frwr_reset_mr(struct rpcrdma_ia *ia, struct rpcrdma_mw *r) + } + + static void +-__frwr_reset_and_unmap(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mw *mw) ++__frwr_reset_and_unmap(struct rpcrdma_mw *mw) + { ++ struct rpcrdma_xprt *r_xprt = mw->mw_xprt; + struct rpcrdma_ia *ia = &r_xprt->rx_ia; +- struct rpcrdma_frmr *f = &mw->frmr; + int rc; + + rc = __frwr_reset_mr(ia, mw); +- ib_dma_unmap_sg(ia->ri_device, f->fr_sg, f->fr_nents, f->fr_dir); ++ ib_dma_unmap_sg(ia->ri_device, mw->mw_sg, mw->mw_nents, mw->mw_dir); + if (rc) + return; +- + rpcrdma_put_mw(r_xprt, mw); + } + +@@ -152,8 +151,7 @@ __frwr_recovery_worker(struct work_struct *work) + struct rpcrdma_mw *r = container_of(work, struct rpcrdma_mw, + mw_work); + +- __frwr_reset_and_unmap(r->mw_xprt, r); +- return; ++ __frwr_reset_and_unmap(r); + } + + /* A broken MR was discovered in a context that can't sleep. +@@ -167,8 +165,7 @@ __frwr_queue_recovery(struct rpcrdma_mw *r) + } + + static int +-__frwr_init(struct rpcrdma_mw *r, struct ib_pd *pd, struct ib_device *device, +- unsigned int depth) ++__frwr_init(struct rpcrdma_mw *r, struct ib_pd *pd, unsigned int depth) + { + struct rpcrdma_frmr *f = &r->frmr; + int rc; +@@ -177,11 +174,11 @@ __frwr_init(struct rpcrdma_mw *r, struct ib_pd *pd, struct ib_device *device, + if (IS_ERR(f->fr_mr)) + goto out_mr_err; + +- f->fr_sg = kcalloc(depth, sizeof(*f->fr_sg), GFP_KERNEL); +- if (!f->fr_sg) ++ r->mw_sg = kcalloc(depth, sizeof(*r->mw_sg), GFP_KERNEL); ++ if (!r->mw_sg) + goto out_list_err; + +- sg_init_table(f->fr_sg, depth); ++ sg_init_table(r->mw_sg, depth); + + init_completion(&f->fr_linv_done); + +@@ -210,7 +207,7 @@ __frwr_release(struct rpcrdma_mw *r) + if (rc) + dprintk("RPC: %s: ib_dereg_mr status %i\n", + __func__, rc); +- kfree(r->frmr.fr_sg); ++ kfree(r->mw_sg); + } + + static int +@@ -350,7 +347,6 @@ static int + frwr_op_init(struct rpcrdma_xprt *r_xprt) + { + struct rpcrdma_buffer *buf = &r_xprt->rx_buf; +- struct ib_device *device = r_xprt->rx_ia.ri_device; + unsigned int depth = r_xprt->rx_ia.ri_max_frmr_depth; + struct ib_pd *pd = r_xprt->rx_ia.ri_pd; + int i; +@@ -372,7 +368,7 @@ frwr_op_init(struct rpcrdma_xprt *r_xprt) + if (!r) + return -ENOMEM; + +- rc = __frwr_init(r, pd, device, depth); ++ rc = __frwr_init(r, pd, depth); + if (rc) { + kfree(r); + return rc; +@@ -386,7 +382,7 @@ frwr_op_init(struct rpcrdma_xprt *r_xprt) + return 0; + } + +-/* Post a FAST_REG Work Request to register a memory region ++/* Post a REG_MR Work Request to register a memory region + * for remote access via RDMA READ or RDMA WRITE. + */ + static int +@@ -394,8 +390,6 @@ frwr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg, + int nsegs, bool writing) + { + struct rpcrdma_ia *ia = &r_xprt->rx_ia; +- struct ib_device *device = ia->ri_device; +- enum dma_data_direction direction = rpcrdma_data_dir(writing); + struct rpcrdma_mr_seg *seg1 = seg; + struct rpcrdma_mw *mw; + struct rpcrdma_frmr *frmr; +@@ -421,15 +415,14 @@ frwr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg, + + if (nsegs > ia->ri_max_frmr_depth) + nsegs = ia->ri_max_frmr_depth; +- + for (i = 0; i < nsegs;) { + if (seg->mr_page) +- sg_set_page(&frmr->fr_sg[i], ++ sg_set_page(&mw->mw_sg[i], + seg->mr_page, + seg->mr_len, + offset_in_page(seg->mr_offset)); + else +- sg_set_buf(&frmr->fr_sg[i], seg->mr_offset, ++ sg_set_buf(&mw->mw_sg[i], seg->mr_offset, + seg->mr_len); + + ++seg; +@@ -440,26 +433,20 @@ frwr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg, + offset_in_page((seg-1)->mr_offset + (seg-1)->mr_len)) + break; + } +- frmr->fr_nents = i; +- frmr->fr_dir = direction; +- +- dma_nents = ib_dma_map_sg(device, frmr->fr_sg, frmr->fr_nents, direction); +- if (!dma_nents) { +- pr_err("RPC: %s: failed to dma map sg %p sg_nents %u\n", +- __func__, frmr->fr_sg, frmr->fr_nents); +- return -ENOMEM; +- } ++ mw->mw_nents = i; ++ mw->mw_dir = rpcrdma_data_dir(writing); + +- n = ib_map_mr_sg(mr, frmr->fr_sg, frmr->fr_nents, NULL, PAGE_SIZE); +- if (unlikely(n != frmr->fr_nents)) { +- pr_err("RPC: %s: failed to map mr %p (%u/%u)\n", +- __func__, frmr->fr_mr, n, frmr->fr_nents); +- rc = n < 0 ? n : -EINVAL; +- goto out_senderr; +- } ++ dma_nents = ib_dma_map_sg(ia->ri_device, ++ mw->mw_sg, mw->mw_nents, mw->mw_dir); ++ if (!dma_nents) ++ goto out_dmamap_err; ++ ++ n = ib_map_mr_sg(mr, mw->mw_sg, mw->mw_nents, NULL, PAGE_SIZE); ++ if (unlikely(n != mw->mw_nents)) ++ goto out_mapmr_err; + + dprintk("RPC: %s: Using frmr %p to map %u segments (%u bytes)\n", +- __func__, mw, frmr->fr_nents, mr->length); ++ __func__, mw, mw->mw_nents, mr->length); + + key = (u8)(mr->rkey & 0x000000FF); + ib_update_fast_reg_key(mr, ++key); +@@ -484,13 +471,25 @@ frwr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg, + seg1->rl_mw = mw; + seg1->mr_rkey = mr->rkey; + seg1->mr_base = mr->iova; +- seg1->mr_nsegs = frmr->fr_nents; ++ seg1->mr_nsegs = mw->mw_nents; + seg1->mr_len = mr->length; + +- return frmr->fr_nents; ++ return mw->mw_nents; ++ ++out_dmamap_err: ++ pr_err("rpcrdma: failed to dma map sg %p sg_nents %u\n", ++ mw->mw_sg, mw->mw_nents); ++ return -ENOMEM; ++ ++out_mapmr_err: ++ pr_err("rpcrdma: failed to map mr %p (%u/%u)\n", ++ frmr->fr_mr, n, mw->mw_nents); ++ rc = n < 0 ? n : -EIO; ++ __frwr_queue_recovery(mw); ++ return rc; + + out_senderr: +- dprintk("RPC: %s: ib_post_send status %i\n", __func__, rc); ++ pr_err("rpcrdma: ib_post_send status %i\n", rc); + __frwr_queue_recovery(mw); + return rc; + } +@@ -582,8 +581,8 @@ unmap: + mw = seg->rl_mw; + seg->rl_mw = NULL; + +- ib_dma_unmap_sg(ia->ri_device, f->fr_sg, f->fr_nents, +- f->fr_dir); ++ ib_dma_unmap_sg(ia->ri_device, ++ mw->mw_sg, mw->mw_nents, mw->mw_dir); + rpcrdma_put_mw(r_xprt, mw); + + i += seg->mr_nsegs; +@@ -630,7 +629,7 @@ frwr_op_unmap_safe(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req, + mw = seg->rl_mw; + + if (sync) +- __frwr_reset_and_unmap(r_xprt, mw); ++ __frwr_reset_and_unmap(mw); + else + __frwr_queue_recovery(mw); + +diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h +index 95cdc66..c53abd1 100644 +--- a/net/sunrpc/xprtrdma/xprt_rdma.h ++++ b/net/sunrpc/xprtrdma/xprt_rdma.h +@@ -221,9 +221,6 @@ enum rpcrdma_frmr_state { + }; + + struct rpcrdma_frmr { +- struct scatterlist *fr_sg; +- int fr_nents; +- enum dma_data_direction fr_dir; + struct ib_mr *fr_mr; + struct ib_cqe fr_cqe; + enum rpcrdma_frmr_state fr_state; +@@ -240,13 +237,16 @@ struct rpcrdma_fmr { + }; + + struct rpcrdma_mw { ++ struct list_head mw_list; ++ struct scatterlist *mw_sg; ++ int mw_nents; ++ enum dma_data_direction mw_dir; + union { + struct rpcrdma_fmr fmr; + struct rpcrdma_frmr frmr; + }; + struct work_struct mw_work; + struct rpcrdma_xprt *mw_xprt; +- struct list_head mw_list; + struct list_head mw_all; + }; + +diff --git a/net/sysctl_net.c b/net/sysctl_net.c +index ed98c1f..46a71c7 100644 +--- a/net/sysctl_net.c ++++ b/net/sysctl_net.c +@@ -46,7 +46,7 @@ static int net_ctl_permissions(struct ctl_table_header *head, + kgid_t root_gid = make_kgid(net->user_ns, 0); + + /* Allow network administrator to have same access as root. */ +- if (ns_capable(net->user_ns, CAP_NET_ADMIN) || ++ if (ns_capable_noaudit(net->user_ns, CAP_NET_ADMIN) || + uid_eq(root_uid, current_euid())) { + int mode = (table->mode >> 6) & 7; + return (mode << 6) | (mode << 3) | mode; +diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c +index 705c287..7347fcc 100644 +--- a/security/apparmor/policy.c ++++ b/security/apparmor/policy.c +@@ -766,7 +766,9 @@ struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name) + struct aa_profile *profile; + + rcu_read_lock(); +- profile = aa_get_profile(__find_child(&parent->base.profiles, name)); ++ do { ++ profile = __find_child(&parent->base.profiles, name); ++ } while (profile && !aa_get_profile_not0(profile)); + rcu_read_unlock(); + + /* refcount released by caller */ +diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c +index 795437b..b450a27 100644 +--- a/sound/core/rawmidi.c ++++ b/sound/core/rawmidi.c +@@ -1633,11 +1633,13 @@ static int snd_rawmidi_dev_register(struct snd_device *device) + return -EBUSY; + } + list_add_tail(&rmidi->list, &snd_rawmidi_devices); ++ mutex_unlock(®ister_mutex); + err = snd_register_device(SNDRV_DEVICE_TYPE_RAWMIDI, + rmidi->card, rmidi->device, + &snd_rawmidi_f_ops, rmidi, &rmidi->dev); + if (err < 0) { + rmidi_err(rmidi, "unable to register\n"); ++ mutex_lock(®ister_mutex); + list_del(&rmidi->list); + mutex_unlock(®ister_mutex); + return err; +@@ -1645,6 +1647,7 @@ static int snd_rawmidi_dev_register(struct snd_device *device) + if (rmidi->ops && rmidi->ops->dev_register && + (err = rmidi->ops->dev_register(rmidi)) < 0) { + snd_unregister_device(&rmidi->dev); ++ mutex_lock(®ister_mutex); + list_del(&rmidi->list); + mutex_unlock(®ister_mutex); + return err; +@@ -1677,7 +1680,6 @@ static int snd_rawmidi_dev_register(struct snd_device *device) + } + } + #endif /* CONFIG_SND_OSSEMUL */ +- mutex_unlock(®ister_mutex); + sprintf(name, "midi%d", rmidi->device); + entry = snd_info_create_card_entry(rmidi->card, name, rmidi->card->proc_root); + if (entry) { +diff --git a/sound/core/timer.c b/sound/core/timer.c +index 9a6157e..fc144f4 100644 +--- a/sound/core/timer.c ++++ b/sound/core/timer.c +@@ -35,6 +35,9 @@ + #include <sound/initval.h> + #include <linux/kmod.h> + ++/* internal flags */ ++#define SNDRV_TIMER_IFLG_PAUSED 0x00010000 ++ + #if IS_ENABLED(CONFIG_SND_HRTIMER) + #define DEFAULT_TIMER_LIMIT 4 + #else +@@ -294,8 +297,21 @@ int snd_timer_open(struct snd_timer_instance **ti, + get_device(&timer->card->card_dev); + timeri->slave_class = tid->dev_sclass; + timeri->slave_id = slave_id; +- if (list_empty(&timer->open_list_head) && timer->hw.open) +- timer->hw.open(timer); ++ ++ if (list_empty(&timer->open_list_head) && timer->hw.open) { ++ int err = timer->hw.open(timer); ++ if (err) { ++ kfree(timeri->owner); ++ kfree(timeri); ++ ++ if (timer->card) ++ put_device(&timer->card->card_dev); ++ module_put(timer->module); ++ mutex_unlock(®ister_mutex); ++ return err; ++ } ++ } ++ + list_add_tail(&timeri->open_list, &timer->open_list_head); + snd_timer_check_master(timeri); + mutex_unlock(®ister_mutex); +@@ -526,6 +542,10 @@ static int snd_timer_stop1(struct snd_timer_instance *timeri, bool stop) + } + } + timeri->flags &= ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START); ++ if (stop) ++ timeri->flags &= ~SNDRV_TIMER_IFLG_PAUSED; ++ else ++ timeri->flags |= SNDRV_TIMER_IFLG_PAUSED; + snd_timer_notify1(timeri, stop ? SNDRV_TIMER_EVENT_STOP : + SNDRV_TIMER_EVENT_CONTINUE); + unlock: +@@ -587,6 +607,10 @@ int snd_timer_stop(struct snd_timer_instance *timeri) + */ + int snd_timer_continue(struct snd_timer_instance *timeri) + { ++ /* timer can continue only after pause */ ++ if (!(timeri->flags & SNDRV_TIMER_IFLG_PAUSED)) ++ return -EINVAL; ++ + if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) + return snd_timer_start_slave(timeri, false); + else +@@ -813,6 +837,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, + timer->tmr_subdevice = tid->subdevice; + if (id) + strlcpy(timer->id, id, sizeof(timer->id)); ++ timer->sticks = 1; + INIT_LIST_HEAD(&timer->device_list); + INIT_LIST_HEAD(&timer->open_list_head); + INIT_LIST_HEAD(&timer->active_list_head); +@@ -1817,6 +1842,9 @@ static int snd_timer_user_continue(struct file *file) + tu = file->private_data; + if (!tu->timeri) + return -EBADFD; ++ /* start timer instead of continue if it's not used before */ ++ if (!(tu->timeri->flags & SNDRV_TIMER_IFLG_PAUSED)) ++ return snd_timer_user_start(file); + tu->timeri->lost = 0; + return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0; + } +@@ -1958,6 +1986,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, + tu->qused--; + spin_unlock_irq(&tu->qlock); + ++ mutex_lock(&tu->ioctl_lock); + if (tu->tread) { + if (copy_to_user(buffer, &tu->tqueue[qhead], + sizeof(struct snd_timer_tread))) +@@ -1967,6 +1996,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, + sizeof(struct snd_timer_read))) + err = -EFAULT; + } ++ mutex_unlock(&tu->ioctl_lock); + + spin_lock_irq(&tu->qlock); + if (err < 0) +diff --git a/sound/firewire/fireworks/fireworks.h b/sound/firewire/fireworks/fireworks.h +index 03ed352..d73c12b 100644 +--- a/sound/firewire/fireworks/fireworks.h ++++ b/sound/firewire/fireworks/fireworks.h +@@ -108,7 +108,6 @@ struct snd_efw { + u8 *resp_buf; + u8 *pull_ptr; + u8 *push_ptr; +- unsigned int resp_queues; + }; + + int snd_efw_transaction_cmd(struct fw_unit *unit, +diff --git a/sound/firewire/fireworks/fireworks_hwdep.c b/sound/firewire/fireworks/fireworks_hwdep.c +index 33df865..2e1d9a2 100644 +--- a/sound/firewire/fireworks/fireworks_hwdep.c ++++ b/sound/firewire/fireworks/fireworks_hwdep.c +@@ -25,6 +25,7 @@ hwdep_read_resp_buf(struct snd_efw *efw, char __user *buf, long remained, + { + unsigned int length, till_end, type; + struct snd_efw_transaction *t; ++ u8 *pull_ptr; + long count = 0; + + if (remained < sizeof(type) + sizeof(struct snd_efw_transaction)) +@@ -38,8 +39,17 @@ hwdep_read_resp_buf(struct snd_efw *efw, char __user *buf, long remained, + buf += sizeof(type); + + /* write into buffer as many responses as possible */ +- while (efw->resp_queues > 0) { +- t = (struct snd_efw_transaction *)(efw->pull_ptr); ++ spin_lock_irq(&efw->lock); ++ ++ /* ++ * When another task reaches here during this task's access to user ++ * space, it picks up current position in buffer and can read the same ++ * series of responses. ++ */ ++ pull_ptr = efw->pull_ptr; ++ ++ while (efw->push_ptr != pull_ptr) { ++ t = (struct snd_efw_transaction *)(pull_ptr); + length = be32_to_cpu(t->length) * sizeof(__be32); + + /* confirm enough space for this response */ +@@ -49,26 +59,39 @@ hwdep_read_resp_buf(struct snd_efw *efw, char __user *buf, long remained, + /* copy from ring buffer to user buffer */ + while (length > 0) { + till_end = snd_efw_resp_buf_size - +- (unsigned int)(efw->pull_ptr - efw->resp_buf); ++ (unsigned int)(pull_ptr - efw->resp_buf); + till_end = min_t(unsigned int, length, till_end); + +- if (copy_to_user(buf, efw->pull_ptr, till_end)) ++ spin_unlock_irq(&efw->lock); ++ ++ if (copy_to_user(buf, pull_ptr, till_end)) + return -EFAULT; + +- efw->pull_ptr += till_end; +- if (efw->pull_ptr >= efw->resp_buf + +- snd_efw_resp_buf_size) +- efw->pull_ptr -= snd_efw_resp_buf_size; ++ spin_lock_irq(&efw->lock); ++ ++ pull_ptr += till_end; ++ if (pull_ptr >= efw->resp_buf + snd_efw_resp_buf_size) ++ pull_ptr -= snd_efw_resp_buf_size; + + length -= till_end; + buf += till_end; + count += till_end; + remained -= till_end; + } +- +- efw->resp_queues--; + } + ++ /* ++ * All of tasks can read from the buffer nearly simultaneously, but the ++ * last position for each task is different depending on the length of ++ * given buffer. Here, for simplicity, a position of buffer is set by ++ * the latest task. It's better for a listening application to allow one ++ * thread to read from the buffer. Unless, each task can read different ++ * sequence of responses depending on variation of buffer length. ++ */ ++ efw->pull_ptr = pull_ptr; ++ ++ spin_unlock_irq(&efw->lock); ++ + return count; + } + +@@ -76,14 +99,17 @@ static long + hwdep_read_locked(struct snd_efw *efw, char __user *buf, long count, + loff_t *offset) + { +- union snd_firewire_event event; ++ union snd_firewire_event event = { ++ .lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS, ++ }; + +- memset(&event, 0, sizeof(event)); ++ spin_lock_irq(&efw->lock); + +- event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS; + event.lock_status.status = (efw->dev_lock_count > 0); + efw->dev_lock_changed = false; + ++ spin_unlock_irq(&efw->lock); ++ + count = min_t(long, count, sizeof(event.lock_status)); + + if (copy_to_user(buf, &event, count)) +@@ -98,10 +124,15 @@ hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count, + { + struct snd_efw *efw = hwdep->private_data; + DEFINE_WAIT(wait); ++ bool dev_lock_changed; ++ bool queued; + + spin_lock_irq(&efw->lock); + +- while ((!efw->dev_lock_changed) && (efw->resp_queues == 0)) { ++ dev_lock_changed = efw->dev_lock_changed; ++ queued = efw->push_ptr != efw->pull_ptr; ++ ++ while (!dev_lock_changed && !queued) { + prepare_to_wait(&efw->hwdep_wait, &wait, TASK_INTERRUPTIBLE); + spin_unlock_irq(&efw->lock); + schedule(); +@@ -109,15 +140,17 @@ hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count, + if (signal_pending(current)) + return -ERESTARTSYS; + spin_lock_irq(&efw->lock); ++ dev_lock_changed = efw->dev_lock_changed; ++ queued = efw->push_ptr != efw->pull_ptr; + } + +- if (efw->dev_lock_changed) ++ spin_unlock_irq(&efw->lock); ++ ++ if (dev_lock_changed) + count = hwdep_read_locked(efw, buf, count, offset); +- else if (efw->resp_queues > 0) ++ else if (queued) + count = hwdep_read_resp_buf(efw, buf, count, offset); + +- spin_unlock_irq(&efw->lock); +- + return count; + } + +@@ -160,7 +193,7 @@ hwdep_poll(struct snd_hwdep *hwdep, struct file *file, poll_table *wait) + poll_wait(file, &efw->hwdep_wait, wait); + + spin_lock_irq(&efw->lock); +- if (efw->dev_lock_changed || (efw->resp_queues > 0)) ++ if (efw->dev_lock_changed || efw->pull_ptr != efw->push_ptr) + events = POLLIN | POLLRDNORM; + else + events = 0; +diff --git a/sound/firewire/fireworks/fireworks_proc.c b/sound/firewire/fireworks/fireworks_proc.c +index 0639dcb..beb0a0f 100644 +--- a/sound/firewire/fireworks/fireworks_proc.c ++++ b/sound/firewire/fireworks/fireworks_proc.c +@@ -188,8 +188,8 @@ proc_read_queues_state(struct snd_info_entry *entry, + else + consumed = (unsigned int)(efw->push_ptr - efw->pull_ptr); + +- snd_iprintf(buffer, "%d %d/%d\n", +- efw->resp_queues, consumed, snd_efw_resp_buf_size); ++ snd_iprintf(buffer, "%d/%d\n", ++ consumed, snd_efw_resp_buf_size); + } + + static void +diff --git a/sound/firewire/fireworks/fireworks_transaction.c b/sound/firewire/fireworks/fireworks_transaction.c +index f550808..36a08ba 100644 +--- a/sound/firewire/fireworks/fireworks_transaction.c ++++ b/sound/firewire/fireworks/fireworks_transaction.c +@@ -121,11 +121,11 @@ copy_resp_to_buf(struct snd_efw *efw, void *data, size_t length, int *rcode) + size_t capacity, till_end; + struct snd_efw_transaction *t; + +- spin_lock_irq(&efw->lock); +- + t = (struct snd_efw_transaction *)data; + length = min_t(size_t, be32_to_cpu(t->length) * sizeof(u32), length); + ++ spin_lock_irq(&efw->lock); ++ + if (efw->push_ptr < efw->pull_ptr) + capacity = (unsigned int)(efw->pull_ptr - efw->push_ptr); + else +@@ -155,7 +155,6 @@ copy_resp_to_buf(struct snd_efw *efw, void *data, size_t length, int *rcode) + } + + /* for hwdep */ +- efw->resp_queues++; + wake_up(&efw->hwdep_wait); + + *rcode = RCODE_COMPLETE; +diff --git a/sound/firewire/tascam/tascam-hwdep.c b/sound/firewire/tascam/tascam-hwdep.c +index 131267c..106406c 100644 +--- a/sound/firewire/tascam/tascam-hwdep.c ++++ b/sound/firewire/tascam/tascam-hwdep.c +@@ -16,31 +16,14 @@ + + #include "tascam.h" + +-static long hwdep_read_locked(struct snd_tscm *tscm, char __user *buf, +- long count) +-{ +- union snd_firewire_event event; +- +- memset(&event, 0, sizeof(event)); +- +- event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS; +- event.lock_status.status = (tscm->dev_lock_count > 0); +- tscm->dev_lock_changed = false; +- +- count = min_t(long, count, sizeof(event.lock_status)); +- +- if (copy_to_user(buf, &event, count)) +- return -EFAULT; +- +- return count; +-} +- + static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count, + loff_t *offset) + { + struct snd_tscm *tscm = hwdep->private_data; + DEFINE_WAIT(wait); +- union snd_firewire_event event; ++ union snd_firewire_event event = { ++ .lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS, ++ }; + + spin_lock_irq(&tscm->lock); + +@@ -54,10 +37,16 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count, + spin_lock_irq(&tscm->lock); + } + +- memset(&event, 0, sizeof(event)); +- count = hwdep_read_locked(tscm, buf, count); ++ event.lock_status.status = (tscm->dev_lock_count > 0); ++ tscm->dev_lock_changed = false; ++ + spin_unlock_irq(&tscm->lock); + ++ count = min_t(long, count, sizeof(event.lock_status)); ++ ++ if (copy_to_user(buf, &event, count)) ++ return -EFAULT; ++ + return count; + } + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index f25479b..eaee626 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -4840,6 +4840,7 @@ enum { + ALC221_FIXUP_HP_FRONT_MIC, + ALC292_FIXUP_TPT460, + ALC298_FIXUP_SPK_VOLUME, ++ ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER, + }; + + static const struct hda_fixup alc269_fixups[] = { +@@ -5501,6 +5502,15 @@ static const struct hda_fixup alc269_fixups[] = { + .chained = true, + .chain_id = ALC298_FIXUP_DELL1_MIC_NO_PRESENCE, + }, ++ [ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ { 0x1b, 0x90170151 }, ++ { } ++ }, ++ .chained = true, ++ .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE ++ }, + }; + + static const struct snd_pci_quirk alc269_fixup_tbl[] = { +@@ -5545,6 +5555,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1028, 0x06df, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK), + SND_PCI_QUIRK(0x1028, 0x06e0, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK), + SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13 9350", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE), ++ SND_PCI_QUIRK(0x1028, 0x0706, "Dell Inspiron 7559", ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER), + SND_PCI_QUIRK(0x1028, 0x0725, "Dell Inspiron 3162", ALC255_FIXUP_DELL_SPK_NOISE), + SND_PCI_QUIRK(0x1028, 0x075b, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE), + SND_PCI_QUIRK(0x1028, 0x075d, "Dell AIO", ALC298_FIXUP_SPK_VOLUME), +@@ -5879,6 +5890,10 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { + {0x12, 0x90a60170}, + {0x14, 0x90170120}, + {0x21, 0x02211030}), ++ SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell Inspiron 5468", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, ++ {0x12, 0x90a60180}, ++ {0x14, 0x90170120}, ++ {0x21, 0x02211030}), + SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, + ALC256_STANDARD_PINS), + SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC280_FIXUP_HP_GPIO4, +diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c +index 1267e1a..633d54ca 100644 +--- a/sound/soc/atmel/atmel_ssc_dai.c ++++ b/sound/soc/atmel/atmel_ssc_dai.c +@@ -299,8 +299,9 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream, + clk_enable(ssc_p->ssc->clk); + ssc_p->mck_rate = clk_get_rate(ssc_p->ssc->clk); + +- /* Reset the SSC to keep it at a clean status */ +- ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST)); ++ /* Reset the SSC unless initialized to keep it in a clean state */ ++ if (!ssc_p->initialized) ++ ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST)); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + dir = 0; +diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index 6cf1f35..152292e 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -1141,6 +1141,7 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip) + case USB_ID(0x0556, 0x0014): /* Phoenix Audio TMX320VC */ + case USB_ID(0x05A3, 0x9420): /* ELP HD USB Camera */ + case USB_ID(0x074D, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */ ++ case USB_ID(0x1901, 0x0191): /* GE B850V3 CP2114 audio interface */ + case USB_ID(0x1de7, 0x0013): /* Phoenix Audio MT202exe */ + case USB_ID(0x1de7, 0x0014): /* Phoenix Audio TMX320 */ + case USB_ID(0x1de7, 0x0114): /* Phoenix Audio MT202pcs */ |