[PATCH 4.4 00/74] 4.4.5-stable review

classic Classic list List threaded Threaded
86 messages Options
12345
Reply | Threaded
Open this post in threaded view
|

[PATCH 4.4 23/74] drm/ast: Fix incorrect register check for DRAM width

Greg KH-4
4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Timothy Pearson <[hidden email]>

commit 2d02b8bdba322b527c5f5168ce1ca10c2d982a78 upstream.

During DRAM initialization on certain ASpeed devices, an incorrect
bit (bit 10) was checked in the "SDRAM Bus Width Status" register
to determine DRAM width.

Query bit 6 instead in accordance with the Aspeed AST2050 datasheet v1.05.

Signed-off-by: Timothy Pearson <[hidden email]>
Signed-off-by: Dave Airlie <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>

---
 drivers/gpu/drm/ast/ast_main.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -227,7 +227,7 @@ static int ast_get_dram_info(struct drm_
  } while (ast_read32(ast, 0x10000) != 0x01);
  data = ast_read32(ast, 0x10004);
 
- if (data & 0x400)
+ if (data & 0x40)
  ast->dram_bus_width = 16;
  else
  ast->dram_bus_width = 32;


Reply | Threaded
Open this post in threaded view
|

[PATCH 4.4 64/74] cxl: Fix PSL timebase synchronization detection

Greg KH-4
In reply to this post by Greg KH-4
4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Frederic Barrat <[hidden email]>

commit 923adb1646d5ba739d2a1e63ee20d60574d9da8e upstream.

The PSL timebase synchronization is seemingly failing for
configuration not including VIRT_CPU_ACCOUNTING_NATIVE. The driver
shows the following trace in dmesg:
PSL: Timebase sync: giving up!

The PSL timebase register is actually syncing correctly, but the cxl
driver is not detecting it. Fix is to use the proper timebase-to-time
conversion.

Signed-off-by: Frederic Barrat <[hidden email]>
Acked-by: Michael Neuling <[hidden email]>
Reviewed-by: Matthew R. Ochs <[hidden email]>
Acked-by: Ian Munsie <[hidden email]>
Reviewed-by: Andrew Donnellan <[hidden email]>
Reviewed-by: Vaibhav Jain <[hidden email]>
Signed-off-by: Michael Ellerman <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>

---
 drivers/misc/cxl/pci.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/misc/cxl/pci.c
+++ b/drivers/misc/cxl/pci.c
@@ -414,7 +414,7 @@ static int cxl_setup_psl_timebase(struct
  delta = mftb() - psl_tb;
  if (delta < 0)
  delta = -delta;
- } while (cputime_to_usecs(delta) > 16);
+ } while (tb_to_ns(delta) > 16000);
 
  return 0;
 }


Reply | Threaded
Open this post in threaded view
|

[PATCH 4.4 63/74] MIPS: traps: Fix SIGFPE information leak from `do_ov and `do_trap_or_bp

Greg KH-4
In reply to this post by Greg KH-4
4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Maciej W. Rozycki <[hidden email]>

commit e723e3f7f9591b79e8c56b3d7c5a204a9c571b55 upstream.

Avoid sending a partially initialised `siginfo_t' structure along SIGFPE
signals issued from `do_ov' and `do_trap_or_bp', leading to information
leaking from the kernel stack.

Signed-off-by: Maciej W. Rozycki <[hidden email]>
Signed-off-by: Ralf Baechle <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>

---
 arch/mips/kernel/traps.c |   13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -690,15 +690,15 @@ static int simulate_sync(struct pt_regs
 asmlinkage void do_ov(struct pt_regs *regs)
 {
  enum ctx_state prev_state;
- siginfo_t info;
+ siginfo_t info = {
+ .si_signo = SIGFPE,
+ .si_code = FPE_INTOVF,
+ .si_addr = (void __user *)regs->cp0_epc,
+ };
 
  prev_state = exception_enter();
  die_if_kernel("Integer overflow", regs);
 
- info.si_code = FPE_INTOVF;
- info.si_signo = SIGFPE;
- info.si_errno = 0;
- info.si_addr = (void __user *) regs->cp0_epc;
  force_sig_info(SIGFPE, &info, current);
  exception_exit(prev_state);
 }
@@ -874,7 +874,7 @@ out:
 void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
  const char *str)
 {
- siginfo_t info;
+ siginfo_t info = { 0 };
  char b[40];
 
 #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
@@ -903,7 +903,6 @@ void do_trap_or_bp(struct pt_regs *regs,
  else
  info.si_code = FPE_INTOVF;
  info.si_signo = SIGFPE;
- info.si_errno = 0;
  info.si_addr = (void __user *) regs->cp0_epc;
  force_sig_info(SIGFPE, &info, current);
  break;


Reply | Threaded
Open this post in threaded view
|

[PATCH 4.4 53/74] ALSA: hdsp: Fix wrong boolean ctl value accesses

Greg KH-4
In reply to this post by Greg KH-4
4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Takashi Iwai <[hidden email]>

commit eab3c4db193f5fcccf70e884de9a922ca2c63d80 upstream.

snd-hdsp driver accesses enum item values (int) instead of boolean
values (long) wrongly for some ctl elements.  This patch fixes them.

Signed-off-by: Takashi Iwai <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>

---
 sound/pci/rme9652/hdsp.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -2879,7 +2879,7 @@ static int snd_hdsp_get_dds_offset(struc
 {
  struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
 
- ucontrol->value.enumerated.item[0] = hdsp_dds_offset(hdsp);
+ ucontrol->value.integer.value[0] = hdsp_dds_offset(hdsp);
  return 0;
 }
 
@@ -2891,7 +2891,7 @@ static int snd_hdsp_put_dds_offset(struc
 
  if (!snd_hdsp_use_is_exclusive(hdsp))
  return -EBUSY;
- val = ucontrol->value.enumerated.item[0];
+ val = ucontrol->value.integer.value[0];
  spin_lock_irq(&hdsp->lock);
  if (val != hdsp_dds_offset(hdsp))
  change = (hdsp_set_dds_offset(hdsp, val) == 0) ? 1 : 0;


Reply | Threaded
Open this post in threaded view
|

[PATCH 4.4 52/74] ALSA: hdspm: Fix wrong boolean ctl value accesses

Greg KH-4
In reply to this post by Greg KH-4
4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Takashi Iwai <[hidden email]>

commit 537e48136295c5860a92138c5ea3959b9542868b upstream.

snd-hdspm driver accesses enum item values (int) instead of boolean
values (long) wrongly for some ctl elements.  This patch fixes them.

Signed-off-by: Takashi Iwai <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>

---
 sound/pci/rme9652/hdspm.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -2261,7 +2261,7 @@ static int snd_hdspm_put_system_sample_r
 {
  struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
 
- hdspm_set_dds_value(hdspm, ucontrol->value.enumerated.item[0]);
+ hdspm_set_dds_value(hdspm, ucontrol->value.integer.value[0]);
  return 0;
 }
 
@@ -4449,7 +4449,7 @@ static int snd_hdspm_get_tco_word_term(s
 {
  struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
 
- ucontrol->value.enumerated.item[0] = hdspm->tco->term;
+ ucontrol->value.integer.value[0] = hdspm->tco->term;
 
  return 0;
 }
@@ -4460,8 +4460,8 @@ static int snd_hdspm_put_tco_word_term(s
 {
  struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
 
- if (hdspm->tco->term != ucontrol->value.enumerated.item[0]) {
- hdspm->tco->term = ucontrol->value.enumerated.item[0];
+ if (hdspm->tco->term != ucontrol->value.integer.value[0]) {
+ hdspm->tco->term = ucontrol->value.integer.value[0];
 
  hdspm_tco_write(hdspm);
 


Reply | Threaded
Open this post in threaded view
|

[PATCH 4.4 50/74] ALSA: pcm: Fix ioctls for X32 ABI

Greg KH-4
In reply to this post by Greg KH-4
4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Takashi Iwai <[hidden email]>

commit 513ace79b657e2022a592e77f24074e088681ecc upstream.

X32 ABI uses the 64bit timespec in addition to 64bit alignment of
64bit values.  This leads to incompatibilities in some PCM ioctls
involved with snd_pcm_channel_info, snd_pcm_status and
snd_pcm_sync_ptr structs.  Fix the PCM compat ABI for these ioctls
like the previous commit for ctl API.

Reported-by: Steven Newbury <[hidden email]>
Signed-off-by: Takashi Iwai <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>

---
 sound/core/pcm_compat.c |  177 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 176 insertions(+), 1 deletion(-)

--- a/sound/core/pcm_compat.c
+++ b/sound/core/pcm_compat.c
@@ -183,6 +183,14 @@ static int snd_pcm_ioctl_channel_info_co
  return err;
 }
 
+#ifdef CONFIG_X86_X32
+/* X32 ABI has the same struct as x86-64 for snd_pcm_channel_info */
+static int snd_pcm_channel_info_user(struct snd_pcm_substream *substream,
+     struct snd_pcm_channel_info __user *src);
+#define snd_pcm_ioctl_channel_info_x32(s, p) \
+ snd_pcm_channel_info_user(s, p)
+#endif /* CONFIG_X86_X32 */
+
 struct snd_pcm_status32 {
  s32 state;
  struct compat_timespec trigger_tstamp;
@@ -243,6 +251,71 @@ static int snd_pcm_status_user_compat(st
  return err;
 }
 
+#ifdef CONFIG_X86_X32
+/* X32 ABI has 64bit timespec and 64bit alignment */
+struct snd_pcm_status_x32 {
+ s32 state;
+ u32 rsvd; /* alignment */
+ struct timespec trigger_tstamp;
+ struct timespec tstamp;
+ u32 appl_ptr;
+ u32 hw_ptr;
+ s32 delay;
+ u32 avail;
+ u32 avail_max;
+ u32 overrange;
+ s32 suspended_state;
+ u32 audio_tstamp_data;
+ struct timespec audio_tstamp;
+ struct timespec driver_tstamp;
+ u32 audio_tstamp_accuracy;
+ unsigned char reserved[52-2*sizeof(struct timespec)];
+} __packed;
+
+#define put_timespec(src, dst) copy_to_user(dst, src, sizeof(*dst))
+
+static int snd_pcm_status_user_x32(struct snd_pcm_substream *substream,
+   struct snd_pcm_status_x32 __user *src,
+   bool ext)
+{
+ struct snd_pcm_status status;
+ int err;
+
+ memset(&status, 0, sizeof(status));
+ /*
+ * with extension, parameters are read/write,
+ * get audio_tstamp_data from user,
+ * ignore rest of status structure
+ */
+ if (ext && get_user(status.audio_tstamp_data,
+ (u32 __user *)(&src->audio_tstamp_data)))
+ return -EFAULT;
+ err = snd_pcm_status(substream, &status);
+ if (err < 0)
+ return err;
+
+ if (clear_user(src, sizeof(*src)))
+ return -EFAULT;
+ if (put_user(status.state, &src->state) ||
+    put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) ||
+    put_timespec(&status.tstamp, &src->tstamp) ||
+    put_user(status.appl_ptr, &src->appl_ptr) ||
+    put_user(status.hw_ptr, &src->hw_ptr) ||
+    put_user(status.delay, &src->delay) ||
+    put_user(status.avail, &src->avail) ||
+    put_user(status.avail_max, &src->avail_max) ||
+    put_user(status.overrange, &src->overrange) ||
+    put_user(status.suspended_state, &src->suspended_state) ||
+    put_user(status.audio_tstamp_data, &src->audio_tstamp_data) ||
+    put_timespec(&status.audio_tstamp, &src->audio_tstamp) ||
+    put_timespec(&status.driver_tstamp, &src->driver_tstamp) ||
+    put_user(status.audio_tstamp_accuracy, &src->audio_tstamp_accuracy))
+ return -EFAULT;
+
+ return err;
+}
+#endif /* CONFIG_X86_X32 */
+
 /* both for HW_PARAMS and HW_REFINE */
 static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream,
   int refine,
@@ -469,6 +542,93 @@ static int snd_pcm_ioctl_sync_ptr_compat
  return 0;
 }
 
+#ifdef CONFIG_X86_X32
+/* X32 ABI has 64bit timespec and 64bit alignment */
+struct snd_pcm_mmap_status_x32 {
+ s32 state;
+ s32 pad1;
+ u32 hw_ptr;
+ u32 pad2; /* alignment */
+ struct timespec tstamp;
+ s32 suspended_state;
+ struct timespec audio_tstamp;
+} __packed;
+
+struct snd_pcm_mmap_control_x32 {
+ u32 appl_ptr;
+ u32 avail_min;
+};
+
+struct snd_pcm_sync_ptr_x32 {
+ u32 flags;
+ u32 rsvd; /* alignment */
+ union {
+ struct snd_pcm_mmap_status_x32 status;
+ unsigned char reserved[64];
+ } s;
+ union {
+ struct snd_pcm_mmap_control_x32 control;
+ unsigned char reserved[64];
+ } c;
+} __packed;
+
+static int snd_pcm_ioctl_sync_ptr_x32(struct snd_pcm_substream *substream,
+      struct snd_pcm_sync_ptr_x32 __user *src)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ volatile struct snd_pcm_mmap_status *status;
+ volatile struct snd_pcm_mmap_control *control;
+ u32 sflags;
+ struct snd_pcm_mmap_control scontrol;
+ struct snd_pcm_mmap_status sstatus;
+ snd_pcm_uframes_t boundary;
+ int err;
+
+ if (snd_BUG_ON(!runtime))
+ return -EINVAL;
+
+ if (get_user(sflags, &src->flags) ||
+    get_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
+    get_user(scontrol.avail_min, &src->c.control.avail_min))
+ return -EFAULT;
+ if (sflags & SNDRV_PCM_SYNC_PTR_HWSYNC) {
+ err = snd_pcm_hwsync(substream);
+ if (err < 0)
+ return err;
+ }
+ status = runtime->status;
+ control = runtime->control;
+ boundary = recalculate_boundary(runtime);
+ if (!boundary)
+ boundary = 0x7fffffff;
+ snd_pcm_stream_lock_irq(substream);
+ /* FIXME: we should consider the boundary for the sync from app */
+ if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL))
+ control->appl_ptr = scontrol.appl_ptr;
+ else
+ scontrol.appl_ptr = control->appl_ptr % boundary;
+ if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
+ control->avail_min = scontrol.avail_min;
+ else
+ scontrol.avail_min = control->avail_min;
+ sstatus.state = status->state;
+ sstatus.hw_ptr = status->hw_ptr % boundary;
+ sstatus.tstamp = status->tstamp;
+ sstatus.suspended_state = status->suspended_state;
+ sstatus.audio_tstamp = status->audio_tstamp;
+ snd_pcm_stream_unlock_irq(substream);
+ if (put_user(sstatus.state, &src->s.status.state) ||
+    put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) ||
+    put_timespec(&sstatus.tstamp, &src->s.status.tstamp) ||
+    put_user(sstatus.suspended_state, &src->s.status.suspended_state) ||
+    put_timespec(&sstatus.audio_tstamp, &src->s.status.audio_tstamp) ||
+    put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
+    put_user(scontrol.avail_min, &src->c.control.avail_min))
+ return -EFAULT;
+
+ return 0;
+}
+#endif /* CONFIG_X86_X32 */
 
 /*
  */
@@ -487,7 +647,12 @@ enum {
  SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct snd_xfern32),
  SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct snd_xfern32),
  SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr32),
-
+#ifdef CONFIG_X86_X32
+ SNDRV_PCM_IOCTL_CHANNEL_INFO_X32 = _IOR('A', 0x32, struct snd_pcm_channel_info),
+ SNDRV_PCM_IOCTL_STATUS_X32 = _IOR('A', 0x20, struct snd_pcm_status_x32),
+ SNDRV_PCM_IOCTL_STATUS_EXT_X32 = _IOWR('A', 0x24, struct snd_pcm_status_x32),
+ SNDRV_PCM_IOCTL_SYNC_PTR_X32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr_x32),
+#endif /* CONFIG_X86_X32 */
 };
 
 static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
@@ -559,6 +724,16 @@ static long snd_pcm_ioctl_compat(struct
  return snd_pcm_ioctl_rewind_compat(substream, argp);
  case SNDRV_PCM_IOCTL_FORWARD32:
  return snd_pcm_ioctl_forward_compat(substream, argp);
+#ifdef CONFIG_X86_X32
+ case SNDRV_PCM_IOCTL_STATUS_X32:
+ return snd_pcm_status_user_x32(substream, argp, false);
+ case SNDRV_PCM_IOCTL_STATUS_EXT_X32:
+ return snd_pcm_status_user_x32(substream, argp, true);
+ case SNDRV_PCM_IOCTL_SYNC_PTR_X32:
+ return snd_pcm_ioctl_sync_ptr_x32(substream, argp);
+ case SNDRV_PCM_IOCTL_CHANNEL_INFO_X32:
+ return snd_pcm_ioctl_channel_info_x32(substream, argp);
+#endif /* CONFIG_X86_X32 */
  }
 
  return -ENOIOCTLCMD;


Reply | Threaded
Open this post in threaded view
|

[PATCH 4.4 54/74] ALSA: hdspm: Fix zero-division

Greg KH-4
In reply to this post by Greg KH-4
4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Takashi Iwai <[hidden email]>

commit c1099c3294c2344110085a38c50e478a5992b368 upstream.

HDSPM driver contains a code issuing zero-division potentially in
system sample rate ctl code.  This patch fixes it by not processing
a zero or invalid rate value as a divisor, as well as excluding the
invalid value to be passed via the given ctl element.

Signed-off-by: Takashi Iwai <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>

---
 sound/pci/rme9652/hdspm.c |    8 ++++++++
 1 file changed, 8 insertions(+)

--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -1601,6 +1601,9 @@ static void hdspm_set_dds_value(struct h
 {
  u64 n;
 
+ if (snd_BUG_ON(rate <= 0))
+ return;
+
  if (rate >= 112000)
  rate /= 4;
  else if (rate >= 56000)
@@ -2215,6 +2218,8 @@ static int hdspm_get_system_sample_rate(
  } else {
  /* slave mode, return external sample rate */
  rate = hdspm_external_sample_rate(hdspm);
+ if (!rate)
+ rate = hdspm->system_sample_rate;
  }
  }
 
@@ -2260,7 +2265,10 @@ static int snd_hdspm_put_system_sample_r
     ucontrol)
 {
  struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+ int rate = ucontrol->value.integer.value[0];
 
+ if (rate < 27000 || rate > 207000)
+ return -EINVAL;
  hdspm_set_dds_value(hdspm, ucontrol->value.integer.value[0]);
  return 0;
 }


Reply | Threaded
Open this post in threaded view
|

[PATCH 4.4 51/74] ALSA: seq: oss: Dont drain at closing a client

Greg KH-4
In reply to this post by Greg KH-4
4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Takashi Iwai <[hidden email]>

commit 197b958c1e76a575d77038cc98b4bebc2134279f upstream.

The OSS sequencer client tries to drain the pending events at
releasing.  Unfortunately, as spotted by syzkaller fuzzer, this may
lead to an unkillable process state when the event has been queued at
the far future.  Since the process being released can't be signaled
any longer, it remains and waits for the echo-back event in that far
future.

Back to history, the draining feature was implemented at the time we
misinterpreted POSIX definition for blocking file operation.
Actually, such a behavior is superfluous at release, and we should
just release the device as is instead of keeping it up forever.

This patch just removes the draining call that may block the release
for too long time unexpectedly.

BugLink: http://lkml.kernel.org/r/CACT4Y+Y4kD-aBGj37rf-xBw9bH3GMU6P+MYg4W1e-s-paVD2pg@...
Reported-by: Dmitry Vyukov <[hidden email]>
Signed-off-by: Takashi Iwai <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>

---
 sound/core/seq/oss/seq_oss.c        |    2 --
 sound/core/seq/oss/seq_oss_device.h |    1 -
 sound/core/seq/oss/seq_oss_init.c   |   16 ----------------
 3 files changed, 19 deletions(-)

--- a/sound/core/seq/oss/seq_oss.c
+++ b/sound/core/seq/oss/seq_oss.c
@@ -148,8 +148,6 @@ odev_release(struct inode *inode, struct
  if ((dp = file->private_data) == NULL)
  return 0;
 
- snd_seq_oss_drain_write(dp);
-
  mutex_lock(&register_mutex);
  snd_seq_oss_release(dp);
  mutex_unlock(&register_mutex);
--- a/sound/core/seq/oss/seq_oss_device.h
+++ b/sound/core/seq/oss/seq_oss_device.h
@@ -127,7 +127,6 @@ int snd_seq_oss_write(struct seq_oss_dev
 unsigned int snd_seq_oss_poll(struct seq_oss_devinfo *dp, struct file *file, poll_table * wait);
 
 void snd_seq_oss_reset(struct seq_oss_devinfo *dp);
-void snd_seq_oss_drain_write(struct seq_oss_devinfo *dp);
 
 /* */
 void snd_seq_oss_process_queue(struct seq_oss_devinfo *dp, abstime_t time);
--- a/sound/core/seq/oss/seq_oss_init.c
+++ b/sound/core/seq/oss/seq_oss_init.c
@@ -436,22 +436,6 @@ snd_seq_oss_release(struct seq_oss_devin
 
 
 /*
- * Wait until the queue is empty (if we don't have nonblock)
- */
-void
-snd_seq_oss_drain_write(struct seq_oss_devinfo *dp)
-{
- if (! dp->timer->running)
- return;
- if (is_write_mode(dp->file_mode) && !is_nonblock_mode(dp->file_mode) &&
-    dp->writeq) {
- while (snd_seq_oss_writeq_sync(dp->writeq))
- ;
- }
-}
-
-
-/*
  * reset sequencer devices
  */
 void


Reply | Threaded
Open this post in threaded view
|

[PATCH 4.4 49/74] ALSA: timer: Fix ioctls for X32 ABI

Greg KH-4
In reply to this post by Greg KH-4
4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Takashi Iwai <[hidden email]>

commit b24e7ad1fdc22177eb3e51584e1cfcb45d818488 upstream.

X32 ABI takes the 64bit timespec, thus the timer user status ioctl becomes
incompatible with IA32.  This results in NOTTY error when the ioctl is
issued.

Meanwhile, this struct in X32 is essentially identical with the one in
X86-64, so we can just bypassing to the existing code for this
specific compat ioctl.

Signed-off-by: Takashi Iwai <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>

---
 sound/core/timer_compat.c |   13 +++++++++++++
 1 file changed, 13 insertions(+)

--- a/sound/core/timer_compat.c
+++ b/sound/core/timer_compat.c
@@ -88,12 +88,21 @@ static int snd_timer_user_status_compat(
  return 0;
 }
 
+#ifdef CONFIG_X86_X32
+/* X32 ABI has the same struct as x86-64 */
+#define snd_timer_user_status_x32(file, s) \
+ snd_timer_user_status(file, s)
+#endif /* CONFIG_X86_X32 */
+
 /*
  */
 
 enum {
  SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32),
  SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct snd_timer_status32),
+#ifdef CONFIG_X86_X32
+ SNDRV_TIMER_IOCTL_STATUS_X32 = _IOW('T', 0x14, struct snd_timer_status),
+#endif /* CONFIG_X86_X32 */
 };
 
 static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
@@ -122,6 +131,10 @@ static long snd_timer_user_ioctl_compat(
  return snd_timer_user_info_compat(file, argp);
  case SNDRV_TIMER_IOCTL_STATUS32:
  return snd_timer_user_status_compat(file, argp);
+#ifdef CONFIG_X86_X32
+ case SNDRV_TIMER_IOCTL_STATUS_X32:
+ return snd_timer_user_status_x32(file, argp);
+#endif /* CONFIG_X86_X32 */
  }
  return -ENOIOCTLCMD;
 }


Reply | Threaded
Open this post in threaded view
|

[PATCH 4.4 48/74] ALSA: rawmidi: Fix ioctls X32 ABI

Greg KH-4
In reply to this post by Greg KH-4
4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Takashi Iwai <[hidden email]>

commit 2251fbbc1539f05b0b206b37a602d5776be37252 upstream.

Like the previous fixes for ctl and PCM, we need a fix for
incompatible X32 ABI regarding the rawmidi: namely, struct
snd_rawmidi_status has the timespec, and the size and the alignment on
X32 differ from IA32.

This patch fixes the incompatible ioctl for X32.

Signed-off-by: Takashi Iwai <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>

---
 sound/core/rawmidi_compat.c |   53 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

--- a/sound/core/rawmidi_compat.c
+++ b/sound/core/rawmidi_compat.c
@@ -94,9 +94,58 @@ static int snd_rawmidi_ioctl_status_comp
  return 0;
 }
 
+#ifdef CONFIG_X86_X32
+/* X32 ABI has 64bit timespec and 64bit alignment */
+struct snd_rawmidi_status_x32 {
+ s32 stream;
+ u32 rsvd; /* alignment */
+ struct timespec tstamp;
+ u32 avail;
+ u32 xruns;
+ unsigned char reserved[16];
+} __attribute__((packed));
+
+#define put_timespec(src, dst) copy_to_user(dst, src, sizeof(*dst))
+
+static int snd_rawmidi_ioctl_status_x32(struct snd_rawmidi_file *rfile,
+ struct snd_rawmidi_status_x32 __user *src)
+{
+ int err;
+ struct snd_rawmidi_status status;
+
+ if (rfile->output == NULL)
+ return -EINVAL;
+ if (get_user(status.stream, &src->stream))
+ return -EFAULT;
+
+ switch (status.stream) {
+ case SNDRV_RAWMIDI_STREAM_OUTPUT:
+ err = snd_rawmidi_output_status(rfile->output, &status);
+ break;
+ case SNDRV_RAWMIDI_STREAM_INPUT:
+ err = snd_rawmidi_input_status(rfile->input, &status);
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (err < 0)
+ return err;
+
+ if (put_timespec(&status.tstamp, &src->tstamp) ||
+    put_user(status.avail, &src->avail) ||
+    put_user(status.xruns, &src->xruns))
+ return -EFAULT;
+
+ return 0;
+}
+#endif /* CONFIG_X86_X32 */
+
 enum {
  SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32),
  SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct snd_rawmidi_status32),
+#ifdef CONFIG_X86_X32
+ SNDRV_RAWMIDI_IOCTL_STATUS_X32 = _IOWR('W', 0x20, struct snd_rawmidi_status_x32),
+#endif /* CONFIG_X86_X32 */
 };
 
 static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
@@ -115,6 +164,10 @@ static long snd_rawmidi_ioctl_compat(str
  return snd_rawmidi_ioctl_params_compat(rfile, argp);
  case SNDRV_RAWMIDI_IOCTL_STATUS32:
  return snd_rawmidi_ioctl_status_compat(rfile, argp);
+#ifdef CONFIG_X86_X32
+ case SNDRV_RAWMIDI_IOCTL_STATUS_X32:
+ return snd_rawmidi_ioctl_status_x32(rfile, argp);
+#endif /* CONFIG_X86_X32 */
  }
  return -ENOIOCTLCMD;
 }


Reply | Threaded
Open this post in threaded view
|

[PATCH 4.4 47/74] ALSA: hda - Fix mic issues on Acer Aspire E1-472

Greg KH-4
In reply to this post by Greg KH-4
4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Simon South <[hidden email]>

commit 02322ac9dee9aff8d8862e8d6660ebe102f492ea upstream.

This patch applies the microphone-related fix created for the Acer
Aspire E1-572 to the E1-472 as well, as it uses the same Realtek ALC282
CODEC and demonstrates the same issues.

This patch allows an external, headset microphone to be used and limits
the gain on the (quite noisy) internal microphone.

Signed-off-by: Simon South <[hidden email]>
Signed-off-by: Takashi Iwai <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>

---
 sound/pci/hda/patch_realtek.c |    1 +
 1 file changed, 1 insertion(+)

--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -5386,6 +5386,7 @@ static const struct snd_pci_quirk alc269
  SND_PCI_QUIRK(0x1025, 0x080d, "Acer Aspire V5-122P", ALC269_FIXUP_ASPIRE_HEADSET_MIC),
  SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK),
  SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK),
+ SND_PCI_QUIRK(0x1025, 0x0762, "Acer Aspire E1-472", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
  SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
  SND_PCI_QUIRK(0x1025, 0x079b, "Acer Aspire V5-573G", ALC282_FIXUP_ASPIRE_V5_PINS),
  SND_PCI_QUIRK(0x1025, 0x106d, "Acer Cloudbook 14", ALC283_FIXUP_CHROME_BOOK),


Reply | Threaded
Open this post in threaded view
|

[PATCH 4.4 20/74] iommu/amd: Fix boot warning when device 00:00.0 is not iommu covered

Greg KH-4
In reply to this post by Greg KH-4
4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Suravee Suthikulpanit <[hidden email]>

commit 38e45d02ea9f194b89d6bf41e52ccafc8e2c2b47 upstream.

The setup code for the performance counters in the AMD IOMMU driver
tests whether the counters can be written. It tests to setup a counter
for device 00:00.0, which fails on systems where this particular device
is not covered by the IOMMU.

Fix this by not relying on device 00:00.0 but only on the IOMMU being
present.

Signed-off-by: Suravee Suthikulpanit <[hidden email]>
Signed-off-by: Joerg Roedel <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>

---
 drivers/iommu/amd_iommu_init.c |   34 ++++++++++++++++++++++------------
 1 file changed, 22 insertions(+), 12 deletions(-)

--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -228,6 +228,10 @@ static int amd_iommu_enable_interrupts(v
 static int __init iommu_go_to_state(enum iommu_init_state state);
 static void init_device_table_dma(void);
 
+static int iommu_pc_get_set_reg_val(struct amd_iommu *iommu,
+    u8 bank, u8 cntr, u8 fxn,
+    u64 *value, bool is_write);
+
 static inline void update_last_devid(u16 devid)
 {
  if (devid > amd_iommu_last_bdf)
@@ -1170,8 +1174,8 @@ static void init_iommu_perf_ctr(struct a
  amd_iommu_pc_present = true;
 
  /* Check if the performance counters can be written to */
- if ((0 != amd_iommu_pc_get_set_reg_val(0, 0, 0, 0, &val, true)) ||
-    (0 != amd_iommu_pc_get_set_reg_val(0, 0, 0, 0, &val2, false)) ||
+ if ((0 != iommu_pc_get_set_reg_val(iommu, 0, 0, 0, &val, true)) ||
+    (0 != iommu_pc_get_set_reg_val(iommu, 0, 0, 0, &val2, false)) ||
     (val != val2)) {
  pr_err("AMD-Vi: Unable to write to IOMMU perf counter.\n");
  amd_iommu_pc_present = false;
@@ -2312,22 +2316,15 @@ u8 amd_iommu_pc_get_max_counters(u16 dev
 }
 EXPORT_SYMBOL(amd_iommu_pc_get_max_counters);
 
-int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn,
+static int iommu_pc_get_set_reg_val(struct amd_iommu *iommu,
+    u8 bank, u8 cntr, u8 fxn,
     u64 *value, bool is_write)
 {
- struct amd_iommu *iommu;
  u32 offset;
  u32 max_offset_lim;
 
- /* Make sure the IOMMU PC resource is available */
- if (!amd_iommu_pc_present)
- return -ENODEV;
-
- /* Locate the iommu associated with the device ID */
- iommu = amd_iommu_rlookup_table[devid];
-
  /* Check for valid iommu and pc register indexing */
- if (WARN_ON((iommu == NULL) || (fxn > 0x28) || (fxn & 7)))
+ if (WARN_ON((fxn > 0x28) || (fxn & 7)))
  return -ENODEV;
 
  offset = (u32)(((0x40|bank) << 12) | (cntr << 8) | fxn);
@@ -2351,3 +2348,16 @@ int amd_iommu_pc_get_set_reg_val(u16 dev
  return 0;
 }
 EXPORT_SYMBOL(amd_iommu_pc_get_set_reg_val);
+
+int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn,
+    u64 *value, bool is_write)
+{
+ struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
+
+ /* Make sure the IOMMU PC resource is available */
+ if (!amd_iommu_pc_present || iommu == NULL)
+ return -ENODEV;
+
+ return iommu_pc_get_set_reg_val(iommu, bank, cntr, fxn,
+ value, is_write);
+}


Reply | Threaded
Open this post in threaded view
|

[PATCH 4.4 46/74] ALSA: ctl: Fix ioctls for X32 ABI

Greg KH-4
In reply to this post by Greg KH-4
4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Takashi Iwai <[hidden email]>

commit 6236d8bb2afcfe71b88ecea554e0dc638090a45f upstream.

The X32 ABI takes the same alignment like x86-64, and this may result
in the incompatible struct size from ia32.  Unfortunately, we hit this
in some control ABI: struct snd_ctl_elem_value differs between them
due to the position of 64bit variable array.  This ends up with the
unknown ioctl (ENOTTY) error.

The fix is to add the compat entries for the new aligned struct.

Reported-and-tested-by: Steven Newbury <[hidden email]>
Signed-off-by: Takashi Iwai <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>

---
 sound/core/control_compat.c |   90 ++++++++++++++++++++++++++++++++++++--------
 1 file changed, 74 insertions(+), 16 deletions(-)

--- a/sound/core/control_compat.c
+++ b/sound/core/control_compat.c
@@ -170,6 +170,19 @@ struct snd_ctl_elem_value32 {
         unsigned char reserved[128];
 };
 
+#ifdef CONFIG_X86_X32
+/* x32 has a different alignment for 64bit values from ia32 */
+struct snd_ctl_elem_value_x32 {
+ struct snd_ctl_elem_id id;
+ unsigned int indirect; /* bit-field causes misalignment */
+ union {
+ s32 integer[128];
+ unsigned char data[512];
+ s64 integer64[64];
+ } value;
+ unsigned char reserved[128];
+};
+#endif /* CONFIG_X86_X32 */
 
 /* get the value type and count of the control */
 static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id,
@@ -219,9 +232,11 @@ static int get_elem_size(int type, int c
 
 static int copy_ctl_value_from_user(struct snd_card *card,
     struct snd_ctl_elem_value *data,
-    struct snd_ctl_elem_value32 __user *data32,
+    void __user *userdata,
+    void __user *valuep,
     int *typep, int *countp)
 {
+ struct snd_ctl_elem_value32 __user *data32 = userdata;
  int i, type, size;
  int uninitialized_var(count);
  unsigned int indirect;
@@ -239,8 +254,9 @@ static int copy_ctl_value_from_user(stru
  if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
     type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
  for (i = 0; i < count; i++) {
+ s32 __user *intp = valuep;
  int val;
- if (get_user(val, &data32->value.integer[i]))
+ if (get_user(val, &intp[i]))
  return -EFAULT;
  data->value.integer.value[i] = val;
  }
@@ -250,8 +266,7 @@ static int copy_ctl_value_from_user(stru
  dev_err(card->dev, "snd_ioctl32_ctl_elem_value: unknown type %d\n", type);
  return -EINVAL;
  }
- if (copy_from_user(data->value.bytes.data,
-   data32->value.data, size))
+ if (copy_from_user(data->value.bytes.data, valuep, size))
  return -EFAULT;
  }
 
@@ -261,7 +276,8 @@ static int copy_ctl_value_from_user(stru
 }
 
 /* restore the value to 32bit */
-static int copy_ctl_value_to_user(struct snd_ctl_elem_value32 __user *data32,
+static int copy_ctl_value_to_user(void __user *userdata,
+  void __user *valuep,
   struct snd_ctl_elem_value *data,
   int type, int count)
 {
@@ -270,22 +286,22 @@ static int copy_ctl_value_to_user(struct
  if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
     type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
  for (i = 0; i < count; i++) {
+ s32 __user *intp = valuep;
  int val;
  val = data->value.integer.value[i];
- if (put_user(val, &data32->value.integer[i]))
+ if (put_user(val, &intp[i]))
  return -EFAULT;
  }
  } else {
  size = get_elem_size(type, count);
- if (copy_to_user(data32->value.data,
- data->value.bytes.data, size))
+ if (copy_to_user(valuep, data->value.bytes.data, size))
  return -EFAULT;
  }
  return 0;
 }
 
-static int snd_ctl_elem_read_user_compat(struct snd_card *card,
- struct snd_ctl_elem_value32 __user *data32)
+static int ctl_elem_read_user(struct snd_card *card,
+      void __user *userdata, void __user *valuep)
 {
  struct snd_ctl_elem_value *data;
  int err, type, count;
@@ -294,7 +310,9 @@ static int snd_ctl_elem_read_user_compat
  if (data == NULL)
  return -ENOMEM;
 
- if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0)
+ err = copy_ctl_value_from_user(card, data, userdata, valuep,
+       &type, &count);
+ if (err < 0)
  goto error;
 
  snd_power_lock(card);
@@ -303,14 +321,15 @@ static int snd_ctl_elem_read_user_compat
  err = snd_ctl_elem_read(card, data);
  snd_power_unlock(card);
  if (err >= 0)
- err = copy_ctl_value_to_user(data32, data, type, count);
+ err = copy_ctl_value_to_user(userdata, valuep, data,
+     type, count);
  error:
  kfree(data);
  return err;
 }
 
-static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file,
-  struct snd_ctl_elem_value32 __user *data32)
+static int ctl_elem_write_user(struct snd_ctl_file *file,
+       void __user *userdata, void __user *valuep)
 {
  struct snd_ctl_elem_value *data;
  struct snd_card *card = file->card;
@@ -320,7 +339,9 @@ static int snd_ctl_elem_write_user_compa
  if (data == NULL)
  return -ENOMEM;
 
- if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0)
+ err = copy_ctl_value_from_user(card, data, userdata, valuep,
+       &type, &count);
+ if (err < 0)
  goto error;
 
  snd_power_lock(card);
@@ -329,12 +350,39 @@ static int snd_ctl_elem_write_user_compa
  err = snd_ctl_elem_write(card, file, data);
  snd_power_unlock(card);
  if (err >= 0)
- err = copy_ctl_value_to_user(data32, data, type, count);
+ err = copy_ctl_value_to_user(userdata, valuep, data,
+     type, count);
  error:
  kfree(data);
  return err;
 }
 
+static int snd_ctl_elem_read_user_compat(struct snd_card *card,
+ struct snd_ctl_elem_value32 __user *data32)
+{
+ return ctl_elem_read_user(card, data32, &data32->value);
+}
+
+static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file,
+  struct snd_ctl_elem_value32 __user *data32)
+{
+ return ctl_elem_write_user(file, data32, &data32->value);
+}
+
+#ifdef CONFIG_X86_X32
+static int snd_ctl_elem_read_user_x32(struct snd_card *card,
+      struct snd_ctl_elem_value_x32 __user *data32)
+{
+ return ctl_elem_read_user(card, data32, &data32->value);
+}
+
+static int snd_ctl_elem_write_user_x32(struct snd_ctl_file *file,
+       struct snd_ctl_elem_value_x32 __user *data32)
+{
+ return ctl_elem_write_user(file, data32, &data32->value);
+}
+#endif /* CONFIG_X86_X32 */
+
 /* add or replace a user control */
 static int snd_ctl_elem_add_compat(struct snd_ctl_file *file,
    struct snd_ctl_elem_info32 __user *data32,
@@ -393,6 +441,10 @@ enum {
  SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct snd_ctl_elem_value32),
  SNDRV_CTL_IOCTL_ELEM_ADD32 = _IOWR('U', 0x17, struct snd_ctl_elem_info32),
  SNDRV_CTL_IOCTL_ELEM_REPLACE32 = _IOWR('U', 0x18, struct snd_ctl_elem_info32),
+#ifdef CONFIG_X86_X32
+ SNDRV_CTL_IOCTL_ELEM_READ_X32 = _IOWR('U', 0x12, struct snd_ctl_elem_value_x32),
+ SNDRV_CTL_IOCTL_ELEM_WRITE_X32 = _IOWR('U', 0x13, struct snd_ctl_elem_value_x32),
+#endif /* CONFIG_X86_X32 */
 };
 
 static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
@@ -431,6 +483,12 @@ static inline long snd_ctl_ioctl_compat(
  return snd_ctl_elem_add_compat(ctl, argp, 0);
  case SNDRV_CTL_IOCTL_ELEM_REPLACE32:
  return snd_ctl_elem_add_compat(ctl, argp, 1);
+#ifdef CONFIG_X86_X32
+ case SNDRV_CTL_IOCTL_ELEM_READ_X32:
+ return snd_ctl_elem_read_user_x32(ctl->card, argp);
+ case SNDRV_CTL_IOCTL_ELEM_WRITE_X32:
+ return snd_ctl_elem_write_user_x32(ctl, argp);
+#endif /* CONFIG_X86_X32 */
  }
 
  down_read(&snd_ioctl_rwsem);


Reply | Threaded
Open this post in threaded view
|

[PATCH 4.4 44/74] [media] adv7604: fix tx 5v detect regression

Greg KH-4
In reply to this post by Greg KH-4
4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Hans Verkuil <[hidden email]>

commit 0ba4581c84cfb39fd527f6b3457f1c97f6356c04 upstream.

The 5 volt detect functionality broke in 3.14: the code reads IO register 0x70
again after it has already been cleared. Instead it should use the cached
irq_reg_0x70 value and the io_write to 0x71 to clear 0x70 can be dropped since
this has already been done.

Signed-off-by: Hans Verkuil <[hidden email]>
Signed-off-by: Mauro Carvalho Chehab <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>

---
 drivers/media/i2c/adv7604.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -1960,10 +1960,9 @@ static int adv76xx_isr(struct v4l2_subde
  }
 
  /* tx 5v detect */
- tx_5v = io_read(sd, 0x70) & info->cable_det_mask;
+ tx_5v = irq_reg_0x70 & info->cable_det_mask;
  if (tx_5v) {
  v4l2_dbg(1, debug, sd, "%s: tx_5v: 0x%x\n", __func__, tx_5v);
- io_write(sd, 0x71, tx_5v);
  adv76xx_s_detect_tx_5v_ctrl(sd);
  if (handled)
  *handled = true;


Reply | Threaded
Open this post in threaded view
|

[PATCH 4.4 45/74] ALSA: usb-audio: Add a quirk for Plantronics DA45

Greg KH-4
In reply to this post by Greg KH-4
4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Dennis Kadioglu <[hidden email]>

commit 17e2df4613be57d0fab68df749f6b8114e453152 upstream.

Plantronics DA45 does not support reading the sample rate which leads
to many lines of "cannot get freq at ep 0x4" and "cannot get freq at
ep 0x84". This patch adds the USB ID of the DA45 to quirks.c and
avoids those error messages.

Signed-off-by: Dennis Kadioglu <[hidden email]>
Signed-off-by: Takashi Iwai <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>

---
 sound/usb/quirks.c |    1 +
 1 file changed, 1 insertion(+)

--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1124,6 +1124,7 @@ bool snd_usb_get_sample_rate_quirk(struc
  case USB_ID(0x045E, 0x076F): /* MS Lifecam HD-6000 */
  case USB_ID(0x045E, 0x0772): /* MS Lifecam Studio */
  case USB_ID(0x045E, 0x0779): /* MS Lifecam HD-3000 */
+ case USB_ID(0x047F, 0xAA05): /* Plantronics DA45 */
  case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */
  case USB_ID(0x074D, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */
  case USB_ID(0x21B4, 0x0081): /* AudioQuest DragonFly */


Reply | Threaded
Open this post in threaded view
|

[PATCH 4.4 43/74] dmaengine: pxa_dma: fix cyclic transfers

Greg KH-4
In reply to this post by Greg KH-4
4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Robert Jarzmik <[hidden email]>

commit f16921275cc3c2442d0b95225785a601603b990f upstream.

While testing audio with pxa2xx-ac97, underrun were happening while the
user application was correctly feeding the music. Debug proved that the
cyclic transfer is not cyclic, ie. the last descriptor did not loop on
the first.

Another issue is that the descriptor length was always set to 8192,
because of an trivial operator issue.

This was tested on a pxa27x platform.

Fixes: a57e16cf0333 ("dmaengine: pxa: add pxa dmaengine driver")
Reported-by: Vasily Khoruzhick <[hidden email]>
Tested-by: Vasily Khoruzhick <[hidden email]>
Signed-off-by: Robert Jarzmik <[hidden email]>
Signed-off-by: Vinod Koul <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>

---
 drivers/dma/pxa_dma.c |    8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

--- a/drivers/dma/pxa_dma.c
+++ b/drivers/dma/pxa_dma.c
@@ -583,6 +583,8 @@ static void set_updater_desc(struct pxad
  (PXA_DCMD_LENGTH & sizeof(u32));
  if (flags & DMA_PREP_INTERRUPT)
  updater->dcmd |= PXA_DCMD_ENDIRQEN;
+ if (sw_desc->cyclic)
+ sw_desc->hw_desc[sw_desc->nb_desc - 2]->ddadr = sw_desc->first;
 }
 
 static bool is_desc_completed(struct virt_dma_desc *vd)
@@ -673,6 +675,10 @@ static irqreturn_t pxad_chan_handler(int
  dev_dbg(&chan->vc.chan.dev->device,
  "%s(): checking txd %p[%x]: completed=%d\n",
  __func__, vd, vd->tx.cookie, is_desc_completed(vd));
+ if (to_pxad_sw_desc(vd)->cyclic) {
+ vchan_cyclic_callback(vd);
+ break;
+ }
  if (is_desc_completed(vd)) {
  list_del(&vd->node);
  vchan_cookie_complete(vd);
@@ -1080,7 +1086,7 @@ pxad_prep_dma_cyclic(struct dma_chan *dc
  return NULL;
 
  pxad_get_config(chan, dir, &dcmd, &dsadr, &dtadr);
- dcmd |= PXA_DCMD_ENDIRQEN | (PXA_DCMD_LENGTH | period_len);
+ dcmd |= PXA_DCMD_ENDIRQEN | (PXA_DCMD_LENGTH & period_len);
  dev_dbg(&chan->vc.chan.dev->device,
  "%s(): buf_addr=0x%lx len=%zu period=%zu dir=%d flags=%lx\n",
  __func__, (unsigned long)buf_addr, len, period_len, dir, flags);


Reply | Threaded
Open this post in threaded view
|

[PATCH 4.4 40/74] Revert "jffs2: Fix lock acquisition order bug in jffs2_write_begin"

Greg KH-4
In reply to this post by Greg KH-4
4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Thomas Betker <[hidden email]>

commit 157078f64b8a9cd7011b6b900b2f2498df850748 upstream.

This reverts commit 5ffd3412ae55
("jffs2: Fix lock acquisition order bug in jffs2_write_begin").

The commit modified jffs2_write_begin() to remove a deadlock with
jffs2_garbage_collect_live(), but this introduced new deadlocks found
by multiple users. page_lock() actually has to be called before
mutex_lock(&c->alloc_sem) or mutex_lock(&f->sem) because
jffs2_write_end() and jffs2_readpage() are called with the page locked,
and they acquire c->alloc_sem and f->sem, resp.

In other words, the lock order in jffs2_write_begin() was correct, and
it is the jffs2_garbage_collect_live() path that has to be changed.

Revert the commit to get rid of the new deadlocks, and to clear the way
for a better fix of the original deadlock.

Reported-by: Deng Chao <[hidden email]>
Reported-by: Ming Liu <[hidden email]>
Reported-by: wangzaiwei <[hidden email]>
Signed-off-by: Thomas Betker <[hidden email]>
Signed-off-by: David Woodhouse <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>

---
 fs/jffs2/file.c |   39 ++++++++++++++++++---------------------
 1 file changed, 18 insertions(+), 21 deletions(-)

--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -137,39 +137,33 @@ static int jffs2_write_begin(struct file
  struct page *pg;
  struct inode *inode = mapping->host;
  struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
- struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
- struct jffs2_raw_inode ri;
- uint32_t alloc_len = 0;
  pgoff_t index = pos >> PAGE_CACHE_SHIFT;
  uint32_t pageofs = index << PAGE_CACHE_SHIFT;
  int ret = 0;
 
- jffs2_dbg(1, "%s()\n", __func__);
-
- if (pageofs > inode->i_size) {
- ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
-  ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
- if (ret)
- return ret;
- }
-
- mutex_lock(&f->sem);
  pg = grab_cache_page_write_begin(mapping, index, flags);
- if (!pg) {
- if (alloc_len)
- jffs2_complete_reservation(c);
- mutex_unlock(&f->sem);
+ if (!pg)
  return -ENOMEM;
- }
  *pagep = pg;
 
- if (alloc_len) {
+ jffs2_dbg(1, "%s()\n", __func__);
+
+ if (pageofs > inode->i_size) {
  /* Make new hole frag from old EOF to new page */
+ struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
+ struct jffs2_raw_inode ri;
  struct jffs2_full_dnode *fn;
+ uint32_t alloc_len;
 
  jffs2_dbg(1, "Writing new hole frag 0x%x-0x%x between current EOF and new page\n",
   (unsigned int)inode->i_size, pageofs);
 
+ ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
+  ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
+ if (ret)
+ goto out_page;
+
+ mutex_lock(&f->sem);
  memset(&ri, 0, sizeof(ri));
 
  ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -196,6 +190,7 @@ static int jffs2_write_begin(struct file
  if (IS_ERR(fn)) {
  ret = PTR_ERR(fn);
  jffs2_complete_reservation(c);
+ mutex_unlock(&f->sem);
  goto out_page;
  }
  ret = jffs2_add_full_dnode_to_inode(c, f, fn);
@@ -210,10 +205,12 @@ static int jffs2_write_begin(struct file
  jffs2_mark_node_obsolete(c, fn->raw);
  jffs2_free_full_dnode(fn);
  jffs2_complete_reservation(c);
+ mutex_unlock(&f->sem);
  goto out_page;
  }
  jffs2_complete_reservation(c);
  inode->i_size = pageofs;
+ mutex_unlock(&f->sem);
  }
 
  /*
@@ -222,18 +219,18 @@ static int jffs2_write_begin(struct file
  * case of a short-copy.
  */
  if (!PageUptodate(pg)) {
+ mutex_lock(&f->sem);
  ret = jffs2_do_readpage_nolock(inode, pg);
+ mutex_unlock(&f->sem);
  if (ret)
  goto out_page;
  }
- mutex_unlock(&f->sem);
  jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags);
  return ret;
 
 out_page:
  unlock_page(pg);
  page_cache_release(pg);
- mutex_unlock(&f->sem);
  return ret;
 }
 


Reply | Threaded
Open this post in threaded view
|

[PATCH 4.4 74/74] drm/amdgpu: fix topaz/tonga gmc assignment in 4.4 stable

Greg KH-4
In reply to this post by Greg KH-4
4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Alex Deucher <[hidden email]>

When upstream commit 429c45deae6e57f1bb91bfb05b671063fb0cef60
was applied to 4.4 as d60703ca942e8d044d61360bc9792fcab54b95d0
it applied incorrectly to the tonga_ip_blocks array rather than
the topaz_ip_blocks array.  Fix that up here.

Bug:
https://bugzilla.kernel.org/show_bug.cgi?id=113951

Signed-off-by: Alex Deucher <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>
---
 drivers/gpu/drm/amd/amdgpu/vi.c |   12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

--- a/drivers/gpu/drm/amd/amdgpu/vi.c
+++ b/drivers/gpu/drm/amd/amdgpu/vi.c
@@ -1082,10 +1082,10 @@ static const struct amdgpu_ip_block_vers
  },
  {
  .type = AMD_IP_BLOCK_TYPE_GMC,
- .major = 8,
- .minor = 0,
+ .major = 7,
+ .minor = 4,
  .rev = 0,
- .funcs = &gmc_v8_0_ip_funcs,
+ .funcs = &gmc_v7_0_ip_funcs,
  },
  {
  .type = AMD_IP_BLOCK_TYPE_IH,
@@ -1129,10 +1129,10 @@ static const struct amdgpu_ip_block_vers
  },
  {
  .type = AMD_IP_BLOCK_TYPE_GMC,
- .major = 7,
- .minor = 4,
+ .major = 8,
+ .minor = 0,
  .rev = 0,
- .funcs = &gmc_v7_0_ip_funcs,
+ .funcs = &gmc_v8_0_ip_funcs,
  },
  {
  .type = AMD_IP_BLOCK_TYPE_IH,


Reply | Threaded
Open this post in threaded view
|

[PATCH 4.4 65/74] ubi: Fix out of bounds write in volume update code

Greg KH-4
In reply to this post by Greg KH-4
4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Richard Weinberger <[hidden email]>

commit e4f6daac20332448529b11f09388f1d55ef2084c upstream.

ubi_start_leb_change() allocates too few bytes.
ubi_more_leb_change_data() will write up to req->upd_bytes +
ubi->min_io_size bytes.

Signed-off-by: Richard Weinberger <[hidden email]>
Reviewed-by: Boris Brezillon <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>

---
 drivers/mtd/ubi/upd.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/mtd/ubi/upd.c
+++ b/drivers/mtd/ubi/upd.c
@@ -193,7 +193,7 @@ int ubi_start_leb_change(struct ubi_devi
  vol->changing_leb = 1;
  vol->ch_lnum = req->lnum;
 
- vol->upd_buf = vmalloc(req->bytes);
+ vol->upd_buf = vmalloc(ALIGN((int)req->bytes, ubi->min_io_size));
  if (!vol->upd_buf)
  return -ENOMEM;
 


Reply | Threaded
Open this post in threaded view
|

[PATCH 4.4 73/74] modules: fix longstanding /proc/kallsyms vs module insertion race.

Greg KH-4
In reply to this post by Greg KH-4
4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Rusty Russell <[hidden email]>

commit 8244062ef1e54502ef55f54cced659913f244c3e upstream.

For CONFIG_KALLSYMS, we keep two symbol tables and two string tables.
There's one full copy, marked SHF_ALLOC and laid out at the end of the
module's init section.  There's also a cut-down version that only
contains core symbols and strings, and lives in the module's core
section.

After module init (and before we free the module memory), we switch
the mod->symtab, mod->num_symtab and mod->strtab to point to the core
versions.  We do this under the module_mutex.

However, kallsyms doesn't take the module_mutex: it uses
preempt_disable() and rcu tricks to walk through the modules, because
it's used in the oops path.  It's also used in /proc/kallsyms.
There's nothing atomic about the change of these variables, so we can
get the old (larger!) num_symtab and the new symtab pointer; in fact
this is what I saw when trying to reproduce.

By grouping these variables together, we can use a
carefully-dereferenced pointer to ensure we always get one or the
other (the free of the module init section is already done in an RCU
callback, so that's safe).  We allocate the init one at the end of the
module init section, and keep the core one inside the struct module
itself (it could also have been allocated at the end of the module
core, but that's probably overkill).

[ Rebased for 4.4-stable and older, because the following changes aren't
  in the older trees:
  - e0224418516b4d8a6c2160574bac18447c354ef0: adds arg to is_core_symbol
  - 7523e4dc5057e157212b4741abd6256e03404cf1: module_init/module_core/init_size/core_size
    become init_layout.base/core_layout.base/init_layout.size/core_layout.size.
]

Reported-by: Weilong Chen <[hidden email]>
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=111541
Cc: [hidden email]
Signed-off-by: Rusty Russell <[hidden email]>
Signed-off-by: Greg Kroah-Hartman <[hidden email]>


---
 include/linux/module.h |   19 ++++----
 kernel/module.c        |  112 ++++++++++++++++++++++++++++++-------------------
 2 files changed, 79 insertions(+), 52 deletions(-)

--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -302,6 +302,12 @@ struct mod_tree_node {
  struct latch_tree_node node;
 };
 
+struct mod_kallsyms {
+ Elf_Sym *symtab;
+ unsigned int num_symtab;
+ char *strtab;
+};
+
 struct module {
  enum module_state state;
 
@@ -411,15 +417,10 @@ struct module {
 #endif
 
 #ifdef CONFIG_KALLSYMS
- /*
- * We keep the symbol and string tables for kallsyms.
- * The core_* fields below are temporary, loader-only (they
- * could really be discarded after module init).
- */
- Elf_Sym *symtab, *core_symtab;
- unsigned int num_symtab, core_num_syms;
- char *strtab, *core_strtab;
-
+ /* Protected by RCU and/or module_mutex: use rcu_dereference() */
+ struct mod_kallsyms *kallsyms;
+ struct mod_kallsyms core_kallsyms;
+
  /* Section attributes */
  struct module_sect_attrs *sect_attrs;
 
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -327,6 +327,9 @@ struct load_info {
  struct _ddebug *debug;
  unsigned int num_debug;
  bool sig_ok;
+#ifdef CONFIG_KALLSYMS
+ unsigned long mod_kallsyms_init_off;
+#endif
  struct {
  unsigned int sym, str, mod, vers, info, pcpu;
  } index;
@@ -2492,10 +2495,21 @@ static void layout_symtab(struct module
  strsect->sh_flags |= SHF_ALLOC;
  strsect->sh_entsize = get_offset(mod, &mod->init_size, strsect,
  info->index.str) | INIT_OFFSET_MASK;
- mod->init_size = debug_align(mod->init_size);
  pr_debug("\t%s\n", info->secstrings + strsect->sh_name);
+
+ /* We'll tack temporary mod_kallsyms on the end. */
+ mod->init_size = ALIGN(mod->init_size,
+       __alignof__(struct mod_kallsyms));
+ info->mod_kallsyms_init_off = mod->init_size;
+ mod->init_size += sizeof(struct mod_kallsyms);
+ mod->init_size = debug_align(mod->init_size);
 }
 
+/*
+ * We use the full symtab and strtab which layout_symtab arranged to
+ * be appended to the init section.  Later we switch to the cut-down
+ * core-only ones.
+ */
 static void add_kallsyms(struct module *mod, const struct load_info *info)
 {
  unsigned int i, ndst;
@@ -2504,28 +2518,33 @@ static void add_kallsyms(struct module *
  char *s;
  Elf_Shdr *symsec = &info->sechdrs[info->index.sym];
 
- mod->symtab = (void *)symsec->sh_addr;
- mod->num_symtab = symsec->sh_size / sizeof(Elf_Sym);
+ /* Set up to point into init section. */
+ mod->kallsyms = mod->module_init + info->mod_kallsyms_init_off;
+
+ mod->kallsyms->symtab = (void *)symsec->sh_addr;
+ mod->kallsyms->num_symtab = symsec->sh_size / sizeof(Elf_Sym);
  /* Make sure we get permanent strtab: don't use info->strtab. */
- mod->strtab = (void *)info->sechdrs[info->index.str].sh_addr;
+ mod->kallsyms->strtab = (void *)info->sechdrs[info->index.str].sh_addr;
 
  /* Set types up while we still have access to sections. */
- for (i = 0; i < mod->num_symtab; i++)
- mod->symtab[i].st_info = elf_type(&mod->symtab[i], info);
-
- mod->core_symtab = dst = mod->module_core + info->symoffs;
- mod->core_strtab = s = mod->module_core + info->stroffs;
- src = mod->symtab;
- for (ndst = i = 0; i < mod->num_symtab; i++) {
+ for (i = 0; i < mod->kallsyms->num_symtab; i++)
+ mod->kallsyms->symtab[i].st_info
+ = elf_type(&mod->kallsyms->symtab[i], info);
+
+ /* Now populate the cut down core kallsyms for after init. */
+ mod->core_kallsyms.symtab = dst = mod->module_core + info->symoffs;
+ mod->core_kallsyms.strtab = s = mod->module_core + info->stroffs;
+ src = mod->kallsyms->symtab;
+ for (ndst = i = 0; i < mod->kallsyms->num_symtab; i++) {
  if (i == 0 ||
     is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) {
  dst[ndst] = src[i];
- dst[ndst++].st_name = s - mod->core_strtab;
- s += strlcpy(s, &mod->strtab[src[i].st_name],
+ dst[ndst++].st_name = s - mod->core_kallsyms.strtab;
+ s += strlcpy(s, &mod->kallsyms->strtab[src[i].st_name],
      KSYM_NAME_LEN) + 1;
  }
  }
- mod->core_num_syms = ndst;
+ mod->core_kallsyms.num_symtab = ndst;
 }
 #else
 static inline void layout_symtab(struct module *mod, struct load_info *info)
@@ -3274,9 +3293,8 @@ static noinline int do_init_module(struc
  module_put(mod);
  trim_init_extable(mod);
 #ifdef CONFIG_KALLSYMS
- mod->num_symtab = mod->core_num_syms;
- mod->symtab = mod->core_symtab;
- mod->strtab = mod->core_strtab;
+ /* Switch to core kallsyms now init is done: kallsyms may be walking! */
+ rcu_assign_pointer(mod->kallsyms, &mod->core_kallsyms);
 #endif
  mod_tree_remove_init(mod);
  unset_module_init_ro_nx(mod);
@@ -3646,9 +3664,9 @@ static inline int is_arm_mapping_symbol(
        && (str[2] == '\0' || str[2] == '.');
 }
 
-static const char *symname(struct module *mod, unsigned int symnum)
+static const char *symname(struct mod_kallsyms *kallsyms, unsigned int symnum)
 {
- return mod->strtab + mod->symtab[symnum].st_name;
+ return kallsyms->strtab + kallsyms->symtab[symnum].st_name;
 }
 
 static const char *get_ksymbol(struct module *mod,
@@ -3658,6 +3676,7 @@ static const char *get_ksymbol(struct mo
 {
  unsigned int i, best = 0;
  unsigned long nextval;
+ struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms);
 
  /* At worse, next value is at end of module */
  if (within_module_init(addr, mod))
@@ -3667,32 +3686,32 @@ static const char *get_ksymbol(struct mo
 
  /* Scan for closest preceding symbol, and next symbol. (ELF
    starts real symbols at 1). */
- for (i = 1; i < mod->num_symtab; i++) {
- if (mod->symtab[i].st_shndx == SHN_UNDEF)
+ for (i = 1; i < kallsyms->num_symtab; i++) {
+ if (kallsyms->symtab[i].st_shndx == SHN_UNDEF)
  continue;
 
  /* We ignore unnamed symbols: they're uninformative
  * and inserted at a whim. */
- if (*symname(mod, i) == '\0'
-    || is_arm_mapping_symbol(symname(mod, i)))
+ if (*symname(kallsyms, i) == '\0'
+    || is_arm_mapping_symbol(symname(kallsyms, i)))
  continue;
 
- if (mod->symtab[i].st_value <= addr
-    && mod->symtab[i].st_value > mod->symtab[best].st_value)
+ if (kallsyms->symtab[i].st_value <= addr
+    && kallsyms->symtab[i].st_value > kallsyms->symtab[best].st_value)
  best = i;
- if (mod->symtab[i].st_value > addr
-    && mod->symtab[i].st_value < nextval)
- nextval = mod->symtab[i].st_value;
+ if (kallsyms->symtab[i].st_value > addr
+    && kallsyms->symtab[i].st_value < nextval)
+ nextval = kallsyms->symtab[i].st_value;
  }
 
  if (!best)
  return NULL;
 
  if (size)
- *size = nextval - mod->symtab[best].st_value;
+ *size = nextval - kallsyms->symtab[best].st_value;
  if (offset)
- *offset = addr - mod->symtab[best].st_value;
- return symname(mod, best);
+ *offset = addr - kallsyms->symtab[best].st_value;
+ return symname(kallsyms, best);
 }
 
 /* For kallsyms to ask for address resolution.  NULL means not found.  Careful
@@ -3782,18 +3801,21 @@ int module_get_kallsym(unsigned int symn
 
  preempt_disable();
  list_for_each_entry_rcu(mod, &modules, list) {
+ struct mod_kallsyms *kallsyms;
+
  if (mod->state == MODULE_STATE_UNFORMED)
  continue;
- if (symnum < mod->num_symtab) {
- *value = mod->symtab[symnum].st_value;
- *type = mod->symtab[symnum].st_info;
- strlcpy(name, symname(mod, symnum), KSYM_NAME_LEN);
+ kallsyms = rcu_dereference_sched(mod->kallsyms);
+ if (symnum < kallsyms->num_symtab) {
+ *value = kallsyms->symtab[symnum].st_value;
+ *type = kallsyms->symtab[symnum].st_info;
+ strlcpy(name, symname(kallsyms, symnum), KSYM_NAME_LEN);
  strlcpy(module_name, mod->name, MODULE_NAME_LEN);
  *exported = is_exported(name, *value, mod);
  preempt_enable();
  return 0;
  }
- symnum -= mod->num_symtab;
+ symnum -= kallsyms->num_symtab;
  }
  preempt_enable();
  return -ERANGE;
@@ -3802,11 +3824,12 @@ int module_get_kallsym(unsigned int symn
 static unsigned long mod_find_symname(struct module *mod, const char *name)
 {
  unsigned int i;
+ struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms);
 
- for (i = 0; i < mod->num_symtab; i++)
- if (strcmp(name, symname(mod, i)) == 0 &&
-    mod->symtab[i].st_info != 'U')
- return mod->symtab[i].st_value;
+ for (i = 0; i < kallsyms->num_symtab; i++)
+ if (strcmp(name, symname(kallsyms, i)) == 0 &&
+    kallsyms->symtab[i].st_info != 'U')
+ return kallsyms->symtab[i].st_value;
  return 0;
 }
 
@@ -3845,11 +3868,14 @@ int module_kallsyms_on_each_symbol(int (
  module_assert_mutex();
 
  list_for_each_entry(mod, &modules, list) {
+ /* We hold module_mutex: no need for rcu_dereference_sched */
+ struct mod_kallsyms *kallsyms = mod->kallsyms;
+
  if (mod->state == MODULE_STATE_UNFORMED)
  continue;
- for (i = 0; i < mod->num_symtab; i++) {
- ret = fn(data, symname(mod, i),
- mod, mod->symtab[i].st_value);
+ for (i = 0; i < kallsyms->num_symtab; i++) {
+ ret = fn(data, symname(kallsyms, i),
+ mod, kallsyms->symtab[i].st_value);
  if (ret != 0)
  return ret;
  }


12345