diff options
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r-- | drivers/acpi/scan.c | 73 |
1 files changed, 67 insertions, 6 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index c0f57ff15024..e00365ccb897 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -86,6 +86,9 @@ int acpi_scan_add_handler_with_hotplug(struct acpi_scan_handler *handler, | |||
86 | * Creates hid/cid(s) string needed for modalias and uevent | 86 | * Creates hid/cid(s) string needed for modalias and uevent |
87 | * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get: | 87 | * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get: |
88 | * char *modalias: "acpi:IBM0001:ACPI0001" | 88 | * char *modalias: "acpi:IBM0001:ACPI0001" |
89 | * Return: 0: no _HID and no _CID | ||
90 | * -EINVAL: output error | ||
91 | * -ENOMEM: output is truncated | ||
89 | */ | 92 | */ |
90 | static int create_modalias(struct acpi_device *acpi_dev, char *modalias, | 93 | static int create_modalias(struct acpi_device *acpi_dev, char *modalias, |
91 | int size) | 94 | int size) |
@@ -102,8 +105,10 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, | |||
102 | 105 | ||
103 | list_for_each_entry(id, &acpi_dev->pnp.ids, list) { | 106 | list_for_each_entry(id, &acpi_dev->pnp.ids, list) { |
104 | count = snprintf(&modalias[len], size, "%s:", id->id); | 107 | count = snprintf(&modalias[len], size, "%s:", id->id); |
105 | if (count < 0 || count >= size) | 108 | if (count < 0) |
106 | return -EINVAL; | 109 | return EINVAL; |
110 | if (count >= size) | ||
111 | return -ENOMEM; | ||
107 | len += count; | 112 | len += count; |
108 | size -= count; | 113 | size -= count; |
109 | } | 114 | } |
@@ -112,15 +117,71 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, | |||
112 | return len; | 117 | return len; |
113 | } | 118 | } |
114 | 119 | ||
120 | /* | ||
121 | * Creates uevent modalias field for ACPI enumerated devices. | ||
122 | * Because the other buses does not support ACPI HIDs & CIDs. | ||
123 | * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get: | ||
124 | * "acpi:IBM0001:ACPI0001" | ||
125 | */ | ||
126 | int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) | ||
127 | { | ||
128 | struct acpi_device *acpi_dev; | ||
129 | int len; | ||
130 | |||
131 | acpi_dev = ACPI_COMPANION(dev); | ||
132 | if (!acpi_dev) | ||
133 | return -ENODEV; | ||
134 | |||
135 | /* Fall back to bus specific way of modalias exporting */ | ||
136 | if (list_empty(&acpi_dev->pnp.ids)) | ||
137 | return -ENODEV; | ||
138 | |||
139 | if (add_uevent_var(env, "MODALIAS=")) | ||
140 | return -ENOMEM; | ||
141 | len = create_modalias(acpi_dev, &env->buf[env->buflen - 1], | ||
142 | sizeof(env->buf) - env->buflen); | ||
143 | if (len <= 0) | ||
144 | return len; | ||
145 | env->buflen += len; | ||
146 | return 0; | ||
147 | } | ||
148 | EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias); | ||
149 | |||
150 | /* | ||
151 | * Creates modalias sysfs attribute for ACPI enumerated devices. | ||
152 | * Because the other buses does not support ACPI HIDs & CIDs. | ||
153 | * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get: | ||
154 | * "acpi:IBM0001:ACPI0001" | ||
155 | */ | ||
156 | int acpi_device_modalias(struct device *dev, char *buf, int size) | ||
157 | { | ||
158 | struct acpi_device *acpi_dev; | ||
159 | int len; | ||
160 | |||
161 | acpi_dev = ACPI_COMPANION(dev); | ||
162 | if (!acpi_dev) | ||
163 | return -ENODEV; | ||
164 | |||
165 | /* Fall back to bus specific way of modalias exporting */ | ||
166 | if (list_empty(&acpi_dev->pnp.ids)) | ||
167 | return -ENODEV; | ||
168 | |||
169 | len = create_modalias(acpi_dev, buf, size -1); | ||
170 | if (len <= 0) | ||
171 | return len; | ||
172 | buf[len++] = '\n'; | ||
173 | return len; | ||
174 | } | ||
175 | EXPORT_SYMBOL_GPL(acpi_device_modalias); | ||
176 | |||
115 | static ssize_t | 177 | static ssize_t |
116 | acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) { | 178 | acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) { |
117 | struct acpi_device *acpi_dev = to_acpi_device(dev); | 179 | struct acpi_device *acpi_dev = to_acpi_device(dev); |
118 | int len; | 180 | int len; |
119 | 181 | ||
120 | /* Device has no HID and no CID or string is >1024 */ | ||
121 | len = create_modalias(acpi_dev, buf, 1024); | 182 | len = create_modalias(acpi_dev, buf, 1024); |
122 | if (len <= 0) | 183 | if (len <= 0) |
123 | return 0; | 184 | return len; |
124 | buf[len++] = '\n'; | 185 | buf[len++] = '\n'; |
125 | return len; | 186 | return len; |
126 | } | 187 | } |
@@ -839,8 +900,8 @@ static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
839 | return -ENOMEM; | 900 | return -ENOMEM; |
840 | len = create_modalias(acpi_dev, &env->buf[env->buflen - 1], | 901 | len = create_modalias(acpi_dev, &env->buf[env->buflen - 1], |
841 | sizeof(env->buf) - env->buflen); | 902 | sizeof(env->buf) - env->buflen); |
842 | if (len >= (sizeof(env->buf) - env->buflen)) | 903 | if (len <= 0) |
843 | return -ENOMEM; | 904 | return len; |
844 | env->buflen += len; | 905 | env->buflen += len; |
845 | return 0; | 906 | return 0; |
846 | } | 907 | } |