Commit | Line | Data |
---|---|---|
911e1c9b N |
1 | /* |
2 | * Purpose: Export the firmware instance and label associated with | |
3 | * a pci device to sysfs | |
4 | * Copyright (C) 2010 Dell Inc. | |
5 | * by Narendra K <Narendra_K@dell.com>, | |
6 | * Jordan Hargrave <Jordan_Hargrave@dell.com> | |
7 | * | |
8 | * SMBIOS defines type 41 for onboard pci devices. This code retrieves | |
9 | * the instance number and string from the type 41 record and exports | |
10 | * it to sysfs. | |
11 | * | |
12 | * Please see http://linux.dell.com/wiki/index.php/Oss/libnetdevname for more | |
13 | * information. | |
14 | */ | |
15 | ||
16 | #include <linux/dmi.h> | |
17 | #include <linux/sysfs.h> | |
18 | #include <linux/pci.h> | |
19 | #include <linux/pci_ids.h> | |
20 | #include <linux/module.h> | |
21 | #include <linux/device.h> | |
22 | #include "pci.h" | |
23 | ||
24 | enum smbios_attr_enum { | |
25 | SMBIOS_ATTR_NONE = 0, | |
26 | SMBIOS_ATTR_LABEL_SHOW, | |
27 | SMBIOS_ATTR_INSTANCE_SHOW, | |
28 | }; | |
29 | ||
30 | static mode_t | |
31 | find_smbios_instance_string(struct pci_dev *pdev, char *buf, | |
32 | enum smbios_attr_enum attribute) | |
33 | { | |
34 | const struct dmi_device *dmi; | |
35 | struct dmi_dev_onboard *donboard; | |
36 | int bus; | |
37 | int devfn; | |
38 | ||
39 | bus = pdev->bus->number; | |
40 | devfn = pdev->devfn; | |
41 | ||
42 | dmi = NULL; | |
43 | while ((dmi = dmi_find_device(DMI_DEV_TYPE_DEV_ONBOARD, | |
44 | NULL, dmi)) != NULL) { | |
45 | donboard = dmi->device_data; | |
46 | if (donboard && donboard->bus == bus && | |
47 | donboard->devfn == devfn) { | |
48 | if (buf) { | |
49 | if (attribute == SMBIOS_ATTR_INSTANCE_SHOW) | |
50 | return scnprintf(buf, PAGE_SIZE, | |
51 | "%d\n", | |
52 | donboard->instance); | |
53 | else if (attribute == SMBIOS_ATTR_LABEL_SHOW) | |
54 | return scnprintf(buf, PAGE_SIZE, | |
55 | "%s\n", | |
56 | dmi->name); | |
57 | } | |
58 | return strlen(dmi->name); | |
59 | } | |
60 | } | |
61 | return 0; | |
62 | } | |
63 | ||
64 | static mode_t | |
65 | smbios_instance_string_exist(struct kobject *kobj, struct attribute *attr, | |
66 | int n) | |
67 | { | |
68 | struct device *dev; | |
69 | struct pci_dev *pdev; | |
70 | ||
71 | dev = container_of(kobj, struct device, kobj); | |
72 | pdev = to_pci_dev(dev); | |
73 | ||
74 | return find_smbios_instance_string(pdev, NULL, SMBIOS_ATTR_NONE) ? | |
75 | S_IRUGO : 0; | |
76 | } | |
77 | ||
78 | static ssize_t | |
79 | smbioslabel_show(struct device *dev, struct device_attribute *attr, char *buf) | |
80 | { | |
81 | struct pci_dev *pdev; | |
82 | pdev = to_pci_dev(dev); | |
83 | ||
84 | return find_smbios_instance_string(pdev, buf, | |
85 | SMBIOS_ATTR_LABEL_SHOW); | |
86 | } | |
87 | ||
88 | static ssize_t | |
89 | smbiosinstance_show(struct device *dev, | |
90 | struct device_attribute *attr, char *buf) | |
91 | { | |
92 | struct pci_dev *pdev; | |
93 | pdev = to_pci_dev(dev); | |
94 | ||
95 | return find_smbios_instance_string(pdev, buf, | |
96 | SMBIOS_ATTR_INSTANCE_SHOW); | |
97 | } | |
98 | ||
99 | static struct device_attribute smbios_attr_label = { | |
100 | .attr = {.name = "label", .mode = 0444, .owner = THIS_MODULE}, | |
101 | .show = smbioslabel_show, | |
102 | }; | |
103 | ||
104 | static struct device_attribute smbios_attr_instance = { | |
105 | .attr = {.name = "index", .mode = 0444, .owner = THIS_MODULE}, | |
106 | .show = smbiosinstance_show, | |
107 | }; | |
108 | ||
109 | static struct attribute *smbios_attributes[] = { | |
110 | &smbios_attr_label.attr, | |
111 | &smbios_attr_instance.attr, | |
112 | NULL, | |
113 | }; | |
114 | ||
115 | static struct attribute_group smbios_attr_group = { | |
116 | .attrs = smbios_attributes, | |
117 | .is_visible = smbios_instance_string_exist, | |
118 | }; | |
119 | ||
120 | static int | |
121 | pci_create_smbiosname_file(struct pci_dev *pdev) | |
122 | { | |
123 | if (!sysfs_create_group(&pdev->dev.kobj, &smbios_attr_group)) | |
124 | return 0; | |
125 | return -ENODEV; | |
126 | } | |
127 | ||
128 | static void | |
129 | pci_remove_smbiosname_file(struct pci_dev *pdev) | |
130 | { | |
131 | sysfs_remove_group(&pdev->dev.kobj, &smbios_attr_group); | |
132 | } | |
133 | ||
134 | void pci_create_firmware_label_files(struct pci_dev *pdev) | |
135 | { | |
136 | if (!pci_create_smbiosname_file(pdev)) | |
137 | ; | |
138 | } | |
139 | ||
140 | void pci_remove_firmware_label_files(struct pci_dev *pdev) | |
141 | { | |
142 | pci_remove_smbiosname_file(pdev); | |
143 | } |