aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/i2c-core.c
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2016-09-20 09:59:25 -0400
committerWolfram Sang <wsa@the-dreams.de>2016-09-22 13:45:51 -0400
commit318ce2782a2732cadb422c6a76ebeb973ecd63cb (patch)
tree0df7430acb572a6622749bd6a042697e1756adcb /drivers/i2c/i2c-core.c
parent38caa925ee67d2359f45a4a9cd1afa2e23a9eece (diff)
i2c / ACPI: Do not touch an I2C device if it belongs to another adapter
When enumerating I2C devices connected to an I2C adapter we scan the whole namespace (as it is possible to have devices anywhere in that namespace, not just below the I2C adapter device) and add each found device to the I2C bus in question. Now after commit 525e6fabeae2 ("i2c / ACPI: add support for ACPI reconfigure notifications") checking of the adapter handle to the one found in the I2cSerialBus() resource was moved to happen after resources of the I2C device has been parsed. This means that if the I2cSerialBus() resource points to an adapter that does not exists in the system we still parse those resources. This is problematic in particular because acpi_dev_resource_interrupt() tries to configure GSI if the device also has an Interrupt() resource. Failing to do that results errrors like this to be printed on the console: [ 10.409490] ERROR: Unable to locate IOAPIC for GSI 37 To fix this we pass the I2C adapter to i2c_acpi_get_info() and make sure the handle matches the one in the I2cSerialBus() resource before doing anything else to the device. Reported-by: Nicolai Stange <nicstange@gmail.com> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Reviewed-by: Nicolai Stange <nicstange@gmail.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c/i2c-core.c')
-rw-r--r--drivers/i2c/i2c-core.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 65242666901e..cdbbd9bdb7b4 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -168,6 +168,7 @@ static int i2c_acpi_do_lookup(struct acpi_device *adev,
168 168
169static int i2c_acpi_get_info(struct acpi_device *adev, 169static int i2c_acpi_get_info(struct acpi_device *adev,
170 struct i2c_board_info *info, 170 struct i2c_board_info *info,
171 struct i2c_adapter *adapter,
171 acpi_handle *adapter_handle) 172 acpi_handle *adapter_handle)
172{ 173{
173 struct list_head resource_list; 174 struct list_head resource_list;
@@ -182,8 +183,24 @@ static int i2c_acpi_get_info(struct acpi_device *adev,
182 if (ret) 183 if (ret)
183 return ret; 184 return ret;
184 185
186 if (adapter) {
187 /* The adapter must match the one in I2cSerialBus() connector */
188 if (ACPI_HANDLE(&adapter->dev) != lookup.adapter_handle)
189 return -ENODEV;
190 } else {
191 struct acpi_device *adapter_adev;
192
193 /* The adapter must be present */
194 if (acpi_bus_get_device(lookup.adapter_handle, &adapter_adev))
195 return -ENODEV;
196 if (acpi_bus_get_status(adapter_adev) ||
197 !adapter_adev->status.present)
198 return -ENODEV;
199 }
200
185 info->fwnode = acpi_fwnode_handle(adev); 201 info->fwnode = acpi_fwnode_handle(adev);
186 *adapter_handle = lookup.adapter_handle; 202 if (adapter_handle)
203 *adapter_handle = lookup.adapter_handle;
187 204
188 /* Then fill IRQ number if any */ 205 /* Then fill IRQ number if any */
189 INIT_LIST_HEAD(&resource_list); 206 INIT_LIST_HEAD(&resource_list);
@@ -225,16 +242,12 @@ static acpi_status i2c_acpi_add_device(acpi_handle handle, u32 level,
225{ 242{
226 struct i2c_adapter *adapter = data; 243 struct i2c_adapter *adapter = data;
227 struct acpi_device *adev; 244 struct acpi_device *adev;
228 acpi_handle adapter_handle;
229 struct i2c_board_info info; 245 struct i2c_board_info info;
230 246
231 if (acpi_bus_get_device(handle, &adev)) 247 if (acpi_bus_get_device(handle, &adev))
232 return AE_OK; 248 return AE_OK;
233 249
234 if (i2c_acpi_get_info(adev, &info, &adapter_handle)) 250 if (i2c_acpi_get_info(adev, &info, adapter, NULL))
235 return AE_OK;
236
237 if (adapter_handle != ACPI_HANDLE(&adapter->dev))
238 return AE_OK; 251 return AE_OK;
239 252
240 i2c_acpi_register_device(adapter, adev, &info); 253 i2c_acpi_register_device(adapter, adev, &info);
@@ -368,7 +381,7 @@ static int i2c_acpi_notify(struct notifier_block *nb, unsigned long value,
368 381
369 switch (value) { 382 switch (value) {
370 case ACPI_RECONFIG_DEVICE_ADD: 383 case ACPI_RECONFIG_DEVICE_ADD:
371 if (i2c_acpi_get_info(adev, &info, &adapter_handle)) 384 if (i2c_acpi_get_info(adev, &info, NULL, &adapter_handle))
372 break; 385 break;
373 386
374 adapter = i2c_acpi_find_adapter_by_handle(adapter_handle); 387 adapter = i2c_acpi_find_adapter_by_handle(adapter_handle);