aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2012-11-10 17:16:02 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2012-11-14 18:28:02 -0500
commitb4b6cae2f36d92b31788f10816709d5290a1119a (patch)
treea8833a3a7989ad27210eae9f8bbf3b7276afe82a
parent91e5687805885f9fceb60b95e950a3d3bdcf4764 (diff)
ACPI / platform: use ACPI device name instead of _HID._UID
Using _UID makes the ACPI platform bus code depend on BIOS to get it right. If it doesn't we fail to create the platform device as the name should be unique. The ACPI core already makes a unique name when it first creates the ACPI device so we can use that same name as the platform device name instead of trusting that the BIOS sets the _UIDs correctly. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/acpi/acpi_platform.c62
1 files changed, 22 insertions, 40 deletions
diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c
index a5a23462287d..dbb31d61e310 100644
--- a/drivers/acpi/acpi_platform.c
+++ b/drivers/acpi/acpi_platform.c
@@ -120,25 +120,6 @@ static acpi_status acpi_platform_add_resources(struct acpi_resource *res,
120 return AE_OK; 120 return AE_OK;
121} 121}
122 122
123static acpi_status acpi_platform_get_device_uid(struct acpi_device *adev,
124 int *uid)
125{
126 struct acpi_device_info *info;
127 acpi_status status;
128
129 status = acpi_get_object_info(adev->handle, &info);
130 if (ACPI_FAILURE(status))
131 return status;
132
133 status = AE_NOT_EXIST;
134 if ((info->valid & ACPI_VALID_UID) &&
135 !kstrtoint(info->unique_id.string, 0, uid))
136 status = AE_OK;
137
138 kfree(info);
139 return status;
140}
141
142/** 123/**
143 * acpi_create_platform_device - Create platform device for ACPI device node 124 * acpi_create_platform_device - Create platform device for ACPI device node
144 * @adev: ACPI device node to create a platform device for. 125 * @adev: ACPI device node to create a platform device for.
@@ -156,19 +137,12 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
156 struct device *parent = NULL; 137 struct device *parent = NULL;
157 struct resource_info ri; 138 struct resource_info ri;
158 acpi_status status; 139 acpi_status status;
159 int devid;
160 140
161 /* If the ACPI node already has a physical device attached, skip it. */ 141 /* If the ACPI node already has a physical device attached, skip it. */
162 if (adev->physical_node_count) 142 if (adev->physical_node_count)
163 return NULL; 143 return NULL;
164 144
165 /* Use the UID of the device as the new platform device id if found. */
166 status = acpi_platform_get_device_uid(adev, &devid);
167 if (ACPI_FAILURE(status))
168 devid = -1;
169
170 memset(&ri, 0, sizeof(ri)); 145 memset(&ri, 0, sizeof(ri));
171
172 /* First, count the resources. */ 146 /* First, count the resources. */
173 status = acpi_walk_resources(adev->handle, METHOD_NAME__CRS, 147 status = acpi_walk_resources(adev->handle, METHOD_NAME__CRS,
174 acpi_platform_count_resources, &ri); 148 acpi_platform_count_resources, &ri);
@@ -214,8 +188,8 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
214 } 188 }
215 mutex_unlock(&acpi_parent->physical_node_lock); 189 mutex_unlock(&acpi_parent->physical_node_lock);
216 } 190 }
217 pdev = platform_device_register_resndata(parent, acpi_device_hid(adev), 191 pdev = platform_device_register_resndata(parent, dev_name(&adev->dev),
218 devid, ri.res, ri.n, NULL, 0); 192 -1, ri.res, ri.n, NULL, 0);
219 if (IS_ERR(pdev)) { 193 if (IS_ERR(pdev)) {
220 dev_err(&adev->dev, "platform device creation failed: %ld\n", 194 dev_err(&adev->dev, "platform device creation failed: %ld\n",
221 PTR_ERR(pdev)); 195 PTR_ERR(pdev));
@@ -245,17 +219,7 @@ static acpi_status acpi_platform_match(acpi_handle handle, u32 depth,
245 if (adev->physical_node_count) 219 if (adev->physical_node_count)
246 return AE_OK; 220 return AE_OK;
247 221
248 if (!strcmp(pdev->name, acpi_device_hid(adev))) { 222 if (!strcmp(dev_name(&pdev->dev), dev_name(&adev->dev))) {
249 int devid;
250
251 /* Check that both name and UID match if it exists */
252 status = acpi_platform_get_device_uid(adev, &devid);
253 if (ACPI_FAILURE(status))
254 devid = -1;
255
256 if (pdev->id != devid)
257 return AE_OK;
258
259 *(acpi_handle *)return_value = handle; 223 *(acpi_handle *)return_value = handle;
260 return AE_CTRL_TERMINATE; 224 return AE_CTRL_TERMINATE;
261 } 225 }
@@ -266,10 +230,28 @@ static acpi_status acpi_platform_match(acpi_handle handle, u32 depth,
266static int acpi_platform_find_device(struct device *dev, acpi_handle *handle) 230static int acpi_platform_find_device(struct device *dev, acpi_handle *handle)
267{ 231{
268 struct platform_device *pdev = to_platform_device(dev); 232 struct platform_device *pdev = to_platform_device(dev);
233 char *name, *tmp, *hid;
234
235 /*
236 * The platform device is named using the ACPI device name
237 * _HID:INSTANCE so we strip the INSTANCE out in order to find the
238 * correct device using its _HID.
239 */
240 name = kstrdup(dev_name(dev), GFP_KERNEL);
241 if (!name)
242 return -ENOMEM;
243
244 tmp = name;
245 hid = strsep(&tmp, ":");
246 if (!hid) {
247 kfree(name);
248 return -ENODEV;
249 }
269 250
270 *handle = NULL; 251 *handle = NULL;
271 acpi_get_devices(pdev->name, acpi_platform_match, pdev, handle); 252 acpi_get_devices(hid, acpi_platform_match, pdev, handle);
272 253
254 kfree(name);
273 return *handle ? 0 : -ENODEV; 255 return *handle ? 0 : -ENODEV;
274} 256}
275 257