Loading drivers/soc/qcom/ramdump.c +36 −3 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2011-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2011-2020, The Linux Foundation. All rights reserved. */ #include <linux/kernel.h> Loading @@ -17,6 +17,7 @@ #include <linux/elf.h> #include <linux/wait.h> #include <linux/cdev.h> #include <linux/srcu.h> #include <linux/atomic.h> #include <soc/qcom/ramdump.h> #include <linux/dma-mapping.h> Loading Loading @@ -61,6 +62,8 @@ struct ramdump_device { char *elfcore_buf; unsigned long attrs; bool complete_ramdump; bool abort_ramdump; struct srcu_struct rd_srcu; }; static int ramdump_open(struct inode *inode, struct file *filep) Loading Loading @@ -160,15 +163,26 @@ static ssize_t ramdump_read(struct file *filep, char __user *buf, size_t count, size_t copy_size = 0, alignsize; unsigned char *alignbuf = NULL, *finalbuf = NULL; int ret = 0; int srcu_idx; loff_t orig_pos = *pos; if ((filep->f_flags & O_NONBLOCK) && !entry->data_ready) return -EAGAIN; ret = wait_event_interruptible(rd_dev->dump_wait_q, entry->data_ready); ret = wait_event_interruptible(rd_dev->dump_wait_q, (entry->data_ready || rd_dev->abort_ramdump)); if (ret) return ret; srcu_idx = srcu_read_lock(&rd_dev->rd_srcu); if (rd_dev->abort_ramdump) { pr_err("Ramdump(%s): Ramdump aborted\n", rd_dev->name); rd_dev->ramdump_status = -1; ret = -ETIME; goto ramdump_done; } if (*pos < rd_dev->elfcore_size) { copy_size = rd_dev->elfcore_size - *pos; copy_size = min(copy_size, count); Loading @@ -180,9 +194,11 @@ static ssize_t ramdump_read(struct file *filep, char __user *buf, size_t count, *pos += copy_size; count -= copy_size; buf += copy_size; if (count == 0) if (count == 0) { srcu_read_unlock(&rd_dev->rd_srcu, srcu_idx); return copy_size; } } addr = offset_translate(*pos - rd_dev->elfcore_size, rd_dev, &data_left, &vaddr); Loading Loading @@ -258,12 +274,15 @@ static ssize_t ramdump_read(struct file *filep, char __user *buf, size_t count, pr_debug("Ramdump(%s): Read %zd bytes from address %lx.", rd_dev->name, copy_size, addr); srcu_read_unlock(&rd_dev->rd_srcu, srcu_idx); return *pos - orig_pos; ramdump_done: if (!vaddr && origdevice_mem) dma_unremap(rd_dev->dev->parent, origdevice_mem, copy_size); srcu_read_unlock(&rd_dev->rd_srcu, srcu_idx); kfree(finalbuf); *pos = 0; reset_ramdump_entry(entry); Loading Loading @@ -368,6 +387,7 @@ void *create_ramdump_device(const char *dev_name, struct device *parent) mutex_init(&rd_dev->consumer_lock); atomic_set(&rd_dev->readers_left, 0); init_srcu_struct(&rd_dev->rd_srcu); cdev_init(&rd_dev->cdev, &ramdump_file_ops); ret = cdev_add(&rd_dev->cdev, MKDEV(MAJOR(ramdump_dev), minor), 1); Loading @@ -380,6 +400,7 @@ void *create_ramdump_device(const char *dev_name, struct device *parent) return (void *)rd_dev; fail_cdev_add: cleanup_srcu_struct(&rd_dev->rd_srcu); mutex_destroy(&rd_dev->consumer_lock); device_unregister(rd_dev->dev); fail_return_minor: Loading @@ -400,6 +421,7 @@ void destroy_ramdump_device(void *dev) cdev_del(&rd_dev->cdev); device_unregister(rd_dev->dev); cleanup_srcu_struct(&rd_dev->rd_srcu); ida_simple_remove(&rd_minor_id, minor); kfree(rd_dev); } Loading Loading @@ -480,6 +502,7 @@ static int _do_ramdump(void *handle, struct ramdump_segment *segments, list_for_each_entry(entry, &rd_dev->consumer_list, list) entry->data_ready = true; rd_dev->ramdump_status = -1; rd_dev->abort_ramdump = false; reinit_completion(&rd_dev->ramdump_complete); atomic_set(&rd_dev->readers_left, rd_dev->consumers); Loading @@ -496,6 +519,11 @@ static int _do_ramdump(void *handle, struct ramdump_segment *segments, pr_err("Ramdump(%s): Timed out waiting for userspace.\n", rd_dev->name); ret = -EPIPE; rd_dev->abort_ramdump = true; /* Wait for pending readers to complete (if any) */ synchronize_srcu(&rd_dev->rd_srcu); } else ret = (rd_dev->ramdump_status == 0) ? 0 : -EPIPE; Loading Loading @@ -609,6 +637,7 @@ static int _do_minidump(void *handle, struct ramdump_segment *segments, list_for_each_entry(entry, &rd_dev->consumer_list, list) entry->data_ready = true; rd_dev->ramdump_status = -1; rd_dev->abort_ramdump = false; reinit_completion(&rd_dev->ramdump_complete); atomic_set(&rd_dev->readers_left, rd_dev->consumers); Loading @@ -625,6 +654,10 @@ static int _do_minidump(void *handle, struct ramdump_segment *segments, pr_err("Ramdump(%s): Timed out waiting for userspace.\n", rd_dev->name); ret = -EPIPE; rd_dev->abort_ramdump = true; /* Wait for pending readers to complete (if any) */ synchronize_srcu(&rd_dev->rd_srcu); } else { ret = (rd_dev->ramdump_status == 0) ? 0 : -EPIPE; } Loading Loading
drivers/soc/qcom/ramdump.c +36 −3 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2011-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2011-2020, The Linux Foundation. All rights reserved. */ #include <linux/kernel.h> Loading @@ -17,6 +17,7 @@ #include <linux/elf.h> #include <linux/wait.h> #include <linux/cdev.h> #include <linux/srcu.h> #include <linux/atomic.h> #include <soc/qcom/ramdump.h> #include <linux/dma-mapping.h> Loading Loading @@ -61,6 +62,8 @@ struct ramdump_device { char *elfcore_buf; unsigned long attrs; bool complete_ramdump; bool abort_ramdump; struct srcu_struct rd_srcu; }; static int ramdump_open(struct inode *inode, struct file *filep) Loading Loading @@ -160,15 +163,26 @@ static ssize_t ramdump_read(struct file *filep, char __user *buf, size_t count, size_t copy_size = 0, alignsize; unsigned char *alignbuf = NULL, *finalbuf = NULL; int ret = 0; int srcu_idx; loff_t orig_pos = *pos; if ((filep->f_flags & O_NONBLOCK) && !entry->data_ready) return -EAGAIN; ret = wait_event_interruptible(rd_dev->dump_wait_q, entry->data_ready); ret = wait_event_interruptible(rd_dev->dump_wait_q, (entry->data_ready || rd_dev->abort_ramdump)); if (ret) return ret; srcu_idx = srcu_read_lock(&rd_dev->rd_srcu); if (rd_dev->abort_ramdump) { pr_err("Ramdump(%s): Ramdump aborted\n", rd_dev->name); rd_dev->ramdump_status = -1; ret = -ETIME; goto ramdump_done; } if (*pos < rd_dev->elfcore_size) { copy_size = rd_dev->elfcore_size - *pos; copy_size = min(copy_size, count); Loading @@ -180,9 +194,11 @@ static ssize_t ramdump_read(struct file *filep, char __user *buf, size_t count, *pos += copy_size; count -= copy_size; buf += copy_size; if (count == 0) if (count == 0) { srcu_read_unlock(&rd_dev->rd_srcu, srcu_idx); return copy_size; } } addr = offset_translate(*pos - rd_dev->elfcore_size, rd_dev, &data_left, &vaddr); Loading Loading @@ -258,12 +274,15 @@ static ssize_t ramdump_read(struct file *filep, char __user *buf, size_t count, pr_debug("Ramdump(%s): Read %zd bytes from address %lx.", rd_dev->name, copy_size, addr); srcu_read_unlock(&rd_dev->rd_srcu, srcu_idx); return *pos - orig_pos; ramdump_done: if (!vaddr && origdevice_mem) dma_unremap(rd_dev->dev->parent, origdevice_mem, copy_size); srcu_read_unlock(&rd_dev->rd_srcu, srcu_idx); kfree(finalbuf); *pos = 0; reset_ramdump_entry(entry); Loading Loading @@ -368,6 +387,7 @@ void *create_ramdump_device(const char *dev_name, struct device *parent) mutex_init(&rd_dev->consumer_lock); atomic_set(&rd_dev->readers_left, 0); init_srcu_struct(&rd_dev->rd_srcu); cdev_init(&rd_dev->cdev, &ramdump_file_ops); ret = cdev_add(&rd_dev->cdev, MKDEV(MAJOR(ramdump_dev), minor), 1); Loading @@ -380,6 +400,7 @@ void *create_ramdump_device(const char *dev_name, struct device *parent) return (void *)rd_dev; fail_cdev_add: cleanup_srcu_struct(&rd_dev->rd_srcu); mutex_destroy(&rd_dev->consumer_lock); device_unregister(rd_dev->dev); fail_return_minor: Loading @@ -400,6 +421,7 @@ void destroy_ramdump_device(void *dev) cdev_del(&rd_dev->cdev); device_unregister(rd_dev->dev); cleanup_srcu_struct(&rd_dev->rd_srcu); ida_simple_remove(&rd_minor_id, minor); kfree(rd_dev); } Loading Loading @@ -480,6 +502,7 @@ static int _do_ramdump(void *handle, struct ramdump_segment *segments, list_for_each_entry(entry, &rd_dev->consumer_list, list) entry->data_ready = true; rd_dev->ramdump_status = -1; rd_dev->abort_ramdump = false; reinit_completion(&rd_dev->ramdump_complete); atomic_set(&rd_dev->readers_left, rd_dev->consumers); Loading @@ -496,6 +519,11 @@ static int _do_ramdump(void *handle, struct ramdump_segment *segments, pr_err("Ramdump(%s): Timed out waiting for userspace.\n", rd_dev->name); ret = -EPIPE; rd_dev->abort_ramdump = true; /* Wait for pending readers to complete (if any) */ synchronize_srcu(&rd_dev->rd_srcu); } else ret = (rd_dev->ramdump_status == 0) ? 0 : -EPIPE; Loading Loading @@ -609,6 +637,7 @@ static int _do_minidump(void *handle, struct ramdump_segment *segments, list_for_each_entry(entry, &rd_dev->consumer_list, list) entry->data_ready = true; rd_dev->ramdump_status = -1; rd_dev->abort_ramdump = false; reinit_completion(&rd_dev->ramdump_complete); atomic_set(&rd_dev->readers_left, rd_dev->consumers); Loading @@ -625,6 +654,10 @@ static int _do_minidump(void *handle, struct ramdump_segment *segments, pr_err("Ramdump(%s): Timed out waiting for userspace.\n", rd_dev->name); ret = -EPIPE; rd_dev->abort_ramdump = true; /* Wait for pending readers to complete (if any) */ synchronize_srcu(&rd_dev->rd_srcu); } else { ret = (rd_dev->ramdump_status == 0) ? 0 : -EPIPE; } Loading