summaryrefslogtreecommitdiff
path: root/drivers/base
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/core.c25
-rw-r--r--drivers/base/devtmpfs.c11
-rw-r--r--drivers/base/power/power.h1
-rw-r--r--drivers/base/power/wakeirq.c13
-rw-r--r--drivers/base/regmap/regmap-debugfs.c20
-rw-r--r--drivers/base/regmap/regmap-i2c.c4
-rw-r--r--drivers/base/regmap/regmap-mmio.c24
-rw-r--r--drivers/base/regmap/regmap.c306
8 files changed, 200 insertions, 204 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 5847364f25d9..b610816eb887 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -196,8 +196,10 @@ struct device_link *device_link_add(struct device *consumer,
}
list_for_each_entry(link, &supplier->links.consumers, s_node)
- if (link->consumer == consumer)
+ if (link->consumer == consumer) {
+ kref_get(&link->kref);
goto out;
+ }
link = kzalloc(sizeof(*link), GFP_KERNEL);
if (!link)
@@ -222,6 +224,7 @@ struct device_link *device_link_add(struct device *consumer,
link->consumer = consumer;
INIT_LIST_HEAD(&link->c_node);
link->flags = flags;
+ kref_init(&link->kref);
/* Determine the initial link state. */
if (flags & DL_FLAG_STATELESS) {
@@ -292,8 +295,10 @@ static void __device_link_free_srcu(struct rcu_head *rhead)
device_link_free(container_of(rhead, struct device_link, rcu_head));
}
-static void __device_link_del(struct device_link *link)
+static void __device_link_del(struct kref *kref)
{
+ struct device_link *link = container_of(kref, struct device_link, kref);
+
dev_info(link->consumer, "Dropping the link to %s\n",
dev_name(link->supplier));
@@ -305,8 +310,10 @@ static void __device_link_del(struct device_link *link)
call_srcu(&device_links_srcu, &link->rcu_head, __device_link_free_srcu);
}
#else /* !CONFIG_SRCU */
-static void __device_link_del(struct device_link *link)
+static void __device_link_del(struct kref *kref)
{
+ struct device_link *link = container_of(kref, struct device_link, kref);
+
dev_info(link->consumer, "Dropping the link to %s\n",
dev_name(link->supplier));
@@ -324,13 +331,15 @@ static void __device_link_del(struct device_link *link)
* @link: Device link to delete.
*
* The caller must ensure proper synchronization of this function with runtime
- * PM.
+ * PM. If the link was added multiple times, it needs to be deleted as often.
+ * Care is required for hotplugged devices: Their links are purged on removal
+ * and calling device_link_del() is then no longer allowed.
*/
void device_link_del(struct device_link *link)
{
device_links_write_lock();
device_pm_lock();
- __device_link_del(link);
+ kref_put(&link->kref, __device_link_del);
device_pm_unlock();
device_links_write_unlock();
}
@@ -444,7 +453,7 @@ static void __device_links_no_driver(struct device *dev)
continue;
if (link->flags & DL_FLAG_AUTOREMOVE)
- __device_link_del(link);
+ kref_put(&link->kref, __device_link_del);
else if (link->status != DL_STATE_SUPPLIER_UNBIND)
WRITE_ONCE(link->status, DL_STATE_AVAILABLE);
}
@@ -597,13 +606,13 @@ static void device_links_purge(struct device *dev)
list_for_each_entry_safe_reverse(link, ln, &dev->links.suppliers, c_node) {
WARN_ON(link->status == DL_STATE_ACTIVE);
- __device_link_del(link);
+ __device_link_del(&link->kref);
}
list_for_each_entry_safe_reverse(link, ln, &dev->links.consumers, s_node) {
WARN_ON(link->status != DL_STATE_DORMANT &&
link->status != DL_STATE_NONE);
- __device_link_del(link);
+ __device_link_del(&link->kref);
}
device_links_write_unlock();
diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c
index 50025d7959cb..f7768077e817 100644
--- a/drivers/base/devtmpfs.c
+++ b/drivers/base/devtmpfs.c
@@ -356,7 +356,8 @@ int devtmpfs_mount(const char *mntdir)
if (!thread)
return 0;
- err = sys_mount("devtmpfs", (char *)mntdir, "devtmpfs", MS_SILENT, NULL);
+ err = ksys_mount("devtmpfs", (char *)mntdir, "devtmpfs", MS_SILENT,
+ NULL);
if (err)
printk(KERN_INFO "devtmpfs: error mounting %i\n", err);
else
@@ -379,14 +380,14 @@ static int devtmpfsd(void *p)
{
char options[] = "mode=0755";
int *err = p;
- *err = sys_unshare(CLONE_NEWNS);
+ *err = ksys_unshare(CLONE_NEWNS);
if (*err)
goto out;
- *err = sys_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, options);
+ *err = ksys_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, options);
if (*err)
goto out;
- sys_chdir("/.."); /* will traverse into overmounted root */
- sys_chroot(".");
+ ksys_chdir("/.."); /* will traverse into overmounted root */
+ ksys_chroot(".");
complete(&setup_done);
while (1) {
spin_lock(&req_lock);
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index 21244c53e377..86e67e70b509 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -31,6 +31,7 @@ struct wake_irq {
struct device *dev;
unsigned int status;
int irq;
+ const char *name;
};
extern void dev_pm_arm_wake_irq(struct wake_irq *wirq);
diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c
index 6637fc319269..b8fa5c0f2d13 100644
--- a/drivers/base/power/wakeirq.c
+++ b/drivers/base/power/wakeirq.c
@@ -112,6 +112,7 @@ void dev_pm_clear_wake_irq(struct device *dev)
free_irq(wirq->irq, wirq);
wirq->status &= ~WAKE_IRQ_DEDICATED_MASK;
}
+ kfree(wirq->name);
kfree(wirq);
}
EXPORT_SYMBOL_GPL(dev_pm_clear_wake_irq);
@@ -184,6 +185,12 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
if (!wirq)
return -ENOMEM;
+ wirq->name = kasprintf(GFP_KERNEL, "%s:wakeup", dev_name(dev));
+ if (!wirq->name) {
+ err = -ENOMEM;
+ goto err_free;
+ }
+
wirq->dev = dev;
wirq->irq = irq;
irq_set_status_flags(irq, IRQ_NOAUTOEN);
@@ -196,9 +203,9 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
* so we use a threaded irq.
*/
err = request_threaded_irq(irq, NULL, handle_threaded_wake_irq,
- IRQF_ONESHOT, dev_name(dev), wirq);
+ IRQF_ONESHOT, wirq->name, wirq);
if (err)
- goto err_free;
+ goto err_free_name;
err = dev_pm_attach_wake_irq(dev, irq, wirq);
if (err)
@@ -210,6 +217,8 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
err_free_irq:
free_irq(irq, wirq);
+err_free_name:
+ kfree(wirq->name);
err_free:
kfree(wirq);
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
index f3266334063e..87b562e49a43 100644
--- a/drivers/base/regmap/regmap-debugfs.c
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -25,6 +25,7 @@ struct regmap_debugfs_node {
struct list_head link;
};
+static unsigned int dummy_index;
static struct dentry *regmap_debugfs_root;
static LIST_HEAD(regmap_debugfs_early_list);
static DEFINE_MUTEX(regmap_debugfs_early_lock);
@@ -40,6 +41,7 @@ static ssize_t regmap_name_read_file(struct file *file,
loff_t *ppos)
{
struct regmap *map = file->private_data;
+ const char *name = "nodev";
int ret;
char *buf;
@@ -47,7 +49,10 @@ static ssize_t regmap_name_read_file(struct file *file,
if (!buf)
return -ENOMEM;
- ret = snprintf(buf, PAGE_SIZE, "%s\n", map->dev->driver->name);
+ if (map->dev && map->dev->driver)
+ name = map->dev->driver->name;
+
+ ret = snprintf(buf, PAGE_SIZE, "%s\n", name);
if (ret < 0) {
kfree(buf);
return ret;
@@ -569,9 +574,20 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
name = devname;
}
+ if (!strcmp(name, "dummy")) {
+ map->debugfs_name = kasprintf(GFP_KERNEL, "dummy%d",
+ dummy_index);
+ name = map->debugfs_name;
+ dummy_index++;
+ }
+
map->debugfs = debugfs_create_dir(name, regmap_debugfs_root);
if (!map->debugfs) {
- dev_warn(map->dev, "Failed to create debugfs directory\n");
+ dev_warn(map->dev,
+ "Failed to create %s debugfs directory\n", name);
+
+ kfree(map->debugfs_name);
+ map->debugfs_name = NULL;
return;
}
diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c
index 4735318f4268..056acde5e7d3 100644
--- a/drivers/base/regmap/regmap-i2c.c
+++ b/drivers/base/regmap/regmap-i2c.c
@@ -217,8 +217,6 @@ static int regmap_i2c_smbus_i2c_write(void *context, const void *data,
if (count < 1)
return -EINVAL;
- if (count >= I2C_SMBUS_BLOCK_MAX)
- return -E2BIG;
--count;
return i2c_smbus_write_i2c_block_data(i2c, ((u8 *)data)[0], count,
@@ -235,8 +233,6 @@ static int regmap_i2c_smbus_i2c_read(void *context, const void *reg,
if (reg_size != 1 || val_size < 1)
return -EINVAL;
- if (val_size >= I2C_SMBUS_BLOCK_MAX)
- return -E2BIG;
ret = i2c_smbus_read_i2c_block_data(i2c, ((u8 *)reg)[0], val_size, val);
if (ret == val_size)
diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c
index 5189fd6182f6..5cadfd3394d8 100644
--- a/drivers/base/regmap/regmap-mmio.c
+++ b/drivers/base/regmap/regmap-mmio.c
@@ -28,6 +28,8 @@
struct regmap_mmio_context {
void __iomem *regs;
unsigned val_bytes;
+
+ bool attached_clk;
struct clk *clk;
void (*reg_write)(struct regmap_mmio_context *ctx,
@@ -363,4 +365,26 @@ struct regmap *__devm_regmap_init_mmio_clk(struct device *dev,
}
EXPORT_SYMBOL_GPL(__devm_regmap_init_mmio_clk);
+int regmap_mmio_attach_clk(struct regmap *map, struct clk *clk)
+{
+ struct regmap_mmio_context *ctx = map->bus_context;
+
+ ctx->clk = clk;
+ ctx->attached_clk = true;
+
+ return clk_prepare(ctx->clk);
+}
+EXPORT_SYMBOL_GPL(regmap_mmio_attach_clk);
+
+void regmap_mmio_detach_clk(struct regmap *map)
+{
+ struct regmap_mmio_context *ctx = map->bus_context;
+
+ clk_unprepare(ctx->clk);
+
+ ctx->attached_clk = false;
+ ctx->clk = NULL;
+}
+EXPORT_SYMBOL_GPL(regmap_mmio_detach_clk);
+
MODULE_LICENSE("GPL v2");
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index ee302ccdfbc8..3bc84885eb91 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -99,7 +99,7 @@ bool regmap_cached(struct regmap *map, unsigned int reg)
int ret;
unsigned int val;
- if (map->cache == REGCACHE_NONE)
+ if (map->cache_type == REGCACHE_NONE)
return false;
if (!map->cache_ops)
@@ -174,7 +174,7 @@ static bool regmap_volatile_range(struct regmap *map, unsigned int reg,
unsigned int i;
for (i = 0; i < num; i++)
- if (!regmap_volatile(map, reg + i))
+ if (!regmap_volatile(map, reg + regmap_get_offset(map, i)))
return false;
return true;
@@ -1116,6 +1116,8 @@ skip_format_initialization:
ret = regmap_attach_dev(dev, map, config);
if (ret != 0)
goto err_regcache;
+ } else {
+ regmap_debugfs_init(map, config->name);
}
return map;
@@ -1438,8 +1440,8 @@ static void regmap_set_work_buf_flag_mask(struct regmap *map, int max_bytes,
buf[i] |= (mask >> (8 * i)) & 0xff;
}
-int _regmap_raw_write(struct regmap *map, unsigned int reg,
- const void *val, size_t val_len)
+static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,
+ const void *val, size_t val_len)
{
struct regmap_range_node *range;
unsigned long flags;
@@ -1490,8 +1492,9 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
while (val_num > win_residue) {
dev_dbg(map->dev, "Writing window %d/%zu\n",
win_residue, val_len / map->format.val_bytes);
- ret = _regmap_raw_write(map, reg, val, win_residue *
- map->format.val_bytes);
+ ret = _regmap_raw_write_impl(map, reg, val,
+ win_residue *
+ map->format.val_bytes);
if (ret != 0)
return ret;
@@ -1707,11 +1710,11 @@ static int _regmap_bus_raw_write(void *context, unsigned int reg,
map->format.format_val(map->work_buf + map->format.reg_bytes
+ map->format.pad_bytes, val, 0);
- return _regmap_raw_write(map, reg,
- map->work_buf +
- map->format.reg_bytes +
- map->format.pad_bytes,
- map->format.val_bytes);
+ return _regmap_raw_write_impl(map, reg,
+ map->work_buf +
+ map->format.reg_bytes +
+ map->format.pad_bytes,
+ map->format.val_bytes);
}
static inline void *_regmap_map_get_context(struct regmap *map)
@@ -1806,6 +1809,44 @@ int regmap_write_async(struct regmap *map, unsigned int reg, unsigned int val)
}
EXPORT_SYMBOL_GPL(regmap_write_async);
+int _regmap_raw_write(struct regmap *map, unsigned int reg,
+ const void *val, size_t val_len)
+{
+ size_t val_bytes = map->format.val_bytes;
+ size_t val_count = val_len / val_bytes;
+ size_t chunk_count, chunk_bytes;
+ size_t chunk_regs = val_count;
+ int ret, i;
+
+ if (!val_count)
+ return -EINVAL;
+
+ if (map->use_single_write)
+ chunk_regs = 1;
+ else if (map->max_raw_write && val_len > map->max_raw_write)
+ chunk_regs = map->max_raw_write / val_bytes;
+
+ chunk_count = val_count / chunk_regs;
+ chunk_bytes = chunk_regs * val_bytes;
+
+ /* Write as many bytes as possible with chunk_size */
+ for (i = 0; i < chunk_count; i++) {
+ ret = _regmap_raw_write_impl(map, reg, val, chunk_bytes);
+ if (ret)
+ return ret;
+
+ reg += regmap_get_offset(map, chunk_regs);
+ val += chunk_bytes;
+ val_len -= chunk_bytes;
+ }
+
+ /* Write remaining bytes */
+ if (val_len)
+ ret = _regmap_raw_write_impl(map, reg, val, val_len);
+
+ return ret;
+}
+
/**
* regmap_raw_write() - Write raw values to one or more registers
*
@@ -1831,8 +1872,6 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
return -EINVAL;
if (val_len % map->format.val_bytes)
return -EINVAL;
- if (map->max_raw_write && map->max_raw_write > val_len)
- return -E2BIG;
map->lock(map->lock_arg);
@@ -1923,23 +1962,15 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
{
int ret = 0, i;
size_t val_bytes = map->format.val_bytes;
- size_t total_size = val_bytes * val_count;
if (!IS_ALIGNED(reg, map->reg_stride))
return -EINVAL;
/*
- * Some devices don't support bulk write, for
- * them we have a series of single write operations in the first two if
- * blocks.
- *
- * The first if block is used for memory mapped io. It does not allow
- * val_bytes of 3 for example.
- * The second one is for busses that do not provide raw I/O.
- * The third one is used for busses which do not have these limitations
- * and can write arbitrary value lengths.
+ * Some devices don't support bulk write, for them we have a series of
+ * single write operations.
*/
- if (!map->bus) {
+ if (!map->bus || !map->format.parse_inplace) {
map->lock(map->lock_arg);
for (i = 0; i < val_count; i++) {
unsigned int ival;
@@ -1972,81 +2003,17 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
}
out:
map->unlock(map->lock_arg);
- } else if (map->bus && !map->format.parse_inplace) {
- const u8 *u8 = val;
- const u16 *u16 = val;
- const u32 *u32 = val;
- unsigned int ival;
-
- for (i = 0; i < val_count; i++) {
- switch (map->format.val_bytes) {
- case 4:
- ival = u32[i];
- break;
- case 2:
- ival = u16[i];
- break;
- case 1:
- ival = u8[i];
- break;
- default:
- return -EINVAL;
- }
-
- ret = regmap_write(map, reg + (i * map->reg_stride),
- ival);
- if (ret)
- return ret;
- }
- } else if (map->use_single_write ||
- (map->max_raw_write && map->max_raw_write < total_size)) {
- int chunk_stride = map->reg_stride;
- size_t chunk_size = val_bytes;
- size_t chunk_count = val_count;
-
- if (!map->use_single_write) {
- chunk_size = map->max_raw_write;
- if (chunk_size % val_bytes)
- chunk_size -= chunk_size % val_bytes;
- chunk_count = total_size / chunk_size;
- chunk_stride *= chunk_size / val_bytes;
- }
-
- map->lock(map->lock_arg);
- /* Write as many bytes as possible with chunk_size */
- for (i = 0; i < chunk_count; i++) {
- ret = _regmap_raw_write(map,
- reg + (i * chunk_stride),
- val + (i * chunk_size),
- chunk_size);
- if (ret)
- break;
- }
-
- /* Write remaining bytes */
- if (!ret && chunk_size * i < total_size) {
- ret = _regmap_raw_write(map, reg + (i * chunk_stride),
- val + (i * chunk_size),
- total_size - i * chunk_size);
- }
- map->unlock(map->lock_arg);
} else {
void *wval;
- if (!val_count)
- return -EINVAL;
-
wval = kmemdup(val, val_count * val_bytes, map->alloc_flags);
- if (!wval) {
- dev_err(map->dev, "Error in memory allocation\n");
+ if (!wval)
return -ENOMEM;
- }
+
for (i = 0; i < val_count * val_bytes; i += val_bytes)
map->format.parse_inplace(wval + i);
- map->lock(map->lock_arg);
- ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count);
- map->unlock(map->lock_arg);
+ ret = regmap_raw_write(map, reg, wval, val_bytes * val_count);
kfree(wval);
}
@@ -2542,18 +2509,39 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
if (regmap_volatile_range(map, reg, val_count) || map->cache_bypass ||
map->cache_type == REGCACHE_NONE) {
+ size_t chunk_count, chunk_bytes;
+ size_t chunk_regs = val_count;
+
if (!map->bus->read) {
ret = -ENOTSUPP;
goto out;
}
- if (map->max_raw_read && map->max_raw_read < val_len) {
- ret = -E2BIG;
- goto out;
- }
- /* Physical block read if there's no cache involved */
- ret = _regmap_raw_read(map, reg, val, val_len);
+ if (map->use_single_read)
+ chunk_regs = 1;
+ else if (map->max_raw_read && val_len > map->max_raw_read)
+ chunk_regs = map->max_raw_read / val_bytes;
+
+ chunk_count = val_count / chunk_regs;
+ chunk_bytes = chunk_regs * val_bytes;
+ /* Read bytes that fit into whole chunks */
+ for (i = 0; i < chunk_count; i++) {
+ ret = _regmap_raw_read(map, reg, val, chunk_bytes);
+ if (ret != 0)
+ goto out;
+
+ reg += regmap_get_offset(map, chunk_regs);
+ val += chunk_bytes;
+ val_len -= chunk_bytes;
+ }
+
+ /* Read remaining bytes */
+ if (val_len) {
+ ret = _regmap_raw_read(map, reg, val, val_len);
+ if (ret != 0)
+ goto out;
+ }
} else {
/* Otherwise go word by word for the cache; should be low
* cost as we expect to hit the cache.
@@ -2653,108 +2641,60 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
if (!IS_ALIGNED(reg, map->reg_stride))
return -EINVAL;
+ if (val_count == 0)
+ return -EINVAL;
if (map->bus && map->format.parse_inplace && (vol || map->cache_type == REGCACHE_NONE)) {
- /*
- * Some devices does not support bulk read, for
- * them we have a series of single read operations.
- */
- size_t total_size = val_bytes * val_count;
-
- if (!map->use_single_read &&
- (!map->max_raw_read || map->max_raw_read > total_size)) {
- ret = regmap_raw_read(map, reg, val,
- val_bytes * val_count);
- if (ret != 0)
- return ret;
- } else {
- /*
- * Some devices do not support bulk read or do not
- * support large bulk reads, for them we have a series
- * of read operations.
- */
- int chunk_stride = map->reg_stride;
- size_t chunk_size = val_bytes;
- size_t chunk_count = val_count;
-
- if (!map->use_single_read) {
- chunk_size = map->max_raw_read;
- if (chunk_size % val_bytes)
- chunk_size -= chunk_size % val_bytes;
- chunk_count = total_size / chunk_size;
- chunk_stride *= chunk_size / val_bytes;
- }
-
- /* Read bytes that fit into a multiple of chunk_size */
- for (i = 0; i < chunk_count; i++) {
- ret = regmap_raw_read(map,
- reg + (i * chunk_stride),
- val + (i * chunk_size),
- chunk_size);
- if (ret != 0)
- return ret;
- }
-
- /* Read remaining bytes */
- if (chunk_size * i < total_size) {
- ret = regmap_raw_read(map,
- reg + (i * chunk_stride),
- val + (i * chunk_size),
- total_size - i * chunk_size);
- if (ret != 0)
- return ret;
- }
- }
+ ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
+ if (ret != 0)
+ return ret;
for (i = 0; i < val_count * val_bytes; i += val_bytes)
map->format.parse_inplace(val + i);
} else {
+#ifdef CONFIG_64BIT
+ u64 *u64 = val;
+#endif
+ u32 *u32 = val;
+ u16 *u16 = val;
+ u8 *u8 = val;
+
+ map->lock(map->lock_arg);
+
for (i = 0; i < val_count; i++) {
unsigned int ival;
- ret = regmap_read(map, reg + regmap_get_offset(map, i),
- &ival);
- if (ret != 0)
- return ret;
- if (map->format.format_val) {
- map->format.format_val(val + (i * val_bytes), ival, 0);
- } else {
- /* Devices providing read and write
- * operations can use the bulk I/O
- * functions if they define a val_bytes,
- * we assume that the values are native
- * endian.
- */
-#ifdef CONFIG_64BIT
- u64 *u64 = val;
-#endif
- u32 *u32 = val;
- u16 *u16 = val;
- u8 *u8 = val;
+ ret = _regmap_read(map, reg + regmap_get_offset(map, i),
+ &ival);
+ if (ret != 0)
+ goto out;
- switch (map->format.val_bytes) {
+ switch (map->format.val_bytes) {
#ifdef CONFIG_64BIT
- case 8:
- u64[i] = ival;
- break;
+ case 8:
+ u64[i] = ival;
+ break;
#endif
- case 4:
- u32[i] = ival;
- break;
- case 2:
- u16[i] = ival;
- break;
- case 1:
- u8[i] = ival;
- break;
- default:
- return -EINVAL;
- }
+ case 4:
+ u32[i] = ival;
+ break;
+ case 2:
+ u16[i] = ival;
+ break;
+ case 1:
+ u8[i] = ival;
+ break;
+ default:
+ ret = -EINVAL;
+ goto out;
}
}
+
+out:
+ map->unlock(map->lock_arg);
}
- return 0;
+ return ret;
}
EXPORT_SYMBOL_GPL(regmap_bulk_read);