--- /dev/null
+From 7e1d90f60a0d501c8503e636942ca704a454d910 Mon Sep 17 00:00:00 2001
+From: Daniel Mentz <danielmentz@google.com>
+Date: Mon, 14 Aug 2017 14:46:01 -0700
+Subject: ALSA: seq: 2nd attempt at fixing race creating a queue
+
+From: Daniel Mentz <danielmentz@google.com>
+
+commit 7e1d90f60a0d501c8503e636942ca704a454d910 upstream.
+
+commit 4842e98f26dd80be3623c4714a244ba52ea096a8 ("ALSA: seq: Fix race at
+creating a queue") attempted to fix a race reported by syzkaller. That
+fix has been described as follows:
+
+"
+When a sequencer queue is created in snd_seq_queue_alloc(),it adds the
+new queue element to the public list before referencing it. Thus the
+queue might be deleted before the call of snd_seq_queue_use(), and it
+results in the use-after-free error, as spotted by syzkaller.
+
+The fix is to reference the queue object at the right time.
+"
+
+Even with that fix in place, syzkaller reported a use-after-free error.
+It specifically pointed to the last instruction "return q->queue" in
+snd_seq_queue_alloc(). The pointer q is being used after kfree() has
+been called on it.
+
+It turned out that there is still a small window where a race can
+happen. The window opens at
+snd_seq_ioctl_create_queue()->snd_seq_queue_alloc()->queue_list_add()
+and closes at
+snd_seq_ioctl_create_queue()->queueptr()->snd_use_lock_use(). Between
+these two calls, a different thread could delete the queue and possibly
+re-create a different queue in the same location in queue_list.
+
+This change prevents this situation by calling snd_use_lock_use() from
+snd_seq_queue_alloc() prior to calling queue_list_add(). It is then the
+caller's responsibility to call snd_use_lock_free(&q->use_lock).
+
+Fixes: 4842e98f26dd ("ALSA: seq: Fix race at creating a queue")
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Daniel Mentz <danielmentz@google.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/seq/seq_clientmgr.c | 13 ++++---------
+ sound/core/seq/seq_queue.c | 14 +++++++++-----
+ sound/core/seq/seq_queue.h | 2 +-
+ 3 files changed, 14 insertions(+), 15 deletions(-)
+
+--- a/sound/core/seq/seq_clientmgr.c
++++ b/sound/core/seq/seq_clientmgr.c
+@@ -1502,16 +1502,11 @@ static int snd_seq_ioctl_unsubscribe_por
+ static int snd_seq_ioctl_create_queue(struct snd_seq_client *client, void *arg)
+ {
+ struct snd_seq_queue_info *info = arg;
+- int result;
+ struct snd_seq_queue *q;
+
+- result = snd_seq_queue_alloc(client->number, info->locked, info->flags);
+- if (result < 0)
+- return result;
+-
+- q = queueptr(result);
+- if (q == NULL)
+- return -EINVAL;
++ q = snd_seq_queue_alloc(client->number, info->locked, info->flags);
++ if (IS_ERR(q))
++ return PTR_ERR(q);
+
+ info->queue = q->queue;
+ info->locked = q->locked;
+@@ -1521,7 +1516,7 @@ static int snd_seq_ioctl_create_queue(st
+ if (!info->name[0])
+ snprintf(info->name, sizeof(info->name), "Queue-%d", q->queue);
+ strlcpy(q->name, info->name, sizeof(q->name));
+- queuefree(q);
++ snd_use_lock_free(&q->use_lock);
+
+ return 0;
+ }
+--- a/sound/core/seq/seq_queue.c
++++ b/sound/core/seq/seq_queue.c
+@@ -184,22 +184,26 @@ void __exit snd_seq_queues_delete(void)
+ static void queue_use(struct snd_seq_queue *queue, int client, int use);
+
+ /* allocate a new queue -
+- * return queue index value or negative value for error
++ * return pointer to new queue or ERR_PTR(-errno) for error
++ * The new queue's use_lock is set to 1. It is the caller's responsibility to
++ * call snd_use_lock_free(&q->use_lock).
+ */
+-int snd_seq_queue_alloc(int client, int locked, unsigned int info_flags)
++struct snd_seq_queue *snd_seq_queue_alloc(int client, int locked, unsigned int info_flags)
+ {
+ struct snd_seq_queue *q;
+
+ q = queue_new(client, locked);
+ if (q == NULL)
+- return -ENOMEM;
++ return ERR_PTR(-ENOMEM);
+ q->info_flags = info_flags;
+ queue_use(q, client, 1);
++ snd_use_lock_use(&q->use_lock);
+ if (queue_list_add(q) < 0) {
++ snd_use_lock_free(&q->use_lock);
+ queue_delete(q);
+- return -ENOMEM;
++ return ERR_PTR(-ENOMEM);
+ }
+- return q->queue;
++ return q;
+ }
+
+ /* delete a queue - queue must be owned by the client */
+--- a/sound/core/seq/seq_queue.h
++++ b/sound/core/seq/seq_queue.h
+@@ -71,7 +71,7 @@ void snd_seq_queues_delete(void);
+
+
+ /* create new queue (constructor) */
+-int snd_seq_queue_alloc(int client, int locked, unsigned int flags);
++struct snd_seq_queue *snd_seq_queue_alloc(int client, int locked, unsigned int flags);
+
+ /* delete queue (destructor) */
+ int snd_seq_queue_delete(int client, int queueid);
--- /dev/null
+From ed993c6fdfa7734881a4516852d95ae2d3b604d3 Mon Sep 17 00:00:00 2001
+From: Jussi Laako <jussi@sonarnerd.net>
+Date: Fri, 18 Aug 2017 10:42:14 +0300
+Subject: ALSA: usb-audio: add DSD support for new Amanero PID
+
+From: Jussi Laako <jussi@sonarnerd.net>
+
+commit ed993c6fdfa7734881a4516852d95ae2d3b604d3 upstream.
+
+Add DSD support for new Amanero Combo384 firmware version with a new
+PID. This firmware uses DSD_U32_BE.
+
+Fixes: 3eff682d765b ("ALSA: usb-audio: Support both DSD LE/BE Amanero firmware versions")
+Signed-off-by: Jussi Laako <jussi@sonarnerd.net>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/usb/quirks.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -1375,6 +1375,10 @@ u64 snd_usb_interface_dsd_format_quirks(
+ }
+ }
+ break;
++ case USB_ID(0x16d0, 0x0a23):
++ if (fp->altsetting == 2)
++ return SNDRV_PCM_FMTBIT_DSD_U32_BE;
++ break;
+
+ default:
+ break;
--- /dev/null
+From 0f174b3525a43bd51f9397394763925e0ebe7bc7 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 16 Aug 2017 14:18:37 +0200
+Subject: ALSA: usb-audio: Add mute TLV for playback volumes on C-Media devices
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 0f174b3525a43bd51f9397394763925e0ebe7bc7 upstream.
+
+C-Media devices (at least some models) mute the playback stream when
+volumes are set to the minimum value. But this isn't informed via TLV
+and the user-space, typically PulseAudio, gets confused as if it's
+still played in a low volume.
+
+This patch adds the new flag, min_mute, to struct usb_mixer_elem_info
+for indicating that the mixer element is with the minimum-mute volume.
+This flag is set for known C-Media devices in
+snd_usb_mixer_fu_apply_quirk() in turn.
+
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=196669
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/usb/mixer.c | 2 ++
+ sound/usb/mixer.h | 1 +
+ sound/usb/mixer_quirks.c | 6 ++++++
+ 3 files changed, 9 insertions(+)
+
+--- a/sound/usb/mixer.c
++++ b/sound/usb/mixer.c
+@@ -542,6 +542,8 @@ int snd_usb_mixer_vol_tlv(struct snd_kco
+
+ if (size < sizeof(scale))
+ return -ENOMEM;
++ if (cval->min_mute)
++ scale[0] = SNDRV_CTL_TLVT_DB_MINMAX_MUTE;
+ scale[2] = cval->dBmin;
+ scale[3] = cval->dBmax;
+ if (copy_to_user(_tlv, scale, sizeof(scale)))
+--- a/sound/usb/mixer.h
++++ b/sound/usb/mixer.h
+@@ -64,6 +64,7 @@ struct usb_mixer_elem_info {
+ int cached;
+ int cache_val[MAX_CHANNELS];
+ u8 initialized;
++ u8 min_mute;
+ void *private_data;
+ };
+
+--- a/sound/usb/mixer_quirks.c
++++ b/sound/usb/mixer_quirks.c
+@@ -1878,6 +1878,12 @@ void snd_usb_mixer_fu_apply_quirk(struct
+ if (unitid == 7 && cval->control == UAC_FU_VOLUME)
+ snd_dragonfly_quirk_db_scale(mixer, cval, kctl);
+ break;
++ /* lowest playback value is muted on C-Media devices */
++ case USB_ID(0x0d8c, 0x000c):
++ case USB_ID(0x0d8c, 0x0014):
++ if (strstr(kctl->id.name, "Playback"))
++ cval->min_mute = 1;
++ break;
+ }
+ }
+
--- /dev/null
+From a8e800fe0f68bc28ce309914f47e432742b865ed Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 14 Aug 2017 14:35:50 +0200
+Subject: ALSA: usb-audio: Apply sample rate quirk to Sennheiser headset
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit a8e800fe0f68bc28ce309914f47e432742b865ed upstream.
+
+A Senheisser headset requires the typical sample-rate quirk for
+avoiding spurious errors from inquiring the current sample rate like:
+ usb 1-1: 2:1: cannot get freq at ep 0x4
+ usb 1-1: 3:1: cannot get freq at ep 0x83
+
+The USB ID 1395:740a has to be added to the entries in
+snd_usb_get_sample_rate_quirk().
+
+Bugzilla: https://bugzilla.suse.com/show_bug.cgi?id=1052580
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/usb/quirks.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -1142,6 +1142,7 @@ bool snd_usb_get_sample_rate_quirk(struc
+ case USB_ID(0x0556, 0x0014): /* Phoenix Audio TMX320VC */
+ case USB_ID(0x05A3, 0x9420): /* ELP HD USB Camera */
+ case USB_ID(0x074D, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */
++ case USB_ID(0x1395, 0x740a): /* Sennheiser DECT */
+ case USB_ID(0x1901, 0x0191): /* GE B850V3 CP2114 audio interface */
+ case USB_ID(0x1de7, 0x0013): /* Phoenix Audio MT202exe */
+ case USB_ID(0x1de7, 0x0014): /* Phoenix Audio TMX320 */
--- /dev/null
+From 3010f876500f9ba921afaeccec30c45ca6584dc8 Mon Sep 17 00:00:00 2001
+From: Pavel Tatashin <pasha.tatashin@oracle.com>
+Date: Fri, 18 Aug 2017 15:16:05 -0700
+Subject: mm: discard memblock data later
+
+From: Pavel Tatashin <pasha.tatashin@oracle.com>
+
+commit 3010f876500f9ba921afaeccec30c45ca6584dc8 upstream.
+
+There is existing use after free bug when deferred struct pages are
+enabled:
+
+The memblock_add() allocates memory for the memory array if more than
+128 entries are needed. See comment in e820__memblock_setup():
+
+ * The bootstrap memblock region count maximum is 128 entries
+ * (INIT_MEMBLOCK_REGIONS), but EFI might pass us more E820 entries
+ * than that - so allow memblock resizing.
+
+This memblock memory is freed here:
+ free_low_memory_core_early()
+
+We access the freed memblock.memory later in boot when deferred pages
+are initialized in this path:
+
+ deferred_init_memmap()
+ for_each_mem_pfn_range()
+ __next_mem_pfn_range()
+ type = &memblock.memory;
+
+One possible explanation for why this use-after-free hasn't been hit
+before is that the limit of INIT_MEMBLOCK_REGIONS has never been
+exceeded at least on systems where deferred struct pages were enabled.
+
+Tested by reducing INIT_MEMBLOCK_REGIONS down to 4 from the current 128,
+and verifying in qemu that this code is getting excuted and that the
+freed pages are sane.
+
+Link: http://lkml.kernel.org/r/1502485554-318703-2-git-send-email-pasha.tatashin@oracle.com
+Fixes: 7e18adb4f80b ("mm: meminit: initialise remaining struct pages in parallel with kswapd")
+Signed-off-by: Pavel Tatashin <pasha.tatashin@oracle.com>
+Reviewed-by: Steven Sistare <steven.sistare@oracle.com>
+Reviewed-by: Daniel Jordan <daniel.m.jordan@oracle.com>
+Reviewed-by: Bob Picco <bob.picco@oracle.com>
+Acked-by: Michal Hocko <mhocko@suse.com>
+Cc: Mel Gorman <mgorman@techsingularity.net>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/linux/memblock.h | 6 ++++--
+ mm/memblock.c | 40 ++++++++++++++++++----------------------
+ mm/nobootmem.c | 16 ----------------
+ mm/page_alloc.c | 4 ++++
+ 4 files changed, 26 insertions(+), 40 deletions(-)
+
+--- a/include/linux/memblock.h
++++ b/include/linux/memblock.h
+@@ -65,6 +65,7 @@ extern bool movable_node_enabled;
+ #ifdef CONFIG_ARCH_DISCARD_MEMBLOCK
+ #define __init_memblock __meminit
+ #define __initdata_memblock __meminitdata
++void memblock_discard(void);
+ #else
+ #define __init_memblock
+ #define __initdata_memblock
+@@ -78,8 +79,6 @@ phys_addr_t memblock_find_in_range_node(
+ int nid, ulong flags);
+ phys_addr_t memblock_find_in_range(phys_addr_t start, phys_addr_t end,
+ phys_addr_t size, phys_addr_t align);
+-phys_addr_t get_allocated_memblock_reserved_regions_info(phys_addr_t *addr);
+-phys_addr_t get_allocated_memblock_memory_regions_info(phys_addr_t *addr);
+ void memblock_allow_resize(void);
+ int memblock_add_node(phys_addr_t base, phys_addr_t size, int nid);
+ int memblock_add(phys_addr_t base, phys_addr_t size);
+@@ -114,6 +113,9 @@ void __next_mem_range_rev(u64 *idx, int
+ void __next_reserved_mem_region(u64 *idx, phys_addr_t *out_start,
+ phys_addr_t *out_end);
+
++void __memblock_free_early(phys_addr_t base, phys_addr_t size);
++void __memblock_free_late(phys_addr_t base, phys_addr_t size);
++
+ /**
+ * for_each_mem_range - iterate through memblock areas from type_a and not
+ * included in type_b. Or just type_a if type_b is NULL.
+--- a/mm/memblock.c
++++ b/mm/memblock.c
+@@ -288,31 +288,27 @@ static void __init_memblock memblock_rem
+ }
+
+ #ifdef CONFIG_ARCH_DISCARD_MEMBLOCK
+-
+-phys_addr_t __init_memblock get_allocated_memblock_reserved_regions_info(
+- phys_addr_t *addr)
+-{
+- if (memblock.reserved.regions == memblock_reserved_init_regions)
+- return 0;
+-
+- *addr = __pa(memblock.reserved.regions);
+-
+- return PAGE_ALIGN(sizeof(struct memblock_region) *
+- memblock.reserved.max);
+-}
+-
+-phys_addr_t __init_memblock get_allocated_memblock_memory_regions_info(
+- phys_addr_t *addr)
++/**
++ * Discard memory and reserved arrays if they were allocated
++ */
++void __init memblock_discard(void)
+ {
+- if (memblock.memory.regions == memblock_memory_init_regions)
+- return 0;
++ phys_addr_t addr, size;
+
+- *addr = __pa(memblock.memory.regions);
+-
+- return PAGE_ALIGN(sizeof(struct memblock_region) *
+- memblock.memory.max);
++ if (memblock.reserved.regions != memblock_reserved_init_regions) {
++ addr = __pa(memblock.reserved.regions);
++ size = PAGE_ALIGN(sizeof(struct memblock_region) *
++ memblock.reserved.max);
++ __memblock_free_late(addr, size);
++ }
++
++ if (memblock.memory.regions == memblock_memory_init_regions) {
++ addr = __pa(memblock.memory.regions);
++ size = PAGE_ALIGN(sizeof(struct memblock_region) *
++ memblock.memory.max);
++ __memblock_free_late(addr, size);
++ }
+ }
+-
+ #endif
+
+ /**
+--- a/mm/nobootmem.c
++++ b/mm/nobootmem.c
+@@ -146,22 +146,6 @@ static unsigned long __init free_low_mem
+ NULL)
+ count += __free_memory_core(start, end);
+
+-#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK
+- {
+- phys_addr_t size;
+-
+- /* Free memblock.reserved array if it was allocated */
+- size = get_allocated_memblock_reserved_regions_info(&start);
+- if (size)
+- count += __free_memory_core(start, start + size);
+-
+- /* Free memblock.memory array if it was allocated */
+- size = get_allocated_memblock_memory_regions_info(&start);
+- if (size)
+- count += __free_memory_core(start, start + size);
+- }
+-#endif
+-
+ return count;
+ }
+
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -1582,6 +1582,10 @@ void __init page_alloc_init_late(void)
+ /* Reinit limits that are based on free pages after the kernel is up */
+ files_maxfiles_init();
+ #endif
++#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK
++ /* Discard memblock private memory */
++ memblock_discard();
++#endif
+
+ for_each_populated_zone(zone)
+ set_zone_contiguous(zone);
md-fix-test-in-md_write_start.patch
md-always-clear-safemode-when-md_check_recovery-gets-the-mddev-lock.patch
md-not-clear-safemode-for-external-metadata-array.patch
+alsa-seq-2nd-attempt-at-fixing-race-creating-a-queue.patch
+alsa-usb-audio-apply-sample-rate-quirk-to-sennheiser-headset.patch
+alsa-usb-audio-add-mute-tlv-for-playback-volumes-on-c-media-devices.patch
+alsa-usb-audio-add-dsd-support-for-new-amanero-pid.patch
+mm-discard-memblock-data-later.patch
+slub-fix-per-memcg-cache-leak-on-css-offline.patch
--- /dev/null
+From f6ba488073fe8159851fe398cc3c5ee383bb4c7a Mon Sep 17 00:00:00 2001
+From: Vladimir Davydov <vdavydov.dev@gmail.com>
+Date: Fri, 18 Aug 2017 15:16:08 -0700
+Subject: slub: fix per memcg cache leak on css offline
+
+From: Vladimir Davydov <vdavydov.dev@gmail.com>
+
+commit f6ba488073fe8159851fe398cc3c5ee383bb4c7a upstream.
+
+To avoid a possible deadlock, sysfs_slab_remove() schedules an
+asynchronous work to delete sysfs entries corresponding to the kmem
+cache. To ensure the cache isn't freed before the work function is
+called, it takes a reference to the cache kobject. The reference is
+supposed to be released by the work function.
+
+However, the work function (sysfs_slab_remove_workfn()) does nothing in
+case the cache sysfs entry has already been deleted, leaking the kobject
+and the corresponding cache.
+
+This may happen on a per memcg cache destruction, because sysfs entries
+of a per memcg cache are deleted on memcg offline if the cache is empty
+(see __kmemcg_cache_deactivate()).
+
+The kmemleak report looks like this:
+
+ unreferenced object 0xffff9f798a79f540 (size 32):
+ comm "kworker/1:4", pid 15416, jiffies 4307432429 (age 28687.554s)
+ hex dump (first 32 bytes):
+ 6b 6d 61 6c 6c 6f 63 2d 31 36 28 31 35 39 39 3a kmalloc-16(1599:
+ 6e 65 77 72 6f 6f 74 29 00 23 6b c0 ff ff ff ff newroot).#k.....
+ backtrace:
+ kmemleak_alloc+0x4a/0xa0
+ __kmalloc_track_caller+0x148/0x2c0
+ kvasprintf+0x66/0xd0
+ kasprintf+0x49/0x70
+ memcg_create_kmem_cache+0xe6/0x160
+ memcg_kmem_cache_create_func+0x20/0x110
+ process_one_work+0x205/0x5d0
+ worker_thread+0x4e/0x3a0
+ kthread+0x109/0x140
+ ret_from_fork+0x2a/0x40
+ unreferenced object 0xffff9f79b6136840 (size 416):
+ comm "kworker/1:4", pid 15416, jiffies 4307432429 (age 28687.573s)
+ hex dump (first 32 bytes):
+ 40 fb 80 c2 3e 33 00 00 00 00 00 40 00 00 00 00 @...>3.....@....
+ 00 00 00 00 00 00 00 00 10 00 00 00 10 00 00 00 ................
+ backtrace:
+ kmemleak_alloc+0x4a/0xa0
+ kmem_cache_alloc+0x128/0x280
+ create_cache+0x3b/0x1e0
+ memcg_create_kmem_cache+0x118/0x160
+ memcg_kmem_cache_create_func+0x20/0x110
+ process_one_work+0x205/0x5d0
+ worker_thread+0x4e/0x3a0
+ kthread+0x109/0x140
+ ret_from_fork+0x2a/0x40
+
+Fix the leak by adding the missing call to kobject_put() to
+sysfs_slab_remove_workfn().
+
+Link: http://lkml.kernel.org/r/20170812181134.25027-1-vdavydov.dev@gmail.com
+Fixes: 3b7b314053d02 ("slub: make sysfs file removal asynchronous")
+Signed-off-by: Vladimir Davydov <vdavydov.dev@gmail.com>
+Reported-by: Andrei Vagin <avagin@gmail.com>
+Tested-by: Andrei Vagin <avagin@gmail.com>
+Acked-by: Tejun Heo <tj@kernel.org>
+Acked-by: David Rientjes <rientjes@google.com>
+Cc: Michal Hocko <mhocko@kernel.org>
+Cc: Johannes Weiner <hannes@cmpxchg.org>
+Cc: Christoph Lameter <cl@linux.com>
+Cc: Pekka Enberg <penberg@kernel.org>
+Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ mm/slub.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/mm/slub.c
++++ b/mm/slub.c
+@@ -5637,13 +5637,14 @@ static void sysfs_slab_remove_workfn(str
+ * A cache is never shut down before deactivation is
+ * complete, so no need to worry about synchronization.
+ */
+- return;
++ goto out;
+
+ #ifdef CONFIG_MEMCG
+ kset_unregister(s->memcg_kset);
+ #endif
+ kobject_uevent(&s->kobj, KOBJ_REMOVE);
+ kobject_del(&s->kobj);
++out:
+ kobject_put(&s->kobj);
+ }
+