“244f324a06ee27e9b658c98a7b741df0c4aab6e5”上不存在“components/i/library/Select.vue”
提交 5679078b 编写于 作者: J John Garry 提交者: Xie XiuQi

lib: logic_pio: Fix RCU usage

commit 06709e81c668f5f56c65b806895b278517bd44e0 upstream.

The traversing of io_range_list with list_for_each_entry_rcu()
is not properly protected by rcu_read_lock() and rcu_read_unlock(),
so add them.

These functions mark the critical section scope where the list is
protected for the reader, it cannot be  "reclaimed". Any updater - in
this case, the logical PIO registration functions - cannot update the
list until the reader exits this critical section.

In addition, the list traversing used in logic_pio_register_range()
does not need to use the rcu variant.

This is because we are already using io_range_mutex to guarantee mutual
exclusion from mutating the list.

Cc: stable@vger.kernel.org
Fixes: 031e3601 ("lib: Add generic PIO mapping method")
Signed-off-by: NJohn Garry <john.garry@huawei.com>
Signed-off-by: NWei Xu <xuwei5@hisilicon.com>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 fb929981
...@@ -46,7 +46,7 @@ int logic_pio_register_range(struct logic_pio_hwaddr *new_range) ...@@ -46,7 +46,7 @@ int logic_pio_register_range(struct logic_pio_hwaddr *new_range)
end = new_range->hw_start + new_range->size; end = new_range->hw_start + new_range->size;
mutex_lock(&io_range_mutex); mutex_lock(&io_range_mutex);
list_for_each_entry_rcu(range, &io_range_list, list) { list_for_each_entry(range, &io_range_list, list) {
if (range->fwnode == new_range->fwnode) { if (range->fwnode == new_range->fwnode) {
/* range already there */ /* range already there */
goto end_register; goto end_register;
...@@ -108,26 +108,38 @@ int logic_pio_register_range(struct logic_pio_hwaddr *new_range) ...@@ -108,26 +108,38 @@ int logic_pio_register_range(struct logic_pio_hwaddr *new_range)
*/ */
struct logic_pio_hwaddr *find_io_range_by_fwnode(struct fwnode_handle *fwnode) struct logic_pio_hwaddr *find_io_range_by_fwnode(struct fwnode_handle *fwnode)
{ {
struct logic_pio_hwaddr *range; struct logic_pio_hwaddr *range, *found_range = NULL;
rcu_read_lock();
list_for_each_entry_rcu(range, &io_range_list, list) { list_for_each_entry_rcu(range, &io_range_list, list) {
if (range->fwnode == fwnode) if (range->fwnode == fwnode) {
return range; found_range = range;
break;
}
} }
return NULL; rcu_read_unlock();
return found_range;
} }
/* Return a registered range given an input PIO token */ /* Return a registered range given an input PIO token */
static struct logic_pio_hwaddr *find_io_range(unsigned long pio) static struct logic_pio_hwaddr *find_io_range(unsigned long pio)
{ {
struct logic_pio_hwaddr *range; struct logic_pio_hwaddr *range, *found_range = NULL;
rcu_read_lock();
list_for_each_entry_rcu(range, &io_range_list, list) { list_for_each_entry_rcu(range, &io_range_list, list) {
if (in_range(pio, range->io_start, range->size)) if (in_range(pio, range->io_start, range->size)) {
return range; found_range = range;
break;
}
} }
pr_err("PIO entry token %lx invalid\n", pio); rcu_read_unlock();
return NULL;
if (!found_range)
pr_err("PIO entry token 0x%lx invalid\n", pio);
return found_range;
} }
/** /**
...@@ -180,14 +192,23 @@ unsigned long logic_pio_trans_cpuaddr(resource_size_t addr) ...@@ -180,14 +192,23 @@ unsigned long logic_pio_trans_cpuaddr(resource_size_t addr)
{ {
struct logic_pio_hwaddr *range; struct logic_pio_hwaddr *range;
rcu_read_lock();
list_for_each_entry_rcu(range, &io_range_list, list) { list_for_each_entry_rcu(range, &io_range_list, list) {
if (range->flags != LOGIC_PIO_CPU_MMIO) if (range->flags != LOGIC_PIO_CPU_MMIO)
continue; continue;
if (in_range(addr, range->hw_start, range->size)) if (in_range(addr, range->hw_start, range->size)) {
return addr - range->hw_start + range->io_start; unsigned long cpuaddr;
cpuaddr = addr - range->hw_start + range->io_start;
rcu_read_unlock();
return cpuaddr;
}
} }
pr_err("addr %llx not registered in io_range_list\n", rcu_read_unlock();
(unsigned long long) addr);
pr_err("addr %pa not registered in io_range_list\n", &addr);
return ~0UL; return ~0UL;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册