From patchwork Wed Oct 23 21:45:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pierre-Louis Bossart X-Patchwork-Id: 11207783 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CBD4D14E5 for ; Wed, 23 Oct 2019 21:48:52 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5FDA520659 for ; Wed, 23 Oct 2019 21:48:52 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="b7/ltrtn" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5FDA520659 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id AFCA2167D; Wed, 23 Oct 2019 23:48:00 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz AFCA2167D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1571867330; bh=qAzK3z6VW6G11sHeTxVKNYYB8irEwKGWDtGpF/Ubz6o=; h=From:To:Date:In-Reply-To:References:Cc:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=b7/ltrtnrx5JQ5Fc0E3vCIfjhXq0ycdzIvtNAhq8KK8lDC71+P80d/rMEliy2IHwA 8hxD59UmAh+rZjNNleD/1QjTJWhgCT0K7zvPtCmkZ3pGwl5r/wGlaGlfBYKIRVSdYX eDsZsDsaH7qFKF/Wj8FSIxB9Cq4/mqsa3u5rE11k= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id CB911F80274; Wed, 23 Oct 2019 23:46:22 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa1.perex.cz (Postfix, from userid 50401) id 5F24DF8058C; Wed, 23 Oct 2019 23:46:20 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on alsa1.perex.cz X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=SPF_HELO_NONE,SPF_NONE, SURBL_BLOCKED,URIBL_BLOCKED autolearn=disabled version=3.4.0 Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 2F038F802DF for ; Wed, 23 Oct 2019 23:46:16 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 2F038F802DF X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 23 Oct 2019 14:46:15 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.68,222,1569308400"; d="scan'208";a="196908123" Received: from ayamada-mobl1.gar.corp.intel.com (HELO pbossart-mobl3.intel.com) ([10.254.95.208]) by fmsmga008.fm.intel.com with ESMTP; 23 Oct 2019 14:46:13 -0700 From: Pierre-Louis Bossart To: alsa-devel@alsa-project.org Date: Wed, 23 Oct 2019 16:45:45 -0500 Message-Id: <20191023214601.883-3-pierre-louis.bossart@linux.intel.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191023214601.883-1-pierre-louis.bossart@linux.intel.com> References: <20191023214601.883-1-pierre-louis.bossart@linux.intel.com> MIME-Version: 1.0 Cc: Pierre-Louis Bossart , tiwai@suse.de, gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org, Ranjani Sridharan , vkoul@kernel.org, broonie@kernel.org, srinivas.kandagatla@linaro.org, jank@cadence.com, slawomir.blauciak@intel.com, Sanyog Kale , Bard liao , Rander Wang Subject: [alsa-devel] [PATCH 02/18] soundwire: fix race between driver probe and update_status callback X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" The driver probe takes care of basic initialization and is invoked when a Slave becomes attached, after a match between the Slave DevID registers and ACPI/DT entries. The update_status callback is invoked when a Slave state changes, e.g. when it is assigned a non-zero Device Number and it reports with an ATTACHED/ALERT state. The state change detection is usually hardware-based and based on the SoundWire frame rate (e.g. double-digit microseconds) while the probe is a pure software operation, which may involve a kernel module load. In corner cases, it's possible that the state changes before the probe completes. This patch suggests the use of wait_for_completion to avoid races on startup, so that the update_status callback does not rely on invalid pointers/data structures. Signed-off-by: Pierre-Louis Bossart --- drivers/soundwire/bus.c | 24 +++++++++++++++++++++--- drivers/soundwire/bus.h | 1 + drivers/soundwire/bus_type.c | 5 +++++ drivers/soundwire/slave.c | 2 ++ 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index 4b22ee996a65..903aee258800 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -961,10 +961,28 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave) static int sdw_update_slave_status(struct sdw_slave *slave, enum sdw_slave_status status) { - if (slave->ops && slave->ops->update_status) - return slave->ops->update_status(slave, status); + unsigned long time; - return 0; + if (!slave->ops || !slave->ops->update_status) + return 0; + + if (!slave->probed) { + /* + * the slave status update is typically handled in an + * interrupt thread, which can race with the driver + * probe, e.g. when a module needs to be loaded. + * + * make sure the probe is complete before updating + * status. + */ + time = wait_for_completion_timeout(&slave->probe_complete, + msecs_to_jiffies(DEFAULT_PROBE_TIMEOUT)); + if (!time) { + dev_err(&slave->dev, "Probe not complete, timed out\n"); + return -ETIMEDOUT; + } + } + return slave->ops->update_status(slave, status); } /** diff --git a/drivers/soundwire/bus.h b/drivers/soundwire/bus.h index cb482da914da..acb8d11a4c84 100644 --- a/drivers/soundwire/bus.h +++ b/drivers/soundwire/bus.h @@ -5,6 +5,7 @@ #define __SDW_BUS_H #define DEFAULT_BANK_SWITCH_TIMEOUT 3000 +#define DEFAULT_PROBE_TIMEOUT 2000 #if IS_ENABLED(CONFIG_ACPI) int sdw_acpi_find_slaves(struct sdw_bus *bus); diff --git a/drivers/soundwire/bus_type.c b/drivers/soundwire/bus_type.c index cf33f63773f0..3d52b72654c5 100644 --- a/drivers/soundwire/bus_type.c +++ b/drivers/soundwire/bus_type.c @@ -121,6 +121,11 @@ static int sdw_slave_drv_probe(struct device *dev) slave->bus->clk_stop_timeout = max_t(u32, slave->bus->clk_stop_timeout, slave->prop.clk_stop_timeout); + slave->probed = true; + complete(&slave->probe_complete); + + dev_dbg(dev, "probe complete\n"); + return 0; } diff --git a/drivers/soundwire/slave.c b/drivers/soundwire/slave.c index c87267f12a3b..81b94cd3985e 100644 --- a/drivers/soundwire/slave.c +++ b/drivers/soundwire/slave.c @@ -52,6 +52,8 @@ static int sdw_slave_add(struct sdw_bus *bus, slave->bus = bus; slave->status = SDW_SLAVE_UNATTACHED; slave->dev_num = 0; + init_completion(&slave->probe_complete); + slave->probed = false; mutex_lock(&bus->bus_lock); list_add_tail(&slave->node, &bus->slaves);