summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '5.4/01_all_backport-5.6-alsa-timespec64-p6.patch')
-rw-r--r--5.4/01_all_backport-5.6-alsa-timespec64-p6.patch248
1 files changed, 248 insertions, 0 deletions
diff --git a/5.4/01_all_backport-5.6-alsa-timespec64-p6.patch b/5.4/01_all_backport-5.6-alsa-timespec64-p6.patch
new file mode 100644
index 0000000..0f7ed72
--- /dev/null
+++ b/5.4/01_all_backport-5.6-alsa-timespec64-p6.patch
@@ -0,0 +1,248 @@
+From 80fe7430c7085951d1246d83f638cc17e6c0be36 Mon Sep 17 00:00:00 2001
+From: Arnd Bergmann <arnd@arndb.de>
+Date: Tue, 24 Apr 2018 20:06:15 +0800
+Subject: [PATCH] ALSA: add new 32-bit layout for snd_pcm_mmap_status/control
+
+The snd_pcm_mmap_status and snd_pcm_mmap_control interfaces are one of the
+trickiest areas to get right when moving to 64-bit time_t in user space.
+
+The snd_pcm_mmap_status structure layout is incompatible with user space
+that uses a 64-bit time_t, so we need a new layout for it. Since the
+SNDRV_PCM_IOCTL_SYNC_PTR ioctl combines it with snd_pcm_mmap_control
+into snd_pcm_sync_ptr, we need to change those two as well.
+
+Both structures are also exported via an mmap() operation on certain
+architectures, and this suffers from incompatibility between 32-bit
+and 64-bit user space. As we have to change both structures anyway,
+this is a good opportunity to fix the mmap() problem as well, so let's
+standardize on the existing 64-bit layout of the structure where possible.
+
+The downside is that we lose mmap() support for existing 32-bit x86 and
+powerpc applications, adding that would introduce very noticeable runtime
+overhead and complexity. My assumption here is that not too many people
+will miss the removed feature, given that:
+
+- Almost all x86 and powerpc users these days are on 64-bit kernels,
+the majority of today's 32-bit users are on architectures that never
+supported mmap (ARM, MIPS, ...).
+- It never worked in compat mode (it was intentionally disabled there)
+- The application already needs to work with a fallback to
+SNDRV_PCM_IOCTL_SYNC_PTR, which will keep working with both the old
+and new structure layout.
+
+Both the ioctl() and mmap() based interfaces are changed at the same
+time, as they are based on the same structures. Unlike other interfaces,
+we change the uapi header to export both the traditional structure and
+a version that is portable between 32-bit and 64-bit user space code
+and that corresponds to the existing 64-bit layout. We further check the
+__USE_TIME_BITS64 macro that will be defined by future C library versions
+whenever we use the new time_t definition, so any existing user space
+source code will not see any changes until it gets rebuilt against a new
+C library. However, the new structures are all visible in addition to the
+old ones, allowing applications to explicitly request the new structures.
+
+In order to detect the difference between the old snd_pcm_mmap_status and
+the new __snd_pcm_mmap_status64 structure from the ioctl command number,
+we rely on one quirk in the structure definition: snd_pcm_mmap_status
+must be aligned to alignof(time_t), which leads the compiler to insert
+four bytes of padding in struct snd_pcm_sync_ptr after 'flags' and a
+corresponding change in the size of snd_pcm_sync_ptr itself. On x86-32
+(and only there), the compiler doesn't use 64-bit alignment in structure,
+so I'm adding an explicit pad in the structure that has no effect on the
+existing 64-bit architectures but ensures that the layout matches for x86.
+
+The snd_pcm_uframes_t type compatibility requires another hack: we can't
+easily make that 64 bit wide, so I leave the type as 'unsigned long',
+but add padding before and after it, to ensure that the data is properly
+aligned to the respective 64-bit field in the in-kernel structure.
+
+For the SNDRV_PCM_MMAP_OFFSET_STATUS/CONTROL constants that are used
+as the virtual file offset in the mmap() function, we also have to
+introduce new constants that depend on hte __USE_TIME_BITS64 macro:
+The existing macros are renamed to SNDRV_PCM_MMAP_OFFSET_STATUS_OLD
+and SNDRV_PCM_MMAP_OFFSET_CONTROL_OLD, they continue to work fine on
+64-bit architectures, but stop working on native 32-bit user space.
+The replacement _NEW constants are now used by default for user space
+built with __USE_TIME_BITS64, those now work on all new kernels for x86,
+ppc and alpha (32 and 64 bit, native and compat). It might be a good idea
+for a future alsa-lib to support both the _OLD and _NEW macros and use
+the corresponding structures directly. Unmodified alsa-lib source code
+will retain the current behavior, so it will no longer be able to use
+mmap() for the status/control structures on 32-bit systems, until either
+the C library gets updated to 64-bit time_t or alsa-lib gets updated to
+support both mmap() layouts.
+
+Co-developed-with: Baolin Wang <baolin.wang@linaro.org>
+Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+---
+ include/uapi/sound/asound.h | 110 ++++++++++++++++++++++++++++++++----
+
+--- a/include/uapi/sound/asound.h
++++ b/include/uapi/sound/asound.h
+@@ -35,6 +35,8 @@
+ #include <time.h>
+ #endif
+
++#include <asm/byteorder.h>
++
+ /*
+ * protocol version
+ */
+@@ -301,7 +303,9 @@ typedef int __bitwise snd_pcm_subformat_t;
+ #define SNDRV_PCM_INFO_DRAIN_TRIGGER 0x40000000 /* internal kernel flag - trigger in drain */
+ #define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000 /* internal kernel flag - FIFO size is in frames */
+
+-
++#if (__BITS_PER_LONG == 32 && defined(__USE_TIME_BITS64)) || defined __KERNEL__
++#define __SND_STRUCT_TIME64
++#endif
+
+ typedef int __bitwise snd_pcm_state_t;
+ #define SNDRV_PCM_STATE_OPEN ((__force snd_pcm_state_t) 0) /* stream is open */
+@@ -317,8 +321,17 @@ typedef int __bitwise snd_pcm_state_t;
+
+ enum {
+ SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000,
+- SNDRV_PCM_MMAP_OFFSET_STATUS = 0x80000000,
+- SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000,
++ SNDRV_PCM_MMAP_OFFSET_STATUS_OLD = 0x80000000,
++ SNDRV_PCM_MMAP_OFFSET_CONTROL_OLD = 0x81000000,
++ SNDRV_PCM_MMAP_OFFSET_STATUS_NEW = 0x82000000,
++ SNDRV_PCM_MMAP_OFFSET_CONTROL_NEW = 0x83000000,
++#ifdef __SND_STRUCT_TIME64
++ SNDRV_PCM_MMAP_OFFSET_STATUS = SNDRV_PCM_MMAP_OFFSET_STATUS_NEW,
++ SNDRV_PCM_MMAP_OFFSET_CONTROL = SNDRV_PCM_MMAP_OFFSET_CONTROL_NEW,
++#else
++ SNDRV_PCM_MMAP_OFFSET_STATUS = SNDRV_PCM_MMAP_OFFSET_STATUS_OLD,
++ SNDRV_PCM_MMAP_OFFSET_CONTROL = SNDRV_PCM_MMAP_OFFSET_CONTROL_OLD,
++#endif
+ };
+
+ union snd_pcm_sync_id {
+@@ -480,16 +493,46 @@ struct snd_pcm_status {
+ };
+ #endif
+
+-struct snd_pcm_mmap_status {
++/*
++ * For mmap operations, we need the 64-bit layout, both for compat mode,
++ * and for y2038 compatibility. For 64-bit applications, the two definitions
++ * are identical, so we keep the traditional version.
++ */
++#ifdef __SND_STRUCT_TIME64
++#define __snd_pcm_mmap_status64 snd_pcm_mmap_status
++#define __snd_pcm_mmap_control64 snd_pcm_mmap_control
++#define __snd_pcm_sync_ptr64 snd_pcm_sync_ptr
++#ifdef __KERNEL__
++#define __snd_timespec64 __kernel_timespec
++#else
++#define __snd_timespec64 timespec
++#endif
++struct __snd_timespec {
++ __s32 tv_sec;
++ __s32 tv_nsec;
++};
++#else
++#define __snd_pcm_mmap_status snd_pcm_mmap_status
++#define __snd_pcm_mmap_control snd_pcm_mmap_control
++#define __snd_pcm_sync_ptr snd_pcm_sync_ptr
++#define __snd_timespec timespec
++struct __snd_timespec64 {
++ __s64 tv_sec;
++ __s64 tv_nsec;
++};
++
++#endif
++
++struct __snd_pcm_mmap_status {
+ snd_pcm_state_t state; /* RO: state - SNDRV_PCM_STATE_XXXX */
+ int pad1; /* Needed for 64 bit alignment */
+ snd_pcm_uframes_t hw_ptr; /* RO: hw ptr (0...boundary-1) */
+- struct timespec tstamp; /* Timestamp */
++ struct __snd_timespec tstamp; /* Timestamp */
+ snd_pcm_state_t suspended_state; /* RO: suspended stream state */
+- struct timespec audio_tstamp; /* from sample counter or wall clock */
++ struct __snd_timespec audio_tstamp; /* from sample counter or wall clock */
+ };
+
+-struct snd_pcm_mmap_control {
++struct __snd_pcm_mmap_control {
+ snd_pcm_uframes_t appl_ptr; /* RW: appl ptr (0...boundary-1) */
+ snd_pcm_uframes_t avail_min; /* RW: min available frames for wakeup */
+ };
+@@ -498,14 +541,59 @@ struct snd_pcm_mmap_control {
+ #define SNDRV_PCM_SYNC_PTR_APPL (1<<1) /* get appl_ptr from driver (r/w op) */
+ #define SNDRV_PCM_SYNC_PTR_AVAIL_MIN (1<<2) /* get avail_min from driver */
+
+-struct snd_pcm_sync_ptr {
++struct __snd_pcm_sync_ptr {
+ unsigned int flags;
+ union {
+- struct snd_pcm_mmap_status status;
++ struct __snd_pcm_mmap_status status;
++ unsigned char reserved[64];
++ } s;
++ union {
++ struct __snd_pcm_mmap_control control;
++ unsigned char reserved[64];
++ } c;
++};
++
++#if defined(__BYTE_ORDER) ? __BYTE_ORDER == __BIG_ENDIAN : defined(__BIG_ENDIAN)
++typedef char __pad_before_uframe[sizeof(__u64) - sizeof(snd_pcm_uframes_t)];
++typedef char __pad_after_uframe[0];
++#endif
++
++#if defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : defined(__LITTLE_ENDIAN)
++typedef char __pad_before_uframe[0];
++typedef char __pad_after_uframe[sizeof(__u64) - sizeof(snd_pcm_uframes_t)];
++#endif
++
++struct __snd_pcm_mmap_status64 {
++ __s32 state; /* RO: state - SNDRV_PCM_STATE_XXXX */
++ __u32 pad1; /* Needed for 64 bit alignment */
++ __pad_before_uframe __pad1;
++ snd_pcm_uframes_t hw_ptr; /* RO: hw ptr (0...boundary-1) */
++ __pad_after_uframe __pad2;
++ struct __snd_timespec64 tstamp; /* Timestamp */
++ __s32 suspended_state; /* RO: suspended stream state */
++ __u32 pad3; /* Needed for 64 bit alignment */
++ struct __snd_timespec64 audio_tstamp; /* sample counter or wall clock */
++};
++
++struct __snd_pcm_mmap_control64 {
++ __pad_before_uframe __pad1;
++ snd_pcm_uframes_t appl_ptr; /* RW: appl ptr (0...boundary-1) */
++ __pad_before_uframe __pad2;
++
++ __pad_before_uframe __pad3;
++ snd_pcm_uframes_t avail_min; /* RW: min available frames for wakeup */
++ __pad_after_uframe __pad4;
++};
++
++struct __snd_pcm_sync_ptr64 {
++ __u32 flags;
++ __u32 pad1;
++ union {
++ struct __snd_pcm_mmap_status64 status;
+ unsigned char reserved[64];
+ } s;
+ union {
+- struct snd_pcm_mmap_control control;
++ struct __snd_pcm_mmap_control64 control;
+ unsigned char reserved[64];
+ } c;
+ };
+@@ -590,6 +678,8 @@ enum {
+ #define SNDRV_PCM_IOCTL_STATUS _IOR('A', 0x20, struct snd_pcm_status)
+ #define SNDRV_PCM_IOCTL_DELAY _IOR('A', 0x21, snd_pcm_sframes_t)
+ #define SNDRV_PCM_IOCTL_HWSYNC _IO('A', 0x22)
++#define __SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct __snd_pcm_sync_ptr)
++#define __SNDRV_PCM_IOCTL_SYNC_PTR64 _IOWR('A', 0x23, struct __snd_pcm_sync_ptr64)
+ #define SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct snd_pcm_sync_ptr)
+ #define SNDRV_PCM_IOCTL_STATUS_EXT _IOWR('A', 0x24, struct snd_pcm_status)
+ #define SNDRV_PCM_IOCTL_CHANNEL_INFO _IOR('A', 0x32, struct snd_pcm_channel_info)
+--
+2.26.2
+