From: Greg Kroah-Hartman Date: Thu, 29 Nov 2018 12:49:23 +0000 (+0100) Subject: 4.19-stable patches X-Git-Tag: v4.19.6~15 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7a40797b9b566941ce11cd032d0ee28e17120c8b;p=thirdparty%2Fkernel%2Fstable-queue.git 4.19-stable patches added patches: gfs2-fix-iomap-buffer-head-reference-counting-bug.patch media-ov5640-fix-auto-controls-values-when-switching-to-manual-mode.patch media-ov5640-fix-auto-gain-exposure-when-changing-mode.patch media-ov5640-fix-exposure-regression.patch media-ov5640-fix-timings-setup-code.patch media-ov5640-fix-wrong-binning-value-in-exposure-calculation.patch media-ov5640-re-work-mipi-startup-sequence.patch rcu-make-need_resched-respond-to-urgent-rcu-qs-needs.patch --- diff --git a/queue-4.19/gfs2-fix-iomap-buffer-head-reference-counting-bug.patch b/queue-4.19/gfs2-fix-iomap-buffer-head-reference-counting-bug.patch new file mode 100644 index 00000000000..5fd93b869ba --- /dev/null +++ b/queue-4.19/gfs2-fix-iomap-buffer-head-reference-counting-bug.patch @@ -0,0 +1,158 @@ +From c26b5aa8ef0d46035060fded475e6ab957b9f69f Mon Sep 17 00:00:00 2001 +From: Andreas Gruenbacher +Date: Sun, 11 Nov 2018 11:15:21 +0000 +Subject: gfs2: Fix iomap buffer head reference counting bug + +From: Andreas Gruenbacher + +commit c26b5aa8ef0d46035060fded475e6ab957b9f69f upstream. + +GFS2 passes the inode buffer head (dibh) from gfs2_iomap_begin to +gfs2_iomap_end in iomap->private. It sets that private pointer in +gfs2_iomap_get. Users of gfs2_iomap_get other than gfs2_iomap_begin +would have to release iomap->private, but this isn't done correctly, +leading to a leak of buffer head references. + +To fix this, move the code for setting iomap->private from +gfs2_iomap_get to gfs2_iomap_begin. + +Fixes: 64bc06bb32 ("gfs2: iomap buffered write support") +Cc: stable@vger.kernel.org # v4.19+ +Signed-off-by: Andreas Gruenbacher +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + + +--- + fs/gfs2/bmap.c | 40 +++++++++++++++++----------------------- + 1 file changed, 17 insertions(+), 23 deletions(-) + +--- a/fs/gfs2/bmap.c ++++ b/fs/gfs2/bmap.c +@@ -826,7 +826,7 @@ static int gfs2_iomap_get(struct inode * + ret = gfs2_meta_inode_buffer(ip, &dibh); + if (ret) + goto unlock; +- iomap->private = dibh; ++ mp->mp_bh[0] = dibh; + + if (gfs2_is_stuffed(ip)) { + if (flags & IOMAP_WRITE) { +@@ -863,9 +863,6 @@ unstuff: + len = lblock_stop - lblock + 1; + iomap->length = len << inode->i_blkbits; + +- get_bh(dibh); +- mp->mp_bh[0] = dibh; +- + height = ip->i_height; + while ((lblock + 1) * sdp->sd_sb.sb_bsize > sdp->sd_heightsize[height]) + height++; +@@ -898,8 +895,6 @@ out: + iomap->bdev = inode->i_sb->s_bdev; + unlock: + up_read(&ip->i_rw_mutex); +- if (ret && dibh) +- brelse(dibh); + return ret; + + do_alloc: +@@ -980,9 +975,9 @@ static void gfs2_iomap_journaled_page_do + + static int gfs2_iomap_begin_write(struct inode *inode, loff_t pos, + loff_t length, unsigned flags, +- struct iomap *iomap) ++ struct iomap *iomap, ++ struct metapath *mp) + { +- struct metapath mp = { .mp_aheight = 1, }; + struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_sbd *sdp = GFS2_SB(inode); + unsigned int data_blocks = 0, ind_blocks = 0, rblocks; +@@ -996,9 +991,9 @@ static int gfs2_iomap_begin_write(struct + unstuff = gfs2_is_stuffed(ip) && + pos + length > gfs2_max_stuffed_size(ip); + +- ret = gfs2_iomap_get(inode, pos, length, flags, iomap, &mp); ++ ret = gfs2_iomap_get(inode, pos, length, flags, iomap, mp); + if (ret) +- goto out_release; ++ goto out_unlock; + + alloc_required = unstuff || iomap->type == IOMAP_HOLE; + +@@ -1013,7 +1008,7 @@ static int gfs2_iomap_begin_write(struct + + ret = gfs2_quota_lock_check(ip, &ap); + if (ret) +- goto out_release; ++ goto out_unlock; + + ret = gfs2_inplace_reserve(ip, &ap); + if (ret) +@@ -1038,17 +1033,15 @@ static int gfs2_iomap_begin_write(struct + ret = gfs2_unstuff_dinode(ip, NULL); + if (ret) + goto out_trans_end; +- release_metapath(&mp); +- brelse(iomap->private); +- iomap->private = NULL; ++ release_metapath(mp); + ret = gfs2_iomap_get(inode, iomap->offset, iomap->length, +- flags, iomap, &mp); ++ flags, iomap, mp); + if (ret) + goto out_trans_end; + } + + if (iomap->type == IOMAP_HOLE) { +- ret = gfs2_iomap_alloc(inode, iomap, flags, &mp); ++ ret = gfs2_iomap_alloc(inode, iomap, flags, mp); + if (ret) { + gfs2_trans_end(sdp); + gfs2_inplace_release(ip); +@@ -1056,7 +1049,6 @@ static int gfs2_iomap_begin_write(struct + goto out_qunlock; + } + } +- release_metapath(&mp); + if (!gfs2_is_stuffed(ip) && gfs2_is_jdata(ip)) + iomap->page_done = gfs2_iomap_journaled_page_done; + return 0; +@@ -1069,10 +1061,7 @@ out_trans_fail: + out_qunlock: + if (alloc_required) + gfs2_quota_unlock(ip); +-out_release: +- if (iomap->private) +- brelse(iomap->private); +- release_metapath(&mp); ++out_unlock: + gfs2_write_unlock(inode); + return ret; + } +@@ -1088,10 +1077,10 @@ static int gfs2_iomap_begin(struct inode + + trace_gfs2_iomap_start(ip, pos, length, flags); + if ((flags & IOMAP_WRITE) && !(flags & IOMAP_DIRECT)) { +- ret = gfs2_iomap_begin_write(inode, pos, length, flags, iomap); ++ ret = gfs2_iomap_begin_write(inode, pos, length, flags, iomap, &mp); + } else { + ret = gfs2_iomap_get(inode, pos, length, flags, iomap, &mp); +- release_metapath(&mp); ++ + /* + * Silently fall back to buffered I/O for stuffed files or if + * we've hot a hole (see gfs2_file_direct_write). +@@ -1100,6 +1089,11 @@ static int gfs2_iomap_begin(struct inode + iomap->type != IOMAP_MAPPED) + ret = -ENOTBLK; + } ++ if (!ret) { ++ get_bh(mp.mp_bh[0]); ++ iomap->private = mp.mp_bh[0]; ++ } ++ release_metapath(&mp); + trace_gfs2_iomap_end(ip, iomap, ret); + return ret; + } diff --git a/queue-4.19/media-ov5640-fix-auto-controls-values-when-switching-to-manual-mode.patch b/queue-4.19/media-ov5640-fix-auto-controls-values-when-switching-to-manual-mode.patch new file mode 100644 index 00000000000..3c878c6da35 --- /dev/null +++ b/queue-4.19/media-ov5640-fix-auto-controls-values-when-switching-to-manual-mode.patch @@ -0,0 +1,43 @@ +From a8f438c684eaa4cbe6c98828eb996d5ec53e24fb Mon Sep 17 00:00:00 2001 +From: Hugues Fruchet +Date: Tue, 11 Sep 2018 09:48:20 -0400 +Subject: media: ov5640: fix auto controls values when switching to manual mode + +From: Hugues Fruchet + +commit a8f438c684eaa4cbe6c98828eb996d5ec53e24fb upstream. + +When switching from auto to manual mode, V4L2 core is calling +g_volatile_ctrl() in manual mode in order to get the manual initial value. +Remove the manual mode check/return to not break this behaviour. + +Signed-off-by: Hugues Fruchet +Tested-by: Jacopo Mondi +Signed-off-by: Sakari Ailus +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Adam Ford +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/i2c/ov5640.c | 4 ---- + 1 file changed, 4 deletions(-) + +--- a/drivers/media/i2c/ov5640.c ++++ b/drivers/media/i2c/ov5640.c +@@ -2337,16 +2337,12 @@ static int ov5640_g_volatile_ctrl(struct + + switch (ctrl->id) { + case V4L2_CID_AUTOGAIN: +- if (!ctrl->val) +- return 0; + val = ov5640_get_gain(sensor); + if (val < 0) + return val; + sensor->ctrls.gain->val = val; + break; + case V4L2_CID_EXPOSURE_AUTO: +- if (ctrl->val == V4L2_EXPOSURE_MANUAL) +- return 0; + val = ov5640_get_exposure(sensor); + if (val < 0) + return val; diff --git a/queue-4.19/media-ov5640-fix-auto-gain-exposure-when-changing-mode.patch b/queue-4.19/media-ov5640-fix-auto-gain-exposure-when-changing-mode.patch new file mode 100644 index 00000000000..1c7be1c35c6 --- /dev/null +++ b/queue-4.19/media-ov5640-fix-auto-gain-exposure-when-changing-mode.patch @@ -0,0 +1,223 @@ +From 3cca8ef5f774cbd61c8db05d9aa401de9bb59c66 Mon Sep 17 00:00:00 2001 +From: Hugues Fruchet +Date: Tue, 11 Sep 2018 09:48:18 -0400 +Subject: media: ov5640: fix auto gain & exposure when changing mode + +From: Hugues Fruchet + +commit 3cca8ef5f774cbd61c8db05d9aa401de9bb59c66 upstream. + +Ensure that auto gain and auto exposure are well restored +when changing mode. + +Signed-off-by: Hugues Fruchet +Reviewed-by: Jacopo Mondi +Tested-by: Jacopo Mondi +Signed-off-by: Sakari Ailus +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Adam Ford +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/i2c/ov5640.c | 96 +++++++++++++++++++++++++-------------------- + 1 file changed, 54 insertions(+), 42 deletions(-) + +--- a/drivers/media/i2c/ov5640.c ++++ b/drivers/media/i2c/ov5640.c +@@ -1022,6 +1022,18 @@ static int ov5640_get_gain(struct ov5640 + return gain & 0x3ff; + } + ++static int ov5640_set_gain(struct ov5640_dev *sensor, int gain) ++{ ++ return ov5640_write_reg16(sensor, OV5640_REG_AEC_PK_REAL_GAIN, ++ (u16)gain & 0x3ff); ++} ++ ++static int ov5640_set_autogain(struct ov5640_dev *sensor, bool on) ++{ ++ return ov5640_mod_reg(sensor, OV5640_REG_AEC_PK_MANUAL, ++ BIT(1), on ? 0 : BIT(1)); ++} ++ + static int ov5640_set_stream_dvp(struct ov5640_dev *sensor, bool on) + { + int ret; +@@ -1588,7 +1600,7 @@ static int ov5640_set_mode_exposure_calc + } + + /* set capture gain */ +- ret = __v4l2_ctrl_s_ctrl(sensor->ctrls.gain, cap_gain16); ++ ret = ov5640_set_gain(sensor, cap_gain16); + if (ret) + return ret; + +@@ -1601,7 +1613,7 @@ static int ov5640_set_mode_exposure_calc + } + + /* set exposure */ +- return __v4l2_ctrl_s_ctrl(sensor->ctrls.exposure, cap_shutter); ++ return ov5640_set_exposure(sensor, cap_shutter); + } + + /* +@@ -1609,26 +1621,13 @@ static int ov5640_set_mode_exposure_calc + * change mode directly + */ + static int ov5640_set_mode_direct(struct ov5640_dev *sensor, +- const struct ov5640_mode_info *mode, +- bool auto_exp) ++ const struct ov5640_mode_info *mode) + { +- int ret; +- + if (!mode->reg_data) + return -EINVAL; + + /* Write capture setting */ +- ret = ov5640_load_regs(sensor, mode); +- if (ret < 0) +- return ret; +- +- /* turn auto gain/exposure back on for direct mode */ +- ret = __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_gain, 1); +- if (ret) +- return ret; +- +- return __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_exp, auto_exp ? +- V4L2_EXPOSURE_AUTO : V4L2_EXPOSURE_MANUAL); ++ return ov5640_load_regs(sensor, mode); + } + + static int ov5640_set_mode(struct ov5640_dev *sensor) +@@ -1636,6 +1635,7 @@ static int ov5640_set_mode(struct ov5640 + const struct ov5640_mode_info *mode = sensor->current_mode; + const struct ov5640_mode_info *orig_mode = sensor->last_mode; + enum ov5640_downsize_mode dn_mode, orig_dn_mode; ++ bool auto_gain = sensor->ctrls.auto_gain->val == 1; + bool auto_exp = sensor->ctrls.auto_exp->val == V4L2_EXPOSURE_AUTO; + int ret; + +@@ -1643,19 +1643,23 @@ static int ov5640_set_mode(struct ov5640 + orig_dn_mode = orig_mode->dn_mode; + + /* auto gain and exposure must be turned off when changing modes */ +- ret = __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_gain, 0); +- if (ret) +- return ret; ++ if (auto_gain) { ++ ret = ov5640_set_autogain(sensor, false); ++ if (ret) ++ return ret; ++ } + +- ret = ov5640_set_autoexposure(sensor, false); +- if (ret) +- return ret; ++ if (auto_exp) { ++ ret = ov5640_set_autoexposure(sensor, false); ++ if (ret) ++ goto restore_auto_gain; ++ } + + if ((dn_mode == SUBSAMPLING && orig_dn_mode == SCALING) || + (dn_mode == SCALING && orig_dn_mode == SUBSAMPLING)) { + /* + * change between subsampling and scaling +- * go through exposure calucation ++ * go through exposure calculation + */ + ret = ov5640_set_mode_exposure_calc(sensor, mode); + } else { +@@ -1663,11 +1667,16 @@ static int ov5640_set_mode(struct ov5640 + * change inside subsampling or scaling + * download firmware directly + */ +- ret = ov5640_set_mode_direct(sensor, mode, auto_exp); ++ ret = ov5640_set_mode_direct(sensor, mode); + } +- + if (ret < 0) +- return ret; ++ goto restore_auto_exp_gain; ++ ++ /* restore auto gain and exposure */ ++ if (auto_gain) ++ ov5640_set_autogain(sensor, true); ++ if (auto_exp) ++ ov5640_set_autoexposure(sensor, true); + + ret = ov5640_set_binning(sensor, dn_mode != SCALING); + if (ret < 0) +@@ -1689,6 +1698,15 @@ static int ov5640_set_mode(struct ov5640 + sensor->last_mode = mode; + + return 0; ++ ++restore_auto_exp_gain: ++ if (auto_exp) ++ ov5640_set_autoexposure(sensor, true); ++restore_auto_gain: ++ if (auto_gain) ++ ov5640_set_autogain(sensor, true); ++ ++ return ret; + } + + static int ov5640_set_framefmt(struct ov5640_dev *sensor, +@@ -2201,20 +2219,20 @@ static int ov5640_set_ctrl_white_balance + return ret; + } + +-static int ov5640_set_ctrl_exposure(struct ov5640_dev *sensor, int exp) ++static int ov5640_set_ctrl_exposure(struct ov5640_dev *sensor, ++ enum v4l2_exposure_auto_type auto_exposure) + { + struct ov5640_ctrls *ctrls = &sensor->ctrls; +- bool auto_exposure = (exp == V4L2_EXPOSURE_AUTO); ++ bool auto_exp = (auto_exposure == V4L2_EXPOSURE_AUTO); + int ret = 0; + + if (ctrls->auto_exp->is_new) { +- ret = ov5640_mod_reg(sensor, OV5640_REG_AEC_PK_MANUAL, +- BIT(0), auto_exposure ? 0 : BIT(0)); ++ ret = ov5640_set_autoexposure(sensor, auto_exp); + if (ret) + return ret; + } + +- if (!auto_exposure && ctrls->exposure->is_new) { ++ if (!auto_exp && ctrls->exposure->is_new) { + u16 max_exp; + + ret = ov5640_read_reg16(sensor, OV5640_REG_AEC_PK_VTS, +@@ -2234,25 +2252,19 @@ static int ov5640_set_ctrl_exposure(stru + return ret; + } + +-static int ov5640_set_ctrl_gain(struct ov5640_dev *sensor, int auto_gain) ++static int ov5640_set_ctrl_gain(struct ov5640_dev *sensor, bool auto_gain) + { + struct ov5640_ctrls *ctrls = &sensor->ctrls; + int ret = 0; + + if (ctrls->auto_gain->is_new) { +- ret = ov5640_mod_reg(sensor, OV5640_REG_AEC_PK_MANUAL, +- BIT(1), +- ctrls->auto_gain->val ? 0 : BIT(1)); ++ ret = ov5640_set_autogain(sensor, auto_gain); + if (ret) + return ret; + } + +- if (!auto_gain && ctrls->gain->is_new) { +- u16 gain = (u16)ctrls->gain->val; +- +- ret = ov5640_write_reg16(sensor, OV5640_REG_AEC_PK_REAL_GAIN, +- gain & 0x3ff); +- } ++ if (!auto_gain && ctrls->gain->is_new) ++ ret = ov5640_set_gain(sensor, ctrls->gain->val); + + return ret; + } diff --git a/queue-4.19/media-ov5640-fix-exposure-regression.patch b/queue-4.19/media-ov5640-fix-exposure-regression.patch new file mode 100644 index 00000000000..362e738c979 --- /dev/null +++ b/queue-4.19/media-ov5640-fix-exposure-regression.patch @@ -0,0 +1,89 @@ +From dc29a1c187eedc1d498cb567c44bbbc832b009cb Mon Sep 17 00:00:00 2001 +From: Hugues Fruchet +Date: Tue, 11 Sep 2018 09:48:17 -0400 +Subject: media: ov5640: fix exposure regression + +From: Hugues Fruchet + +commit dc29a1c187eedc1d498cb567c44bbbc832b009cb upstream. + +Symptom was black image when capturing HD or 5Mp picture +due to manual exposure set to 1 while it was intended to +set autoexposure to "manual", fix this. + +Fixes: bf4a4b518c20 ("media: ov5640: Don't force the auto exposure state at start time"). + +Signed-off-by: Hugues Fruchet +Reviewed-by: Laurent Pinchart +Tested-by: Jacopo Mondi +Signed-off-by: Sakari Ailus +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Adam Ford +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/i2c/ov5640.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +--- a/drivers/media/i2c/ov5640.c ++++ b/drivers/media/i2c/ov5640.c +@@ -960,6 +960,12 @@ static int ov5640_load_regs(struct ov564 + return ov5640_set_timings(sensor, mode); + } + ++static int ov5640_set_autoexposure(struct ov5640_dev *sensor, bool on) ++{ ++ return ov5640_mod_reg(sensor, OV5640_REG_AEC_PK_MANUAL, ++ BIT(0), on ? 0 : BIT(0)); ++} ++ + /* read exposure, in number of line periods */ + static int ov5640_get_exposure(struct ov5640_dev *sensor) + { +@@ -1604,7 +1610,7 @@ static int ov5640_set_mode_exposure_calc + */ + static int ov5640_set_mode_direct(struct ov5640_dev *sensor, + const struct ov5640_mode_info *mode, +- s32 exposure) ++ bool auto_exp) + { + int ret; + +@@ -1621,7 +1627,8 @@ static int ov5640_set_mode_direct(struct + if (ret) + return ret; + +- return __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_exp, exposure); ++ return __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_exp, auto_exp ? ++ V4L2_EXPOSURE_AUTO : V4L2_EXPOSURE_MANUAL); + } + + static int ov5640_set_mode(struct ov5640_dev *sensor) +@@ -1629,7 +1636,7 @@ static int ov5640_set_mode(struct ov5640 + const struct ov5640_mode_info *mode = sensor->current_mode; + const struct ov5640_mode_info *orig_mode = sensor->last_mode; + enum ov5640_downsize_mode dn_mode, orig_dn_mode; +- s32 exposure; ++ bool auto_exp = sensor->ctrls.auto_exp->val == V4L2_EXPOSURE_AUTO; + int ret; + + dn_mode = mode->dn_mode; +@@ -1640,8 +1647,7 @@ static int ov5640_set_mode(struct ov5640 + if (ret) + return ret; + +- exposure = sensor->ctrls.auto_exp->val; +- ret = ov5640_set_exposure(sensor, V4L2_EXPOSURE_MANUAL); ++ ret = ov5640_set_autoexposure(sensor, false); + if (ret) + return ret; + +@@ -1657,7 +1663,7 @@ static int ov5640_set_mode(struct ov5640 + * change inside subsampling or scaling + * download firmware directly + */ +- ret = ov5640_set_mode_direct(sensor, mode, exposure); ++ ret = ov5640_set_mode_direct(sensor, mode, auto_exp); + } + + if (ret < 0) diff --git a/queue-4.19/media-ov5640-fix-timings-setup-code.patch b/queue-4.19/media-ov5640-fix-timings-setup-code.patch new file mode 100644 index 00000000000..8b25d33efbb --- /dev/null +++ b/queue-4.19/media-ov5640-fix-timings-setup-code.patch @@ -0,0 +1,118 @@ +From bad1774ed41e98a43074e50e7d5ac9e1e848d99a Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Wed, 18 Jul 2018 06:06:23 -0400 +Subject: media: ov5640: Fix timings setup code + +From: Jacopo Mondi + +commit bad1774ed41e98a43074e50e7d5ac9e1e848d99a upstream. + +As of: commit 476dec012f4c ("media: ov5640: Add horizontal and vertical +totals") the timings parameters gets programmed separately from the +static register values array. + +When changing capture mode, the vertical and horizontal totals gets +inspected by the set_mode_exposure_calc() functions, and only later +programmed with the new values. This means exposure, light banding +filter and shutter gain are calculated using the previous timings, and +are thus not correct. + +Fix this by programming timings right after the static register value +table has been sent to the sensor in the ov5640_load_regs() function. + +Fixes: 476dec012f4c ("media: ov5640: Add horizontal and vertical totals") + +Tested-by: Steve Longerbeam # i.MX6q SabreSD, CSI-2 +Tested-by: Loic Poulain # Dragonboard-410c, CSI-2 +Signed-off-by: Samuel Bobrowicz +Signed-off-by: Maxime Ripard +Signed-off-by: Jacopo Mondi +Signed-off-by: Sakari Ailus +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Adam Ford +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/i2c/ov5640.c | 50 ++++++++++++++++++--------------------------- + 1 file changed, 21 insertions(+), 29 deletions(-) + +--- a/drivers/media/i2c/ov5640.c ++++ b/drivers/media/i2c/ov5640.c +@@ -910,6 +910,26 @@ static int ov5640_mod_reg(struct ov5640_ + } + + /* download ov5640 settings to sensor through i2c */ ++static int ov5640_set_timings(struct ov5640_dev *sensor, ++ const struct ov5640_mode_info *mode) ++{ ++ int ret; ++ ++ ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPHO, mode->hact); ++ if (ret < 0) ++ return ret; ++ ++ ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPVO, mode->vact); ++ if (ret < 0) ++ return ret; ++ ++ ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_HTS, mode->htot); ++ if (ret < 0) ++ return ret; ++ ++ return ov5640_write_reg16(sensor, OV5640_REG_TIMING_VTS, mode->vtot); ++} ++ + static int ov5640_load_regs(struct ov5640_dev *sensor, + const struct ov5640_mode_info *mode) + { +@@ -937,7 +957,7 @@ static int ov5640_load_regs(struct ov564 + usleep_range(1000 * delay_ms, 1000 * delay_ms + 100); + } + +- return ret; ++ return ov5640_set_timings(sensor, mode); + } + + /* read exposure, in number of line periods */ +@@ -1400,30 +1420,6 @@ static int ov5640_set_virtual_channel(st + return ov5640_write_reg(sensor, OV5640_REG_DEBUG_MODE, temp); + } + +-static int ov5640_set_timings(struct ov5640_dev *sensor, +- const struct ov5640_mode_info *mode) +-{ +- int ret; +- +- ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPHO, mode->hact); +- if (ret < 0) +- return ret; +- +- ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPVO, mode->vact); +- if (ret < 0) +- return ret; +- +- ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_HTS, mode->htot); +- if (ret < 0) +- return ret; +- +- ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_VTS, mode->vtot); +- if (ret < 0) +- return ret; +- +- return 0; +-} +- + static const struct ov5640_mode_info * + ov5640_find_mode(struct ov5640_dev *sensor, enum ov5640_frame_rate fr, + int width, int height, bool nearest) +@@ -1667,10 +1663,6 @@ static int ov5640_set_mode(struct ov5640 + if (ret < 0) + return ret; + +- ret = ov5640_set_timings(sensor, mode); +- if (ret < 0) +- return ret; +- + ret = ov5640_set_binning(sensor, dn_mode != SCALING); + if (ret < 0) + return ret; diff --git a/queue-4.19/media-ov5640-fix-wrong-binning-value-in-exposure-calculation.patch b/queue-4.19/media-ov5640-fix-wrong-binning-value-in-exposure-calculation.patch new file mode 100644 index 00000000000..21506b491e3 --- /dev/null +++ b/queue-4.19/media-ov5640-fix-wrong-binning-value-in-exposure-calculation.patch @@ -0,0 +1,57 @@ +From c2c3f42df4dd9bb231d756bacb0c897f662c6d3c Mon Sep 17 00:00:00 2001 +From: Hugues Fruchet +Date: Tue, 11 Sep 2018 09:48:19 -0400 +Subject: media: ov5640: fix wrong binning value in exposure calculation + +From: Hugues Fruchet + +commit c2c3f42df4dd9bb231d756bacb0c897f662c6d3c upstream. + +ov5640_set_mode_exposure_calc() is checking binning value but +binning value read is buggy, fix this. +Rename ov5640_binning_on() to ov5640_get_binning() as per other +similar functions. + +Signed-off-by: Hugues Fruchet +Reviewed-by: Laurent Pinchart +Reviewed-by: Jacopo Mondi +Signed-off-by: Sakari Ailus +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Adam Ford +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/i2c/ov5640.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/media/i2c/ov5640.c ++++ b/drivers/media/i2c/ov5640.c +@@ -1384,7 +1384,7 @@ static int ov5640_set_ae_target(struct o + return ov5640_write_reg(sensor, OV5640_REG_AEC_CTRL1F, fast_low); + } + +-static int ov5640_binning_on(struct ov5640_dev *sensor) ++static int ov5640_get_binning(struct ov5640_dev *sensor) + { + u8 temp; + int ret; +@@ -1392,8 +1392,8 @@ static int ov5640_binning_on(struct ov56 + ret = ov5640_read_reg(sensor, OV5640_REG_TIMING_TC_REG21, &temp); + if (ret) + return ret; +- temp &= 0xfe; +- return temp ? 1 : 0; ++ ++ return temp & BIT(0); + } + + static int ov5640_set_binning(struct ov5640_dev *sensor, bool enable) +@@ -1479,7 +1479,7 @@ static int ov5640_set_mode_exposure_calc + if (ret < 0) + return ret; + prev_shutter = ret; +- ret = ov5640_binning_on(sensor); ++ ret = ov5640_get_binning(sensor); + if (ret < 0) + return ret; + if (ret && mode->id != OV5640_MODE_720P_1280_720 && diff --git a/queue-4.19/media-ov5640-re-work-mipi-startup-sequence.patch b/queue-4.19/media-ov5640-re-work-mipi-startup-sequence.patch new file mode 100644 index 00000000000..2d1531631e1 --- /dev/null +++ b/queue-4.19/media-ov5640-re-work-mipi-startup-sequence.patch @@ -0,0 +1,187 @@ +From aa4bb8b8838ffcc776a79f49a4d7476b82405349 Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Fri, 6 Jul 2018 05:51:52 -0400 +Subject: media: ov5640: Re-work MIPI startup sequence + +From: Jacopo Mondi + +commit aa4bb8b8838ffcc776a79f49a4d7476b82405349 upstream. + +Rework the MIPI interface startup sequence with the following changes: + +- Remove MIPI bus initialization from the initial settings blob +- At set_power(1) time power up MIPI Tx/Rx and set data and clock lanes in + LP11 during 'sleep' and 'idle' with MIPI clock in non-continuous mode. +- At s_stream time enable/disable the MIPI interface output. +- Restore default settings at set_power(0) time. + +Before this commit the sensor MIPI interface was initialized with settings +that require a start/stop sequence at power-up time in order to force lanes +into LP11 state, as they were initialized in LP00 when in 'sleep mode', +which is assumed to be the sensor manual definition for the D-PHY defined +stop mode. + +The stream start/stop was performed by enabling disabling clock gating, +and had the side effect to change the lanes sleep mode configuration when +stream was stopped. + +Clock gating/ungating: +- ret = ov5640_mod_reg(sensor, OV5640_REG_MIPI_CTRL00, BIT(5), +- on ? 0 : BIT(5)); +- if (ret) + +Set lanes in LP11 when in 'sleep mode': +- ret = ov5640_write_reg(sensor, OV5640_REG_PAD_OUTPUT00, +- on ? 0x00 : 0x70); + +This commit fixes an issue reported by Jagan Teki on i.MX6 platforms that +prevents the host interface from powering up correctly: +https://lkml.org/lkml/2018/6/1/38 + +It also improves MIPI capture operations stability on my testing platform +where MIPI capture often failed and returned all-purple frames. + +Fixes: f22996db44e2 ("media: ov5640: add support of DVP parallel interface") + +Tested-by: Steve Longerbeam (i.MX6q SabreSD, CSI-2) +Tested-by: Loic Poulain (Dragonboard-410c, CSI-2) +Reported-by: Jagan Teki +Signed-off-by: Jacopo Mondi +Signed-off-by: Sakari Ailus +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Adam Ford +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/i2c/ov5640.c | 99 +++++++++++++++++++++++++++++++++++---------- + 1 file changed, 79 insertions(+), 20 deletions(-) + +--- a/drivers/media/i2c/ov5640.c ++++ b/drivers/media/i2c/ov5640.c +@@ -288,10 +288,10 @@ static const struct reg_value ov5640_ini + {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0}, + {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x3000, 0x00, 0, 0}, + {0x3002, 0x1c, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3006, 0xc3, 0, 0}, +- {0x300e, 0x45, 0, 0}, {0x302e, 0x08, 0, 0}, {0x4300, 0x3f, 0, 0}, ++ {0x302e, 0x08, 0, 0}, {0x4300, 0x3f, 0, 0}, + {0x501f, 0x00, 0, 0}, {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, + {0x440e, 0x00, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0}, +- {0x4837, 0x0a, 0, 0}, {0x4800, 0x04, 0, 0}, {0x3824, 0x02, 0, 0}, ++ {0x4837, 0x0a, 0, 0}, {0x3824, 0x02, 0, 0}, + {0x5000, 0xa7, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x5180, 0xff, 0, 0}, + {0x5181, 0xf2, 0, 0}, {0x5182, 0x00, 0, 0}, {0x5183, 0x14, 0, 0}, + {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, {0x5186, 0x09, 0, 0}, +@@ -1104,12 +1104,25 @@ static int ov5640_set_stream_mipi(struct + { + int ret; + +- ret = ov5640_mod_reg(sensor, OV5640_REG_MIPI_CTRL00, BIT(5), +- on ? 0 : BIT(5)); +- if (ret) +- return ret; +- ret = ov5640_write_reg(sensor, OV5640_REG_PAD_OUTPUT00, +- on ? 0x00 : 0x70); ++ /* ++ * Enable/disable the MIPI interface ++ * ++ * 0x300e = on ? 0x45 : 0x40 ++ * ++ * FIXME: the sensor manual (version 2.03) reports ++ * [7:5] = 000 : 1 data lane mode ++ * [7:5] = 001 : 2 data lanes mode ++ * But this settings do not work, while the following ones ++ * have been validated for 2 data lanes mode. ++ * ++ * [7:5] = 010 : 2 data lanes mode ++ * [4] = 0 : Power up MIPI HS Tx ++ * [3] = 0 : Power up MIPI LS Rx ++ * [2] = 1/0 : MIPI interface enable/disable ++ * [1:0] = 01/00: FIXME: 'debug' ++ */ ++ ret = ov5640_write_reg(sensor, OV5640_REG_IO_MIPI_CTRL00, ++ on ? 0x45 : 0x40); + if (ret) + return ret; + +@@ -1790,23 +1803,69 @@ static int ov5640_set_power(struct ov564 + if (ret) + goto power_off; + ++ /* We're done here for DVP bus, while CSI-2 needs setup. */ ++ if (sensor->ep.bus_type != V4L2_MBUS_CSI2) ++ return 0; ++ ++ /* ++ * Power up MIPI HS Tx and LS Rx; 2 data lanes mode ++ * ++ * 0x300e = 0x40 ++ * [7:5] = 010 : 2 data lanes mode (see FIXME note in ++ * "ov5640_set_stream_mipi()") ++ * [4] = 0 : Power up MIPI HS Tx ++ * [3] = 0 : Power up MIPI LS Rx ++ * [2] = 0 : MIPI interface disabled ++ */ ++ ret = ov5640_write_reg(sensor, ++ OV5640_REG_IO_MIPI_CTRL00, 0x40); ++ if (ret) ++ goto power_off; ++ ++ /* ++ * Gate clock and set LP11 in 'no packets mode' (idle) ++ * ++ * 0x4800 = 0x24 ++ * [5] = 1 : Gate clock when 'no packets' ++ * [2] = 1 : MIPI bus in LP11 when 'no packets' ++ */ ++ ret = ov5640_write_reg(sensor, ++ OV5640_REG_MIPI_CTRL00, 0x24); ++ if (ret) ++ goto power_off; ++ ++ /* ++ * Set data lanes and clock in LP11 when 'sleeping' ++ * ++ * 0x3019 = 0x70 ++ * [6] = 1 : MIPI data lane 2 in LP11 when 'sleeping' ++ * [5] = 1 : MIPI data lane 1 in LP11 when 'sleeping' ++ * [4] = 1 : MIPI clock lane in LP11 when 'sleeping' ++ */ ++ ret = ov5640_write_reg(sensor, ++ OV5640_REG_PAD_OUTPUT00, 0x70); ++ if (ret) ++ goto power_off; ++ ++ /* Give lanes some time to coax into LP11 state. */ ++ usleep_range(500, 1000); ++ ++ } else { + if (sensor->ep.bus_type == V4L2_MBUS_CSI2) { +- /* +- * start streaming briefly followed by stream off in +- * order to coax the clock lane into LP-11 state. +- */ +- ret = ov5640_set_stream_mipi(sensor, true); +- if (ret) +- goto power_off; +- usleep_range(1000, 2000); +- ret = ov5640_set_stream_mipi(sensor, false); +- if (ret) +- goto power_off; ++ /* Reset MIPI bus settings to their default values. */ ++ ov5640_write_reg(sensor, ++ OV5640_REG_IO_MIPI_CTRL00, 0x58); ++ ov5640_write_reg(sensor, ++ OV5640_REG_MIPI_CTRL00, 0x04); ++ ov5640_write_reg(sensor, ++ OV5640_REG_PAD_OUTPUT00, 0x00); + } + +- return 0; ++ ov5640_set_power_off(sensor); + } + ++ return 0; ++ + power_off: + ov5640_set_power_off(sensor); + return ret; diff --git a/queue-4.19/rcu-make-need_resched-respond-to-urgent-rcu-qs-needs.patch b/queue-4.19/rcu-make-need_resched-respond-to-urgent-rcu-qs-needs.patch new file mode 100644 index 00000000000..3ca876481b9 --- /dev/null +++ b/queue-4.19/rcu-make-need_resched-respond-to-urgent-rcu-qs-needs.patch @@ -0,0 +1,59 @@ +From 92aa39e9dc77481b90cbef25e547d66cab901496 Mon Sep 17 00:00:00 2001 +From: "Paul E. McKenney" +Date: Mon, 9 Jul 2018 13:47:30 -0700 +Subject: rcu: Make need_resched() respond to urgent RCU-QS needs + +From: Paul E. McKenney + +commit 92aa39e9dc77481b90cbef25e547d66cab901496 upstream. + +The per-CPU rcu_dynticks.rcu_urgent_qs variable communicates an urgent +need for an RCU quiescent state from the force-quiescent-state processing +within the grace-period kthread to context switches and to cond_resched(). +Unfortunately, such urgent needs are not communicated to need_resched(), +which is sometimes used to decide when to invoke cond_resched(), for +but one example, within the KVM vcpu_run() function. As of v4.15, this +can result in synchronize_sched() being delayed by up to ten seconds, +which can be problematic, to say nothing of annoying. + +This commit therefore checks rcu_dynticks.rcu_urgent_qs from within +rcu_check_callbacks(), which is invoked from the scheduling-clock +interrupt handler. If the current task is not an idle task and is +not executing in usermode, a context switch is forced, and either way, +the rcu_dynticks.rcu_urgent_qs variable is set to false. If the current +task is an idle task, then RCU's dyntick-idle code will detect the +quiescent state, so no further action is required. Similarly, if the +task is executing in usermode, other code in rcu_check_callbacks() and +its called functions will report the corresponding quiescent state. + +Reported-by: Marius Hillenbrand +Reported-by: David Woodhouse +Suggested-by: Peter Zijlstra +Signed-off-by: Paul E. McKenney +[ paulmck: Backported to make patch apply cleanly on older versions. ] +Tested-by: Marius Hillenbrand +Cc: # 4.12.x - 4.19.x +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/rcu/tree.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/kernel/rcu/tree.c ++++ b/kernel/rcu/tree.c +@@ -2662,6 +2662,15 @@ void rcu_check_callbacks(int user) + rcu_bh_qs(); + } + rcu_preempt_check_callbacks(); ++ /* The load-acquire pairs with the store-release setting to true. */ ++ if (smp_load_acquire(this_cpu_ptr(&rcu_dynticks.rcu_urgent_qs))) { ++ /* Idle and userspace execution already are quiescent states. */ ++ if (!rcu_is_cpu_rrupt_from_idle() && !user) { ++ set_tsk_need_resched(current); ++ set_preempt_need_resched(); ++ } ++ __this_cpu_write(rcu_dynticks.rcu_urgent_qs, false); ++ } + if (rcu_pending()) + invoke_rcu_core(); + diff --git a/queue-4.19/series b/queue-4.19/series index e0d5ff8017b..389291ddbd2 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -100,3 +100,11 @@ dax-avoid-losing-wakeup-in-dax_lock_mapping_entry.patch include-linux-pfn_t.h-force-to-be-parsed-as-an-unary-operator.patch tty-wipe-buffer.patch tty-wipe-buffer-if-not-echoing-data.patch +gfs2-fix-iomap-buffer-head-reference-counting-bug.patch +rcu-make-need_resched-respond-to-urgent-rcu-qs-needs.patch +media-ov5640-re-work-mipi-startup-sequence.patch +media-ov5640-fix-timings-setup-code.patch +media-ov5640-fix-exposure-regression.patch +media-ov5640-fix-auto-gain-exposure-when-changing-mode.patch +media-ov5640-fix-wrong-binning-value-in-exposure-calculation.patch +media-ov5640-fix-auto-controls-values-when-switching-to-manual-mode.patch