Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'regmap-fix-v5.9-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap

Pull regmap fixes from Mark Brown:
"Two issues here - one is a fix for use after free issues in the case
where a regmap overrides its name using something dynamically
generated, the other is that we weren't handling access checks
non-incrementing I/O on registers within paged register regions
correctly resulting in spurious errors.

Both of these are quite rare but serious if they occur"

* tag 'regmap-fix-v5.9-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap:
regmap: fix page selection for noinc writes
regmap: fix page selection for noinc reads
regmap: debugfs: Add back in erroneously removed initialisation of ret
regmap: debugfs: Fix handling of name string for debugfs init delays

+56 -34
+3 -3
drivers/base/regmap/internal.h
··· 217 217 218 218 #ifdef CONFIG_DEBUG_FS 219 219 extern void regmap_debugfs_initcall(void); 220 - extern void regmap_debugfs_init(struct regmap *map, const char *name); 220 + extern void regmap_debugfs_init(struct regmap *map); 221 221 extern void regmap_debugfs_exit(struct regmap *map); 222 222 223 223 static inline void regmap_debugfs_disable(struct regmap *map) ··· 227 227 228 228 #else 229 229 static inline void regmap_debugfs_initcall(void) { } 230 - static inline void regmap_debugfs_init(struct regmap *map, const char *name) { } 230 + static inline void regmap_debugfs_init(struct regmap *map) { } 231 231 static inline void regmap_debugfs_exit(struct regmap *map) { } 232 232 static inline void regmap_debugfs_disable(struct regmap *map) { } 233 233 #endif ··· 259 259 int regcache_lookup_reg(struct regmap *map, unsigned int reg); 260 260 261 261 int _regmap_raw_write(struct regmap *map, unsigned int reg, 262 - const void *val, size_t val_len); 262 + const void *val, size_t val_len, bool noinc); 263 263 264 264 void regmap_async_complete_cb(struct regmap_async *async, int ret); 265 265
+1 -1
drivers/base/regmap/regcache.c
··· 717 717 718 718 map->cache_bypass = true; 719 719 720 - ret = _regmap_raw_write(map, base, *data, count * val_bytes); 720 + ret = _regmap_raw_write(map, base, *data, count * val_bytes, false); 721 721 if (ret) 722 722 dev_err(map->dev, "Unable to sync registers %#x-%#x. %d\n", 723 723 base, cur - map->reg_stride, ret);
+3 -4
drivers/base/regmap/regmap-debugfs.c
··· 17 17 18 18 struct regmap_debugfs_node { 19 19 struct regmap *map; 20 - const char *name; 21 20 struct list_head link; 22 21 }; 23 22 ··· 543 544 .write = regmap_cache_bypass_write_file, 544 545 }; 545 546 546 - void regmap_debugfs_init(struct regmap *map, const char *name) 547 + void regmap_debugfs_init(struct regmap *map) 547 548 { 548 549 struct rb_node *next; 549 550 struct regmap_range_node *range_node; 550 551 const char *devname = "dummy"; 552 + const char *name = map->name; 551 553 552 554 /* 553 555 * Userspace can initiate reads from the hardware over debugfs. ··· 569 569 if (!node) 570 570 return; 571 571 node->map = map; 572 - node->name = name; 573 572 mutex_lock(&regmap_debugfs_early_lock); 574 573 list_add(&node->link, &regmap_debugfs_early_list); 575 574 mutex_unlock(&regmap_debugfs_early_lock); ··· 678 679 679 680 mutex_lock(&regmap_debugfs_early_lock); 680 681 list_for_each_entry_safe(node, tmp, &regmap_debugfs_early_list, link) { 681 - regmap_debugfs_init(node->map, node->name); 682 + regmap_debugfs_init(node->map); 682 683 list_del(&node->link); 683 684 kfree(node); 684 685 }
+49 -26
drivers/base/regmap/regmap.c
··· 581 581 kfree(map->selector_work_buf); 582 582 } 583 583 584 + static int regmap_set_name(struct regmap *map, const struct regmap_config *config) 585 + { 586 + if (config->name) { 587 + const char *name = kstrdup_const(config->name, GFP_KERNEL); 588 + 589 + if (!name) 590 + return -ENOMEM; 591 + 592 + kfree_const(map->name); 593 + map->name = name; 594 + } 595 + 596 + return 0; 597 + } 598 + 584 599 int regmap_attach_dev(struct device *dev, struct regmap *map, 585 600 const struct regmap_config *config) 586 601 { 587 602 struct regmap **m; 603 + int ret; 588 604 589 605 map->dev = dev; 590 606 591 - regmap_debugfs_init(map, config->name); 607 + ret = regmap_set_name(map, config); 608 + if (ret) 609 + return ret; 610 + 611 + regmap_debugfs_init(map); 592 612 593 613 /* Add a devres resource for dev_get_regmap() */ 594 614 m = devres_alloc(dev_get_regmap_release, sizeof(*m), GFP_KERNEL); ··· 707 687 goto err; 708 688 } 709 689 710 - if (config->name) { 711 - map->name = kstrdup_const(config->name, GFP_KERNEL); 712 - if (!map->name) { 713 - ret = -ENOMEM; 714 - goto err_map; 715 - } 716 - } 690 + ret = regmap_set_name(map, config); 691 + if (ret) 692 + goto err_map; 717 693 718 694 if (config->disable_locking) { 719 695 map->lock = map->unlock = regmap_lock_unlock_none; ··· 1153 1137 if (ret != 0) 1154 1138 goto err_regcache; 1155 1139 } else { 1156 - regmap_debugfs_init(map, config->name); 1140 + regmap_debugfs_init(map); 1157 1141 } 1158 1142 1159 1143 return map; ··· 1313 1297 */ 1314 1298 int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config) 1315 1299 { 1300 + int ret; 1301 + 1316 1302 regcache_exit(map); 1317 1303 regmap_debugfs_exit(map); 1318 1304 ··· 1327 1309 map->readable_noinc_reg = config->readable_noinc_reg; 1328 1310 map->cache_type = config->cache_type; 1329 1311 1330 - regmap_debugfs_init(map, config->name); 1312 + ret = regmap_set_name(map, config); 1313 + if (ret) 1314 + return ret; 1315 + 1316 + regmap_debugfs_init(map); 1331 1317 1332 1318 map->cache_bypass = false; 1333 1319 map->cache_only = false; ··· 1486 1464 } 1487 1465 1488 1466 static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg, 1489 - const void *val, size_t val_len) 1467 + const void *val, size_t val_len, bool noinc) 1490 1468 { 1491 1469 struct regmap_range_node *range; 1492 1470 unsigned long flags; ··· 1545 1523 win_residue, val_len / map->format.val_bytes); 1546 1524 ret = _regmap_raw_write_impl(map, reg, val, 1547 1525 win_residue * 1548 - map->format.val_bytes); 1526 + map->format.val_bytes, noinc); 1549 1527 if (ret != 0) 1550 1528 return ret; 1551 1529 ··· 1559 1537 win_residue = range->window_len - win_offset; 1560 1538 } 1561 1539 1562 - ret = _regmap_select_page(map, &reg, range, val_num); 1540 + ret = _regmap_select_page(map, &reg, range, noinc ? 1 : val_num); 1563 1541 if (ret != 0) 1564 1542 return ret; 1565 1543 } ··· 1767 1745 map->work_buf + 1768 1746 map->format.reg_bytes + 1769 1747 map->format.pad_bytes, 1770 - map->format.val_bytes); 1748 + map->format.val_bytes, 1749 + false); 1771 1750 } 1772 1751 1773 1752 static inline void *_regmap_map_get_context(struct regmap *map) ··· 1862 1839 EXPORT_SYMBOL_GPL(regmap_write_async); 1863 1840 1864 1841 int _regmap_raw_write(struct regmap *map, unsigned int reg, 1865 - const void *val, size_t val_len) 1842 + const void *val, size_t val_len, bool noinc) 1866 1843 { 1867 1844 size_t val_bytes = map->format.val_bytes; 1868 1845 size_t val_count = val_len / val_bytes; ··· 1883 1860 1884 1861 /* Write as many bytes as possible with chunk_size */ 1885 1862 for (i = 0; i < chunk_count; i++) { 1886 - ret = _regmap_raw_write_impl(map, reg, val, chunk_bytes); 1863 + ret = _regmap_raw_write_impl(map, reg, val, chunk_bytes, noinc); 1887 1864 if (ret) 1888 1865 return ret; 1889 1866 ··· 1894 1871 1895 1872 /* Write remaining bytes */ 1896 1873 if (val_len) 1897 - ret = _regmap_raw_write_impl(map, reg, val, val_len); 1874 + ret = _regmap_raw_write_impl(map, reg, val, val_len, noinc); 1898 1875 1899 1876 return ret; 1900 1877 } ··· 1927 1904 1928 1905 map->lock(map->lock_arg); 1929 1906 1930 - ret = _regmap_raw_write(map, reg, val, val_len); 1907 + ret = _regmap_raw_write(map, reg, val, val_len, false); 1931 1908 1932 1909 map->unlock(map->lock_arg); 1933 1910 ··· 1985 1962 write_len = map->max_raw_write; 1986 1963 else 1987 1964 write_len = val_len; 1988 - ret = _regmap_raw_write(map, reg, val, write_len); 1965 + ret = _regmap_raw_write(map, reg, val, write_len, true); 1989 1966 if (ret) 1990 1967 goto out_unlock; 1991 1968 val = ((u8 *)val) + write_len; ··· 2462 2439 2463 2440 map->async = true; 2464 2441 2465 - ret = _regmap_raw_write(map, reg, val, val_len); 2442 + ret = _regmap_raw_write(map, reg, val, val_len, false); 2466 2443 2467 2444 map->async = false; 2468 2445 ··· 2473 2450 EXPORT_SYMBOL_GPL(regmap_raw_write_async); 2474 2451 2475 2452 static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, 2476 - unsigned int val_len) 2453 + unsigned int val_len, bool noinc) 2477 2454 { 2478 2455 struct regmap_range_node *range; 2479 2456 int ret; ··· 2486 2463 range = _regmap_range_lookup(map, reg); 2487 2464 if (range) { 2488 2465 ret = _regmap_select_page(map, &reg, range, 2489 - val_len / map->format.val_bytes); 2466 + noinc ? 1 : val_len / map->format.val_bytes); 2490 2467 if (ret != 0) 2491 2468 return ret; 2492 2469 } ··· 2524 2501 if (!map->format.parse_val) 2525 2502 return -EINVAL; 2526 2503 2527 - ret = _regmap_raw_read(map, reg, work_val, map->format.val_bytes); 2504 + ret = _regmap_raw_read(map, reg, work_val, map->format.val_bytes, false); 2528 2505 if (ret == 0) 2529 2506 *val = map->format.parse_val(work_val); 2530 2507 ··· 2640 2617 2641 2618 /* Read bytes that fit into whole chunks */ 2642 2619 for (i = 0; i < chunk_count; i++) { 2643 - ret = _regmap_raw_read(map, reg, val, chunk_bytes); 2620 + ret = _regmap_raw_read(map, reg, val, chunk_bytes, false); 2644 2621 if (ret != 0) 2645 2622 goto out; 2646 2623 ··· 2651 2628 2652 2629 /* Read remaining bytes */ 2653 2630 if (val_len) { 2654 - ret = _regmap_raw_read(map, reg, val, val_len); 2631 + ret = _regmap_raw_read(map, reg, val, val_len, false); 2655 2632 if (ret != 0) 2656 2633 goto out; 2657 2634 } ··· 2726 2703 read_len = map->max_raw_read; 2727 2704 else 2728 2705 read_len = val_len; 2729 - ret = _regmap_raw_read(map, reg, val, read_len); 2706 + ret = _regmap_raw_read(map, reg, val, read_len, true); 2730 2707 if (ret) 2731 2708 goto out_unlock; 2732 2709 val = ((u8 *)val) + read_len;