mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-24 10:11:26 +03:00
misc: mods: fix ioctl for writing into sysfs files
f_op->write doesn't always have to exist, it can be NULL. Instead, use kernel function which handles this correctly. Change-Id: I955bc1c2e97d3bfee3e5c7e48fefcbda4af1214c Signed-off-by: Chris Dragan <kdragan@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2457926 Tested-by: mobile promotions <svcmobile_promotions@nvidia.com> Reviewed-by: Anand Nahar <anahar@nvidia.com> Reviewed-by: Sachin Nikam <snikam@nvidia.com> Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> GVS: Gerrit_Virtual_Submit
This commit is contained in:
committed by
Laxman Dewangan
parent
a51241efac
commit
32e7a1caab
@@ -86,6 +86,10 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if KERNEL_VERSION(4, 14, 0) <= MODS_KERNEL_VERSION
|
||||
# define MODS_HAS_KERNEL_WRITE
|
||||
#endif
|
||||
|
||||
#if KERNEL_VERSION(4, 16, 0) > MODS_KERNEL_VERSION && defined(CONFIG_X86)
|
||||
# define MODS_HAS_MAP_SG_ATTRS
|
||||
#endif
|
||||
|
||||
@@ -88,31 +88,32 @@ struct irq_q_info {
|
||||
* different processes. This structure tracks data specific to each open fd.
|
||||
*/
|
||||
struct mods_client {
|
||||
struct list_head irq_list;
|
||||
struct list_head mem_alloc_list;
|
||||
struct list_head mem_map_list;
|
||||
struct list_head free_mem_list; /* list of unused UC/WC chunks */
|
||||
struct list_head irq_list;
|
||||
struct list_head mem_alloc_list;
|
||||
struct list_head mem_map_list;
|
||||
struct list_head free_mem_list; /* unused UC/WC chunks */
|
||||
#if defined(CONFIG_PPC64)
|
||||
struct list_head ppc_tce_bypass_list;
|
||||
struct list_head nvlink_sysmem_trained_list;
|
||||
struct list_head ppc_tce_bypass_list;
|
||||
struct list_head nvlink_sysmem_trained_list;
|
||||
#endif
|
||||
wait_queue_head_t interrupt_event;
|
||||
struct irq_q_info irq_queue;
|
||||
spinlock_t irq_lock;
|
||||
struct en_dev_entry *enabled_devices;
|
||||
struct mem_type mem_type;
|
||||
wait_queue_head_t interrupt_event;
|
||||
struct irq_q_info irq_queue;
|
||||
spinlock_t irq_lock;
|
||||
struct en_dev_entry *enabled_devices;
|
||||
struct workqueue_struct *work_queue;
|
||||
struct mem_type mem_type;
|
||||
#if defined(CONFIG_PCI)
|
||||
struct pci_dev *cached_dev;
|
||||
struct pci_dev *cached_dev;
|
||||
#endif
|
||||
struct mutex mtx;
|
||||
int mods_fb_suspended[FB_MAX];
|
||||
u32 access_token;
|
||||
atomic_t num_allocs;
|
||||
atomic_t num_pages;
|
||||
struct mutex mtx;
|
||||
int mods_fb_suspended[FB_MAX];
|
||||
u32 access_token;
|
||||
atomic_t num_allocs;
|
||||
atomic_t num_pages;
|
||||
#if defined(MODS_HAS_CONSOLE_LOCK)
|
||||
atomic_t console_is_locked;
|
||||
atomic_t console_is_locked;
|
||||
#endif
|
||||
u8 client_id;
|
||||
u8 client_id;
|
||||
};
|
||||
|
||||
/* VM private data */
|
||||
|
||||
@@ -1039,6 +1039,11 @@ static int mods_krnl_close(struct inode *ip, struct file *fp)
|
||||
}
|
||||
}
|
||||
|
||||
if (client->work_queue) {
|
||||
destroy_workqueue(client->work_queue);
|
||||
client->work_queue = NULL;
|
||||
}
|
||||
|
||||
mods_free_client(client_id);
|
||||
|
||||
pr_info("mods [%d]: driver closed\n", client_id);
|
||||
@@ -1618,10 +1623,17 @@ static void sysfs_write_task(struct work_struct *w)
|
||||
task->err = PTR_ERR(f);
|
||||
else {
|
||||
f->f_pos = 0;
|
||||
task->err = f->f_op->write(f,
|
||||
task->data,
|
||||
task->data_size,
|
||||
&f->f_pos);
|
||||
#ifdef MODS_HAS_KERNEL_WRITE
|
||||
task->err = kernel_write(f,
|
||||
task->data,
|
||||
task->data_size,
|
||||
&f->f_pos);
|
||||
#else
|
||||
task->err = vfs_write(f,
|
||||
(__force const char __user *)task->data,
|
||||
task->data_size,
|
||||
&f->f_pos);
|
||||
#endif
|
||||
filp_close(f, NULL);
|
||||
}
|
||||
|
||||
@@ -1630,23 +1642,39 @@ static void sysfs_write_task(struct work_struct *w)
|
||||
LOG_EXT();
|
||||
}
|
||||
|
||||
static int create_work_queue(struct mods_client *client)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (unlikely(mutex_lock_interruptible(&client->mtx)))
|
||||
return -EINTR;
|
||||
|
||||
if (!client->work_queue) {
|
||||
client->work_queue = create_singlethread_workqueue("mods_wq");
|
||||
if (!client->work_queue) {
|
||||
cl_error("failed to create work queue\n");
|
||||
err = -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&client->mtx);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int run_write_task(struct mods_client *client,
|
||||
struct mods_file_work *task)
|
||||
{
|
||||
struct workqueue_struct *wq;
|
||||
int err = create_work_queue(client);
|
||||
|
||||
wq = create_singlethread_workqueue("mods_file_write");
|
||||
if (!wq) {
|
||||
cl_error("failed to create work queue\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
cl_info("write %.*s to %s\n", task->data_size, task->data, task->path);
|
||||
|
||||
INIT_WORK(&task->work, sysfs_write_task);
|
||||
queue_work(wq, &task->work);
|
||||
flush_workqueue(wq);
|
||||
destroy_workqueue(wq);
|
||||
queue_work(client->work_queue, &task->work);
|
||||
flush_workqueue(client->work_queue);
|
||||
|
||||
if (task->err < 0)
|
||||
cl_error("failed to write %.*s to %s\n",
|
||||
|
||||
Reference in New Issue
Block a user