diff mbox

[4/8] ALSA: Avoid using timespec for struct snd_pcm_status

Message ID 7809a25514e8f7f72a276d19414346b2e4100945.1524570852.git.baolin.wang@linaro.org (mailing list archive)
State New, archived
Headers show

Commit Message

(Exiting) Baolin Wang April 24, 2018, 12:06 p.m. UTC
The struct snd_pcm_status will use 'timespec' type variables to record
timestamp, which is not year 2038 safe on 32bits system.

Userspace will use SNDRV_PCM_IOCTL_STATUS and SNDRV_PCM_IOCTL_STATUS_EXT
as commands to issue ioctl() to fill the 'snd_pcm_status' structure in
userspace. The command number is always defined through _IOR/_IOW/IORW,
so when userspace changes the definition of 'struct timespec' to use
64-bit types, the command number also changes.

Thus in the kernel, we now need to define two versions of each such ioctl
and corresponding ioctl commands to handle 32bit time_t and 64bit time_t
in native mode:
struct snd_pcm_status32 {
	......

	s32 trigger_tstamp_sec;
	s32 trigger_tstamp_nsec;

	......

	s32 audio_tstamp_sec;
	s32 audio_tstamp_nsec;

	......
};

struct snd_pcm_status64 {
	......

	s32 trigger_tstamp_sec;
	s32 trigger_tstamp_nsec;

	......

	s32 audio_tstamp_sec;
	s32 audio_tstamp_nsec;

	......
};

Moreover in compat file, we renamed or introduced new structures to handle
32bit/64bit time_t in compatible mode. The 'struct snd_pcm_status32' and
snd_pcm_status_user32() are used to handle 32bit time_t in compat mode.
'struct compat_snd_pcm_status64' and snd_pcm_status_user_compat64() are used
to handle 64bit time_t.

Finally we can replace SNDRV_PCM_IOCTL_STATUS and SNDRV_PCM_IOCTL_STATUS_EXT
with new commands and introduce new functions to fill new 'struct snd_pcm_status64'
instead of using unsafe 'struct snd_pcm_status'. Then in future, the new
commands can be matched when userspace changes 'timespec' to 64bit type
to make a size change of 'struct snd_pcm_status'. When glibc changes time_t
to 64-bit, any recompiled program will issue ioctl commands that the kernel
does not understand without this patch.

Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
---
 include/sound/pcm.h         |   56 +++++++++++++++-
 include/uapi/sound/asound.h |    1 +
 sound/core/pcm.c            |   12 ++--
 sound/core/pcm_compat.c     |  154 +++++++++++++++----------------------------
 sound/core/pcm_native.c     |   96 ++++++++++++++++++++++-----
 5 files changed, 193 insertions(+), 126 deletions(-)

Comments

kernel test robot April 26, 2018, 9:20 a.m. UTC | #1
Hi Baolin,

I love your patch! Perhaps something to improve:

[auto build test WARNING on v4.17-rc2]
[cannot apply to sound/for-next asoc/for-next arm-soc/for-next next-20180426]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Baolin-Wang/Fix-year-2038-issue-for-sound-subsystem/20180426-010145
reproduce:
        # apt-get install sparse
        make ARCH=x86_64 allmodconfig
        make C=1 CF=-D__CHECK_ENDIAN__


sparse warnings: (new ones prefixed by >>)

   sound/core/pcm_native.c:561:51: sparse: incorrect type in assignment (different base types) @@    expected restricted snd_pcm_state_t [usertype] state @@    got t [usertype] state @@
   sound/core/pcm_native.c:561:51:    expected restricted snd_pcm_state_t [usertype] state
   sound/core/pcm_native.c:561:51:    got int [signed] state
   sound/core/pcm_native.c:726:38: sparse: incorrect type in argument 2 (different base types) @@    expected int [signed] state @@    got restricted snd_pcm_state_int [signed] state @@
   sound/core/pcm_native.c:726:38:    expected int [signed] state
   sound/core/pcm_native.c:726:38:    got restricted snd_pcm_state_t [usertype] <noident>
   sound/core/pcm_native.c:738:38: sparse: incorrect type in argument 2 (different base types) @@    expected int [signed] state @@    got restricted snd_pcm_state_int [signed] state @@
   sound/core/pcm_native.c:738:38:    expected int [signed] state
   sound/core/pcm_native.c:738:38:    got restricted snd_pcm_state_t [usertype] <noident>
   sound/core/pcm_native.c:787:38: sparse: incorrect type in argument 2 (different base types) @@    expected int [signed] state @@    got restricted snd_pcm_state_int [signed] state @@
   sound/core/pcm_native.c:787:38:    expected int [signed] state
   sound/core/pcm_native.c:787:38:    got restricted snd_pcm_state_t [usertype] <noident>
>> sound/core/pcm_native.c:995:34: sparse: incorrect type in initializer (different base types) @@    expected signed int [signed] [usertype] [explicitly-signed] state @@    got restricted ssigned int [signed] [usertype] [explicitly-signed] state @@
   sound/core/pcm_native.c:995:34:    expected signed int [signed] [usertype] [explicitly-signed] state
   sound/core/pcm_native.c:995:34:    got restricted snd_pcm_state_t [addressable] [assigned] [usertype] state
>> sound/core/pcm_native.c:1006:44: sparse: incorrect type in initializer (different base types) @@    expected signed int [signed] [usertype] [explicitly-signed] suspended_state @@    got restricted ssigned int [signed] [usertype] [explicitly-signed] suspended_state @@
   sound/core/pcm_native.c:1006:44:    expected signed int [signed] [usertype] [explicitly-signed] suspended_state
   sound/core/pcm_native.c:1006:44:    got restricted snd_pcm_state_t [addressable] [assigned] [usertype] suspended_state
   sound/core/pcm_native.c:1259:32: sparse: incorrect type in assignment (different base types) @@    expected restricted snd_pcm_state_t [usertype] state @@    got t [usertype] state @@
   sound/core/pcm_native.c:1259:32:    expected restricted snd_pcm_state_t [usertype] state
   sound/core/pcm_native.c:1259:32:    got int [signed] state
   sound/core/pcm_native.c:1283:31: sparse: incorrect type in argument 3 (different base types) @@    expected int [signed] state @@    got restricted snd_pcm_state_int [signed] state @@
   sound/core/pcm_native.c:1283:31:    expected int [signed] state
   sound/core/pcm_native.c:1283:31:    got restricted snd_pcm_state_t [usertype] <noident>
   sound/core/pcm_native.c:1290:40: sparse: incorrect type in argument 3 (different base types) @@    expected int [signed] state @@    got restricted snd_pcm_state_int [signed] state @@
   sound/core/pcm_native.c:1290:40:    expected int [signed] state
   sound/core/pcm_native.c:1290:40:    got restricted snd_pcm_state_t [usertype] <noident>
   sound/core/pcm_native.c:1316:28: sparse: restricted snd_pcm_state_t degrades to integer
   sound/core/pcm_native.c:1318:40: sparse: incorrect type in assignment (different base types) @@    expected restricted snd_pcm_state_t [usertype] state @@    got t [usertype] state @@
   sound/core/pcm_native.c:1318:40:    expected restricted snd_pcm_state_t [usertype] state
   sound/core/pcm_native.c:1318:40:    got int [signed] state
   sound/core/pcm_native.c:1342:64: sparse: incorrect type in argument 3 (different base types) @@    expected int [signed] state @@    got restricted snd_pcm_state_int [signed] state @@
   sound/core/pcm_native.c:1342:64:    expected int [signed] state
   sound/core/pcm_native.c:1342:64:    got restricted snd_pcm_state_t [usertype] state
   sound/core/pcm_native.c:1358:38: sparse: incorrect type in argument 3 (different base types) @@    expected int [signed] state @@    got restricted snd_pcm_state_int [signed] state @@
   sound/core/pcm_native.c:1358:38:    expected int [signed] state
   sound/core/pcm_native.c:1358:38:    got restricted snd_pcm_state_t [usertype] <noident>
   sound/core/pcm_native.c:1717:38: sparse: incorrect type in argument 2 (different base types) @@    expected int [signed] state @@    got restricted snd_pcm_state_int [signed] state @@
   sound/core/pcm_native.c:1717:38:    expected int [signed] state
   sound/core/pcm_native.c:1717:38:    got restricted snd_pcm_state_t [usertype] <noident>
   sound/core/pcm_native.c:1783:61: sparse: incorrect type in argument 2 (different base types) @@    expected int [signed] state @@    got restricted snd_pcm_state_int [signed] state @@
   sound/core/pcm_native.c:1783:61:    expected int [signed] state
   sound/core/pcm_native.c:1783:61:    got restricted snd_pcm_state_t [usertype] <noident>
   sound/core/pcm_native.c:1784:63: sparse: incorrect type in argument 2 (different base types) @@    expected int [signed] state @@    got restricted snd_pcm_state_int [signed] state @@
   sound/core/pcm_native.c:1784:63:    expected int [signed] state
   sound/core/pcm_native.c:1784:63:    got restricted snd_pcm_state_t [usertype] <noident>
   sound/core/pcm_native.c:1801:76: sparse: incorrect type in initializer (different base types) @@    expected int [signed] new_state @@    got restricted snint [signed] new_state @@
   sound/core/pcm_native.c:1801:76:    expected int [signed] new_state
   sound/core/pcm_native.c:1801:76:    got restricted snd_pcm_state_t
   sound/core/pcm_native.c:1904:40: sparse: expression using sizeof(void)
   sound/core/pcm_native.c:1904:40: sparse: expression using sizeof(void)
   sound/core/pcm_native.c:2122:26: sparse: restricted snd_pcm_format_t degrades to integer
   sound/core/pcm_native.c:2126:54: sparse: incorrect type in argument 1 (different base types) @@    expected restricted snd_pcm_format_t [usertype] format @@    got ricted snd_pcm_format_t [usertype] format @@
   sound/core/pcm_native.c:2126:54:    expected restricted snd_pcm_format_t [usertype] format
   sound/core/pcm_native.c:2126:54:    got unsigned int [unsigned] [assigned] k
   sound/core/pcm_native.c:2144:26: sparse: restricted snd_pcm_format_t degrades to integer
   sound/core/pcm_native.c:2148:54: sparse: incorrect type in argument 1 (different base types) @@    expected restricted snd_pcm_format_t [usertype] format @@    got ricted snd_pcm_format_t [usertype] format @@
   sound/core/pcm_native.c:2148:54:    expected restricted snd_pcm_format_t [usertype] format
   sound/core/pcm_native.c:2148:54:    got unsigned int [unsigned] [assigned] k
   sound/core/pcm_native.c:2328:30: sparse: restricted snd_pcm_access_t degrades to integer
   sound/core/pcm_native.c:2330:30: sparse: restricted snd_pcm_access_t degrades to integer
   sound/core/pcm_native.c:2333:38: sparse: restricted snd_pcm_access_t degrades to integer
   sound/core/pcm_native.c:2335:38: sparse: restricted snd_pcm_access_t degrades to integer
   sound/core/pcm_native.c:2337:38: sparse: restricted snd_pcm_access_t degrades to integer
   sound/core/pcm_native.c:2347:86: sparse: restricted snd_pcm_subformat_t degrades to integer
   include/sound/pcm.h:1093:47: sparse: cast removes address space of expression
   include/sound/pcm.h:1100:47: sparse: cast removes address space of expression
   include/sound/pcm.h:1100:47: sparse: cast removes address space of expression
   include/sound/pcm.h:1093:47: sparse: cast removes address space of expression
   sound/core/pcm_compat.c:241:32: sparse: incorrect type in initializer (different base types) @@    expected signed int [signed] [usertype] [explicitly-signed] state @@    got restricted ssigned int [signed] [usertype] [explicitly-signed] state @@
   sound/core/pcm_compat.c:241:32:    expected signed int [signed] [usertype] [explicitly-signed] state
   sound/core/pcm_compat.c:241:32:    got restricted snd_pcm_state_t [addressable] [assigned] [usertype] state
   sound/core/pcm_compat.c:252:42: sparse: incorrect type in initializer (different base types) @@    expected signed int [signed] [usertype] [explicitly-signed] suspended_state @@    got restricted ssigned int [signed] [usertype] [explicitly-signed] suspended_state @@
   sound/core/pcm_compat.c:252:42:    expected signed int [signed] [usertype] [explicitly-signed] suspended_state
   sound/core/pcm_compat.c:252:42:    got restricted snd_pcm_state_t [addressable] [assigned] [usertype] suspended_state
   include/sound/pcm.h:1093:47: sparse: cast removes address space of expression
   include/sound/pcm.h:1100:47: sparse: cast removes address space of expression
   sound/core/pcm_compat.c:480:13: sparse: incorrect type in assignment (different base types) @@    expected signed int [signed] [explicitly-signed] __pu_val @@    got restrictesigned int [signed] [explicitly-signed] __pu_val @@
   sound/core/pcm_compat.c:480:13:    expected signed int [signed] [explicitly-signed] __pu_val
   sound/core/pcm_compat.c:480:13:    got restricted snd_pcm_state_t [assigned] [usertype] state
   sound/core/pcm_compat.c:483:13: sparse: incorrect type in assignment (different base types) @@    expected signed int [signed] [explicitly-signed] __pu_val @@    got restrictesigned int [signed] [explicitly-signed] __pu_val @@
   sound/core/pcm_compat.c:483:13:    expected signed int [signed] [explicitly-signed] __pu_val
   sound/core/pcm_compat.c:483:13:    got restricted snd_pcm_state_t [assigned] [usertype] suspended_state
   sound/core/pcm_compat.c:569:13: sparse: incorrect type in assignment (different base types) @@    expected signed int [signed] [explicitly-signed] __pu_val @@    got restrictesigned int [signed] [explicitly-signed] __pu_val @@
   sound/core/pcm_compat.c:569:13:    expected signed int [signed] [explicitly-signed] __pu_val
   sound/core/pcm_compat.c:569:13:    got restricted snd_pcm_state_t [assigned] [usertype] state
   sound/core/pcm_compat.c:572:13: sparse: incorrect type in assignment (different base types) @@    expected signed int [signed] [explicitly-signed] __pu_val @@    got restrictesigned int [signed] [explicitly-signed] __pu_val @@
   sound/core/pcm_compat.c:572:13:    expected signed int [signed] [explicitly-signed] __pu_val
   sound/core/pcm_compat.c:572:13:    got restricted snd_pcm_state_t [assigned] [usertype] suspended_state
   sound/core/pcm_native.c:112:9: sparse: context imbalance in 'snd_pcm_stream_lock' - different lock contexts for basic block
   sound/core/pcm_native.c:134:28: sparse: context imbalance in 'snd_pcm_stream_unlock' - unexpected unlock
   sound/core/pcm_native.c:1130:52: sparse: context imbalance in 'snd_pcm_action_group' - unexpected unlock

vim +995 sound/core/pcm_native.c

   971	
   972	static int snd_pcm_status_user32(struct snd_pcm_substream *substream,
   973					 struct snd_pcm_status32 __user * _status,
   974					 bool ext)
   975	{
   976		struct snd_pcm_status64 status64;
   977		struct snd_pcm_status32 status32;
   978		int res;
   979	
   980		memset(&status64, 0, sizeof(status64));
   981		memset(&status32, 0, sizeof(status32));
   982		/*
   983		 * with extension, parameters are read/write,
   984		 * get audio_tstamp_data from user,
   985		 * ignore rest of status structure
   986		 */
   987		if (ext && get_user(status64.audio_tstamp_data,
   988				    (u32 __user *)(&_status->audio_tstamp_data)))
   989			return -EFAULT;
   990		res = snd_pcm_status64(substream, &status64);
   991		if (res < 0)
   992			return res;
   993	
   994		status32 = (struct snd_pcm_status32) {
 > 995			.state = status64.state,
   996			.trigger_tstamp_sec = status64.trigger_tstamp_sec,
   997			.trigger_tstamp_nsec = status64.trigger_tstamp_nsec,
   998			.tstamp_sec = status64.tstamp_sec,
   999			.tstamp_nsec = status64.tstamp_nsec,
  1000			.appl_ptr = status64.appl_ptr,
  1001			.hw_ptr = status64.hw_ptr,
  1002			.delay = status64.delay,
  1003			.avail = status64.avail,
  1004			.avail_max = status64.avail_max,
  1005			.overrange = status64.overrange,
> 1006			.suspended_state = status64.suspended_state,
  1007			.audio_tstamp_data = status64.audio_tstamp_data,
  1008			.audio_tstamp_sec = status64.audio_tstamp_sec,
  1009			.audio_tstamp_nsec = status64.audio_tstamp_nsec,
  1010			.driver_tstamp_sec = status64.audio_tstamp_sec,
  1011			.driver_tstamp_nsec = status64.audio_tstamp_nsec,
  1012			.audio_tstamp_accuracy = status64.audio_tstamp_accuracy,
  1013		};
  1014	
  1015		if (copy_to_user(_status, &status32, sizeof(status32)))
  1016			return -EFAULT;
  1017	
  1018		return 0;
  1019	}
  1020	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
(Exiting) Baolin Wang April 26, 2018, 10:53 a.m. UTC | #2
Hi Arnd,

On 26 April 2018 at 17:20, kbuild test robot <lkp@intel.com> wrote:
> Hi Baolin,
>
> I love your patch! Perhaps something to improve:
>
> [auto build test WARNING on v4.17-rc2]
> [cannot apply to sound/for-next asoc/for-next arm-soc/for-next next-20180426]
> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
>
> url:    https://github.com/0day-ci/linux/commits/Baolin-Wang/Fix-year-2038-issue-for-sound-subsystem/20180426-010145
> reproduce:
>         # apt-get install sparse
>         make ARCH=x86_64 allmodconfig
>         make C=1 CF=-D__CHECK_ENDIAN__
>
>
> sparse warnings: (new ones prefixed by >>)
>
>    sound/core/pcm_native.c:561:51: sparse: incorrect type in assignment (different base types) @@    expected restricted snd_pcm_state_t [usertype] state @@    got t [usertype] state @@
>    sound/core/pcm_native.c:561:51:    expected restricted snd_pcm_state_t [usertype] state
>    sound/core/pcm_native.c:561:51:    got int [signed] state
>    sound/core/pcm_native.c:726:38: sparse: incorrect type in argument 2 (different base types) @@    expected int [signed] state @@    got restricted snd_pcm_state_int [signed] state @@
>    sound/core/pcm_native.c:726:38:    expected int [signed] state
>    sound/core/pcm_native.c:726:38:    got restricted snd_pcm_state_t [usertype] <noident>
>    sound/core/pcm_native.c:738:38: sparse: incorrect type in argument 2 (different base types) @@    expected int [signed] state @@    got restricted snd_pcm_state_int [signed] state @@
>    sound/core/pcm_native.c:738:38:    expected int [signed] state
>    sound/core/pcm_native.c:738:38:    got restricted snd_pcm_state_t [usertype] <noident>
>    sound/core/pcm_native.c:787:38: sparse: incorrect type in argument 2 (different base types) @@    expected int [signed] state @@    got restricted snd_pcm_state_int [signed] state @@
>    sound/core/pcm_native.c:787:38:    expected int [signed] state
>    sound/core/pcm_native.c:787:38:    got restricted snd_pcm_state_t [usertype] <noident>
>>> sound/core/pcm_native.c:995:34: sparse: incorrect type in initializer (different base types) @@    expected signed int [signed] [usertype] [explicitly-signed] state @@    got restricted ssigned int [signed] [usertype] [explicitly-signed] state @@
>    sound/core/pcm_native.c:995:34:    expected signed int [signed] [usertype] [explicitly-signed] state
>    sound/core/pcm_native.c:995:34:    got restricted snd_pcm_state_t [addressable] [assigned] [usertype] state
>>> sound/core/pcm_native.c:1006:44: sparse: incorrect type in initializer (different base types) @@    expected signed int [signed] [usertype] [explicitly-signed] suspended_state @@    got restricted ssigned int [signed] [usertype] [explicitly-signed] suspended_state @@
>    sound/core/pcm_native.c:1006:44:    expected signed int [signed] [usertype] [explicitly-signed] suspended_state
>    sound/core/pcm_native.c:1006:44:    got restricted snd_pcm_state_t [addressable] [assigned] [usertype] suspended_state
>    sound/core/pcm_native.c:1259:32: sparse: incorrect type in assignment (different base types) @@    expected restricted snd_pcm_state_t [usertype] state @@    got t [usertype] state @@
>    sound/core/pcm_native.c:1259:32:    expected restricted snd_pcm_state_t [usertype] state
>    sound/core/pcm_native.c:1259:32:    got int [signed] state
>    sound/core/pcm_native.c:1283:31: sparse: incorrect type in argument 3 (different base types) @@    expected int [signed] state @@    got restricted snd_pcm_state_int [signed] state @@
>    sound/core/pcm_native.c:1283:31:    expected int [signed] state
>    sound/core/pcm_native.c:1283:31:    got restricted snd_pcm_state_t [usertype] <noident>
>    sound/core/pcm_native.c:1290:40: sparse: incorrect type in argument 3 (different base types) @@    expected int [signed] state @@    got restricted snd_pcm_state_int [signed] state @@
>    sound/core/pcm_native.c:1290:40:    expected int [signed] state
>    sound/core/pcm_native.c:1290:40:    got restricted snd_pcm_state_t [usertype] <noident>
>    sound/core/pcm_native.c:1316:28: sparse: restricted snd_pcm_state_t degrades to integer
>    sound/core/pcm_native.c:1318:40: sparse: incorrect type in assignment (different base types) @@    expected restricted snd_pcm_state_t [usertype] state @@    got t [usertype] state @@
>    sound/core/pcm_native.c:1318:40:    expected restricted snd_pcm_state_t [usertype] state
>    sound/core/pcm_native.c:1318:40:    got int [signed] state
>    sound/core/pcm_native.c:1342:64: sparse: incorrect type in argument 3 (different base types) @@    expected int [signed] state @@    got restricted snd_pcm_state_int [signed] state @@
>    sound/core/pcm_native.c:1342:64:    expected int [signed] state
>    sound/core/pcm_native.c:1342:64:    got restricted snd_pcm_state_t [usertype] state
>    sound/core/pcm_native.c:1358:38: sparse: incorrect type in argument 3 (different base types) @@    expected int [signed] state @@    got restricted snd_pcm_state_int [signed] state @@
>    sound/core/pcm_native.c:1358:38:    expected int [signed] state
>    sound/core/pcm_native.c:1358:38:    got restricted snd_pcm_state_t [usertype] <noident>
>    sound/core/pcm_native.c:1717:38: sparse: incorrect type in argument 2 (different base types) @@    expected int [signed] state @@    got restricted snd_pcm_state_int [signed] state @@
>    sound/core/pcm_native.c:1717:38:    expected int [signed] state
>    sound/core/pcm_native.c:1717:38:    got restricted snd_pcm_state_t [usertype] <noident>
>    sound/core/pcm_native.c:1783:61: sparse: incorrect type in argument 2 (different base types) @@    expected int [signed] state @@    got restricted snd_pcm_state_int [signed] state @@
>    sound/core/pcm_native.c:1783:61:    expected int [signed] state
>    sound/core/pcm_native.c:1783:61:    got restricted snd_pcm_state_t [usertype] <noident>
>    sound/core/pcm_native.c:1784:63: sparse: incorrect type in argument 2 (different base types) @@    expected int [signed] state @@    got restricted snd_pcm_state_int [signed] state @@
>    sound/core/pcm_native.c:1784:63:    expected int [signed] state
>    sound/core/pcm_native.c:1784:63:    got restricted snd_pcm_state_t [usertype] <noident>
>    sound/core/pcm_native.c:1801:76: sparse: incorrect type in initializer (different base types) @@    expected int [signed] new_state @@    got restricted snint [signed] new_state @@
>    sound/core/pcm_native.c:1801:76:    expected int [signed] new_state
>    sound/core/pcm_native.c:1801:76:    got restricted snd_pcm_state_t
>    sound/core/pcm_native.c:1904:40: sparse: expression using sizeof(void)
>    sound/core/pcm_native.c:1904:40: sparse: expression using sizeof(void)
>    sound/core/pcm_native.c:2122:26: sparse: restricted snd_pcm_format_t degrades to integer
>    sound/core/pcm_native.c:2126:54: sparse: incorrect type in argument 1 (different base types) @@    expected restricted snd_pcm_format_t [usertype] format @@    got ricted snd_pcm_format_t [usertype] format @@
>    sound/core/pcm_native.c:2126:54:    expected restricted snd_pcm_format_t [usertype] format
>    sound/core/pcm_native.c:2126:54:    got unsigned int [unsigned] [assigned] k
>    sound/core/pcm_native.c:2144:26: sparse: restricted snd_pcm_format_t degrades to integer
>    sound/core/pcm_native.c:2148:54: sparse: incorrect type in argument 1 (different base types) @@    expected restricted snd_pcm_format_t [usertype] format @@    got ricted snd_pcm_format_t [usertype] format @@
>    sound/core/pcm_native.c:2148:54:    expected restricted snd_pcm_format_t [usertype] format
>    sound/core/pcm_native.c:2148:54:    got unsigned int [unsigned] [assigned] k
>    sound/core/pcm_native.c:2328:30: sparse: restricted snd_pcm_access_t degrades to integer
>    sound/core/pcm_native.c:2330:30: sparse: restricted snd_pcm_access_t degrades to integer
>    sound/core/pcm_native.c:2333:38: sparse: restricted snd_pcm_access_t degrades to integer
>    sound/core/pcm_native.c:2335:38: sparse: restricted snd_pcm_access_t degrades to integer
>    sound/core/pcm_native.c:2337:38: sparse: restricted snd_pcm_access_t degrades to integer
>    sound/core/pcm_native.c:2347:86: sparse: restricted snd_pcm_subformat_t degrades to integer
>    include/sound/pcm.h:1093:47: sparse: cast removes address space of expression
>    include/sound/pcm.h:1100:47: sparse: cast removes address space of expression
>    include/sound/pcm.h:1100:47: sparse: cast removes address space of expression
>    include/sound/pcm.h:1093:47: sparse: cast removes address space of expression
>    sound/core/pcm_compat.c:241:32: sparse: incorrect type in initializer (different base types) @@    expected signed int [signed] [usertype] [explicitly-signed] state @@    got restricted ssigned int [signed] [usertype] [explicitly-signed] state @@
>    sound/core/pcm_compat.c:241:32:    expected signed int [signed] [usertype] [explicitly-signed] state
>    sound/core/pcm_compat.c:241:32:    got restricted snd_pcm_state_t [addressable] [assigned] [usertype] state
>    sound/core/pcm_compat.c:252:42: sparse: incorrect type in initializer (different base types) @@    expected signed int [signed] [usertype] [explicitly-signed] suspended_state @@    got restricted ssigned int [signed] [usertype] [explicitly-signed] suspended_state @@
>    sound/core/pcm_compat.c:252:42:    expected signed int [signed] [usertype] [explicitly-signed] suspended_state
>    sound/core/pcm_compat.c:252:42:    got restricted snd_pcm_state_t [addressable] [assigned] [usertype] suspended_state
>    include/sound/pcm.h:1093:47: sparse: cast removes address space of expression
>    include/sound/pcm.h:1100:47: sparse: cast removes address space of expression
>    sound/core/pcm_compat.c:480:13: sparse: incorrect type in assignment (different base types) @@    expected signed int [signed] [explicitly-signed] __pu_val @@    got restrictesigned int [signed] [explicitly-signed] __pu_val @@
>    sound/core/pcm_compat.c:480:13:    expected signed int [signed] [explicitly-signed] __pu_val
>    sound/core/pcm_compat.c:480:13:    got restricted snd_pcm_state_t [assigned] [usertype] state
>    sound/core/pcm_compat.c:483:13: sparse: incorrect type in assignment (different base types) @@    expected signed int [signed] [explicitly-signed] __pu_val @@    got restrictesigned int [signed] [explicitly-signed] __pu_val @@
>    sound/core/pcm_compat.c:483:13:    expected signed int [signed] [explicitly-signed] __pu_val
>    sound/core/pcm_compat.c:483:13:    got restricted snd_pcm_state_t [assigned] [usertype] suspended_state
>    sound/core/pcm_compat.c:569:13: sparse: incorrect type in assignment (different base types) @@    expected signed int [signed] [explicitly-signed] __pu_val @@    got restrictesigned int [signed] [explicitly-signed] __pu_val @@
>    sound/core/pcm_compat.c:569:13:    expected signed int [signed] [explicitly-signed] __pu_val
>    sound/core/pcm_compat.c:569:13:    got restricted snd_pcm_state_t [assigned] [usertype] state
>    sound/core/pcm_compat.c:572:13: sparse: incorrect type in assignment (different base types) @@    expected signed int [signed] [explicitly-signed] __pu_val @@    got restrictesigned int [signed] [explicitly-signed] __pu_val @@
>    sound/core/pcm_compat.c:572:13:    expected signed int [signed] [explicitly-signed] __pu_val
>    sound/core/pcm_compat.c:572:13:    got restricted snd_pcm_state_t [assigned] [usertype] suspended_state
>    sound/core/pcm_native.c:112:9: sparse: context imbalance in 'snd_pcm_stream_lock' - different lock contexts for basic block
>    sound/core/pcm_native.c:134:28: sparse: context imbalance in 'snd_pcm_stream_unlock' - unexpected unlock
>    sound/core/pcm_native.c:1130:52: sparse: context imbalance in 'snd_pcm_action_group' - unexpected unlock
>
> vim +995 sound/core/pcm_native.c
>
>    971
>    972  static int snd_pcm_status_user32(struct snd_pcm_substream *substream,
>    973                                   struct snd_pcm_status32 __user * _status,
>    974                                   bool ext)
>    975  {
>    976          struct snd_pcm_status64 status64;
>    977          struct snd_pcm_status32 status32;
>    978          int res;
>    979
>    980          memset(&status64, 0, sizeof(status64));
>    981          memset(&status32, 0, sizeof(status32));
>    982          /*
>    983           * with extension, parameters are read/write,
>    984           * get audio_tstamp_data from user,
>    985           * ignore rest of status structure
>    986           */
>    987          if (ext && get_user(status64.audio_tstamp_data,
>    988                              (u32 __user *)(&_status->audio_tstamp_data)))
>    989                  return -EFAULT;
>    990          res = snd_pcm_status64(substream, &status64);
>    991          if (res < 0)
>    992                  return res;
>    993
>    994          status32 = (struct snd_pcm_status32) {
>  > 995                  .state = status64.state,
>    996                  .trigger_tstamp_sec = status64.trigger_tstamp_sec,
>    997                  .trigger_tstamp_nsec = status64.trigger_tstamp_nsec,
>    998                  .tstamp_sec = status64.tstamp_sec,
>    999                  .tstamp_nsec = status64.tstamp_nsec,
>   1000                  .appl_ptr = status64.appl_ptr,
>   1001                  .hw_ptr = status64.hw_ptr,
>   1002                  .delay = status64.delay,
>   1003                  .avail = status64.avail,
>   1004                  .avail_max = status64.avail_max,
>   1005                  .overrange = status64.overrange,
>> 1006                  .suspended_state = status64.suspended_state,

I am not sure for the warning here, we should change 'snd_pcm_state_t'
to 's32' for struct snd_pcm_status64?

typedef int __bitwise snd_pcm_state_t;
Arnd Bergmann April 26, 2018, 12:50 p.m. UTC | #3
On Thu, Apr 26, 2018 at 12:53 PM, Baolin Wang <baolin.wang@linaro.org> wrote:

>>
>>    971
>>    972  static int snd_pcm_status_user32(struct snd_pcm_substream *substream,
>>    973                                   struct snd_pcm_status32 __user * _status,
>>    974                                   bool ext)
>>    975  {
>>    976          struct snd_pcm_status64 status64;
>>    977          struct snd_pcm_status32 status32;
>>    978          int res;
>>    979
>>    980          memset(&status64, 0, sizeof(status64));
>>    981          memset(&status32, 0, sizeof(status32));
>>    982          /*
>>    983           * with extension, parameters are read/write,
>>    984           * get audio_tstamp_data from user,
>>    985           * ignore rest of status structure
>>    986           */
>>    987          if (ext && get_user(status64.audio_tstamp_data,
>>    988                              (u32 __user *)(&_status->audio_tstamp_data)))
>>    989                  return -EFAULT;
>>    990          res = snd_pcm_status64(substream, &status64);
>>    991          if (res < 0)
>>    992                  return res;
>>    993
>>    994          status32 = (struct snd_pcm_status32) {
>>  > 995                  .state = status64.state,
>>    996                  .trigger_tstamp_sec = status64.trigger_tstamp_sec,
>>    997                  .trigger_tstamp_nsec = status64.trigger_tstamp_nsec,
>>    998                  .tstamp_sec = status64.tstamp_sec,
>>    999                  .tstamp_nsec = status64.tstamp_nsec,
>>   1000                  .appl_ptr = status64.appl_ptr,
>>   1001                  .hw_ptr = status64.hw_ptr,
>>   1002                  .delay = status64.delay,
>>   1003                  .avail = status64.avail,
>>   1004                  .avail_max = status64.avail_max,
>>   1005                  .overrange = status64.overrange,
>>> 1006                  .suspended_state = status64.suspended_state,
>
> I am not sure for the warning here, we should change 'snd_pcm_state_t'
> to 's32' for struct snd_pcm_status64?
>
> typedef int __bitwise snd_pcm_state_t;

The problem is that snd_pcm_status32 uses 'u32' here instead of snd_pcm_state_t,
and the __bitwise annotation makes the two types incompatible. This is a
preexisting problem, the warning mail just appeared because you moved that
code to a different file.

If you want to avoid that warning, either use a type case with '__force',
or change the snd_pcm_status32 structure to also use snd_pcm_state_t.

That would be a useful change, but it should be separate from your
other changes since it's an unrelated problem.

      Arnd
diff mbox

Patch

diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 973d674..398e81d 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -58,6 +58,7 @@  struct snd_pcm_hardware {
 	size_t fifo_size;		/* fifo size in bytes */
 };
 
+struct snd_pcm_status64;
 struct snd_pcm_substream;
 
 struct snd_pcm_audio_tstamp_config; /* definitions further down */
@@ -573,8 +574,8 @@  struct snd_pcm_notify {
 int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info);
 int snd_pcm_info_user(struct snd_pcm_substream *substream,
 		      struct snd_pcm_info __user *info);
-int snd_pcm_status(struct snd_pcm_substream *substream,
-		   struct snd_pcm_status *status);
+int snd_pcm_status64(struct snd_pcm_substream *substream,
+		     struct snd_pcm_status64 *status);
 int snd_pcm_start(struct snd_pcm_substream *substream);
 int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t status);
 int snd_pcm_drain_done(struct snd_pcm_substream *substream);
@@ -1448,4 +1449,55 @@  static inline u64 pcm_format_to_bits(snd_pcm_format_t pcm_format)
 #define pcm_dbg(pcm, fmt, args...) \
 	dev_dbg((pcm)->card->dev, fmt, ##args)
 
+struct snd_pcm_status64 {
+	snd_pcm_state_t state;		/* stream state */
+	u8 rsvd[sizeof(time_t) - sizeof(snd_pcm_state_t)];
+	s64 trigger_tstamp_sec;		/* time when stream was started/stopped/paused */
+	s64 trigger_tstamp_nsec;
+	s64 tstamp_sec;			/* reference timestamp */
+	s64 tstamp_nsec;
+	snd_pcm_uframes_t appl_ptr;	/* appl ptr */
+	snd_pcm_uframes_t hw_ptr;	/* hw ptr */
+	snd_pcm_sframes_t delay;	/* current delay in frames */
+	snd_pcm_uframes_t avail;	/* number of frames available */
+	snd_pcm_uframes_t avail_max;	/* max frames available on hw since last status */
+	snd_pcm_uframes_t overrange;	/* count of ADC (capture) overrange detections from last status */
+	snd_pcm_state_t suspended_state; /* suspended stream state */
+	__u32 audio_tstamp_data;	 /* needed for 64-bit alignment, used for configs/report to/from userspace */
+	s64 audio_tstamp_sec;		/* sample counter, wall clock, PHC or on-demand sync'ed */
+	s64 audio_tstamp_nsec;
+	s64 driver_tstamp_sec;		/* useful in case reference system tstamp is reported with delay */
+	s64 driver_tstamp_nsec;
+	__u32 audio_tstamp_accuracy;	/* in ns units, only valid if indicated in audio_tstamp_data */
+	unsigned char reserved[52-4*sizeof(s64)]; /* must be filled with zero */
+};
+
+#define SNDRV_PCM_IOCTL_STATUS64	_IOR('A', 0x20, struct snd_pcm_status64)
+#define SNDRV_PCM_IOCTL_STATUS_EXT64	_IOWR('A', 0x24, struct snd_pcm_status64)
+
+struct snd_pcm_status32 {
+	s32 state;		/* stream state */
+	s32 trigger_tstamp_sec;	/* time when stream was started/stopped/paused */
+	s32 trigger_tstamp_nsec;
+	s32 tstamp_sec;		/* reference timestamp */
+	s32 tstamp_nsec;
+	u32 appl_ptr;		/* appl ptr */
+	u32 hw_ptr;		/* hw ptr */
+	s32 delay;		/* current delay in frames */
+	u32 avail;		/* number of frames available */
+	u32 avail_max;		/* max frames available on hw since last status */
+	u32 overrange;		/* count of ADC (capture) overrange detections from last status */
+	s32 suspended_state;	/* suspended stream state */
+	u32 audio_tstamp_data;	/* needed for 64-bit alignment, used for configs/report to/from userspace */
+	s32 audio_tstamp_sec;	/* sample counter, wall clock, PHC or on-demand sync'ed */
+	s32 audio_tstamp_nsec;
+	s32 driver_tstamp_sec;	/* useful in case reference system tstamp is reported with delay */
+	s32 driver_tstamp_nsec;
+	u32 audio_tstamp_accuracy;	/* in ns units, only valid if indicated in audio_tstamp_data */
+	unsigned char reserved[52-4*sizeof(s32)]; /* must be filled with zero */
+};
+
+#define SNDRV_PCM_IOCTL_STATUS32	_IOR('A', 0x20, struct snd_pcm_status32)
+#define SNDRV_PCM_IOCTL_STATUS_EXT32	_IOWR('A', 0x24, struct snd_pcm_status32)
+
 #endif /* __SOUND_PCM_H */
diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h
index 1231f0a..c9afde4 100644
--- a/include/uapi/sound/asound.h
+++ b/include/uapi/sound/asound.h
@@ -457,6 +457,7 @@  enum {
 
 struct snd_pcm_status {
 	snd_pcm_state_t state;		/* stream state */
+	unsigned char pad1[sizeof(time_t) - sizeof(snd_pcm_state_t)]; /* align to timespec */
 	struct timespec trigger_tstamp;	/* time when stream was started/stopped/paused */
 	struct timespec tstamp;		/* reference timestamp */
 	snd_pcm_uframes_t appl_ptr;	/* appl ptr */
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 66ac89a..74d2580 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -456,7 +456,7 @@  static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
 {
 	struct snd_pcm_substream *substream = entry->private_data;
 	struct snd_pcm_runtime *runtime;
-	struct snd_pcm_status status;
+	struct snd_pcm_status64 status;
 	int err;
 
 	mutex_lock(&substream->pcm->open_mutex);
@@ -466,17 +466,17 @@  static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
 		goto unlock;
 	}
 	memset(&status, 0, sizeof(status));
-	err = snd_pcm_status(substream, &status);
+	err = snd_pcm_status64(substream, &status);
 	if (err < 0) {
 		snd_iprintf(buffer, "error %d\n", err);
 		goto unlock;
 	}
 	snd_iprintf(buffer, "state: %s\n", snd_pcm_state_name(status.state));
 	snd_iprintf(buffer, "owner_pid   : %d\n", pid_vnr(substream->pid));
-	snd_iprintf(buffer, "trigger_time: %ld.%09ld\n",
-		status.trigger_tstamp.tv_sec, status.trigger_tstamp.tv_nsec);
-	snd_iprintf(buffer, "tstamp      : %ld.%09ld\n",
-		status.tstamp.tv_sec, status.tstamp.tv_nsec);
+	snd_iprintf(buffer, "trigger_time: %lld.%09lld\n",
+		status.trigger_tstamp_sec, status.trigger_tstamp_nsec);
+	snd_iprintf(buffer, "tstamp      : %lld.%09lld\n",
+		status.tstamp_sec, status.tstamp_nsec);
 	snd_iprintf(buffer, "delay       : %ld\n", status.delay);
 	snd_iprintf(buffer, "avail       : %ld\n", status.avail);
 	snd_iprintf(buffer, "avail_max   : %ld\n", status.avail_max);
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
index b719d0b..a4ef13b 100644
--- a/sound/core/pcm_compat.c
+++ b/sound/core/pcm_compat.c
@@ -187,73 +187,13 @@  static int snd_pcm_channel_info_user(struct snd_pcm_substream *substream,
 	snd_pcm_channel_info_user(s, p)
 #endif /* CONFIG_X86_X32 */
 
-struct snd_pcm_status32 {
+struct compat_snd_pcm_status64 {
 	s32 state;
-	struct compat_timespec trigger_tstamp;
-	struct compat_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 compat_timespec audio_tstamp;
-	struct compat_timespec driver_tstamp;
-	u32 audio_tstamp_accuracy;
-	unsigned char reserved[52-2*sizeof(struct compat_timespec)];
-} __attribute__((packed));
-
-
-static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream,
-				      struct snd_pcm_status32 __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) ||
-	    compat_put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) ||
-	    compat_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) ||
-	    compat_put_timespec(&status.audio_tstamp, &src->audio_tstamp) ||
-	    compat_put_timespec(&status.driver_tstamp, &src->driver_tstamp) ||
-	    put_user(status.audio_tstamp_accuracy, &src->audio_tstamp_accuracy))
-		return -EFAULT;
-
-	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;
+	u8 rsvd[sizeof(time_t) - sizeof(s32)]; /* alignment */
+	s64 trigger_tstamp_sec;
+	s64 trigger_tstamp_nsec;
+	s64 tstamp_sec;
+	s64 tstamp_nsec;
 	u32 appl_ptr;
 	u32 hw_ptr;
 	s32 delay;
@@ -262,22 +202,26 @@  struct snd_pcm_status_x32 {
 	u32 overrange;
 	s32 suspended_state;
 	u32 audio_tstamp_data;
-	struct timespec audio_tstamp;
-	struct timespec driver_tstamp;
+	s64 audio_tstamp_sec;
+	s64 audio_tstamp_nsec;
+	s64 driver_tstamp_sec;
+	s64 driver_tstamp_nsec;
 	u32 audio_tstamp_accuracy;
-	unsigned char reserved[52-2*sizeof(struct timespec)];
+	unsigned char reserved[52-4*sizeof(s64)];
 } __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)
+static int snd_pcm_status_user_compat64(struct snd_pcm_substream *substream,
+					struct compat_snd_pcm_status64 __user *src,
+					bool ext)
 {
-	struct snd_pcm_status status;
+	struct snd_pcm_status64 status;
+	struct compat_snd_pcm_status64 compat_status64;
 	int err;
 
 	memset(&status, 0, sizeof(status));
+	memset(&compat_status64, 0, sizeof(compat_status64));
 	/*
 	 * with extension, parameters are read/write,
 	 * get audio_tstamp_data from user,
@@ -286,31 +230,39 @@  static int snd_pcm_status_user_x32(struct snd_pcm_substream *substream,
 	if (ext && get_user(status.audio_tstamp_data,
 				(u32 __user *)(&src->audio_tstamp_data)))
 		return -EFAULT;
-	err = snd_pcm_status(substream, &status);
+	err = snd_pcm_status64(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))
+
+	compat_status64 = (struct compat_snd_pcm_status64) {
+		.state = status.state,
+		.trigger_tstamp_sec = status.trigger_tstamp_sec,
+		.trigger_tstamp_nsec = status.trigger_tstamp_nsec,
+		.tstamp_sec = status.tstamp_sec,
+		.tstamp_nsec = status.tstamp_nsec,
+		.appl_ptr = status.appl_ptr,
+		.hw_ptr = status.hw_ptr,
+		.delay = status.delay,
+		.avail = status.avail,
+		.avail_max = status.avail_max,
+		.overrange = status.overrange,
+		.suspended_state = status.suspended_state,
+		.audio_tstamp_data = status.audio_tstamp_data,
+		.audio_tstamp_sec = status.audio_tstamp_sec,
+		.audio_tstamp_nsec = status.audio_tstamp_nsec,
+		.driver_tstamp_sec = status.audio_tstamp_sec,
+		.driver_tstamp_nsec = status.audio_tstamp_nsec,
+		.audio_tstamp_accuracy = status.audio_tstamp_accuracy,
+	};
+
+	if (copy_to_user(src, &compat_status64, sizeof(compat_status64)))
 		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,
@@ -633,8 +585,8 @@  enum {
 	SNDRV_PCM_IOCTL_HW_REFINE32 = _IOWR('A', 0x10, struct snd_pcm_hw_params32),
 	SNDRV_PCM_IOCTL_HW_PARAMS32 = _IOWR('A', 0x11, struct snd_pcm_hw_params32),
 	SNDRV_PCM_IOCTL_SW_PARAMS32 = _IOWR('A', 0x13, struct snd_pcm_sw_params32),
-	SNDRV_PCM_IOCTL_STATUS32 = _IOR('A', 0x20, struct snd_pcm_status32),
-	SNDRV_PCM_IOCTL_STATUS_EXT32 = _IOWR('A', 0x24, struct snd_pcm_status32),
+	SNDRV_PCM_IOCTL_STATUS_COMPAT32 = _IOR('A', 0x20, struct snd_pcm_status32),
+	SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT32 = _IOWR('A', 0x24, struct snd_pcm_status32),
 	SNDRV_PCM_IOCTL_DELAY32 = _IOR('A', 0x21, s32),
 	SNDRV_PCM_IOCTL_CHANNEL_INFO32 = _IOR('A', 0x32, struct snd_pcm_channel_info32),
 	SNDRV_PCM_IOCTL_REWIND32 = _IOW('A', 0x46, u32),
@@ -644,10 +596,10 @@  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),
+	SNDRV_PCM_IOCTL_STATUS_COMPAT64 = _IOR('A', 0x20, struct compat_snd_pcm_status64),
+	SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT64 = _IOWR('A', 0x24, struct compat_snd_pcm_status64),
 #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 */
 };
@@ -697,10 +649,10 @@  static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l
 		return snd_pcm_ioctl_hw_params_compat(substream, 0, argp);
 	case SNDRV_PCM_IOCTL_SW_PARAMS32:
 		return snd_pcm_ioctl_sw_params_compat(substream, argp);
-	case SNDRV_PCM_IOCTL_STATUS32:
-		return snd_pcm_status_user_compat(substream, argp, false);
-	case SNDRV_PCM_IOCTL_STATUS_EXT32:
-		return snd_pcm_status_user_compat(substream, argp, true);
+	case SNDRV_PCM_IOCTL_STATUS_COMPAT32:
+		return snd_pcm_status_user32(substream, argp, false);
+	case SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT32:
+		return snd_pcm_status_user32(substream, argp, true);
 	case SNDRV_PCM_IOCTL_SYNC_PTR32:
 		return snd_pcm_ioctl_sync_ptr_compat(substream, argp);
 	case SNDRV_PCM_IOCTL_CHANNEL_INFO32:
@@ -719,11 +671,11 @@  static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l
 		return snd_pcm_ioctl_rewind_compat(substream, argp);
 	case SNDRV_PCM_IOCTL_FORWARD32:
 		return snd_pcm_ioctl_forward_compat(substream, argp);
+	case SNDRV_PCM_IOCTL_STATUS_COMPAT64:
+		return snd_pcm_status_user_compat64(substream, argp, false);
+	case SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT64:
+		return snd_pcm_status_user_compat64(substream, argp, true);
 #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:
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index c57dd4b..0c2ec6d 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -857,8 +857,8 @@  static int snd_pcm_sw_params_user(struct snd_pcm_substream *substream,
 	return err;
 }
 
-int snd_pcm_status(struct snd_pcm_substream *substream,
-		   struct snd_pcm_status *status)
+int snd_pcm_status64(struct snd_pcm_substream *substream,
+		     struct snd_pcm_status64 *status)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 
@@ -884,14 +884,22 @@  int snd_pcm_status(struct snd_pcm_substream *substream,
 	status->suspended_state = runtime->status->suspended_state;
 	if (status->state == SNDRV_PCM_STATE_OPEN)
 		goto _end;
-	status->trigger_tstamp = timespec64_to_timespec(runtime->trigger_tstamp);
+	status->trigger_tstamp_sec = runtime->trigger_tstamp.tv_sec;
+	status->trigger_tstamp_nsec = runtime->trigger_tstamp.tv_nsec;
 	if (snd_pcm_running(substream)) {
 		snd_pcm_update_hw_ptr(substream);
 		if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
-			status->tstamp = runtime->status->tstamp;
-			status->driver_tstamp = timespec64_to_timespec(runtime->driver_tstamp);
-			status->audio_tstamp =
-				runtime->status->audio_tstamp;
+			status->tstamp_sec = runtime->status->tstamp.tv_sec;
+			status->tstamp_nsec =
+				runtime->status->tstamp.tv_nsec;
+			status->driver_tstamp_sec =
+				runtime->driver_tstamp.tv_sec;
+			status->driver_tstamp_nsec =
+				runtime->driver_tstamp.tv_nsec;
+			status->audio_tstamp_sec =
+				runtime->status->audio_tstamp.tv_sec;
+			status->audio_tstamp_nsec =
+				runtime->status->audio_tstamp.tv_nsec;
 			if (runtime->audio_tstamp_report.valid == 1)
 				/* backwards compatibility, no report provided in COMPAT mode */
 				snd_pcm_pack_audio_tstamp_report(&status->audio_tstamp_data,
@@ -906,7 +914,8 @@  int snd_pcm_status(struct snd_pcm_substream *substream,
 			struct timespec64 tstamp;
 
 			snd_pcm_gettime(runtime, &tstamp);
-			status->tstamp = timespec64_to_timespec(tstamp);
+			status->tstamp_sec = tstamp.tv_sec;
+			status->tstamp_nsec = tstamp.tv_nsec;
 		}
 	}
  _tstamp_end:
@@ -936,11 +945,11 @@  int snd_pcm_status(struct snd_pcm_substream *substream,
 	return 0;
 }
 
-static int snd_pcm_status_user(struct snd_pcm_substream *substream,
-			       struct snd_pcm_status __user * _status,
-			       bool ext)
+static int snd_pcm_status_user64(struct snd_pcm_substream *substream,
+				 struct snd_pcm_status64 __user * _status,
+				 bool ext)
 {
-	struct snd_pcm_status status;
+	struct snd_pcm_status64 status;
 	int res;
 
 	memset(&status, 0, sizeof(status));
@@ -952,7 +961,7 @@  static int snd_pcm_status_user(struct snd_pcm_substream *substream,
 	if (ext && get_user(status.audio_tstamp_data,
 				(u32 __user *)(&_status->audio_tstamp_data)))
 		return -EFAULT;
-	res = snd_pcm_status(substream, &status);
+	res = snd_pcm_status64(substream, &status);
 	if (res < 0)
 		return res;
 	if (copy_to_user(_status, &status, sizeof(status)))
@@ -960,6 +969,55 @@  static int snd_pcm_status_user(struct snd_pcm_substream *substream,
 	return 0;
 }
 
+static int snd_pcm_status_user32(struct snd_pcm_substream *substream,
+				 struct snd_pcm_status32 __user * _status,
+				 bool ext)
+{
+	struct snd_pcm_status64 status64;
+	struct snd_pcm_status32 status32;
+	int res;
+
+	memset(&status64, 0, sizeof(status64));
+	memset(&status32, 0, sizeof(status32));
+	/*
+	 * with extension, parameters are read/write,
+	 * get audio_tstamp_data from user,
+	 * ignore rest of status structure
+	 */
+	if (ext && get_user(status64.audio_tstamp_data,
+			    (u32 __user *)(&_status->audio_tstamp_data)))
+		return -EFAULT;
+	res = snd_pcm_status64(substream, &status64);
+	if (res < 0)
+		return res;
+
+	status32 = (struct snd_pcm_status32) {
+		.state = status64.state,
+		.trigger_tstamp_sec = status64.trigger_tstamp_sec,
+		.trigger_tstamp_nsec = status64.trigger_tstamp_nsec,
+		.tstamp_sec = status64.tstamp_sec,
+		.tstamp_nsec = status64.tstamp_nsec,
+		.appl_ptr = status64.appl_ptr,
+		.hw_ptr = status64.hw_ptr,
+		.delay = status64.delay,
+		.avail = status64.avail,
+		.avail_max = status64.avail_max,
+		.overrange = status64.overrange,
+		.suspended_state = status64.suspended_state,
+		.audio_tstamp_data = status64.audio_tstamp_data,
+		.audio_tstamp_sec = status64.audio_tstamp_sec,
+		.audio_tstamp_nsec = status64.audio_tstamp_nsec,
+		.driver_tstamp_sec = status64.audio_tstamp_sec,
+		.driver_tstamp_nsec = status64.audio_tstamp_nsec,
+		.audio_tstamp_accuracy = status64.audio_tstamp_accuracy,
+	};
+
+	if (copy_to_user(_status, &status32, sizeof(status32)))
+		return -EFAULT;
+
+	return 0;
+}
+
 static int snd_pcm_channel_info(struct snd_pcm_substream *substream,
 				struct snd_pcm_channel_info * info)
 {
@@ -2896,10 +2954,14 @@  static int snd_pcm_common_ioctl(struct file *file,
 		return snd_pcm_hw_free(substream);
 	case SNDRV_PCM_IOCTL_SW_PARAMS:
 		return snd_pcm_sw_params_user(substream, arg);
-	case SNDRV_PCM_IOCTL_STATUS:
-		return snd_pcm_status_user(substream, arg, false);
-	case SNDRV_PCM_IOCTL_STATUS_EXT:
-		return snd_pcm_status_user(substream, arg, true);
+	case SNDRV_PCM_IOCTL_STATUS32:
+		return snd_pcm_status_user32(substream, arg, false);
+	case SNDRV_PCM_IOCTL_STATUS_EXT32:
+		return snd_pcm_status_user32(substream, arg, true);
+	case SNDRV_PCM_IOCTL_STATUS64:
+		return snd_pcm_status_user64(substream, arg, false);
+	case SNDRV_PCM_IOCTL_STATUS_EXT64:
+		return snd_pcm_status_user64(substream, arg, true);
 	case SNDRV_PCM_IOCTL_CHANNEL_INFO:
 		return snd_pcm_channel_info_user(substream, arg);
 	case SNDRV_PCM_IOCTL_PREPARE: