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-v7.0-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap

Pull regmap fix from Mark Brown:
"A fix from Andy Shevchenko for an issue with caching of page selector
registers which are located inside the page they are switching"

* tag 'regmap-fix-v7.0-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap:
regmap: Synchronize cache for the page selector

+26 -4
+26 -4
drivers/base/regmap/regmap.c
··· 1545 1545 unsigned int val_num) 1546 1546 { 1547 1547 void *orig_work_buf; 1548 + unsigned int selector_reg; 1548 1549 unsigned int win_offset; 1549 1550 unsigned int win_page; 1550 1551 bool page_chg; ··· 1564 1563 return -EINVAL; 1565 1564 } 1566 1565 1567 - /* It is possible to have selector register inside data window. 1568 - In that case, selector register is located on every page and 1569 - it needs no page switching, when accessed alone. */ 1566 + /* 1567 + * Calculate the address of the selector register in the corresponding 1568 + * data window if it is located on every page. 1569 + */ 1570 + page_chg = in_range(range->selector_reg, range->window_start, range->window_len); 1571 + if (page_chg) 1572 + selector_reg = range->range_min + win_page * range->window_len + 1573 + range->selector_reg - range->window_start; 1574 + 1575 + /* 1576 + * It is possible to have selector register inside data window. 1577 + * In that case, selector register is located on every page and it 1578 + * needs no page switching, when accessed alone. 1579 + * 1580 + * Nevertheless we should synchronize the cache values for it. 1581 + * This can't be properly achieved if the selector register is 1582 + * the first and the only one to be read inside the data window. 1583 + * That's why we update it in that case as well. 1584 + * 1585 + * However, we specifically avoid updating it for the default page, 1586 + * when it's overlapped with the real data window, to prevent from 1587 + * infinite looping. 1588 + */ 1570 1589 if (val_num > 1 || 1590 + (page_chg && selector_reg != range->selector_reg) || 1571 1591 range->window_start + win_offset != range->selector_reg) { 1572 1592 /* Use separate work_buf during page switching */ 1573 1593 orig_work_buf = map->work_buf; ··· 1597 1575 ret = _regmap_update_bits(map, range->selector_reg, 1598 1576 range->selector_mask, 1599 1577 win_page << range->selector_shift, 1600 - &page_chg, false); 1578 + NULL, false); 1601 1579 1602 1580 map->work_buf = orig_work_buf; 1603 1581