X-Git-Url: http://git.cascardo.info/?p=cascardo%2Flinux.git;a=blobdiff_plain;f=drivers%2Fi2c%2Fi2c-core.c;h=5ab67219f71e64a95c926e20b4c45cb1edce68bf;hp=05794423e01ff55be3f37a4ce27490541601daef;hb=b2edcdae3d9a29b25f6c161a8711caa74ce49991;hpb=6d54f1446dbe1c595e8af2e750d0e82c6697c936 diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 05794423e01f..5ab67219f71e 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, static int i2c_acpi_get_info(struct acpi_device *adev, struct i2c_board_info *info, + struct i2c_adapter *adapter, acpi_handle *adapter_handle) { struct list_head resource_list; @@ -182,8 +183,24 @@ static int i2c_acpi_get_info(struct acpi_device *adev, if (ret) return ret; + if (adapter) { + /* The adapter must match the one in I2cSerialBus() connector */ + if (ACPI_HANDLE(&adapter->dev) != lookup.adapter_handle) + return -ENODEV; + } else { + struct acpi_device *adapter_adev; + + /* The adapter must be present */ + if (acpi_bus_get_device(lookup.adapter_handle, &adapter_adev)) + return -ENODEV; + if (acpi_bus_get_status(adapter_adev) || + !adapter_adev->status.present) + return -ENODEV; + } + info->fwnode = acpi_fwnode_handle(adev); - *adapter_handle = lookup.adapter_handle; + if (adapter_handle) + *adapter_handle = lookup.adapter_handle; /* Then fill IRQ number if any */ INIT_LIST_HEAD(&resource_list); @@ -225,16 +242,12 @@ static acpi_status i2c_acpi_add_device(acpi_handle handle, u32 level, { struct i2c_adapter *adapter = data; struct acpi_device *adev; - acpi_handle adapter_handle; struct i2c_board_info info; if (acpi_bus_get_device(handle, &adev)) return AE_OK; - if (i2c_acpi_get_info(adev, &info, &adapter_handle)) - return AE_OK; - - if (adapter_handle != ACPI_HANDLE(&adapter->dev)) + if (i2c_acpi_get_info(adev, &info, adapter, NULL)) return AE_OK; i2c_acpi_register_device(adapter, adev, &info); @@ -368,7 +381,7 @@ static int i2c_acpi_notify(struct notifier_block *nb, unsigned long value, switch (value) { case ACPI_RECONFIG_DEVICE_ADD: - if (i2c_acpi_get_info(adev, &info, &adapter_handle)) + if (i2c_acpi_get_info(adev, &info, NULL, &adapter_handle)) break; adapter = i2c_acpi_find_adapter_by_handle(adapter_handle); @@ -930,7 +943,7 @@ static int i2c_device_probe(struct device *dev) status = 0; if (status) - dev_warn(&client->dev, "failed to set up wakeup irq"); + dev_warn(&client->dev, "failed to set up wakeup irq\n"); } dev_dbg(dev, "probe\n"); @@ -1285,8 +1298,9 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) return client; out_err: - dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x " - "(%d)\n", client->name, client->addr, status); + dev_err(&adap->dev, + "Failed to register i2c client %s at 0x%02x (%d)\n", + client->name, client->addr, status); out_err_silent: kfree(client); return NULL; @@ -1412,21 +1426,19 @@ static void i2c_adapter_dev_release(struct device *dev) complete(&adap->dev_released); } -/* - * This function is only needed for mutex_lock_nested, so it is never - * called unless locking correctness checking is enabled. Thus we - * make it inline to avoid a compiler warning. That's what gcc ends up - * doing anyway. - */ -static inline unsigned int i2c_adapter_depth(struct i2c_adapter *adapter) +unsigned int i2c_adapter_depth(struct i2c_adapter *adapter) { unsigned int depth = 0; while ((adapter = i2c_parent_is_i2c_adapter(adapter))) depth++; + WARN_ONCE(depth >= MAX_LOCKDEP_SUBCLASSES, + "adapter depth exceeds lockdep subclass limit\n"); + return depth; } +EXPORT_SYMBOL_GPL(i2c_adapter_depth); /* * Let users instantiate I2C devices through sysfs. This can be used when @@ -1668,7 +1680,7 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap, static void of_i2c_register_devices(struct i2c_adapter *adap) { - struct device_node *node; + struct device_node *bus, *node; /* Only register child devices if the adapter has a node pointer set */ if (!adap->dev.of_node) @@ -1676,11 +1688,17 @@ static void of_i2c_register_devices(struct i2c_adapter *adap) dev_dbg(&adap->dev, "of_i2c: walking child nodes\n"); - for_each_available_child_of_node(adap->dev.of_node, node) { + bus = of_get_child_by_name(adap->dev.of_node, "i2c-bus"); + if (!bus) + bus = of_node_get(adap->dev.of_node); + + for_each_available_child_of_node(bus, node) { if (of_node_test_and_set_flag(node, OF_POPULATED)) continue; of_i2c_register_device(adap, node); } + + of_node_put(bus); } static int of_dev_node_match(struct device *dev, void *data) @@ -1755,8 +1773,8 @@ static int i2c_do_add_adapter(struct i2c_driver *driver, if (driver->attach_adapter) { dev_warn(&adap->dev, "%s: attach_adapter method is deprecated\n", driver->driver.name); - dev_warn(&adap->dev, "Please use another way to instantiate " - "your i2c_client\n"); + dev_warn(&adap->dev, + "Please use another way to instantiate your i2c_client\n"); /* We ignore the return code; if it fails, too bad */ driver->attach_adapter(adap); } @@ -1768,6 +1786,12 @@ static int __process_new_adapter(struct device_driver *d, void *data) return i2c_do_add_adapter(to_i2c_driver(d), data); } +static const struct i2c_lock_operations i2c_adapter_lock_ops = { + .lock_bus = i2c_adapter_lock_bus, + .trylock_bus = i2c_adapter_trylock_bus, + .unlock_bus = i2c_adapter_unlock_bus, +}; + static int i2c_register_adapter(struct i2c_adapter *adap) { int res = -EINVAL; @@ -1787,11 +1811,8 @@ static int i2c_register_adapter(struct i2c_adapter *adap) goto out_list; } - if (!adap->lock_bus) { - adap->lock_bus = i2c_adapter_lock_bus; - adap->trylock_bus = i2c_adapter_trylock_bus; - adap->unlock_bus = i2c_adapter_unlock_bus; - } + if (!adap->lock_ops) + adap->lock_ops = &i2c_adapter_lock_ops; rt_mutex_init(&adap->bus_lock); rt_mutex_init(&adap->mux_lock); @@ -2528,9 +2549,10 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) if (adap->algo->master_xfer) { #ifdef DEBUG for (ret = 0; ret < num; ret++) { - dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, " - "len=%d%s\n", ret, (msgs[ret].flags & I2C_M_RD) - ? 'R' : 'W', msgs[ret].addr, msgs[ret].len, + dev_dbg(&adap->dev, + "master_xfer[%d] %c, addr=0x%02x, len=%d%s\n", + ret, (msgs[ret].flags & I2C_M_RD) ? 'R' : 'W', + msgs[ret].addr, msgs[ret].len, (msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : ""); } #endif @@ -2696,9 +2718,9 @@ static int i2c_detect_address(struct i2c_client *temp_client, /* Consistency check */ if (info.type[0] == '\0') { - dev_err(&adapter->dev, "%s detection function provided " - "no name for 0x%x\n", driver->driver.name, - addr); + dev_err(&adapter->dev, + "%s detection function provided no name for 0x%x\n", + driver->driver.name, addr); } else { struct i2c_client *client; @@ -2736,9 +2758,8 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver) /* Warn that the adapter lost class based instantiation */ if (adapter->class == I2C_CLASS_DEPRECATED) { dev_dbg(&adapter->dev, - "This adapter dropped support for I2C classes and " - "won't auto-detect %s devices anymore. If you need it, check " - "'Documentation/i2c/instantiating-devices' for alternatives.\n", + "This adapter dropped support for I2C classes and won't auto-detect %s devices anymore. " + "If you need it, check 'Documentation/i2c/instantiating-devices' for alternatives.\n", driver->driver.name); return 0; } @@ -2754,8 +2775,9 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver) temp_client->adapter = adapter; for (i = 0; address_list[i] != I2C_CLIENT_END; i += 1) { - dev_dbg(&adapter->dev, "found normal entry for adapter %d, " - "addr 0x%02x\n", adap_id, address_list[i]); + dev_dbg(&adapter->dev, + "found normal entry for adapter %d, addr 0x%02x\n", + adap_id, address_list[i]); temp_client->addr = address_list[i]; err = i2c_detect_address(temp_client, driver); if (unlikely(err)) @@ -2787,15 +2809,16 @@ i2c_new_probed_device(struct i2c_adapter *adap, for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) { /* Check address validity */ if (i2c_check_7bit_addr_validity_strict(addr_list[i]) < 0) { - dev_warn(&adap->dev, "Invalid 7-bit address " - "0x%02x\n", addr_list[i]); + dev_warn(&adap->dev, "Invalid 7-bit address 0x%02x\n", + addr_list[i]); continue; } /* Check address availability (7 bit, no need to encode flags) */ if (i2c_check_addr_busy(adap, addr_list[i])) { - dev_dbg(&adap->dev, "Address 0x%02x already in " - "use, not probing\n", addr_list[i]); + dev_dbg(&adap->dev, + "Address 0x%02x already in use, not probing\n", + addr_list[i]); continue; }