Message ID | 20230119165104.3433290-2-ckeepax@opensource.cirrus.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp440128wrn; Thu, 19 Jan 2023 09:04:09 -0800 (PST) X-Google-Smtp-Source: AMrXdXu9Osw/rMs7aERU2JmJSIEU2zi62KFhTa16z7J0qpcJevCpUFhxVQVuTjrLQoPssBfnS0ZV X-Received: by 2002:a17:907:c23:b0:7c1:ad6:7333 with SMTP id ga35-20020a1709070c2300b007c10ad67333mr14922770ejc.10.1674147849479; Thu, 19 Jan 2023 09:04:09 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1674147849; cv=none; d=google.com; s=arc-20160816; b=pbiw4wylZr3a293ovgSbFzDDq0tpAnO+HxvpxZ3lyQrVUxqIIRhJoTZ2/PJvzh3Es6 vWg6ZXENc59HbK7nAfiF3y+xhsQt/hv6eRj89DL6E1YqkCqrB8VG1+vQ5FvIyw4OGAIS QoBrcrEtqAliCSx87FdM4co6HBnJjOXf3KfTctFqJQyeIlPa8n3M7eQabfO+pMPfPdtG ZJRcPE/pgEy07DBo5y46M52hOoRsplmea7jqGpQ4q9o25ttl5NUnDusyWvQx1q4IdMVk I9fWqkJb4KZkhVSdMYFGHBa+bkZwvvqQMuCGDs4k2uj55GApHurI2E2DN2t1vbkc9z9G pKUw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=SftSV7gvE+qMf6Vai8FZHIFOJ0BkZ4KenaMUMu6OZGU=; b=W0DkWqDkQcj1uO5CBNlIhG68+oLHTKh+MHSjdyjOoNKBFQyq+i+Hz17MX2hVJiiMDa 9hotPGf/IUxb/ecSa335XIYL1nWOevcyVyJMghF6navNzTJakHLGIyMh04lXaqp3ZNN5 ms+8qEeDxnXCtutVQj7SZ9CBAq0t2h2GpLuNzxHVyzGjMna4kl8Hm1eGMEgkGFnz54e1 X9D++apw2ktFEylfgsC9BrY+uF+CIcKSAC2uqTyuda3B7XvR54NTPCmqkxnckt2gagnF bJa4ZtlX3m43ONyISFgFxvFS7b6qzoUZ/C56uM5VBHn/lwyGKwMo/WIz2hhjWnFbdneN FW4g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b=od1uJdNx; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id mp23-20020a1709071b1700b007826cb6f57csi41562227ejc.407.2023.01.19.09.03.45; Thu, 19 Jan 2023 09:04:09 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b=od1uJdNx; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230251AbjASQvw (ORCPT <rfc822;pfffrao@gmail.com> + 99 others); Thu, 19 Jan 2023 11:51:52 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43438 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229765AbjASQvT (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Thu, 19 Jan 2023 11:51:19 -0500 Received: from mx0b-001ae601.pphosted.com (mx0a-001ae601.pphosted.com [67.231.149.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 600E7829B2 for <linux-kernel@vger.kernel.org>; Thu, 19 Jan 2023 08:51:14 -0800 (PST) Received: from pps.filterd (m0077473.ppops.net [127.0.0.1]) by mx0a-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30J1KBdf020876; Thu, 19 Jan 2023 10:51:07 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=SftSV7gvE+qMf6Vai8FZHIFOJ0BkZ4KenaMUMu6OZGU=; b=od1uJdNxKbfqBeIw8DpVyiOWn/dLGvG/w5pVBF+4SHCCaIcBBG8a+9ByWJy/Z/a5d+Pd IFcE6CXiIz68b8xkNjx4QOmOLEMjVNneMsCSodhu0BhmLtlxAeOPBYdQwyTzf8yNBNNT eA4el5nUeCKrq3XHn2u2Im8Bec3o484ZN8kwa1/1CKRijyJhAgmwuEOlpyQ2upnvXAn3 Rk1Aj/iTHbXFvScmtBqiR66f0PY9m+uE7zOV4lVLqX/CBDOpyVTicq6/wCVvOmYuuvnJ hJqMLrZIEYjrBE8wDDhBg3FGf6R9Zu06/HmKyRi5kNEZkgFqo97JQ2aPU2LLHOu6DAuV IQ== Received: from ediex02.ad.cirrus.com ([84.19.233.68]) by mx0a-001ae601.pphosted.com (PPS) with ESMTPS id 3n3tp6ga7w-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 19 Jan 2023 10:51:07 -0600 Received: from ediex02.ad.cirrus.com (198.61.84.81) by ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.21; Thu, 19 Jan 2023 10:51:04 -0600 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by anon-ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server id 15.2.1118.7 via Frontend Transport; Thu, 19 Jan 2023 10:51:04 -0600 Received: from algalon.ad.cirrus.com (algalon.ad.cirrus.com [198.90.251.122]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 6BD3D11CB; Thu, 19 Jan 2023 16:51:04 +0000 (UTC) From: Charles Keepax <ckeepax@opensource.cirrus.com> To: <vkoul@kernel.org> CC: <yung-chuan.liao@linux.intel.com>, <pierre-louis.bossart@linux.intel.com>, <sanyog.r.kale@intel.com>, <alsa-devel@alsa-project.org>, <linux-kernel@vger.kernel.org>, <patches@opensource.cirrus.com> Subject: [PATCH 2/2] soundwire: bus: Allow SoundWire peripherals to register IRQ handlers Date: Thu, 19 Jan 2023 16:51:04 +0000 Message-ID: <20230119165104.3433290-2-ckeepax@opensource.cirrus.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230119165104.3433290-1-ckeepax@opensource.cirrus.com> References: <20230119165104.3433290-1-ckeepax@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-Proofpoint-ORIG-GUID: dv3xlRQxIx3faMjWQx2X1KI5vfyzj45L X-Proofpoint-GUID: dv3xlRQxIx3faMjWQx2X1KI5vfyzj45L X-Proofpoint-Spam-Reason: safe X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1755471255644857635?= X-GMAIL-MSGID: =?utf-8?q?1755471255644857635?= |
Series |
[1/2] soundwire: bus: Don't filter slave alerts
|
|
Commit Message
Charles Keepax
Jan. 19, 2023, 4:51 p.m. UTC
From: Lucas Tanure <tanureal@opensource.cirrus.com> Allow SoundWire peripherals to register a normal IRQ handler to receive SoundWire alerts. This allows sharing the IRQ code between I2C/SPI which typically use a normal IRQ handler, and SoundWire which historically used a callback. Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com> Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com> --- drivers/soundwire/bus.c | 39 +++++++++++++++++++++++++++++++++++ include/linux/soundwire/sdw.h | 9 ++++++++ 2 files changed, 48 insertions(+)
Comments
No objection on this addition, just a couple of comments to improve it: > EXPORT_SYMBOL(sdw_bus_master_add); > @@ -158,6 +183,8 @@ static int sdw_delete_slave(struct device *dev, void *data) > mutex_lock(&bus->bus_lock); > > if (slave->dev_num) { /* clear dev_num if assigned */ > + irq_dispose_mapping(irq_find_mapping(bus->domain, slave->dev_num)); > + could this be done conditionally. e.g. if (slave->prop.irq) irq_dispose_mapping(irq_find_mapping(bus->domain, slave->dev_num)); ... > clear_bit(slave->dev_num, bus->assigned); > if (bus->dev_num_ida_min) > ida_free(&sdw_peripheral_ida, slave->dev_num); > @@ -178,6 +205,9 @@ static int sdw_delete_slave(struct device *dev, void *data) > void sdw_bus_master_delete(struct sdw_bus *bus) > { > device_for_each_child(bus->dev, NULL, sdw_delete_slave); > + > + irq_domain_remove(bus->domain); > + > sdw_master_device_del(bus); > > sdw_bus_debugfs_exit(bus); > @@ -717,6 +747,12 @@ static int sdw_assign_device_num(struct sdw_slave *slave) > slave->dev_num = dev_num; > slave->dev_num_sticky = dev_num; > new_device = true; > + > + slave->irq = irq_create_mapping(bus->domain, dev_num); > + if (!slave->irq) { > + dev_err(bus->dev, "Failed to map IRQ\n"); > + return -EINVAL; > + } ...and here.... if (slave->prop.irq) { slave->irq = irq_create_mapping(bus->domain, dev_num); if (!slave->irq) { dev_err(bus->dev, "Failed to map IRQ\n"); return -EINVAL; } } > } else { > slave->dev_num = slave->dev_num_sticky; > } > @@ -1682,6 +1718,9 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave) > struct device *dev = &slave->dev; > struct sdw_driver *drv = drv_to_sdw_driver(dev->driver); > > + if (slave->prop.irq && slave->irq) > + handle_nested_irq(slave->irq); .... that would be consistent with this conditional use. > @@ -369,6 +371,7 @@ struct sdw_dpn_prop { > * @clock_reg_supported: the Peripheral implements the clock base and scale > * registers introduced with the SoundWire 1.2 specification. SDCA devices > * do not need to set this boolean property as the registers are required. > + * @irq: call actual IRQ handler on slave, as well as callback > */ > struct sdw_slave_prop { > u32 mipi_revision; > @@ -393,6 +396,7 @@ struct sdw_slave_prop { > u8 scp_int1_mask; > u32 quirks; > bool clock_reg_supported; > + bool irq; this can be confused with the 'wake_capable' property. maybe 'out_of_band_irq' ? There should be an explanation and something checking that both are not used concurrently.
On Thu, Jan 19, 2023 at 11:12:04AM -0600, Pierre-Louis Bossart wrote: > No objection on this addition, just a couple of comments to improve it: > > > EXPORT_SYMBOL(sdw_bus_master_add); > > @@ -158,6 +183,8 @@ static int sdw_delete_slave(struct device *dev, void *data) > > mutex_lock(&bus->bus_lock); > > > > if (slave->dev_num) { /* clear dev_num if assigned */ > > + irq_dispose_mapping(irq_find_mapping(bus->domain, slave->dev_num)); > > + > > could this be done conditionally. e.g. > > if (slave->prop.irq) > irq_dispose_mapping(irq_find_mapping(bus->domain, slave->dev_num)); > > > + slave->irq = irq_create_mapping(bus->domain, dev_num); > > + if (!slave->irq) { > > + dev_err(bus->dev, "Failed to map IRQ\n"); > > + return -EINVAL; > > + } > > ...and here.... > > if (slave->prop.irq) { > slave->irq = irq_create_mapping(bus->domain, dev_num); > if (!slave->irq) { > dev_err(bus->dev, "Failed to map IRQ\n"); > return -EINVAL; > } > } > Yeah I am happy to make those conditional, I guess it is cleaner to not map IRQs if they wont be used. > > @@ -369,6 +371,7 @@ struct sdw_dpn_prop { > > * @clock_reg_supported: the Peripheral implements the clock base and scale > > * registers introduced with the SoundWire 1.2 specification. SDCA devices > > * do not need to set this boolean property as the registers are required. > > + * @irq: call actual IRQ handler on slave, as well as callback > > */ > > struct sdw_slave_prop { > > u32 mipi_revision; > > @@ -393,6 +396,7 @@ struct sdw_slave_prop { > > u8 scp_int1_mask; > > u32 quirks; > > bool clock_reg_supported; > > + bool irq; > > this can be confused with the 'wake_capable' property. > > maybe 'out_of_band_irq' ? > Yes I struggle on the name a bit and then just gave up and went with plain "irq", hard to know what to call it. Not sure out_of_band is quite right since it not really out of band, handle_nested_irq pretty much basically boils down to a function call really. Maybe something like "map_irq", or "use_domain_irq"? > There should be an explanation and something checking that both are not > used concurrently. I will try to expand the explanation a litte, but I dont see any reason to block calling both handlers, no ill effects would come for a driver having both and it is useful if any soundwire specific steps are needed that arn't on other control buses. Thanks, Charles
On 1/20/23 03:59, Charles Keepax wrote: > On Thu, Jan 19, 2023 at 11:12:04AM -0600, Pierre-Louis Bossart wrote: >> No objection on this addition, just a couple of comments to improve it: >> >>> EXPORT_SYMBOL(sdw_bus_master_add); >>> @@ -158,6 +183,8 @@ static int sdw_delete_slave(struct device *dev, void *data) >>> mutex_lock(&bus->bus_lock); >>> >>> if (slave->dev_num) { /* clear dev_num if assigned */ >>> + irq_dispose_mapping(irq_find_mapping(bus->domain, slave->dev_num)); >>> + >> >> could this be done conditionally. e.g. >> >> if (slave->prop.irq) >> irq_dispose_mapping(irq_find_mapping(bus->domain, slave->dev_num)); >> >>> + slave->irq = irq_create_mapping(bus->domain, dev_num); >>> + if (!slave->irq) { >>> + dev_err(bus->dev, "Failed to map IRQ\n"); >>> + return -EINVAL; >>> + } >> >> ...and here.... >> >> if (slave->prop.irq) { >> slave->irq = irq_create_mapping(bus->domain, dev_num); >> if (!slave->irq) { >> dev_err(bus->dev, "Failed to map IRQ\n"); >> return -EINVAL; >> } >> } >> > > Yeah I am happy to make those conditional, I guess it is cleaner > to not map IRQs if they wont be used. ok > >>> @@ -369,6 +371,7 @@ struct sdw_dpn_prop { >>> * @clock_reg_supported: the Peripheral implements the clock base and scale >>> * registers introduced with the SoundWire 1.2 specification. SDCA devices >>> * do not need to set this boolean property as the registers are required. >>> + * @irq: call actual IRQ handler on slave, as well as callback >>> */ >>> struct sdw_slave_prop { >>> u32 mipi_revision; >>> @@ -393,6 +396,7 @@ struct sdw_slave_prop { >>> u8 scp_int1_mask; >>> u32 quirks; >>> bool clock_reg_supported; >>> + bool irq; >> >> this can be confused with the 'wake_capable' property. >> >> maybe 'out_of_band_irq' ? >> > > Yes I struggle on the name a bit and then just gave up and > went with plain "irq", hard to know what to call it. Not sure > out_of_band is quite right since it not really out of band, > handle_nested_irq pretty much basically boils down to a function > call really. Maybe something like "map_irq", or "use_domain_irq"? Naming is hard. I use 'in-band wake' for SoundWire-based notifications, so I used 'out-of-band' for non-SoundWire stuff. use_domain_irq sounds goods to me, it's different enough that confusions are not possible. >> There should be an explanation and something checking that both are not >> used concurrently. > > I will try to expand the explanation a litte, but I dont see any > reason to block calling both handlers, no ill effects would come > for a driver having both and it is useful if any soundwire > specific steps are needed that arn't on other control buses. I think it's problematic if the peripheral tries to wake-up the manager from clock-stop with both an in-band wake (i.e. drive the data line high) and a separate GPIO-based interrupt. It's asking for trouble IMHO. We spent hours in the MIPI team to make sure there were no races between the manager-initiated restarts and peripheral-initiated restarts, adding a 3rd mechanism in the mix gives me a migraine already.
On Fri, Jan 20, 2023 at 10:20:50AM -0600, Pierre-Louis Bossart wrote: > On 1/20/23 03:59, Charles Keepax wrote: > > On Thu, Jan 19, 2023 at 11:12:04AM -0600, Pierre-Louis Bossart wrote: > >> There should be an explanation and something checking that both are not > >> used concurrently. > > > > I will try to expand the explanation a litte, but I dont see any > > reason to block calling both handlers, no ill effects would come > > for a driver having both and it is useful if any soundwire > > specific steps are needed that arn't on other control buses. > > I think it's problematic if the peripheral tries to wake-up the manager > from clock-stop with both an in-band wake (i.e. drive the data line > high) and a separate GPIO-based interrupt. It's asking for trouble IMHO. > We spent hours in the MIPI team to make sure there were no races between > the manager-initiated restarts and peripheral-initiated restarts, adding > a 3rd mechanism in the mix gives me a migraine already. Apologies but I am struggling see why this has any bearing on the case of a device that does both an in-band and out-of-band wake. The code we are adding in this patch will only be called in the in-band case. handle_nested_irq doesn't do any hardware magic or schedule any threads, it just calls a function that was provided when the client called request_threaded_irq. The only guarantee of atomicity you have on the interrupt_callback is sdw_dev_lock and that is being held across both calls after the patch. Could you be a little more specific on what you mean by this represents a 3rd mechanism, to me this isn't a new mechanism just an extra callback? Say for example this patch added an interrupt_callback_early to sdw_slave_ops that is called just before interrupt_callback. @@ -1681,6 +1681,9 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave) struct device *dev = &slave->dev; struct sdw_driver *drv = drv_to_sdw_driver(dev->driver); + if (drv->ops && drv->ops->interrupt_callback_early) + drv->ops->interrupt_callback_early(slave); + if (drv->ops && drv->ops->interrupt_callback) { slave_intr.sdca_cascade = sdca_cascade; slave_intr.control_port = clear; Would that similarly worry you? As in is it the client driver writer dealing with 2 points of entry that worries you, or something deeper relating to the IRQs? Also if it helps I could go over in a little more detail how the IRQs on our device works and why that means I would prefer to have the option to use both. There are alternatives but they arn't really as pretty. Thanks, Charles
On 1/23/23 08:53, Charles Keepax wrote: > On Fri, Jan 20, 2023 at 10:20:50AM -0600, Pierre-Louis Bossart wrote: >> On 1/20/23 03:59, Charles Keepax wrote: >>> On Thu, Jan 19, 2023 at 11:12:04AM -0600, Pierre-Louis Bossart wrote: >>>> There should be an explanation and something checking that both are not >>>> used concurrently. >>> >>> I will try to expand the explanation a litte, but I dont see any >>> reason to block calling both handlers, no ill effects would come >>> for a driver having both and it is useful if any soundwire >>> specific steps are needed that arn't on other control buses. >> >> I think it's problematic if the peripheral tries to wake-up the manager >> from clock-stop with both an in-band wake (i.e. drive the data line >> high) and a separate GPIO-based interrupt. It's asking for trouble IMHO. >> We spent hours in the MIPI team to make sure there were no races between >> the manager-initiated restarts and peripheral-initiated restarts, adding >> a 3rd mechanism in the mix gives me a migraine already. > > Apologies but I am struggling see why this has any bearing on > the case of a device that does both an in-band and out-of-band > wake. The code we are adding in this patch will only be called in the > in-band case. handle_nested_irq doesn't do any hardware magic or > schedule any threads, it just calls a function that was provided > when the client called request_threaded_irq. The only guarantee > of atomicity you have on the interrupt_callback is sdw_dev_lock > and that is being held across both calls after the patch. > > Could you be a little more specific on what you mean by this > represents a 3rd mechanism, to me this isn't a new mechanism just > an extra callback? Say for example this patch added an > interrupt_callback_early to sdw_slave_ops that is called just > before interrupt_callback. Well, the main concern is exiting the clock-stop. That is handled by the manager and could be done a) as the result of the framework deciding that something needs to be done (typically as a result of user/applications starting a stream) b) by the device with an in-band wake in case of e.g. jack detection or acoustic events detected c) same as b) but with a separate out-of-band interrupt. I'd like to make sure b) and c) are mutually-exclusive options, and that the device will not throw BOTH an in-band wake and an external interrupt.
On 23/01/2023 15:50, Pierre-Louis Bossart wrote: > > > On 1/23/23 08:53, Charles Keepax wrote: >> On Fri, Jan 20, 2023 at 10:20:50AM -0600, Pierre-Louis Bossart wrote: >>> On 1/20/23 03:59, Charles Keepax wrote: >>>> On Thu, Jan 19, 2023 at 11:12:04AM -0600, Pierre-Louis Bossart wrote: >>>>> There should be an explanation and something checking that both are not >>>>> used concurrently. >>>> >>>> I will try to expand the explanation a litte, but I dont see any >>>> reason to block calling both handlers, no ill effects would come >>>> for a driver having both and it is useful if any soundwire >>>> specific steps are needed that arn't on other control buses. >>> >>> I think it's problematic if the peripheral tries to wake-up the manager >>> from clock-stop with both an in-band wake (i.e. drive the data line >>> high) and a separate GPIO-based interrupt. It's asking for trouble IMHO. >>> We spent hours in the MIPI team to make sure there were no races between >>> the manager-initiated restarts and peripheral-initiated restarts, adding >>> a 3rd mechanism in the mix gives me a migraine already. >> >> Apologies but I am struggling see why this has any bearing on >> the case of a device that does both an in-band and out-of-band >> wake. The code we are adding in this patch will only be called in the >> in-band case. handle_nested_irq doesn't do any hardware magic or >> schedule any threads, it just calls a function that was provided >> when the client called request_threaded_irq. The only guarantee >> of atomicity you have on the interrupt_callback is sdw_dev_lock >> and that is being held across both calls after the patch. >> >> Could you be a little more specific on what you mean by this >> represents a 3rd mechanism, to me this isn't a new mechanism just >> an extra callback? Say for example this patch added an >> interrupt_callback_early to sdw_slave_ops that is called just >> before interrupt_callback. > > Well, the main concern is exiting the clock-stop. That is handled by the > manager and could be done > a) as the result of the framework deciding that something needs to be > done (typically as a result of user/applications starting a stream) > b) by the device with an in-band wake in case of e.g. jack detection or > acoustic events detected > c) same as b) but with a separate out-of-band interrupt. > > I'd like to make sure b) and c) are mutually-exclusive options, and that > the device will not throw BOTH an in-band wake and an external interrupt. Why would it be a problem if the device did (b) and (c)? (c) is completely invisible to the SoundWire core and not something that it has to handle. The handler for an out-of-band interrupt must call pm_runtime_get_sync() or pm_runtime_resume_and_get() and that would wake its own driver and the host controller.
On 1/23/23 10:08, Richard Fitzgerald wrote: > On 23/01/2023 15:50, Pierre-Louis Bossart wrote: >> >> >> On 1/23/23 08:53, Charles Keepax wrote: >>> On Fri, Jan 20, 2023 at 10:20:50AM -0600, Pierre-Louis Bossart wrote: >>>> On 1/20/23 03:59, Charles Keepax wrote: >>>>> On Thu, Jan 19, 2023 at 11:12:04AM -0600, Pierre-Louis Bossart wrote: >>>>>> There should be an explanation and something checking that both >>>>>> are not >>>>>> used concurrently. >>>>> >>>>> I will try to expand the explanation a litte, but I dont see any >>>>> reason to block calling both handlers, no ill effects would come >>>>> for a driver having both and it is useful if any soundwire >>>>> specific steps are needed that arn't on other control buses. >>>> >>>> I think it's problematic if the peripheral tries to wake-up the manager >>>> from clock-stop with both an in-band wake (i.e. drive the data line >>>> high) and a separate GPIO-based interrupt. It's asking for trouble >>>> IMHO. >>>> We spent hours in the MIPI team to make sure there were no races >>>> between >>>> the manager-initiated restarts and peripheral-initiated restarts, >>>> adding >>>> a 3rd mechanism in the mix gives me a migraine already. >>> >>> Apologies but I am struggling see why this has any bearing on >>> the case of a device that does both an in-band and out-of-band >>> wake. The code we are adding in this patch will only be called in the >>> in-band case. handle_nested_irq doesn't do any hardware magic or >>> schedule any threads, it just calls a function that was provided >>> when the client called request_threaded_irq. The only guarantee >>> of atomicity you have on the interrupt_callback is sdw_dev_lock >>> and that is being held across both calls after the patch. >>> >>> Could you be a little more specific on what you mean by this >>> represents a 3rd mechanism, to me this isn't a new mechanism just >>> an extra callback? Say for example this patch added an >>> interrupt_callback_early to sdw_slave_ops that is called just >>> before interrupt_callback. >> >> Well, the main concern is exiting the clock-stop. That is handled by the >> manager and could be done >> a) as the result of the framework deciding that something needs to be >> done (typically as a result of user/applications starting a stream) >> b) by the device with an in-band wake in case of e.g. jack detection or >> acoustic events detected >> c) same as b) but with a separate out-of-band interrupt. >> >> I'd like to make sure b) and c) are mutually-exclusive options, and that >> the device will not throw BOTH an in-band wake and an external interrupt. > > Why would it be a problem if the device did (b) and (c)? > (c) is completely invisible to the SoundWire core and not something > that it has to handle. The handler for an out-of-band interrupt must > call pm_runtime_get_sync() or pm_runtime_resume_and_get() and that > would wake its own driver and the host controller. The Intel hardware has a power optimization for the clock-stop, which leads to different paths to wake the system. The SoundWire IP can deal with the data line staying high, but in the optimized mode the wakes are signaled as DSP interrupts at a higher level. That's why we added this intel_link_process_wakeen_event() function called from hda_dsp_interrupt_thread(). So yes on paper everything would work nicely, but that's asking for trouble with races left and right. In other words, unless you have a very good reason for using two wake-up mechanisms, pick a single one. (a) and (c) are very similar in that all the exit is handled by pm_runtime so I am not worried too much. I do worry about paths that were never tested and never planned for.
On Mon, Jan 23, 2023 at 09:50:15AM -0600, Pierre-Louis Bossart wrote: > On 1/23/23 08:53, Charles Keepax wrote: > > On Fri, Jan 20, 2023 at 10:20:50AM -0600, Pierre-Louis Bossart wrote: > >> On 1/20/23 03:59, Charles Keepax wrote: > >>> On Thu, Jan 19, 2023 at 11:12:04AM -0600, Pierre-Louis Bossart wrote: > >>>> There should be an explanation and something checking that both are not > >>>> used concurrently. > >>> > >>> I will try to expand the explanation a litte, but I dont see any > >>> reason to block calling both handlers, no ill effects would come > >>> for a driver having both and it is useful if any soundwire > >>> specific steps are needed that arn't on other control buses. > >> > >> I think it's problematic if the peripheral tries to wake-up the manager > >> from clock-stop with both an in-band wake (i.e. drive the data line > >> high) and a separate GPIO-based interrupt. It's asking for trouble IMHO. > >> We spent hours in the MIPI team to make sure there were no races between > >> the manager-initiated restarts and peripheral-initiated restarts, adding > >> a 3rd mechanism in the mix gives me a migraine already. > > > > Apologies but I am struggling see why this has any bearing on > > the case of a device that does both an in-band and out-of-band > > wake. The code we are adding in this patch will only be called in the > > in-band case. handle_nested_irq doesn't do any hardware magic or > > schedule any threads, it just calls a function that was provided > > when the client called request_threaded_irq. The only guarantee > > of atomicity you have on the interrupt_callback is sdw_dev_lock > > and that is being held across both calls after the patch. > > > > Could you be a little more specific on what you mean by this > > represents a 3rd mechanism, to me this isn't a new mechanism just > > an extra callback? Say for example this patch added an > > interrupt_callback_early to sdw_slave_ops that is called just > > before interrupt_callback. > > Well, the main concern is exiting the clock-stop. That is handled by the > manager and could be done > a) as the result of the framework deciding that something needs to be > done (typically as a result of user/applications starting a stream) > b) by the device with an in-band wake in case of e.g. jack detection or > acoustic events detected > c) same as b) but with a separate out-of-band interrupt. > > I'd like to make sure b) and c) are mutually-exclusive options, and that > the device will not throw BOTH an in-band wake and an external interrupt. I think this is the bit I don't follow why does this patch have anything to do with whether b) and c) are mutually-exclusive options? This patch lets you register an IRQ handler to the in-band IRQs, it has nothing to do with whether you register an IRQ handler to some out of band IRQ and there is nothing in the current framework that will prevent someone doing that. Adding a check that forces someone to choose between using handle_nested_irq or interrupt_callback will also have no bearing on whether they attach an IRQ handler to an out-of-band IRQ. Thanks, Charles
On 23/01/2023 16:38, Pierre-Louis Bossart wrote: > > > On 1/23/23 10:08, Richard Fitzgerald wrote: >> On 23/01/2023 15:50, Pierre-Louis Bossart wrote: >>> >>> >>> On 1/23/23 08:53, Charles Keepax wrote: >>>> On Fri, Jan 20, 2023 at 10:20:50AM -0600, Pierre-Louis Bossart wrote: >>>>> On 1/20/23 03:59, Charles Keepax wrote: >>>>>> On Thu, Jan 19, 2023 at 11:12:04AM -0600, Pierre-Louis Bossart wrote: >>>>>>> There should be an explanation and something checking that both >>>>>>> are not >>>>>>> used concurrently. >>>>>> >>>>>> I will try to expand the explanation a litte, but I dont see any >>>>>> reason to block calling both handlers, no ill effects would come >>>>>> for a driver having both and it is useful if any soundwire >>>>>> specific steps are needed that arn't on other control buses. >>>>> >>>>> I think it's problematic if the peripheral tries to wake-up the manager >>>>> from clock-stop with both an in-band wake (i.e. drive the data line >>>>> high) and a separate GPIO-based interrupt. It's asking for trouble >>>>> IMHO. >>>>> We spent hours in the MIPI team to make sure there were no races >>>>> between >>>>> the manager-initiated restarts and peripheral-initiated restarts, >>>>> adding >>>>> a 3rd mechanism in the mix gives me a migraine already. >>>> >>>> Apologies but I am struggling see why this has any bearing on >>>> the case of a device that does both an in-band and out-of-band >>>> wake. The code we are adding in this patch will only be called in the >>>> in-band case. handle_nested_irq doesn't do any hardware magic or >>>> schedule any threads, it just calls a function that was provided >>>> when the client called request_threaded_irq. The only guarantee >>>> of atomicity you have on the interrupt_callback is sdw_dev_lock >>>> and that is being held across both calls after the patch. >>>> >>>> Could you be a little more specific on what you mean by this >>>> represents a 3rd mechanism, to me this isn't a new mechanism just >>>> an extra callback? Say for example this patch added an >>>> interrupt_callback_early to sdw_slave_ops that is called just >>>> before interrupt_callback. >>> >>> Well, the main concern is exiting the clock-stop. That is handled by the >>> manager and could be done >>> a) as the result of the framework deciding that something needs to be >>> done (typically as a result of user/applications starting a stream) >>> b) by the device with an in-band wake in case of e.g. jack detection or >>> acoustic events detected >>> c) same as b) but with a separate out-of-band interrupt. >>> >>> I'd like to make sure b) and c) are mutually-exclusive options, and that >>> the device will not throw BOTH an in-band wake and an external interrupt. >> >> Why would it be a problem if the device did (b) and (c)? >> (c) is completely invisible to the SoundWire core and not something >> that it has to handle. The handler for an out-of-band interrupt must >> call pm_runtime_get_sync() or pm_runtime_resume_and_get() and that >> would wake its own driver and the host controller. > > The Intel hardware has a power optimization for the clock-stop, which > leads to different paths to wake the system. The SoundWire IP can deal > with the data line staying high, but in the optimized mode the wakes are > signaled as DSP interrupts at a higher level. That's why we added this > intel_link_process_wakeen_event() function called from > hda_dsp_interrupt_thread(). > > So yes on paper everything would work nicely, but that's asking for > trouble with races left and right. In other words, unless you have a Wake up from a hard INT is simply a runtime_resume of the codec driver. That is no different from ASoC runtime resuming the driver to perform some audio activity, or to access a volatile register. An event caused a runtime-resume - the driver and the host controller must resume. The Intel code _must_ be able to safely wakeup from clock-stop if something runtime-resumes the codec driver. ASoC relies on that, and pm_runtime would be broken if that doesn't work. > very good reason for using two wake-up mechanisms, pick a single one. > > (a) and (c) are very similar in that all the exit is handled by > pm_runtime so I am not worried too much. I do worry about paths that > were never tested and never planned for.
On 1/23/23 11:17, Richard Fitzgerald wrote: > On 23/01/2023 16:38, Pierre-Louis Bossart wrote: >> >> >> On 1/23/23 10:08, Richard Fitzgerald wrote: >>> On 23/01/2023 15:50, Pierre-Louis Bossart wrote: >>>> >>>> >>>> On 1/23/23 08:53, Charles Keepax wrote: >>>>> On Fri, Jan 20, 2023 at 10:20:50AM -0600, Pierre-Louis Bossart wrote: >>>>>> On 1/20/23 03:59, Charles Keepax wrote: >>>>>>> On Thu, Jan 19, 2023 at 11:12:04AM -0600, Pierre-Louis Bossart >>>>>>> wrote: >>>>>>>> There should be an explanation and something checking that both >>>>>>>> are not >>>>>>>> used concurrently. >>>>>>> >>>>>>> I will try to expand the explanation a litte, but I dont see any >>>>>>> reason to block calling both handlers, no ill effects would come >>>>>>> for a driver having both and it is useful if any soundwire >>>>>>> specific steps are needed that arn't on other control buses. >>>>>> >>>>>> I think it's problematic if the peripheral tries to wake-up the >>>>>> manager >>>>>> from clock-stop with both an in-band wake (i.e. drive the data line >>>>>> high) and a separate GPIO-based interrupt. It's asking for trouble >>>>>> IMHO. >>>>>> We spent hours in the MIPI team to make sure there were no races >>>>>> between >>>>>> the manager-initiated restarts and peripheral-initiated restarts, >>>>>> adding >>>>>> a 3rd mechanism in the mix gives me a migraine already. >>>>> >>>>> Apologies but I am struggling see why this has any bearing on >>>>> the case of a device that does both an in-band and out-of-band >>>>> wake. The code we are adding in this patch will only be called in the >>>>> in-band case. handle_nested_irq doesn't do any hardware magic or >>>>> schedule any threads, it just calls a function that was provided >>>>> when the client called request_threaded_irq. The only guarantee >>>>> of atomicity you have on the interrupt_callback is sdw_dev_lock >>>>> and that is being held across both calls after the patch. >>>>> >>>>> Could you be a little more specific on what you mean by this >>>>> represents a 3rd mechanism, to me this isn't a new mechanism just >>>>> an extra callback? Say for example this patch added an >>>>> interrupt_callback_early to sdw_slave_ops that is called just >>>>> before interrupt_callback. >>>> >>>> Well, the main concern is exiting the clock-stop. That is handled by >>>> the >>>> manager and could be done >>>> a) as the result of the framework deciding that something needs to be >>>> done (typically as a result of user/applications starting a stream) >>>> b) by the device with an in-band wake in case of e.g. jack detection or >>>> acoustic events detected >>>> c) same as b) but with a separate out-of-band interrupt. >>>> >>>> I'd like to make sure b) and c) are mutually-exclusive options, and >>>> that >>>> the device will not throw BOTH an in-band wake and an external >>>> interrupt. >>> >>> Why would it be a problem if the device did (b) and (c)? >>> (c) is completely invisible to the SoundWire core and not something >>> that it has to handle. The handler for an out-of-band interrupt must >>> call pm_runtime_get_sync() or pm_runtime_resume_and_get() and that >>> would wake its own driver and the host controller. >> >> The Intel hardware has a power optimization for the clock-stop, which >> leads to different paths to wake the system. The SoundWire IP can deal >> with the data line staying high, but in the optimized mode the wakes are >> signaled as DSP interrupts at a higher level. That's why we added this >> intel_link_process_wakeen_event() function called from >> hda_dsp_interrupt_thread(). >> >> So yes on paper everything would work nicely, but that's asking for >> trouble with races left and right. In other words, unless you have a > > Wake up from a hard INT is simply a runtime_resume of the codec driver. > That is no different from ASoC runtime resuming the driver to perform > some audio activity, or to access a volatile register. An event caused > a runtime-resume - the driver and the host controller must resume. > > The Intel code _must_ be able to safely wakeup from clock-stop if > something runtime-resumes the codec driver. ASoC relies on that, and > pm_runtime would be broken if that doesn't work. Like I said before, the Intel code will work with either b) or c). Using both to exit clock stop is not a recommended/tested solution, and it's not something I have a burning desire to look into. If you register an external IRQ, then pretty please describe your device as not 'wake_capable'. >> very good reason for using two wake-up mechanisms, pick a single one. >> >> (a) and (c) are very similar in that all the exit is handled by >> pm_runtime so I am not worried too much. I do worry about paths that >> were never tested and never planned for.
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index daee2cca94a4d..49087e0ca3c3c 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -3,6 +3,7 @@ #include <linux/acpi.h> #include <linux/delay.h> +#include <linux/irq.h> #include <linux/mod_devicetable.h> #include <linux/pm_runtime.h> #include <linux/soundwire/sdw_registers.h> @@ -25,6 +26,23 @@ static int sdw_get_id(struct sdw_bus *bus) return 0; } +static int sdw_irq_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw) +{ + struct sdw_bus *bus = h->host_data; + + irq_set_chip_data(virq, bus); + irq_set_chip(virq, &bus->irq_chip); + irq_set_nested_thread(virq, 1); + irq_set_noprobe(virq); + + return 0; +} + +static const struct irq_domain_ops sdw_domain_ops = { + .map = sdw_irq_map, +}; + /** * sdw_bus_master_add() - add a bus Master instance * @bus: bus instance @@ -142,6 +160,13 @@ int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent, bus->params.curr_bank = SDW_BANK0; bus->params.next_bank = SDW_BANK1; + bus->irq_chip.name = dev_name(bus->dev); + bus->domain = irq_domain_add_linear(NULL, SDW_MAX_DEVICES, &sdw_domain_ops, bus); + if (!bus->domain) { + dev_err(bus->dev, "Failed to add IRQ domain\n"); + return -EINVAL; + } + return 0; } EXPORT_SYMBOL(sdw_bus_master_add); @@ -158,6 +183,8 @@ static int sdw_delete_slave(struct device *dev, void *data) mutex_lock(&bus->bus_lock); if (slave->dev_num) { /* clear dev_num if assigned */ + irq_dispose_mapping(irq_find_mapping(bus->domain, slave->dev_num)); + clear_bit(slave->dev_num, bus->assigned); if (bus->dev_num_ida_min) ida_free(&sdw_peripheral_ida, slave->dev_num); @@ -178,6 +205,9 @@ static int sdw_delete_slave(struct device *dev, void *data) void sdw_bus_master_delete(struct sdw_bus *bus) { device_for_each_child(bus->dev, NULL, sdw_delete_slave); + + irq_domain_remove(bus->domain); + sdw_master_device_del(bus); sdw_bus_debugfs_exit(bus); @@ -717,6 +747,12 @@ static int sdw_assign_device_num(struct sdw_slave *slave) slave->dev_num = dev_num; slave->dev_num_sticky = dev_num; new_device = true; + + slave->irq = irq_create_mapping(bus->domain, dev_num); + if (!slave->irq) { + dev_err(bus->dev, "Failed to map IRQ\n"); + return -EINVAL; + } } else { slave->dev_num = slave->dev_num_sticky; } @@ -1682,6 +1718,9 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave) struct device *dev = &slave->dev; struct sdw_driver *drv = drv_to_sdw_driver(dev->driver); + if (slave->prop.irq && slave->irq) + handle_nested_irq(slave->irq); + if (drv->ops && drv->ops->interrupt_callback) { slave_intr.sdca_cascade = sdca_cascade; slave_intr.control_port = clear; diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 3cd2a761911ff..7627c459ab20f 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -5,6 +5,8 @@ #define __SOUNDWIRE_H #include <linux/bug.h> +#include <linux/irq.h> +#include <linux/irqdomain.h> #include <linux/mod_devicetable.h> #include <linux/bitfield.h> @@ -369,6 +371,7 @@ struct sdw_dpn_prop { * @clock_reg_supported: the Peripheral implements the clock base and scale * registers introduced with the SoundWire 1.2 specification. SDCA devices * do not need to set this boolean property as the registers are required. + * @irq: call actual IRQ handler on slave, as well as callback */ struct sdw_slave_prop { u32 mipi_revision; @@ -393,6 +396,7 @@ struct sdw_slave_prop { u8 scp_int1_mask; u32 quirks; bool clock_reg_supported; + bool irq; }; #define SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY BIT(0) @@ -638,6 +642,7 @@ struct sdw_slave_ops { * struct sdw_slave - SoundWire Slave * @id: MIPI device ID * @dev: Linux device + * @irq: IRQ number * @status: Status reported by the Slave * @bus: Bus handle * @prop: Slave properties @@ -667,6 +672,7 @@ struct sdw_slave_ops { struct sdw_slave { struct sdw_slave_id id; struct device dev; + int irq; enum sdw_slave_status status; struct sdw_bus *bus; struct sdw_slave_prop prop; @@ -884,6 +890,7 @@ struct sdw_master_ops { * is used to compute and program bus bandwidth, clock, frame shape, * transport and port parameters * @debugfs: Bus debugfs + * @domain: IRQ domain * @defer_msg: Defer message * @clk_stop_timeout: Clock stop timeout computed * @bank_switch_timeout: Bank switch timeout computed @@ -917,6 +924,8 @@ struct sdw_bus { #ifdef CONFIG_DEBUG_FS struct dentry *debugfs; #endif + struct irq_chip irq_chip; + struct irq_domain *domain; struct sdw_defer defer_msg; unsigned int clk_stop_timeout; u32 bank_switch_timeout;