Merge branch 'for-linus' into for-next
Back-merge of for-linus branch for further API/ABI cleanups.
This commit is contained in:
commit
97128577f3
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue