Message ID | 20230531033736.792464-3-yung-chuan.liao@linux.intel.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp2617641vqr; Tue, 30 May 2023 20:46:41 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ7F/TRLDPvgWO5+EFOasb2RwWeqvPFng9fHZNB2NNNjM2gKWPpc4AWAzjU13G5LXEKj3wEC X-Received: by 2002:a05:6a00:1389:b0:645:1081:98ec with SMTP id t9-20020a056a00138900b00645108198ecmr5754856pfg.13.1685504800741; Tue, 30 May 2023 20:46:40 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685504800; cv=none; d=google.com; s=arc-20160816; b=mrt/XrFrXX02lfbBPZlNYIMLpSlnWGlJJa7wSOSX9bbw+F1lZFV0q0t3cgXhPwYIAQ Tom5rVsnXxBtWnK2SNdd5rq/+ZapHnUdumOmqeDshKp1OYyDbZdavnFcXjbbJJk4siBK n9YdGI7ZrIol9SgngcYz9xIjHPwyllVIDP+g8han/wBOwflkcV6PNnxt4E05Yjg+uOcZ P7XKJ0eBDN55BQko0sZ/n//Z3WLhV8n+GI1mqYjKE16gKAiutgF3aVNWxYht39PFUDXm 64KLYNtkxtOaNyEvcAXKOO0Lli0YH7qB9wW7whlSeEv3zF5cNa3nhYvgCOMawjTQ1dkJ sTLA== 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=m1nUMfRNWMqQvEUSK7okRsfssJTAUm2X7ZbVZvQrTQ0=; b=YiO2TFTbh1o4yA21JP/6d5D3+LpEX9YMt2f8tawbSstszgsfS5kxG6T3pAj2KKxMuB 6BsVflecs41P+nMc9yJryCPzxT9ziZK+npoeyEXT3TdBf+lXg1QbbtUM3ozirGmxRJZI mdUelNKONrDDUCZXyx1nk4XsZ2trGFmKuceSZw0f3pN3guYMQxuAiqWCGIqvYQvJMVX+ i3IpsUN+E1WcLQpJlnCOJxLreHkUWpRwiXGdPZDcaRqRnogQKp1WxEWNMucFl7aMh9gN 0+ij5Wcs+9gKa8c/JCOxfz+aa6w8YNN3jdQEHYgq7oaMYqmPxiqqEsiETsHPhX39dksq Rv9Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=GgDfbPpZ; 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=NONE sp=NONE dis=NONE) header.from=intel.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id a127-20020a624d85000000b0064d2f7f1622si2922649pfb.68.2023.05.30.20.46.27; Tue, 30 May 2023 20:46:40 -0700 (PDT) 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=@intel.com header.s=Intel header.b=GgDfbPpZ; 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=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234172AbjEaDQC (ORCPT <rfc822;callmefire3@gmail.com> + 99 others); Tue, 30 May 2023 23:16:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41624 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234008AbjEaDPj (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Tue, 30 May 2023 23:15:39 -0400 Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 30A96133 for <linux-kernel@vger.kernel.org>; Tue, 30 May 2023 20:15:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1685502938; x=1717038938; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=cDPxAfvdGUM1tm5hvXaDY204P9qt4B3UxsBRfKyYP3M=; b=GgDfbPpZPyDMPUO5i/9fGXLmmB/AcKCYbDJNPl3Wd7pb6woBKhQIabsx aWOCfhLbwZqQMU4X+H7Sv5Ro4Qanjqa/a7zhjR++KJtkN7BaCxgSAMUWm mg9+cGZEYl8oeUQGjDKBKzfCgYnp0yZE2fRpIluIhAX70UxaScRfOKB+l jY2t1hFfx1QlGbe3Z6TJvUQRES3OThR0HAgUaTk1tVMu3JGYwtIliozm4 gK8UK+1EZAsbYs9DWF/ztYdEYvyXImbNj5g0PsxhFd0HY6s406vi4hL/o fRQ0UD7Z4JchkB9DcjrzvBOExeLStVi9tsd3Anbcovffy+Yo7GGB6DjXQ A==; X-IronPort-AV: E=McAfee;i="6600,9927,10726"; a="357507661" X-IronPort-AV: E=Sophos;i="6.00,205,1681196400"; d="scan'208";a="357507661" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 May 2023 20:15:38 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10726"; a="739769514" X-IronPort-AV: E=Sophos;i="6.00,205,1681196400"; d="scan'208";a="739769514" Received: from bard-ubuntu.sh.intel.com ([10.239.185.57]) by orsmga001-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 May 2023 20:15:36 -0700 From: Bard Liao <yung-chuan.liao@linux.intel.com> To: alsa-devel@alsa-project.org, vkoul@kernel.org Cc: vinod.koul@linaro.org, linux-kernel@vger.kernel.org, pierre-louis.bossart@linux.intel.com, bard.liao@intel.com Subject: [PATCH 2/4] soundwire: introduce SDW_DEV_NUM_ALLOC_IDA_WAKE_ONLY Date: Wed, 31 May 2023 11:37:34 +0800 Message-Id: <20230531033736.792464-3-yung-chuan.liao@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230531033736.792464-1-yung-chuan.liao@linux.intel.com> References: <20230531033736.792464-1-yung-chuan.liao@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-4.5 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_EF,RCVD_IN_DNSWL_MED, RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_NONE, T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED 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?1767379881829157951?= X-GMAIL-MSGID: =?utf-8?q?1767379881829157951?= |
Series |
soundwire: allow for more than 8 devices, keep IDA for wake-capable devices
|
|
Commit Message
Bard Liao
May 31, 2023, 3:37 a.m. UTC
From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> This patch adds a new Device Number allocation strategy, with the IDA used only for devices that are wake-capable. "regular" devices such as amplifiers will use Device Numbers [1..min_ida-1]. "wake-capable" devices such as jack or microphone codecs will use Device Numbers [min_ida..11]. This hybrid strategy extends the number of supported devices in a system by only constraining the allocation if required, e.g. in the case of Intel LunarLake platforms the wake-capable devices are required to have a unique address to use the HDaudio SDI and HDAudio WAKEEN/WAKESTS registers. Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Reviewed-by: Rander Wang <rander.wang@intel.com> Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com> --- drivers/soundwire/bus.c | 26 +++++++++++++++++++++----- include/linux/soundwire/sdw.h | 4 ++++ 2 files changed, 25 insertions(+), 5 deletions(-)
Comments
On 31-05-23, 11:37, Bard Liao wrote: > From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> > > This patch adds a new Device Number allocation strategy, with the IDA > used only for devices that are wake-capable. > > "regular" devices such as amplifiers will use Device Numbers > [1..min_ida-1]. > > "wake-capable" devices such as jack or microphone codecs will use > Device Numbers [min_ida..11]. > > This hybrid strategy extends the number of supported devices in a > system by only constraining the allocation if required, e.g. in the > case of Intel LunarLake platforms the wake-capable devices are > required to have a unique address to use the HDaudio SDI and HDAudio > WAKEEN/WAKESTS registers. This seems to be a consequence of Intel hardware decisions, so I guess best suited place for this is Intel controller, do we really want to have this in core logic? > > Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> > Reviewed-by: Rander Wang <rander.wang@intel.com> > Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com> > --- > drivers/soundwire/bus.c | 26 +++++++++++++++++++++----- > include/linux/soundwire/sdw.h | 4 ++++ > 2 files changed, 25 insertions(+), 5 deletions(-) > > diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c > index e8c1c55a2a73..6f465cce8369 100644 > --- a/drivers/soundwire/bus.c > +++ b/drivers/soundwire/bus.c > @@ -159,7 +159,9 @@ static int sdw_delete_slave(struct device *dev, void *data) > > if (slave->dev_num) { /* clear dev_num if assigned */ > clear_bit(slave->dev_num, bus->assigned); > - if (bus->dev_num_alloc == SDW_DEV_NUM_ALLOC_IDA) > + if (bus->dev_num_alloc == SDW_DEV_NUM_ALLOC_IDA || > + (bus->dev_num_alloc == SDW_DEV_NUM_ALLOC_IDA_WAKE_ONLY && > + slave->prop.wake_capable)) > ida_free(&sdw_peripheral_ida, slave->dev_num); > } > list_del_init(&slave->node); > @@ -699,17 +701,31 @@ EXPORT_SYMBOL(sdw_compare_devid); > /* called with bus_lock held */ > static int sdw_get_device_num(struct sdw_slave *slave) > { > + struct sdw_bus *bus = slave->bus; > int bit; > > - if (slave->bus->dev_num_alloc == SDW_DEV_NUM_ALLOC_IDA) { > + if (bus->dev_num_alloc == SDW_DEV_NUM_ALLOC_IDA || > + (bus->dev_num_alloc == SDW_DEV_NUM_ALLOC_IDA_WAKE_ONLY && > + slave->prop.wake_capable)) { > bit = ida_alloc_range(&sdw_peripheral_ida, > - slave->bus->dev_num_ida_min, SDW_MAX_DEVICES, > + bus->dev_num_ida_min, SDW_MAX_DEVICES, > GFP_KERNEL); > if (bit < 0) > goto err; > } else { > - bit = find_first_zero_bit(slave->bus->assigned, SDW_MAX_DEVICES); > - if (bit == SDW_MAX_DEVICES) { > + int max_devices = SDW_MAX_DEVICES; > + > + if (bus->dev_num_alloc == SDW_DEV_NUM_ALLOC_IDA_WAKE_ONLY && > + !slave->prop.wake_capable) { > + max_devices = bus->dev_num_ida_min - 1; > + > + /* range check */ > + if (max_devices < 1 || max_devices > SDW_MAX_DEVICES) > + return -EINVAL; > + } > + > + bit = find_first_zero_bit(bus->assigned, max_devices); > + if (bit == max_devices) { > bit = -ENODEV; > goto err; > } > diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h > index 4656d6d0f3bb..8a7541ac735e 100644 > --- a/include/linux/soundwire/sdw.h > +++ b/include/linux/soundwire/sdw.h > @@ -869,10 +869,14 @@ struct sdw_master_ops { > * @SDW_DEV_NUM_ALLOC_DEFAULT: unconstrained first-come-first-serve allocation, > * using range [1, 11] > * @SDW_DEV_NUM_ALLOC_IDA: IDA-based allocation, using range [ida_min, 11] > + * @SDW_DEV_NUM_ALLOC_IDA_WAKE_ONLY: Hybrid allocation where wake-capable devices rely on > + * IDA-based allocation and range [ida_min, 11], while regular devices rely on default > + * allocation in range [1, ida_min - 1] > */ > enum sdw_dev_num_alloc { > SDW_DEV_NUM_ALLOC_DEFAULT = 0, > SDW_DEV_NUM_ALLOC_IDA, > + SDW_DEV_NUM_ALLOC_IDA_WAKE_ONLY, > }; > > /** > -- > 2.25.1
On 6/8/23 02:06, Vinod Koul wrote: > On 31-05-23, 11:37, Bard Liao wrote: >> From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> >> >> This patch adds a new Device Number allocation strategy, with the IDA >> used only for devices that are wake-capable. >> >> "regular" devices such as amplifiers will use Device Numbers >> [1..min_ida-1]. >> >> "wake-capable" devices such as jack or microphone codecs will use >> Device Numbers [min_ida..11]. >> >> This hybrid strategy extends the number of supported devices in a >> system by only constraining the allocation if required, e.g. in the >> case of Intel LunarLake platforms the wake-capable devices are >> required to have a unique address to use the HDaudio SDI and HDAudio >> WAKEEN/WAKESTS registers. > > This seems to be a consequence of Intel hardware decisions, so I guess > best suited place for this is Intel controller, do we really want to > have this in core logic? It's a valid objection. The reason why I added the alternate strategies in the core logic is that the IDA and hybrid approach are just software-based with no specific hardware dependencies. If QCOM or AMD wanted to use the strategies contributed and tested by Intel, it'd be a two-line change on their side. That said, it's likely that at some point *someone* will want to constrain the device number allocation further, be it with ACPI/DT properties or reading hardware registers. The device number is a de-facto priority given the way we scan the PING frames, so some systems may want to give a higher priority to a specific peripherals. This would push us to add a master ops callback to control the device number allocation. It's a bit invasive but that would give the ultimate flexibility. Reuse between vendors could be possible if 'generic' callbacks were part of a library to pick from. I don't really have any objections if this vendor-specific callback was preferred, it may be a bit early to add this but long-term it's probably what makes more sense. I'll go with the flow on suggested recommendations. >> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> >> Reviewed-by: Rander Wang <rander.wang@intel.com> >> Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com> >> --- >> drivers/soundwire/bus.c | 26 +++++++++++++++++++++----- >> include/linux/soundwire/sdw.h | 4 ++++ >> 2 files changed, 25 insertions(+), 5 deletions(-) >> >> diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c >> index e8c1c55a2a73..6f465cce8369 100644 >> --- a/drivers/soundwire/bus.c >> +++ b/drivers/soundwire/bus.c >> @@ -159,7 +159,9 @@ static int sdw_delete_slave(struct device *dev, void *data) >> >> if (slave->dev_num) { /* clear dev_num if assigned */ >> clear_bit(slave->dev_num, bus->assigned); >> - if (bus->dev_num_alloc == SDW_DEV_NUM_ALLOC_IDA) >> + if (bus->dev_num_alloc == SDW_DEV_NUM_ALLOC_IDA || >> + (bus->dev_num_alloc == SDW_DEV_NUM_ALLOC_IDA_WAKE_ONLY && >> + slave->prop.wake_capable)) >> ida_free(&sdw_peripheral_ida, slave->dev_num); >> } >> list_del_init(&slave->node); >> @@ -699,17 +701,31 @@ EXPORT_SYMBOL(sdw_compare_devid); >> /* called with bus_lock held */ >> static int sdw_get_device_num(struct sdw_slave *slave) >> { >> + struct sdw_bus *bus = slave->bus; >> int bit; >> >> - if (slave->bus->dev_num_alloc == SDW_DEV_NUM_ALLOC_IDA) { >> + if (bus->dev_num_alloc == SDW_DEV_NUM_ALLOC_IDA || >> + (bus->dev_num_alloc == SDW_DEV_NUM_ALLOC_IDA_WAKE_ONLY && >> + slave->prop.wake_capable)) { >> bit = ida_alloc_range(&sdw_peripheral_ida, >> - slave->bus->dev_num_ida_min, SDW_MAX_DEVICES, >> + bus->dev_num_ida_min, SDW_MAX_DEVICES, >> GFP_KERNEL); >> if (bit < 0) >> goto err; >> } else { >> - bit = find_first_zero_bit(slave->bus->assigned, SDW_MAX_DEVICES); >> - if (bit == SDW_MAX_DEVICES) { >> + int max_devices = SDW_MAX_DEVICES; >> + >> + if (bus->dev_num_alloc == SDW_DEV_NUM_ALLOC_IDA_WAKE_ONLY && >> + !slave->prop.wake_capable) { >> + max_devices = bus->dev_num_ida_min - 1; >> + >> + /* range check */ >> + if (max_devices < 1 || max_devices > SDW_MAX_DEVICES) >> + return -EINVAL; >> + } >> + >> + bit = find_first_zero_bit(bus->assigned, max_devices); >> + if (bit == max_devices) { >> bit = -ENODEV; >> goto err; >> } >> diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h >> index 4656d6d0f3bb..8a7541ac735e 100644 >> --- a/include/linux/soundwire/sdw.h >> +++ b/include/linux/soundwire/sdw.h >> @@ -869,10 +869,14 @@ struct sdw_master_ops { >> * @SDW_DEV_NUM_ALLOC_DEFAULT: unconstrained first-come-first-serve allocation, >> * using range [1, 11] >> * @SDW_DEV_NUM_ALLOC_IDA: IDA-based allocation, using range [ida_min, 11] >> + * @SDW_DEV_NUM_ALLOC_IDA_WAKE_ONLY: Hybrid allocation where wake-capable devices rely on >> + * IDA-based allocation and range [ida_min, 11], while regular devices rely on default >> + * allocation in range [1, ida_min - 1] >> */ >> enum sdw_dev_num_alloc { >> SDW_DEV_NUM_ALLOC_DEFAULT = 0, >> SDW_DEV_NUM_ALLOC_IDA, >> + SDW_DEV_NUM_ALLOC_IDA_WAKE_ONLY, >> }; >> >> /** >> -- >> 2.25.1 >
On 08-06-23, 10:09, Pierre-Louis Bossart wrote: > > > On 6/8/23 02:06, Vinod Koul wrote: > > On 31-05-23, 11:37, Bard Liao wrote: > >> From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> > >> > >> This patch adds a new Device Number allocation strategy, with the IDA > >> used only for devices that are wake-capable. > >> > >> "regular" devices such as amplifiers will use Device Numbers > >> [1..min_ida-1]. > >> > >> "wake-capable" devices such as jack or microphone codecs will use > >> Device Numbers [min_ida..11]. > >> > >> This hybrid strategy extends the number of supported devices in a > >> system by only constraining the allocation if required, e.g. in the > >> case of Intel LunarLake platforms the wake-capable devices are > >> required to have a unique address to use the HDaudio SDI and HDAudio > >> WAKEEN/WAKESTS registers. > > > > This seems to be a consequence of Intel hardware decisions, so I guess > > best suited place for this is Intel controller, do we really want to > > have this in core logic? > > It's a valid objection. > > The reason why I added the alternate strategies in the core logic is > that the IDA and hybrid approach are just software-based with no > specific hardware dependencies. If QCOM or AMD wanted to use the > strategies contributed and tested by Intel, it'd be a two-line change on > their side. > > That said, it's likely that at some point *someone* will want to > constrain the device number allocation further, be it with ACPI/DT > properties or reading hardware registers. The device number is a > de-facto priority given the way we scan the PING frames, so some systems > may want to give a higher priority to a specific peripherals. > > This would push us to add a master ops callback to control the device > number allocation. It's a bit invasive but that would give the ultimate > flexibility. Reuse between vendors could be possible if 'generic' > callbacks were part of a library to pick from. > > I don't really have any objections if this vendor-specific callback was > preferred, it may be a bit early to add this but long-term it's probably > what makes more sense. > > I'll go with the flow on suggested recommendations. Thanks, if it all one of the other two controller start using this, it would make sense to move it to core then, for now would be better to have this in specific driver
>>> This seems to be a consequence of Intel hardware decisions, so I guess >>> best suited place for this is Intel controller, do we really want to >>> have this in core logic? >> >> It's a valid objection. >> >> The reason why I added the alternate strategies in the core logic is >> that the IDA and hybrid approach are just software-based with no >> specific hardware dependencies. If QCOM or AMD wanted to use the >> strategies contributed and tested by Intel, it'd be a two-line change on >> their side. >> >> That said, it's likely that at some point *someone* will want to >> constrain the device number allocation further, be it with ACPI/DT >> properties or reading hardware registers. The device number is a >> de-facto priority given the way we scan the PING frames, so some systems >> may want to give a higher priority to a specific peripherals. >> >> This would push us to add a master ops callback to control the device >> number allocation. It's a bit invasive but that would give the ultimate >> flexibility. Reuse between vendors could be possible if 'generic' >> callbacks were part of a library to pick from. >> >> I don't really have any objections if this vendor-specific callback was >> preferred, it may be a bit early to add this but long-term it's probably >> what makes more sense. >> >> I'll go with the flow on suggested recommendations. > > Thanks, if it all one of the other two controller start using this, it > would make sense to move it to core then, for now would be better to > have this in specific driver The code is much cleaner indeed that way. I still have to work on a race condition if the codec driver probe happens *after* the enumeration. In that case, the properties needed to decide which allocation to use are not initialized yet. We may need to either force the codec to re-enumerate with a ForceReset, or to switch the device number. In theory the latter is straightforward but there can be additional races if there are interrupts thrown just before the device number change happens.
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index e8c1c55a2a73..6f465cce8369 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -159,7 +159,9 @@ static int sdw_delete_slave(struct device *dev, void *data) if (slave->dev_num) { /* clear dev_num if assigned */ clear_bit(slave->dev_num, bus->assigned); - if (bus->dev_num_alloc == SDW_DEV_NUM_ALLOC_IDA) + if (bus->dev_num_alloc == SDW_DEV_NUM_ALLOC_IDA || + (bus->dev_num_alloc == SDW_DEV_NUM_ALLOC_IDA_WAKE_ONLY && + slave->prop.wake_capable)) ida_free(&sdw_peripheral_ida, slave->dev_num); } list_del_init(&slave->node); @@ -699,17 +701,31 @@ EXPORT_SYMBOL(sdw_compare_devid); /* called with bus_lock held */ static int sdw_get_device_num(struct sdw_slave *slave) { + struct sdw_bus *bus = slave->bus; int bit; - if (slave->bus->dev_num_alloc == SDW_DEV_NUM_ALLOC_IDA) { + if (bus->dev_num_alloc == SDW_DEV_NUM_ALLOC_IDA || + (bus->dev_num_alloc == SDW_DEV_NUM_ALLOC_IDA_WAKE_ONLY && + slave->prop.wake_capable)) { bit = ida_alloc_range(&sdw_peripheral_ida, - slave->bus->dev_num_ida_min, SDW_MAX_DEVICES, + bus->dev_num_ida_min, SDW_MAX_DEVICES, GFP_KERNEL); if (bit < 0) goto err; } else { - bit = find_first_zero_bit(slave->bus->assigned, SDW_MAX_DEVICES); - if (bit == SDW_MAX_DEVICES) { + int max_devices = SDW_MAX_DEVICES; + + if (bus->dev_num_alloc == SDW_DEV_NUM_ALLOC_IDA_WAKE_ONLY && + !slave->prop.wake_capable) { + max_devices = bus->dev_num_ida_min - 1; + + /* range check */ + if (max_devices < 1 || max_devices > SDW_MAX_DEVICES) + return -EINVAL; + } + + bit = find_first_zero_bit(bus->assigned, max_devices); + if (bit == max_devices) { bit = -ENODEV; goto err; } diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 4656d6d0f3bb..8a7541ac735e 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -869,10 +869,14 @@ struct sdw_master_ops { * @SDW_DEV_NUM_ALLOC_DEFAULT: unconstrained first-come-first-serve allocation, * using range [1, 11] * @SDW_DEV_NUM_ALLOC_IDA: IDA-based allocation, using range [ida_min, 11] + * @SDW_DEV_NUM_ALLOC_IDA_WAKE_ONLY: Hybrid allocation where wake-capable devices rely on + * IDA-based allocation and range [ida_min, 11], while regular devices rely on default + * allocation in range [1, ida_min - 1] */ enum sdw_dev_num_alloc { SDW_DEV_NUM_ALLOC_DEFAULT = 0, SDW_DEV_NUM_ALLOC_IDA, + SDW_DEV_NUM_ALLOC_IDA_WAKE_ONLY, }; /**