From patchwork Thu Sep 21 06:18:03 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "\(Exiting\) Baolin Wang" X-Patchwork-Id: 113190 Delivered-To: patch@linaro.org Received: by 10.140.106.117 with SMTP id d108csp1641165qgf; Wed, 20 Sep 2017 23:18:35 -0700 (PDT) X-Received: by 10.98.197.134 with SMTP id j128mr4597691pfg.113.1505974715574; Wed, 20 Sep 2017 23:18:35 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1505974715; cv=none; d=google.com; s=arc-20160816; b=KhWQKiVwTZlocdA3IX/d2iVVlHUJ/iTJacH9yXYh/7vCMKKkwlXdrf6sbRmSA8SZMC TfofAs8k3fotFCaCoF30YlhNDI59fBuWoBBZUnzCSG4AnaemPVGMfU1O7iD/z15rjqM3 JUd14eUmZ7mdUYO8bVlWhEfjXhJDOaYkzUOziBnGRMP4PWlappLkWg3VyjCbGv50AhMt ipMKUMLGwjqt2mwWuZhthcIXnhUL7a/krvlDRZOBvczo5VGjWT+WZscvbpz/2Dj81l+k E7cKXqTcD6WkTyPJX74yofks2wyT1gHAsoMOl/CLjHOcCBjhU8cMvFScNSVEGl6PlAza m5vw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=ZyDU73b31oe8ySM9Vo4fOM/+e3BZqc3fBmCQMwjTxx4=; b=qLn4bE5Az7eY3J/DTM300vPJw09zuUk5+gM2sRjxSn8eL92AcrVJ1s75q92MdeIPaE +U+hn4CFcrbBz7dR87PinZFY6uzJNdDCwr2hqY2TJIrDyK7vrccHG3qhUFolgEWZ9deL pBFz8UvkvbI4kXloEb+vbDqrugA7ciZjfpqj1IEEkNHPMot/X1MhLZCW6qKDTOR02m0q IAixW2xPkmYQNIsy+gkbHt5rJKrcoclw7yrA1C1423wQIeu94X9Jbj0GCmOY0AwUXtZ/ pAE7XnQK3akITo7W8OjyJSBAZB52bkeEqJqd9eQYO11kycYcK94U4I7G5aV9lFyI/nRb eQsw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=VpEiixpD; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id d15si575921plj.369.2017.09.20.23.18.35; Wed, 20 Sep 2017 23:18:35 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=VpEiixpD; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751704AbdIUGSe (ORCPT + 26 others); Thu, 21 Sep 2017 02:18:34 -0400 Received: from mail-pf0-f172.google.com ([209.85.192.172]:56814 "EHLO mail-pf0-f172.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751652AbdIUGSb (ORCPT ); Thu, 21 Sep 2017 02:18:31 -0400 Received: by mail-pf0-f172.google.com with SMTP id g65so2739609pfe.13 for ; Wed, 20 Sep 2017 23:18:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=ZyDU73b31oe8ySM9Vo4fOM/+e3BZqc3fBmCQMwjTxx4=; b=VpEiixpDnlgZHaYR0mgAYdi4x5cJ8Xg8uyqfh5Ik5H2RjPsQo1VD3zJOwbgrPTfv2g UttGenid7osU4O7ADF05wF4ojup3vyFH8sFQevxPksEQGSWuYy5OoyR2+QjoYecsVXM0 D3EP3vdHyA0Ih9xx5FJzVZiqe9TFAvqeozA5I= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=ZyDU73b31oe8ySM9Vo4fOM/+e3BZqc3fBmCQMwjTxx4=; b=HRHxZdTfCXeTg/DmriiedbHbTE7bTWqs8puvsBwXaLRW02NSrSLfXg5EekVF0MIa6+ kRIFCBPNZFL815fMK/6YZ73xmWXSyxMxAwlRHPIfSIBu3mrcc+MX8eMWplLJ39oL3dnh OQaUiKtIfyVYCgjEPZWVcjw0I+u4Dd8bft0K8QFyZA6va4nG6tpickK/wefzZB5pa544 6OC5d+Xh0mx6naLzvrtjeRpmdm3Rv9oqCs+PRMCiyEd0lKjl1BjBhpCWgHnS3EZDHjGt 9p3oa6iafc70DS5No0xb5LR230Xrw/v/+9fGgmRlBZN6ogFjxvKCh8dqLm3PeQv7zDDI rI9Q== X-Gm-Message-State: AHPjjUgn+DF4zozaaVwUMAfgtbr0FCvD26eXE+uWFJGhG1Ojkh3YcyLQ 23YPLzcx7ClBfpVKxGEdYsjBwQ== X-Google-Smtp-Source: AOwi7QDRxIDGdKFMeIV4fOK6ZJSOPJVBIWPyzurZmYBFK7lLITMHGgsXWZ5ZnaR56QdwolZjxkpN/w== X-Received: by 10.98.101.4 with SMTP id z4mr4618799pfb.6.1505974711007; Wed, 20 Sep 2017 23:18:31 -0700 (PDT) Received: from baolinwangubtpc.spreadtrum.com ([117.18.48.82]) by smtp.gmail.com with ESMTPSA id q23sm1037773pfk.182.2017.09.20.23.18.24 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 20 Sep 2017 23:18:30 -0700 (PDT) From: Baolin Wang To: perex@perex.cz, tiwai@suse.com Cc: lgirdwood@gmail.com, mingo@kernel.org, o-takashi@sakamocchi.jp, elfring@users.sourceforge.net, dan.carpenter@oracle.com, jeeja.kp@intel.com, vinod.koul@intel.com, dharageswari.r@intel.com, guneshwor.o.singh@intel.com, bhumirks@gmail.com, gudishax.kranthikumar@intel.com, naveen.m@intel.com, hardik.t.shah@intel.com, arvind.yadav.cs@gmail.com, fabf@skynet.be, arnd@arndb.de, broonie@kernel.org, deepa.kernel@gmail.com, baolin.wang@linaro.org, alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 1/7] sound: Replace timespec with timespec64 Date: Thu, 21 Sep 2017 14:18:03 +0800 Message-Id: <5ebd5e37e8f1bf2675996cf56538179b743bc95b.1505973912.git.baolin.wang@linaro.org> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Since timespec is not year 2038 safe on 32bit system, and we need to convert all timespec variables to timespec64 type for sound subsystem. This patch is used to do preparation for following patches, that will convert all structures defined in uapi/sound/asound.h to use 64-bit time_t. Signed-off-by: Baolin Wang --- include/sound/pcm.h | 18 +++++++++--------- include/sound/timer.h | 4 ++-- sound/core/pcm_lib.c | 30 +++++++++++++++++------------- sound/core/pcm_native.c | 12 ++++++++---- sound/core/timer.c | 28 ++++++++++++++-------------- sound/pci/hda/hda_controller.c | 10 +++++----- sound/soc/intel/skylake/skl-pcm.c | 4 ++-- 7 files changed, 57 insertions(+), 49 deletions(-) -- 1.7.9.5 diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 24febf9..cd1ecd6 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -75,7 +75,7 @@ struct snd_pcm_ops { int (*trigger)(struct snd_pcm_substream *substream, int cmd); 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 +343,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; @@ -419,7 +419,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 -- */ @@ -1167,22 +1167,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); + getrawmonotonic64(tv); break; default: - getnstimeofday(tv); + ktime_get_real_ts64(tv); break; } } diff --git a/include/sound/timer.h b/include/sound/timer.h index c4d76ff..c196c07 100644 --- a/include/sound/timer.h +++ b/include/sound/timer.h @@ -102,7 +102,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; @@ -126,7 +126,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); diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index a93a423..5ca9dc3 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -158,8 +158,12 @@ static void xrun(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; trace_xrun(substream); - if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) - snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp); + if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) { + struct timespec64 tstamp; + + snd_pcm_gettime(runtime, &tstamp); + runtime->status->tstamp = timespec64_to_timespec(tstamp); + } snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); if (xrun_debug(substream, XRUN_DEBUG_BASIC)) { char name[16]; @@ -217,12 +221,12 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream, } static void update_audio_tstamp(struct snd_pcm_substream *substream, - struct timespec *curr_tstamp, - struct timespec *audio_tstamp) + struct timespec64 *curr_tstamp, + struct timespec64 *audio_tstamp) { struct snd_pcm_runtime *runtime = substream->runtime; u64 audio_frames, audio_nsecs; - struct timespec driver_tstamp; + struct timespec64 driver_tstamp; if (runtime->tstamp_mode != SNDRV_PCM_TSTAMP_ENABLE) return; @@ -246,16 +250,16 @@ static void update_audio_tstamp(struct snd_pcm_substream *substream, } audio_nsecs = div_u64(audio_frames * 1000000000LL, runtime->rate); - *audio_tstamp = ns_to_timespec(audio_nsecs); + *audio_tstamp = ns_to_timespec64(audio_nsecs); } - runtime->status->audio_tstamp = *audio_tstamp; - runtime->status->tstamp = *curr_tstamp; + runtime->status->audio_tstamp = timespec64_to_timespec(*audio_tstamp); + runtime->status->tstamp = timespec64_to_timespec(*curr_tstamp); /* * re-take a driver timestamp to let apps detect if the reference tstamp * read by low-level hardware was provided with a delay */ - snd_pcm_gettime(substream->runtime, (struct timespec *)&driver_tstamp); + snd_pcm_gettime(substream->runtime, &driver_tstamp); runtime->driver_tstamp = driver_tstamp; } @@ -268,8 +272,8 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, snd_pcm_sframes_t hdelta, delta; unsigned long jdelta; unsigned long curr_jiffies; - struct timespec curr_tstamp; - struct timespec audio_tstamp; + struct timespec64 curr_tstamp; + struct timespec64 audio_tstamp; int crossed_boundary = 0; old_hw_ptr = runtime->status->hw_ptr; @@ -292,9 +296,9 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, /* re-test in case tstamp type is not supported in hardware and was demoted to DEFAULT */ if (runtime->audio_tstamp_report.actual_type == SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT) - snd_pcm_gettime(runtime, (struct timespec *)&curr_tstamp); + snd_pcm_gettime(runtime, &curr_tstamp); } else - snd_pcm_gettime(runtime, (struct timespec *)&curr_tstamp); + snd_pcm_gettime(runtime, &curr_tstamp); } if (pos == SNDRV_PCM_POS_XRUN) { diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 2fec2fe..60bc303 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -881,12 +881,12 @@ 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 = runtime->trigger_tstamp; + status->trigger_tstamp = timespec64_to_timespec(runtime->trigger_tstamp); 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 = runtime->driver_tstamp; + status->driver_tstamp = timespec64_to_timespec(runtime->driver_tstamp); status->audio_tstamp = runtime->status->audio_tstamp; if (runtime->audio_tstamp_report.valid == 1) @@ -899,8 +899,12 @@ int snd_pcm_status(struct snd_pcm_substream *substream, } } else { /* get tstamp only in fallback mode and only if enabled */ - if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) - snd_pcm_gettime(runtime, &status->tstamp); + if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) { + struct timespec64 tstamp; + + snd_pcm_gettime(runtime, &tstamp); + status->tstamp = timespec64_to_timespec(tstamp); + } } _tstamp_end: status->appl_ptr = runtime->control->appl_ptr; diff --git a/sound/core/timer.c b/sound/core/timer.c index 6cdd04a..f44d702 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -73,7 +73,7 @@ struct snd_timer_user { spinlock_t qlock; unsigned long last_resolution; unsigned int filter; - struct timespec tstamp; /* trigger tstamp */ + struct timespec64 tstamp; /* trigger tstamp */ wait_queue_head_t qchange_sleep; struct fasync_struct *fasync; struct mutex ioctl_lock; @@ -408,12 +408,12 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event) struct snd_timer *timer; unsigned long resolution = 0; struct snd_timer_instance *ts; - struct timespec tstamp; + struct timespec64 tstamp; if (timer_tstamp_monotonic) - ktime_get_ts(&tstamp); + ktime_get_ts64(&tstamp); else - getnstimeofday(&tstamp); + ktime_get_real_ts64(&tstamp); if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_START || event > SNDRV_TIMER_EVENT_PAUSE)) return; @@ -957,7 +957,7 @@ static int snd_timer_dev_disconnect(struct snd_device *device) return 0; } -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) { unsigned long flags; unsigned long resolution = 0; @@ -1251,7 +1251,7 @@ static void snd_timer_user_append_to_tqueue(struct snd_timer_user *tu, static void snd_timer_user_ccallback(struct snd_timer_instance *timeri, int event, - struct timespec *tstamp, + struct timespec64 *tstamp, unsigned long resolution) { struct snd_timer_user *tu = timeri->callback_data; @@ -1265,7 +1265,7 @@ static void snd_timer_user_ccallback(struct snd_timer_instance *timeri, return; memset(&r1, 0, sizeof(r1)); r1.event = event; - r1.tstamp = *tstamp; + r1.tstamp = timespec64_to_timespec(*tstamp); r1.val = resolution; spin_lock_irqsave(&tu->qlock, flags); snd_timer_user_append_to_tqueue(tu, &r1); @@ -1288,7 +1288,7 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri, { struct snd_timer_user *tu = timeri->callback_data; struct snd_timer_tread *r, r1; - struct timespec tstamp; + struct timespec64 tstamp; int prev, append = 0; memset(&r1, 0, sizeof(r1)); @@ -1301,14 +1301,14 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri, } if (tu->last_resolution != resolution || ticks > 0) { if (timer_tstamp_monotonic) - ktime_get_ts(&tstamp); + ktime_get_ts64(&tstamp); else - getnstimeofday(&tstamp); + ktime_get_real_ts64(&tstamp); } if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) && tu->last_resolution != resolution) { r1.event = SNDRV_TIMER_EVENT_RESOLUTION; - r1.tstamp = tstamp; + r1.tstamp = timespec64_to_timespec(tstamp); r1.val = resolution; snd_timer_user_append_to_tqueue(tu, &r1); tu->last_resolution = resolution; @@ -1322,14 +1322,14 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri, prev = tu->qtail == 0 ? tu->queue_size - 1 : tu->qtail - 1; r = &tu->tqueue[prev]; if (r->event == SNDRV_TIMER_EVENT_TICK) { - r->tstamp = tstamp; + r->tstamp = timespec64_to_timespec(tstamp); r->val += ticks; append++; goto __wake; } } r1.event = SNDRV_TIMER_EVENT_TICK; - r1.tstamp = tstamp; + r1.tstamp = timespec64_to_timespec(tstamp); r1.val = ticks; snd_timer_user_append_to_tqueue(tu, &r1); append++; @@ -1808,7 +1808,7 @@ static int snd_timer_user_status(struct file *file, if (!tu->timeri) return -EBADFD; memset(&status, 0, sizeof(status)); - status.tstamp = tu->tstamp; + status.tstamp = timespec64_to_timespec(tu->tstamp); status.resolution = snd_timer_resolution(tu->timeri); status.lost = tu->timeri->lost; status.overrun = tu->overrun; diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index d1eb148..c3e4516 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -502,7 +502,7 @@ static inline bool is_link_time_supported(struct snd_pcm_runtime *runtime, } static int azx_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) { @@ -522,7 +522,7 @@ static int azx_get_time_info(struct snd_pcm_substream *substream, if (audio_tstamp_config->report_delay) nsec = azx_adjust_codec_delay(substream, nsec); - *audio_ts = ns_to_timespec(nsec); + *audio_ts = ns_to_timespec64(nsec); audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK; audio_tstamp_report->accuracy_report = 1; /* rest of structure is valid */ @@ -539,16 +539,16 @@ static int azx_get_time_info(struct snd_pcm_substream *substream, return -EINVAL; case SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW: - *system_ts = ktime_to_timespec(xtstamp.sys_monoraw); + *system_ts = ktime_to_timespec64(xtstamp.sys_monoraw); break; default: - *system_ts = ktime_to_timespec(xtstamp.sys_realtime); + *system_ts = ktime_to_timespec64(xtstamp.sys_realtime); break; } - *audio_ts = ktime_to_timespec(xtstamp.device); + *audio_ts = ktime_to_timespec64(xtstamp.device); audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED; diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 2b1e513..9f905c4 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -1141,7 +1141,7 @@ static u64 skl_adjust_codec_delay(struct snd_pcm_substream *substream, } static int skl_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) { @@ -1159,7 +1159,7 @@ static int skl_get_time_info(struct snd_pcm_substream *substream, if (audio_tstamp_config->report_delay) nsec = skl_adjust_codec_delay(substream, nsec); - *audio_ts = ns_to_timespec(nsec); + *audio_ts = ns_to_timespec64(nsec); audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK; audio_tstamp_report->accuracy_report = 1; /* rest of struct is valid */ From patchwork Thu Sep 21 06:18:04 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "\(Exiting\) Baolin Wang" X-Patchwork-Id: 113191 Delivered-To: patch@linaro.org Received: by 10.140.106.117 with SMTP id d108csp1641270qgf; Wed, 20 Sep 2017 23:18:43 -0700 (PDT) X-Received: by 10.84.130.78 with SMTP id 72mr4580517plc.406.1505974723123; Wed, 20 Sep 2017 23:18:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1505974723; cv=none; d=google.com; s=arc-20160816; b=QdX4qGHgQ0NCs79U6rFTltw/8NyQXzDijwiybQeKwVYUxQDpNkRR9XIe4ukXp4R9hv m6OcCJttgxY/Y0pXhszAjhUfA0iqzFG3F2HhaZVW8V6b1HqJ7HlV67AP7k8CrUqr8nIb p9MTvHHdByysUnHAwEfsb+QtSZhAtNr5NovAlFhHZNIbqh821Yu7IximDn2M8+aZ1fNy F8wSa7E95ikJ9tfxEo3oJrQzUbqrcCFctyza4PZ75p0ZA2c7AtJ9Y7jUNKT2SgMxVQfE Hz4Msm5K+bx9iPfYGEVi+/cs0Sg+6RjoJ7ZhQNDsTqMuG5pv9bb0Ey2OwjcBbHD7y6lL nRmg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=0Kkufujaam/tr38CMdCwWmU1UNiljhQNtrHmRhJl+v4=; b=w9jQ1ApkBVrqnqBwmXk/Aa7oF1CykhHsAVwBvemieXtpMqcqvNVElkxYlF/4OcHVkk +hXsdaD0rrG0IET4CBAlEArd1dPEYqEKYH1hBbChZkGr31R8AKPX7kMqKClfz4cxg0H3 M8mQiC7v20f2cm+dRgSZG2I2277+Otn/l30YeeLmTVFphaRqti2dWsrArikS17AZi3nd XQVrLdA2SnzU8GXpgNaCQQpyFN8ewfuM6HqO8632pU6Z2PSdXsgTKD7vqCWovk6un9wv nTwAfNgxTaXnYYlF/nhuU85OpS4EA2LaIXchrXRpZrYuxQ3XxurpGxX6KMyaqq+ZOtgX JWiA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Zl3WGWCU; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id s5si611891pgp.32.2017.09.20.23.18.42; Wed, 20 Sep 2017 23:18:43 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Zl3WGWCU; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751738AbdIUGSk (ORCPT + 26 others); Thu, 21 Sep 2017 02:18:40 -0400 Received: from mail-pg0-f45.google.com ([74.125.83.45]:47732 "EHLO mail-pg0-f45.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751710AbdIUGSi (ORCPT ); Thu, 21 Sep 2017 02:18:38 -0400 Received: by mail-pg0-f45.google.com with SMTP id d8so3015716pgt.4 for ; Wed, 20 Sep 2017 23:18:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=0Kkufujaam/tr38CMdCwWmU1UNiljhQNtrHmRhJl+v4=; b=Zl3WGWCURhINXeQBYLA90PzjvoBauSGqJFlJnGRA9C/tL55sbEme9+yXmA1Fqi582B Nx6S3wSzkN0WqDo71QdqwTFGQ4RPGo8Lvq+0wuXp4y+dcw+XLsWhvGFItayCJAcOPUT1 CicGLVcEVRxOYp+AeArLNSEWhKN01srxgnNFY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=0Kkufujaam/tr38CMdCwWmU1UNiljhQNtrHmRhJl+v4=; b=My/ue1Nin8yZmAzFWPtC55b8NH9JOiBMDwZoqDgFQzvodP0jD9xnE5IoALcccfy8TQ eI8ay0NAvmevLZPPexbmeXnODyOkc6qksHBIxjBMUHJDgPjNXPpYS7FnwImjF7Xhlk6v YzqVGKbfPiL/167LXHUAQGisdbaxKSxGBOO1K6o3aL2ukyeAPlUwUmqwDwPXVH1Qcom6 TRStVhOygMVM5za/QBq9pdTLGkRP/Fbx6n++wizQR9QH+NyP0gW2uB07jZddxTpsxVc8 r+m4LWFTgLHldFo5HulkK2+TNv0wEWE3Sm9Rm3Vi60GwloEEk2hycJy04cODHm/etshF FY8g== X-Gm-Message-State: AHPjjUjqiqCyiLs/ibV7CH113VcC/xbdZSAGC4O7EVr3ln1rpX4sa93/ /6CfVk93SVGYfi73HWL9J436aA== X-Google-Smtp-Source: AOwi7QCgjLje+sUuAzqdFIldAixHyZ8EDgdyGedUrLCBDQS3h9VufVh+O5u4uxJqJm+6a0pT0Skamg== X-Received: by 10.84.238.205 with SMTP id l13mr4423878pln.173.1505974717310; Wed, 20 Sep 2017 23:18:37 -0700 (PDT) Received: from baolinwangubtpc.spreadtrum.com ([117.18.48.82]) by smtp.gmail.com with ESMTPSA id q23sm1037773pfk.182.2017.09.20.23.18.31 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 20 Sep 2017 23:18:36 -0700 (PDT) From: Baolin Wang To: perex@perex.cz, tiwai@suse.com Cc: lgirdwood@gmail.com, mingo@kernel.org, o-takashi@sakamocchi.jp, elfring@users.sourceforge.net, dan.carpenter@oracle.com, jeeja.kp@intel.com, vinod.koul@intel.com, dharageswari.r@intel.com, guneshwor.o.singh@intel.com, bhumirks@gmail.com, gudishax.kranthikumar@intel.com, naveen.m@intel.com, hardik.t.shah@intel.com, arvind.yadav.cs@gmail.com, fabf@skynet.be, arnd@arndb.de, broonie@kernel.org, deepa.kernel@gmail.com, baolin.wang@linaro.org, alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 2/7] sound: core: Avoid using timespec for struct snd_pcm_status Date: Thu, 21 Sep 2017 14:18:04 +0800 Message-Id: <78aa803db47d99c2bee1a4dc8d426621324785b8.1505973912.git.baolin.wang@linaro.org> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 { ...... struct { s32 tv_sec; s32 tv_nsec; } trigger_tstamp; struct { s32 tv_sec; s32 tv_nsec; } tstamp; ...... } struct snd_pcm_status64 { ...... struct { s64 tv_sec; s64 tv_nsec; } trigger_tstamp; struct { s64 tv_sec; s64 tv_nsec; } tstamp; ...... } Moreover in compat file, we renamed or introduced new structures to handle 32bit/64bit time_t in compatible mode. 'struct compat_snd_pcm_status32' and snd_pcm_status_user_compat() 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 with 64bit alignment. 'struct compat_snd_pcm_status64_x86_32' and snd_pcm_status_user_compat64_x86_32() are used to handle 64bit time_t with 32bit alignment. 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 --- include/sound/pcm.h | 49 +++++++++- sound/core/pcm.c | 8 +- sound/core/pcm_compat.c | 238 ++++++++++++++++++++++++++++++++++++----------- sound/core/pcm_native.c | 108 +++++++++++++++++---- 4 files changed, 324 insertions(+), 79 deletions(-) -- 1.7.9.5 diff --git a/include/sound/pcm.h b/include/sound/pcm.h index cd1ecd6..114cc29 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 */ @@ -565,8 +566,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); @@ -1440,4 +1441,48 @@ 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 */ + struct { s64 tv_sec; s64 tv_nsec; } trigger_tstamp; /* time when stream was started/stopped/paused */ + struct { s64 tv_sec; s64 tv_nsec; } tstamp; /* reference timestamp */ + 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 */ + struct { s64 tv_sec; s64 tv_nsec; } audio_tstamp; /* sample counter, wall clock, PHC or on-demand sync'ed */ + struct { s64 tv_sec; s64 tv_nsec; } driver_tstamp; /* useful in case reference system tstamp is reported with delay */ + __u32 audio_tstamp_accuracy; /* in ns units, only valid if indicated in audio_tstamp_data */ + unsigned char reserved[52-2*sizeof(struct { s64 tv_sec; s64 tv_nsec; })]; /* 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) + +#if __BITS_PER_LONG == 32 +struct snd_pcm_status32 { + snd_pcm_state_t state; /* stream state */ + struct { s32 tv_sec; s32 tv_nsec; } trigger_tstamp; /* time when stream was started/stopped/paused */ + struct { s32 tv_sec; s32 tv_nsec; } tstamp; /* reference timestamp */ + 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 */ + struct { s32 tv_sec; s32 tv_nsec; } audio_tstamp; /* sample counter, wall clock, PHC or on-demand sync'ed */ + struct { s32 tv_sec; s32 tv_nsec; } driver_tstamp; /* useful in case reference system tstamp is reported with delay */ + __u32 audio_tstamp_accuracy; /* in ns units, only valid if indicated in audio_tstamp_data */ + unsigned char reserved[52-2*sizeof(struct { s32 tv_sec; s32 tv_nsec; })]; /* 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 + #endif /* __SOUND_PCM_H */ diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 7eadb7f..2d990d9 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -453,7 +453,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); @@ -463,16 +463,16 @@ 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", + snd_iprintf(buffer, "trigger_time: %lld.%09lld\n", status.trigger_tstamp.tv_sec, status.trigger_tstamp.tv_nsec); - snd_iprintf(buffer, "tstamp : %ld.%09ld\n", + snd_iprintf(buffer, "tstamp : %lld.%09lld\n", status.tstamp.tv_sec, status.tstamp.tv_nsec); snd_iprintf(buffer, "delay : %ld\n", status.delay); snd_iprintf(buffer, "avail : %ld\n", status.avail); diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index b719d0b..79e7475 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c @@ -187,7 +187,7 @@ 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_status32 { s32 state; struct compat_timespec trigger_tstamp; struct compat_timespec tstamp; @@ -207,13 +207,15 @@ struct snd_pcm_status32 { static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream, - struct snd_pcm_status32 __user *src, + struct compat_snd_pcm_status32 __user *src, bool ext) { - struct snd_pcm_status status; + struct snd_pcm_status64 status; + struct compat_snd_pcm_status32 compat_status32; int err; memset(&status, 0, sizeof(status)); + memset(&compat_status32, 0, sizeof(compat_status32)); /* * with extension, parameters are read/write, * get audio_tstamp_data from user, @@ -222,38 +224,53 @@ static int snd_pcm_status_user_compat(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) || - 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)) + + compat_status32 = (struct compat_snd_pcm_status32) { + .state = status.state, + .trigger_tstamp = { + .tv_sec = status.trigger_tstamp.tv_sec, + .tv_nsec = status.trigger_tstamp.tv_nsec, + }, + .tstamp = { + .tv_sec = status.tstamp.tv_sec, + .tv_nsec = status.tstamp.tv_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 = { + .tv_sec = status.audio_tstamp.tv_sec, + .tv_nsec = status.audio_tstamp.tv_nsec, + }, + .driver_tstamp = { + .tv_sec = status.audio_tstamp.tv_sec, + .tv_nsec = status.audio_tstamp.tv_nsec, + }, + .audio_tstamp_accuracy = status.audio_tstamp_accuracy, + }; + + if (copy_to_user(src, &compat_status32, sizeof(compat_status32))) return -EFAULT; return err; } -#ifdef CONFIG_X86_X32 -/* X32 ABI has 64bit timespec and 64bit alignment */ -struct snd_pcm_status_x32 { +struct compat_snd_pcm_status64 { s32 state; u32 rsvd; /* alignment */ - struct timespec trigger_tstamp; - struct timespec tstamp; + struct { s64 tv_sec; s64 tv_nsec; } trigger_tstamp; + struct { s64 tv_sec; s64 tv_nsec; } tstamp; u32 appl_ptr; u32 hw_ptr; s32 delay; @@ -262,22 +279,24 @@ struct snd_pcm_status_x32 { u32 overrange; s32 suspended_state; u32 audio_tstamp_data; - struct timespec audio_tstamp; - struct timespec driver_tstamp; + struct { s64 tv_sec; s64 tv_nsec; } audio_tstamp; + struct { s64 tv_sec; s64 tv_nsec; } driver_tstamp; u32 audio_tstamp_accuracy; - unsigned char reserved[52-2*sizeof(struct timespec)]; + unsigned char reserved[52-2*sizeof(struct { s64 tv_sec; s64 tv_nsec; })]; } __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 +305,128 @@ 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 = { + .tv_sec = status.trigger_tstamp.tv_sec, + .tv_nsec = status.trigger_tstamp.tv_nsec, + }, + .tstamp = { + .tv_sec = status.tstamp.tv_sec, + .tv_nsec = status.tstamp.tv_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 = { + .tv_sec = status.audio_tstamp.tv_sec, + .tv_nsec = status.audio_tstamp.tv_nsec, + }, + .driver_tstamp = { + .tv_sec = status.audio_tstamp.tv_sec, + .tv_nsec = status.audio_tstamp.tv_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 */ + +#ifdef IA32_EMULATION +struct compat_snd_pcm_status64_x86_32 { + s32 state; + struct { s64 tv_sec; s64 tv_nsec; } trigger_tstamp; + struct { s64 tv_sec; s64 tv_nsec; } tstamp; + u32 appl_ptr; + u32 hw_ptr; + s32 delay; + u32 avail; + u32 avail_max; + u32 overrange; + s32 suspended_state; + u32 audio_tstamp_data; + struct { s64 tv_sec; s64 tv_nsec; } audio_tstamp; + struct { s64 tv_sec; s64 tv_nsec; } driver_tstamp; + u32 audio_tstamp_accuracy; + unsigned char reserved[52-2*sizeof(struct { s64 tv_sec; s64 tv_nsec; })]; +} __packed; + +static int +snd_pcm_status_user_compat64_x86_32(struct snd_pcm_substream *substream, + struct compat_snd_pcm_status64_x86_32 __user *src, + bool ext) +{ + struct snd_pcm_status64 status; + struct compat_snd_pcm_status64_x86_32 status_x86_32; + int err; + + memset(&status, 0, sizeof(status)); + memset(&status_x86_32, 0, sizeof(status_x86_32)); + /* + * 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_status64(substream, &status); + if (err < 0) + return err; + + if (clear_user(src, sizeof(*src))) + return -EFAULT; + + status_x86_32 = (struct compat_snd_pcm_status64_x86_32) { + .state = status.state, + .trigger_tstamp = { + .tv_sec = status.trigger_tstamp.tv_sec, + .tv_nsec = status.trigger_tstamp.tv_nsec, + }, + .tstamp = { + .tv_sec = status.tstamp.tv_sec, + .tv_nsec = status.tstamp.tv_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 = { + .tv_sec = status.audio_tstamp.tv_sec, + .tv_nsec = status.audio_tstamp.tv_nsec, + }, + .driver_tstamp = { + .tv_sec = status.audio_tstamp.tv_sec, + .tv_nsec = status.audio_tstamp.tv_nsec, + }, + .audio_tstamp_accuracy = status.audio_tstamp_accuracy, + }; + + if (copy_to_user(src, &status_x86_32, sizeof(status_x86_32))) + return -EFAULT; + + return err; +} +#endif /* both for HW_PARAMS and HW_REFINE */ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream, @@ -633,8 +749,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 compat_snd_pcm_status32), + SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT32 = _IOWR('A', 0x24, struct compat_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 +760,14 @@ 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 IA32_EMULATION + SNDRV_PCM_IOCTL_STATUS_COMPAT64_X86_32 = _IOR('A', 0x20, struct compat_snd_pcm_status64_x86_32), + SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT64_X86_32 = _IOWR('A', 0x24, struct compat_snd_pcm_status64_x86_32), +#endif #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,9 +817,9 @@ 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: + case SNDRV_PCM_IOCTL_STATUS_COMPAT32: return snd_pcm_status_user_compat(substream, argp, false); - case SNDRV_PCM_IOCTL_STATUS_EXT32: + case SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT32: return snd_pcm_status_user_compat(substream, argp, true); case SNDRV_PCM_IOCTL_SYNC_PTR32: return snd_pcm_ioctl_sync_ptr_compat(substream, argp); @@ -719,11 +839,17 @@ 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 IA32_EMULATION + case SNDRV_PCM_IOCTL_STATUS_COMPAT64_X86_32: + return snd_pcm_status_user_compat64_x86_32(substream, argp, false); + case SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT64_X86_32: + return snd_pcm_status_user_compat64_x86_32(substream, argp, true); +#endif #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 60bc303..7f1f60d 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -854,8 +854,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; @@ -881,14 +881,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.tv_sec = runtime->trigger_tstamp.tv_sec; + status->trigger_tstamp.tv_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.tv_sec = runtime->status->tstamp.tv_sec; + status->tstamp.tv_nsec = + runtime->status->tstamp.tv_nsec; + status->driver_tstamp.tv_sec = + runtime->driver_tstamp.tv_sec; + status->driver_tstamp.tv_nsec = + runtime->driver_tstamp.tv_nsec; + status->audio_tstamp.tv_sec = + runtime->status->audio_tstamp.tv_sec; + status->audio_tstamp.tv_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, @@ -903,7 +911,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.tv_sec = tstamp.tv_sec; + status->tstamp.tv_nsec = tstamp.tv_nsec; } } _tstamp_end: @@ -933,11 +942,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)); @@ -949,7 +958,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))) @@ -957,6 +966,65 @@ static int snd_pcm_status_user(struct snd_pcm_substream *substream, return 0; } +#if __BITS_PER_LONG == 32 +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 = { + .tv_sec = status64.trigger_tstamp.tv_sec, + .tv_nsec = status64.trigger_tstamp.tv_nsec, + }, + .tstamp = { + .tv_sec = status64.tstamp.tv_sec, + .tv_nsec = status64.tstamp.tv_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 = { + .tv_sec = status64.audio_tstamp.tv_sec, + .tv_nsec = status64.audio_tstamp.tv_nsec, + }, + .driver_tstamp = { + .tv_sec = status64.audio_tstamp.tv_sec, + .tv_nsec = status64.audio_tstamp.tv_nsec, + }, + .audio_tstamp_accuracy = status64.audio_tstamp_accuracy, + }; + + if (copy_to_user(_status, &status32, sizeof(status32))) + return -EFAULT; + + return 0; +} +#endif + static int snd_pcm_channel_info(struct snd_pcm_substream *substream, struct snd_pcm_channel_info * info) { @@ -2888,10 +2956,16 @@ 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); +#if __BITS_PER_LONG == 32 + 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); +#endif + 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: From patchwork Thu Sep 21 06:18:05 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "\(Exiting\) Baolin Wang" X-Patchwork-Id: 113192 Delivered-To: patch@linaro.org Received: by 10.140.106.117 with SMTP id d108csp1641336qgf; Wed, 20 Sep 2017 23:18:50 -0700 (PDT) X-Received: by 10.84.129.193 with SMTP id b59mr4570691plb.108.1505974730771; Wed, 20 Sep 2017 23:18:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1505974730; cv=none; d=google.com; s=arc-20160816; b=peaM3KzKK5OWlNjk8XXGCgiJmAxaRytfuSIaUiZRpbHyA1CxUjHrsj/PwsyMnm0Ycf IcTUpZLbyNEd1zQAVDlOdHKj+cjxZQNASpR017xgfurAfxBIXDBEYu1h98Nkcg98X62V uCAytZMDj6i3SisfgDDZdYbRmqhIWpRMQW8rnZv0QZ5qDk31FdF6lYhYb9wUC3Kio0aY usOTSSF2YpP1l01B9vJ4fufaCKUmwxu1uP9wC32J3M/68Hoo8Mf/zgA25Wxbkh3i2f5b wsYN6xxivZV57RWZ1Hg68K8UCfMbI7ehzI+/zwh0oJhK/j+97jeiZj/MxbR9QkimSJPO NbEA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=7RJO4M74ZsrM9ASaHlppJj1l31MmAw/A1SaR9bZKfyE=; b=AeodU89KHOoOIObUwJqAOdp0787dibG4MVwSZydkU8P/kYapna/MJEUVv2i9JLwSmw UQBZFCa075mWtWOQiaoM+4df5LKywOw2L6RWYE7EZ6W5UbR0qNoN3fv/SokMcJZ1iEM9 YRgxrLtBPFvXuWiSqbO21uuyUhdDdps+AAnY62sJVczj4zKel1qr+aNknKd8SXLvTg5J YXqkpHO4qVtYOXqD5wuf3POZnh8o2pb4TnjqnuoGD9X7/4Axge/6fKzf8stmGWpWZxS0 HA14SoCmvNPMDqZADCAKDvaz9PbWOk4zIM5btLBiF7jh6WHFNfqtAtPDEDAGqMWB0azO AR7g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=V3uCSjbT; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h4si580232pgr.700.2017.09.20.23.18.50; Wed, 20 Sep 2017 23:18:50 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=V3uCSjbT; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751785AbdIUGSs (ORCPT + 26 others); Thu, 21 Sep 2017 02:18:48 -0400 Received: from mail-pf0-f178.google.com ([209.85.192.178]:46108 "EHLO mail-pf0-f178.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751743AbdIUGSp (ORCPT ); Thu, 21 Sep 2017 02:18:45 -0400 Received: by mail-pf0-f178.google.com with SMTP id r68so2754036pfj.3 for ; Wed, 20 Sep 2017 23:18:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=7RJO4M74ZsrM9ASaHlppJj1l31MmAw/A1SaR9bZKfyE=; b=V3uCSjbTYnHcJTsL5Ov7onlAfQxyHqtfn+7gWVVnqYYXkQFO+iBsKZIrl5P3QQo22v eGcdMmWbEACQVxljpCMmw06GRKNLpYNKNmrilNZrgqQ6QK6dxvLsIQ6pbMgzz3sHeMPE aPqSIi+eKIKbP4pT9XeUTTx29brxqrUG64UtE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=7RJO4M74ZsrM9ASaHlppJj1l31MmAw/A1SaR9bZKfyE=; b=pDoVCAc00aWpqUR3RiI4ZlU/atJv3sMYaE3rdpGG/7F+65BqgVKtIHNoIih2YefEAl 8BThU2TK00wJU+9ATC0uKCOxlN4QNGZ9qPTSVX3IhVIq0lpKKHICwB13MkZhuSQvLP2s 94sgdIRibVULie0E3dWBFbdcG9a9i0EhppcDuivwOLi4bcF4juILl75/k07EL/MXT/7u Fdl0RuT5XiWHLbgiLs0IadI/6hpAkbEeiXV472tj30dfKfN/uiA4kL5cBNDcGVz5jYBs vgL/Blq1IIRZuN5yESqJfTf0g0Ovj/wFhzew9xJm+wbE0p1EMpgYuQf2eWNahI3ah9TH hmQA== X-Gm-Message-State: AHPjjUgIVJvg97aMB2Juig9LxXJVIFZv7yZN73N3ZlSISnbyn7VnEb0F a4X0MPPdCUP0wIxpLQtu6A4ACg== X-Google-Smtp-Source: AOwi7QD8xUHGxmGNhKiu2BlqUfPJw0IWluyodcJas0aq7b4opd8ncEDJCV5QfFPPW5GTGvzS62HpPg== X-Received: by 10.99.62.142 with SMTP id l136mr4744584pga.130.1505974724095; Wed, 20 Sep 2017 23:18:44 -0700 (PDT) Received: from baolinwangubtpc.spreadtrum.com ([117.18.48.82]) by smtp.gmail.com with ESMTPSA id q23sm1037773pfk.182.2017.09.20.23.18.37 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 20 Sep 2017 23:18:43 -0700 (PDT) From: Baolin Wang To: perex@perex.cz, tiwai@suse.com Cc: lgirdwood@gmail.com, mingo@kernel.org, o-takashi@sakamocchi.jp, elfring@users.sourceforge.net, dan.carpenter@oracle.com, jeeja.kp@intel.com, vinod.koul@intel.com, dharageswari.r@intel.com, guneshwor.o.singh@intel.com, bhumirks@gmail.com, gudishax.kranthikumar@intel.com, naveen.m@intel.com, hardik.t.shah@intel.com, arvind.yadav.cs@gmail.com, fabf@skynet.be, arnd@arndb.de, broonie@kernel.org, deepa.kernel@gmail.com, baolin.wang@linaro.org, alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 3/7] sound: core: Avoid using timespec for struct snd_pcm_sync_ptr Date: Thu, 21 Sep 2017 14:18:05 +0800 Message-Id: <6781c7b4e5934ad65e3c5b401c0a1bbd7cb44db6.1505973912.git.baolin.wang@linaro.org> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The struct snd_pcm_sync_ptr will use 'timespec' type variables to record timestamp, which is not year 2038 safe on 32bits system. Thus we introduced 'struct snd_pcm_sync_ptr32' and 'struct snd_pcm_sync_ptr64' to handle 32bit time_t and 64bit time_t in native mode, which replace timespec with s64 type. In compat mode, we renamed or introduced new structures to handle 32bit/64bit time_t in compatible mode. The 'struct compat_snd_pcm_sync_ptr32' and snd_pcm_ioctl_sync_ptr_compat() are used to handle 32bit time_t in compat mode. 'struct compat_snd_pcm_sync_ptr64' and snd_pcm_ioctl_sync_ptr_compat64() are used to handle 64bit time_t with 64bit alignment. 'struct compat_snd_pcm_sync_ptr64_x86_32' and snd_pcm_ioctl_sync_ptr_compat64_x86_32() are used to handle 64bit time_t with 32bit alignment. When glibc changes time_t to 64bit, any recompiled program will issue ioctl commands that the kernel does not understand without this patch. Signed-off-by: Baolin Wang --- include/sound/pcm.h | 46 +++++++++- sound/core/pcm.c | 6 +- sound/core/pcm_compat.c | 228 ++++++++++++++++++++++++++++++++++++++--------- sound/core/pcm_lib.c | 9 +- sound/core/pcm_native.c | 113 ++++++++++++++++++----- 5 files changed, 329 insertions(+), 73 deletions(-) -- 1.7.9.5 diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 114cc29..c253cbf 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -64,6 +64,15 @@ struct snd_pcm_hardware { struct snd_pcm_audio_tstamp_config; /* definitions further down */ struct snd_pcm_audio_tstamp_report; +struct snd_pcm_mmap_status64 { + 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 { s64 tv_sec; s64 tv_nsec; } tstamp; /* Timestamp */ + snd_pcm_state_t suspended_state; /* RO: suspended stream state */ + struct { s64 tv_sec; s64 tv_nsec; } audio_tstamp; /* from sample counter or wall clock */ +}; + struct snd_pcm_ops { int (*open)(struct snd_pcm_substream *substream); int (*close)(struct snd_pcm_substream *substream); @@ -389,7 +398,7 @@ struct snd_pcm_runtime { union snd_pcm_sync_id sync; /* hardware synchronization ID */ /* -- mmap -- */ - struct snd_pcm_mmap_status *status; + struct snd_pcm_mmap_status64 *status; struct snd_pcm_mmap_control *control; /* -- locking / scheduling -- */ @@ -1459,8 +1468,21 @@ struct snd_pcm_status64 { unsigned char reserved[52-2*sizeof(struct { s64 tv_sec; s64 tv_nsec; })]; /* must be filled with zero */ }; +struct snd_pcm_sync_ptr64 { + unsigned int flags; + union { + struct snd_pcm_mmap_status64 status; + unsigned char reserved[64]; + } s; + union { + struct snd_pcm_mmap_control control; + unsigned char reserved[64]; + } c; +}; + #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) +#define SNDRV_PCM_IOCTL_SYNC_PTR64 _IOWR('A', 0x23, struct snd_pcm_sync_ptr64) #if __BITS_PER_LONG == 32 struct snd_pcm_status32 { @@ -1481,8 +1503,30 @@ struct snd_pcm_status32 { unsigned char reserved[52-2*sizeof(struct { s32 tv_sec; s32 tv_nsec; })]; /* must be filled with zero */ }; +struct snd_pcm_mmap_status32 { + 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 { s32 tv_sec; s32 tv_nsec; } tstamp; /* Timestamp */ + snd_pcm_state_t suspended_state; /* RO: suspended stream state */ + struct { s32 tv_sec; s32 tv_nsec; } audio_tstamp; /* from sample counter or wall clock */ +}; + +struct snd_pcm_sync_ptr32 { + unsigned int flags; + union { + struct snd_pcm_mmap_status32 status; + unsigned char reserved[64]; + } s; + union { + struct snd_pcm_mmap_control control; + unsigned char reserved[64]; + } c; +}; + #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) +#define SNDRV_PCM_IOCTL_SYNC_PTR32 _IOWR('A', 0x23, struct snd_pcm_sync_ptr32) #endif #endif /* __SOUND_PCM_H */ diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 2d990d9..ca8a7df 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -1001,7 +1001,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, if (runtime == NULL) return -ENOMEM; - size = PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)); + size = PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status64)); runtime->status = snd_malloc_pages(size, GFP_KERNEL); if (runtime->status == NULL) { kfree(runtime); @@ -1013,7 +1013,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, runtime->control = snd_malloc_pages(size, GFP_KERNEL); if (runtime->control == NULL) { snd_free_pages((void*)runtime->status, - PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status))); + PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status64))); kfree(runtime); return -ENOMEM; } @@ -1044,7 +1044,7 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream) if (runtime->private_free != NULL) runtime->private_free(runtime); snd_free_pages((void*)runtime->status, - PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status))); + PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status64))); snd_free_pages((void*)runtime->control, PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control))); kfree(runtime->hw_constraints.rules); diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index 79e7475..7d690b2 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c @@ -570,7 +570,7 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream, } -struct snd_pcm_mmap_status32 { +struct compat_snd_pcm_mmap_status32 { s32 state; s32 pad1; u32 hw_ptr; @@ -579,32 +579,33 @@ struct snd_pcm_mmap_status32 { struct compat_timespec audio_tstamp; } __attribute__((packed)); -struct snd_pcm_mmap_control32 { +struct compat_snd_pcm_mmap_control32 { u32 appl_ptr; u32 avail_min; }; -struct snd_pcm_sync_ptr32 { +struct compat_snd_pcm_sync_ptr32 { u32 flags; union { - struct snd_pcm_mmap_status32 status; + struct compat_snd_pcm_mmap_status32 status; unsigned char reserved[64]; } s; union { - struct snd_pcm_mmap_control32 control; + struct compat_snd_pcm_mmap_control32 control; unsigned char reserved[64]; } c; } __attribute__((packed)); static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream, - struct snd_pcm_sync_ptr32 __user *src) + struct compat_snd_pcm_sync_ptr32 __user *src) { struct snd_pcm_runtime *runtime = substream->runtime; - volatile struct snd_pcm_mmap_status *status; + volatile struct snd_pcm_mmap_status64 *status; volatile struct snd_pcm_mmap_control *control; u32 sflags; struct snd_pcm_mmap_control scontrol; - struct snd_pcm_mmap_status sstatus; + struct snd_pcm_mmap_status64 sstatus; + struct compat_snd_pcm_sync_ptr32 sync_ptr; snd_pcm_uframes_t boundary; int err; @@ -637,63 +638,78 @@ static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream, scontrol.avail_min = control->avail_min; sstatus.state = status->state; sstatus.hw_ptr = status->hw_ptr % boundary; - sstatus.tstamp = status->tstamp; + sstatus.tstamp.tv_sec = status->tstamp.tv_sec; + sstatus.tstamp.tv_nsec = status->tstamp.tv_nsec; sstatus.suspended_state = status->suspended_state; - sstatus.audio_tstamp = status->audio_tstamp; + sstatus.audio_tstamp.tv_sec = status->audio_tstamp.tv_sec; + sstatus.audio_tstamp.tv_nsec = status->audio_tstamp.tv_nsec; 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) || - compat_put_timespec(&sstatus.tstamp, &src->s.status.tstamp) || - put_user(sstatus.suspended_state, &src->s.status.suspended_state) || - compat_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)) + + memset(&sync_ptr, 0, sizeof(sync_ptr)); + sync_ptr.s.status = (struct compat_snd_pcm_mmap_status32) { + .state = sstatus.state, + .hw_ptr = sstatus.hw_ptr, + .tstamp = { + .tv_sec = sstatus.tstamp.tv_sec, + .tv_nsec = sstatus.tstamp.tv_nsec, + }, + .suspended_state = sstatus.suspended_state, + .audio_tstamp = { + .tv_sec = sstatus.audio_tstamp.tv_sec, + .tv_nsec = sstatus.audio_tstamp.tv_nsec, + }, + }; + + sync_ptr.c.control = (struct compat_snd_pcm_mmap_control32) { + .appl_ptr = scontrol.appl_ptr, + .avail_min = scontrol.avail_min, + }; + + if (copy_to_user(src, &sync_ptr, sizeof(sync_ptr))) return -EFAULT; return 0; } -#ifdef CONFIG_X86_X32 -/* X32 ABI has 64bit timespec and 64bit alignment */ -struct snd_pcm_mmap_status_x32 { +struct compat_snd_pcm_mmap_status64 { s32 state; s32 pad1; u32 hw_ptr; u32 pad2; /* alignment */ - struct timespec tstamp; + struct { s64 tv_sec; s64 tv_nsec; } tstamp; s32 suspended_state; s32 pad3; - struct timespec audio_tstamp; + struct { s64 tv_sec; s64 tv_nsec; } audio_tstamp; } __packed; -struct snd_pcm_mmap_control_x32 { +struct compat_snd_pcm_mmap_control64 { u32 appl_ptr; u32 avail_min; }; -struct snd_pcm_sync_ptr_x32 { +struct compat_snd_pcm_sync_ptr64 { u32 flags; u32 rsvd; /* alignment */ union { - struct snd_pcm_mmap_status_x32 status; + struct compat_snd_pcm_mmap_status64 status; unsigned char reserved[64]; } s; union { - struct snd_pcm_mmap_control_x32 control; + struct compat_snd_pcm_mmap_control64 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) +static int snd_pcm_ioctl_sync_ptr_compat64(struct snd_pcm_substream *substream, + struct compat_snd_pcm_sync_ptr64 __user *src) { struct snd_pcm_runtime *runtime = substream->runtime; - volatile struct snd_pcm_mmap_status *status; + volatile struct snd_pcm_mmap_status64 *status; volatile struct snd_pcm_mmap_control *control; u32 sflags; struct snd_pcm_mmap_control scontrol; - struct snd_pcm_mmap_status sstatus; + struct snd_pcm_mmap_status64 sstatus; + struct compat_snd_pcm_sync_ptr64 sync_ptr; snd_pcm_uframes_t boundary; int err; @@ -726,22 +742,142 @@ static int snd_pcm_ioctl_sync_ptr_x32(struct snd_pcm_substream *substream, scontrol.avail_min = control->avail_min; sstatus.state = status->state; sstatus.hw_ptr = status->hw_ptr % boundary; - sstatus.tstamp = status->tstamp; + sstatus.tstamp.tv_sec = status->tstamp.tv_sec; + sstatus.tstamp.tv_nsec = status->tstamp.tv_nsec; sstatus.suspended_state = status->suspended_state; - sstatus.audio_tstamp = status->audio_tstamp; + sstatus.audio_tstamp.tv_sec = status->audio_tstamp.tv_sec; + sstatus.audio_tstamp.tv_nsec = status->audio_tstamp.tv_nsec; 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)) + + memset(&sync_ptr, 0, sizeof(sync_ptr)); + sync_ptr.s.status = (struct compat_snd_pcm_mmap_status64) { + .state = sstatus.state, + .hw_ptr = sstatus.hw_ptr, + .tstamp = { + .tv_sec = sstatus.tstamp.tv_sec, + .tv_nsec = sstatus.tstamp.tv_nsec, + }, + .suspended_state = sstatus.suspended_state, + .audio_tstamp = { + .tv_sec = sstatus.audio_tstamp.tv_sec, + .tv_nsec = sstatus.audio_tstamp.tv_nsec, + }, + }; + + sync_ptr.c.control = (struct compat_snd_pcm_mmap_control64) { + .appl_ptr = scontrol.appl_ptr, + .avail_min = scontrol.avail_min, + }; + + if (copy_to_user(src, &sync_ptr, sizeof(sync_ptr))) return -EFAULT; return 0; } -#endif /* CONFIG_X86_X32 */ + +#ifdef IA32_EMULATION +struct compat_snd_pcm_mmap_status64_x86_32 { + s32 state; + s32 pad1; + u32 hw_ptr; + struct { s64 tv_sec; s64 tv_nsec; } tstamp; + s32 suspended_state; + struct { s64 tv_sec; s64 tv_nsec; } audio_tstamp; +} __packed; + +struct compat_snd_pcm_mmap_control64_x86_32 { + u32 appl_ptr; + u32 avail_min; +}; + +struct compat_snd_pcm_sync_ptr64_x86_32 { + u32 flags; + union { + struct compat_snd_pcm_mmap_status64_x86_32 status; + unsigned char reserved[64]; + } s; + union { + struct compat_snd_pcm_mmap_control64_x86_32 control; + unsigned char reserved[64]; + } c; +} __packed; + +static int +snd_pcm_ioctl_sync_ptr_compat64_x86_32(struct snd_pcm_substream *substream, + struct compat_snd_pcm_sync_ptr64_x86_32 __user *src) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + volatile struct snd_pcm_mmap_status64 *status; + volatile struct snd_pcm_mmap_control *control; + u32 sflags; + struct snd_pcm_mmap_control scontrol; + struct snd_pcm_mmap_status64 sstatus; + struct compat_snd_pcm_sync_ptr64_x86_32 sync_ptr; + 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.tv_sec = status->tstamp.tv_sec; + sstatus.tstamp.tv_nsec = status->tstamp.tv_nsec; + sstatus.suspended_state = status->suspended_state; + sstatus.audio_tstamp.tv_sec = status->audio_tstamp.tv_sec; + sstatus.audio_tstamp.tv_nsec = status->audio_tstamp.tv_nsec; + snd_pcm_stream_unlock_irq(substream); + + memset(&sync_ptr, 0, sizeof(sync_ptr)); + sync_ptr.s.status = (struct compat_snd_pcm_mmap_status64_x86_32) { + .state = sstatus.state, + .hw_ptr = sstatus.hw_ptr, + .tstamp = { + .tv_sec = sstatus.tstamp.tv_sec, + .tv_nsec = sstatus.tstamp.tv_nsec, + }, + .suspended_state = sstatus.suspended_state, + .audio_tstamp = { + .tv_sec = sstatus.audio_tstamp.tv_sec, + .tv_nsec = sstatus.audio_tstamp.tv_nsec, + }, + }; + + sync_ptr.c.control = (struct compat_snd_pcm_mmap_control64_x86_32) { + .appl_ptr = scontrol.appl_ptr, + .avail_min = scontrol.avail_min, + }; + + if (copy_to_user(src, &sync_ptr, sizeof(sync_ptr))) + return -EFAULT; + + return 0; +} +#endif /* */ @@ -759,12 +895,14 @@ enum { SNDRV_PCM_IOCTL_READI_FRAMES32 = _IOR('A', 0x51, struct snd_xferi32), 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_SYNC_PTR_COMPAT32 = _IOWR('A', 0x23, struct compat_snd_pcm_sync_ptr32), + SNDRV_PCM_IOCTL_SYNC_PTR_COMPAT64 = _IOWR('A', 0x23, struct compat_snd_pcm_sync_ptr64), 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 IA32_EMULATION SNDRV_PCM_IOCTL_STATUS_COMPAT64_X86_32 = _IOR('A', 0x20, struct compat_snd_pcm_status64_x86_32), SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT64_X86_32 = _IOWR('A', 0x24, struct compat_snd_pcm_status64_x86_32), + SNDRV_PCM_IOCTL_SYNC_PTR_COMPAT64_X86_32 = _IOWR('A', 0x23, struct compat_snd_pcm_sync_ptr64_x86_32), #endif #ifdef CONFIG_X86_X32 SNDRV_PCM_IOCTL_CHANNEL_INFO_X32 = _IOR('A', 0x32, struct snd_pcm_channel_info), @@ -821,8 +959,10 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l return snd_pcm_status_user_compat(substream, argp, false); case SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT32: return snd_pcm_status_user_compat(substream, argp, true); - case SNDRV_PCM_IOCTL_SYNC_PTR32: + case SNDRV_PCM_IOCTL_SYNC_PTR_COMPAT32: return snd_pcm_ioctl_sync_ptr_compat(substream, argp); + case SNDRV_PCM_IOCTL_SYNC_PTR_COMPAT64: + return snd_pcm_ioctl_sync_ptr_compat64(substream, argp); case SNDRV_PCM_IOCTL_CHANNEL_INFO32: return snd_pcm_ioctl_channel_info_compat(substream, argp); case SNDRV_PCM_IOCTL_WRITEI_FRAMES32: @@ -848,6 +988,8 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l return snd_pcm_status_user_compat64_x86_32(substream, argp, false); case SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT64_X86_32: return snd_pcm_status_user_compat64_x86_32(substream, argp, true); + case SNDRV_PCM_IOCTL_SYNC_PTR_COMPAT64_X86_32: + return snd_pcm_ioctl_sync_ptr_compat64_x86_32(substream, argp); #endif #ifdef CONFIG_X86_X32 case SNDRV_PCM_IOCTL_SYNC_PTR_X32: diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 5ca9dc3..96047cc 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -162,7 +162,8 @@ static void xrun(struct snd_pcm_substream *substream) struct timespec64 tstamp; snd_pcm_gettime(runtime, &tstamp); - runtime->status->tstamp = timespec64_to_timespec(tstamp); + runtime->status->tstamp.tv_sec = tstamp.tv_sec; + runtime->status->tstamp.tv_nsec = tstamp.tv_nsec; } snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); if (xrun_debug(substream, XRUN_DEBUG_BASIC)) { @@ -252,8 +253,10 @@ static void update_audio_tstamp(struct snd_pcm_substream *substream, runtime->rate); *audio_tstamp = ns_to_timespec64(audio_nsecs); } - runtime->status->audio_tstamp = timespec64_to_timespec(*audio_tstamp); - runtime->status->tstamp = timespec64_to_timespec(*curr_tstamp); + runtime->status->audio_tstamp.tv_sec = audio_tstamp->tv_sec; + runtime->status->audio_tstamp.tv_nsec = audio_tstamp->tv_nsec; + runtime->status->tstamp.tv_sec = curr_tstamp->tv_sec; + runtime->status->tstamp.tv_nsec = curr_tstamp->tv_nsec; /* * re-take a driver timestamp to let apps detect if the reference tstamp diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 7f1f60d..287f20a 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -2774,50 +2774,113 @@ static snd_pcm_sframes_t snd_pcm_delay(struct snd_pcm_substream *substream) snd_pcm_stream_unlock_irq(substream); return err < 0 ? err : n; } - + static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream, - struct snd_pcm_sync_ptr __user *_sync_ptr) + struct snd_pcm_sync_ptr64 *sync_ptr) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_pcm_sync_ptr sync_ptr; - volatile struct snd_pcm_mmap_status *status; + volatile struct snd_pcm_mmap_status64 *status; volatile struct snd_pcm_mmap_control *control; int err; - memset(&sync_ptr, 0, sizeof(sync_ptr)); - if (get_user(sync_ptr.flags, (unsigned __user *)&(_sync_ptr->flags))) - return -EFAULT; - if (copy_from_user(&sync_ptr.c.control, &(_sync_ptr->c.control), sizeof(struct snd_pcm_mmap_control))) - return -EFAULT; status = runtime->status; control = runtime->control; - if (sync_ptr.flags & SNDRV_PCM_SYNC_PTR_HWSYNC) { + if (sync_ptr->flags & SNDRV_PCM_SYNC_PTR_HWSYNC) { err = snd_pcm_hwsync(substream); if (err < 0) return err; } snd_pcm_stream_lock_irq(substream); - if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) { + if (!(sync_ptr->flags & SNDRV_PCM_SYNC_PTR_APPL)) { err = pcm_lib_apply_appl_ptr(substream, - sync_ptr.c.control.appl_ptr); + sync_ptr->c.control.appl_ptr); if (err < 0) { snd_pcm_stream_unlock_irq(substream); return err; } } else { - sync_ptr.c.control.appl_ptr = control->appl_ptr; + sync_ptr->c.control.appl_ptr = control->appl_ptr; } - if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN)) - control->avail_min = sync_ptr.c.control.avail_min; + if (!(sync_ptr->flags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN)) + control->avail_min = sync_ptr->c.control.avail_min; else - sync_ptr.c.control.avail_min = control->avail_min; - sync_ptr.s.status.state = status->state; - sync_ptr.s.status.hw_ptr = status->hw_ptr; - sync_ptr.s.status.tstamp = status->tstamp; - sync_ptr.s.status.suspended_state = status->suspended_state; + sync_ptr->c.control.avail_min = control->avail_min; + sync_ptr->s.status.state = status->state; + sync_ptr->s.status.hw_ptr = status->hw_ptr; + sync_ptr->s.status.tstamp.tv_sec = status->tstamp.tv_sec; + sync_ptr->s.status.tstamp.tv_nsec = status->tstamp.tv_nsec; + sync_ptr->s.status.suspended_state = status->suspended_state; snd_pcm_stream_unlock_irq(substream); + + return 0; +} + +#if __BITS_PER_LONG == 32 +static int snd_pcm_sync_ptr32(struct snd_pcm_substream *substream, + struct snd_pcm_sync_ptr32 __user *_sync_ptr) +{ + struct snd_pcm_sync_ptr64 sync_ptr64; + struct snd_pcm_sync_ptr32 sync_ptr32; + int ret; + + memset(&sync_ptr64, 0, sizeof(sync_ptr64)); + memset(&sync_ptr32, 0, sizeof(sync_ptr32)); + if (get_user(sync_ptr64.flags, (unsigned __user *)&(_sync_ptr->flags))) + return -EFAULT; + if (copy_from_user(&sync_ptr64.c.control, &(_sync_ptr->c.control), + sizeof(struct snd_pcm_mmap_control))) + return -EFAULT; + + ret = snd_pcm_sync_ptr(substream, &sync_ptr64); + if (ret) + return ret; + + sync_ptr32.s.status = (struct snd_pcm_mmap_status32) { + .state = sync_ptr64.s.status.state, + .hw_ptr = sync_ptr64.s.status.hw_ptr, + .tstamp = { + .tv_sec = sync_ptr64.s.status.tstamp.tv_sec, + .tv_nsec = sync_ptr64.s.status.tstamp.tv_nsec, + }, + .suspended_state = sync_ptr64.s.status.suspended_state, + .audio_tstamp = { + .tv_sec = sync_ptr64.s.status.audio_tstamp.tv_sec, + .tv_nsec = sync_ptr64.s.status.audio_tstamp.tv_nsec, + }, + }; + + sync_ptr32.c.control = (struct snd_pcm_mmap_control) { + .appl_ptr = sync_ptr64.c.control.appl_ptr, + .avail_min = sync_ptr64.c.control.avail_min, + }; + + if (copy_to_user(_sync_ptr, &sync_ptr32, sizeof(sync_ptr32))) + return -EFAULT; + + return 0; +} +#endif + +static int snd_pcm_sync_ptr64(struct snd_pcm_substream *substream, + struct snd_pcm_sync_ptr64 __user *_sync_ptr) +{ + struct snd_pcm_sync_ptr64 sync_ptr; + int ret; + + memset(&sync_ptr, 0, sizeof(sync_ptr)); + if (get_user(sync_ptr.flags, (unsigned __user *)&(_sync_ptr->flags))) + return -EFAULT; + if (copy_from_user(&sync_ptr.c.control, &(_sync_ptr->c.control), + sizeof(struct snd_pcm_mmap_control))) + return -EFAULT; + + ret = snd_pcm_sync_ptr(substream, &sync_ptr); + if (ret) + return ret; + if (copy_to_user(_sync_ptr, &sync_ptr, sizeof(sync_ptr))) return -EFAULT; + return 0; } @@ -2995,8 +3058,12 @@ static int snd_pcm_common_ioctl(struct file *file, return -EFAULT; return 0; } - case SNDRV_PCM_IOCTL_SYNC_PTR: - return snd_pcm_sync_ptr(substream, arg); +#if __BITS_PER_LONG == 32 + case SNDRV_PCM_IOCTL_SYNC_PTR32: + return snd_pcm_sync_ptr32(substream, arg); +#endif + case SNDRV_PCM_IOCTL_SYNC_PTR64: + return snd_pcm_sync_ptr64(substream, arg); #ifdef CONFIG_SND_SUPPORT_OLD_API case SNDRV_PCM_IOCTL_HW_REFINE_OLD: return snd_pcm_hw_refine_old_user(substream, arg); @@ -3329,7 +3396,7 @@ static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file if (!(area->vm_flags & VM_READ)) return -EINVAL; size = area->vm_end - area->vm_start; - if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status))) + if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status64))) return -EINVAL; area->vm_ops = &snd_pcm_vm_ops_status; area->vm_private_data = substream; From patchwork Thu Sep 21 06:18:06 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "\(Exiting\) Baolin Wang" X-Patchwork-Id: 113193 Delivered-To: patch@linaro.org Received: by 10.140.106.117 with SMTP id d108csp1641382qgf; Wed, 20 Sep 2017 23:18:57 -0700 (PDT) X-Received: by 10.84.142.101 with SMTP id 92mr4441758plw.254.1505974737091; Wed, 20 Sep 2017 23:18:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1505974737; cv=none; d=google.com; s=arc-20160816; b=Sup2dGuD+O1BCWVSZQ8c+wfQMCrgGAmBgv6pCAhpjOkv0GF/pOHXvZjYTYkTVfSSU1 8y6RryJJ+pf+JU1/RggHpv7kPcodzBouRWsah9gj28ZFoUaSer9UvgL6s1odpSvArLGw DGkkGlwkgbvSNFGknKIPbnayPJVzpymi6wAhbQ43Ba00XaEZlQJdz7IYtwBwwJvW6ZFe 1+32bUmt7Hp50A6AN2TtdnovY93taoB3yfTzcm4X4DWFVnsjHek5Qkpe4VXTVSl1vUf1 F/drDsApw3zXUylJar01iT2sf/x1+8C/BPECiBMBWnGpQPWjL3I9zW7+k1zFep0lrZVj zx3A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=g6oiF0QJV4h1lC6MykkeYZWwX0nJ+y0ULmxPNv2l5dw=; b=SZ5mJOSl/vFvfmZgTtCp1T1rFbU22ayXgw9bklV6kA4G4lv9q/6yadUjN/MYhu7cHV JS0LjqJeUHPgyxhtbtg/sPhTi7PwvIRadwMND9xcRIS3huzm1Viowgsms83CryQpjsH8 vFX+TxXBEEQam0VWZB/kl+BuW6HnsJBRZQHXTzDVEEMBGxkG6yGvcsngWrhpCNrl6Wa9 PFPiVmnI8ryMWmrOVCSpGXOU7L8lfLm7cLqxCfzxNChEcYWg27bbsvAShyYCZYkdpAvN IVEwfsj5WZnbSSHsKwnL+D8vCtdtLGS/r2mbJ970QtUep8WJhUH+R1StGmnRjhoPJUaD YlUw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=GovqIGIB; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h90si568406plb.279.2017.09.20.23.18.56; Wed, 20 Sep 2017 23:18:57 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=GovqIGIB; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751801AbdIUGSy (ORCPT + 26 others); Thu, 21 Sep 2017 02:18:54 -0400 Received: from mail-pf0-f178.google.com ([209.85.192.178]:50639 "EHLO mail-pf0-f178.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751743AbdIUGSu (ORCPT ); Thu, 21 Sep 2017 02:18:50 -0400 Received: by mail-pf0-f178.google.com with SMTP id m63so2748006pfk.7 for ; Wed, 20 Sep 2017 23:18:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=g6oiF0QJV4h1lC6MykkeYZWwX0nJ+y0ULmxPNv2l5dw=; b=GovqIGIBfdW4vCCnvqQCryRJ9ygOZzkPJZ1jn6ciNEDqKzgbUS9/8GbALRkdr0XG4g RRim6sok2K0bIU5xvFGhF2m4dQD5pfxOW2YCQ3Yj+KqfbRwLnn3bNFGiiEVnXLh5CsXR FXrwBXjaSfde3yeacOkoDg8vNnGH5ENjs7hXw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=g6oiF0QJV4h1lC6MykkeYZWwX0nJ+y0ULmxPNv2l5dw=; b=ArPvLsSbc0riJGkXrZmglA7m7dYxeZSks4DijIMYTAu4tjmex2vCDOYMcjB2vVS4Dy mRegoRqke13TPrNEj7IRbP1glvBPZSZGZGAbJsK3MIlZUwWNH+3RvuPH59La9NKvgV69 jiQcuSIw0Bj/+V+yq+UpvKylUzXwdm9CTrvCaGdEiJbgYXyYmoD/wKXEYQxEido6Ew8v uc3tgEtXMe9the7RhQTNo4vZ6Y0UMtp67x8Jm1fXgUX8RA+7mt8Mhn59mnlcXzy75JhC mKI/u0vLIHIJdCk0IvXQrDgsn5ioUii9LhsFAr74AlbK4jWg39PnAq+gltSXBTocKF7c dT5A== X-Gm-Message-State: AHPjjUhLl1kE5EFfBzMEhqD4zWXJs4wMbxU3WpoEGZw2tJFUawjWDBRe QRz/xn9FHgSzLkCLXJHFP0MYlA== X-Google-Smtp-Source: AOwi7QBtpLrGmq6pHdtGGMokAwyQCSr8zFLbtQZV8XRVRVpzOxNMFb9m+r4fo6mtyNlsjVp+SuhYtw== X-Received: by 10.98.48.195 with SMTP id w186mr4603666pfw.213.1505974729758; Wed, 20 Sep 2017 23:18:49 -0700 (PDT) Received: from baolinwangubtpc.spreadtrum.com ([117.18.48.82]) by smtp.gmail.com with ESMTPSA id q23sm1037773pfk.182.2017.09.20.23.18.44 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 20 Sep 2017 23:18:49 -0700 (PDT) From: Baolin Wang To: perex@perex.cz, tiwai@suse.com Cc: lgirdwood@gmail.com, mingo@kernel.org, o-takashi@sakamocchi.jp, elfring@users.sourceforge.net, dan.carpenter@oracle.com, jeeja.kp@intel.com, vinod.koul@intel.com, dharageswari.r@intel.com, guneshwor.o.singh@intel.com, bhumirks@gmail.com, gudishax.kranthikumar@intel.com, naveen.m@intel.com, hardik.t.shah@intel.com, arvind.yadav.cs@gmail.com, fabf@skynet.be, arnd@arndb.de, broonie@kernel.org, deepa.kernel@gmail.com, baolin.wang@linaro.org, alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 4/7] sound: core: Avoid using timespec for struct snd_rawmidi_status Date: Thu, 21 Sep 2017 14:18:06 +0800 Message-Id: X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The struct snd_rawmidi_status will use 'timespec' type variables to record timestamp, which is not year 2038 safe on 32bits system. Thus we introduced 'struct snd_rawmidi_status32' and 'struct snd_rawmidi_status64' to handle 32bit time_t and 64bit time_t in native mode, which replace timespec with s64 type. In compat mode, we renamed or introduced new structures to handle 32bit/64bit time_t in compatible mode. 'struct compat_snd_rawmidi_status32' and snd_rawmidi_ioctl_status_compat() are used to handle 32bit time_t in compat mode. 'struct compat_snd_rawmidi_status64' and snd_rawmidi_ioctl_status_compat64() are used to handle 64bit time_t with 64bit alignment. 'struct compat_snd_rawmidi_status64_x86_32' and snd_rawmidi_ioctl_status_compat64_x86_32() are used to handle 64bit time_t with 32bit alignment. 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 --- sound/core/rawmidi.c | 74 ++++++++++++++++++++++++++++++++--- sound/core/rawmidi_compat.c | 90 ++++++++++++++++++++++++++++++++----------- 2 files changed, 135 insertions(+), 29 deletions(-) -- 1.7.9.5 diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index b3b353d..7afb1a4 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -63,6 +63,28 @@ #define rmidi_dbg(rmidi, fmt, args...) \ dev_dbg(&(rmidi)->dev, fmt, ##args) +#if __BITS_PER_LONG == 32 +struct snd_rawmidi_status32 { + int stream; + struct { s32 tv_sec; s32 tv_nsec; } 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 */ +}; + +#define SNDRV_RAWMIDI_IOCTL_STATUS32 _IOWR('W', 0x20, struct snd_rawmidi_status32) +#endif + +struct snd_rawmidi_status64 { + int stream; + struct { s64 tv_sec; s64 tv_nsec; } 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 */ +}; + +#define SNDRV_RAWMIDI_IOCTL_STATUS64 _IOWR('W', 0x20, struct snd_rawmidi_status64) + static struct snd_rawmidi *snd_rawmidi_search(struct snd_card *card, int device) { struct snd_rawmidi *rawmidi; @@ -680,7 +702,7 @@ int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream, EXPORT_SYMBOL(snd_rawmidi_input_params); static int snd_rawmidi_output_status(struct snd_rawmidi_substream *substream, - struct snd_rawmidi_status * status) + struct snd_rawmidi_status64 * status) { struct snd_rawmidi_runtime *runtime = substream->runtime; @@ -693,7 +715,7 @@ static int snd_rawmidi_output_status(struct snd_rawmidi_substream *substream, } static int snd_rawmidi_input_status(struct snd_rawmidi_substream *substream, - struct snd_rawmidi_status * status) + struct snd_rawmidi_status64 * status) { struct snd_rawmidi_runtime *runtime = substream->runtime; @@ -751,11 +773,50 @@ static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long return -EINVAL; } } - case SNDRV_RAWMIDI_IOCTL_STATUS: +#if __BITS_PER_LONG == 32 + case SNDRV_RAWMIDI_IOCTL_STATUS32: + { + int err = 0; + struct snd_rawmidi_status32 __user *status = argp; + struct snd_rawmidi_status32 status32; + struct snd_rawmidi_status64 status64; + + if (copy_from_user(&status32, argp, + sizeof(struct snd_rawmidi_status32))) + return -EFAULT; + switch (status32.stream) { + case SNDRV_RAWMIDI_STREAM_OUTPUT: + if (rfile->output == NULL) + return -EINVAL; + err = snd_rawmidi_output_status(rfile->output, &status64); + break; + case SNDRV_RAWMIDI_STREAM_INPUT: + if (rfile->input == NULL) + return -EINVAL; + err = snd_rawmidi_input_status(rfile->input, &status64); + break; + default: + return -EINVAL; + } + if (err < 0) + return err; + + if (put_user(status64.stream, &status->stream) || + put_user(status64.tstamp.tv_sec, &status->tstamp.tv_sec) || + put_user(status64.tstamp.tv_nsec, &status->tstamp.tv_nsec) || + put_user(status64.avail, &status->avail) || + put_user(status64.xruns, &status->xruns)) + return -EFAULT; + return 0; + } +#endif + case SNDRV_RAWMIDI_IOCTL_STATUS64: { int err = 0; - struct snd_rawmidi_status status; - if (copy_from_user(&status, argp, sizeof(struct snd_rawmidi_status))) + struct snd_rawmidi_status64 status; + + if (copy_from_user(&status, argp, + sizeof(struct snd_rawmidi_status64))) return -EFAULT; switch (status.stream) { case SNDRV_RAWMIDI_STREAM_OUTPUT: @@ -773,7 +834,8 @@ static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long } if (err < 0) return err; - if (copy_to_user(argp, &status, sizeof(struct snd_rawmidi_status))) + if (copy_to_user(argp, &status, + sizeof(struct snd_rawmidi_status64))) return -EFAULT; return 0; } diff --git a/sound/core/rawmidi_compat.c b/sound/core/rawmidi_compat.c index f69764d..4b5a612 100644 --- a/sound/core/rawmidi_compat.c +++ b/sound/core/rawmidi_compat.c @@ -53,7 +53,7 @@ static int snd_rawmidi_ioctl_params_compat(struct snd_rawmidi_file *rfile, return -EINVAL; } -struct snd_rawmidi_status32 { +struct compat_snd_rawmidi_status32 { s32 stream; struct compat_timespec tstamp; u32 avail; @@ -62,10 +62,10 @@ struct snd_rawmidi_status32 { } __attribute__((packed)); static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile, - struct snd_rawmidi_status32 __user *src) + struct compat_snd_rawmidi_status32 __user *src) { int err; - struct snd_rawmidi_status status; + struct snd_rawmidi_status64 status; if (rfile->output == NULL) return -EINVAL; @@ -85,7 +85,8 @@ static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile, if (err < 0) return err; - if (compat_put_timespec(&status.tstamp, &src->tstamp) || + if (put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) || + put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) || put_user(status.avail, &src->avail) || put_user(status.xruns, &src->xruns)) return -EFAULT; @@ -93,24 +94,63 @@ static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile, return 0; } -#ifdef CONFIG_X86_X32 -/* X32 ABI has 64bit timespec and 64bit alignment */ -struct snd_rawmidi_status_x32 { +struct compat_snd_rawmidi_status64 { s32 stream; u32 rsvd; /* alignment */ - struct timespec tstamp; + struct { s64 tv_sec; s64 tv_nsec; } 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_compat64(struct snd_rawmidi_file *rfile, + struct compat_snd_rawmidi_status64 __user *src) +{ + int err; + struct snd_rawmidi_status64 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_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) || + put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) || + put_user(status.avail, &src->avail) || + put_user(status.xruns, &src->xruns)) + return -EFAULT; + + return 0; +} + +#ifdef IA32_EMULATION +struct compat_snd_rawmidi_status64_x86_32 { + s32 stream; + struct { s64 tv_sec; s64 tv_nsec; } tstamp; + u32 avail; + u32 xruns; + unsigned char reserved[16]; +} __attribute__((packed)); -static int snd_rawmidi_ioctl_status_x32(struct snd_rawmidi_file *rfile, - struct snd_rawmidi_status_x32 __user *src) +static int +snd_rawmidi_ioctl_status_compat64_x86_32(struct snd_rawmidi_file *rfile, + struct compat_snd_rawmidi_status64_x86_32 __user *src) { int err; - struct snd_rawmidi_status status; + struct snd_rawmidi_status64 status; if (rfile->output == NULL) return -EINVAL; @@ -130,21 +170,23 @@ static int snd_rawmidi_ioctl_status_x32(struct snd_rawmidi_file *rfile, if (err < 0) return err; - if (put_timespec(&status.tstamp, &src->tstamp) || + if (put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) || + put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) || put_user(status.avail, &src->avail) || put_user(status.xruns, &src->xruns)) return -EFAULT; return 0; } -#endif /* CONFIG_X86_X32 */ +#endif enum { SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32), - 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 */ + SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT32 = _IOWR('W', 0x20, struct compat_snd_rawmidi_status32), + SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT64 = _IOWR('W', 0x20, struct compat_snd_rawmidi_status64), +#ifdef IA32_EMULATION + SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT64_X86_32 = _IOWR('W', 0x20, struct compat_snd_rawmidi_status64_x86_32), +#endif }; static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) @@ -161,12 +203,14 @@ static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsign return snd_rawmidi_ioctl(file, cmd, (unsigned long)argp); case SNDRV_RAWMIDI_IOCTL_PARAMS32: return snd_rawmidi_ioctl_params_compat(rfile, argp); - case SNDRV_RAWMIDI_IOCTL_STATUS32: + case SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT32: 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 */ + case SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT64: + return snd_rawmidi_ioctl_status_compat64(rfile, argp); +#ifdef IA32_EMULATION + case SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT64_X86_32: + return snd_rawmidi_ioctl_status_compat64_x86_32(rfile, argp); +#endif } return -ENOIOCTLCMD; } From patchwork Thu Sep 21 06:18:07 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "\(Exiting\) Baolin Wang" X-Patchwork-Id: 113194 Delivered-To: patch@linaro.org Received: by 10.140.106.117 with SMTP id d108csp1641455qgf; Wed, 20 Sep 2017 23:19:03 -0700 (PDT) X-Received: by 10.84.238.142 with SMTP id v14mr4490733plk.388.1505974743494; Wed, 20 Sep 2017 23:19:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1505974743; cv=none; d=google.com; s=arc-20160816; b=e7A0wWjPfMPCi/Asl1FTncgFuUtv13JGA+ZMOlItlmSyxhK/++ePJgFVKnq/NJgmon O6sryvqLU3OSqgBjf9SKUTtsLHQBeh96pvRmYRrXj5ZvudVyUqHDRvDo5WJBH9q5yQpp CIK8/HGczTASYal56zu8z4bllmAj4n9EAYnXXw379XM3zBWN1WPMQGYsMs4kD/gF1r08 thTN2INC4GoQbmh7PEDJWcAmM95Uo6RZsjE2cZcQTW8q3AXWAZXaTmyMnzA4Z1mFKcDF lOBB5SvS75bpfiy/j4lmZ1bVhbRJY/8LZGZ6FhNCTjyToCzUkIs3NMtCaR0UmG9hTPAY ITEQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=9UKJs7bSYshiNCpbGIPWwCRi4TXlyyRz3ngV2Dn2lOE=; b=YeTlRr/EWEjmfZGh031V12wnAIFovW9245pgdTTznRSC0XM/WoNp+v+4tBo/5RyJxa lrZlJlLE3xZm2+hFSqb+C3VZRcb61eEiahZjDSHIiLCOInYu72LbcxiE/5/yDkxHlc6g zTUxgU9q2/r9pcewB+TdEaeR9+4ldldbne/sQmtUAXHi7/m+SpBq6CZuHOFaS6Rajtwo 7PKt/nbVoAebeSJbKw754ZpAfHXkYf4N/Z74gfdHfdurS/MHYd1XXXZinJErStUEqgr9 jGOv5k8lEnqKwyGUTNS4LJayT9N3dXlYLvI2m6FK9NfjMe666hT0GT0QDqaNoy4rXWDv b6Vg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Q8oXGhjR; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id i3si562739pli.293.2017.09.20.23.19.03; Wed, 20 Sep 2017 23:19:03 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Q8oXGhjR; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751825AbdIUGTB (ORCPT + 26 others); Thu, 21 Sep 2017 02:19:01 -0400 Received: from mail-pg0-f42.google.com ([74.125.83.42]:53862 "EHLO mail-pg0-f42.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751743AbdIUGS4 (ORCPT ); Thu, 21 Sep 2017 02:18:56 -0400 Received: by mail-pg0-f42.google.com with SMTP id j70so3009154pgc.10 for ; Wed, 20 Sep 2017 23:18:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=9UKJs7bSYshiNCpbGIPWwCRi4TXlyyRz3ngV2Dn2lOE=; b=Q8oXGhjRMjQAipu81SRyxqO2u7YI1xau+51QL9yIkOyV1uJqzIzGEQxdNRbBA54HMR 8glGl0RV2V1L7LEpQ59SgrML58lRIc73cRGZUsdmQWvJr2bGP3nU314ZiEb4j+eOEZIN mr+K3kLa6TSGAnrmNTU5QRF8L6V+ULcwxLqbA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=9UKJs7bSYshiNCpbGIPWwCRi4TXlyyRz3ngV2Dn2lOE=; b=NANkc4o2tBA95b68Rp0UfthPjG+sZtzaZfg9nqHwjywDevGmrf3cUZlENBwrd9fr6Z sCc4f8NYu/cv6/v9Yp/6/z+CBW3Wf44PRqWFerxDTwTyp6sRqjn9ht9gz+gWTAGXHjym gjsFkKfv7qQfFo8jmgw7tb37A/0YyE9EcDvGEOAXkHh1F/zBTRe686DlAl9yhAOdmPOi GGBf4Ss2xEeHzDzxIBFsJa8uyRY+oqWK08lhEdQ5dDSQb0Qc+uwiYJX0634vS21LQSkw RlqsbkqBnuFVCEEsjfizQvLczZdMGK2q7nMhXjK7hKDxwiDevtSxrjempqUdl/3EeoDq L4EQ== X-Gm-Message-State: AHPjjUg0Vw/Z99a64K0cjYbGoRzxsCvCjEGFsudG58yhnz2c+t2DVjHm 4YMXZc/rX4rZqIlG4dVsWYrzIg== X-Google-Smtp-Source: AOwi7QCRVHj5+KX+DJbuq+7kG1odsk+CRbk8U5SaJBDV6LDqpv2j2z7FcFQuwUJ9zr117yNyfusjSw== X-Received: by 10.84.238.143 with SMTP id v15mr4576173plk.303.1505974735836; Wed, 20 Sep 2017 23:18:55 -0700 (PDT) Received: from baolinwangubtpc.spreadtrum.com ([117.18.48.82]) by smtp.gmail.com with ESMTPSA id q23sm1037773pfk.182.2017.09.20.23.18.50 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 20 Sep 2017 23:18:55 -0700 (PDT) From: Baolin Wang To: perex@perex.cz, tiwai@suse.com Cc: lgirdwood@gmail.com, mingo@kernel.org, o-takashi@sakamocchi.jp, elfring@users.sourceforge.net, dan.carpenter@oracle.com, jeeja.kp@intel.com, vinod.koul@intel.com, dharageswari.r@intel.com, guneshwor.o.singh@intel.com, bhumirks@gmail.com, gudishax.kranthikumar@intel.com, naveen.m@intel.com, hardik.t.shah@intel.com, arvind.yadav.cs@gmail.com, fabf@skynet.be, arnd@arndb.de, broonie@kernel.org, deepa.kernel@gmail.com, baolin.wang@linaro.org, alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 5/7] sound: core: Avoid using timespec for struct snd_timer_status Date: Thu, 21 Sep 2017 14:18:07 +0800 Message-Id: X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The struct snd_timer_status will use 'timespec' type variables to record timestamp, which is not year 2038 safe on 32bits system. Thus thia patch introduces 'struct snd_timer_status32' and 'struct snd_timer_status64' to handle 32bit time_t and 64bit time_t in native mode, which replace timespec with s64 type. In compat mode, this patch renamed the structure as 'struct compat_snd_timer_status32' to handle 32bit time_t. Moreover we should use 'struct snd_timer_status64' to handle 64bit time_t no matter 32bit or 64bit alignment, since they have the same size. 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 --- sound/core/timer.c | 66 ++++++++++++++++++++++++++++++++++++++++----- sound/core/timer_compat.c | 25 ++++++----------- 2 files changed, 68 insertions(+), 23 deletions(-) -- 1.7.9.5 diff --git a/sound/core/timer.c b/sound/core/timer.c index f44d702..376b7e6 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -79,6 +79,30 @@ struct snd_timer_user { struct mutex ioctl_lock; }; +#if __BITS_PER_LONG == 32 +struct snd_timer_status32 { + struct { s32 tv_sec; s32 tv_nsec; } tstamp; /* Timestamp - last update */ + unsigned int resolution; /* current period resolution in ns */ + unsigned int lost; /* counter of master tick lost */ + unsigned int overrun; /* count of read queue overruns */ + unsigned int queue; /* used queue size */ + unsigned char reserved[64]; /* reserved */ +}; + +#define SNDRV_TIMER_IOCTL_STATUS32 _IOR('T', 0x14, struct snd_timer_status32) +#endif + +struct snd_timer_status64 { + struct { s64 tv_sec; s64 tv_nsec; } tstamp; /* Timestamp - last update */ + unsigned int resolution; /* current period resolution in ns */ + unsigned int lost; /* counter of master tick lost */ + unsigned int overrun; /* count of read queue overruns */ + unsigned int queue; /* used queue size */ + unsigned char reserved[64]; /* reserved */ +}; + +#define SNDRV_TIMER_IOCTL_STATUS64 _IOR('T', 0x14, struct snd_timer_status64) + /* list of timers */ static LIST_HEAD(snd_timer_list); @@ -1798,17 +1822,43 @@ static int snd_timer_user_params(struct file *file, return err; } -static int snd_timer_user_status(struct file *file, - struct snd_timer_status __user *_status) +#if __BITS_PER_LONG == 32 +static int snd_timer_user_status32(struct file *file, + struct snd_timer_status32 __user *_status) + { + struct snd_timer_user *tu; + struct snd_timer_status32 status; + + tu = file->private_data; + if (!tu->timeri) + return -EBADFD; + memset(&status, 0, sizeof(status)); + status.tstamp.tv_sec = tu->tstamp.tv_sec; + status.tstamp.tv_nsec = tu->tstamp.tv_nsec; + status.resolution = snd_timer_resolution(tu->timeri); + status.lost = tu->timeri->lost; + status.overrun = tu->overrun; + spin_lock_irq(&tu->qlock); + status.queue = tu->qused; + spin_unlock_irq(&tu->qlock); + if (copy_to_user(_status, &status, sizeof(status))) + return -EFAULT; + return 0; +} +#endif + +static int snd_timer_user_status64(struct file *file, + struct snd_timer_status64 __user *_status) { struct snd_timer_user *tu; - struct snd_timer_status status; + struct snd_timer_status64 status; tu = file->private_data; if (!tu->timeri) return -EBADFD; memset(&status, 0, sizeof(status)); - status.tstamp = timespec64_to_timespec(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.lost = tu->timeri->lost; status.overrun = tu->overrun; @@ -1920,8 +1970,12 @@ static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd, return snd_timer_user_info(file, argp); case SNDRV_TIMER_IOCTL_PARAMS: return snd_timer_user_params(file, argp); - case SNDRV_TIMER_IOCTL_STATUS: - return snd_timer_user_status(file, argp); +#if __BITS_PER_LONG == 32 + case SNDRV_TIMER_IOCTL_STATUS32: + return snd_timer_user_status32(file, argp); +#endif + case SNDRV_TIMER_IOCTL_STATUS64: + return snd_timer_user_status64(file, argp); case SNDRV_TIMER_IOCTL_START: case SNDRV_TIMER_IOCTL_START_OLD: return snd_timer_user_start(file); diff --git a/sound/core/timer_compat.c b/sound/core/timer_compat.c index 6a437eb..c592603 100644 --- a/sound/core/timer_compat.c +++ b/sound/core/timer_compat.c @@ -83,7 +83,7 @@ static int snd_timer_user_info_compat(struct file *file, return 0; } -struct snd_timer_status32 { +struct compat_snd_timer_status32 { struct compat_timespec tstamp; u32 resolution; u32 lost; @@ -93,10 +93,10 @@ struct snd_timer_status32 { }; static int snd_timer_user_status_compat(struct file *file, - struct snd_timer_status32 __user *_status) + struct compat_snd_timer_status32 __user *_status) { struct snd_timer_user *tu; - struct snd_timer_status32 status; + struct compat_snd_timer_status32 status; tu = file->private_data; if (snd_BUG_ON(!tu->timeri)) @@ -115,12 +115,6 @@ static int snd_timer_user_status_compat(struct file *file, 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 */ - /* */ @@ -128,9 +122,8 @@ enum { SNDRV_TIMER_IOCTL_GPARAMS32 = _IOW('T', 0x04, struct snd_timer_gparams32), SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32), 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 */ + SNDRV_TIMER_IOCTL_STATUS_COMPAT32 = _IOW('T', 0x14, struct compat_snd_timer_status32), + SNDRV_TIMER_IOCTL_STATUS_COMPAT64 = _IOW('T', 0x14, struct snd_timer_status64), }; static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) @@ -158,12 +151,10 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, uns return snd_timer_user_gparams_compat(file, argp); case SNDRV_TIMER_IOCTL_INFO32: return snd_timer_user_info_compat(file, argp); - case SNDRV_TIMER_IOCTL_STATUS32: + case SNDRV_TIMER_IOCTL_STATUS_COMPAT32: 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 */ + case SNDRV_TIMER_IOCTL_STATUS_COMPAT64: + return snd_timer_user_status64(file, argp); } return -ENOIOCTLCMD; } From patchwork Thu Sep 21 06:18:08 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "\(Exiting\) Baolin Wang" X-Patchwork-Id: 113195 Delivered-To: patch@linaro.org Received: by 10.140.106.117 with SMTP id d108csp1641491qgf; Wed, 20 Sep 2017 23:19:06 -0700 (PDT) X-Received: by 10.98.76.70 with SMTP id z67mr4661747pfa.78.1505974746035; Wed, 20 Sep 2017 23:19:06 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1505974746; cv=none; d=google.com; s=arc-20160816; b=XWleGjGZk/+HbriYuC0Z46GvpYV7zEO+W4HxuzSUcRXaG08q8SNMahga+eP/TOBC6X knMYVlBTOh47RvJF8NJ88Ukb98zc/sVvqjviRGnUjFw7Dbm40/F6FuN+DmJsgIn0igjh ZGkvy54yTUzYja31xOiqQWAMQtwgrpxw7YfSCx1Ld4nZYmTbsPpeaDvefqxwB9c/cOfp 8vwxNJXxqQrLBOPCh+qQwmaL09Y9WeIPD/jHD8y+WLVTMrDPJbkk59XfCUYyqslU26Ig fPqWV0lwyLGHdGPqFVFOeAzpDAA815Wyx2EvRxxdg4lgIItlJjVj4knXWAPt6aU9eOl7 AlAQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=hqQlmYft16Py82zVPENySRlvYUvy2LphLnOwzFzB0aU=; b=i7iiVIhV1/4v1x2gScBsXyQx7D+0FGq2c38UNzWwDq/YySZXMG5PoGfr8mfzZ1NT64 FpLOyvpCLn7pCJip21K7qQrH+ULwW/yyH9GoUuwhACb7q4fVBpI+QCsMT5whp11kOzTo eFnONdYg5pEqUyMZEHQ0PpeboNRHQtckWA8gt1j4n4SqVuEOaQ1YEZ641RZ7TwuYzwSi 39xbPDSgk9RZVxQ4pyNBpPcQ42+Te2aeWrQy9g7ubGwMOGSMY/1GTOFeDFmxybi3yKQf ynbmjBPJWRR/LoZRTBZj7ibQR/5hYHaGGCxvZHrtj/D8jWamjuEcT+n7QCKOHcxvwREo iMNw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=BonFcXlG; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id i3si562739pli.293.2017.09.20.23.19.05; Wed, 20 Sep 2017 23:19:06 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=BonFcXlG; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751845AbdIUGTE (ORCPT + 26 others); Thu, 21 Sep 2017 02:19:04 -0400 Received: from mail-pg0-f52.google.com ([74.125.83.52]:46139 "EHLO mail-pg0-f52.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751743AbdIUGTC (ORCPT ); Thu, 21 Sep 2017 02:19:02 -0400 Received: by mail-pg0-f52.google.com with SMTP id i130so3018544pgc.3 for ; Wed, 20 Sep 2017 23:19:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=hqQlmYft16Py82zVPENySRlvYUvy2LphLnOwzFzB0aU=; b=BonFcXlGFRaSwY3BSZ2Zaca5fzx1JYi7h2GBmBDZr+zT2CefsQcCqa6LC9yR3h4LNj P/Dl4D5N6GuHNUz08aUqHrHVavPLlU5IL7BXfSoWJIqABLC5KbbFrsTPtXDjg0q8WgRx OT/qkg/UJdfgLBw3oNflzgz9/AXOjygbXvQok= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=hqQlmYft16Py82zVPENySRlvYUvy2LphLnOwzFzB0aU=; b=bFZWVsyizsBVBCBsOb5PpwIjK2lFpRtIXTYp+l9XFJZUYeGgli8bd7/nyQR6AO3oSv pjO23bGorgZ8WshRHGFaUUvAACxAbHIWmxe3motQdqFJt+bSDlg8P5tzWjBNGlw1S1jK Q+/XSuuC0aRaxmLqTTYJpw23VOm/7NFLmBau4JY4xC1WnQQ+KjcaOZ9qBf2NdWVTKWaZ MobYsotiY26aca0FZBq/ygKD/lvi0MJqq+iLTQwRdkuDC0f4M1VU68US2Wod6jwugtJE bOsrIuIUG7G7kg+3Zz+1TUHoKekQ2U/J+QYUl0GAJf51e+41ZwjyHriG/OXkJbdEmLUQ zHSw== X-Gm-Message-State: AHPjjUjfM+opTpo34kI5X5iMys5YMYm4YqtNURqaHm2uSqoUE1OvdQnj NWnGD0BlGAsOLIkASSF9vy9inA== X-Google-Smtp-Source: AOwi7QDC4t6/0RUwsEXYhJsXiZEX3siLhp70j5bcYOWBmp1MousQ3QT1SwWPRwgTZdvPnzz3GuNBnA== X-Received: by 10.101.81.135 with SMTP id h7mr4753564pgq.48.1505974741977; Wed, 20 Sep 2017 23:19:01 -0700 (PDT) Received: from baolinwangubtpc.spreadtrum.com ([117.18.48.82]) by smtp.gmail.com with ESMTPSA id q23sm1037773pfk.182.2017.09.20.23.18.56 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 20 Sep 2017 23:19:01 -0700 (PDT) From: Baolin Wang To: perex@perex.cz, tiwai@suse.com Cc: lgirdwood@gmail.com, mingo@kernel.org, o-takashi@sakamocchi.jp, elfring@users.sourceforge.net, dan.carpenter@oracle.com, jeeja.kp@intel.com, vinod.koul@intel.com, dharageswari.r@intel.com, guneshwor.o.singh@intel.com, bhumirks@gmail.com, gudishax.kranthikumar@intel.com, naveen.m@intel.com, hardik.t.shah@intel.com, arvind.yadav.cs@gmail.com, fabf@skynet.be, arnd@arndb.de, broonie@kernel.org, deepa.kernel@gmail.com, baolin.wang@linaro.org, alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 6/7] uapi: sound: Avoid using timespec for struct snd_ctl_elem_value Date: Thu, 21 Sep 2017 14:18:08 +0800 Message-Id: X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The struct snd_ctl_elem_value will use 'timespec' type variables to record timestamp, which is not year 2038 safe on 32bits system. Since there are no drivers will implemented the tstamp member of the struct snd_ctl_elem_value, and also the stucture size will not be changed if we change timespec to s64 for tstamp member of struct snd_ctl_elem_value. Thus we can simply change timespec to s64 for tstamp member to avoid using the type which is not year 2038 safe on 32bits system. Signed-off-by: Baolin Wang --- include/uapi/sound/asound.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) -- 1.7.9.5 diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h index 1949923..71bce52 100644 --- a/include/uapi/sound/asound.h +++ b/include/uapi/sound/asound.h @@ -943,8 +943,8 @@ struct snd_ctl_elem_value { } bytes; struct snd_aes_iec958 iec958; } value; /* RO */ - struct timespec tstamp; - unsigned char reserved[128-sizeof(struct timespec)]; + struct { s64 tv_sec; s64 tv_nsec; } tstamp; + unsigned char reserved[128-sizeof(struct { s64 tv_sec; s64 tv_nsec; })]; }; struct snd_ctl_tlv { From patchwork Thu Sep 21 06:18:09 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "\(Exiting\) Baolin Wang" X-Patchwork-Id: 113196 Delivered-To: patch@linaro.org Received: by 10.140.106.117 with SMTP id d108csp1641567qgf; Wed, 20 Sep 2017 23:19:13 -0700 (PDT) X-Received: by 10.99.117.30 with SMTP id q30mr4773834pgc.106.1505974753350; Wed, 20 Sep 2017 23:19:13 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1505974753; cv=none; d=google.com; s=arc-20160816; b=nLe0UOYVOgxoypMZK2YDD46sD02lVGkkBq8zjz8aqqv7VQCkRx8OUaJY3DvP+k2kJo fXveBY7CVc3Q9swxCABPh9CyhKpzzR1rsROwzQtVn0RbuzdV6KIJYWn9aXNVXo89ynQI A0AAW9LjN+PArL7S1alfixqYZU5fIAynzW9aiNhYLjKl31dwqlQVvpHPT/KNNM7vvNJ2 yEWmIu29tSzKmqd6UQLK6q1R4GyhCCvgBG0s9CDXDyswRDKCptnyTLeVgAA2xl7BmHr7 OlABuosp9H8I0Sh33hoBajHdRJ9dsfNnbxRQDuQfmAt+VsAcgCQ/K9kAKP+CgnDQBVVU B/3A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=0Cgp7uMZp8Q7aQLqjS0d1mCT6cjLeCenTiMXIxR1FOI=; b=Rw298GEOTyhBLIlB4hdNgtHflB8DoNBiTZGAAtiFq/6Je5gexm7Ym+CfjXmPu+ieAf IZ9bFc+gO1qTHDgDnKOM46Z9AwkwkrnDIhr7gsgPpX/ghR93Kf2QOmMuF4epTV7mSfbg uTmQ7N5YmJAto/Fu9GJr2eb34WnYNKIiYsmNatPWHjy6uvhTkkNAACt80alGKMr0mxB/ 8ts65kB8VIPdlHZQRx7IHTLO6X/u3piFJIB9qhxo07DgyWoEnQ+Mtw1L7+gDikNIalhP MjaF1z8iugNZwVjloF/DvTuvjIHfsELDQ1nJs2z+4JTNNW9xvc8mC69KMoqoBdinH+AN MInA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=J8xqLa8o; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id v6si565935pgf.178.2017.09.20.23.19.13; Wed, 20 Sep 2017 23:19:13 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=J8xqLa8o; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751864AbdIUGTL (ORCPT + 26 others); Thu, 21 Sep 2017 02:19:11 -0400 Received: from mail-pg0-f51.google.com ([74.125.83.51]:49989 "EHLO mail-pg0-f51.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751743AbdIUGTI (ORCPT ); Thu, 21 Sep 2017 02:19:08 -0400 Received: by mail-pg0-f51.google.com with SMTP id m30so3013799pgn.6 for ; Wed, 20 Sep 2017 23:19:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=0Cgp7uMZp8Q7aQLqjS0d1mCT6cjLeCenTiMXIxR1FOI=; b=J8xqLa8obDob3n0634Q+c5g5y7s+aRQXTta2qoinsJw5Xc8ZaEv2kAHnsvGGjetkUT EEV2EyIqtOPDujZa5pt+70N0H1N5jMv5nwtEwfT2s3Ew8gfcWtbEUyZMlboiryn+nBca 6lLSnD2TGC1psHnU1Q2y+PRGamejPrKmFDFIw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=0Cgp7uMZp8Q7aQLqjS0d1mCT6cjLeCenTiMXIxR1FOI=; b=nKACDWv5aIsR5RjbAaQ8GPNg6Q9uFv0W/BmaO15a9hqzZioBGdohYGzt0awlfQ9v/T Hfmxlw9hu1vpvbUYuzAcHi3ZJCLLK9W8jxJ0hNEnHvH272C/JU9kDSet5zqicE0w1Lmy Aw/zgOdsU6rXoE2eo+wTQF2pceBzjX0mbrfMEa2ij8m6gcBCBgZmFXu2yjwaYa4RGZJd oCjD2hVU6e94RyFbH8dq/pG96Ostrsqu3GcmX7VkjYbOtsnXL2FvO61GPVAL8ypT++eK PeWsLfCaHye9ZblpmKjCNKOtfnvPEhV0gnnkSs4kiwh4DkYJ1HXpLkQVWLHQl1rRXsv4 ga0A== X-Gm-Message-State: AHPjjUgoVYj4b+VJR0TCx8Gv4HUe1nwlLTDsXc47URCUZ1+GnvVeNlsq I383AU19mr5ySzwpt9RdhtDz4A== X-Google-Smtp-Source: AOwi7QAsfL6CLzTpr4Ct4XakgnypYcjCRjAaOBBb+VaTaj2Liaheu2eAncqQwp09mL0vX9tfXuNGwA== X-Received: by 10.99.115.28 with SMTP id o28mr4696515pgc.374.1505974748314; Wed, 20 Sep 2017 23:19:08 -0700 (PDT) Received: from baolinwangubtpc.spreadtrum.com ([117.18.48.82]) by smtp.gmail.com with ESMTPSA id q23sm1037773pfk.182.2017.09.20.23.19.02 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 20 Sep 2017 23:19:07 -0700 (PDT) From: Baolin Wang To: perex@perex.cz, tiwai@suse.com Cc: lgirdwood@gmail.com, mingo@kernel.org, o-takashi@sakamocchi.jp, elfring@users.sourceforge.net, dan.carpenter@oracle.com, jeeja.kp@intel.com, vinod.koul@intel.com, dharageswari.r@intel.com, guneshwor.o.singh@intel.com, bhumirks@gmail.com, gudishax.kranthikumar@intel.com, naveen.m@intel.com, hardik.t.shah@intel.com, arvind.yadav.cs@gmail.com, fabf@skynet.be, arnd@arndb.de, broonie@kernel.org, deepa.kernel@gmail.com, baolin.wang@linaro.org, alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 7/7] sound: core: Avoid using timespec for struct snd_timer_tread Date: Thu, 21 Sep 2017 14:18:09 +0800 Message-Id: <1091b589bec6317ea686937060c0f9f9db10651a.1505973912.git.baolin.wang@linaro.org> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The struct snd_timer_tread will use 'timespec' type variables to record timestamp, which is not year 2038 safe on 32bits system. Since the struct snd_timer_tread is passed through read() rather than ioctl(), and the read syscall has no command number that lets us pick between the 32-bit or 64-bit version of this structure. Thus we introduced one new command SNDRV_TIMER_IOCTL_TREAD64 and new struct snd_timer_tread64 replacing timespec with s64 type to handle 64bit time_t. Also add one struct compat_snd_timer_tread64_x86_32 to handle 64bit time_t with 32bit alignment. That means we will set tu->tread = 2 when user space has a 64bit time_t, then we will copy to user with struct snd_timer_tread64. For x86_32 mode, we will set tu->tread = 3 to copy struct compat_snd_timer_tread64_x86_32 for user. Otherwise we will use 32bit time_t variables when copying to user. Moreover this patch replaces timespec type with timespec64 type and related y2038 safe APIs. Signed-off-by: Baolin Wang --- include/uapi/sound/asound.h | 11 ++- sound/core/timer.c | 163 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 142 insertions(+), 32 deletions(-) -- 1.7.9.5 diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h index 71bce52..ef738bf 100644 --- a/include/uapi/sound/asound.h +++ b/include/uapi/sound/asound.h @@ -760,7 +760,7 @@ struct snd_timer_status { #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) @@ -773,6 +773,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; diff --git a/sound/core/timer.c b/sound/core/timer.c index 376b7e6..c33a1be 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -58,6 +58,22 @@ MODULE_ALIAS_CHARDEV(CONFIG_SND_MAJOR, SNDRV_MINOR_TIMER); MODULE_ALIAS("devname:snd/timer"); +struct snd_timer_tread64 { + int event; + u32 pad1; + struct { s64 tv_sec; s64 tv_nsec; } tstamp; + unsigned int val; + u32 pad2; +}; + +#ifdef IA32_EMULATION +struct compat_snd_timer_tread64_x86_32 { + int event; + struct { s64 tv_sec; s64 tv_nsec; } tstamp; + unsigned int val; +} __packed; +#endif + struct snd_timer_user { struct snd_timer_instance *timeri; int tread; /* enhanced read with timestamps and events */ @@ -69,7 +85,7 @@ struct snd_timer_user { int queue_size; bool disconnected; struct snd_timer_read *queue; - struct snd_timer_tread *tqueue; + struct snd_timer_tread64 *tqueue; spinlock_t qlock; unsigned long last_resolution; unsigned int filter; @@ -1262,7 +1278,7 @@ static void snd_timer_user_interrupt(struct snd_timer_instance *timeri, } static void snd_timer_user_append_to_tqueue(struct snd_timer_user *tu, - struct snd_timer_tread *tread) + struct snd_timer_tread64 *tread) { if (tu->qused >= tu->queue_size) { tu->overrun++; @@ -1279,7 +1295,7 @@ static void snd_timer_user_ccallback(struct snd_timer_instance *timeri, unsigned long resolution) { struct snd_timer_user *tu = timeri->callback_data; - struct snd_timer_tread r1; + struct snd_timer_tread64 r1; unsigned long flags; if (event >= SNDRV_TIMER_EVENT_START && @@ -1289,7 +1305,8 @@ static void snd_timer_user_ccallback(struct snd_timer_instance *timeri, return; memset(&r1, 0, sizeof(r1)); r1.event = event; - r1.tstamp = timespec64_to_timespec(*tstamp); + r1.tstamp.tv_sec = tstamp->tv_sec; + r1.tstamp.tv_nsec = tstamp->tv_nsec; r1.val = resolution; spin_lock_irqsave(&tu->qlock, flags); snd_timer_user_append_to_tqueue(tu, &r1); @@ -1311,7 +1328,7 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri, unsigned long ticks) { struct snd_timer_user *tu = timeri->callback_data; - struct snd_timer_tread *r, r1; + struct snd_timer_tread64 *r, r1; struct timespec64 tstamp; int prev, append = 0; @@ -1332,7 +1349,8 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri, if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) && tu->last_resolution != resolution) { r1.event = SNDRV_TIMER_EVENT_RESOLUTION; - r1.tstamp = timespec64_to_timespec(tstamp); + r1.tstamp.tv_sec = tstamp.tv_sec; + r1.tstamp.tv_nsec = tstamp.tv_nsec; r1.val = resolution; snd_timer_user_append_to_tqueue(tu, &r1); tu->last_resolution = resolution; @@ -1346,14 +1364,16 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri, prev = tu->qtail == 0 ? tu->queue_size - 1 : tu->qtail - 1; r = &tu->tqueue[prev]; if (r->event == SNDRV_TIMER_EVENT_TICK) { - r->tstamp = timespec64_to_timespec(tstamp); + r->tstamp.tv_sec = tstamp.tv_sec; + r->tstamp.tv_nsec = tstamp.tv_nsec; r->val += ticks; append++; goto __wake; } } r1.event = SNDRV_TIMER_EVENT_TICK; - r1.tstamp = timespec64_to_timespec(tstamp); + r1.tstamp.tv_sec = tstamp.tv_sec; + r1.tstamp.tv_nsec = tstamp.tv_nsec; r1.val = ticks; snd_timer_user_append_to_tqueue(tu, &r1); append++; @@ -1368,7 +1388,7 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri, static int realloc_user_queue(struct snd_timer_user *tu, int size) { struct snd_timer_read *queue = NULL; - struct snd_timer_tread *tqueue = NULL; + struct snd_timer_tread64 *tqueue = NULL; if (tu->tread) { tqueue = kcalloc(size, sizeof(*tqueue), GFP_KERNEL); @@ -1797,7 +1817,7 @@ static int snd_timer_user_params(struct file *file, tu->qhead = tu->qtail = tu->qused = 0; if (tu->timeri->flags & SNDRV_TIMER_IFLG_EARLY_EVENT) { if (tu->tread) { - struct snd_timer_tread tread; + struct snd_timer_tread64 tread; memset(&tread, 0, sizeof(tread)); tread.event = SNDRV_TIMER_EVENT_EARLY; tread.tstamp.tv_sec = 0; @@ -1921,6 +1941,39 @@ static int snd_timer_user_pause(struct file *file) return (err = snd_timer_pause(tu->timeri)) < 0 ? err : 0; } +static int snd_timer_user_tread(void __user *argp, struct snd_timer_user *tu, + unsigned int cmd) +{ + int __user *p = argp; + int xarg, old_tread; + + if (tu->timeri) /* too late */ + return -EBUSY; + if (get_user(xarg, p)) + return -EFAULT; + + old_tread = tu->tread; +#if __BITS_PER_LONG == 64 + tu->tread = xarg ? 2 : 0; +#ifdef IA32_EMULATION + tu->tread = xarg ? 3 : 0; +#endif +#else + if (cmd == SNDRV_TIMER_IOCTL_TREAD64) + tu->tread = xarg ? 2 : 0; + else + tu->tread = xarg ? 1 : 0; +#endif + + if (tu->tread != old_tread && + realloc_user_queue(tu, tu->queue_size) < 0) { + tu->tread = old_tread; + return -ENOMEM; + } + + return 0; +} + enum { SNDRV_TIMER_IOCTL_START_OLD = _IO('T', 0x20), SNDRV_TIMER_IOCTL_STOP_OLD = _IO('T', 0x21), @@ -1941,23 +1994,9 @@ static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd, return put_user(SNDRV_TIMER_VERSION, p) ? -EFAULT : 0; case SNDRV_TIMER_IOCTL_NEXT_DEVICE: return snd_timer_user_next_device(argp); - case SNDRV_TIMER_IOCTL_TREAD: - { - int xarg, old_tread; - - if (tu->timeri) /* too late */ - return -EBUSY; - if (get_user(xarg, p)) - return -EFAULT; - old_tread = tu->tread; - tu->tread = xarg ? 1 : 0; - if (tu->tread != old_tread && - realloc_user_queue(tu, tu->queue_size) < 0) { - tu->tread = old_tread; - return -ENOMEM; - } - return 0; - } + case SNDRV_TIMER_IOCTL_TREAD_OLD: + case SNDRV_TIMER_IOCTL_TREAD64: + return snd_timer_user_tread(argp, tu, cmd); case SNDRV_TIMER_IOCTL_GINFO: return snd_timer_user_ginfo(file, argp); case SNDRV_TIMER_IOCTL_GPARAMS: @@ -2021,7 +2060,25 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, int err = 0; tu = file->private_data; - unit = tu->tread ? sizeof(struct snd_timer_tread) : sizeof(struct snd_timer_read); + switch (tu->tread) { +#ifdef IA32_EMULATION + case 3: + unit = sizeof(struct compat_snd_timer_tread64_x86_32); + break; +#endif + case 2: + unit = sizeof(struct snd_timer_tread64); + break; + case 1: + unit = sizeof(struct snd_timer_tread); + break; + case 0: + unit = sizeof(struct snd_timer_read); + break; + default: + return -ENOTSUPP; + } + mutex_lock(&tu->ioctl_lock); spin_lock_irq(&tu->qlock); while ((long)count - result >= unit) { @@ -2061,9 +2118,53 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, spin_unlock_irq(&tu->qlock); if (tu->tread) { - if (copy_to_user(buffer, &tu->tqueue[qhead], - sizeof(struct snd_timer_tread))) - err = -EFAULT; + struct snd_timer_tread64 *tread = &tu->tqueue[qhead]; + struct snd_timer_tread tread32; +#ifdef IA32_EMULATION + struct compat_snd_timer_tread64_x86_32 compat_tread64; +#endif + + switch (tu->tread) { +#ifdef IA32_EMULATION + case 3: + memset(&compat_tread64, 0, sizeof(compat_tread64)); + compat_tread64 = (struct compat_snd_timer_tread64_x86_32) { + .event = tread->event, + .tstamp = { + .tv_sec = tread->tstamp.tv_sec, + .tv_nsec = tread->tstamp.tv_nsec, + }, + .val = tread->val, + }; + + if (copy_to_user(buffer, &compat_tread64, + sizeof(compat_tread64))) + err = -EFAULT; + break; +#endif + case 2: + if (copy_to_user(buffer, tread, + sizeof(struct snd_timer_tread64))) + err = -EFAULT; + break; + case 1: + memset(&tread32, 0, sizeof(tread32)); + tread32 = (struct snd_timer_tread) { + .event = tread->event, + .tstamp = { + .tv_sec = tread->tstamp.tv_sec, + .tv_nsec = tread->tstamp.tv_nsec, + }, + .val = tread->val, + }; + + if (copy_to_user(buffer, &tread32, sizeof(tread32))) + err = -EFAULT; + break; + default: + err = -ENOTSUPP; + break; + } } else { if (copy_to_user(buffer, &tu->queue[qhead], sizeof(struct snd_timer_read)))