On Mon, Jul 31, 2023 at 03:42:47PM -0700, Mike Tipton wrote: > +static int icc_get_set(void *data, u64 val) > +{ > + struct debugfs_path *debugfs_path; > + char *src, *dst; > + int ret = 0; > + > + mutex_lock(&debugfs_lock); > + > + rcu_read_lock(); > + src = rcu_dereference(src_node); > + dst = rcu_dereference(dst_node); > + > + /* > + * If we've already looked up a path, then use the existing one instead > + * of calling icc_get() again. This allows for updating previous BW > + * votes when "get" is written to multiple times for multiple paths. > + */ > + cur_path = get_path(src, dst); > + if (cur_path) { > + rcu_read_unlock(); > + goto out; > + } > + > + src = kstrdup(src, GFP_KERNEL); > + dst = kstrdup(dst, GFP_KERNEL); > + rcu_read_unlock(); > + Blocking calls are not allowed from RCU critical section. So we would need to replace GFP_KERNEL with GFP_ATOMIC. > + if (!src || !dst) { > + ret = -ENOMEM; > + goto err_free; > + } > + > + cur_path = icc_get(&pdev->dev, src, dst); > + if (IS_ERR(cur_path)) { > + ret = PTR_ERR(cur_path); > + goto err_free; > + } > + > + debugfs_path = kzalloc(sizeof(*debugfs_path), GFP_KERNEL); > + if (!debugfs_path) { > + ret = -ENOMEM; > + goto err_put; > + } > + > + debugfs_path->path = cur_path; > + debugfs_path->src = src; > + debugfs_path->dst = dst; > + list_add_tail(&debugfs_path->list, &debugfs_paths); > + > + goto out; > + > +err_put: > + icc_put(cur_path); > +err_free: > + kfree(src); > + kfree(dst); > +out: > + mutex_unlock(&debugfs_lock); > + return ret; > +}