aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core/pcm_compat.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core/pcm_compat.c')
-rw-r--r--sound/core/pcm_compat.c49
1 files changed, 34 insertions, 15 deletions
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
index 3920bf0eebbf..4b6307df846d 100644
--- a/sound/core/pcm_compat.c
+++ b/sound/core/pcm_compat.c
@@ -103,10 +103,24 @@ struct sndrv_pcm_sw_params32 {
103 unsigned char reserved[64]; 103 unsigned char reserved[64];
104}; 104};
105 105
106/* recalcuate the boundary within 32bit */
107static snd_pcm_uframes_t recalculate_boundary(snd_pcm_runtime_t *runtime)
108{
109 snd_pcm_uframes_t boundary;
110
111 if (! runtime->buffer_size)
112 return 0;
113 boundary = runtime->buffer_size;
114 while (boundary * 2 <= 0x7fffffffUL - runtime->buffer_size)
115 boundary *= 2;
116 return boundary;
117}
118
106static int snd_pcm_ioctl_sw_params_compat(snd_pcm_substream_t *substream, 119static int snd_pcm_ioctl_sw_params_compat(snd_pcm_substream_t *substream,
107 struct sndrv_pcm_sw_params32 __user *src) 120 struct sndrv_pcm_sw_params32 __user *src)
108{ 121{
109 snd_pcm_sw_params_t params; 122 snd_pcm_sw_params_t params;
123 snd_pcm_uframes_t boundary;
110 int err; 124 int err;
111 125
112 memset(&params, 0, sizeof(params)); 126 memset(&params, 0, sizeof(params));
@@ -120,10 +134,17 @@ static int snd_pcm_ioctl_sw_params_compat(snd_pcm_substream_t *substream,
120 get_user(params.silence_threshold, &src->silence_threshold) || 134 get_user(params.silence_threshold, &src->silence_threshold) ||
121 get_user(params.silence_size, &src->silence_size)) 135 get_user(params.silence_size, &src->silence_size))
122 return -EFAULT; 136 return -EFAULT;
137 /*
138 * Check silent_size parameter. Since we have 64bit boundary,
139 * silence_size must be compared with the 32bit boundary.
140 */
141 boundary = recalculate_boundary(substream->runtime);
142 if (boundary && params.silence_size >= boundary)
143 params.silence_size = substream->runtime->boundary;
123 err = snd_pcm_sw_params(substream, &params); 144 err = snd_pcm_sw_params(substream, &params);
124 if (err < 0) 145 if (err < 0)
125 return err; 146 return err;
126 if (put_user(params.boundary, &src->boundary)) 147 if (boundary && put_user(boundary, &src->boundary))
127 return -EFAULT; 148 return -EFAULT;
128 return err; 149 return err;
129} 150}
@@ -199,16 +220,6 @@ static int snd_pcm_status_user_compat(snd_pcm_substream_t *substream,
199 return err; 220 return err;
200} 221}
201 222
202/* recalcuate the boundary within 32bit */
203static void recalculate_boundary(snd_pcm_runtime_t *runtime)
204{
205 if (! runtime->buffer_size)
206 return;
207 runtime->boundary = runtime->buffer_size;
208 while (runtime->boundary * 2 <= 0x7fffffffUL - runtime->buffer_size)
209 runtime->boundary *= 2;
210}
211
212/* both for HW_PARAMS and HW_REFINE */ 223/* both for HW_PARAMS and HW_REFINE */
213static int snd_pcm_ioctl_hw_params_compat(snd_pcm_substream_t *substream, 224static int snd_pcm_ioctl_hw_params_compat(snd_pcm_substream_t *substream,
214 int refine, 225 int refine,
@@ -241,8 +252,11 @@ static int snd_pcm_ioctl_hw_params_compat(snd_pcm_substream_t *substream,
241 goto error; 252 goto error;
242 } 253 }
243 254
244 if (! refine) 255 if (! refine) {
245 recalculate_boundary(runtime); 256 unsigned int new_boundary = recalculate_boundary(runtime);
257 if (new_boundary)
258 runtime->boundary = new_boundary;
259 }
246 error: 260 error:
247 kfree(data); 261 kfree(data);
248 return err; 262 return err;
@@ -380,6 +394,7 @@ static int snd_pcm_ioctl_sync_ptr_compat(snd_pcm_substream_t *substream,
380 u32 sflags; 394 u32 sflags;
381 struct sndrv_pcm_mmap_control scontrol; 395 struct sndrv_pcm_mmap_control scontrol;
382 struct sndrv_pcm_mmap_status sstatus; 396 struct sndrv_pcm_mmap_status sstatus;
397 snd_pcm_uframes_t boundary;
383 int err; 398 int err;
384 399
385 snd_assert(runtime, return -EINVAL); 400 snd_assert(runtime, return -EINVAL);
@@ -395,17 +410,21 @@ static int snd_pcm_ioctl_sync_ptr_compat(snd_pcm_substream_t *substream,
395 } 410 }
396 status = runtime->status; 411 status = runtime->status;
397 control = runtime->control; 412 control = runtime->control;
413 boundary = recalculate_boundary(runtime);
414 if (! boundary)
415 boundary = 0x7fffffff;
398 snd_pcm_stream_lock_irq(substream); 416 snd_pcm_stream_lock_irq(substream);
417 /* FIXME: we should consider the boundary for the sync from app */
399 if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL)) 418 if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL))
400 control->appl_ptr = scontrol.appl_ptr; 419 control->appl_ptr = scontrol.appl_ptr;
401 else 420 else
402 scontrol.appl_ptr = control->appl_ptr; 421 scontrol.appl_ptr = control->appl_ptr % boundary;
403 if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN)) 422 if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
404 control->avail_min = scontrol.avail_min; 423 control->avail_min = scontrol.avail_min;
405 else 424 else
406 scontrol.avail_min = control->avail_min; 425 scontrol.avail_min = control->avail_min;
407 sstatus.state = status->state; 426 sstatus.state = status->state;
408 sstatus.hw_ptr = status->hw_ptr; 427 sstatus.hw_ptr = status->hw_ptr % boundary;
409 sstatus.tstamp = status->tstamp; 428 sstatus.tstamp = status->tstamp;
410 sstatus.suspended_state = status->suspended_state; 429 sstatus.suspended_state = status->suspended_state;
411 snd_pcm_stream_unlock_irq(substream); 430 snd_pcm_stream_unlock_irq(substream);