Commit df1d6ea0 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

Merge tag 'y2038-alsa-v8-signed' of...

Merge tag 'y2038-alsa-v8-signed' of git://git.kernel.org:/pub/scm/linux/kernel/git/arnd/playground into for-next

ALSA: Fix year 2038 issue for sound subsystem

This is a series I worked on with Baolin in 2017 and 2018, but we
never quite managed to finish up the last pieces. During the
ALSA developer meetup at ELC-E 2018 in Edinburgh, a decision was
made to go with this approach for keeping best compatibility
with existing source code, and then I failed to follow up by
resending the patches.

Now I have patches for all remaining time_t uses in the kernel,
so it's absolutely time to revisit them. I have done more
review of the patches myself and found a couple of minor issues
that I have fixed up, otherwise the series is still the same as
before.

Conceptually, the idea of these patches is:

- 64-bit applications should see no changes at all, neither
  compile-time nor run-time.

- 32-bit code compiled with a 64-bit time_t currently
  does not work with ALSA, and requires kernel changes and/or
  sound/asound.h changes

- Most 32-bit code using these interfaces will work correctly
  on a modified kernel, with or without the uapi header changes.

- 32-bit code using SNDRV_TIMER_IOCTL_TREAD requires the
  updated header file for 64-bit time_t support

- 32-bit i386 user space with 64-bit time_t is broken for
  SNDRV_PCM_IOCTL_STATUS, SNDRV_RAWMIDI_IOCTL_STATUS and
  SNDRV_PCM_IOCTL_SYNC_PTR because of i386 alignment. This is also
  addressed by the updated uapi header.

- PCM mmap is currently supported on native x86 kernels
  (both 32-bit and 64-bit) but not for compat mode. This series breaks
  the 32-bit native mmap support for 32-bit time_t, but instead allows
  it for 64-bit time_t on both native and compat kernels. This seems to
  be the best trade-off, as mmap support is optional already, and most
  32-bit code runs in compat mode anyway.

- I've tried to avoid breaking compilation of 32-bit code
  as much as possible. Anything that does break however is likely code
  that is already broken on 64-bit time_t and needs source changes to
  fix them.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/arnd/playground.git y2038-alsa-v8
[2] https://lore.kernel.org/lkml/CAK8P3a2Os66+iwQYf97qh05W2JP8rmWao8zmKoHiXqVHvyYAJA@mail.gmail.com/T/#m6519cb07cfda08adf1dedea6596bb98892b4d5dc



Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>

Changes since v7: (Arnd):
 - Fix a typo found by Ben Hutchings

Changes since v6: (Arnd):
 - Add a patch to update the API versions
 - Hide a timespec reference in #ifndef __KERNEL__ to remove the
   last reference to time_t
 - Use a more readable way to do padding and describe it in the
   changelog
 - Rebase to linux-5.5-rc1, changing include/sound/soc-component.h
   and sound/drivers/aloop.c as needed.

Changes since v5 (Arnd):
 - Rebased to linux-5.4-rc4
 - Updated to completely remove timespec and time_t references from alsa
 - found and fixed a few bugs

Changes since v4 (Baolin):
 - Add patch 5 to change trigger_tstamp member of struct snd_pcm_runtime.
 - Add patch 8 to change internal timespec.
 - Add more explanation in commit message.
 - Use ktime_get_real_ts64() in patch 6.
 - Split common code out into a separate function in patch 6.
 - Fix tu->tread bug in patch 6 and remove #if __BITS_PER_LONG == 64 macro.

Changes since v3:
 - Move struct snd_pcm_status32 to pcm.h file.
 - Modify comments and commit message.
 - Add new patch2 ~ patch6.

Changes since v2:
 - Renamed all structures to make clear.
 - Remove CONFIG_X86_X32 macro and introduced new compat_snd_pcm_status64_x86_32.

Changes since v1:
 - Add one macro for struct snd_pcm_status_32 which only active in 32bits kernel.
 - Convert pcm_compat.c to use struct snd_pcm_status_64.
 - Convert pcm_native.c to use struct snd_pcm_status_64.
parents d8cac620 1cfaef96
Loading
Loading
Loading
Loading
+63 −11
Original line number Diff line number Diff line
@@ -44,6 +44,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 */
@@ -62,7 +63,7 @@ struct snd_pcm_ops {
	int (*sync_stop)(struct snd_pcm_substream *substream);
	snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *substream);
	int (*get_time_info)(struct snd_pcm_substream *substream,
			struct timespec *system_ts, struct timespec *audio_ts,
			struct timespec64 *system_ts, struct timespec64 *audio_ts,
			struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
			struct snd_pcm_audio_tstamp_report *audio_tstamp_report);
	int (*fill_silence)(struct snd_pcm_substream *substream, int channel,
@@ -343,7 +344,7 @@ static inline void snd_pcm_pack_audio_tstamp_report(__u32 *data, __u32 *accuracy
struct snd_pcm_runtime {
	/* -- Status -- */
	struct snd_pcm_substream *trigger_master;
	struct timespec trigger_tstamp;	/* trigger timestamp */
	struct timespec64 trigger_tstamp;	/* trigger timestamp */
	bool trigger_tstamp_latched;     /* trigger timestamp latched in low-level driver/hardware */
	int overrange;
	snd_pcm_uframes_t avail_max;
@@ -421,7 +422,7 @@ struct snd_pcm_runtime {
	/* -- audio timestamp config -- */
	struct snd_pcm_audio_tstamp_config audio_tstamp_config;
	struct snd_pcm_audio_tstamp_report audio_tstamp_report;
	struct timespec driver_tstamp;
	struct timespec64 driver_tstamp;

#if IS_ENABLED(CONFIG_SND_PCM_OSS)
	/* -- OSS things -- */
@@ -558,8 +559,8 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree);
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);
@@ -1155,22 +1156,22 @@ static inline void snd_pcm_set_runtime_buffer(struct snd_pcm_substream *substrea
}

/**
 * snd_pcm_gettime - Fill the timespec depending on the timestamp mode
 * snd_pcm_gettime - Fill the timespec64 depending on the timestamp mode
 * @runtime: PCM runtime instance
 * @tv: timespec to fill
 * @tv: timespec64 to fill
 */
static inline void snd_pcm_gettime(struct snd_pcm_runtime *runtime,
				   struct timespec *tv)
				   struct timespec64 *tv)
{
	switch (runtime->tstamp_type) {
	case SNDRV_PCM_TSTAMP_TYPE_MONOTONIC:
		ktime_get_ts(tv);
		ktime_get_ts64(tv);
		break;
	case SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW:
		getrawmonotonic(tv);
		ktime_get_raw_ts64(tv);
		break;
	default:
		getnstimeofday(tv);
		ktime_get_real_ts64(tv);
		break;
	}
}
@@ -1422,4 +1423,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[4];
	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 */
+2 −2
Original line number Diff line number Diff line
@@ -93,8 +93,8 @@ struct snd_soc_component_driver {
	snd_pcm_uframes_t (*pointer)(struct snd_soc_component *component,
				     struct snd_pcm_substream *substream);
	int (*get_time_info)(struct snd_soc_component *component,
		struct snd_pcm_substream *substream, struct timespec *system_ts,
		struct timespec *audio_ts,
		struct snd_pcm_substream *substream, struct timespec64 *system_ts,
		struct timespec64 *audio_ts,
		struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
		struct snd_pcm_audio_tstamp_report *audio_tstamp_report);
	int (*copy_user)(struct snd_soc_component *component,
+2 −2
Original line number Diff line number Diff line
@@ -89,7 +89,7 @@ struct snd_timer_instance {
			  unsigned long ticks, unsigned long resolution);
	void (*ccallback) (struct snd_timer_instance * timeri,
			   int event,
			   struct timespec * tstamp,
			   struct timespec64 * tstamp,
			   unsigned long resolution);
	void (*disconnect)(struct snd_timer_instance *timeri);
	void *callback_data;
@@ -113,7 +113,7 @@ struct snd_timer_instance {
 */

int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, struct snd_timer **rtimer);
void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstamp);
void snd_timer_notify(struct snd_timer *timer, int event, struct timespec64 *tstamp);
int snd_timer_global_new(char *id, int device, struct snd_timer **rtimer);
int snd_timer_global_free(struct snd_timer *timer);
int snd_timer_global_register(struct snd_timer *timer);
+129 −16
Original line number Diff line number Diff line
@@ -35,6 +35,8 @@
#include <time.h>
#endif

#include <asm/byteorder.h>

/*
 *  protocol version
 */
@@ -154,7 +156,7 @@ struct snd_hwdep_dsp_image {
 *                                                                           *
 *****************************************************************************/

#define SNDRV_PCM_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 14)
#define SNDRV_PCM_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 15)

typedef unsigned long snd_pcm_uframes_t;
typedef signed long snd_pcm_sframes_t;
@@ -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 {
@@ -456,8 +469,13 @@ enum {
	SNDRV_PCM_AUDIO_TSTAMP_TYPE_LAST = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED
};

#ifndef __KERNEL__
/* explicit padding avoids incompatibility between i386 and x86-64 */
typedef struct { unsigned char pad[sizeof(time_t) - sizeof(int)] __time_pad;

struct snd_pcm_status {
	snd_pcm_state_t state;		/* stream state */
	__time_pad pad1;		/* 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 */
@@ -473,17 +491,48 @@ struct snd_pcm_status {
	__u32 audio_tstamp_accuracy;	/* in ns units, only valid if indicated in audio_tstamp_data */
	unsigned char reserved[52-2*sizeof(struct timespec)]; /* must be filled with zero */
};
#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 */
};
@@ -492,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;
};
@@ -584,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)
@@ -614,7 +710,7 @@ enum {
 *  Raw MIDI section - /dev/snd/midi??
 */

#define SNDRV_RAWMIDI_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 0)
#define SNDRV_RAWMIDI_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 1)

enum {
	SNDRV_RAWMIDI_STREAM_OUTPUT = 0,
@@ -648,13 +744,16 @@ struct snd_rawmidi_params {
	unsigned char reserved[16];	/* reserved for future use */
};

#ifndef __KERNEL__
struct snd_rawmidi_status {
	int stream;
	__time_pad pad1;
	struct timespec tstamp;		/* Timestamp */
	size_t avail;			/* available bytes */
	size_t xruns;			/* count of overruns since last status (in bytes) */
	unsigned char reserved[16];	/* reserved for future use */
};
#endif

#define SNDRV_RAWMIDI_IOCTL_PVERSION	_IOR('W', 0x00, int)
#define SNDRV_RAWMIDI_IOCTL_INFO	_IOR('W', 0x01, struct snd_rawmidi_info)
@@ -667,7 +766,7 @@ struct snd_rawmidi_status {
 *  Timer section - /dev/snd/timer
 */

#define SNDRV_TIMER_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 6)
#define SNDRV_TIMER_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 7)

enum {
	SNDRV_TIMER_CLASS_NONE = -1,
@@ -761,6 +860,7 @@ struct snd_timer_params {
	unsigned char reserved[60];	/* reserved */
};

#ifndef __KERNEL__
struct snd_timer_status {
	struct timespec tstamp;		/* Timestamp - last update */
	unsigned int resolution;	/* current period resolution in ns */
@@ -769,10 +869,11 @@ struct snd_timer_status {
	unsigned int queue;		/* used queue size */
	unsigned char reserved[64];	/* reserved */
};
#endif

#define SNDRV_TIMER_IOCTL_PVERSION	_IOR('T', 0x00, int)
#define SNDRV_TIMER_IOCTL_NEXT_DEVICE	_IOWR('T', 0x01, struct snd_timer_id)
#define SNDRV_TIMER_IOCTL_TREAD		_IOW('T', 0x02, int)
#define SNDRV_TIMER_IOCTL_TREAD_OLD	_IOW('T', 0x02, int)
#define SNDRV_TIMER_IOCTL_GINFO		_IOWR('T', 0x03, struct snd_timer_ginfo)
#define SNDRV_TIMER_IOCTL_GPARAMS	_IOW('T', 0x04, struct snd_timer_gparams)
#define SNDRV_TIMER_IOCTL_GSTATUS	_IOWR('T', 0x05, struct snd_timer_gstatus)
@@ -785,6 +886,15 @@ struct snd_timer_status {
#define SNDRV_TIMER_IOCTL_STOP		_IO('T', 0xa1)
#define SNDRV_TIMER_IOCTL_CONTINUE	_IO('T', 0xa2)
#define SNDRV_TIMER_IOCTL_PAUSE		_IO('T', 0xa3)
#define SNDRV_TIMER_IOCTL_TREAD64	_IOW('T', 0xa4, int)

#if __BITS_PER_LONG == 64
#define SNDRV_TIMER_IOCTL_TREAD SNDRV_TIMER_IOCTL_TREAD_OLD
#else
#define SNDRV_TIMER_IOCTL_TREAD ((sizeof(__kernel_long_t) >= sizeof(time_t)) ? \
				 SNDRV_TIMER_IOCTL_TREAD_OLD : \
				 SNDRV_TIMER_IOCTL_TREAD64)
#endif

struct snd_timer_read {
	unsigned int resolution;
@@ -810,11 +920,15 @@ enum {
	SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10,
};

#ifndef __KERNEL__
struct snd_timer_tread {
	int event;
	__time_pad pad1;
	struct timespec tstamp;
	unsigned int val;
	__time_pad pad2;
};
#endif

/****************************************************************************
 *                                                                          *
@@ -955,8 +1069,7 @@ struct snd_ctl_elem_value {
		} bytes;
		struct snd_aes_iec958 iec958;
	} value;		/* RO */
	struct timespec tstamp;
	unsigned char reserved[128-sizeof(struct timespec)];
	unsigned char reserved[128];
};

struct snd_ctl_tlv {
+6 −6
Original line number Diff line number Diff line
@@ -443,7 +443,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);
@@ -453,17 +453,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);
Loading