Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

Merge branch 'for-linus' into for-next

Back-merge of for-linus branch for further API/ABI cleanups.
parents 0bbf7e02 b24e7ad1
Loading
Loading
Loading
Loading
+74 −16
Original line number Original line Diff line number Diff line
@@ -170,6 +170,19 @@ struct snd_ctl_elem_value32 {
        unsigned char reserved[128];
        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 */
/* get the value type and count of the control */
static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id,
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 count)


static int copy_ctl_value_from_user(struct snd_card *card,
static int copy_ctl_value_from_user(struct snd_card *card,
				    struct snd_ctl_elem_value *data,
				    struct snd_ctl_elem_value *data,
				    struct snd_ctl_elem_value32 __user *data32,
				    void __user *userdata,
				    void __user *valuep,
				    int *typep, int *countp)
				    int *typep, int *countp)
{
{
	struct snd_ctl_elem_value32 __user *data32 = userdata;
	int i, type, size;
	int i, type, size;
	int uninitialized_var(count);
	int uninitialized_var(count);
	unsigned int indirect;
	unsigned int indirect;
@@ -239,8 +254,9 @@ static int copy_ctl_value_from_user(struct snd_card *card,
	if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
	if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
	    type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
	    type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
		for (i = 0; i < count; i++) {
		for (i = 0; i < count; i++) {
			s32 __user *intp = valuep;
			int val;
			int val;
			if (get_user(val, &data32->value.integer[i]))
			if (get_user(val, &intp[i]))
				return -EFAULT;
				return -EFAULT;
			data->value.integer.value[i] = val;
			data->value.integer.value[i] = val;
		}
		}
@@ -250,8 +266,7 @@ static int copy_ctl_value_from_user(struct snd_card *card,
			dev_err(card->dev, "snd_ioctl32_ctl_elem_value: unknown type %d\n", type);
			dev_err(card->dev, "snd_ioctl32_ctl_elem_value: unknown type %d\n", type);
			return -EINVAL;
			return -EINVAL;
		}
		}
		if (copy_from_user(data->value.bytes.data,
		if (copy_from_user(data->value.bytes.data, valuep, size))
				   data32->value.data, size))
			return -EFAULT;
			return -EFAULT;
	}
	}


@@ -261,7 +276,8 @@ static int copy_ctl_value_from_user(struct snd_card *card,
}
}


/* restore the value to 32bit */
/* 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,
				  struct snd_ctl_elem_value *data,
				  int type, int count)
				  int type, int count)
{
{
@@ -270,22 +286,22 @@ static int copy_ctl_value_to_user(struct snd_ctl_elem_value32 __user *data32,
	if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
	if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
	    type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
	    type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
		for (i = 0; i < count; i++) {
		for (i = 0; i < count; i++) {
			s32 __user *intp = valuep;
			int val;
			int val;
			val = data->value.integer.value[i];
			val = data->value.integer.value[i];
			if (put_user(val, &data32->value.integer[i]))
			if (put_user(val, &intp[i]))
				return -EFAULT;
				return -EFAULT;
		}
		}
	} else {
	} else {
		size = get_elem_size(type, count);
		size = get_elem_size(type, count);
		if (copy_to_user(data32->value.data,
		if (copy_to_user(valuep, data->value.bytes.data, size))
				 data->value.bytes.data, size))
			return -EFAULT;
			return -EFAULT;
	}
	}
	return 0;
	return 0;
}
}


static int snd_ctl_elem_read_user_compat(struct snd_card *card, 
static int ctl_elem_read_user(struct snd_card *card,
					 struct snd_ctl_elem_value32 __user *data32)
			      void __user *userdata, void __user *valuep)
{
{
	struct snd_ctl_elem_value *data;
	struct snd_ctl_elem_value *data;
	int err, type, count;
	int err, type, count;
@@ -294,7 +310,9 @@ static int snd_ctl_elem_read_user_compat(struct snd_card *card,
	if (data == NULL)
	if (data == NULL)
		return -ENOMEM;
		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;
		goto error;


	snd_power_lock(card);
	snd_power_lock(card);
@@ -303,14 +321,15 @@ static int snd_ctl_elem_read_user_compat(struct snd_card *card,
		err = snd_ctl_elem_read(card, data);
		err = snd_ctl_elem_read(card, data);
	snd_power_unlock(card);
	snd_power_unlock(card);
	if (err >= 0)
	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:
 error:
	kfree(data);
	kfree(data);
	return err;
	return err;
}
}


static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file,
static int ctl_elem_write_user(struct snd_ctl_file *file,
					  struct snd_ctl_elem_value32 __user *data32)
			       void __user *userdata, void __user *valuep)
{
{
	struct snd_ctl_elem_value *data;
	struct snd_ctl_elem_value *data;
	struct snd_card *card = file->card;
	struct snd_card *card = file->card;
@@ -320,7 +339,9 @@ static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file,
	if (data == NULL)
	if (data == NULL)
		return -ENOMEM;
		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;
		goto error;


	snd_power_lock(card);
	snd_power_lock(card);
@@ -329,12 +350,39 @@ static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file,
		err = snd_ctl_elem_write(card, file, data);
		err = snd_ctl_elem_write(card, file, data);
	snd_power_unlock(card);
	snd_power_unlock(card);
	if (err >= 0)
	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:
 error:
	kfree(data);
	kfree(data);
	return err;
	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 */
/* add or replace a user control */
static int snd_ctl_elem_add_compat(struct snd_ctl_file *file,
static int snd_ctl_elem_add_compat(struct snd_ctl_file *file,
				   struct snd_ctl_elem_info32 __user *data32,
				   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_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_ADD32 = _IOWR('U', 0x17, struct snd_ctl_elem_info32),
	SNDRV_CTL_IOCTL_ELEM_REPLACE32 = _IOWR('U', 0x18, 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)
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(struct file *file, unsigned int cmd, uns
		return snd_ctl_elem_add_compat(ctl, argp, 0);
		return snd_ctl_elem_add_compat(ctl, argp, 0);
	case SNDRV_CTL_IOCTL_ELEM_REPLACE32:
	case SNDRV_CTL_IOCTL_ELEM_REPLACE32:
		return snd_ctl_elem_add_compat(ctl, argp, 1);
		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);
	down_read(&snd_ioctl_rwsem);
+176 −1
Original line number Original line Diff line number Diff line
@@ -183,6 +183,14 @@ static int snd_pcm_ioctl_channel_info_compat(struct snd_pcm_substream *substream
	return err;
	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 {
struct snd_pcm_status32 {
	s32 state;
	s32 state;
	struct compat_timespec trigger_tstamp;
	struct compat_timespec trigger_tstamp;
@@ -243,6 +251,71 @@ static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream,
	return err;
	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 */
/* both for HW_PARAMS and HW_REFINE */
static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream,
static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream,
					  int refine, 
					  int refine, 
@@ -469,6 +542,93 @@ static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream,
	return 0;
	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_WRITEN_FRAMES32 = _IOW('A', 0x52, struct snd_xfern32),
	SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, 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_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)
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 file *file, unsigned int cmd, unsigned l
		return snd_pcm_ioctl_rewind_compat(substream, argp);
		return snd_pcm_ioctl_rewind_compat(substream, argp);
	case SNDRV_PCM_IOCTL_FORWARD32:
	case SNDRV_PCM_IOCTL_FORWARD32:
		return snd_pcm_ioctl_forward_compat(substream, argp);
		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;
	return -ENOIOCTLCMD;
+54 −2
Original line number Original line Diff line number Diff line
@@ -85,8 +85,7 @@ static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile,
	if (err < 0)
	if (err < 0)
		return err;
		return err;


	if (put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) ||
	if (compat_put_timespec(&status.tstamp, &src->tstamp) ||
	    put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) ||
	    put_user(status.avail, &src->avail) ||
	    put_user(status.avail, &src->avail) ||
	    put_user(status.xruns, &src->xruns))
	    put_user(status.xruns, &src->xruns))
		return -EFAULT;
		return -EFAULT;
@@ -94,9 +93,58 @@ static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile,
	return 0;
	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 {
enum {
	SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32),
	SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32),
	SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct snd_rawmidi_status32),
	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)
static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
@@ -115,6 +163,10 @@ static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsign
		return snd_rawmidi_ioctl_params_compat(rfile, argp);
		return snd_rawmidi_ioctl_params_compat(rfile, argp);
	case SNDRV_RAWMIDI_IOCTL_STATUS32:
	case SNDRV_RAWMIDI_IOCTL_STATUS32:
		return snd_rawmidi_ioctl_status_compat(rfile, argp);
		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;
	return -ENOIOCTLCMD;
}
}
+16 −2
Original line number Original line Diff line number Diff line
@@ -70,13 +70,14 @@ static int snd_timer_user_status_compat(struct file *file,
					struct snd_timer_status32 __user *_status)
					struct snd_timer_status32 __user *_status)
{
{
	struct snd_timer_user *tu;
	struct snd_timer_user *tu;
	struct snd_timer_status status;
	struct snd_timer_status32 status;
	
	
	tu = file->private_data;
	tu = file->private_data;
	if (snd_BUG_ON(!tu->timeri))
	if (snd_BUG_ON(!tu->timeri))
		return -ENXIO;
		return -ENXIO;
	memset(&status, 0, sizeof(status));
	memset(&status, 0, sizeof(status));
	status.tstamp = tu->tstamp;
	status.tstamp.tv_sec = tu->tstamp.tv_sec;
	status.tstamp.tv_nsec = tu->tstamp.tv_nsec;
	status.resolution = snd_timer_resolution(tu->timeri);
	status.resolution = snd_timer_resolution(tu->timeri);
	status.lost = tu->timeri->lost;
	status.lost = tu->timeri->lost;
	status.overrun = tu->overrun;
	status.overrun = tu->overrun;
@@ -88,12 +89,21 @@ static int snd_timer_user_status_compat(struct file *file,
	return 0;
	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 {
enum {
	SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32),
	SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32),
	SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct snd_timer_status32),
	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)
static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
@@ -122,6 +132,10 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, uns
		return snd_timer_user_info_compat(file, argp);
		return snd_timer_user_info_compat(file, argp);
	case SNDRV_TIMER_IOCTL_STATUS32:
	case SNDRV_TIMER_IOCTL_STATUS32:
		return snd_timer_user_status_compat(file, argp);
		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;
	return -ENOIOCTLCMD;
}
}