0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 #include <linux/dmi.h>
0026 #include <linux/sysfs.h>
0027 #include <linux/pci.h>
0028 #include <linux/pci_ids.h>
0029 #include <linux/module.h>
0030 #include <linux/device.h>
0031 #include <linux/nls.h>
0032 #include <linux/acpi.h>
0033 #include <linux/pci-acpi.h>
0034 #include "pci.h"
0035
0036 static bool device_has_acpi_name(struct device *dev)
0037 {
0038 #ifdef CONFIG_ACPI
0039 acpi_handle handle = ACPI_HANDLE(dev);
0040
0041 if (!handle)
0042 return false;
0043
0044 return acpi_check_dsm(handle, &pci_acpi_dsm_guid, 0x2,
0045 1 << DSM_PCI_DEVICE_NAME);
0046 #else
0047 return false;
0048 #endif
0049 }
0050
0051 #ifdef CONFIG_DMI
0052 enum smbios_attr_enum {
0053 SMBIOS_ATTR_NONE = 0,
0054 SMBIOS_ATTR_LABEL_SHOW,
0055 SMBIOS_ATTR_INSTANCE_SHOW,
0056 };
0057
0058 static size_t find_smbios_instance_string(struct pci_dev *pdev, char *buf,
0059 enum smbios_attr_enum attribute)
0060 {
0061 const struct dmi_device *dmi;
0062 struct dmi_dev_onboard *donboard;
0063 int domain_nr = pci_domain_nr(pdev->bus);
0064 int bus = pdev->bus->number;
0065 int devfn = pdev->devfn;
0066
0067 dmi = NULL;
0068 while ((dmi = dmi_find_device(DMI_DEV_TYPE_DEV_ONBOARD,
0069 NULL, dmi)) != NULL) {
0070 donboard = dmi->device_data;
0071 if (donboard && donboard->segment == domain_nr &&
0072 donboard->bus == bus &&
0073 donboard->devfn == devfn) {
0074 if (buf) {
0075 if (attribute == SMBIOS_ATTR_INSTANCE_SHOW)
0076 return sysfs_emit(buf, "%d\n",
0077 donboard->instance);
0078 else if (attribute == SMBIOS_ATTR_LABEL_SHOW)
0079 return sysfs_emit(buf, "%s\n",
0080 dmi->name);
0081 }
0082 return strlen(dmi->name);
0083 }
0084 }
0085 return 0;
0086 }
0087
0088 static ssize_t smbios_label_show(struct device *dev,
0089 struct device_attribute *attr, char *buf)
0090 {
0091 struct pci_dev *pdev = to_pci_dev(dev);
0092
0093 return find_smbios_instance_string(pdev, buf,
0094 SMBIOS_ATTR_LABEL_SHOW);
0095 }
0096 static struct device_attribute dev_attr_smbios_label = __ATTR(label, 0444,
0097 smbios_label_show, NULL);
0098
0099 static ssize_t index_show(struct device *dev, struct device_attribute *attr,
0100 char *buf)
0101 {
0102 struct pci_dev *pdev = to_pci_dev(dev);
0103
0104 return find_smbios_instance_string(pdev, buf,
0105 SMBIOS_ATTR_INSTANCE_SHOW);
0106 }
0107 static DEVICE_ATTR_RO(index);
0108
0109 static struct attribute *smbios_attrs[] = {
0110 &dev_attr_smbios_label.attr,
0111 &dev_attr_index.attr,
0112 NULL,
0113 };
0114
0115 static umode_t smbios_attr_is_visible(struct kobject *kobj, struct attribute *a,
0116 int n)
0117 {
0118 struct device *dev = kobj_to_dev(kobj);
0119 struct pci_dev *pdev = to_pci_dev(dev);
0120
0121 if (device_has_acpi_name(dev))
0122 return 0;
0123
0124 if (!find_smbios_instance_string(pdev, NULL, SMBIOS_ATTR_NONE))
0125 return 0;
0126
0127 return a->mode;
0128 }
0129
0130 const struct attribute_group pci_dev_smbios_attr_group = {
0131 .attrs = smbios_attrs,
0132 .is_visible = smbios_attr_is_visible,
0133 };
0134 #endif
0135
0136 #ifdef CONFIG_ACPI
0137 enum acpi_attr_enum {
0138 ACPI_ATTR_LABEL_SHOW,
0139 ACPI_ATTR_INDEX_SHOW,
0140 };
0141
0142 static int dsm_label_utf16s_to_utf8s(union acpi_object *obj, char *buf)
0143 {
0144 int len;
0145
0146 len = utf16s_to_utf8s((const wchar_t *)obj->buffer.pointer,
0147 obj->buffer.length,
0148 UTF16_LITTLE_ENDIAN,
0149 buf, PAGE_SIZE - 1);
0150 buf[len++] = '\n';
0151
0152 return len;
0153 }
0154
0155 static int dsm_get_label(struct device *dev, char *buf,
0156 enum acpi_attr_enum attr)
0157 {
0158 acpi_handle handle = ACPI_HANDLE(dev);
0159 union acpi_object *obj, *tmp;
0160 int len = 0;
0161
0162 if (!handle)
0163 return -1;
0164
0165 obj = acpi_evaluate_dsm(handle, &pci_acpi_dsm_guid, 0x2,
0166 DSM_PCI_DEVICE_NAME, NULL);
0167 if (!obj)
0168 return -1;
0169
0170 tmp = obj->package.elements;
0171 if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 2 &&
0172 tmp[0].type == ACPI_TYPE_INTEGER &&
0173 (tmp[1].type == ACPI_TYPE_STRING ||
0174 tmp[1].type == ACPI_TYPE_BUFFER)) {
0175
0176
0177
0178
0179
0180 if (attr == ACPI_ATTR_INDEX_SHOW) {
0181 len = sysfs_emit(buf, "%llu\n", tmp->integer.value);
0182 } else if (attr == ACPI_ATTR_LABEL_SHOW) {
0183 if (tmp[1].type == ACPI_TYPE_STRING)
0184 len = sysfs_emit(buf, "%s\n",
0185 tmp[1].string.pointer);
0186 else if (tmp[1].type == ACPI_TYPE_BUFFER)
0187 len = dsm_label_utf16s_to_utf8s(tmp + 1, buf);
0188 }
0189 }
0190
0191 ACPI_FREE(obj);
0192
0193 return len > 0 ? len : -1;
0194 }
0195
0196 static ssize_t label_show(struct device *dev, struct device_attribute *attr,
0197 char *buf)
0198 {
0199 return dsm_get_label(dev, buf, ACPI_ATTR_LABEL_SHOW);
0200 }
0201 static DEVICE_ATTR_RO(label);
0202
0203 static ssize_t acpi_index_show(struct device *dev,
0204 struct device_attribute *attr, char *buf)
0205 {
0206 return dsm_get_label(dev, buf, ACPI_ATTR_INDEX_SHOW);
0207 }
0208 static DEVICE_ATTR_RO(acpi_index);
0209
0210 static struct attribute *acpi_attrs[] = {
0211 &dev_attr_label.attr,
0212 &dev_attr_acpi_index.attr,
0213 NULL,
0214 };
0215
0216 static umode_t acpi_attr_is_visible(struct kobject *kobj, struct attribute *a,
0217 int n)
0218 {
0219 struct device *dev = kobj_to_dev(kobj);
0220
0221 if (!device_has_acpi_name(dev))
0222 return 0;
0223
0224 return a->mode;
0225 }
0226
0227 const struct attribute_group pci_dev_acpi_attr_group = {
0228 .attrs = acpi_attrs,
0229 .is_visible = acpi_attr_is_visible,
0230 };
0231 #endif