Merge branch 'i2c/for-4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
[cascardo/linux.git] / drivers / i2c / i2c-core.c
index fc2ee82..069a41f 100644 (file)
@@ -257,7 +257,7 @@ acpi_i2c_space_handler(u32 function, acpi_physical_address command,
        struct acpi_connection_info *info = &data->info;
        struct acpi_resource_i2c_serialbus *sb;
        struct i2c_adapter *adapter = data->adapter;
-       struct i2c_client client;
+       struct i2c_client *client;
        struct acpi_resource *ares;
        u32 accessor_type = function >> 16;
        u8 action = function & ACPI_IO_MASK;
@@ -268,6 +268,12 @@ acpi_i2c_space_handler(u32 function, acpi_physical_address command,
        if (ACPI_FAILURE(ret))
                return ret;
 
+       client = kzalloc(sizeof(*client), GFP_KERNEL);
+       if (!client) {
+               ret = AE_NO_MEMORY;
+               goto err;
+       }
+
        if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) {
                ret = AE_BAD_PARAMETER;
                goto err;
@@ -279,75 +285,73 @@ acpi_i2c_space_handler(u32 function, acpi_physical_address command,
                goto err;
        }
 
-       memset(&client, 0, sizeof(client));
-       client.adapter = adapter;
-       client.addr = sb->slave_address;
-       client.flags = 0;
+       client->adapter = adapter;
+       client->addr = sb->slave_address;
 
        if (sb->access_mode == ACPI_I2C_10BIT_MODE)
-               client.flags |= I2C_CLIENT_TEN;
+               client->flags |= I2C_CLIENT_TEN;
 
        switch (accessor_type) {
        case ACPI_GSB_ACCESS_ATTRIB_SEND_RCV:
                if (action == ACPI_READ) {
-                       status = i2c_smbus_read_byte(&client);
+                       status = i2c_smbus_read_byte(client);
                        if (status >= 0) {
                                gsb->bdata = status;
                                status = 0;
                        }
                } else {
-                       status = i2c_smbus_write_byte(&client, gsb->bdata);
+                       status = i2c_smbus_write_byte(client, gsb->bdata);
                }
                break;
 
        case ACPI_GSB_ACCESS_ATTRIB_BYTE:
                if (action == ACPI_READ) {
-                       status = i2c_smbus_read_byte_data(&client, command);
+                       status = i2c_smbus_read_byte_data(client, command);
                        if (status >= 0) {
                                gsb->bdata = status;
                                status = 0;
                        }
                } else {
-                       status = i2c_smbus_write_byte_data(&client, command,
+                       status = i2c_smbus_write_byte_data(client, command,
                                        gsb->bdata);
                }
                break;
 
        case ACPI_GSB_ACCESS_ATTRIB_WORD:
                if (action == ACPI_READ) {
-                       status = i2c_smbus_read_word_data(&client, command);
+                       status = i2c_smbus_read_word_data(client, command);
                        if (status >= 0) {
                                gsb->wdata = status;
                                status = 0;
                        }
                } else {
-                       status = i2c_smbus_write_word_data(&client, command,
+                       status = i2c_smbus_write_word_data(client, command,
                                        gsb->wdata);
                }
                break;
 
        case ACPI_GSB_ACCESS_ATTRIB_BLOCK:
                if (action == ACPI_READ) {
-                       status = i2c_smbus_read_block_data(&client, command,
+                       status = i2c_smbus_read_block_data(client, command,
                                        gsb->data);
                        if (status >= 0) {
                                gsb->len = status;
                                status = 0;
                        }
                } else {
-                       status = i2c_smbus_write_block_data(&client, command,
+                       status = i2c_smbus_write_block_data(client, command,
                                        gsb->len, gsb->data);
                }
                break;
 
        case ACPI_GSB_ACCESS_ATTRIB_MULTIBYTE:
                if (action == ACPI_READ) {
-                       status = acpi_gsb_i2c_read_bytes(&client, command,
+                       status = acpi_gsb_i2c_read_bytes(client, command,
                                        gsb->data, info->access_length);
                        if (status > 0)
                                status = 0;
                } else {
-                       status = acpi_gsb_i2c_write_bytes(&client, command,
+                       status = acpi_gsb_i2c_write_bytes(client, command,
                                        gsb->data, info->access_length);
                }
                break;
@@ -361,6 +365,7 @@ acpi_i2c_space_handler(u32 function, acpi_physical_address command,
        gsb->status = status;
 
  err:
+       kfree(client);
        ACPI_FREE(ares);
        return ret;
 }
@@ -1276,7 +1281,7 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
        }
 
        addr = of_get_property(node, "reg", &len);
-       if (!addr || (len < sizeof(int))) {
+       if (!addr || (len < sizeof(*addr))) {
                dev_err(&adap->dev, "of_i2c: invalid reg on %s\n",
                        node->full_name);
                return ERR_PTR(-EINVAL);
@@ -1677,7 +1682,7 @@ void i2c_del_adapter(struct i2c_adapter *adap)
         * FIXME: This is old code and should ideally be replaced by an
         * alternative which results in decoupling the lifetime of the struct
         * device from the i2c_adapter, like spi or netdev do. Any solution
-        * should be throughly tested with DEBUG_KOBJECT_RELEASE enabled!
+        * should be thoroughly tested with DEBUG_KOBJECT_RELEASE enabled!
         */
        init_completion(&adap->dev_released);
        device_unregister(&adap->dev);
@@ -2918,18 +2923,24 @@ int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb)
 {
        int ret;
 
-       if (!client || !slave_cb)
+       if (!client || !slave_cb) {
+               WARN(1, "insufficent data\n");
                return -EINVAL;
+       }
 
        if (!(client->flags & I2C_CLIENT_TEN)) {
                /* Enforce stricter address checking */
                ret = i2c_check_addr_validity(client->addr);
-               if (ret)
+               if (ret) {
+                       dev_err(&client->dev, "%s: invalid address\n", __func__);
                        return ret;
+               }
        }
 
-       if (!client->adapter->algo->reg_slave)
+       if (!client->adapter->algo->reg_slave) {
+               dev_err(&client->dev, "%s: not supported by adapter\n", __func__);
                return -EOPNOTSUPP;
+       }
 
        client->slave_cb = slave_cb;
 
@@ -2937,8 +2948,10 @@ int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb)
        ret = client->adapter->algo->reg_slave(client);
        i2c_unlock_adapter(client->adapter);
 
-       if (ret)
+       if (ret) {
                client->slave_cb = NULL;
+               dev_err(&client->dev, "%s: adapter returned error %d\n", __func__, ret);
+       }
 
        return ret;
 }
@@ -2948,8 +2961,10 @@ int i2c_slave_unregister(struct i2c_client *client)
 {
        int ret;
 
-       if (!client->adapter->algo->unreg_slave)
+       if (!client->adapter->algo->unreg_slave) {
+               dev_err(&client->dev, "%s: not supported by adapter\n", __func__);
                return -EOPNOTSUPP;
+       }
 
        i2c_lock_adapter(client->adapter);
        ret = client->adapter->algo->unreg_slave(client);
@@ -2957,6 +2972,8 @@ int i2c_slave_unregister(struct i2c_client *client)
 
        if (ret == 0)
                client->slave_cb = NULL;
+       else
+               dev_err(&client->dev, "%s: adapter returned error %d\n", __func__, ret);
 
        return ret;
 }