diff options
Diffstat (limited to 'drivers/i2c/i2c-core.c')
-rw-r--r-- | drivers/i2c/i2c-core.c | 72 |
1 files changed, 55 insertions, 17 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 9cb277d6aa4..01233f0f777 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -183,15 +183,21 @@ int i2c_add_adapter(struct i2c_adapter *adap) sprintf(adap->dev.bus_id, "i2c-%d", adap->nr); adap->dev.driver = &i2c_adapter_driver; adap->dev.release = &i2c_adapter_dev_release; - device_register(&adap->dev); - device_create_file(&adap->dev, &dev_attr_name); + res = device_register(&adap->dev); + if (res) + goto out_list; + res = device_create_file(&adap->dev, &dev_attr_name); + if (res) + goto out_unregister; /* Add this adapter to the i2c_adapter class */ memset(&adap->class_dev, 0x00, sizeof(struct class_device)); adap->class_dev.dev = &adap->dev; adap->class_dev.class = &i2c_adapter_class; strlcpy(adap->class_dev.class_id, adap->dev.bus_id, BUS_ID_SIZE); - class_device_register(&adap->class_dev); + res = class_device_register(&adap->class_dev); + if (res) + goto out_remove_name; dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name); @@ -206,6 +212,17 @@ int i2c_add_adapter(struct i2c_adapter *adap) out_unlock: mutex_unlock(&core_lists); return res; + +out_remove_name: + device_remove_file(&adap->dev, &dev_attr_name); +out_unregister: + init_completion(&adap->dev_released); /* Needed? */ + device_unregister(&adap->dev); + wait_for_completion(&adap->dev_released); +out_list: + list_del(&adap->list); + idr_remove(&i2c_adapter_idr, adap->nr); + goto out_unlock; } @@ -394,14 +411,14 @@ int i2c_check_addr(struct i2c_adapter *adapter, int addr) int i2c_attach_client(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; + int res = 0; mutex_lock(&adapter->clist_lock); if (__i2c_check_addr(client->adapter, client->addr)) { - mutex_unlock(&adapter->clist_lock); - return -EBUSY; + res = -EBUSY; + goto out_unlock; } list_add_tail(&client->list,&adapter->clients); - mutex_unlock(&adapter->clist_lock); if (adapter->client_register) { if (adapter->client_register(client)) { @@ -422,10 +439,26 @@ int i2c_attach_client(struct i2c_client *client) "%d-%04x", i2c_adapter_id(adapter), client->addr); dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n", client->name, client->dev.bus_id); - device_register(&client->dev); - device_create_file(&client->dev, &dev_attr_client_name); - - return 0; + res = device_register(&client->dev); + if (res) + goto out_list; + res = device_create_file(&client->dev, &dev_attr_client_name); + if (res) + goto out_unregister; + +out_unlock: + mutex_unlock(&adapter->clist_lock); + return res; + +out_unregister: + init_completion(&client->released); /* Needed? */ + device_unregister(&client->dev); + wait_for_completion(&client->released); +out_list: + list_del(&client->list); + dev_err(&adapter->dev, "Failed to attach i2c client %s at 0x%02x " + "(%d)\n", client->name, client->addr, res); + goto out_unlock; } @@ -674,11 +707,16 @@ static int i2c_probe_address(struct i2c_adapter *adapter, int addr, int kind, /* Finally call the custom detection function */ err = found_proc(adapter, addr, kind); - /* -ENODEV can be returned if there is a chip at the given address but it isn't supported by this chip driver. We catch it here as this isn't an error. */ - return (err == -ENODEV) ? 0 : err; + if (err == -ENODEV) + err = 0; + + if (err) + dev_warn(&adapter->dev, "Client creation failed at 0x%x (%d)\n", + addr, err); + return err; } int i2c_probe(struct i2c_adapter *adapter, @@ -868,7 +906,7 @@ s32 i2c_smbus_read_byte(struct i2c_client *client) I2C_SMBUS_READ,0,I2C_SMBUS_BYTE, &data)) return -1; else - return 0x0FF & data.byte; + return data.byte; } s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value) @@ -884,7 +922,7 @@ s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command) I2C_SMBUS_READ,command, I2C_SMBUS_BYTE_DATA,&data)) return -1; else - return 0x0FF & data.byte; + return data.byte; } s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value) @@ -903,7 +941,7 @@ s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command) I2C_SMBUS_READ,command, I2C_SMBUS_WORD_DATA, &data)) return -1; else - return 0x0FFFF & data.word; + return data.word; } s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value) @@ -1006,7 +1044,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, else { msg[0].len=3; msgbuf0[1] = data->word & 0xff; - msgbuf0[2] = (data->word >> 8) & 0xff; + msgbuf0[2] = data->word >> 8; } break; case I2C_SMBUS_PROC_CALL: @@ -1015,7 +1053,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, msg[0].len = 3; msg[1].len = 2; msgbuf0[1] = data->word & 0xff; - msgbuf0[2] = (data->word >> 8) & 0xff; + msgbuf0[2] = data->word >> 8; break; case I2C_SMBUS_BLOCK_DATA: if (read_write == I2C_SMBUS_READ) { |