162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright(c) 2014 Intel Mobile Communications GmbH
462306a36Sopenharmony_ci * Copyright(c) 2015 Intel Deutschland GmbH
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Author: Johannes Berg <johannes@sipsolutions.net>
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci#include <linux/module.h>
962306a36Sopenharmony_ci#include <linux/device.h>
1062306a36Sopenharmony_ci#include <linux/devcoredump.h>
1162306a36Sopenharmony_ci#include <linux/list.h>
1262306a36Sopenharmony_ci#include <linux/slab.h>
1362306a36Sopenharmony_ci#include <linux/fs.h>
1462306a36Sopenharmony_ci#include <linux/workqueue.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_cistatic struct class devcd_class;
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci/* global disable flag, for security purposes */
1962306a36Sopenharmony_cistatic bool devcd_disabled;
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci/* if data isn't read by userspace after 5 minutes then delete it */
2262306a36Sopenharmony_ci#define DEVCD_TIMEOUT	(HZ * 60 * 5)
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_cistruct devcd_entry {
2562306a36Sopenharmony_ci	struct device devcd_dev;
2662306a36Sopenharmony_ci	void *data;
2762306a36Sopenharmony_ci	size_t datalen;
2862306a36Sopenharmony_ci	/*
2962306a36Sopenharmony_ci	 * Here, mutex is required to serialize the calls to del_wk work between
3062306a36Sopenharmony_ci	 * user/kernel space which happens when devcd is added with device_add()
3162306a36Sopenharmony_ci	 * and that sends uevent to user space. User space reads the uevents,
3262306a36Sopenharmony_ci	 * and calls to devcd_data_write() which try to modify the work which is
3362306a36Sopenharmony_ci	 * not even initialized/queued from devcoredump.
3462306a36Sopenharmony_ci	 *
3562306a36Sopenharmony_ci	 *
3662306a36Sopenharmony_ci	 *
3762306a36Sopenharmony_ci	 *        cpu0(X)                                 cpu1(Y)
3862306a36Sopenharmony_ci	 *
3962306a36Sopenharmony_ci	 *        dev_coredump() uevent sent to user space
4062306a36Sopenharmony_ci	 *        device_add()  ======================> user space process Y reads the
4162306a36Sopenharmony_ci	 *                                              uevents writes to devcd fd
4262306a36Sopenharmony_ci	 *                                              which results into writes to
4362306a36Sopenharmony_ci	 *
4462306a36Sopenharmony_ci	 *                                             devcd_data_write()
4562306a36Sopenharmony_ci	 *                                               mod_delayed_work()
4662306a36Sopenharmony_ci	 *                                                 try_to_grab_pending()
4762306a36Sopenharmony_ci	 *                                                   del_timer()
4862306a36Sopenharmony_ci	 *                                                     debug_assert_init()
4962306a36Sopenharmony_ci	 *       INIT_DELAYED_WORK()
5062306a36Sopenharmony_ci	 *       schedule_delayed_work()
5162306a36Sopenharmony_ci	 *
5262306a36Sopenharmony_ci	 *
5362306a36Sopenharmony_ci	 * Also, mutex alone would not be enough to avoid scheduling of
5462306a36Sopenharmony_ci	 * del_wk work after it get flush from a call to devcd_free()
5562306a36Sopenharmony_ci	 * mentioned as below.
5662306a36Sopenharmony_ci	 *
5762306a36Sopenharmony_ci	 *	disabled_store()
5862306a36Sopenharmony_ci	 *        devcd_free()
5962306a36Sopenharmony_ci	 *          mutex_lock()             devcd_data_write()
6062306a36Sopenharmony_ci	 *          flush_delayed_work()
6162306a36Sopenharmony_ci	 *          mutex_unlock()
6262306a36Sopenharmony_ci	 *                                   mutex_lock()
6362306a36Sopenharmony_ci	 *                                   mod_delayed_work()
6462306a36Sopenharmony_ci	 *                                   mutex_unlock()
6562306a36Sopenharmony_ci	 * So, delete_work flag is required.
6662306a36Sopenharmony_ci	 */
6762306a36Sopenharmony_ci	struct mutex mutex;
6862306a36Sopenharmony_ci	bool delete_work;
6962306a36Sopenharmony_ci	struct module *owner;
7062306a36Sopenharmony_ci	ssize_t (*read)(char *buffer, loff_t offset, size_t count,
7162306a36Sopenharmony_ci			void *data, size_t datalen);
7262306a36Sopenharmony_ci	void (*free)(void *data);
7362306a36Sopenharmony_ci	struct delayed_work del_wk;
7462306a36Sopenharmony_ci	struct device *failing_dev;
7562306a36Sopenharmony_ci};
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_cistatic struct devcd_entry *dev_to_devcd(struct device *dev)
7862306a36Sopenharmony_ci{
7962306a36Sopenharmony_ci	return container_of(dev, struct devcd_entry, devcd_dev);
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cistatic void devcd_dev_release(struct device *dev)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	struct devcd_entry *devcd = dev_to_devcd(dev);
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	devcd->free(devcd->data);
8762306a36Sopenharmony_ci	module_put(devcd->owner);
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	/*
9062306a36Sopenharmony_ci	 * this seems racy, but I don't see a notifier or such on
9162306a36Sopenharmony_ci	 * a struct device to know when it goes away?
9262306a36Sopenharmony_ci	 */
9362306a36Sopenharmony_ci	if (devcd->failing_dev->kobj.sd)
9462306a36Sopenharmony_ci		sysfs_delete_link(&devcd->failing_dev->kobj, &dev->kobj,
9562306a36Sopenharmony_ci				  "devcoredump");
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	put_device(devcd->failing_dev);
9862306a36Sopenharmony_ci	kfree(devcd);
9962306a36Sopenharmony_ci}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_cistatic void devcd_del(struct work_struct *wk)
10262306a36Sopenharmony_ci{
10362306a36Sopenharmony_ci	struct devcd_entry *devcd;
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	devcd = container_of(wk, struct devcd_entry, del_wk.work);
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	device_del(&devcd->devcd_dev);
10862306a36Sopenharmony_ci	put_device(&devcd->devcd_dev);
10962306a36Sopenharmony_ci}
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_cistatic ssize_t devcd_data_read(struct file *filp, struct kobject *kobj,
11262306a36Sopenharmony_ci			       struct bin_attribute *bin_attr,
11362306a36Sopenharmony_ci			       char *buffer, loff_t offset, size_t count)
11462306a36Sopenharmony_ci{
11562306a36Sopenharmony_ci	struct device *dev = kobj_to_dev(kobj);
11662306a36Sopenharmony_ci	struct devcd_entry *devcd = dev_to_devcd(dev);
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	return devcd->read(buffer, offset, count, devcd->data, devcd->datalen);
11962306a36Sopenharmony_ci}
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_cistatic ssize_t devcd_data_write(struct file *filp, struct kobject *kobj,
12262306a36Sopenharmony_ci				struct bin_attribute *bin_attr,
12362306a36Sopenharmony_ci				char *buffer, loff_t offset, size_t count)
12462306a36Sopenharmony_ci{
12562306a36Sopenharmony_ci	struct device *dev = kobj_to_dev(kobj);
12662306a36Sopenharmony_ci	struct devcd_entry *devcd = dev_to_devcd(dev);
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci	mutex_lock(&devcd->mutex);
12962306a36Sopenharmony_ci	if (!devcd->delete_work) {
13062306a36Sopenharmony_ci		devcd->delete_work = true;
13162306a36Sopenharmony_ci		mod_delayed_work(system_wq, &devcd->del_wk, 0);
13262306a36Sopenharmony_ci	}
13362306a36Sopenharmony_ci	mutex_unlock(&devcd->mutex);
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	return count;
13662306a36Sopenharmony_ci}
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_cistatic struct bin_attribute devcd_attr_data = {
13962306a36Sopenharmony_ci	.attr = { .name = "data", .mode = S_IRUSR | S_IWUSR, },
14062306a36Sopenharmony_ci	.size = 0,
14162306a36Sopenharmony_ci	.read = devcd_data_read,
14262306a36Sopenharmony_ci	.write = devcd_data_write,
14362306a36Sopenharmony_ci};
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_cistatic struct bin_attribute *devcd_dev_bin_attrs[] = {
14662306a36Sopenharmony_ci	&devcd_attr_data, NULL,
14762306a36Sopenharmony_ci};
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_cistatic const struct attribute_group devcd_dev_group = {
15062306a36Sopenharmony_ci	.bin_attrs = devcd_dev_bin_attrs,
15162306a36Sopenharmony_ci};
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_cistatic const struct attribute_group *devcd_dev_groups[] = {
15462306a36Sopenharmony_ci	&devcd_dev_group, NULL,
15562306a36Sopenharmony_ci};
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_cistatic int devcd_free(struct device *dev, void *data)
15862306a36Sopenharmony_ci{
15962306a36Sopenharmony_ci	struct devcd_entry *devcd = dev_to_devcd(dev);
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	mutex_lock(&devcd->mutex);
16262306a36Sopenharmony_ci	if (!devcd->delete_work)
16362306a36Sopenharmony_ci		devcd->delete_work = true;
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	flush_delayed_work(&devcd->del_wk);
16662306a36Sopenharmony_ci	mutex_unlock(&devcd->mutex);
16762306a36Sopenharmony_ci	return 0;
16862306a36Sopenharmony_ci}
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_cistatic ssize_t disabled_show(const struct class *class, const struct class_attribute *attr,
17162306a36Sopenharmony_ci			     char *buf)
17262306a36Sopenharmony_ci{
17362306a36Sopenharmony_ci	return sysfs_emit(buf, "%d\n", devcd_disabled);
17462306a36Sopenharmony_ci}
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci/*
17762306a36Sopenharmony_ci *
17862306a36Sopenharmony_ci *	disabled_store()                                	worker()
17962306a36Sopenharmony_ci *	 class_for_each_device(&devcd_class,
18062306a36Sopenharmony_ci *		NULL, NULL, devcd_free)
18162306a36Sopenharmony_ci *         ...
18262306a36Sopenharmony_ci *         ...
18362306a36Sopenharmony_ci *	   while ((dev = class_dev_iter_next(&iter))
18462306a36Sopenharmony_ci *                                                             devcd_del()
18562306a36Sopenharmony_ci *                                                               device_del()
18662306a36Sopenharmony_ci *                                                                 put_device() <- last reference
18762306a36Sopenharmony_ci *             error = fn(dev, data)                           devcd_dev_release()
18862306a36Sopenharmony_ci *             devcd_free(dev, data)                           kfree(devcd)
18962306a36Sopenharmony_ci *             mutex_lock(&devcd->mutex);
19062306a36Sopenharmony_ci *
19162306a36Sopenharmony_ci *
19262306a36Sopenharmony_ci * In the above diagram, It looks like disabled_store() would be racing with parallely
19362306a36Sopenharmony_ci * running devcd_del() and result in memory abort while acquiring devcd->mutex which
19462306a36Sopenharmony_ci * is called after kfree of devcd memory  after dropping its last reference with
19562306a36Sopenharmony_ci * put_device(). However, this will not happens as fn(dev, data) runs
19662306a36Sopenharmony_ci * with its own reference to device via klist_node so it is not its last reference.
19762306a36Sopenharmony_ci * so, above situation would not occur.
19862306a36Sopenharmony_ci */
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_cistatic ssize_t disabled_store(const struct class *class, const struct class_attribute *attr,
20162306a36Sopenharmony_ci			      const char *buf, size_t count)
20262306a36Sopenharmony_ci{
20362306a36Sopenharmony_ci	long tmp = simple_strtol(buf, NULL, 10);
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	/*
20662306a36Sopenharmony_ci	 * This essentially makes the attribute write-once, since you can't
20762306a36Sopenharmony_ci	 * go back to not having it disabled. This is intentional, it serves
20862306a36Sopenharmony_ci	 * as a system lockdown feature.
20962306a36Sopenharmony_ci	 */
21062306a36Sopenharmony_ci	if (tmp != 1)
21162306a36Sopenharmony_ci		return -EINVAL;
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci	devcd_disabled = true;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	class_for_each_device(&devcd_class, NULL, NULL, devcd_free);
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	return count;
21862306a36Sopenharmony_ci}
21962306a36Sopenharmony_cistatic CLASS_ATTR_RW(disabled);
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_cistatic struct attribute *devcd_class_attrs[] = {
22262306a36Sopenharmony_ci	&class_attr_disabled.attr,
22362306a36Sopenharmony_ci	NULL,
22462306a36Sopenharmony_ci};
22562306a36Sopenharmony_ciATTRIBUTE_GROUPS(devcd_class);
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_cistatic struct class devcd_class = {
22862306a36Sopenharmony_ci	.name		= "devcoredump",
22962306a36Sopenharmony_ci	.dev_release	= devcd_dev_release,
23062306a36Sopenharmony_ci	.dev_groups	= devcd_dev_groups,
23162306a36Sopenharmony_ci	.class_groups	= devcd_class_groups,
23262306a36Sopenharmony_ci};
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_cistatic ssize_t devcd_readv(char *buffer, loff_t offset, size_t count,
23562306a36Sopenharmony_ci			   void *data, size_t datalen)
23662306a36Sopenharmony_ci{
23762306a36Sopenharmony_ci	return memory_read_from_buffer(buffer, count, &offset, data, datalen);
23862306a36Sopenharmony_ci}
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_cistatic void devcd_freev(void *data)
24162306a36Sopenharmony_ci{
24262306a36Sopenharmony_ci	vfree(data);
24362306a36Sopenharmony_ci}
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci/**
24662306a36Sopenharmony_ci * dev_coredumpv - create device coredump with vmalloc data
24762306a36Sopenharmony_ci * @dev: the struct device for the crashed device
24862306a36Sopenharmony_ci * @data: vmalloc data containing the device coredump
24962306a36Sopenharmony_ci * @datalen: length of the data
25062306a36Sopenharmony_ci * @gfp: allocation flags
25162306a36Sopenharmony_ci *
25262306a36Sopenharmony_ci * This function takes ownership of the vmalloc'ed data and will free
25362306a36Sopenharmony_ci * it when it is no longer used. See dev_coredumpm() for more information.
25462306a36Sopenharmony_ci */
25562306a36Sopenharmony_civoid dev_coredumpv(struct device *dev, void *data, size_t datalen,
25662306a36Sopenharmony_ci		   gfp_t gfp)
25762306a36Sopenharmony_ci{
25862306a36Sopenharmony_ci	dev_coredumpm(dev, NULL, data, datalen, gfp, devcd_readv, devcd_freev);
25962306a36Sopenharmony_ci}
26062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(dev_coredumpv);
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_cistatic int devcd_match_failing(struct device *dev, const void *failing)
26362306a36Sopenharmony_ci{
26462306a36Sopenharmony_ci	struct devcd_entry *devcd = dev_to_devcd(dev);
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci	return devcd->failing_dev == failing;
26762306a36Sopenharmony_ci}
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci/**
27062306a36Sopenharmony_ci * devcd_free_sgtable - free all the memory of the given scatterlist table
27162306a36Sopenharmony_ci * (i.e. both pages and scatterlist instances)
27262306a36Sopenharmony_ci * NOTE: if two tables allocated with devcd_alloc_sgtable and then chained
27362306a36Sopenharmony_ci * using the sg_chain function then that function should be called only once
27462306a36Sopenharmony_ci * on the chained table
27562306a36Sopenharmony_ci * @data: pointer to sg_table to free
27662306a36Sopenharmony_ci */
27762306a36Sopenharmony_cistatic void devcd_free_sgtable(void *data)
27862306a36Sopenharmony_ci{
27962306a36Sopenharmony_ci	_devcd_free_sgtable(data);
28062306a36Sopenharmony_ci}
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci/**
28362306a36Sopenharmony_ci * devcd_read_from_sgtable - copy data from sg_table to a given buffer
28462306a36Sopenharmony_ci * and return the number of bytes read
28562306a36Sopenharmony_ci * @buffer: the buffer to copy the data to it
28662306a36Sopenharmony_ci * @buf_len: the length of the buffer
28762306a36Sopenharmony_ci * @data: the scatterlist table to copy from
28862306a36Sopenharmony_ci * @offset: start copy from @offset@ bytes from the head of the data
28962306a36Sopenharmony_ci *	in the given scatterlist
29062306a36Sopenharmony_ci * @data_len: the length of the data in the sg_table
29162306a36Sopenharmony_ci */
29262306a36Sopenharmony_cistatic ssize_t devcd_read_from_sgtable(char *buffer, loff_t offset,
29362306a36Sopenharmony_ci				       size_t buf_len, void *data,
29462306a36Sopenharmony_ci				       size_t data_len)
29562306a36Sopenharmony_ci{
29662306a36Sopenharmony_ci	struct scatterlist *table = data;
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci	if (offset > data_len)
29962306a36Sopenharmony_ci		return -EINVAL;
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci	if (offset + buf_len > data_len)
30262306a36Sopenharmony_ci		buf_len = data_len - offset;
30362306a36Sopenharmony_ci	return sg_pcopy_to_buffer(table, sg_nents(table), buffer, buf_len,
30462306a36Sopenharmony_ci				  offset);
30562306a36Sopenharmony_ci}
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci/**
30862306a36Sopenharmony_ci * dev_coredumpm - create device coredump with read/free methods
30962306a36Sopenharmony_ci * @dev: the struct device for the crashed device
31062306a36Sopenharmony_ci * @owner: the module that contains the read/free functions, use %THIS_MODULE
31162306a36Sopenharmony_ci * @data: data cookie for the @read/@free functions
31262306a36Sopenharmony_ci * @datalen: length of the data
31362306a36Sopenharmony_ci * @gfp: allocation flags
31462306a36Sopenharmony_ci * @read: function to read from the given buffer
31562306a36Sopenharmony_ci * @free: function to free the given buffer
31662306a36Sopenharmony_ci *
31762306a36Sopenharmony_ci * Creates a new device coredump for the given device. If a previous one hasn't
31862306a36Sopenharmony_ci * been read yet, the new coredump is discarded. The data lifetime is determined
31962306a36Sopenharmony_ci * by the device coredump framework and when it is no longer needed the @free
32062306a36Sopenharmony_ci * function will be called to free the data.
32162306a36Sopenharmony_ci */
32262306a36Sopenharmony_civoid dev_coredumpm(struct device *dev, struct module *owner,
32362306a36Sopenharmony_ci		   void *data, size_t datalen, gfp_t gfp,
32462306a36Sopenharmony_ci		   ssize_t (*read)(char *buffer, loff_t offset, size_t count,
32562306a36Sopenharmony_ci				   void *data, size_t datalen),
32662306a36Sopenharmony_ci		   void (*free)(void *data))
32762306a36Sopenharmony_ci{
32862306a36Sopenharmony_ci	static atomic_t devcd_count = ATOMIC_INIT(0);
32962306a36Sopenharmony_ci	struct devcd_entry *devcd;
33062306a36Sopenharmony_ci	struct device *existing;
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	if (devcd_disabled)
33362306a36Sopenharmony_ci		goto free;
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	existing = class_find_device(&devcd_class, NULL, dev,
33662306a36Sopenharmony_ci				     devcd_match_failing);
33762306a36Sopenharmony_ci	if (existing) {
33862306a36Sopenharmony_ci		put_device(existing);
33962306a36Sopenharmony_ci		goto free;
34062306a36Sopenharmony_ci	}
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci	if (!try_module_get(owner))
34362306a36Sopenharmony_ci		goto free;
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci	devcd = kzalloc(sizeof(*devcd), gfp);
34662306a36Sopenharmony_ci	if (!devcd)
34762306a36Sopenharmony_ci		goto put_module;
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	devcd->owner = owner;
35062306a36Sopenharmony_ci	devcd->data = data;
35162306a36Sopenharmony_ci	devcd->datalen = datalen;
35262306a36Sopenharmony_ci	devcd->read = read;
35362306a36Sopenharmony_ci	devcd->free = free;
35462306a36Sopenharmony_ci	devcd->failing_dev = get_device(dev);
35562306a36Sopenharmony_ci	devcd->delete_work = false;
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	mutex_init(&devcd->mutex);
35862306a36Sopenharmony_ci	device_initialize(&devcd->devcd_dev);
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	dev_set_name(&devcd->devcd_dev, "devcd%d",
36162306a36Sopenharmony_ci		     atomic_inc_return(&devcd_count));
36262306a36Sopenharmony_ci	devcd->devcd_dev.class = &devcd_class;
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	mutex_lock(&devcd->mutex);
36562306a36Sopenharmony_ci	dev_set_uevent_suppress(&devcd->devcd_dev, true);
36662306a36Sopenharmony_ci	if (device_add(&devcd->devcd_dev))
36762306a36Sopenharmony_ci		goto put_device;
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	/*
37062306a36Sopenharmony_ci	 * These should normally not fail, but there is no problem
37162306a36Sopenharmony_ci	 * continuing without the links, so just warn instead of
37262306a36Sopenharmony_ci	 * failing.
37362306a36Sopenharmony_ci	 */
37462306a36Sopenharmony_ci	if (sysfs_create_link(&devcd->devcd_dev.kobj, &dev->kobj,
37562306a36Sopenharmony_ci			      "failing_device") ||
37662306a36Sopenharmony_ci	    sysfs_create_link(&dev->kobj, &devcd->devcd_dev.kobj,
37762306a36Sopenharmony_ci		              "devcoredump"))
37862306a36Sopenharmony_ci		dev_warn(dev, "devcoredump create_link failed\n");
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	dev_set_uevent_suppress(&devcd->devcd_dev, false);
38162306a36Sopenharmony_ci	kobject_uevent(&devcd->devcd_dev.kobj, KOBJ_ADD);
38262306a36Sopenharmony_ci	INIT_DELAYED_WORK(&devcd->del_wk, devcd_del);
38362306a36Sopenharmony_ci	schedule_delayed_work(&devcd->del_wk, DEVCD_TIMEOUT);
38462306a36Sopenharmony_ci	mutex_unlock(&devcd->mutex);
38562306a36Sopenharmony_ci	return;
38662306a36Sopenharmony_ci put_device:
38762306a36Sopenharmony_ci	put_device(&devcd->devcd_dev);
38862306a36Sopenharmony_ci	mutex_unlock(&devcd->mutex);
38962306a36Sopenharmony_ci put_module:
39062306a36Sopenharmony_ci	module_put(owner);
39162306a36Sopenharmony_ci free:
39262306a36Sopenharmony_ci	free(data);
39362306a36Sopenharmony_ci}
39462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(dev_coredumpm);
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci/**
39762306a36Sopenharmony_ci * dev_coredumpsg - create device coredump that uses scatterlist as data
39862306a36Sopenharmony_ci * parameter
39962306a36Sopenharmony_ci * @dev: the struct device for the crashed device
40062306a36Sopenharmony_ci * @table: the dump data
40162306a36Sopenharmony_ci * @datalen: length of the data
40262306a36Sopenharmony_ci * @gfp: allocation flags
40362306a36Sopenharmony_ci *
40462306a36Sopenharmony_ci * Creates a new device coredump for the given device. If a previous one hasn't
40562306a36Sopenharmony_ci * been read yet, the new coredump is discarded. The data lifetime is determined
40662306a36Sopenharmony_ci * by the device coredump framework and when it is no longer needed
40762306a36Sopenharmony_ci * it will free the data.
40862306a36Sopenharmony_ci */
40962306a36Sopenharmony_civoid dev_coredumpsg(struct device *dev, struct scatterlist *table,
41062306a36Sopenharmony_ci		    size_t datalen, gfp_t gfp)
41162306a36Sopenharmony_ci{
41262306a36Sopenharmony_ci	dev_coredumpm(dev, NULL, table, datalen, gfp, devcd_read_from_sgtable,
41362306a36Sopenharmony_ci		      devcd_free_sgtable);
41462306a36Sopenharmony_ci}
41562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(dev_coredumpsg);
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_cistatic int __init devcoredump_init(void)
41862306a36Sopenharmony_ci{
41962306a36Sopenharmony_ci	return class_register(&devcd_class);
42062306a36Sopenharmony_ci}
42162306a36Sopenharmony_ci__initcall(devcoredump_init);
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_cistatic void __exit devcoredump_exit(void)
42462306a36Sopenharmony_ci{
42562306a36Sopenharmony_ci	class_for_each_device(&devcd_class, NULL, NULL, devcd_free);
42662306a36Sopenharmony_ci	class_unregister(&devcd_class);
42762306a36Sopenharmony_ci}
42862306a36Sopenharmony_ci__exitcall(devcoredump_exit);
429