]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.19-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 29 Nov 2018 12:49:23 +0000 (13:49 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 29 Nov 2018 12:49:23 +0000 (13:49 +0100)
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

queue-4.19/gfs2-fix-iomap-buffer-head-reference-counting-bug.patch [new file with mode: 0644]
queue-4.19/media-ov5640-fix-auto-controls-values-when-switching-to-manual-mode.patch [new file with mode: 0644]
queue-4.19/media-ov5640-fix-auto-gain-exposure-when-changing-mode.patch [new file with mode: 0644]
queue-4.19/media-ov5640-fix-exposure-regression.patch [new file with mode: 0644]
queue-4.19/media-ov5640-fix-timings-setup-code.patch [new file with mode: 0644]
queue-4.19/media-ov5640-fix-wrong-binning-value-in-exposure-calculation.patch [new file with mode: 0644]
queue-4.19/media-ov5640-re-work-mipi-startup-sequence.patch [new file with mode: 0644]
queue-4.19/rcu-make-need_resched-respond-to-urgent-rcu-qs-needs.patch [new file with mode: 0644]
queue-4.19/series

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 (file)
index 0000000..5fd93b8
--- /dev/null
@@ -0,0 +1,158 @@
+From c26b5aa8ef0d46035060fded475e6ab957b9f69f Mon Sep 17 00:00:00 2001
+From: Andreas Gruenbacher <agruenba@redhat.com>
+Date: Sun, 11 Nov 2018 11:15:21 +0000
+Subject: gfs2: Fix iomap buffer head reference counting bug
+
+From: Andreas Gruenbacher <agruenba@redhat.com>
+
+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 <agruenba@redhat.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ 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 (file)
index 0000000..3c878c6
--- /dev/null
@@ -0,0 +1,43 @@
+From a8f438c684eaa4cbe6c98828eb996d5ec53e24fb Mon Sep 17 00:00:00 2001
+From: Hugues Fruchet <hugues.fruchet@st.com>
+Date: Tue, 11 Sep 2018 09:48:20 -0400
+Subject: media: ov5640: fix auto controls values when switching to manual mode
+
+From: Hugues Fruchet <hugues.fruchet@st.com>
+
+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 <hugues.fruchet@st.com>
+Tested-by: Jacopo Mondi <jacopo@jmondi.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+Signed-off-by: Adam Ford <aford173@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..1c7be1c
--- /dev/null
@@ -0,0 +1,223 @@
+From 3cca8ef5f774cbd61c8db05d9aa401de9bb59c66 Mon Sep 17 00:00:00 2001
+From: Hugues Fruchet <hugues.fruchet@st.com>
+Date: Tue, 11 Sep 2018 09:48:18 -0400
+Subject: media: ov5640: fix auto gain & exposure when changing mode
+
+From: Hugues Fruchet <hugues.fruchet@st.com>
+
+commit 3cca8ef5f774cbd61c8db05d9aa401de9bb59c66 upstream.
+
+Ensure that auto gain and auto exposure are well restored
+when changing mode.
+
+Signed-off-by: Hugues Fruchet <hugues.fruchet@st.com>
+Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
+Tested-by: Jacopo Mondi <jacopo@jmondi.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+Signed-off-by: Adam Ford <aford173@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..362e738
--- /dev/null
@@ -0,0 +1,89 @@
+From dc29a1c187eedc1d498cb567c44bbbc832b009cb Mon Sep 17 00:00:00 2001
+From: Hugues Fruchet <hugues.fruchet@st.com>
+Date: Tue, 11 Sep 2018 09:48:17 -0400
+Subject: media: ov5640: fix exposure regression
+
+From: Hugues Fruchet <hugues.fruchet@st.com>
+
+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 <hugues.fruchet@st.com>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Tested-by: Jacopo Mondi <jacopo@jmondi.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+Signed-off-by: Adam Ford <aford173@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..8b25d33
--- /dev/null
@@ -0,0 +1,118 @@
+From bad1774ed41e98a43074e50e7d5ac9e1e848d99a Mon Sep 17 00:00:00 2001
+From: Jacopo Mondi <jacopo@jmondi.org>
+Date: Wed, 18 Jul 2018 06:06:23 -0400
+Subject: media: ov5640: Fix timings setup code
+
+From: Jacopo Mondi <jacopo@jmondi.org>
+
+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 <slongerbeam@gmail.com> # i.MX6q SabreSD, CSI-2
+Tested-by: Loic Poulain <loic.poulain@linaro.org> # Dragonboard-410c, CSI-2
+Signed-off-by: Samuel Bobrowicz <sam@elite-embedded.com>
+Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
+Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+Signed-off-by: Adam Ford <aford173@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..21506b4
--- /dev/null
@@ -0,0 +1,57 @@
+From c2c3f42df4dd9bb231d756bacb0c897f662c6d3c Mon Sep 17 00:00:00 2001
+From: Hugues Fruchet <hugues.fruchet@st.com>
+Date: Tue, 11 Sep 2018 09:48:19 -0400
+Subject: media: ov5640: fix wrong binning value in exposure calculation
+
+From: Hugues Fruchet <hugues.fruchet@st.com>
+
+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 <hugues.fruchet@st.com>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+Signed-off-by: Adam Ford <aford173@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..2d15316
--- /dev/null
@@ -0,0 +1,187 @@
+From aa4bb8b8838ffcc776a79f49a4d7476b82405349 Mon Sep 17 00:00:00 2001
+From: Jacopo Mondi <jacopo@jmondi.org>
+Date: Fri, 6 Jul 2018 05:51:52 -0400
+Subject: media: ov5640: Re-work MIPI startup sequence
+
+From: Jacopo Mondi <jacopo@jmondi.org>
+
+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 <slongerbeam@gmail.com> (i.MX6q SabreSD, CSI-2)
+Tested-by: Loic Poulain <loic.poulain@linaro.org> (Dragonboard-410c, CSI-2)
+Reported-by: Jagan Teki <jagan@amarulasolutions.com>
+Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+Signed-off-by: Adam Ford <aford173@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..3ca8764
--- /dev/null
@@ -0,0 +1,59 @@
+From 92aa39e9dc77481b90cbef25e547d66cab901496 Mon Sep 17 00:00:00 2001
+From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
+Date: Mon, 9 Jul 2018 13:47:30 -0700
+Subject: rcu: Make need_resched() respond to urgent RCU-QS needs
+
+From: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+
+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 <mhillenb@amazon.de>
+Reported-by: David Woodhouse <dwmw2@infradead.org>
+Suggested-by: Peter Zijlstra <peterz@infradead.org>
+Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+[ paulmck: Backported to make patch apply cleanly on older versions. ]
+Tested-by: Marius Hillenbrand <mhillenb@amazon.de>
+Cc: <stable@vger.kernel.org> # 4.12.x - 4.19.x
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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();
index e0d5ff8017b22af584354c529bb27d0960cdd2b9..389291ddbd2bb30caaf3cf00f2113679b1220158 100644 (file)
@@ -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