X-Git-Url: https://git.karo-electronics.de/?a=blobdiff_plain;f=drivers%2Fi2c%2Fi2c-core.c;fp=drivers%2Fi2c%2Fi2c-core.c;h=f0bd5bcdf56329294b5cab85a0fe41ce06600dd6;hb=f2ec334db8d14ae3ec2e4bf8d974f75b8f772e26;hp=bea4c5021d26cb5b4c92e9b58cabeda2b882023c;hpb=81e20d4d8d0317ecf1c7d193a52ab26cf74e1737;p=mv-sheeva.git diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index bea4c5021d2..f0bd5bcdf56 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -196,88 +196,60 @@ static int i2c_device_pm_suspend(struct device *dev) { const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - if (pm) { - if (pm_runtime_suspended(dev)) - return 0; - else - return pm->suspend ? pm->suspend(dev) : 0; - } - - return i2c_legacy_suspend(dev, PMSG_SUSPEND); + if (pm) + return pm_generic_suspend(dev); + else + return i2c_legacy_suspend(dev, PMSG_SUSPEND); } static int i2c_device_pm_resume(struct device *dev) { const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - int ret; if (pm) - ret = pm->resume ? pm->resume(dev) : 0; + return pm_generic_resume(dev); else - ret = i2c_legacy_resume(dev); - - return ret; + return i2c_legacy_resume(dev); } static int i2c_device_pm_freeze(struct device *dev) { const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - if (pm) { - if (pm_runtime_suspended(dev)) - return 0; - else - return pm->freeze ? pm->freeze(dev) : 0; - } - - return i2c_legacy_suspend(dev, PMSG_FREEZE); + if (pm) + return pm_generic_freeze(dev); + else + return i2c_legacy_suspend(dev, PMSG_FREEZE); } static int i2c_device_pm_thaw(struct device *dev) { const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - if (pm) { - if (pm_runtime_suspended(dev)) - return 0; - else - return pm->thaw ? pm->thaw(dev) : 0; - } - - return i2c_legacy_resume(dev); + if (pm) + return pm_generic_thaw(dev); + else + return i2c_legacy_resume(dev); } static int i2c_device_pm_poweroff(struct device *dev) { const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - if (pm) { - if (pm_runtime_suspended(dev)) - return 0; - else - return pm->poweroff ? pm->poweroff(dev) : 0; - } - - return i2c_legacy_suspend(dev, PMSG_HIBERNATE); + if (pm) + return pm_generic_poweroff(dev); + else + return i2c_legacy_suspend(dev, PMSG_HIBERNATE); } static int i2c_device_pm_restore(struct device *dev) { const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - int ret; if (pm) - ret = pm->restore ? pm->restore(dev) : 0; + return pm_generic_restore(dev); else - ret = i2c_legacy_resume(dev); - - if (!ret) { - pm_runtime_disable(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - } - - return ret; + return i2c_legacy_resume(dev); } #else /* !CONFIG_PM_SLEEP */ #define i2c_device_pm_suspend NULL @@ -425,14 +397,14 @@ static int __i2c_check_addr_busy(struct device *dev, void *addrp) /* walk up mux tree */ static int i2c_check_mux_parents(struct i2c_adapter *adapter, int addr) { + struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); int result; result = device_for_each_child(&adapter->dev, &addr, __i2c_check_addr_busy); - if (!result && i2c_parent_is_i2c_adapter(adapter)) - result = i2c_check_mux_parents( - to_i2c_adapter(adapter->dev.parent), addr); + if (!result && parent) + result = i2c_check_mux_parents(parent, addr); return result; } @@ -453,11 +425,11 @@ static int i2c_check_mux_children(struct device *dev, void *addrp) static int i2c_check_addr_busy(struct i2c_adapter *adapter, int addr) { + struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); int result = 0; - if (i2c_parent_is_i2c_adapter(adapter)) - result = i2c_check_mux_parents( - to_i2c_adapter(adapter->dev.parent), addr); + if (parent) + result = i2c_check_mux_parents(parent, addr); if (!result) result = device_for_each_child(&adapter->dev, &addr, @@ -472,8 +444,10 @@ static int i2c_check_addr_busy(struct i2c_adapter *adapter, int addr) */ void i2c_lock_adapter(struct i2c_adapter *adapter) { - if (i2c_parent_is_i2c_adapter(adapter)) - i2c_lock_adapter(to_i2c_adapter(adapter->dev.parent)); + struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); + + if (parent) + i2c_lock_adapter(parent); else rt_mutex_lock(&adapter->bus_lock); } @@ -485,8 +459,10 @@ EXPORT_SYMBOL_GPL(i2c_lock_adapter); */ static int i2c_trylock_adapter(struct i2c_adapter *adapter) { - if (i2c_parent_is_i2c_adapter(adapter)) - return i2c_trylock_adapter(to_i2c_adapter(adapter->dev.parent)); + struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); + + if (parent) + return i2c_trylock_adapter(parent); else return rt_mutex_trylock(&adapter->bus_lock); } @@ -497,8 +473,10 @@ static int i2c_trylock_adapter(struct i2c_adapter *adapter) */ void i2c_unlock_adapter(struct i2c_adapter *adapter) { - if (i2c_parent_is_i2c_adapter(adapter)) - i2c_unlock_adapter(to_i2c_adapter(adapter->dev.parent)); + struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); + + if (parent) + i2c_unlock_adapter(parent); else rt_mutex_unlock(&adapter->bus_lock); } @@ -677,8 +655,6 @@ i2c_sysfs_new_device(struct device *dev, struct device_attribute *attr, char *blank, end; int res; - dev_warn(dev, "The new_device interface is still experimental " - "and may change in a near future\n"); memset(&info, 0, sizeof(struct i2c_board_info)); blank = strchr(buf, ' '); @@ -844,6 +820,18 @@ static int i2c_register_adapter(struct i2c_adapter *adap) goto out_list; } + /* Sanity checks */ + if (unlikely(adap->name[0] == '\0')) { + pr_err("i2c-core: Attempt to register an adapter with " + "no name!\n"); + return -EINVAL; + } + if (unlikely(!adap->algo)) { + pr_err("i2c-core: Attempt to register adapter '%s' with " + "no algo!\n", adap->name); + return -EINVAL; + } + rt_mutex_init(&adap->bus_lock); mutex_init(&adap->userspace_clients_lock); INIT_LIST_HEAD(&adap->userspace_clients); @@ -1003,6 +991,14 @@ static int i2c_do_del_adapter(struct i2c_driver *driver, } static int __unregister_client(struct device *dev, void *dummy) +{ + struct i2c_client *client = i2c_verify_client(dev); + if (client && strcmp(client->name, "dummy")) + i2c_unregister_device(client); + return 0; +} + +static int __unregister_dummy(struct device *dev, void *dummy) { struct i2c_client *client = i2c_verify_client(dev); if (client) @@ -1059,8 +1055,12 @@ int i2c_del_adapter(struct i2c_adapter *adap) mutex_unlock(&adap->userspace_clients_lock); /* Detach any active clients. This can't fail, thus we do not - checking the returned value. */ + * check the returned value. This is a two-pass process, because + * we can't remove the dummy devices during the first pass: they + * could have been instantiated by real devices wishing to clean + * them up properly, so we give them a chance to do that first. */ res = device_for_each_child(&adap->dev, NULL, __unregister_client); + res = device_for_each_child(&adap->dev, NULL, __unregister_dummy); #ifdef CONFIG_I2C_COMPAT class_compat_remove_link(i2c_adapter_compat_class, &adap->dev, @@ -1124,6 +1124,14 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) if (res) return res; + /* Drivers should switch to dev_pm_ops instead. */ + if (driver->suspend) + pr_warn("i2c-core: driver [%s] using legacy suspend method\n", + driver->driver.name); + if (driver->resume) + pr_warn("i2c-core: driver [%s] using legacy resume method\n", + driver->driver.name); + pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); INIT_LIST_HEAD(&driver->clients); @@ -1346,7 +1354,7 @@ EXPORT_SYMBOL(i2c_transfer); * * Returns negative errno, or else the number of bytes written. */ -int i2c_master_send(struct i2c_client *client, const char *buf, int count) +int i2c_master_send(const struct i2c_client *client, const char *buf, int count) { int ret; struct i2c_adapter *adap = client->adapter; @@ -1373,7 +1381,7 @@ EXPORT_SYMBOL(i2c_master_send); * * Returns negative errno, or else the number of bytes read. */ -int i2c_master_recv(struct i2c_client *client, char *buf, int count) +int i2c_master_recv(const struct i2c_client *client, char *buf, int count) { struct i2c_adapter *adap = client->adapter; struct i2c_msg msg; @@ -1504,26 +1512,25 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver) if (!driver->detect || !address_list) return 0; + /* Stop here if the classes do not match */ + if (!(adapter->class & driver->class)) + return 0; + /* Set up a temporary client to help detect callback */ temp_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); if (!temp_client) return -ENOMEM; temp_client->adapter = adapter; - /* Stop here if the classes do not match */ - if (!(adapter->class & driver->class)) - goto exit_free; - 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]); temp_client->addr = address_list[i]; err = i2c_detect_address(temp_client, driver); - if (err) - goto exit_free; + if (unlikely(err)) + break; } - exit_free: kfree(temp_client); return err; } @@ -1664,7 +1671,7 @@ static int i2c_smbus_check_pec(u8 cpec, struct i2c_msg *msg) * This executes the SMBus "receive byte" protocol, returning negative errno * else the byte received from the device. */ -s32 i2c_smbus_read_byte(struct i2c_client *client) +s32 i2c_smbus_read_byte(const struct i2c_client *client) { union i2c_smbus_data data; int status; @@ -1684,7 +1691,7 @@ EXPORT_SYMBOL(i2c_smbus_read_byte); * This executes the SMBus "send byte" protocol, returning negative errno * else zero on success. */ -s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value) +s32 i2c_smbus_write_byte(const struct i2c_client *client, u8 value) { return i2c_smbus_xfer(client->adapter, client->addr, client->flags, I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL); @@ -1699,7 +1706,7 @@ EXPORT_SYMBOL(i2c_smbus_write_byte); * This executes the SMBus "read byte" protocol, returning negative errno * else a data byte received from the device. */ -s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command) +s32 i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command) { union i2c_smbus_data data; int status; @@ -1720,7 +1727,8 @@ EXPORT_SYMBOL(i2c_smbus_read_byte_data); * This executes the SMBus "write byte" protocol, returning negative errno * else zero on success. */ -s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value) +s32 i2c_smbus_write_byte_data(const struct i2c_client *client, u8 command, + u8 value) { union i2c_smbus_data data; data.byte = value; @@ -1738,7 +1746,7 @@ EXPORT_SYMBOL(i2c_smbus_write_byte_data); * This executes the SMBus "read word" protocol, returning negative errno * else a 16-bit unsigned "word" received from the device. */ -s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command) +s32 i2c_smbus_read_word_data(const struct i2c_client *client, u8 command) { union i2c_smbus_data data; int status; @@ -1759,7 +1767,8 @@ EXPORT_SYMBOL(i2c_smbus_read_word_data); * This executes the SMBus "write word" protocol, returning negative errno * else zero on success. */ -s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value) +s32 i2c_smbus_write_word_data(const struct i2c_client *client, u8 command, + u16 value) { union i2c_smbus_data data; data.word = value; @@ -1778,7 +1787,8 @@ EXPORT_SYMBOL(i2c_smbus_write_word_data); * This executes the SMBus "process call" protocol, returning negative errno * else a 16-bit unsigned "word" received from the device. */ -s32 i2c_smbus_process_call(struct i2c_client *client, u8 command, u16 value) +s32 i2c_smbus_process_call(const struct i2c_client *client, u8 command, + u16 value) { union i2c_smbus_data data; int status; @@ -1806,7 +1816,7 @@ EXPORT_SYMBOL(i2c_smbus_process_call); * support this; its emulation through I2C messaging relies on a specific * mechanism (I2C_M_RECV_LEN) which may not be implemented. */ -s32 i2c_smbus_read_block_data(struct i2c_client *client, u8 command, +s32 i2c_smbus_read_block_data(const struct i2c_client *client, u8 command, u8 *values) { union i2c_smbus_data data; @@ -1833,7 +1843,7 @@ EXPORT_SYMBOL(i2c_smbus_read_block_data); * This executes the SMBus "block write" protocol, returning negative errno * else zero on success. */ -s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command, +s32 i2c_smbus_write_block_data(const struct i2c_client *client, u8 command, u8 length, const u8 *values) { union i2c_smbus_data data; @@ -1849,7 +1859,7 @@ s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command, EXPORT_SYMBOL(i2c_smbus_write_block_data); /* Returns the number of read bytes */ -s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, +s32 i2c_smbus_read_i2c_block_data(const struct i2c_client *client, u8 command, u8 length, u8 *values) { union i2c_smbus_data data; @@ -1869,7 +1879,7 @@ s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, } EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data); -s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command, +s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client, u8 command, u8 length, const u8 *values) { union i2c_smbus_data data;