From: Greg Kroah-Hartman Date: Wed, 21 Nov 2012 01:36:57 +0000 (-0800) Subject: 3.4-stable patches X-Git-Tag: v3.0.53~23^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=de84fc9f4da020e33814d9171487cde7e0fc3091;p=thirdparty%2Fkernel%2Fstable-queue.git 3.4-stable patches added patches: drm-i915-fix-overlay-on-i830m.patch ecryptfs-check-for-ecryptfs-cipher-support-at-mount.patch ecryptfs-copy-up-posix-acl-and-read-only-flags-from-lower-mount.patch nfs-wait-for-session-recovery-to-finish-before-returning.patch s390-signal-set-correct-address-space-control.patch sky2-fix-for-interrupt-handler.patch usb-use-usb_serial_put-in-usb_serial_probe-errors.patch --- diff --git a/queue-3.4/drm-i915-fix-overlay-on-i830m.patch b/queue-3.4/drm-i915-fix-overlay-on-i830m.patch new file mode 100644 index 00000000000..ecbda039717 --- /dev/null +++ b/queue-3.4/drm-i915-fix-overlay-on-i830m.patch @@ -0,0 +1,83 @@ +From a9193983f4f292a82a00c72971c17ec0ee8c6c15 Mon Sep 17 00:00:00 2001 +From: Daniel Vetter +Date: Mon, 22 Oct 2012 12:55:55 +0200 +Subject: drm/i915: fix overlay on i830M + +From: Daniel Vetter + +commit a9193983f4f292a82a00c72971c17ec0ee8c6c15 upstream. + +The overlay on the i830M has a peculiar failure mode: It works the +first time around after boot-up, but consistenly hangs the second time +it's used. + +Chris Wilson has dug out a nice errata: + +"1.5.12 Clock Gating Disable for Display Register +Address Offset: 06200h–06203h + +"Bit 3 +Ovrunit Clock Gating Disable. +0 = Clock gating controlled by unit enabling logic +1 = Disable clock gating function +DevALM Errata ALM049: Overlay Clock Gating Must be Disabled: Overlay +& L2 Cache clock gating must be disabled in order to prevent device +hangs when turning off overlay.SW must turn off Ovrunit clock gating +(6200h) and L2 Cache clock gating (C8h)." + +Now I've nowhere found that 0xc8 register and hence couldn't apply the +l2 cache workaround. But I've remembered that part of the magic that +the OVERLAY_ON/OFF commands are supposed to do is to rearrange cache +allocations so that the overlay scaler has some scratch space. + +And while pondering how that could explain the hang the 2nd time we +enable the overlay, I've remembered that the old ums overlay code did +_not_ issue the OVERLAY_OFF cmd. + +And indeed, disabling the OFF cmd results in the overlay working +flawlessly, so I guess we can workaround the lack of the above +workaround by simply never disabling the overlay engine once it's +enabled. + +Note that we have the first part of the above w/a already implemented +in i830_init_clock_gating - leave that as-is to avoid surprises. + +v2: Add a comment in the code. + +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=47827 +Tested-by: Rhys +Reviewed-by: Chris Wilson +Signed-off-by: Daniel Vetter +[bwh: Backported to 3.2: + - Adjust context + - s/intel_ring_emit(ring, /OUT_RING(/] +Signed-off-by: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/intel_overlay.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/i915/intel_overlay.c ++++ b/drivers/gpu/drm/i915/intel_overlay.c +@@ -427,9 +427,17 @@ static int intel_overlay_off(struct inte + OUT_RING(flip_addr); + OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); + /* turn overlay off */ +- OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF); +- OUT_RING(flip_addr); +- OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); ++ if (IS_I830(dev)) { ++ /* Workaround: Don't disable the overlay fully, since otherwise ++ * it dies on the next OVERLAY_ON cmd. */ ++ OUT_RING(MI_NOOP); ++ OUT_RING(MI_NOOP); ++ OUT_RING(MI_NOOP); ++ } else { ++ OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF); ++ OUT_RING(flip_addr); ++ OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); ++ } + ADVANCE_LP_RING(); + + return intel_overlay_do_wait_request(overlay, request, diff --git a/queue-3.4/ecryptfs-check-for-ecryptfs-cipher-support-at-mount.patch b/queue-3.4/ecryptfs-check-for-ecryptfs-cipher-support-at-mount.patch new file mode 100644 index 00000000000..98dea31708f --- /dev/null +++ b/queue-3.4/ecryptfs-check-for-ecryptfs-cipher-support-at-mount.patch @@ -0,0 +1,55 @@ +From 5f5b331d5c21228a6519dcb793fc1629646c51a6 Mon Sep 17 00:00:00 2001 +From: Tim Sally +Date: Thu, 12 Jul 2012 19:10:24 -0400 +Subject: eCryptfs: check for eCryptfs cipher support at mount + +From: Tim Sally + +commit 5f5b331d5c21228a6519dcb793fc1629646c51a6 upstream. + +The issue occurs when eCryptfs is mounted with a cipher supported by +the crypto subsystem but not by eCryptfs. The mount succeeds and an +error does not occur until a write. This change checks for eCryptfs +cipher support at mount time. + +Resolves Launchpad issue #338914, reported by Tyler Hicks in 03/2009. +https://bugs.launchpad.net/ecryptfs/+bug/338914 + +Signed-off-by: Tim Sally +Signed-off-by: Tyler Hicks +Cc: Herton Ronaldo Krzesinski +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ecryptfs/main.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/fs/ecryptfs/main.c ++++ b/fs/ecryptfs/main.c +@@ -280,6 +280,7 @@ static int ecryptfs_parse_options(struct + char *fnek_src; + char *cipher_key_bytes_src; + char *fn_cipher_key_bytes_src; ++ u8 cipher_code; + + *check_ruid = 0; + +@@ -421,6 +422,18 @@ static int ecryptfs_parse_options(struct + && !fn_cipher_key_bytes_set) + mount_crypt_stat->global_default_fn_cipher_key_bytes = + mount_crypt_stat->global_default_cipher_key_size; ++ ++ cipher_code = ecryptfs_code_for_cipher_string( ++ mount_crypt_stat->global_default_cipher_name, ++ mount_crypt_stat->global_default_cipher_key_size); ++ if (!cipher_code) { ++ ecryptfs_printk(KERN_ERR, ++ "eCryptfs doesn't support cipher: %s", ++ mount_crypt_stat->global_default_cipher_name); ++ rc = -EINVAL; ++ goto out; ++ } ++ + mutex_lock(&key_tfm_list_mutex); + if (!ecryptfs_tfm_exists(mount_crypt_stat->global_default_cipher_name, + NULL)) { diff --git a/queue-3.4/ecryptfs-copy-up-posix-acl-and-read-only-flags-from-lower-mount.patch b/queue-3.4/ecryptfs-copy-up-posix-acl-and-read-only-flags-from-lower-mount.patch new file mode 100644 index 00000000000..143bc66d94c --- /dev/null +++ b/queue-3.4/ecryptfs-copy-up-posix-acl-and-read-only-flags-from-lower-mount.patch @@ -0,0 +1,64 @@ +From 069ddcda37b2cf5bb4b6031a944c0e9359213262 Mon Sep 17 00:00:00 2001 +From: Tyler Hicks +Date: Mon, 11 Jun 2012 15:42:32 -0700 +Subject: eCryptfs: Copy up POSIX ACL and read-only flags from lower mount + +From: Tyler Hicks + +commit 069ddcda37b2cf5bb4b6031a944c0e9359213262 upstream. + +When the eCryptfs mount options do not include '-o acl', but the lower +filesystem's mount options do include 'acl', the MS_POSIXACL flag is not +flipped on in the eCryptfs super block flags. This flag is what the VFS +checks in do_last() when deciding if the current umask should be applied +to a newly created inode's mode or not. When a default POSIX ACL mask is +set on a directory, the current umask is incorrectly applied to new +inodes created in the directory. This patch ignores the MS_POSIXACL flag +passed into ecryptfs_mount() and sets the flag on the eCryptfs super +block depending on the flag's presence on the lower super block. + +Additionally, it is incorrect to allow a writeable eCryptfs mount on top +of a read-only lower mount. This missing check did not allow writes to +the read-only lower mount because permissions checks are still performed +on the lower filesystem's objects but it is best to simply not allow a +rw mount on top of ro mount. However, a ro eCryptfs mount on top of a rw +mount is valid and still allowed. + +https://launchpad.net/bugs/1009207 + +Signed-off-by: Tyler Hicks +Reported-by: Stefan Beller +Cc: John Johansen +Cc: Herton Ronaldo Krzesinski +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ecryptfs/main.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +--- a/fs/ecryptfs/main.c ++++ b/fs/ecryptfs/main.c +@@ -506,7 +506,6 @@ static struct dentry *ecryptfs_mount(str + goto out; + } + +- s->s_flags = flags; + rc = bdi_setup_and_register(&sbi->bdi, "ecryptfs", BDI_CAP_MAP_COPY); + if (rc) + goto out1; +@@ -542,6 +541,15 @@ static struct dentry *ecryptfs_mount(str + } + + ecryptfs_set_superblock_lower(s, path.dentry->d_sb); ++ ++ /** ++ * Set the POSIX ACL flag based on whether they're enabled in the lower ++ * mount. Force a read-only eCryptfs mount if the lower mount is ro. ++ * Allow a ro eCryptfs mount even when the lower mount is rw. ++ */ ++ s->s_flags = flags & ~MS_POSIXACL; ++ s->s_flags |= path.dentry->d_sb->s_flags & (MS_RDONLY | MS_POSIXACL); ++ + s->s_maxbytes = path.dentry->d_sb->s_maxbytes; + s->s_blocksize = path.dentry->d_sb->s_blocksize; + s->s_magic = ECRYPTFS_SUPER_MAGIC; diff --git a/queue-3.4/nfs-wait-for-session-recovery-to-finish-before-returning.patch b/queue-3.4/nfs-wait-for-session-recovery-to-finish-before-returning.patch new file mode 100644 index 00000000000..d68b156d371 --- /dev/null +++ b/queue-3.4/nfs-wait-for-session-recovery-to-finish-before-returning.patch @@ -0,0 +1,48 @@ +From 399f11c3d872bd748e1575574de265a6304c7c43 Mon Sep 17 00:00:00 2001 +From: Bryan Schumaker +Date: Tue, 30 Oct 2012 16:06:35 -0400 +Subject: NFS: Wait for session recovery to finish before returning + +From: Bryan Schumaker + +commit 399f11c3d872bd748e1575574de265a6304c7c43 upstream. + +Currently, we will schedule session recovery and then return to the +caller of nfs4_handle_exception. This works for most cases, but causes +a hang on the following test case: + + Client Server + ------ ------ + Open file over NFS v4.1 + Write to file + Expire client + Try to lock file + +The server will return NFS4ERR_BADSESSION, prompting the client to +schedule recovery. However, the client will continue placing lock +attempts and the open recovery never seems to be scheduled. The +simplest solution is to wait for session recovery to run before retrying +the lock. + +Signed-off-by: Bryan Schumaker +Signed-off-by: Trond Myklebust +[bwh: Backported to 3.2: adjust context] +Signed-off-by: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/nfs4proc.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -307,8 +307,7 @@ static int nfs4_handle_exception(struct + dprintk("%s ERROR: %d Reset session\n", __func__, + errorcode); + nfs4_schedule_session_recovery(clp->cl_session); +- exception->retry = 1; +- break; ++ goto wait_on_recovery; + #endif /* defined(CONFIG_NFS_V4_1) */ + case -NFS4ERR_FILE_OPEN: + if (exception->timeout > HZ) { diff --git a/queue-3.4/s390-signal-set-correct-address-space-control.patch b/queue-3.4/s390-signal-set-correct-address-space-control.patch new file mode 100644 index 00000000000..1d0244397f1 --- /dev/null +++ b/queue-3.4/s390-signal-set-correct-address-space-control.patch @@ -0,0 +1,137 @@ +From fa968ee215c0ca91e4a9c3a69ac2405aae6e5d2f Mon Sep 17 00:00:00 2001 +From: Martin Schwidefsky +Date: Wed, 7 Nov 2012 10:44:08 +0100 +Subject: s390/signal: set correct address space control + +From: Martin Schwidefsky + +commit fa968ee215c0ca91e4a9c3a69ac2405aae6e5d2f upstream. + +If user space is running in primary mode it can switch to secondary +or access register mode, this is used e.g. in the clock_gettime code +of the vdso. If a signal is delivered to the user space process while +it has been running in access register mode the signal handler is +executed in access register mode as well which will result in a crash +most of the time. + +Set the address space control bits in the PSW to the default for the +execution of the signal handler and make sure that the previous +address space control is restored on signal return. Take care +that user space can not switch to the kernel address space by +modifying the registers in the signal frame. + +Signed-off-by: Martin Schwidefsky +Signed-off-by: Greg Kroah-Hartman + +--- + arch/s390/include/asm/compat.h | 2 +- + arch/s390/include/asm/ptrace.h | 4 ++-- + arch/s390/kernel/compat_signal.c | 14 ++++++++++++-- + arch/s390/kernel/signal.c | 14 ++++++++++++-- + 4 files changed, 27 insertions(+), 7 deletions(-) + +--- a/arch/s390/include/asm/compat.h ++++ b/arch/s390/include/asm/compat.h +@@ -20,7 +20,7 @@ + #define PSW32_MASK_CC 0x00003000UL + #define PSW32_MASK_PM 0x00000f00UL + +-#define PSW32_MASK_USER 0x00003F00UL ++#define PSW32_MASK_USER 0x0000FF00UL + + #define PSW32_ADDR_AMODE 0x80000000UL + #define PSW32_ADDR_INSN 0x7FFFFFFFUL +--- a/arch/s390/include/asm/ptrace.h ++++ b/arch/s390/include/asm/ptrace.h +@@ -240,7 +240,7 @@ typedef struct + #define PSW_MASK_EA 0x00000000UL + #define PSW_MASK_BA 0x00000000UL + +-#define PSW_MASK_USER 0x00003F00UL ++#define PSW_MASK_USER 0x0000FF00UL + + #define PSW_ADDR_AMODE 0x80000000UL + #define PSW_ADDR_INSN 0x7FFFFFFFUL +@@ -269,7 +269,7 @@ typedef struct + #define PSW_MASK_EA 0x0000000100000000UL + #define PSW_MASK_BA 0x0000000080000000UL + +-#define PSW_MASK_USER 0x00003F0180000000UL ++#define PSW_MASK_USER 0x0000FF0180000000UL + + #define PSW_ADDR_AMODE 0x0000000000000000UL + #define PSW_ADDR_INSN 0xFFFFFFFFFFFFFFFFUL +--- a/arch/s390/kernel/compat_signal.c ++++ b/arch/s390/kernel/compat_signal.c +@@ -313,6 +313,10 @@ static int restore_sigregs32(struct pt_r + regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) | + (__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32 | + (__u64)(regs32.psw.addr & PSW32_ADDR_AMODE); ++ /* Check for invalid user address space control. */ ++ if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC)) ++ regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) | ++ (regs->psw.mask & ~PSW_MASK_ASC); + regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN); + for (i = 0; i < NUM_GPRS; i++) + regs->gprs[i] = (__u64) regs32.gprs[i]; +@@ -494,7 +498,10 @@ static int setup_frame32(int sig, struct + + /* Set up registers for signal handler */ + regs->gprs[15] = (__force __u64) frame; +- regs->psw.mask |= PSW_MASK_BA; /* force amode 31 */ ++ /* Force 31 bit amode and default user address space control. */ ++ regs->psw.mask = PSW_MASK_BA | ++ (psw_user_bits & PSW_MASK_ASC) | ++ (regs->psw.mask & ~PSW_MASK_ASC); + regs->psw.addr = (__force __u64) ka->sa.sa_handler; + + regs->gprs[2] = map_signal(sig); +@@ -562,7 +569,10 @@ static int setup_rt_frame32(int sig, str + + /* Set up registers for signal handler */ + regs->gprs[15] = (__force __u64) frame; +- regs->psw.mask |= PSW_MASK_BA; /* force amode 31 */ ++ /* Force 31 bit amode and default user address space control. */ ++ regs->psw.mask = PSW_MASK_BA | ++ (psw_user_bits & PSW_MASK_ASC) | ++ (regs->psw.mask & ~PSW_MASK_ASC); + regs->psw.addr = (__u64) ka->sa.sa_handler; + + regs->gprs[2] = map_signal(sig); +--- a/arch/s390/kernel/signal.c ++++ b/arch/s390/kernel/signal.c +@@ -148,6 +148,10 @@ static int restore_sigregs(struct pt_reg + /* Use regs->psw.mask instead of psw_user_bits to preserve PER bit. */ + regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) | + (user_sregs.regs.psw.mask & PSW_MASK_USER); ++ /* Check for invalid user address space control. */ ++ if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC)) ++ regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) | ++ (regs->psw.mask & ~PSW_MASK_ASC); + /* Check for invalid amode */ + if (regs->psw.mask & PSW_MASK_EA) + regs->psw.mask |= PSW_MASK_BA; +@@ -294,7 +298,10 @@ static int setup_frame(int sig, struct k + + /* Set up registers for signal handler */ + regs->gprs[15] = (unsigned long) frame; +- regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA; /* 64 bit amode */ ++ /* Force default amode and default user address space control. */ ++ regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA | ++ (psw_user_bits & PSW_MASK_ASC) | ++ (regs->psw.mask & ~PSW_MASK_ASC); + regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE; + + regs->gprs[2] = map_signal(sig); +@@ -367,7 +374,10 @@ static int setup_rt_frame(int sig, struc + + /* Set up registers for signal handler */ + regs->gprs[15] = (unsigned long) frame; +- regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA; /* 64 bit amode */ ++ /* Force default amode and default user address space control. */ ++ regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA | ++ (psw_user_bits & PSW_MASK_ASC) | ++ (regs->psw.mask & ~PSW_MASK_ASC); + regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE; + + regs->gprs[2] = map_signal(sig); diff --git a/queue-3.4/series b/queue-3.4/series index 6d0e5b73469..b5b2ebe8976 100644 --- a/queue-3.4/series +++ b/queue-3.4/series @@ -32,3 +32,10 @@ r8169-allow-multicast-packets-on-sub-8168f-chipset.patch netfilter-validate-the-sequence-number-of-dataless-ack-packets-as-well.patch netfilter-mark-syn-ack-packets-as-invalid-from-original-direction.patch netfilter-nf_nat-don-t-check-for-port-change-on-icmp-tuples.patch +usb-use-usb_serial_put-in-usb_serial_probe-errors.patch +ecryptfs-copy-up-posix-acl-and-read-only-flags-from-lower-mount.patch +ecryptfs-check-for-ecryptfs-cipher-support-at-mount.patch +sky2-fix-for-interrupt-handler.patch +s390-signal-set-correct-address-space-control.patch +drm-i915-fix-overlay-on-i830m.patch +nfs-wait-for-session-recovery-to-finish-before-returning.patch diff --git a/queue-3.4/sky2-fix-for-interrupt-handler.patch b/queue-3.4/sky2-fix-for-interrupt-handler.patch new file mode 100644 index 00000000000..e7971a8d34b --- /dev/null +++ b/queue-3.4/sky2-fix-for-interrupt-handler.patch @@ -0,0 +1,34 @@ +From d663d181b9e92d80c2455e460e932d34e7a2a7ae Mon Sep 17 00:00:00 2001 +From: Mirko Lindner +Date: Tue, 3 Jul 2012 23:38:46 +0000 +Subject: sky2: Fix for interrupt handler + +From: Mirko Lindner + +commit d663d181b9e92d80c2455e460e932d34e7a2a7ae upstream. + +Re-enable interrupts if it is not our interrupt + +Signed-off-by: Mirko Lindner +Signed-off-by: David S. Miller +Cc: Jonathan Nieder +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/ethernet/marvell/sky2.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/marvell/sky2.c ++++ b/drivers/net/ethernet/marvell/sky2.c +@@ -3079,8 +3079,10 @@ static irqreturn_t sky2_intr(int irq, vo + + /* Reading this mask interrupts as side effect */ + status = sky2_read32(hw, B0_Y2_SP_ISRC2); +- if (status == 0 || status == ~0) ++ if (status == 0 || status == ~0) { ++ sky2_write32(hw, B0_Y2_SP_ICR, 2); + return IRQ_NONE; ++ } + + prefetch(&hw->st_le[hw->st_idx]); + diff --git a/queue-3.4/usb-use-usb_serial_put-in-usb_serial_probe-errors.patch b/queue-3.4/usb-use-usb_serial_put-in-usb_serial_probe-errors.patch new file mode 100644 index 00000000000..f6dd3380a1b --- /dev/null +++ b/queue-3.4/usb-use-usb_serial_put-in-usb_serial_probe-errors.patch @@ -0,0 +1,52 @@ +From 0658a3366db7e27fa32c12e886230bb58c414c92 Mon Sep 17 00:00:00 2001 +From: Jan Safrata +Date: Tue, 22 May 2012 14:04:50 +0200 +Subject: usb: use usb_serial_put in usb_serial_probe errors + +From: Jan Safrata + +commit 0658a3366db7e27fa32c12e886230bb58c414c92 upstream. + +The use of kfree(serial) in error cases of usb_serial_probe +was invalid - usb_serial structure allocated in create_serial() +gets reference of usb_device that needs to be put, so we need +to use usb_serial_put() instead of simple kfree(). + +Signed-off-by: Jan Safrata +Acked-by: Johan Hovold +Cc: Richard Retanubun +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/usb-serial.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/usb/serial/usb-serial.c ++++ b/drivers/usb/serial/usb-serial.c +@@ -768,7 +768,7 @@ int usb_serial_probe(struct usb_interfac + + if (retval) { + dbg("sub driver rejected device"); +- kfree(serial); ++ usb_serial_put(serial); + module_put(type->driver.owner); + return retval; + } +@@ -840,7 +840,7 @@ int usb_serial_probe(struct usb_interfac + */ + if (num_bulk_in == 0 || num_bulk_out == 0) { + dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n"); +- kfree(serial); ++ usb_serial_put(serial); + module_put(type->driver.owner); + return -ENODEV; + } +@@ -854,7 +854,7 @@ int usb_serial_probe(struct usb_interfac + if (num_ports == 0) { + dev_err(&interface->dev, + "Generic device with no bulk out, not allowed.\n"); +- kfree(serial); ++ usb_serial_put(serial); + module_put(type->driver.owner); + return -EIO; + }