Skip to content

Commit 9ddaf9c

Browse files
committed
PCI/IDE: Report available IDE streams
The limited number of link-encryption (IDE) streams that a given set of host bridges supports is a platform specific detail. Provide pci_ide_init_nr_streams() as a generic facility for either platform TSM drivers, or PCI core native IDE, to report the number available streams. After invoking pci_ide_init_nr_streams() an "available_secure_streams" attribute appears in PCI host bridge sysfs to convey that count. Introduce a device-type, @pci_host_bridge_type, now that both a release method and sysfs attribute groups are being specified for all 'struct pci_host_bridge' instances. Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Lukas Wunner <lukas@wunner.de> Cc: Samuel Ortiz <sameo@rivosinc.com> Cc: Alexey Kardashevskiy <aik@amd.com> Cc: Xu Yilun <yilun.xu@linux.intel.com> Acked-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com> Link: https://patch.msgid.link/20251031212902.2256310-9-dan.j.williams@intel.com Signed-off-by: Dan Williams <dan.j.williams@intel.com>
1 parent 1e4d2ff commit 9ddaf9c

5 files changed

Lines changed: 94 additions & 1 deletion

File tree

Documentation/ABI/testing/sysfs-devices-pci-host-bridge

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,15 @@ Description:
3131
platform specific pool of stream resources shared by the Root
3232
Ports in a host bridge. See /sys/devices/pciDDDD:BB entry for
3333
details about the DDDD:BB format.
34+
35+
What: pciDDDD:BB/available_secure_streams
36+
Contact: linux-pci@vger.kernel.org
37+
Description:
38+
(RO) When a host bridge has Root Ports that support PCIe IDE
39+
(link encryption and integrity protection) there may be a
40+
limited number of Selective IDE Streams that can be used for
41+
establishing new end-to-end secure links. This attribute
42+
decrements upon secure link setup, and increments upon secure
43+
link teardown. The in-use stream count is determined by counting
44+
stream symlinks. See /sys/devices/pciDDDD:BB entry for details
45+
about the DDDD:BB format.

drivers/pci/ide.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,3 +514,70 @@ void pci_ide_init_host_bridge(struct pci_host_bridge *hb)
514514
hb->nr_ide_streams = 256;
515515
ida_init(&hb->ide_stream_ida);
516516
}
517+
518+
static ssize_t available_secure_streams_show(struct device *dev,
519+
struct device_attribute *attr,
520+
char *buf)
521+
{
522+
struct pci_host_bridge *hb = to_pci_host_bridge(dev);
523+
int nr = READ_ONCE(hb->nr_ide_streams);
524+
int avail = nr;
525+
526+
if (!nr)
527+
return -ENXIO;
528+
529+
/*
530+
* Yes, this is inefficient and racy, but it is only for occasional
531+
* platform resource surveys. Worst case is bounded to 256 streams.
532+
*/
533+
for (int i = 0; i < nr; i++)
534+
if (ida_exists(&hb->ide_stream_ida, i))
535+
avail--;
536+
return sysfs_emit(buf, "%d\n", avail);
537+
}
538+
static DEVICE_ATTR_RO(available_secure_streams);
539+
540+
static struct attribute *pci_ide_attrs[] = {
541+
&dev_attr_available_secure_streams.attr,
542+
NULL
543+
};
544+
545+
static umode_t pci_ide_attr_visible(struct kobject *kobj, struct attribute *a, int n)
546+
{
547+
struct device *dev = kobj_to_dev(kobj);
548+
struct pci_host_bridge *hb = to_pci_host_bridge(dev);
549+
550+
if (a == &dev_attr_available_secure_streams.attr)
551+
if (!hb->nr_ide_streams)
552+
return 0;
553+
554+
return a->mode;
555+
}
556+
557+
const struct attribute_group pci_ide_attr_group = {
558+
.attrs = pci_ide_attrs,
559+
.is_visible = pci_ide_attr_visible,
560+
};
561+
562+
/**
563+
* pci_ide_set_nr_streams() - sets size of the pool of IDE Stream resources
564+
* @hb: host bridge boundary for the stream pool
565+
* @nr: number of streams
566+
*
567+
* Platform PCI init and/or expert test module use only. Limit IDE
568+
* Stream establishment by setting the number of stream resources
569+
* available at the host bridge. Platform init code must set this before
570+
* the first pci_ide_stream_alloc() call if the platform has less than the
571+
* default of 256 streams per host-bridge.
572+
*
573+
* The "PCI_IDE" symbol namespace is required because this is typically
574+
* a detail that is settled in early PCI init. I.e. this export is not
575+
* for endpoint drivers.
576+
*/
577+
void pci_ide_set_nr_streams(struct pci_host_bridge *hb, u16 nr)
578+
{
579+
hb->nr_ide_streams = min(nr, 256);
580+
WARN_ON_ONCE(!ida_is_empty(&hb->ide_stream_ida));
581+
sysfs_update_group(&hb->dev.kobj, &pci_ide_attr_group);
582+
}
583+
EXPORT_SYMBOL_NS_GPL(pci_ide_set_nr_streams, "PCI_IDE");

drivers/pci/pci.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,7 @@ static inline void pci_doe_sysfs_teardown(struct pci_dev *pdev) { }
616616
#ifdef CONFIG_PCI_IDE
617617
void pci_ide_init(struct pci_dev *dev);
618618
void pci_ide_init_host_bridge(struct pci_host_bridge *hb);
619+
extern const struct attribute_group pci_ide_attr_group;
619620
#else
620621
static inline void pci_ide_init(struct pci_dev *dev) { }
621622
static inline void pci_ide_init_host_bridge(struct pci_host_bridge *hb) { }

drivers/pci/probe.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,18 @@ static void pci_release_host_bridge_dev(struct device *dev)
653653
kfree(bridge);
654654
}
655655

656+
static const struct attribute_group *pci_host_bridge_groups[] = {
657+
#ifdef CONFIG_PCI_IDE
658+
&pci_ide_attr_group,
659+
#endif
660+
NULL
661+
};
662+
663+
static const struct device_type pci_host_bridge_type = {
664+
.groups = pci_host_bridge_groups,
665+
.release = pci_release_host_bridge_dev,
666+
};
667+
656668
static void pci_init_host_bridge(struct pci_host_bridge *bridge)
657669
{
658670
INIT_LIST_HEAD(&bridge->windows);
@@ -672,6 +684,7 @@ static void pci_init_host_bridge(struct pci_host_bridge *bridge)
672684
bridge->native_dpc = 1;
673685
bridge->domain_nr = PCI_DOMAIN_NR_NOT_SET;
674686
bridge->native_cxl_error = 1;
687+
bridge->dev.type = &pci_host_bridge_type;
675688
pci_ide_init_host_bridge(bridge);
676689

677690
device_initialize(&bridge->dev);
@@ -686,7 +699,6 @@ struct pci_host_bridge *pci_alloc_host_bridge(size_t priv)
686699
return NULL;
687700

688701
pci_init_host_bridge(bridge);
689-
bridge->dev.release = pci_release_host_bridge_dev;
690702

691703
return bridge;
692704
}

include/linux/pci-ide.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ struct pci_ide {
6363
const char *name;
6464
};
6565

66+
void pci_ide_set_nr_streams(struct pci_host_bridge *hb, u16 nr);
6667
struct pci_ide_partner *pci_ide_to_settings(struct pci_dev *pdev,
6768
struct pci_ide *ide);
6869
struct pci_ide *pci_ide_stream_alloc(struct pci_dev *pdev);

0 commit comments

Comments
 (0)