mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
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>
This commit is contained in:
@@ -31,3 +31,15 @@ Description:
|
||||
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.
|
||||
|
||||
What: pciDDDD:BB/available_secure_streams
|
||||
Contact: linux-pci@vger.kernel.org
|
||||
Description:
|
||||
(RO) When a host bridge has Root Ports that support PCIe IDE
|
||||
(link encryption and integrity protection) there may be a
|
||||
limited number of Selective IDE Streams that can be used for
|
||||
establishing new end-to-end secure links. This attribute
|
||||
decrements upon secure link setup, and increments upon secure
|
||||
link teardown. The in-use stream count is determined by counting
|
||||
stream symlinks. See /sys/devices/pciDDDD:BB entry for details
|
||||
about the DDDD:BB format.
|
||||
|
||||
@@ -514,3 +514,70 @@ void pci_ide_init_host_bridge(struct pci_host_bridge *hb)
|
||||
hb->nr_ide_streams = 256;
|
||||
ida_init(&hb->ide_stream_ida);
|
||||
}
|
||||
|
||||
static ssize_t available_secure_streams_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct pci_host_bridge *hb = to_pci_host_bridge(dev);
|
||||
int nr = READ_ONCE(hb->nr_ide_streams);
|
||||
int avail = nr;
|
||||
|
||||
if (!nr)
|
||||
return -ENXIO;
|
||||
|
||||
/*
|
||||
* Yes, this is inefficient and racy, but it is only for occasional
|
||||
* platform resource surveys. Worst case is bounded to 256 streams.
|
||||
*/
|
||||
for (int i = 0; i < nr; i++)
|
||||
if (ida_exists(&hb->ide_stream_ida, i))
|
||||
avail--;
|
||||
return sysfs_emit(buf, "%d\n", avail);
|
||||
}
|
||||
static DEVICE_ATTR_RO(available_secure_streams);
|
||||
|
||||
static struct attribute *pci_ide_attrs[] = {
|
||||
&dev_attr_available_secure_streams.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static umode_t pci_ide_attr_visible(struct kobject *kobj, struct attribute *a, int n)
|
||||
{
|
||||
struct device *dev = kobj_to_dev(kobj);
|
||||
struct pci_host_bridge *hb = to_pci_host_bridge(dev);
|
||||
|
||||
if (a == &dev_attr_available_secure_streams.attr)
|
||||
if (!hb->nr_ide_streams)
|
||||
return 0;
|
||||
|
||||
return a->mode;
|
||||
}
|
||||
|
||||
const struct attribute_group pci_ide_attr_group = {
|
||||
.attrs = pci_ide_attrs,
|
||||
.is_visible = pci_ide_attr_visible,
|
||||
};
|
||||
|
||||
/**
|
||||
* pci_ide_set_nr_streams() - sets size of the pool of IDE Stream resources
|
||||
* @hb: host bridge boundary for the stream pool
|
||||
* @nr: number of streams
|
||||
*
|
||||
* Platform PCI init and/or expert test module use only. Limit IDE
|
||||
* Stream establishment by setting the number of stream resources
|
||||
* available at the host bridge. Platform init code must set this before
|
||||
* the first pci_ide_stream_alloc() call if the platform has less than the
|
||||
* default of 256 streams per host-bridge.
|
||||
*
|
||||
* The "PCI_IDE" symbol namespace is required because this is typically
|
||||
* a detail that is settled in early PCI init. I.e. this export is not
|
||||
* for endpoint drivers.
|
||||
*/
|
||||
void pci_ide_set_nr_streams(struct pci_host_bridge *hb, u16 nr)
|
||||
{
|
||||
hb->nr_ide_streams = min(nr, 256);
|
||||
WARN_ON_ONCE(!ida_is_empty(&hb->ide_stream_ida));
|
||||
sysfs_update_group(&hb->dev.kobj, &pci_ide_attr_group);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(pci_ide_set_nr_streams, "PCI_IDE");
|
||||
|
||||
@@ -616,6 +616,7 @@ static inline void pci_doe_sysfs_teardown(struct pci_dev *pdev) { }
|
||||
#ifdef CONFIG_PCI_IDE
|
||||
void pci_ide_init(struct pci_dev *dev);
|
||||
void pci_ide_init_host_bridge(struct pci_host_bridge *hb);
|
||||
extern const struct attribute_group pci_ide_attr_group;
|
||||
#else
|
||||
static inline void pci_ide_init(struct pci_dev *dev) { }
|
||||
static inline void pci_ide_init_host_bridge(struct pci_host_bridge *hb) { }
|
||||
|
||||
@@ -653,6 +653,18 @@ static void pci_release_host_bridge_dev(struct device *dev)
|
||||
kfree(bridge);
|
||||
}
|
||||
|
||||
static const struct attribute_group *pci_host_bridge_groups[] = {
|
||||
#ifdef CONFIG_PCI_IDE
|
||||
&pci_ide_attr_group,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct device_type pci_host_bridge_type = {
|
||||
.groups = pci_host_bridge_groups,
|
||||
.release = pci_release_host_bridge_dev,
|
||||
};
|
||||
|
||||
static void pci_init_host_bridge(struct pci_host_bridge *bridge)
|
||||
{
|
||||
INIT_LIST_HEAD(&bridge->windows);
|
||||
@@ -672,6 +684,7 @@ static void pci_init_host_bridge(struct pci_host_bridge *bridge)
|
||||
bridge->native_dpc = 1;
|
||||
bridge->domain_nr = PCI_DOMAIN_NR_NOT_SET;
|
||||
bridge->native_cxl_error = 1;
|
||||
bridge->dev.type = &pci_host_bridge_type;
|
||||
pci_ide_init_host_bridge(bridge);
|
||||
|
||||
device_initialize(&bridge->dev);
|
||||
@@ -686,7 +699,6 @@ struct pci_host_bridge *pci_alloc_host_bridge(size_t priv)
|
||||
return NULL;
|
||||
|
||||
pci_init_host_bridge(bridge);
|
||||
bridge->dev.release = pci_release_host_bridge_dev;
|
||||
|
||||
return bridge;
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@ struct pci_ide {
|
||||
const char *name;
|
||||
};
|
||||
|
||||
void pci_ide_set_nr_streams(struct pci_host_bridge *hb, u16 nr);
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user