--- /dev/null
+From 5d135c6a3e6cfb279e3fde493f856173d484d5e7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 21 Mar 2016 10:30:28 -0300
+Subject: drivers/media/media-devnode: clear private_data before put_device()
+
+From: Max Kellermann <max@duempel.org>
+
+commit bf244f665d76d20312c80524689b32a752888838 upstream.
+
+Callbacks invoked from put_device() may free the struct media_devnode
+pointer, so any cleanup needs to be done before put_device().
+
+Signed-off-by: Max Kellermann <max@duempel.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/media-devnode.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c
+index a8cb52dc8c4f..6c56aebd8db0 100644
+--- a/drivers/media/media-devnode.c
++++ b/drivers/media/media-devnode.c
+@@ -197,10 +197,11 @@ static int media_release(struct inode *inode, struct file *filp)
+ if (mdev->fops->release)
+ mdev->fops->release(filp);
+
++ filp->private_data = NULL;
++
+ /* decrease the refcount unconditionally since the release()
+ return value is ignored. */
+ put_device(&mdev->dev);
+- filp->private_data = NULL;
+ return 0;
+ }
+
+--
+2.25.1
+
--- /dev/null
+From 940eeed2adac118127c453aff2000fd6f02c021e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Jul 2016 19:57:06 -0700
+Subject: i2c-dev: don't get i2c adapter via i2c_dev
+
+From: viresh kumar <viresh.kumar@linaro.org>
+
+commit 5136ed4fcb05cd4981cc6034a11e66370ed84789 upstream.
+
+There is no code protecting i2c_dev to be freed after it is returned
+from i2c_dev_get_by_minor() and using it to access the value which we
+already have (minor) isn't safe really.
+
+Avoid using it and get the adapter directly from 'minor'.
+
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+Reviewed-by: Jean Delvare <jdelvare@suse.de>
+Tested-by: Jean Delvare <jdelvare@suse.de>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i2c/i2c-dev.c | 7 +------
+ 1 file changed, 1 insertion(+), 6 deletions(-)
+
+diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
+index e5cd307ebfc9..5543b49e2e05 100644
+--- a/drivers/i2c/i2c-dev.c
++++ b/drivers/i2c/i2c-dev.c
+@@ -492,13 +492,8 @@ static int i2cdev_open(struct inode *inode, struct file *file)
+ unsigned int minor = iminor(inode);
+ struct i2c_client *client;
+ struct i2c_adapter *adap;
+- struct i2c_dev *i2c_dev;
+-
+- i2c_dev = i2c_dev_get_by_minor(minor);
+- if (!i2c_dev)
+- return -ENODEV;
+
+- adap = i2c_get_adapter(i2c_dev->adap->nr);
++ adap = i2c_get_adapter(minor);
+ if (!adap)
+ return -ENODEV;
+
+--
+2.25.1
+
--- /dev/null
+From 108a1d68bee0b317808828d0f0d3354e45a411ad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 27 May 2016 13:13:01 +0200
+Subject: i2c: dev: don't start function name with 'return'
+
+From: Wolfram Sang <wsa@the-dreams.de>
+
+commit 72a71f869c95dc11b73f09fe18c593d4a0618c3f upstream.
+
+I stumbled multiple times over 'return_i2c_dev', especially before the
+actual 'return res'. It makes the code hard to read, so reanme the
+function to 'put_i2c_dev' which also better matches 'get_free_i2c_dev'.
+
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i2c/i2c-dev.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
+index 5fecc1d9e0a1..382c66d5a470 100644
+--- a/drivers/i2c/i2c-dev.c
++++ b/drivers/i2c/i2c-dev.c
+@@ -91,7 +91,7 @@ static struct i2c_dev *get_free_i2c_dev(struct i2c_adapter *adap)
+ return i2c_dev;
+ }
+
+-static void return_i2c_dev(struct i2c_dev *i2c_dev)
++static void put_i2c_dev(struct i2c_dev *i2c_dev)
+ {
+ spin_lock(&i2c_dev_list_lock);
+ list_del(&i2c_dev->list);
+@@ -582,7 +582,7 @@ static int i2cdev_attach_adapter(struct device *dev, void *dummy)
+ error:
+ cdev_del(&i2c_dev->cdev);
+ error_cdev:
+- return_i2c_dev(i2c_dev);
++ put_i2c_dev(i2c_dev);
+ return res;
+ }
+
+@@ -599,7 +599,7 @@ static int i2cdev_detach_adapter(struct device *dev, void *dummy)
+ if (!i2c_dev) /* attach_adapter must have failed */
+ return 0;
+
+- return_i2c_dev(i2c_dev);
++ put_i2c_dev(i2c_dev);
+ device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
+ cdev_del(&i2c_dev->cdev);
+
+--
+2.25.1
+
--- /dev/null
+From 1329cc3082b4fe3e34bbb839a4c8bfb22084729e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 11 Oct 2019 23:00:14 +0800
+Subject: i2c: dev: Fix the race between the release of i2c_dev and cdev
+
+From: Kevin Hao <haokexin@gmail.com>
+
+commit 1413ef638abae4ab5621901cf4d8ef08a4a48ba6 upstream.
+
+The struct cdev is embedded in the struct i2c_dev. In the current code,
+we would free the i2c_dev struct directly in put_i2c_dev(), but the
+cdev is manged by a kobject, and the release of it is not predictable.
+So it is very possible that the i2c_dev is freed before the cdev is
+entirely released. We can easily get the following call trace with
+CONFIG_DEBUG_KOBJECT_RELEASE and CONFIG_DEBUG_OBJECTS_TIMERS enabled.
+ ODEBUG: free active (active state 0) object type: timer_list hint: delayed_work_timer_fn+0x0/0x38
+ WARNING: CPU: 19 PID: 1 at lib/debugobjects.c:325 debug_print_object+0xb0/0xf0
+ Modules linked in:
+ CPU: 19 PID: 1 Comm: swapper/0 Tainted: G W 5.2.20-yocto-standard+ #120
+ Hardware name: Marvell OcteonTX CN96XX board (DT)
+ pstate: 80c00089 (Nzcv daIf +PAN +UAO)
+ pc : debug_print_object+0xb0/0xf0
+ lr : debug_print_object+0xb0/0xf0
+ sp : ffff00001292f7d0
+ x29: ffff00001292f7d0 x28: ffff800b82151788
+ x27: 0000000000000001 x26: ffff800b892c0000
+ x25: ffff0000124a2558 x24: 0000000000000000
+ x23: ffff00001107a1d8 x22: ffff0000116b5088
+ x21: ffff800bdc6afca8 x20: ffff000012471ae8
+ x19: ffff00001168f2c8 x18: 0000000000000010
+ x17: 00000000fd6f304b x16: 00000000ee79de43
+ x15: ffff800bc0e80568 x14: 79616c6564203a74
+ x13: 6e6968207473696c x12: 5f72656d6974203a
+ x11: ffff0000113f0018 x10: 0000000000000000
+ x9 : 000000000000001f x8 : 0000000000000000
+ x7 : ffff0000101294cc x6 : 0000000000000000
+ x5 : 0000000000000000 x4 : 0000000000000001
+ x3 : 00000000ffffffff x2 : 0000000000000000
+ x1 : 387fc15c8ec0f200 x0 : 0000000000000000
+ Call trace:
+ debug_print_object+0xb0/0xf0
+ __debug_check_no_obj_freed+0x19c/0x228
+ debug_check_no_obj_freed+0x1c/0x28
+ kfree+0x250/0x440
+ put_i2c_dev+0x68/0x78
+ i2cdev_detach_adapter+0x60/0xc8
+ i2cdev_notifier_call+0x3c/0x70
+ notifier_call_chain+0x8c/0xe8
+ blocking_notifier_call_chain+0x64/0x88
+ device_del+0x74/0x380
+ device_unregister+0x54/0x78
+ i2c_del_adapter+0x278/0x2d0
+ unittest_i2c_bus_remove+0x3c/0x80
+ platform_drv_remove+0x30/0x50
+ device_release_driver_internal+0xf4/0x1c0
+ driver_detach+0x58/0xa0
+ bus_remove_driver+0x84/0xd8
+ driver_unregister+0x34/0x60
+ platform_driver_unregister+0x20/0x30
+ of_unittest_overlay+0x8d4/0xbe0
+ of_unittest+0xae8/0xb3c
+ do_one_initcall+0xac/0x450
+ do_initcall_level+0x208/0x224
+ kernel_init_freeable+0x2d8/0x36c
+ kernel_init+0x18/0x108
+ ret_from_fork+0x10/0x1c
+ irq event stamp: 3934661
+ hardirqs last enabled at (3934661): [<ffff00001009fa04>] debug_exception_exit+0x4c/0x58
+ hardirqs last disabled at (3934660): [<ffff00001009fb14>] debug_exception_enter+0xa4/0xe0
+ softirqs last enabled at (3934654): [<ffff000010081d94>] __do_softirq+0x46c/0x628
+ softirqs last disabled at (3934649): [<ffff0000100b4a1c>] irq_exit+0x104/0x118
+
+This is a common issue when using cdev embedded in a struct.
+Fortunately, we already have a mechanism to solve this kind of issue.
+Please see commit 233ed09d7fda ("chardev: add helper function to
+register char devs with a struct device") for more detail.
+
+In this patch, we choose to embed the struct device into the i2c_dev,
+and use the API provided by the commit 233ed09d7fda to make sure that
+the release of i2c_dev and cdev are in sequence.
+
+Signed-off-by: Kevin Hao <haokexin@gmail.com>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i2c/i2c-dev.c | 48 +++++++++++++++++++++++--------------------
+ 1 file changed, 26 insertions(+), 22 deletions(-)
+
+diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
+index 5543b49e2e05..7584f292e2fd 100644
+--- a/drivers/i2c/i2c-dev.c
++++ b/drivers/i2c/i2c-dev.c
+@@ -47,7 +47,7 @@
+ struct i2c_dev {
+ struct list_head list;
+ struct i2c_adapter *adap;
+- struct device *dev;
++ struct device dev;
+ struct cdev cdev;
+ };
+
+@@ -91,12 +91,14 @@ static struct i2c_dev *get_free_i2c_dev(struct i2c_adapter *adap)
+ return i2c_dev;
+ }
+
+-static void put_i2c_dev(struct i2c_dev *i2c_dev)
++static void put_i2c_dev(struct i2c_dev *i2c_dev, bool del_cdev)
+ {
+ spin_lock(&i2c_dev_list_lock);
+ list_del(&i2c_dev->list);
+ spin_unlock(&i2c_dev_list_lock);
+- kfree(i2c_dev);
++ if (del_cdev)
++ cdev_device_del(&i2c_dev->cdev, &i2c_dev->dev);
++ put_device(&i2c_dev->dev);
+ }
+
+ static ssize_t name_show(struct device *dev,
+@@ -542,6 +544,14 @@ static const struct file_operations i2cdev_fops = {
+
+ static struct class *i2c_dev_class;
+
++static void i2cdev_dev_release(struct device *dev)
++{
++ struct i2c_dev *i2c_dev;
++
++ i2c_dev = container_of(dev, struct i2c_dev, dev);
++ kfree(i2c_dev);
++}
++
+ static int i2cdev_attach_adapter(struct device *dev, void *dummy)
+ {
+ struct i2c_adapter *adap;
+@@ -558,27 +568,23 @@ static int i2cdev_attach_adapter(struct device *dev, void *dummy)
+
+ cdev_init(&i2c_dev->cdev, &i2cdev_fops);
+ i2c_dev->cdev.owner = THIS_MODULE;
+- res = cdev_add(&i2c_dev->cdev, MKDEV(I2C_MAJOR, adap->nr), 1);
+- if (res)
+- goto error_cdev;
+-
+- /* register this i2c device with the driver core */
+- i2c_dev->dev = device_create(i2c_dev_class, &adap->dev,
+- MKDEV(I2C_MAJOR, adap->nr), NULL,
+- "i2c-%d", adap->nr);
+- if (IS_ERR(i2c_dev->dev)) {
+- res = PTR_ERR(i2c_dev->dev);
+- goto error;
++
++ device_initialize(&i2c_dev->dev);
++ i2c_dev->dev.devt = MKDEV(I2C_MAJOR, adap->nr);
++ i2c_dev->dev.class = i2c_dev_class;
++ i2c_dev->dev.parent = &adap->dev;
++ i2c_dev->dev.release = i2cdev_dev_release;
++ dev_set_name(&i2c_dev->dev, "i2c-%d", adap->nr);
++
++ res = cdev_device_add(&i2c_dev->cdev, &i2c_dev->dev);
++ if (res) {
++ put_i2c_dev(i2c_dev, false);
++ return res;
+ }
+
+ pr_debug("i2c-dev: adapter [%s] registered as minor %d\n",
+ adap->name, adap->nr);
+ return 0;
+-error:
+- cdev_del(&i2c_dev->cdev);
+-error_cdev:
+- put_i2c_dev(i2c_dev);
+- return res;
+ }
+
+ static int i2cdev_detach_adapter(struct device *dev, void *dummy)
+@@ -594,9 +600,7 @@ static int i2cdev_detach_adapter(struct device *dev, void *dummy)
+ if (!i2c_dev) /* attach_adapter must have failed */
+ return 0;
+
+- cdev_del(&i2c_dev->cdev);
+- put_i2c_dev(i2c_dev);
+- device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
++ put_i2c_dev(i2c_dev, true);
+
+ pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name);
+ return 0;
+--
+2.25.1
+
--- /dev/null
+From 528303832f25e979851e632cb34b24577b8d43b3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 May 2016 15:45:43 -0300
+Subject: i2c: dev: switch from register_chrdev to cdev API
+
+From: Erico Nunes <erico.nunes@datacom.ind.br>
+
+commit d6760b14d4a1243f918d983bba1e35c5a5cd5a6d upstream.
+
+i2c-dev had never moved away from the older register_chrdev interface to
+implement its char device registration. The register_chrdev API has the
+limitation of enabling only up to 256 i2c-dev busses to exist.
+
+Large platforms with lots of i2c devices (i.e. pluggable transceivers)
+with dedicated busses may have to exceed that limit.
+In particular, there are also platforms making use of the i2c bus
+multiplexing API, which instantiates a virtual bus for each possible
+multiplexed selection.
+
+This patch removes the register_chrdev usage and replaces it with the
+less old cdev API, which takes away the 256 i2c-dev bus limitation.
+It should not have any other impact for i2c bus drivers or user space.
+
+This patch has been tested on qemu x86 and qemu powerpc platforms with
+the aid of a module which adds and removes 5000 virtual i2c busses, as
+well as validated on an existing powerpc hardware platform which makes
+use of the i2c bus multiplexing API.
+i2c-dev busses with device minor numbers larger than 256 have also been
+validated to work with the existing i2c-tools.
+
+Signed-off-by: Erico Nunes <erico.nunes@datacom.ind.br>
+[wsa: kept includes sorted]
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+[bwh: Backported to 4.4: adjust context]
+Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i2c/i2c-dev.c | 19 +++++++++++++++----
+ 1 file changed, 15 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
+index e56b774e7cf9..5fecc1d9e0a1 100644
+--- a/drivers/i2c/i2c-dev.c
++++ b/drivers/i2c/i2c-dev.c
+@@ -22,6 +22,7 @@
+
+ /* The I2C_RDWR ioctl code is written by Kolja Waschk <waschk@telos.de> */
+
++#include <linux/cdev.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/device.h>
+@@ -47,9 +48,10 @@ struct i2c_dev {
+ struct list_head list;
+ struct i2c_adapter *adap;
+ struct device *dev;
++ struct cdev cdev;
+ };
+
+-#define I2C_MINORS 256
++#define I2C_MINORS MINORMASK
+ static LIST_HEAD(i2c_dev_list);
+ static DEFINE_SPINLOCK(i2c_dev_list_lock);
+
+@@ -559,6 +561,12 @@ static int i2cdev_attach_adapter(struct device *dev, void *dummy)
+ if (IS_ERR(i2c_dev))
+ return PTR_ERR(i2c_dev);
+
++ cdev_init(&i2c_dev->cdev, &i2cdev_fops);
++ i2c_dev->cdev.owner = THIS_MODULE;
++ res = cdev_add(&i2c_dev->cdev, MKDEV(I2C_MAJOR, adap->nr), 1);
++ if (res)
++ goto error_cdev;
++
+ /* register this i2c device with the driver core */
+ i2c_dev->dev = device_create(i2c_dev_class, &adap->dev,
+ MKDEV(I2C_MAJOR, adap->nr), NULL,
+@@ -572,6 +580,8 @@ static int i2cdev_attach_adapter(struct device *dev, void *dummy)
+ adap->name, adap->nr);
+ return 0;
+ error:
++ cdev_del(&i2c_dev->cdev);
++error_cdev:
+ return_i2c_dev(i2c_dev);
+ return res;
+ }
+@@ -591,6 +601,7 @@ static int i2cdev_detach_adapter(struct device *dev, void *dummy)
+
+ return_i2c_dev(i2c_dev);
+ device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
++ cdev_del(&i2c_dev->cdev);
+
+ pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name);
+ return 0;
+@@ -627,7 +638,7 @@ static int __init i2c_dev_init(void)
+
+ printk(KERN_INFO "i2c /dev entries driver\n");
+
+- res = register_chrdev(I2C_MAJOR, "i2c", &i2cdev_fops);
++ res = register_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS, "i2c");
+ if (res)
+ goto out;
+
+@@ -651,7 +662,7 @@ static int __init i2c_dev_init(void)
+ out_unreg_class:
+ class_destroy(i2c_dev_class);
+ out_unreg_chrdev:
+- unregister_chrdev(I2C_MAJOR, "i2c");
++ unregister_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS);
+ out:
+ printk(KERN_ERR "%s: Driver Initialisation failed\n", __FILE__);
+ return res;
+@@ -662,7 +673,7 @@ static void __exit i2c_dev_exit(void)
+ bus_unregister_notifier(&i2c_bus_type, &i2cdev_notifier);
+ i2c_for_each_dev(NULL, i2cdev_detach_adapter);
+ class_destroy(i2c_dev_class);
+- unregister_chrdev(I2C_MAJOR, "i2c");
++ unregister_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS);
+ }
+
+ MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and "
+--
+2.25.1
+
--- /dev/null
+From 7d36e754a433001e08a1339949e5192be29d966f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 28 May 2016 08:01:46 +0300
+Subject: i2c: dev: use after free in detach
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+commit e6be18f6d62c1d3b331ae020b76a29c2ccf6b0bf upstream.
+
+The call to put_i2c_dev() frees "i2c_dev" so there is a use after
+free when we call cdev_del(&i2c_dev->cdev).
+
+Fixes: d6760b14d4a1 ('i2c: dev: switch from register_chrdev to cdev API')
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i2c/i2c-dev.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
+index 382c66d5a470..e5cd307ebfc9 100644
+--- a/drivers/i2c/i2c-dev.c
++++ b/drivers/i2c/i2c-dev.c
+@@ -599,9 +599,9 @@ static int i2cdev_detach_adapter(struct device *dev, void *dummy)
+ if (!i2c_dev) /* attach_adapter must have failed */
+ return 0;
+
++ cdev_del(&i2c_dev->cdev);
+ put_i2c_dev(i2c_dev);
+ device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
+- cdev_del(&i2c_dev->cdev);
+
+ pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name);
+ return 0;
+--
+2.25.1
+
--- /dev/null
+From 82b2a743620ff7f9f16ee889a400753dd2ea74e5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 Apr 2016 19:28:26 -0300
+Subject: media-device: dynamically allocate struct media_devnode
+
+From: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+
+commit a087ce704b802becbb4b0f2a20f2cb3f6911802e upstream.
+
+struct media_devnode is currently embedded at struct media_device.
+
+While this works fine during normal usage, it leads to a race
+condition during devnode unregister. the problem is that drivers
+assume that, after calling media_device_unregister(), the struct
+that contains media_device can be freed. This is not true, as it
+can't be freed until userspace closes all opened /dev/media devnodes.
+
+In other words, if the media devnode is still open, and media_device
+gets freed, any call to an ioctl will make the core to try to access
+struct media_device, with will cause an use-after-free and even GPF.
+
+Fix this by dynamically allocating the struct media_devnode and only
+freeing it when it is safe.
+
+Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+[bwh: Backported to 4.4:
+ - Drop change in au0828
+ - Include <linux/slab.h> in media-device.c
+ - Adjust context]
+Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/media-device.c | 40 +++++++++++++++++++++---------
+ drivers/media/media-devnode.c | 8 +++++-
+ drivers/media/usb/uvc/uvc_driver.c | 2 +-
+ include/media/media-device.h | 5 +---
+ include/media/media-devnode.h | 10 +++++++-
+ 5 files changed, 46 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
+index 7b39440192d6..fb018fe1a8f7 100644
+--- a/drivers/media/media-device.c
++++ b/drivers/media/media-device.c
+@@ -24,6 +24,7 @@
+ #include <linux/export.h>
+ #include <linux/ioctl.h>
+ #include <linux/media.h>
++#include <linux/slab.h>
+ #include <linux/types.h>
+
+ #include <media/media-device.h>
+@@ -234,7 +235,7 @@ static long media_device_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+ {
+ struct media_devnode *devnode = media_devnode_data(filp);
+- struct media_device *dev = to_media_device(devnode);
++ struct media_device *dev = devnode->media_dev;
+ long ret;
+
+ switch (cmd) {
+@@ -303,7 +304,7 @@ static long media_device_compat_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+ {
+ struct media_devnode *devnode = media_devnode_data(filp);
+- struct media_device *dev = to_media_device(devnode);
++ struct media_device *dev = devnode->media_dev;
+ long ret;
+
+ switch (cmd) {
+@@ -344,7 +345,8 @@ static const struct media_file_operations media_device_fops = {
+ static ssize_t show_model(struct device *cd,
+ struct device_attribute *attr, char *buf)
+ {
+- struct media_device *mdev = to_media_device(to_media_devnode(cd));
++ struct media_devnode *devnode = to_media_devnode(cd);
++ struct media_device *mdev = devnode->media_dev;
+
+ return sprintf(buf, "%.*s\n", (int)sizeof(mdev->model), mdev->model);
+ }
+@@ -372,6 +374,7 @@ static void media_device_release(struct media_devnode *mdev)
+ int __must_check __media_device_register(struct media_device *mdev,
+ struct module *owner)
+ {
++ struct media_devnode *devnode;
+ int ret;
+
+ if (WARN_ON(mdev->dev == NULL || mdev->model[0] == 0))
+@@ -382,17 +385,27 @@ int __must_check __media_device_register(struct media_device *mdev,
+ spin_lock_init(&mdev->lock);
+ mutex_init(&mdev->graph_mutex);
+
++ devnode = kzalloc(sizeof(*devnode), GFP_KERNEL);
++ if (!devnode)
++ return -ENOMEM;
++
+ /* Register the device node. */
+- mdev->devnode.fops = &media_device_fops;
+- mdev->devnode.parent = mdev->dev;
+- mdev->devnode.release = media_device_release;
+- ret = media_devnode_register(&mdev->devnode, owner);
+- if (ret < 0)
++ mdev->devnode = devnode;
++ devnode->fops = &media_device_fops;
++ devnode->parent = mdev->dev;
++ devnode->release = media_device_release;
++ ret = media_devnode_register(mdev, devnode, owner);
++ if (ret < 0) {
++ mdev->devnode = NULL;
++ kfree(devnode);
+ return ret;
++ }
+
+- ret = device_create_file(&mdev->devnode.dev, &dev_attr_model);
++ ret = device_create_file(&devnode->dev, &dev_attr_model);
+ if (ret < 0) {
+- media_devnode_unregister(&mdev->devnode);
++ mdev->devnode = NULL;
++ media_devnode_unregister(devnode);
++ kfree(devnode);
+ return ret;
+ }
+
+@@ -413,8 +426,11 @@ void media_device_unregister(struct media_device *mdev)
+ list_for_each_entry_safe(entity, next, &mdev->entities, list)
+ media_device_unregister_entity(entity);
+
+- device_remove_file(&mdev->devnode.dev, &dev_attr_model);
+- media_devnode_unregister(&mdev->devnode);
++ /* Check if mdev devnode was registered */
++ if (media_devnode_is_registered(mdev->devnode)) {
++ device_remove_file(&mdev->devnode->dev, &dev_attr_model);
++ media_devnode_unregister(mdev->devnode);
++ }
+ }
+ EXPORT_SYMBOL_GPL(media_device_unregister);
+
+diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c
+index 98211c570e11..000efb17b95b 100644
+--- a/drivers/media/media-devnode.c
++++ b/drivers/media/media-devnode.c
+@@ -44,6 +44,7 @@
+ #include <linux/uaccess.h>
+
+ #include <media/media-devnode.h>
++#include <media/media-device.h>
+
+ #define MEDIA_NUM_DEVICES 256
+ #define MEDIA_NAME "media"
+@@ -74,6 +75,8 @@ static void media_devnode_release(struct device *cd)
+ /* Release media_devnode and perform other cleanups as needed. */
+ if (devnode->release)
+ devnode->release(devnode);
++
++ kfree(devnode);
+ }
+
+ static struct bus_type media_bus_type = {
+@@ -221,6 +224,7 @@ static const struct file_operations media_devnode_fops = {
+
+ /**
+ * media_devnode_register - register a media device node
++ * @media_dev: struct media_device we want to register a device node
+ * @devnode: media device node structure we want to register
+ *
+ * The registration code assigns minor numbers and registers the new device node
+@@ -233,7 +237,8 @@ static const struct file_operations media_devnode_fops = {
+ * the media_devnode structure is *not* called, so the caller is responsible for
+ * freeing any data.
+ */
+-int __must_check media_devnode_register(struct media_devnode *devnode,
++int __must_check media_devnode_register(struct media_device *mdev,
++ struct media_devnode *devnode,
+ struct module *owner)
+ {
+ int minor;
+@@ -252,6 +257,7 @@ int __must_check media_devnode_register(struct media_devnode *devnode,
+ mutex_unlock(&media_devnode_lock);
+
+ devnode->minor = minor;
++ devnode->media_dev = mdev;
+
+ /* Part 2: Initialize and register the character device */
+ cdev_init(&devnode->cdev, &media_devnode_fops);
+diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
+index 9cd0268b2767..f353ab569b8e 100644
+--- a/drivers/media/usb/uvc/uvc_driver.c
++++ b/drivers/media/usb/uvc/uvc_driver.c
+@@ -1800,7 +1800,7 @@ static void uvc_delete(struct uvc_device *dev)
+ if (dev->vdev.dev)
+ v4l2_device_unregister(&dev->vdev);
+ #ifdef CONFIG_MEDIA_CONTROLLER
+- if (media_devnode_is_registered(&dev->mdev.devnode))
++ if (media_devnode_is_registered(dev->mdev.devnode))
+ media_device_unregister(&dev->mdev);
+ #endif
+
+diff --git a/include/media/media-device.h b/include/media/media-device.h
+index 6e6db78f1ee2..00bbd679864a 100644
+--- a/include/media/media-device.h
++++ b/include/media/media-device.h
+@@ -60,7 +60,7 @@ struct device;
+ struct media_device {
+ /* dev->driver_data points to this struct. */
+ struct device *dev;
+- struct media_devnode devnode;
++ struct media_devnode *devnode;
+
+ char model[32];
+ char serial[40];
+@@ -84,9 +84,6 @@ struct media_device {
+ #define MEDIA_DEV_NOTIFY_PRE_LINK_CH 0
+ #define MEDIA_DEV_NOTIFY_POST_LINK_CH 1
+
+-/* media_devnode to media_device */
+-#define to_media_device(node) container_of(node, struct media_device, devnode)
+-
+ int __must_check __media_device_register(struct media_device *mdev,
+ struct module *owner);
+ #define media_device_register(mdev) __media_device_register(mdev, THIS_MODULE)
+diff --git a/include/media/media-devnode.h b/include/media/media-devnode.h
+index 79f702d26d1f..8b854c044032 100644
+--- a/include/media/media-devnode.h
++++ b/include/media/media-devnode.h
+@@ -33,6 +33,8 @@
+ #include <linux/device.h>
+ #include <linux/cdev.h>
+
++struct media_device;
++
+ /*
+ * Flag to mark the media_devnode struct as registered. Drivers must not touch
+ * this flag directly, it will be set and cleared by media_devnode_register and
+@@ -67,6 +69,8 @@ struct media_file_operations {
+ * before registering the node.
+ */
+ struct media_devnode {
++ struct media_device *media_dev;
++
+ /* device ops */
+ const struct media_file_operations *fops;
+
+@@ -86,7 +90,8 @@ struct media_devnode {
+ /* dev to media_devnode */
+ #define to_media_devnode(cd) container_of(cd, struct media_devnode, dev)
+
+-int __must_check media_devnode_register(struct media_devnode *devnode,
++int __must_check media_devnode_register(struct media_device *mdev,
++ struct media_devnode *devnode,
+ struct module *owner);
+ void media_devnode_unregister(struct media_devnode *devnode);
+
+@@ -97,6 +102,9 @@ static inline struct media_devnode *media_devnode_data(struct file *filp)
+
+ static inline int media_devnode_is_registered(struct media_devnode *devnode)
+ {
++ if (!devnode)
++ return false;
++
+ return test_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
+ }
+
+--
+2.25.1
+
--- /dev/null
+From 677ab4f9d477410d1a3216d4d51287d075c64195 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 21 Mar 2016 04:33:12 -0700
+Subject: media-devnode: add missing mutex lock in error handler
+
+From: Max Kellermann <max@duempel.org>
+
+commit 88336e174645948da269e1812f138f727cd2896b upstream.
+
+We should protect the device unregister patch too, at the error
+condition.
+
+Signed-off-by: Max Kellermann <max@duempel.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/media-devnode.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c
+index 6c56aebd8db0..86c7c3732c84 100644
+--- a/drivers/media/media-devnode.c
++++ b/drivers/media/media-devnode.c
+@@ -282,8 +282,11 @@ int __must_check media_devnode_register(struct media_devnode *mdev,
+ return 0;
+
+ error:
++ mutex_lock(&media_devnode_lock);
+ cdev_del(&mdev->cdev);
+ clear_bit(mdev->minor, media_devnode_nums);
++ mutex_unlock(&media_devnode_lock);
++
+ return ret;
+ }
+
+--
+2.25.1
+
--- /dev/null
+From 2657e725986ccd5cdae49ec62d204042f6df2f44 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Mar 2016 11:22:57 -0300
+Subject: media-devnode: fix namespace mess
+
+From: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+
+commit 163f1e93e995048b894c5fc86a6034d16beed740 upstream.
+
+Along all media controller code, "mdev" is used to represent
+a pointer to struct media_device, and "devnode" for a pointer
+to struct media_devnode.
+
+However, inside media-devnode.[ch], "mdev" is used to represent
+a pointer to struct media_devnode.
+
+This is very confusing and may lead to development errors.
+
+So, let's change all occurrences at media-devnode.[ch] to
+also use "devnode" for such pointers.
+
+This patch doesn't make any functional changes.
+
+Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+[bwh: Backported to 4.4: adjust filename, context]
+Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/media-devnode.c | 114 +++++++++++++++++-----------------
+ include/media/media-devnode.h | 10 +--
+ 2 files changed, 62 insertions(+), 62 deletions(-)
+
+diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c
+index 86c7c3732c84..98211c570e11 100644
+--- a/drivers/media/media-devnode.c
++++ b/drivers/media/media-devnode.c
+@@ -59,21 +59,21 @@ static DECLARE_BITMAP(media_devnode_nums, MEDIA_NUM_DEVICES);
+ /* Called when the last user of the media device exits. */
+ static void media_devnode_release(struct device *cd)
+ {
+- struct media_devnode *mdev = to_media_devnode(cd);
++ struct media_devnode *devnode = to_media_devnode(cd);
+
+ mutex_lock(&media_devnode_lock);
+
+ /* Delete the cdev on this minor as well */
+- cdev_del(&mdev->cdev);
++ cdev_del(&devnode->cdev);
+
+ /* Mark device node number as free */
+- clear_bit(mdev->minor, media_devnode_nums);
++ clear_bit(devnode->minor, media_devnode_nums);
+
+ mutex_unlock(&media_devnode_lock);
+
+ /* Release media_devnode and perform other cleanups as needed. */
+- if (mdev->release)
+- mdev->release(mdev);
++ if (devnode->release)
++ devnode->release(devnode);
+ }
+
+ static struct bus_type media_bus_type = {
+@@ -83,37 +83,37 @@ static struct bus_type media_bus_type = {
+ static ssize_t media_read(struct file *filp, char __user *buf,
+ size_t sz, loff_t *off)
+ {
+- struct media_devnode *mdev = media_devnode_data(filp);
++ struct media_devnode *devnode = media_devnode_data(filp);
+
+- if (!mdev->fops->read)
++ if (!devnode->fops->read)
+ return -EINVAL;
+- if (!media_devnode_is_registered(mdev))
++ if (!media_devnode_is_registered(devnode))
+ return -EIO;
+- return mdev->fops->read(filp, buf, sz, off);
++ return devnode->fops->read(filp, buf, sz, off);
+ }
+
+ static ssize_t media_write(struct file *filp, const char __user *buf,
+ size_t sz, loff_t *off)
+ {
+- struct media_devnode *mdev = media_devnode_data(filp);
++ struct media_devnode *devnode = media_devnode_data(filp);
+
+- if (!mdev->fops->write)
++ if (!devnode->fops->write)
+ return -EINVAL;
+- if (!media_devnode_is_registered(mdev))
++ if (!media_devnode_is_registered(devnode))
+ return -EIO;
+- return mdev->fops->write(filp, buf, sz, off);
++ return devnode->fops->write(filp, buf, sz, off);
+ }
+
+ static unsigned int media_poll(struct file *filp,
+ struct poll_table_struct *poll)
+ {
+- struct media_devnode *mdev = media_devnode_data(filp);
++ struct media_devnode *devnode = media_devnode_data(filp);
+
+- if (!media_devnode_is_registered(mdev))
++ if (!media_devnode_is_registered(devnode))
+ return POLLERR | POLLHUP;
+- if (!mdev->fops->poll)
++ if (!devnode->fops->poll)
+ return DEFAULT_POLLMASK;
+- return mdev->fops->poll(filp, poll);
++ return devnode->fops->poll(filp, poll);
+ }
+
+ static long
+@@ -121,12 +121,12 @@ __media_ioctl(struct file *filp, unsigned int cmd, unsigned long arg,
+ long (*ioctl_func)(struct file *filp, unsigned int cmd,
+ unsigned long arg))
+ {
+- struct media_devnode *mdev = media_devnode_data(filp);
++ struct media_devnode *devnode = media_devnode_data(filp);
+
+ if (!ioctl_func)
+ return -ENOTTY;
+
+- if (!media_devnode_is_registered(mdev))
++ if (!media_devnode_is_registered(devnode))
+ return -EIO;
+
+ return ioctl_func(filp, cmd, arg);
+@@ -134,9 +134,9 @@ __media_ioctl(struct file *filp, unsigned int cmd, unsigned long arg,
+
+ static long media_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ {
+- struct media_devnode *mdev = media_devnode_data(filp);
++ struct media_devnode *devnode = media_devnode_data(filp);
+
+- return __media_ioctl(filp, cmd, arg, mdev->fops->ioctl);
++ return __media_ioctl(filp, cmd, arg, devnode->fops->ioctl);
+ }
+
+ #ifdef CONFIG_COMPAT
+@@ -144,9 +144,9 @@ static long media_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ static long media_compat_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+ {
+- struct media_devnode *mdev = media_devnode_data(filp);
++ struct media_devnode *devnode = media_devnode_data(filp);
+
+- return __media_ioctl(filp, cmd, arg, mdev->fops->compat_ioctl);
++ return __media_ioctl(filp, cmd, arg, devnode->fops->compat_ioctl);
+ }
+
+ #endif /* CONFIG_COMPAT */
+@@ -154,7 +154,7 @@ static long media_compat_ioctl(struct file *filp, unsigned int cmd,
+ /* Override for the open function */
+ static int media_open(struct inode *inode, struct file *filp)
+ {
+- struct media_devnode *mdev;
++ struct media_devnode *devnode;
+ int ret;
+
+ /* Check if the media device is available. This needs to be done with
+@@ -164,23 +164,23 @@ static int media_open(struct inode *inode, struct file *filp)
+ * a crash.
+ */
+ mutex_lock(&media_devnode_lock);
+- mdev = container_of(inode->i_cdev, struct media_devnode, cdev);
++ devnode = container_of(inode->i_cdev, struct media_devnode, cdev);
+ /* return ENXIO if the media device has been removed
+ already or if it is not registered anymore. */
+- if (!media_devnode_is_registered(mdev)) {
++ if (!media_devnode_is_registered(devnode)) {
+ mutex_unlock(&media_devnode_lock);
+ return -ENXIO;
+ }
+ /* and increase the device refcount */
+- get_device(&mdev->dev);
++ get_device(&devnode->dev);
+ mutex_unlock(&media_devnode_lock);
+
+- filp->private_data = mdev;
++ filp->private_data = devnode;
+
+- if (mdev->fops->open) {
+- ret = mdev->fops->open(filp);
++ if (devnode->fops->open) {
++ ret = devnode->fops->open(filp);
+ if (ret) {
+- put_device(&mdev->dev);
++ put_device(&devnode->dev);
+ filp->private_data = NULL;
+ return ret;
+ }
+@@ -192,16 +192,16 @@ static int media_open(struct inode *inode, struct file *filp)
+ /* Override for the release function */
+ static int media_release(struct inode *inode, struct file *filp)
+ {
+- struct media_devnode *mdev = media_devnode_data(filp);
++ struct media_devnode *devnode = media_devnode_data(filp);
+
+- if (mdev->fops->release)
+- mdev->fops->release(filp);
++ if (devnode->fops->release)
++ devnode->fops->release(filp);
+
+ filp->private_data = NULL;
+
+ /* decrease the refcount unconditionally since the release()
+ return value is ignored. */
+- put_device(&mdev->dev);
++ put_device(&devnode->dev);
+ return 0;
+ }
+
+@@ -221,7 +221,7 @@ static const struct file_operations media_devnode_fops = {
+
+ /**
+ * media_devnode_register - register a media device node
+- * @mdev: media device node structure we want to register
++ * @devnode: media device node structure we want to register
+ *
+ * The registration code assigns minor numbers and registers the new device node
+ * with the kernel. An error is returned if no free minor number can be found,
+@@ -233,7 +233,7 @@ static const struct file_operations media_devnode_fops = {
+ * the media_devnode structure is *not* called, so the caller is responsible for
+ * freeing any data.
+ */
+-int __must_check media_devnode_register(struct media_devnode *mdev,
++int __must_check media_devnode_register(struct media_devnode *devnode,
+ struct module *owner)
+ {
+ int minor;
+@@ -251,40 +251,40 @@ int __must_check media_devnode_register(struct media_devnode *mdev,
+ set_bit(minor, media_devnode_nums);
+ mutex_unlock(&media_devnode_lock);
+
+- mdev->minor = minor;
++ devnode->minor = minor;
+
+ /* Part 2: Initialize and register the character device */
+- cdev_init(&mdev->cdev, &media_devnode_fops);
+- mdev->cdev.owner = owner;
++ cdev_init(&devnode->cdev, &media_devnode_fops);
++ devnode->cdev.owner = owner;
+
+- ret = cdev_add(&mdev->cdev, MKDEV(MAJOR(media_dev_t), mdev->minor), 1);
++ ret = cdev_add(&devnode->cdev, MKDEV(MAJOR(media_dev_t), devnode->minor), 1);
+ if (ret < 0) {
+ pr_err("%s: cdev_add failed\n", __func__);
+ goto error;
+ }
+
+ /* Part 3: Register the media device */
+- mdev->dev.bus = &media_bus_type;
+- mdev->dev.devt = MKDEV(MAJOR(media_dev_t), mdev->minor);
+- mdev->dev.release = media_devnode_release;
+- if (mdev->parent)
+- mdev->dev.parent = mdev->parent;
+- dev_set_name(&mdev->dev, "media%d", mdev->minor);
+- ret = device_register(&mdev->dev);
++ devnode->dev.bus = &media_bus_type;
++ devnode->dev.devt = MKDEV(MAJOR(media_dev_t), devnode->minor);
++ devnode->dev.release = media_devnode_release;
++ if (devnode->parent)
++ devnode->dev.parent = devnode->parent;
++ dev_set_name(&devnode->dev, "media%d", devnode->minor);
++ ret = device_register(&devnode->dev);
+ if (ret < 0) {
+ pr_err("%s: device_register failed\n", __func__);
+ goto error;
+ }
+
+ /* Part 4: Activate this minor. The char device can now be used. */
+- set_bit(MEDIA_FLAG_REGISTERED, &mdev->flags);
++ set_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
+
+ return 0;
+
+ error:
+ mutex_lock(&media_devnode_lock);
+- cdev_del(&mdev->cdev);
+- clear_bit(mdev->minor, media_devnode_nums);
++ cdev_del(&devnode->cdev);
++ clear_bit(devnode->minor, media_devnode_nums);
+ mutex_unlock(&media_devnode_lock);
+
+ return ret;
+@@ -292,7 +292,7 @@ int __must_check media_devnode_register(struct media_devnode *mdev,
+
+ /**
+ * media_devnode_unregister - unregister a media device node
+- * @mdev: the device node to unregister
++ * @devnode: the device node to unregister
+ *
+ * This unregisters the passed device. Future open calls will be met with
+ * errors.
+@@ -300,16 +300,16 @@ int __must_check media_devnode_register(struct media_devnode *mdev,
+ * This function can safely be called if the device node has never been
+ * registered or has already been unregistered.
+ */
+-void media_devnode_unregister(struct media_devnode *mdev)
++void media_devnode_unregister(struct media_devnode *devnode)
+ {
+- /* Check if mdev was ever registered at all */
+- if (!media_devnode_is_registered(mdev))
++ /* Check if devnode was ever registered at all */
++ if (!media_devnode_is_registered(devnode))
+ return;
+
+ mutex_lock(&media_devnode_lock);
+- clear_bit(MEDIA_FLAG_REGISTERED, &mdev->flags);
++ clear_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
+ mutex_unlock(&media_devnode_lock);
+- device_unregister(&mdev->dev);
++ device_unregister(&devnode->dev);
+ }
+
+ /*
+diff --git a/include/media/media-devnode.h b/include/media/media-devnode.h
+index 17ddae32060d..79f702d26d1f 100644
+--- a/include/media/media-devnode.h
++++ b/include/media/media-devnode.h
+@@ -80,24 +80,24 @@ struct media_devnode {
+ unsigned long flags; /* Use bitops to access flags */
+
+ /* callbacks */
+- void (*release)(struct media_devnode *mdev);
++ void (*release)(struct media_devnode *devnode);
+ };
+
+ /* dev to media_devnode */
+ #define to_media_devnode(cd) container_of(cd, struct media_devnode, dev)
+
+-int __must_check media_devnode_register(struct media_devnode *mdev,
++int __must_check media_devnode_register(struct media_devnode *devnode,
+ struct module *owner);
+-void media_devnode_unregister(struct media_devnode *mdev);
++void media_devnode_unregister(struct media_devnode *devnode);
+
+ static inline struct media_devnode *media_devnode_data(struct file *filp)
+ {
+ return filp->private_data;
+ }
+
+-static inline int media_devnode_is_registered(struct media_devnode *mdev)
++static inline int media_devnode_is_registered(struct media_devnode *devnode)
+ {
+- return test_bit(MEDIA_FLAG_REGISTERED, &mdev->flags);
++ return test_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
+ }
+
+ #endif /* _MEDIA_DEVNODE_H */
+--
+2.25.1
+
--- /dev/null
+From 653727fd92f2a8d2db75dcf55ba5c2cbad1cfdd4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Jun 2016 14:37:23 -0300
+Subject: media: fix media devnode ioctl/syscall and unregister race
+
+From: Shuah Khan <shuahkh@osg.samsung.com>
+
+commit 6f0dd24a084a17f9984dd49dffbf7055bf123993 upstream.
+
+Media devnode open/ioctl could be in progress when media device unregister
+is initiated. System calls and ioctls check media device registered status
+at the beginning, however, there is a window where unregister could be in
+progress without changing the media devnode status to unregistered.
+
+process 1 process 2
+fd = open(/dev/media0)
+media_devnode_is_registered()
+ (returns true here)
+
+ media_device_unregister()
+ (unregister is in progress
+ and devnode isn't
+ unregistered yet)
+ ...
+ioctl(fd, ...)
+__media_ioctl()
+media_devnode_is_registered()
+ (returns true here)
+ ...
+ media_devnode_unregister()
+ ...
+ (driver releases the media device
+ memory)
+
+media_device_ioctl()
+ (By this point
+ devnode->media_dev does not
+ point to allocated memory.
+ use-after free in in mutex_lock_nested)
+
+BUG: KASAN: use-after-free in mutex_lock_nested+0x79c/0x800 at addr
+ffff8801ebe914f0
+
+Fix it by clearing register bit when unregister starts to avoid the race.
+
+process 1 process 2
+fd = open(/dev/media0)
+media_devnode_is_registered()
+ (could return true here)
+
+ media_device_unregister()
+ (clear the register bit,
+ then start unregister.)
+ ...
+ioctl(fd, ...)
+__media_ioctl()
+media_devnode_is_registered()
+ (return false here, ioctl
+ returns I/O error, and
+ will not access media
+ device memory)
+ ...
+ media_devnode_unregister()
+ ...
+ (driver releases the media device
+ memory)
+
+Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
+Suggested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Reported-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+Tested-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+[bwh: Backported to 4.4: adjut filename, context]
+Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/media-device.c | 15 ++++++++-------
+ drivers/media/media-devnode.c | 19 ++++++++++++-------
+ include/media/media-devnode.h | 14 ++++++++++++++
+ 3 files changed, 34 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
+index 5d79cd481730..0ca9506f4654 100644
+--- a/drivers/media/media-device.c
++++ b/drivers/media/media-device.c
+@@ -405,6 +405,7 @@ int __must_check __media_device_register(struct media_device *mdev,
+ if (ret < 0) {
+ /* devnode free is handled in media_devnode_*() */
+ mdev->devnode = NULL;
++ media_devnode_unregister_prepare(devnode);
+ media_devnode_unregister(devnode);
+ return ret;
+ }
+@@ -423,16 +424,16 @@ void media_device_unregister(struct media_device *mdev)
+ struct media_entity *entity;
+ struct media_entity *next;
+
++ /* Clear the devnode register bit to avoid races with media dev open */
++ media_devnode_unregister_prepare(mdev->devnode);
++
+ list_for_each_entry_safe(entity, next, &mdev->entities, list)
+ media_device_unregister_entity(entity);
+
+- /* Check if mdev devnode was registered */
+- if (media_devnode_is_registered(mdev->devnode)) {
+- device_remove_file(&mdev->devnode->dev, &dev_attr_model);
+- media_devnode_unregister(mdev->devnode);
+- /* devnode free is handled in media_devnode_*() */
+- mdev->devnode = NULL;
+- }
++ device_remove_file(&mdev->devnode->dev, &dev_attr_model);
++ media_devnode_unregister(mdev->devnode);
++ /* devnode free is handled in media_devnode_*() */
++ mdev->devnode = NULL;
+ }
+ EXPORT_SYMBOL_GPL(media_device_unregister);
+
+diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c
+index 45bb70d27224..e887120d19aa 100644
+--- a/drivers/media/media-devnode.c
++++ b/drivers/media/media-devnode.c
+@@ -302,6 +302,17 @@ int __must_check media_devnode_register(struct media_device *mdev,
+ return ret;
+ }
+
++void media_devnode_unregister_prepare(struct media_devnode *devnode)
++{
++ /* Check if devnode was ever registered at all */
++ if (!media_devnode_is_registered(devnode))
++ return;
++
++ mutex_lock(&media_devnode_lock);
++ clear_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
++ mutex_unlock(&media_devnode_lock);
++}
++
+ /**
+ * media_devnode_unregister - unregister a media device node
+ * @devnode: the device node to unregister
+@@ -309,17 +320,11 @@ int __must_check media_devnode_register(struct media_device *mdev,
+ * This unregisters the passed device. Future open calls will be met with
+ * errors.
+ *
+- * This function can safely be called if the device node has never been
+- * registered or has already been unregistered.
++ * Should be called after media_devnode_unregister_prepare()
+ */
+ void media_devnode_unregister(struct media_devnode *devnode)
+ {
+- /* Check if devnode was ever registered at all */
+- if (!media_devnode_is_registered(devnode))
+- return;
+-
+ mutex_lock(&media_devnode_lock);
+- clear_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
+ /* Delete the cdev on this minor as well */
+ cdev_del(&devnode->cdev);
+ mutex_unlock(&media_devnode_lock);
+diff --git a/include/media/media-devnode.h b/include/media/media-devnode.h
+index 8b854c044032..d5ff95bf2d4b 100644
+--- a/include/media/media-devnode.h
++++ b/include/media/media-devnode.h
+@@ -93,6 +93,20 @@ struct media_devnode {
+ int __must_check media_devnode_register(struct media_device *mdev,
+ struct media_devnode *devnode,
+ struct module *owner);
++
++/**
++ * media_devnode_unregister_prepare - clear the media device node register bit
++ * @devnode: the device node to prepare for unregister
++ *
++ * This clears the passed device register bit. Future open calls will be met
++ * with errors. Should be called before media_devnode_unregister() to avoid
++ * races with unregister and device file open calls.
++ *
++ * This function can safely be called if the device node has never been
++ * registered or has already been unregistered.
++ */
++void media_devnode_unregister_prepare(struct media_devnode *devnode);
++
+ void media_devnode_unregister(struct media_devnode *devnode);
+
+ static inline struct media_devnode *media_devnode_data(struct file *filp)
+--
+2.25.1
+
--- /dev/null
+From b977a5248a55f01ce98e002d5398f38b9f4c991e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 Jan 2016 21:49:33 -0200
+Subject: media: Fix media_open() to clear filp->private_data in error leg
+
+From: Shuah Khan <shuahkh@osg.samsung.com>
+
+commit d40ec6fdb0b03b7be4c7923a3da0e46bf943740a upstream.
+
+Fix media_open() to clear filp->private_data when file open
+fails.
+
+Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
+Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/media-devnode.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c
+index ebf9626e5ae5..a8cb52dc8c4f 100644
+--- a/drivers/media/media-devnode.c
++++ b/drivers/media/media-devnode.c
+@@ -181,6 +181,7 @@ static int media_open(struct inode *inode, struct file *filp)
+ ret = mdev->fops->open(filp);
+ if (ret) {
+ put_device(&mdev->dev);
++ filp->private_data = NULL;
+ return ret;
+ }
+ }
+--
+2.25.1
+
--- /dev/null
+From 3725671d2b4f9d4d74c307c446691e9078ae0d24 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 4 May 2016 16:48:28 -0300
+Subject: media: fix use-after-free in cdev_put() when app exits after driver
+ unbind
+
+From: Shuah Khan <shuahkh@osg.samsung.com>
+
+commit 5b28dde51d0ccc54cee70756e1800d70bed7114a upstream.
+
+When driver unbinds while media_ioctl is in progress, cdev_put() fails with
+when app exits after driver unbinds.
+
+Add devnode struct device kobj as the cdev parent kobject. cdev_add() gets
+a reference to it and releases it in cdev_del() ensuring that the devnode
+is not deallocated as long as the application has the device file open.
+
+media_devnode_register() initializes the struct device kobj before calling
+cdev_add(). media_devnode_unregister() does cdev_del() and then deletes the
+device. devnode is released when the last reference to the struct device is
+gone.
+
+This problem is found on uvcvideo, em28xx, and au0828 drivers and fix has
+been tested on all three.
+
+kernel: [ 193.599736] BUG: KASAN: use-after-free in cdev_put+0x4e/0x50
+kernel: [ 193.599745] Read of size 8 by task media_device_te/1851
+kernel: [ 193.599792] INFO: Allocated in __media_device_register+0x54
+kernel: [ 193.599951] INFO: Freed in media_devnode_release+0xa4/0xc0
+
+kernel: [ 193.601083] Call Trace:
+kernel: [ 193.601093] [<ffffffff81aecac3>] dump_stack+0x67/0x94
+kernel: [ 193.601102] [<ffffffff815359b2>] print_trailer+0x112/0x1a0
+kernel: [ 193.601111] [<ffffffff8153b5e4>] object_err+0x34/0x40
+kernel: [ 193.601119] [<ffffffff8153d9d4>] kasan_report_error+0x224/0x530
+kernel: [ 193.601128] [<ffffffff814a2c3d>] ? kzfree+0x2d/0x40
+kernel: [ 193.601137] [<ffffffff81539d72>] ? kfree+0x1d2/0x1f0
+kernel: [ 193.601154] [<ffffffff8157ca7e>] ? cdev_put+0x4e/0x50
+kernel: [ 193.601162] [<ffffffff8157ca7e>] cdev_put+0x4e/0x50
+kernel: [ 193.601170] [<ffffffff815767eb>] __fput+0x52b/0x6c0
+kernel: [ 193.601179] [<ffffffff8117743a>] ? switch_task_namespaces+0x2a
+kernel: [ 193.601188] [<ffffffff815769ee>] ____fput+0xe/0x10
+kernel: [ 193.601196] [<ffffffff81170023>] task_work_run+0x133/0x1f0
+kernel: [ 193.601204] [<ffffffff8117746e>] ? switch_task_namespaces+0x5e
+kernel: [ 193.601213] [<ffffffff8111b50c>] do_exit+0x72c/0x2c20
+kernel: [ 193.601224] [<ffffffff8111ade0>] ? release_task+0x1250/0x1250
+-
+-
+-
+kernel: [ 193.601360] [<ffffffff81003587>] ? exit_to_usermode_loop+0xe7
+kernel: [ 193.601368] [<ffffffff810035c0>] exit_to_usermode_loop+0x120
+kernel: [ 193.601376] [<ffffffff810061da>] syscall_return_slowpath+0x16a
+kernel: [ 193.601386] [<ffffffff82848b33>] entry_SYSCALL_64_fastpath+0xa6
+
+Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
+Tested-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/media-device.c | 6 +++--
+ drivers/media/media-devnode.c | 48 +++++++++++++++++++++--------------
+ 2 files changed, 33 insertions(+), 21 deletions(-)
+
+diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
+index fb018fe1a8f7..5d79cd481730 100644
+--- a/drivers/media/media-device.c
++++ b/drivers/media/media-device.c
+@@ -396,16 +396,16 @@ int __must_check __media_device_register(struct media_device *mdev,
+ devnode->release = media_device_release;
+ ret = media_devnode_register(mdev, devnode, owner);
+ if (ret < 0) {
++ /* devnode free is handled in media_devnode_*() */
+ mdev->devnode = NULL;
+- kfree(devnode);
+ return ret;
+ }
+
+ ret = device_create_file(&devnode->dev, &dev_attr_model);
+ if (ret < 0) {
++ /* devnode free is handled in media_devnode_*() */
+ mdev->devnode = NULL;
+ media_devnode_unregister(devnode);
+- kfree(devnode);
+ return ret;
+ }
+
+@@ -430,6 +430,8 @@ void media_device_unregister(struct media_device *mdev)
+ if (media_devnode_is_registered(mdev->devnode)) {
+ device_remove_file(&mdev->devnode->dev, &dev_attr_model);
+ media_devnode_unregister(mdev->devnode);
++ /* devnode free is handled in media_devnode_*() */
++ mdev->devnode = NULL;
+ }
+ }
+ EXPORT_SYMBOL_GPL(media_device_unregister);
+diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c
+index 000efb17b95b..45bb70d27224 100644
+--- a/drivers/media/media-devnode.c
++++ b/drivers/media/media-devnode.c
+@@ -63,13 +63,8 @@ static void media_devnode_release(struct device *cd)
+ struct media_devnode *devnode = to_media_devnode(cd);
+
+ mutex_lock(&media_devnode_lock);
+-
+- /* Delete the cdev on this minor as well */
+- cdev_del(&devnode->cdev);
+-
+ /* Mark device node number as free */
+ clear_bit(devnode->minor, media_devnode_nums);
+-
+ mutex_unlock(&media_devnode_lock);
+
+ /* Release media_devnode and perform other cleanups as needed. */
+@@ -77,6 +72,7 @@ static void media_devnode_release(struct device *cd)
+ devnode->release(devnode);
+
+ kfree(devnode);
++ pr_debug("%s: Media Devnode Deallocated\n", __func__);
+ }
+
+ static struct bus_type media_bus_type = {
+@@ -205,6 +201,8 @@ static int media_release(struct inode *inode, struct file *filp)
+ /* decrease the refcount unconditionally since the release()
+ return value is ignored. */
+ put_device(&devnode->dev);
++
++ pr_debug("%s: Media Release\n", __func__);
+ return 0;
+ }
+
+@@ -250,6 +248,7 @@ int __must_check media_devnode_register(struct media_device *mdev,
+ if (minor == MEDIA_NUM_DEVICES) {
+ mutex_unlock(&media_devnode_lock);
+ pr_err("could not get a free minor\n");
++ kfree(devnode);
+ return -ENFILE;
+ }
+
+@@ -259,27 +258,31 @@ int __must_check media_devnode_register(struct media_device *mdev,
+ devnode->minor = minor;
+ devnode->media_dev = mdev;
+
++ /* Part 1: Initialize dev now to use dev.kobj for cdev.kobj.parent */
++ devnode->dev.bus = &media_bus_type;
++ devnode->dev.devt = MKDEV(MAJOR(media_dev_t), devnode->minor);
++ devnode->dev.release = media_devnode_release;
++ if (devnode->parent)
++ devnode->dev.parent = devnode->parent;
++ dev_set_name(&devnode->dev, "media%d", devnode->minor);
++ device_initialize(&devnode->dev);
++
+ /* Part 2: Initialize and register the character device */
+ cdev_init(&devnode->cdev, &media_devnode_fops);
+ devnode->cdev.owner = owner;
++ devnode->cdev.kobj.parent = &devnode->dev.kobj;
+
+ ret = cdev_add(&devnode->cdev, MKDEV(MAJOR(media_dev_t), devnode->minor), 1);
+ if (ret < 0) {
+ pr_err("%s: cdev_add failed\n", __func__);
+- goto error;
++ goto cdev_add_error;
+ }
+
+- /* Part 3: Register the media device */
+- devnode->dev.bus = &media_bus_type;
+- devnode->dev.devt = MKDEV(MAJOR(media_dev_t), devnode->minor);
+- devnode->dev.release = media_devnode_release;
+- if (devnode->parent)
+- devnode->dev.parent = devnode->parent;
+- dev_set_name(&devnode->dev, "media%d", devnode->minor);
+- ret = device_register(&devnode->dev);
++ /* Part 3: Add the media device */
++ ret = device_add(&devnode->dev);
+ if (ret < 0) {
+- pr_err("%s: device_register failed\n", __func__);
+- goto error;
++ pr_err("%s: device_add failed\n", __func__);
++ goto device_add_error;
+ }
+
+ /* Part 4: Activate this minor. The char device can now be used. */
+@@ -287,12 +290,15 @@ int __must_check media_devnode_register(struct media_device *mdev,
+
+ return 0;
+
+-error:
+- mutex_lock(&media_devnode_lock);
++device_add_error:
+ cdev_del(&devnode->cdev);
++cdev_add_error:
++ mutex_lock(&media_devnode_lock);
+ clear_bit(devnode->minor, media_devnode_nums);
++ devnode->media_dev = NULL;
+ mutex_unlock(&media_devnode_lock);
+
++ put_device(&devnode->dev);
+ return ret;
+ }
+
+@@ -314,8 +320,12 @@ void media_devnode_unregister(struct media_devnode *devnode)
+
+ mutex_lock(&media_devnode_lock);
+ clear_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
++ /* Delete the cdev on this minor as well */
++ cdev_del(&devnode->cdev);
+ mutex_unlock(&media_devnode_lock);
+- device_unregister(&devnode->dev);
++ device_del(&devnode->dev);
++ devnode->media_dev = NULL;
++ put_device(&devnode->dev);
+ }
+
+ /*
+--
+2.25.1
+
--- /dev/null
+From 0f5c19f725997d7b5a5bd056a0128ff323cf0d86 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2020 16:51:44 -0400
+Subject: padata: initialize pd->cpu with effective cpumask
+
+From: Daniel Jordan <daniel.m.jordan@oracle.com>
+
+[ Upstream commit ec9c7d19336ee98ecba8de80128aa405c45feebb ]
+
+Exercising CPU hotplug on a 5.2 kernel with recent padata fixes from
+cryptodev-2.6.git in an 8-CPU kvm guest...
+
+ # modprobe tcrypt alg="pcrypt(rfc4106(gcm(aes)))" type=3
+ # echo 0 > /sys/devices/system/cpu/cpu1/online
+ # echo c > /sys/kernel/pcrypt/pencrypt/parallel_cpumask
+ # modprobe tcrypt mode=215
+
+...caused the following crash:
+
+ BUG: kernel NULL pointer dereference, address: 0000000000000000
+ #PF: supervisor read access in kernel mode
+ #PF: error_code(0x0000) - not-present page
+ PGD 0 P4D 0
+ Oops: 0000 [#1] SMP PTI
+ CPU: 2 PID: 134 Comm: kworker/2:2 Not tainted 5.2.0-padata-base+ #7
+ Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-<snip>
+ Workqueue: pencrypt padata_parallel_worker
+ RIP: 0010:padata_reorder+0xcb/0x180
+ ...
+ Call Trace:
+ padata_do_serial+0x57/0x60
+ pcrypt_aead_enc+0x3a/0x50 [pcrypt]
+ padata_parallel_worker+0x9b/0xe0
+ process_one_work+0x1b5/0x3f0
+ worker_thread+0x4a/0x3c0
+ ...
+
+In padata_alloc_pd, pd->cpu is set using the user-supplied cpumask
+instead of the effective cpumask, and in this case cpumask_first picked
+an offline CPU.
+
+The offline CPU's reorder->list.next is NULL in padata_reorder because
+the list wasn't initialized in padata_init_pqueues, which only operates
+on CPUs in the effective mask.
+
+Fix by using the effective mask in padata_alloc_pd.
+
+Fixes: 6fc4dbcf0276 ("padata: Replace delayed timer with immediate workqueue in padata_reorder")
+Signed-off-by: Daniel Jordan <daniel.m.jordan@oracle.com>
+Cc: Herbert Xu <herbert@gondor.apana.org.au>
+Cc: Steffen Klassert <steffen.klassert@secunet.com>
+Cc: linux-crypto@vger.kernel.org
+Cc: linux-kernel@vger.kernel.org
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Daniel Jordan <daniel.m.jordan@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/padata.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/padata.c b/kernel/padata.c
+index e5966eedfa36..43b72f5dfe07 100644
+--- a/kernel/padata.c
++++ b/kernel/padata.c
+@@ -449,7 +449,7 @@ static struct parallel_data *padata_alloc_pd(struct padata_instance *pinst,
+ atomic_set(&pd->refcnt, 1);
+ pd->pinst = pinst;
+ spin_lock_init(&pd->lock);
+- pd->cpu = cpumask_first(pcpumask);
++ pd->cpu = cpumask_first(pd->cpumask.pcpu);
+ INIT_WORK(&pd->reorder_work, invoke_padata_reorder);
+
+ return pd;
+--
+2.25.1
+
--- /dev/null
+From 05539e0e77745aac87da493d8452295cb67fc7a8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2020 16:51:45 -0400
+Subject: padata: purge get_cpu and reorder_via_wq from padata_do_serial
+
+From: Daniel Jordan <daniel.m.jordan@oracle.com>
+
+[ Upstream commit 065cf577135a4977931c7a1e1edf442bfd9773dd]
+
+With the removal of the padata timer, padata_do_serial no longer
+needs special CPU handling, so remove it.
+
+Signed-off-by: Daniel Jordan <daniel.m.jordan@oracle.com>
+Cc: Herbert Xu <herbert@gondor.apana.org.au>
+Cc: Steffen Klassert <steffen.klassert@secunet.com>
+Cc: linux-crypto@vger.kernel.org
+Cc: linux-kernel@vger.kernel.org
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Daniel Jordan <daniel.m.jordan@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/padata.c | 23 +++--------------------
+ 1 file changed, 3 insertions(+), 20 deletions(-)
+
+diff --git a/kernel/padata.c b/kernel/padata.c
+index 43b72f5dfe07..c50975f43b34 100644
+--- a/kernel/padata.c
++++ b/kernel/padata.c
+@@ -322,24 +322,9 @@ static void padata_serial_worker(struct work_struct *serial_work)
+ */
+ void padata_do_serial(struct padata_priv *padata)
+ {
+- int cpu;
+- struct padata_parallel_queue *pqueue;
+- struct parallel_data *pd;
+- int reorder_via_wq = 0;
+-
+- pd = padata->pd;
+-
+- cpu = get_cpu();
+-
+- /* We need to enqueue the padata object into the correct
+- * per-cpu queue.
+- */
+- if (cpu != padata->cpu) {
+- reorder_via_wq = 1;
+- cpu = padata->cpu;
+- }
+-
+- pqueue = per_cpu_ptr(pd->pqueue, cpu);
++ struct parallel_data *pd = padata->pd;
++ struct padata_parallel_queue *pqueue = per_cpu_ptr(pd->pqueue,
++ padata->cpu);
+
+ spin_lock(&pqueue->reorder.lock);
+ list_add_tail(&padata->list, &pqueue->reorder.list);
+@@ -353,8 +338,6 @@ void padata_do_serial(struct padata_priv *padata)
+ */
+ smp_mb__after_atomic();
+
+- put_cpu();
+-
+ padata_reorder(pd);
+ }
+ EXPORT_SYMBOL(padata_do_serial);
+--
+2.25.1
+
--- /dev/null
+From 4c099d6cdd80618907639cb023ce9a879eb83f6c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2020 16:51:43 -0400
+Subject: padata: Replace delayed timer with immediate workqueue in
+ padata_reorder
+
+From: Herbert Xu <herbert@gondor.apana.org.au>
+
+[ Upstream commit 6fc4dbcf0276279d488c5fbbfabe94734134f4fa ]
+
+The function padata_reorder will use a timer when it cannot progress
+while completed jobs are outstanding (pd->reorder_objects > 0). This
+is suboptimal as if we do end up using the timer then it would have
+introduced a gratuitous delay of one second.
+
+In fact we can easily distinguish between whether completed jobs
+are outstanding and whether we can make progress. All we have to
+do is look at the next pqueue list.
+
+This patch does that by replacing pd->processed with pd->cpu so
+that the next pqueue is more accessible.
+
+A work queue is used instead of the original try_again to avoid
+hogging the CPU.
+
+Note that we don't bother removing the work queue in
+padata_flush_queues because the whole premise is broken. You
+cannot flush async crypto requests so it makes no sense to even
+try. A subsequent patch will fix it by replacing it with a ref
+counting scheme.
+
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+[dj: - adjust context
+ - corrected setup_timer -> timer_setup to delete hunk
+ - skip padata_flush_queues() hunk, function already removed
+ in 4.4]
+Signed-off-by: Daniel Jordan <daniel.m.jordan@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/padata.h | 13 ++----
+ kernel/padata.c | 95 ++++++++----------------------------------
+ 2 files changed, 22 insertions(+), 86 deletions(-)
+
+diff --git a/include/linux/padata.h b/include/linux/padata.h
+index e74d61fa50fe..547a8d1e4a3b 100644
+--- a/include/linux/padata.h
++++ b/include/linux/padata.h
+@@ -24,7 +24,6 @@
+ #include <linux/workqueue.h>
+ #include <linux/spinlock.h>
+ #include <linux/list.h>
+-#include <linux/timer.h>
+ #include <linux/notifier.h>
+ #include <linux/kobject.h>
+
+@@ -85,18 +84,14 @@ struct padata_serial_queue {
+ * @serial: List to wait for serialization after reordering.
+ * @pwork: work struct for parallelization.
+ * @swork: work struct for serialization.
+- * @pd: Backpointer to the internal control structure.
+ * @work: work struct for parallelization.
+- * @reorder_work: work struct for reordering.
+ * @num_obj: Number of objects that are processed by this cpu.
+ * @cpu_index: Index of the cpu.
+ */
+ struct padata_parallel_queue {
+ struct padata_list parallel;
+ struct padata_list reorder;
+- struct parallel_data *pd;
+ struct work_struct work;
+- struct work_struct reorder_work;
+ atomic_t num_obj;
+ int cpu_index;
+ };
+@@ -122,10 +117,10 @@ struct padata_cpumask {
+ * @reorder_objects: Number of objects waiting in the reorder queues.
+ * @refcnt: Number of objects holding a reference on this parallel_data.
+ * @max_seq_nr: Maximal used sequence number.
++ * @cpu: Next CPU to be processed.
+ * @cpumask: The cpumasks in use for parallel and serial workers.
++ * @reorder_work: work struct for reordering.
+ * @lock: Reorder lock.
+- * @processed: Number of already processed objects.
+- * @timer: Reorder timer.
+ */
+ struct parallel_data {
+ struct padata_instance *pinst;
+@@ -134,10 +129,10 @@ struct parallel_data {
+ atomic_t reorder_objects;
+ atomic_t refcnt;
+ atomic_t seq_nr;
++ int cpu;
+ struct padata_cpumask cpumask;
++ struct work_struct reorder_work;
+ spinlock_t lock ____cacheline_aligned;
+- unsigned int processed;
+- struct timer_list timer;
+ };
+
+ /**
+diff --git a/kernel/padata.c b/kernel/padata.c
+index 4f860043a8e5..e5966eedfa36 100644
+--- a/kernel/padata.c
++++ b/kernel/padata.c
+@@ -165,23 +165,12 @@ EXPORT_SYMBOL(padata_do_parallel);
+ */
+ static struct padata_priv *padata_get_next(struct parallel_data *pd)
+ {
+- int cpu, num_cpus;
+- unsigned int next_nr, next_index;
+ struct padata_parallel_queue *next_queue;
+ struct padata_priv *padata;
+ struct padata_list *reorder;
++ int cpu = pd->cpu;
+
+- num_cpus = cpumask_weight(pd->cpumask.pcpu);
+-
+- /*
+- * Calculate the percpu reorder queue and the sequence
+- * number of the next object.
+- */
+- next_nr = pd->processed;
+- next_index = next_nr % num_cpus;
+- cpu = padata_index_to_cpu(pd, next_index);
+ next_queue = per_cpu_ptr(pd->pqueue, cpu);
+-
+ reorder = &next_queue->reorder;
+
+ spin_lock(&reorder->lock);
+@@ -192,7 +181,8 @@ static struct padata_priv *padata_get_next(struct parallel_data *pd)
+ list_del_init(&padata->list);
+ atomic_dec(&pd->reorder_objects);
+
+- pd->processed++;
++ pd->cpu = cpumask_next_wrap(cpu, pd->cpumask.pcpu, -1,
++ false);
+
+ spin_unlock(&reorder->lock);
+ goto out;
+@@ -215,6 +205,7 @@ static void padata_reorder(struct parallel_data *pd)
+ struct padata_priv *padata;
+ struct padata_serial_queue *squeue;
+ struct padata_instance *pinst = pd->pinst;
++ struct padata_parallel_queue *next_queue;
+
+ /*
+ * We need to ensure that only one cpu can work on dequeueing of
+@@ -246,7 +237,6 @@ static void padata_reorder(struct parallel_data *pd)
+ * so exit immediately.
+ */
+ if (PTR_ERR(padata) == -ENODATA) {
+- del_timer(&pd->timer);
+ spin_unlock_bh(&pd->lock);
+ return;
+ }
+@@ -265,70 +255,29 @@ static void padata_reorder(struct parallel_data *pd)
+
+ /*
+ * The next object that needs serialization might have arrived to
+- * the reorder queues in the meantime, we will be called again
+- * from the timer function if no one else cares for it.
++ * the reorder queues in the meantime.
+ *
+- * Ensure reorder_objects is read after pd->lock is dropped so we see
+- * an increment from another task in padata_do_serial. Pairs with
++ * Ensure reorder queue is read after pd->lock is dropped so we see
++ * new objects from another task in padata_do_serial. Pairs with
+ * smp_mb__after_atomic in padata_do_serial.
+ */
+ smp_mb();
+- if (atomic_read(&pd->reorder_objects)
+- && !(pinst->flags & PADATA_RESET))
+- mod_timer(&pd->timer, jiffies + HZ);
+- else
+- del_timer(&pd->timer);
+
+- return;
++ next_queue = per_cpu_ptr(pd->pqueue, pd->cpu);
++ if (!list_empty(&next_queue->reorder.list))
++ queue_work(pinst->wq, &pd->reorder_work);
+ }
+
+ static void invoke_padata_reorder(struct work_struct *work)
+ {
+- struct padata_parallel_queue *pqueue;
+ struct parallel_data *pd;
+
+ local_bh_disable();
+- pqueue = container_of(work, struct padata_parallel_queue, reorder_work);
+- pd = pqueue->pd;
++ pd = container_of(work, struct parallel_data, reorder_work);
+ padata_reorder(pd);
+ local_bh_enable();
+ }
+
+-static void padata_reorder_timer(unsigned long arg)
+-{
+- struct parallel_data *pd = (struct parallel_data *)arg;
+- unsigned int weight;
+- int target_cpu, cpu;
+-
+- cpu = get_cpu();
+-
+- /* We don't lock pd here to not interfere with parallel processing
+- * padata_reorder() calls on other CPUs. We just need any CPU out of
+- * the cpumask.pcpu set. It would be nice if it's the right one but
+- * it doesn't matter if we're off to the next one by using an outdated
+- * pd->processed value.
+- */
+- weight = cpumask_weight(pd->cpumask.pcpu);
+- target_cpu = padata_index_to_cpu(pd, pd->processed % weight);
+-
+- /* ensure to call the reorder callback on the correct CPU */
+- if (cpu != target_cpu) {
+- struct padata_parallel_queue *pqueue;
+- struct padata_instance *pinst;
+-
+- /* The timer function is serialized wrt itself -- no locking
+- * needed.
+- */
+- pinst = pd->pinst;
+- pqueue = per_cpu_ptr(pd->pqueue, target_cpu);
+- queue_work_on(target_cpu, pinst->wq, &pqueue->reorder_work);
+- } else {
+- padata_reorder(pd);
+- }
+-
+- put_cpu();
+-}
+-
+ static void padata_serial_worker(struct work_struct *serial_work)
+ {
+ struct padata_serial_queue *squeue;
+@@ -382,9 +331,8 @@ void padata_do_serial(struct padata_priv *padata)
+
+ cpu = get_cpu();
+
+- /* We need to run on the same CPU padata_do_parallel(.., padata, ..)
+- * was called on -- or, at least, enqueue the padata object into the
+- * correct per-cpu queue.
++ /* We need to enqueue the padata object into the correct
++ * per-cpu queue.
+ */
+ if (cpu != padata->cpu) {
+ reorder_via_wq = 1;
+@@ -394,12 +342,12 @@ void padata_do_serial(struct padata_priv *padata)
+ pqueue = per_cpu_ptr(pd->pqueue, cpu);
+
+ spin_lock(&pqueue->reorder.lock);
+- atomic_inc(&pd->reorder_objects);
+ list_add_tail(&padata->list, &pqueue->reorder.list);
++ atomic_inc(&pd->reorder_objects);
+ spin_unlock(&pqueue->reorder.lock);
+
+ /*
+- * Ensure the atomic_inc of reorder_objects above is ordered correctly
++ * Ensure the addition to the reorder list is ordered correctly
+ * with the trylock of pd->lock in padata_reorder. Pairs with smp_mb
+ * in padata_reorder.
+ */
+@@ -407,13 +355,7 @@ void padata_do_serial(struct padata_priv *padata)
+
+ put_cpu();
+
+- /* If we're running on the wrong CPU, call padata_reorder() via a
+- * kernel worker.
+- */
+- if (reorder_via_wq)
+- queue_work_on(cpu, pd->pinst->wq, &pqueue->reorder_work);
+- else
+- padata_reorder(pd);
++ padata_reorder(pd);
+ }
+ EXPORT_SYMBOL(padata_do_serial);
+
+@@ -469,14 +411,12 @@ static void padata_init_pqueues(struct parallel_data *pd)
+ continue;
+ }
+
+- pqueue->pd = pd;
+ pqueue->cpu_index = cpu_index;
+ cpu_index++;
+
+ __padata_list_init(&pqueue->reorder);
+ __padata_list_init(&pqueue->parallel);
+ INIT_WORK(&pqueue->work, padata_parallel_worker);
+- INIT_WORK(&pqueue->reorder_work, invoke_padata_reorder);
+ atomic_set(&pqueue->num_obj, 0);
+ }
+ }
+@@ -504,12 +444,13 @@ static struct parallel_data *padata_alloc_pd(struct padata_instance *pinst,
+
+ padata_init_pqueues(pd);
+ padata_init_squeues(pd);
+- setup_timer(&pd->timer, padata_reorder_timer, (unsigned long)pd);
+ atomic_set(&pd->seq_nr, -1);
+ atomic_set(&pd->reorder_objects, 0);
+ atomic_set(&pd->refcnt, 1);
+ pd->pinst = pinst;
+ spin_lock_init(&pd->lock);
++ pd->cpu = cpumask_first(pcpumask);
++ INIT_WORK(&pd->reorder_work, invoke_padata_reorder);
+
+ return pd;
+
+--
+2.25.1
+
--- /dev/null
+From 0f46a45bb313a0489b467856ebeb3c168f76bbf3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2020 16:51:41 -0400
+Subject: padata: set cpu_index of unused CPUs to -1
+
+From: Mathias Krause <minipli@googlemail.com>
+
+[ Upstream commit 1bd845bcb41d5b7f83745e0cb99273eb376f2ec5 ]
+
+The parallel queue per-cpu data structure gets initialized only for CPUs
+in the 'pcpu' CPU mask set. This is not sufficient as the reorder timer
+may run on a different CPU and might wrongly decide it's the target CPU
+for the next reorder item as per-cpu memory gets memset(0) and we might
+be waiting for the first CPU in cpumask.pcpu, i.e. cpu_index 0.
+
+Make the '__this_cpu_read(pd->pqueue->cpu_index) == next_queue->cpu_index'
+compare in padata_get_next() fail in this case by initializing the
+cpu_index member of all per-cpu parallel queues. Use -1 for unused ones.
+
+Signed-off-by: Mathias Krause <minipli@googlemail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Daniel Jordan <daniel.m.jordan@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/padata.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/kernel/padata.c b/kernel/padata.c
+index 8aef48c3267b..4f860043a8e5 100644
+--- a/kernel/padata.c
++++ b/kernel/padata.c
+@@ -461,8 +461,14 @@ static void padata_init_pqueues(struct parallel_data *pd)
+ struct padata_parallel_queue *pqueue;
+
+ cpu_index = 0;
+- for_each_cpu(cpu, pd->cpumask.pcpu) {
++ for_each_possible_cpu(cpu) {
+ pqueue = per_cpu_ptr(pd->pqueue, cpu);
++
++ if (!cpumask_test_cpu(cpu, pd->cpumask.pcpu)) {
++ pqueue->cpu_index = -1;
++ continue;
++ }
++
+ pqueue->pd = pd;
+ pqueue->cpu_index = cpu_index;
+ cpu_index++;
+--
+2.25.1
+
--- /dev/null
+From 6ab43c8f5881b8385e74fee50517c67847f77565 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2020 16:51:42 -0400
+Subject: sched/fair, cpumask: Export for_each_cpu_wrap()
+
+From: Peter Zijlstra <peterz@infradead.org>
+
+[ Upstream commit c743f0a5c50f2fcbc628526279cfa24f3dabe182 ]
+
+More users for for_each_cpu_wrap() have appeared. Promote the construct
+to generic cpumask interface.
+
+The implementation is slightly modified to reduce arguments.
+
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Cc: Lauro Ramos Venancio <lvenanci@redhat.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Mike Galbraith <efault@gmx.de>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Rik van Riel <riel@redhat.com>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: lwang@redhat.com
+Link: http://lkml.kernel.org/r/20170414122005.o35me2h5nowqkxbv@hirez.programming.kicks-ass.net
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+[dj: include only what's added to the cpumask interface, 4.4 doesn't
+ have them in the scheduler]
+Signed-off-by: Daniel Jordan <daniel.m.jordan@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/cpumask.h | 17 +++++++++++++++++
+ lib/cpumask.c | 32 ++++++++++++++++++++++++++++++++
+ 2 files changed, 49 insertions(+)
+
+diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
+index bb3a4bb35183..1322883e7b46 100644
+--- a/include/linux/cpumask.h
++++ b/include/linux/cpumask.h
+@@ -232,6 +232,23 @@ unsigned int cpumask_local_spread(unsigned int i, int node);
+ (cpu) = cpumask_next_zero((cpu), (mask)), \
+ (cpu) < nr_cpu_ids;)
+
++extern int cpumask_next_wrap(int n, const struct cpumask *mask, int start, bool wrap);
++
++/**
++ * for_each_cpu_wrap - iterate over every cpu in a mask, starting at a specified location
++ * @cpu: the (optionally unsigned) integer iterator
++ * @mask: the cpumask poiter
++ * @start: the start location
++ *
++ * The implementation does not assume any bit in @mask is set (including @start).
++ *
++ * After the loop, cpu is >= nr_cpu_ids.
++ */
++#define for_each_cpu_wrap(cpu, mask, start) \
++ for ((cpu) = cpumask_next_wrap((start)-1, (mask), (start), false); \
++ (cpu) < nr_cpumask_bits; \
++ (cpu) = cpumask_next_wrap((cpu), (mask), (start), true))
++
+ /**
+ * for_each_cpu_and - iterate over every cpu in both masks
+ * @cpu: the (optionally unsigned) integer iterator
+diff --git a/lib/cpumask.c b/lib/cpumask.c
+index 5a70f6196f57..24f06e7abf92 100644
+--- a/lib/cpumask.c
++++ b/lib/cpumask.c
+@@ -42,6 +42,38 @@ int cpumask_any_but(const struct cpumask *mask, unsigned int cpu)
+ return i;
+ }
+
++/**
++ * cpumask_next_wrap - helper to implement for_each_cpu_wrap
++ * @n: the cpu prior to the place to search
++ * @mask: the cpumask pointer
++ * @start: the start point of the iteration
++ * @wrap: assume @n crossing @start terminates the iteration
++ *
++ * Returns >= nr_cpu_ids on completion
++ *
++ * Note: the @wrap argument is required for the start condition when
++ * we cannot assume @start is set in @mask.
++ */
++int cpumask_next_wrap(int n, const struct cpumask *mask, int start, bool wrap)
++{
++ int next;
++
++again:
++ next = cpumask_next(n, mask);
++
++ if (wrap && n < start && next >= start) {
++ return nr_cpumask_bits;
++
++ } else if (next >= nr_cpumask_bits) {
++ wrap = true;
++ n = -1;
++ goto again;
++ }
++
++ return next;
++}
++EXPORT_SYMBOL(cpumask_next_wrap);
++
+ /* These are not inline because of header tangles. */
+ #ifdef CONFIG_CPUMASK_OFFSTACK
+ /**
+--
+2.25.1
+
usb-core-fix-misleading-driver-bug-report.patch
platform-x86-asus-nb-wmi-do-not-load-on-asus-t100ta-.patch
arm-futex-address-build-warning.patch
+media-fix-media_open-to-clear-filp-private_data-in-e.patch
+drivers-media-media-devnode-clear-private_data-befor.patch
+media-devnode-add-missing-mutex-lock-in-error-handle.patch
+media-devnode-fix-namespace-mess.patch
+media-device-dynamically-allocate-struct-media_devno.patch
+media-fix-use-after-free-in-cdev_put-when-app-exits-.patch
+media-fix-media-devnode-ioctl-syscall-and-unregister.patch
+i2c-dev-switch-from-register_chrdev-to-cdev-api.patch
+i2c-dev-don-t-start-function-name-with-return.patch
+i2c-dev-use-after-free-in-detach.patch
+i2c-dev-don-t-get-i2c-adapter-via-i2c_dev.patch
+i2c-dev-fix-the-race-between-the-release-of-i2c_dev-.patch
+padata-set-cpu_index-of-unused-cpus-to-1.patch
+sched-fair-cpumask-export-for_each_cpu_wrap.patch
+padata-replace-delayed-timer-with-immediate-workqueu.patch
+padata-initialize-pd-cpu-with-effective-cpumask.patch
+padata-purge-get_cpu-and-reorder_via_wq-from-padata_.patch