regmap: Merge up v6.4-rc6
authorMark Brown <broonie@kernel.org>
Mon, 12 Jun 2023 13:50:15 +0000 (14:50 +0100)
committerMark Brown <broonie@kernel.org>
Mon, 12 Jun 2023 13:50:15 +0000 (14:50 +0100)
The fix for maple tree RCU locking on sync is a dependency for the
block sync code for the maple tree.

1  2 
drivers/base/regmap/regcache-maple.c
drivers/base/regmap/regmap.c

@@@ -203,15 -203,18 +203,18 @@@ static int regcache_maple_sync(struct r
  
        mas_for_each(&mas, entry, max) {
                for (r = max(mas.index, lmin); r <= min(mas.last, lmax); r++) {
+                       mas_pause(&mas);
+                       rcu_read_unlock();
                        ret = regcache_sync_val(map, r, entry[r - mas.index]);
                        if (ret != 0)
                                goto out;
+                       rcu_read_lock();
                }
        }
  
- out:
        rcu_read_unlock();
  
+ out:
        map->cache_bypass = false;
  
        return ret;
@@@ -239,41 -242,11 +242,41 @@@ static int regcache_maple_exit(struct r
        return 0;
  }
  
 +static int regcache_maple_insert_block(struct regmap *map, int first,
 +                                      int last)
 +{
 +      struct maple_tree *mt = map->cache;
 +      MA_STATE(mas, mt, first, last);
 +      unsigned long *entry;
 +      int i, ret;
 +
 +      entry = kcalloc(last - first + 1, sizeof(unsigned long), GFP_KERNEL);
 +      if (!entry)
 +              return -ENOMEM;
 +
 +      for (i = 0; i < last - first + 1; i++)
 +              entry[i] = map->reg_defaults[first + i].def;
 +
 +      mas_lock(&mas);
 +
 +      mas_set_range(&mas, map->reg_defaults[first].reg,
 +                    map->reg_defaults[last].reg);
 +      ret = mas_store_gfp(&mas, entry, GFP_KERNEL);
 +
 +      mas_unlock(&mas);
 +
 +      if (ret)
 +              kfree(entry);
 +
 +      return ret;
 +}
 +
  static int regcache_maple_init(struct regmap *map)
  {
        struct maple_tree *mt;
        int i;
        int ret;
 +      int range_start;
  
        mt = kmalloc(sizeof(*mt), GFP_KERNEL);
        if (!mt)
  
        mt_init(mt);
  
 -      for (i = 0; i < map->num_reg_defaults; i++) {
 -              ret = regcache_maple_write(map,
 -                                         map->reg_defaults[i].reg,
 -                                         map->reg_defaults[i].def);
 -              if (ret)
 -                      goto err;
 +      if (!map->num_reg_defaults)
 +              return 0;
 +
 +      range_start = 0;
 +
 +      /* Scan for ranges of contiguous registers */
 +      for (i = 1; i < map->num_reg_defaults; i++) {
 +              if (map->reg_defaults[i].reg !=
 +                  map->reg_defaults[i - 1].reg + 1) {
 +                      ret = regcache_maple_insert_block(map, range_start,
 +                                                        i - 1);
 +                      if (ret != 0)
 +                              goto err;
 +
 +                      range_start = i;
 +              }
        }
  
 +      /* Add the last block */
 +      ret = regcache_maple_insert_block(map, range_start,
 +                                        map->num_reg_defaults - 1);
 +      if (ret != 0)
 +              goto err;
 +
        return 0;
  
  err:
@@@ -2082,6 -2082,8 +2082,8 @@@ int _regmap_raw_write(struct regmap *ma
        size_t val_count = val_len / val_bytes;
        size_t chunk_count, chunk_bytes;
        size_t chunk_regs = val_count;
+       size_t max_data = map->max_raw_write - map->format.reg_bytes -
+                       map->format.pad_bytes;
        int ret, i;
  
        if (!val_count)
  
        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;
+       else if (map->max_raw_write && val_len > max_data)
+               chunk_regs = max_data / val_bytes;
  
        chunk_count = val_count / chunk_regs;
        chunk_bytes = chunk_regs * val_bytes;
@@@ -2981,11 -2983,6 +2983,11 @@@ int regmap_raw_read(struct regmap *map
                size_t chunk_count, chunk_bytes;
                size_t chunk_regs = val_count;
  
 +              if (!map->cache_bypass && map->cache_only) {
 +                      ret = -EBUSY;
 +                      goto out;
 +              }
 +
                if (!map->read) {
                        ret = -ENOTSUPP;
                        goto out;
@@@ -3081,19 -3078,18 +3083,19 @@@ int regmap_noinc_read(struct regmap *ma
                goto out_unlock;
        }
  
 +      /*
 +       * We have not defined the FIFO semantics for cache, as the
 +       * cache is just one value deep. Should we return the last
 +       * written value? Just avoid this by always reading the FIFO
 +       * even when using cache. Cache only will not work.
 +       */
 +      if (!map->cache_bypass && map->cache_only) {
 +              ret = -EBUSY;
 +              goto out_unlock;
 +      }
 +
        /* Use the accelerated operation if we can */
        if (map->bus->reg_noinc_read) {
 -              /*
 -               * We have not defined the FIFO semantics for cache, as the
 -               * cache is just one value deep. Should we return the last
 -               * written value? Just avoid this by always reading the FIFO
 -               * even when using cache. Cache only will not work.
 -               */
 -              if (map->cache_only) {
 -                      ret = -EBUSY;
 -                      goto out_unlock;
 -              }
                ret = regmap_noinc_readwrite(map, reg, val, val_len, false);
                goto out_unlock;
        }