Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5a3c177b authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "soc: qcom: ramdump: Fix 'complete ramdump' collection"

parents 032d9702 21eaad12
Loading
Loading
Loading
Loading
+423 −363

File changed.

Preview size limit exceeded, changes collapsed.

+4 −0
Original line number Diff line number Diff line
@@ -1098,6 +1098,7 @@
  init_net
  __init_rwsem
  init_special_inode
  init_srcu_struct
  init_timer_key
  init_uts_ns
  init_wait_entry
@@ -2275,6 +2276,8 @@
  srcu_notifier_call_chain
  srcu_notifier_chain_register
  srcu_notifier_chain_unregister
  __srcu_read_lock
  __srcu_read_unlock
  sscanf
  __stack_chk_fail
  __stack_chk_guard
@@ -2317,6 +2320,7 @@
  synchronize_irq
  synchronize_net
  synchronize_rcu
  synchronize_srcu
  syscon_node_to_regmap
  syscon_regmap_lookup_by_phandle
  sysfs_create_bin_file
+1 −21
Original line number Diff line number Diff line
@@ -498,10 +498,7 @@ int pil_do_ramdump(struct pil_desc *desc,

	s = ramdump_segs;
	list_for_each_entry(seg, &priv->segs, list) {
		s->v_address = ioremap_wc(seg->paddr, seg->sz);
		if (!s->v_address)
			goto ioremap_err;

		s->address = seg->paddr;
		s->size = seg->sz;
		s++;
		map_cnt++;
@@ -509,12 +506,6 @@ int pil_do_ramdump(struct pil_desc *desc,

	ret = do_elf_ramdump(ramdump_dev, ramdump_segs, count);

	s = ramdump_segs;
	list_for_each_entry(seg, &priv->segs, list) {
		iounmap(s->v_address);
		s++;
	}

	kfree(ramdump_segs);

	if (ret)
@@ -526,17 +517,6 @@ int pil_do_ramdump(struct pil_desc *desc,
				(priv->region_end - priv->region_start));

	return ret;

ioremap_err:
	/* Undo all the previous mappings */
	s = ramdump_segs;
	while (map_cnt--) {
		iounmap(s->v_address);
		s++;
	}

	kfree(ramdump_segs);
	return -ENOMEM;
}
EXPORT_SYMBOL(pil_do_ramdump);

+38 −5
Original line number Diff line number Diff line
@@ -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/of.h>
@@ -59,6 +60,8 @@ struct ramdump_device {
	size_t elfcore_size;
	char *elfcore_buf;
	bool complete_ramdump;
	bool abort_ramdump;
	struct srcu_struct rd_srcu;
};

static int ramdump_open(struct inode *inode, struct file *filep)
@@ -158,15 +161,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);
@@ -178,9 +192,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);
@@ -197,9 +213,7 @@ static ssize_t ramdump_read(struct file *filep, char __user *buf, size_t count,
	copy_size = min_t(size_t, count, (size_t)MAX_IOREMAP_SIZE);
	copy_size = min_t(unsigned long, (unsigned long)copy_size, data_left);

	device_mem = (void __iomem *) vaddr;
	origdevice_mem = device_mem;

	device_mem = vaddr ? : ioremap_wc(addr, copy_size);
	if (device_mem == NULL) {
		pr_err("Ramdump(%s): Virtual addr is NULL:addr %lx, size %zd\n",
			rd_dev->name, addr, copy_size);
@@ -208,6 +222,8 @@ static ssize_t ramdump_read(struct file *filep, char __user *buf, size_t count,
		goto ramdump_done;
	}

	origdevice_mem = device_mem;

	alignbuf = kzalloc(copy_size, GFP_KERNEL);
	if (!alignbuf) {
		rd_dev->ramdump_status = -1;
@@ -252,9 +268,12 @@ static ssize_t ramdump_read(struct file *filep, char __user *buf, size_t count,
	pr_debug("Ramdump(%s): Read %zd bytes from address %lx.\n",
			rd_dev->name, copy_size, addr);

	srcu_read_unlock(&rd_dev->rd_srcu, srcu_idx);

	return *pos - orig_pos;

ramdump_done:
	srcu_read_unlock(&rd_dev->rd_srcu, srcu_idx);
	kfree(finalbuf);
	*pos = 0;
	reset_ramdump_entry(entry);
@@ -361,6 +380,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);
@@ -373,6 +393,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:
@@ -393,6 +414,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);
}
@@ -473,6 +495,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);
@@ -489,6 +512,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;

@@ -602,6 +630,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);
@@ -618,6 +647,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;
	}