From: Alexey Kardashevskiy <aik@amd.com>
To: Dan Williams <dan.j.williams@intel.com>,
linux-coco@lists.linux.dev, linux-pci@vger.kernel.org
Cc: yilun.xu@linux.intel.com, aneesh.kumar@kernel.org,
gregkh@linuxfoundation.org, Bjorn Helgaas <bhelgaas@google.com>,
Lukas Wunner <lukas@wunner.de>, Samuel Ortiz <sameo@rivosinc.com>
Subject: Re: [PATCH v5 07/10] PCI/IDE: Add IDE establishment helpers
Date: Tue, 2 Sep 2025 11:29:35 +1000 [thread overview]
Message-ID: <eeca3820-01dd-4abc-a437-cf46dc718ab6@amd.com> (raw)
In-Reply-To: <20250827035126.1356683-8-dan.j.williams@intel.com>
On 27/8/25 13:51, Dan Williams wrote:
> There are two components to establishing an encrypted link, provisioning
> the stream in Partner Port config-space, and programming the keys into
> the link layer via IDE_KM (IDE Key Management). This new library,
> drivers/pci/ide.c, enables the former. IDE_KM, via a TSM low-level
> driver, is saved for later.
>
> With the platform TSM implementations of SEV-TIO and TDX Connect in mind
> this library abstracts small differences in those implementations. For
> example, TDX Connect handles Root Port register setup while SEV-TIO
> expects System Software to update the Root Port registers. This is the
> rationale for fine-grained 'setup' + 'enable' verbs.
>
> The other design detail for TSM-coordinated IDE establishment is that
> the TSM may manage allocation of Stream IDs, this is why the Stream ID
> value is passed in to pci_ide_stream_setup().
>
> The flow is:
>
> pci_ide_stream_alloc():
> Allocate a Selective IDE Stream Register Block in each Partner Port
> (Endpoint + Root Port), and reserve a host bridge / platform stream
> slot. Gather Partner Port specific stream settings like Requester ID.
>
> pci_ide_stream_register():
> Publish the stream in sysfs after allocating a Stream ID. In the TSM
> case the TSM allocates the Stream ID for the Partner Port pair.
>
> pci_ide_stream_setup():
> Program the stream settings to a Partner Port. Caller is responsible
> for optionally calling this for the Root Port as well if the TSM
> implementation requires it.
>
> pci_ide_stream_enable():
> Try to run the stream after IDE_KM.
>
> In support of system administrators auditing where platform, Root Port,
> and Endpoint IDE stream resources are being spent, the allocated stream
> is reflected as a symlink from the host bridge to the endpoint with the
> name:
>
> stream%d.%d.%d
>
> Where the tuple of integers reflects the allocated platform, Root Port,
> and Endpoint stream index (Selective IDE Stream Register Block) values.
>
> Thanks to Wu Hao for a draft implementation of this infrastructure.
>
> Cc: Bjorn Helgaas <bhelgaas@google.com>
> Cc: Lukas Wunner <lukas@wunner.de>
> Cc: Samuel Ortiz <sameo@rivosinc.com>
> Co-developed-by: Alexey Kardashevskiy <aik@amd.com>
> Signed-off-by: Alexey Kardashevskiy <aik@amd.com>
> Co-developed-by: Xu Yilun <yilun.xu@linux.intel.com>
> Signed-off-by: Xu Yilun <yilun.xu@linux.intel.com>
> Acked-by: Bjorn Helgaas <bhelgaas@google.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
> .../ABI/testing/sysfs-devices-pci-host-bridge | 14 +
> drivers/pci/ide.c | 427 ++++++++++++++++++
> include/linux/pci-ide.h | 70 +++
> include/linux/pci.h | 6 +
> 4 files changed, 517 insertions(+)
> create mode 100644 include/linux/pci-ide.h
>
> diff --git a/Documentation/ABI/testing/sysfs-devices-pci-host-bridge b/Documentation/ABI/testing/sysfs-devices-pci-host-bridge
> index 8c3a652799f1..2c66e5bb2bf8 100644
> --- a/Documentation/ABI/testing/sysfs-devices-pci-host-bridge
> +++ b/Documentation/ABI/testing/sysfs-devices-pci-host-bridge
> @@ -17,3 +17,17 @@ Description:
> PNP0A08 (/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00). See
> /sys/devices/pciDDDD:BB entry for details about the DDDD:BB
> format.
> +
> +What: pciDDDD:BB/streamH.R.E
> +Contact: linux-pci@vger.kernel.org
> +Description:
> + (RO) When a platform has established a secure connection, PCIe
> + IDE, between two Partner Ports, this symlink appears. A stream
> + consumes a Stream ID slot in each of the Host bridge (H), Root
> + Port (R) and Endpoint (E). The link points to the Endpoint PCI
> + device in the Selective IDE Stream pairing. Specifically, "R"
> + and "E" represent the assigned Selective IDE Stream Register
> + Block in the Root Port and Endpoint, and "H" represents a
> + platform specific pool of stream resources shared by the Root
> + Ports in a host bridge. See /sys/devices/pciDDDD:BB entry for
> + details about the DDDD:BB format.
> diff --git a/drivers/pci/ide.c b/drivers/pci/ide.c
> index 05ab8c18b768..4f5aa42e05ef 100644
> --- a/drivers/pci/ide.c
> +++ b/drivers/pci/ide.c
> @@ -5,8 +5,12 @@
>
> #define dev_fmt(fmt) "PCI/IDE: " fmt
> #include <linux/bitfield.h>
> +#include <linux/bitops.h>
> #include <linux/pci.h>
> +#include <linux/pci-ide.h>
> #include <linux/pci_regs.h>
> +#include <linux/slab.h>
> +#include <linux/sysfs.h>
>
> #include "pci.h"
>
> @@ -23,6 +27,13 @@ static int __sel_ide_offset(u16 ide_cap, u8 nr_link_ide, u8 stream_index,
> return offset + stream_index * PCI_IDE_SEL_BLOCK_SIZE(nr_ide_mem);
> }
>
> +static int sel_ide_offset(struct pci_dev *pdev,
> + struct pci_ide_partner *settings)
> +{
> + return __sel_ide_offset(pdev->ide_cap, pdev->nr_link_ide,
> + settings->stream_index, pdev->nr_ide_mem);
> +}
> +
> void pci_ide_init(struct pci_dev *pdev)
> {
> u8 nr_link_ide, nr_ide_mem, nr_streams;
> @@ -88,5 +99,421 @@ void pci_ide_init(struct pci_dev *pdev)
>
> pdev->ide_cap = ide_cap;
> pdev->nr_link_ide = nr_link_ide;
> + pdev->nr_sel_ide = nr_streams;
> pdev->nr_ide_mem = nr_ide_mem;
> }
> +
> +struct stream_index {
> + unsigned long *map;
> + u8 max, stream_index;
> +};
> +
> +static void free_stream_index(struct stream_index *stream)
> +{
> + clear_bit_unlock(stream->stream_index, stream->map);
> +}
> +
> +DEFINE_FREE(free_stream, struct stream_index *, if (_T) free_stream_index(_T))
> +static struct stream_index *alloc_stream_index(unsigned long *map, u8 max,
> + struct stream_index *stream)
> +{
> + if (!max)
> + return NULL;
> +
> + do {
> + u8 stream_index = find_first_zero_bit(map, max);
> +
> + if (stream_index == max)
> + return NULL;
> + if (!test_and_set_bit_lock(stream_index, map)) {
> + *stream = (struct stream_index) {
> + .map = map,
> + .max = max,
> + .stream_index = stream_index,
> + };
> + return stream;
> + }
> + /* collided with another stream acquisition */
> + } while (1);
> +}
> +
> +/**
> + * pci_ide_stream_alloc() - Reserve stream indices and probe for settings
> + * @pdev: IDE capable PCIe Endpoint Physical Function
> + *
> + * Retrieve the Requester ID range of @pdev for programming its Root
> + * Port IDE RID Association registers, and conversely retrieve the
> + * Requester ID of the Root Port for programming @pdev's IDE RID
> + * Association registers.
> + *
> + * Allocate a Selective IDE Stream Register Block instance per port.
> + *
> + * Allocate a platform stream resource from the associated host bridge.
> + * Retrieve stream association parameters for Requester ID range and
> + * address range restrictions for the stream.
> + */
> +struct pci_ide *pci_ide_stream_alloc(struct pci_dev *pdev)
> +{
> + /* EP, RP, + HB Stream allocation */
> + struct stream_index __stream[PCI_IDE_HB + 1];
> + struct pci_host_bridge *hb;
> + struct pci_dev *rp;
> + int num_vf, rid_end;
> +
> + if (!pci_is_pcie(pdev))
> + return NULL;
> +
> + if (pci_pcie_type(pdev) != PCI_EXP_TYPE_ENDPOINT)
> + return NULL;
> +
> + if (!pdev->ide_cap)
> + return NULL;
> +
> + /*
> + * Catch buggy PCI platform initialization (missing
> + * pci_ide_init_nr_streams())
> + */
> + hb = pci_find_host_bridge(pdev->bus);
> + if (WARN_ON_ONCE(!hb->nr_ide_streams))
> + return NULL;
> +
> + struct pci_ide *ide __free(kfree) = kzalloc(sizeof(*ide), GFP_KERNEL);
> + if (!ide)
> + return NULL;
> +
> + struct stream_index *hb_stream __free(free_stream) = alloc_stream_index(
> + hb->ide_stream_map, hb->nr_ide_streams, &__stream[PCI_IDE_HB]);
> + if (!hb_stream)
> + return NULL;
> +
> + rp = pcie_find_root_port(pdev);
> + struct stream_index *rp_stream __free(free_stream) = alloc_stream_index(
> + rp->ide_stream_map, rp->nr_sel_ide, &__stream[PCI_IDE_RP]);
> + if (!rp_stream)
> + return NULL;
> +
> + struct stream_index *ep_stream __free(free_stream) = alloc_stream_index(
> + pdev->ide_stream_map, pdev->nr_sel_ide, &__stream[PCI_IDE_EP]);
> + if (!ep_stream)
> + return NULL;
> +
> + /* for SR-IOV case, cover all VFs */
> + num_vf = pci_num_vf(pdev);
> + if (num_vf)
> + rid_end = PCI_DEVID(pci_iov_virtfn_bus(pdev, num_vf),
> + pci_iov_virtfn_devfn(pdev, num_vf));
> + else
> + rid_end = pci_dev_id(pdev);
> +
> + *ide = (struct pci_ide) {
> + .pdev = pdev,
> + .partner = {
> + [PCI_IDE_EP] = {
> + .rid_start = pci_dev_id(rp),
> + .rid_end = pci_dev_id(rp),
> + .stream_index = no_free_ptr(ep_stream)->stream_index,
> + },
> + [PCI_IDE_RP] = {
> + .rid_start = pci_dev_id(pdev),
> + .rid_end = rid_end,
> + .stream_index = no_free_ptr(rp_stream)->stream_index,
> + },
> + },
> + .host_bridge_stream = no_free_ptr(hb_stream)->stream_index,
> + .stream_id = -1,
> + };
> +
> + return_ptr(ide);
> +}
> +EXPORT_SYMBOL_GPL(pci_ide_stream_alloc);
> +
> +/**
> + * pci_ide_stream_free() - unwind pci_ide_stream_alloc()
> + * @ide: idle IDE settings descriptor
> + *
> + * Free all of the stream index (register block) allocations acquired by
> + * pci_ide_stream_alloc(). The stream represented by @ide is assumed to
> + * be unregistered and not instantiated in any device.
> + */
> +void pci_ide_stream_free(struct pci_ide *ide)
> +{
> + struct pci_dev *pdev = ide->pdev;
> + struct pci_dev *rp = pcie_find_root_port(pdev);
> + struct pci_host_bridge *hb = pci_find_host_bridge(pdev->bus);
> +
> + clear_bit_unlock(ide->partner[PCI_IDE_EP].stream_index,
> + pdev->ide_stream_map);
> + clear_bit_unlock(ide->partner[PCI_IDE_RP].stream_index,
> + rp->ide_stream_map);
> + clear_bit_unlock(ide->host_bridge_stream, hb->ide_stream_map);
> + kfree(ide);
> +}
> +EXPORT_SYMBOL_GPL(pci_ide_stream_free);
> +
> +/**
> + * pci_ide_stream_release() - unwind and release an @ide context
> + * @ide: partially or fully registered IDE settings descriptor
> + *
> + * In support of automatic cleanup of IDE setup routines perform IDE
> + * teardown in expected reverse order of setup and with respect to which
> + * aspects of IDE setup have successfully completed.
> + *
> + * Be careful that setup order mirrors this shutdown order. Otherwise,
> + * open code releasing the IDE context.
> + */
> +void pci_ide_stream_release(struct pci_ide *ide)
> +{
> + struct pci_dev *pdev = ide->pdev;
> + struct pci_dev *rp = pcie_find_root_port(pdev);
> +
> + if (ide->partner[PCI_IDE_RP].enable)
> + pci_ide_stream_disable(rp, ide);
> +
> + if (ide->partner[PCI_IDE_EP].enable)
> + pci_ide_stream_disable(pdev, ide);
> +
> + if (ide->partner[PCI_IDE_RP].setup)
> + pci_ide_stream_teardown(rp, ide);
> +
> + if (ide->partner[PCI_IDE_EP].setup)
> + pci_ide_stream_teardown(pdev, ide);
> +
> + if (ide->name)
> + pci_ide_stream_unregister(ide);
> +
> + pci_ide_stream_free(ide);
> +}
> +EXPORT_SYMBOL_GPL(pci_ide_stream_release);
> +
> +/**
> + * pci_ide_stream_register() - Prepare to activate an IDE Stream
> + * @ide: IDE settings descriptor
> + *
> + * After a Stream ID has been acquired for @ide, record the presence of
> + * the stream in sysfs. The expectation is that @ide is immutable while
> + * registered.
> + */
> +int pci_ide_stream_register(struct pci_ide *ide)
> +{
> + struct pci_dev *pdev = ide->pdev;
> + struct pci_host_bridge *hb = pci_find_host_bridge(pdev->bus);
> + u8 ep_stream, rp_stream;
> + int rc;
> +
> + if (ide->stream_id < 0 || ide->stream_id > U8_MAX) {
> + pci_err(pdev, "Setup fail: Invalid Stream ID: %d\n", ide->stream_id);
> + return -ENXIO;
> + }
> +
> + ep_stream = ide->partner[PCI_IDE_EP].stream_index;
> + rp_stream = ide->partner[PCI_IDE_RP].stream_index;
> + const char *name __free(kfree) = kasprintf(GFP_KERNEL, "stream%d.%d.%d",
> + ide->host_bridge_stream,
> + rp_stream, ep_stream);
> + if (!name)
> + return -ENOMEM;
> +
> + rc = sysfs_create_link(&hb->dev.kobj, &pdev->dev.kobj, name);
> + if (rc)
> + return rc;
> +
> + ide->name = no_free_ptr(name);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(pci_ide_stream_register);
> +
> +/**
> + * pci_ide_stream_unregister() - unwind pci_ide_stream_register()
> + * @ide: idle IDE settings descriptor
> + *
> + * In preparation for freeing @ide, remove sysfs enumeration for the
> + * stream.
> + */
> +void pci_ide_stream_unregister(struct pci_ide *ide)
> +{
> + struct pci_dev *pdev = ide->pdev;
> + struct pci_host_bridge *hb = pci_find_host_bridge(pdev->bus);
> +
> + sysfs_remove_link(&hb->dev.kobj, ide->name);
> + kfree(ide->name);
> + ide->name = NULL;
> +}
> +EXPORT_SYMBOL_GPL(pci_ide_stream_unregister);
> +
> +static int pci_ide_domain(struct pci_dev *pdev)
> +{
> + if (pdev->fm_enabled)
> + return pci_domain_nr(pdev->bus);
> + return 0;
> +}
> +
> +struct pci_ide_partner *pci_ide_to_settings(struct pci_dev *pdev, struct pci_ide *ide)
> +{
> + if (!pci_is_pcie(pdev)) {
> + pci_warn_once(pdev, "not a PCIe device\n");
> + return NULL;
> + }
> +
> + switch (pci_pcie_type(pdev)) {
> + case PCI_EXP_TYPE_ENDPOINT:
> + if (pdev != ide->pdev) {
> + pci_warn_once(pdev, "setup expected Endpoint: %s\n", pci_name(ide->pdev));
> + return NULL;
> + }
> + return &ide->partner[PCI_IDE_EP];
> + case PCI_EXP_TYPE_ROOT_PORT: {
> + struct pci_dev *rp = pcie_find_root_port(ide->pdev);
> +
> + if (pdev != rp) {
> + pci_warn_once(pdev, "setup expected Root Port: %s\n",
> + pci_name(rp));
> + return NULL;
> + }
> + return &ide->partner[PCI_IDE_RP];
> + }
> + default:
> + pci_warn_once(pdev, "invalid device type\n");
> + return NULL;
> + }
> +}
> +EXPORT_SYMBOL_GPL(pci_ide_to_settings);
> +
> +static void set_ide_sel_ctl(struct pci_dev *pdev, struct pci_ide *ide, int pos,
> + bool enable)
> +{
> + u32 val = FIELD_PREP(PCI_IDE_SEL_CTL_ID, ide->stream_id) |
> + FIELD_PREP(PCI_IDE_SEL_CTL_CFG_EN, pdev->ide_cfg) |
There was:
FIELD_PREP(PCI_IDE_SEL_CTL_DEFAULT, 1) |
and now it is gone, why? And it is not in any change log, took me a while to find out what broke.
Thanks,
> + FIELD_PREP(PCI_IDE_SEL_CTL_TEE_LIMITED, pdev->ide_tee_limit) |
> + FIELD_PREP(PCI_IDE_SEL_CTL_EN, enable);
> +
> + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_CTL, val);
> +}
> +
> +/**
> + * pci_ide_stream_setup() - program settings to Selective IDE Stream registers
> + * @pdev: PCIe device object for either a Root Port or Endpoint Partner Port
> + * @ide: registered IDE settings descriptor
> + *
> + * When @pdev is a PCI_EXP_TYPE_ENDPOINT then the PCI_IDE_EP partner
> + * settings are written to @pdev's Selective IDE Stream register block,
> + * and when @pdev is a PCI_EXP_TYPE_ROOT_PORT, the PCI_IDE_RP settings
> + * are selected.
> + */
> +void pci_ide_stream_setup(struct pci_dev *pdev, struct pci_ide *ide)
> +{
> + struct pci_ide_partner *settings = pci_ide_to_settings(pdev, ide);
> + int pos;
> + u32 val;
> +
> + if (!settings)
> + return;
> +
> + pos = sel_ide_offset(pdev, settings);
> +
> + val = FIELD_PREP(PCI_IDE_SEL_RID_1_LIMIT, settings->rid_end);
> + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_RID_1, val);
> +
> + val = FIELD_PREP(PCI_IDE_SEL_RID_2_VALID, 1) |
> + FIELD_PREP(PCI_IDE_SEL_RID_2_BASE, settings->rid_start) |
> + FIELD_PREP(PCI_IDE_SEL_RID_2_SEG, pci_ide_domain(pdev));
> +
> + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_RID_2, val);
> +
> + /*
> + * Setup control register early for devices that expect
> + * stream_id is set during key programming.
> + */
> + set_ide_sel_ctl(pdev, ide, pos, false);
> + settings->setup = 1;
> +}
> +EXPORT_SYMBOL_GPL(pci_ide_stream_setup);
> +
> +/**
> + * pci_ide_stream_teardown() - disable the stream and clear all settings
> + * @pdev: PCIe device object for either a Root Port or Endpoint Partner Port
> + * @ide: registered IDE settings descriptor
> + *
> + * For stream destruction, zero all registers that may have been written
> + * by pci_ide_stream_setup(). Consider pci_ide_stream_disable() to leave
> + * settings in place while temporarily disabling the stream.
> + */
> +void pci_ide_stream_teardown(struct pci_dev *pdev, struct pci_ide *ide)
> +{
> + struct pci_ide_partner *settings = pci_ide_to_settings(pdev, ide);
> + int pos;
> +
> + if (!settings)
> + return;
> +
> + pos = sel_ide_offset(pdev, settings);
> +
> + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_CTL, 0);
> + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_RID_2, 0);
> + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_RID_1, 0);
> + settings->setup = 0;
> +}
> +EXPORT_SYMBOL_GPL(pci_ide_stream_teardown);
> +
> +/**
> + * pci_ide_stream_enable() - enable a Selective IDE Stream
> + * @pdev: PCIe device object for either a Root Port or Endpoint Partner Port
> + * @ide: registered and setup IDE settings descriptor
> + *
> + * Activate the stream by writing to the Selective IDE Stream Control
> + * Register.
> + *
> + * Return: 0 if the stream successfully entered the "secure" state, and -ENXIO
> + * otherwise.
> + *
> + * Note that the state may go "insecure" at any point after returning 0, but
> + * those events are equivalent to a "link down" event and handled via
> + * asynchronous error reporting.
> + */
> +int pci_ide_stream_enable(struct pci_dev *pdev, struct pci_ide *ide)
> +{
> + struct pci_ide_partner *settings = pci_ide_to_settings(pdev, ide);
> + int pos;
> + u32 val;
> +
> + if (!settings)
> + return -ENXIO;
> +
> + pos = sel_ide_offset(pdev, settings);
> +
> + set_ide_sel_ctl(pdev, ide, pos, true);
> +
> + pci_read_config_dword(pdev, pos + PCI_IDE_SEL_STS, &val);
> + if (FIELD_GET(PCI_IDE_SEL_STS_STATE, val) !=
> + PCI_IDE_SEL_STS_STATE_SECURE) {
> + set_ide_sel_ctl(pdev, ide, pos, false);
> + return -ENXIO;
> + }
> +
> + settings->enable = 1;
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(pci_ide_stream_enable);
> +
> +/**
> + * pci_ide_stream_disable() - disable a Selective IDE Stream
> + * @pdev: PCIe device object for either a Root Port or Endpoint Partner Port
> + * @ide: registered and setup IDE settings descriptor
> + *
> + * Clear the Selective IDE Stream Control Register, but leave all other
> + * registers untouched.
> + */
> +void pci_ide_stream_disable(struct pci_dev *pdev, struct pci_ide *ide)
> +{
> + struct pci_ide_partner *settings = pci_ide_to_settings(pdev, ide);
> + int pos;
> +
> + if (!settings)
> + return;
> +
> + pos = sel_ide_offset(pdev, settings);
> +
> + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_CTL, 0);
> + settings->enable = 0;
> +}
> +EXPORT_SYMBOL_GPL(pci_ide_stream_disable);
> diff --git a/include/linux/pci-ide.h b/include/linux/pci-ide.h
> new file mode 100644
> index 000000000000..cf1f7a10e8e0
> --- /dev/null
> +++ b/include/linux/pci-ide.h
> @@ -0,0 +1,70 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Copyright(c) 2024 Intel Corporation. All rights reserved. */
> +
> +/* PCIe 6.2 section 6.33 Integrity & Data Encryption (IDE) */
> +
> +#ifndef __PCI_IDE_H__
> +#define __PCI_IDE_H__
> +
> +enum pci_ide_partner_select {
> + PCI_IDE_EP,
> + PCI_IDE_RP,
> + PCI_IDE_PARTNER_MAX,
> + /*
> + * In addition to the resources in each partner port the
> + * platform / host-bridge additionally has a Stream ID pool that
> + * it shares across root ports. Let pci_ide_stream_alloc() use
> + * the alloc_stream_index() helper as endpoints and root ports.
> + */
> + PCI_IDE_HB = PCI_IDE_PARTNER_MAX,
> +};
> +
> +/**
> + * struct pci_ide_partner - Per port pair Selective IDE Stream settings
> + * @rid_start: Partner Port Requester ID range start
> + * @rid_start: Partner Port Requester ID range end
> + * @stream_index: Selective IDE Stream Register Block selection
> + * @setup: flag to track whether to run pci_ide_stream_teardown() for this
> + * partner slot
> + * @enable: flag whether to run pci_ide_stream_disable() for this partner slot
> + */
> +struct pci_ide_partner {
> + u16 rid_start;
> + u16 rid_end;
> + u8 stream_index;
> + unsigned int setup:1;
> + unsigned int enable:1;
> +};
> +
> +/**
> + * struct pci_ide - PCIe Selective IDE Stream descriptor
> + * @pdev: PCIe Endpoint in the pci_ide_partner pair
> + * @partner: per-partner settings
> + * @host_bridge_stream: track platform Stream ID
> + * @stream_id: unique Stream ID (within Partner Port pairing)
> + * @name: name of the established Selective IDE Stream in sysfs
> + *
> + * Negative @stream_id values indicate "uninitialized" on the
> + * expectation that with TSM established IDE the TSM owns the stream_id
> + * allocation.
> + */
> +struct pci_ide {
> + struct pci_dev *pdev;
> + struct pci_ide_partner partner[PCI_IDE_PARTNER_MAX];
> + u8 host_bridge_stream;
> + int stream_id;
> + const char *name;
> +};
> +
> +struct pci_ide_partner *pci_ide_to_settings(struct pci_dev *pdev, struct pci_ide *ide);
> +struct pci_ide *pci_ide_stream_alloc(struct pci_dev *pdev);
> +void pci_ide_stream_free(struct pci_ide *ide);
> +int pci_ide_stream_register(struct pci_ide *ide);
> +void pci_ide_stream_unregister(struct pci_ide *ide);
> +void pci_ide_stream_setup(struct pci_dev *pdev, struct pci_ide *ide);
> +void pci_ide_stream_teardown(struct pci_dev *pdev, struct pci_ide *ide);
> +int pci_ide_stream_enable(struct pci_dev *pdev, struct pci_ide *ide);
> +void pci_ide_stream_disable(struct pci_dev *pdev, struct pci_ide *ide);
> +void pci_ide_stream_release(struct pci_ide *ide);
> +DEFINE_FREE(pci_ide_stream_release, struct pci_ide *, if (_T) pci_ide_stream_release(_T))
> +#endif /* __PCI_IDE_H__ */
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index d3880a4f175e..45360ba87538 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -544,6 +544,8 @@ struct pci_dev {
> u16 ide_cap; /* Link Integrity & Data Encryption */
> u8 nr_ide_mem; /* Address association resources for streams */
> u8 nr_link_ide; /* Link Stream count (Selective Stream offset) */
> + u8 nr_sel_ide; /* Selective Stream count (register block allocator) */
> + DECLARE_BITMAP(ide_stream_map, CONFIG_PCI_IDE_STREAM_MAX);
> unsigned int ide_cfg:1; /* Config cycles over IDE */
> unsigned int ide_tee_limit:1; /* Disallow T=0 traffic over IDE */
> #endif
> @@ -613,6 +615,10 @@ struct pci_host_bridge {
> int domain_nr;
> struct list_head windows; /* resource_entry */
> struct list_head dma_ranges; /* dma ranges resource list */
> +#ifdef CONFIG_PCI_IDE
> + u8 nr_ide_streams; /* Max streams possibly active in @ide_stream_map */
> + DECLARE_BITMAP(ide_stream_map, CONFIG_PCI_IDE_STREAM_MAX);
> +#endif
> u8 (*swizzle_irq)(struct pci_dev *, u8 *); /* Platform IRQ swizzler */
> int (*map_irq)(const struct pci_dev *, u8, u8);
> void (*release_fn)(struct pci_host_bridge *);
--
Alexey
next prev parent reply other threads:[~2025-09-02 1:29 UTC|newest]
Thread overview: 57+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-27 3:51 [PATCH v5 00/10] PCI/TSM: Core infrastructure for PCI device security (TDISP) Dan Williams
2025-08-27 3:51 ` [PATCH v5 01/10] coco/tsm: Introduce a core device for TEE Security Managers Dan Williams
2025-08-27 3:51 ` [PATCH v5 02/10] PCI/IDE: Enumerate Selective Stream IDE capabilities Dan Williams
2025-09-15 16:18 ` Jonathan Cameron
2025-09-19 23:32 ` dan.j.williams
2025-08-27 3:51 ` [PATCH v5 03/10] PCI: Introduce pci_walk_bus_reverse(), for_each_pci_dev_reverse() Dan Williams
2025-08-27 3:51 ` [PATCH v5 04/10] PCI/TSM: Authenticate devices via platform TSM Dan Williams
2025-08-27 13:25 ` Alexey Kardashevskiy
2025-08-29 1:06 ` dan.j.williams
2025-08-29 1:58 ` Alexey Kardashevskiy
2025-09-05 0:50 ` dan.j.williams
2025-09-05 3:34 ` Alexey Kardashevskiy
2025-09-06 2:07 ` dan.j.williams
2025-09-08 6:13 ` Alexey Kardashevskiy
2025-09-09 0:41 ` dan.j.williams
2025-09-09 1:35 ` Alexey Kardashevskiy
2025-09-09 1:52 ` dan.j.williams
2025-09-10 10:55 ` Alexey Kardashevskiy
2025-09-10 15:45 ` dan.j.williams
2025-08-28 11:43 ` Alexey Kardashevskiy
2025-08-29 1:23 ` dan.j.williams
2025-08-30 13:26 ` Alexey Kardashevskiy
2025-09-05 0:51 ` dan.j.williams
2025-09-02 15:08 ` Aneesh Kumar K.V
2025-09-03 2:03 ` Alexey Kardashevskiy
2025-09-05 20:06 ` dan.j.williams
2025-09-05 19:13 ` dan.j.williams
2025-09-02 15:13 ` Aneesh Kumar K.V
2025-09-03 2:07 ` Alexey Kardashevskiy
2025-09-05 20:13 ` dan.j.williams
2025-09-08 11:19 ` Alexey Kardashevskiy
2025-09-05 20:03 ` dan.j.williams
2025-09-03 2:17 ` Alexey Kardashevskiy
2025-09-05 20:35 ` dan.j.williams
2025-08-27 3:51 ` [PATCH v5 05/10] samples/devsec: Introduce a PCI device-security bus + endpoint sample Dan Williams
2025-08-27 3:51 ` [PATCH v5 06/10] PCI: Add PCIe Device 3 Extended Capability enumeration Dan Williams
2025-08-27 3:51 ` [PATCH v5 07/10] PCI/IDE: Add IDE establishment helpers Dan Williams
2025-09-02 1:29 ` Alexey Kardashevskiy [this message]
2025-09-02 1:54 ` Alexey Kardashevskiy
2025-09-05 1:40 ` dan.j.williams
2025-09-05 2:14 ` Alexey Kardashevskiy
2025-09-06 2:00 ` dan.j.williams
2025-09-08 6:25 ` Alexey Kardashevskiy
2025-09-09 0:42 ` dan.j.williams
2025-09-15 11:46 ` Alexey Kardashevskiy
2025-10-17 4:06 ` Alexey Kardashevskiy
2025-10-17 4:40 ` dan.j.williams
2025-10-17 11:15 ` Alexey Kardashevskiy
2025-09-05 1:27 ` dan.j.williams
2025-09-05 2:23 ` Alexey Kardashevskiy
2025-10-17 11:31 ` Alexey Kardashevskiy
2025-10-17 19:18 ` dan.j.williams
2025-10-28 23:00 ` dan.j.williams
2025-10-29 8:04 ` Alexey Kardashevskiy
2025-08-27 3:51 ` [PATCH v5 08/10] PCI/IDE: Report available IDE streams Dan Williams
2025-08-27 3:51 ` [PATCH v5 09/10] PCI/TSM: Report active " Dan Williams
2025-08-27 3:51 ` [PATCH v5 10/10] samples/devsec: Add sample IDE establishment Dan Williams
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=eeca3820-01dd-4abc-a437-cf46dc718ab6@amd.com \
--to=aik@amd.com \
--cc=aneesh.kumar@kernel.org \
--cc=bhelgaas@google.com \
--cc=dan.j.williams@intel.com \
--cc=gregkh@linuxfoundation.org \
--cc=linux-coco@lists.linux.dev \
--cc=linux-pci@vger.kernel.org \
--cc=lukas@wunner.de \
--cc=sameo@rivosinc.com \
--cc=yilun.xu@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.