diff mbox series

[v2,2/7] PCI/sysfs: Add pci_dev_resource_attr() macro

Message ID 20210910202623.2293708-3-kw@linux.com (mailing list archive)
State New, archived
Delegated to: Bjorn Helgaas
Headers show
Series PCI: Convert dynamic PCI resources sysfs objects into static | expand

Commit Message

Krzysztof Wilczyński Sept. 10, 2021, 8:26 p.m. UTC
The pci_dev_resource_attr() macro will be used to declare and define
each of the PCI resource sysfs objects statically while also reducing
unnecessary code repetition.

This macro aims to also replace functions pci_create_resource_files()
and pci_create_attr() that are currently involved in the PCI resource
sysfs objects dynamic creation and set up once the.

Internally this macro relies on the pci_dev_resource_attr_is_visible()
helper which should correctly handle creating either normal and/or
write-combine attributes as required.

Two other macros were also added to help reduce code duplication, the
pci_dev_bin_attribute() and pci_dev_resource_group().

The pci_dev_bin_attribute() macro abstracts the declaration and
definition of a binary attribute with all the required fields from
struct bin_attribute set as needed for a given PCI resource sysfs
attribute.

The pci_dev_resource_group() macro will be used to reduce unnecessary
code repetition following the use of the pci_dev_resource_attr() macro
when adding each of the many newly created resource groups to the list
of other PCI sysfs objects stored in the pci_dev_groups array.

The conversion to static sysfs objects will result in two sysfs
attributes to be created for each PCI resource (the underlying BAR)
independently, one for a normal resource, and one for a resource
that is write-combine capable, should this feature be supported.

Each such resource will be then placed in a dedicated attribute
resource group so that access to it can be controlled using a
dedicated .is_bin_visible() callback where depending on what the
underlying resource (a given BAR) supports will be either made
visible or hidden.

Therefore, for six standard PCI BARs, a total of twelve attribute
groups will be thus created per device.

Signed-off-by: Krzysztof Wilczyński <kw@linux.com>
---
 drivers/pci/pci-sysfs.c | 61 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)
diff mbox series

Patch

diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 4272d1aba205..ccdd1e34aeee 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -1261,6 +1261,67 @@  static umode_t pci_dev_resource_attr_is_visible(struct kobject *kobj,
 	return a->attr.mode;
 };
 
+#define pci_dev_bin_attribute(_name, _mmap, _bar)		\
+struct bin_attribute pci_dev_##_name##_attr = {			\
+	.attr = { .name = __stringify(_name), .mode = 0600 },	\
+	.read = pci_read_resource_io,				\
+	.write = pci_write_resource_io,				\
+	.mmap = _mmap,						\
+	.private = (void *)(unsigned long)_bar,			\
+	.f_mapping = iomem_get_mapping,				\
+}
+
+#define pci_dev_resource_attr(_bar)					\
+static pci_dev_bin_attribute(resource##_bar,				\
+			     pci_mmap_resource_uc,			\
+			     _bar);					\
+									\
+static struct bin_attribute *pci_dev_resource##_bar##_attrs[] = {	\
+	&pci_dev_resource##_bar##_attr,					\
+	NULL,								\
+};									\
+									\
+static umode_t								\
+pci_dev_resource##_bar##_attr_is_visible(struct kobject *kobj,		\
+					 struct bin_attribute *a,	\
+					 int n)				\
+{									\
+	return pci_dev_resource_attr_is_visible(kobj, a, _bar, false);	\
+};									\
+									\
+static const struct							\
+attribute_group pci_dev_resource##_bar##_attr_group = {			\
+	.bin_attrs = pci_dev_resource##_bar##_attrs,			\
+	.is_bin_visible = pci_dev_resource##_bar##_attr_is_visible,	\
+};									\
+									\
+static pci_dev_bin_attribute(resource##_bar##_wc,			\
+			     pci_mmap_resource_wc,			\
+			     _bar);					\
+									\
+static struct bin_attribute *pci_dev_resource##_bar##_wc_attrs[] = {	\
+	&pci_dev_resource##_bar##_wc_attr,				\
+	NULL,								\
+};									\
+									\
+static umode_t								\
+pci_dev_resource##_bar##_wc_attr_is_visible(struct kobject *kobj,	\
+					    struct bin_attribute *a,	\
+					    int n)			\
+{									\
+	return pci_dev_resource_attr_is_visible(kobj, a, _bar, true);	\
+};									\
+									\
+static const struct							\
+attribute_group pci_dev_resource##_bar##_wc_attr_group = {		\
+	.bin_attrs = pci_dev_resource##_bar##_wc_attrs,			\
+	.is_bin_visible = pci_dev_resource##_bar##_wc_attr_is_visible,	\
+}
+
+#define pci_dev_resource_group(_bar)		\
+	&pci_dev_resource##_bar##_attr_group,	\
+	&pci_dev_resource##_bar##_wc_attr_group
+
 #else /* !(defined(HAVE_PCI_MMAP) || defined(ARCH_GENERIC_PCI_MMAP_RESOURCE)) */
 int __weak pci_create_resource_files(struct pci_dev *dev) { return 0; }
 void __weak pci_remove_resource_files(struct pci_dev *dev) { return; }