Skip to contentSkip to conversation

3.6.4-stable review

PATCH In review Greg Kroah-Hartman 5 participants 93 messages Oct 26, 2012 – Nov 1, 2012

Subsystems (49)
lore
Share & tools
lore

Greg Kroah-Hartman

author maintainer
#0 lore raw

cover 3.6.4-stable review

This is the start of the stable review cycle for the 3.6.4 release. There are 85 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.

Responses should be made by Sat Oct 27 23:59:01 UTC 2012. Anything received after that time might be too late.

The whole patch series can be found in one patch at:

	kernel.org/pub/linux/kernel/v3.0/stable-review/patch-3.6.4-rc1.gz

and the diffstat can be found below.

thanks,

greg k-h

-------------
Pseudo-Shortlog of commits:

Thomas Pedersen <[email protected]>
mac80211: call drv_get_tsf() in sleepable context

David S. Miller <[email protected]>
sparc64: Fix bit twiddling in sparc_pmu_enable_event().

David S. Miller <[email protected]>

    sparc64: Like x86 we should check current->mm during perf backtrace generation.

Al Viro <[email protected]>
sparc64: fix ptrace interaction with force_successful_syscall_return()

Eric Dumazet <[email protected]>
ipv6: addrconf: fix /proc/net/if_inet6

Alexey Kuznetsov <[email protected]>
tcp: resets are misrouted

jeff.liu <[email protected]>
RDS: fix rds-ping spinlock recursion

Julian Anastasov <[email protected]>
ipvs: fix ARP resolving for direct routing mode

Julian Anastasov <[email protected]>
ipv4: Add FLOWI_FLAG_KNOWN_NH

Julian Anastasov <[email protected]>
ipv4: introduce rt_uses_gateway

Julian Anastasov <[email protected]>
ipv4: make sure nh_pcpu_rth_output is always allocated

Julian Anastasov <[email protected]>
ipv4: fix forwarding for strict source routes

Julian Anastasov <[email protected]>
ipv4: fix sending of redirects

Florian Zumbiehl <[email protected]>
vlan: don't deliver frames for unknown vlans to protocols

Graham Gower <[email protected]>
skge: Add DMA mask quirk for Marvell 88E8001 on ASUS P5NSLI motherboard

Steffen Klassert <[email protected]>
ipv4: Don't report stale pmtu values to userspace

Steffen Klassert <[email protected]>
ipv4: Don't create nh exeption when the device mtu is smaller than the reported pmtu

Steffen Klassert <[email protected]>
ipv4: Always invalidate or update the route on pmtu events

Eric Dumazet <[email protected]>
ipv6: GRO should be ECN friendly

[email protected] <[email protected]>
net: Fix skb_under_panic oops in neigh_resolve_output

Eric Dumazet <[email protected]>
net: remove skb recycling

Gao feng <[email protected]>
infiniband: pass rdma_cm module to netlink_dump_start

Gao feng <[email protected]>
netlink: add reference of module in netlink_dump_start

Chris Wilson <[email protected]>
drm/i915: Use cpu relocations if the object is in the GTT but not mappable

Devin Heitmueller <[email protected]>
media: au0828: fix case where STREAMOFF being called on stopped stream causes BUG()

Chris Zankel <[email protected]>
xtensa: add missing system calls to the syscall table

Andrew Morton <[email protected]>

    amd64_edac:__amd64_set_scrub_rate(): avoid overindexing scrubrates[]

Hiro Sugawara <[email protected]>
iommu/tegra: smmu: Fix deadly typo

Wei Yongjun <[email protected]>
pinctrl: fix missing unlock on error in pinctrl_groups_show()

Haojian Zhuang <[email protected]>
pinctrl: remove mutex lock in groups show

Pritesh Raithatha <[email protected]>
pinctrl: tegra: set low power mode bank width to 2

Pritesh Raithatha <[email protected]>
dt: Document: correct tegra20/30 pinctrl slew-rate name

Pritesh Raithatha <[email protected]>
pinctrl: tegra: correct bank for pingroup and drv pingroup

Tejun Heo <[email protected]>
Revert "cgroup: Drop task_lock(parent) on cgroup_fork()"

Tejun Heo <[email protected]>
Revert "cgroup: Remove task_lock() from cgroup_post_fork()"

Daisuke Nishimura <[email protected]>
cgroup: notify_on_release may not be triggered in some cases

Alan Stern <[email protected]>
USB: fix port probing and removal in garmin_gps

Sarah Sharp <[email protected]>
usb: Send Set SEL before enabling parent U1/U2 timeout.

Sarah Sharp <[email protected]>
USB: Enable LPM after a failed probe.

Sarah Sharp <[email protected]>
usb: Don't enable LPM if the exit latency is zero.

Felipe Balbi <[email protected]>
usb: dwc3: gadget: fix 'endpoint always busy' bug

Bjørn Mork <[email protected]>
USB: option: add more ZTE devices

Bjørn Mork <[email protected]>
USB: option: blacklist net interface on ZTE devices

Johan Hovold <[email protected]>
USB: keyspan_pda: fix port-data memory leak

Johan Hovold <[email protected]>
USB: io_edgeport: fix port-data memory leak

Johan Hovold <[email protected]>
USB: kl5kusb105: fix port-data memory leak

Johan Hovold <[email protected]>

    USB: ti_usb_3410_5052: fix port-data memory leak

Johan Hovold <[email protected]>
USB: spcp8x5: fix port-data memory leak

Johan Hovold <[email protected]>

    USB: cp210x: fix port-data memory leak

Johan Hovold <[email protected]>
USB: cypress_m8: fix port-data memory leak

Johan Hovold <[email protected]>
USB: kobil_sct: fix port-data memory leak

Johan Hovold <[email protected]>
USB: ssu100: fix port-data memory leak

Johan Hovold <[email protected]>
USB: pl2303: fix port-data memory leak

Johan Hovold <[email protected]>
USB: belkin_sa: fix port-data memory leak

Johan Hovold <[email protected]>
USB: oti6858: fix port-data memory leak

Johan Hovold <[email protected]>
USB: f81232: fix port-data memory leak

Johan Hovold <[email protected]>
USB: ark3116: fix NULL-pointer dereference

Johan Hovold <[email protected]>
USB: iuu_phoenix: fix sysfs-attribute creation

Johan Hovold <[email protected]>
USB: iuu_phoenix: fix port-data memory leak

Alexis R. Cortes <[email protected]>
usb: host: xhci: New system added for Compliance Mode Patch on SN65LVPE502CP

Stefano Babic <[email protected]>
usb: musb: am35xx: drop spurious unplugging a device

Johan Hovold <[email protected]>
USB: cyberjack: fix port-data memory leak

Johan Hovold <[email protected]>
USB: io_ti: fix sysfs-attribute creation

Johan Hovold <[email protected]>
USB: io_ti: fix port-data memory leak

Nicolas Boullis <[email protected]>
usb: acm: fix the computation of the number of data bits

Ming Lei <[email protected]>
USB: cdc-acm: fix pipe type of write endpoint

David Vrabel <[email protected]>
xen/x86: don't corrupt %eip when returning from a signal handler

Jacob Shin <[email protected]>
x86: Exclude E820_RESERVED regions and memory holes above 4 GB from direct mapping.

Daniel J Blueman <[email protected]>
x86, amd, mce: Avoid NULL pointer reference on CPU northbridge lookup

Kees Cook <[email protected]>
use clamp_t in UNAME26 fix

Kees Cook <[email protected]>
kernel/sys.c: fix stack memory content leak via UNAME26

Arnd Bergmann <[email protected]>
pcmcia: sharpsl: don't discard sharpsl_pcmcia_ops

Vaibhav Nagarnaik <[email protected]>
ring-buffer: Check for uninitialized cpu buffer before resizing

Bryan Schumaker <[email protected]>
SUNRPC: Set alloc_slot for backchannel tcp ops

Sasha Levin <[email protected]>
SUNRPC: Prevent kernel stack corruption on long values of flush

Heiko Carstens <[email protected]>
s390: fix linker script for 31 bit builds

Dan Carpenter <[email protected]>
oprofile, x86: Fix wrapping bug in op_x86_get_ctrl()

Trond Myklebust <[email protected]>
NLM: nlm_lookup_file() may return NLMv4-specific error codes

Chris Metcalf <[email protected]>
arch/tile: avoid generating .eh_frame information in modules

Michal Hocko <[email protected]>
nohz: Fix idle ticks in cpu summary line of /proc/stat

Guenter Roeck <[email protected]>

    hwmon: (coretemp) Add support for Atom CE4110/4150/4170

Henrik Rydberg <[email protected]>
usbdevfs: Fix broken scatter-gather transfer

Lukas Czerner <[email protected]>
ext4: Avoid underflow in ext4_trim_fs()

Tao Ma <[email protected]>
ext4: Checksum the block bitmap properly with bigalloc enabled

Dmitry Monakhov <[email protected]>
ext4: race-condition protection for ext4_convert_unwritten_extents_endio

-------------

Diffstat:

 .../bindings/pinctrl/nvidia,tegra20-pinmux.txt      |   2 +-
 .../bindings/pinctrl/nvidia,tegra30-pinmux.txt      |   2 +-
 Documentation/hwmon/coretemp                        |   1 +
 Makefile                                            |   4 +-
 arch/s390/boot/compressed/vmlinux.lds.S             |   2 +-
 arch/s390/kernel/vmlinux.lds.S                      |   2 +-
 arch/sparc/kernel/perf_event.c                      |  15 ++-
 arch/sparc/kernel/syscalls.S                        |  32 ++---
 arch/tile/Makefile                                  |   4 +
 arch/x86/kernel/cpu/mcheck/mce_amd.c                |  10 +-
 arch/x86/kernel/entry_32.S                          |   8 +-
 arch/x86/kernel/entry_64.S                          |   2 +-
 arch/x86/kernel/setup.c                             |  17 ++-
 arch/x86/oprofile/nmi_int.c                         |   2 +-
 arch/xtensa/include/asm/unistd.h                    |  91 ++++++++++---
 drivers/edac/amd64_edac.c                           |  11 +-
 drivers/gpu/drm/i915/i915_gem_execbuffer.c          |   1 +
 drivers/hwmon/coretemp.c                            |   7 +-
 drivers/infiniband/core/cma.c                       |   3 +-
 drivers/infiniband/core/netlink.c                   |   1 +
 drivers/iommu/tegra-smmu.c                          |   2 +-
 drivers/media/video/au0828/au0828-video.c           |  12 +-
 drivers/net/ethernet/calxeda/xgmac.c                |  19 +--
 drivers/net/ethernet/freescale/gianfar.c            |  27 +---
 drivers/net/ethernet/freescale/gianfar.h            |   2 -
 drivers/net/ethernet/freescale/ucc_geth.c           |  29 +---
 drivers/net/ethernet/freescale/ucc_geth.h           |   2 -
 drivers/net/ethernet/marvell/mv643xx_eth.c          |  18 +--
 drivers/net/ethernet/marvell/skge.c                 |   7 +
 drivers/net/ethernet/stmicro/stmmac/stmmac.h        |   1 -
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c   |  20 +--
 drivers/pcmcia/pxa2xx_sharpsl.c                     |   2 +-
 drivers/pinctrl/core.c                              |   4 +-
 drivers/pinctrl/pinconf.c                           |   4 -
 drivers/pinctrl/pinctrl-tegra.c                     |   2 +-
 drivers/pinctrl/pinctrl-tegra30.c                   |  24 ++--
 drivers/usb/class/cdc-acm.c                         |  22 +++-
 drivers/usb/core/devio.c                            |   1 +
 drivers/usb/core/driver.c                           |   4 +
 drivers/usb/core/hub.c                              |  33 +++--
 drivers/usb/dwc3/gadget.c                           |   1 +
 drivers/usb/host/xhci.c                             |   3 +-
 drivers/usb/musb/am35x.c                            |   6 +
 drivers/usb/serial/ark3116.c                        |  26 ++--
 drivers/usb/serial/belkin_sa.c                      |  31 +++--
 drivers/usb/serial/cp210x.c                         |  41 +++---
 drivers/usb/serial/cyberjack.c                      |  48 +++----
 drivers/usb/serial/cypress_m8.c                     |  82 ++++++------
 drivers/usb/serial/f81232.c                         |  43 +++---
 drivers/usb/serial/garmin_gps.c                     |  24 +---
 drivers/usb/serial/io_edgeport.c                    |  54 ++++----
 drivers/usb/serial/io_tables.h                      |   8 ++
 drivers/usb/serial/io_ti.c                          |  91 +++++++------
 drivers/usb/serial/iuu_phoenix.c                    |  84 ++++++------
 drivers/usb/serial/keyspan_pda.c                    |  30 +++--
 drivers/usb/serial/kl5kusb105.c                     |  66 ++++------
 drivers/usb/serial/kobil_sct.c                      |  23 ++--
 drivers/usb/serial/option.c                         |  84 +++++++++---
 drivers/usb/serial/oti6858.c                        |  68 ++++------
 drivers/usb/serial/pl2303.c                         |  90 ++++++++-----
 drivers/usb/serial/spcp8x5.c                        |  46 +++----
 drivers/usb/serial/ssu100.c                         |  34 +++--
 drivers/usb/serial/ti_usb_3410_5052.c               |  88 ++++++-------
 fs/ext4/balloc.c                                    |   8 +-
 fs/ext4/bitmap.c                                    |   6 +-
 fs/ext4/ext4.h                                      |   4 +-
 fs/ext4/extents.c                                   |  57 ++++++--
 fs/ext4/ialloc.c                                    |   4 +-
 fs/ext4/mballoc.c                                   |  14 +-
 fs/ext4/resize.c                                    |   3 +-
 fs/lockd/clntxdr.c                                  |   2 +-
 fs/lockd/svcproc.c                                  |   3 +-
 fs/proc/stat.c                                      |  14 +-
 include/linux/if_vlan.h                             |   8 +-
 include/linux/netlink.h                             |  21 ++-
 include/linux/skbuff.h                              |  24 ----
 include/net/flow.h                                  |   1 +
 include/net/route.h                                 |   3 +-
 include/rdma/rdma_netlink.h                         |   1 +
 kernel/cgroup.c                                     |  41 ++----
 kernel/sys.c                                        |  12 +-
 kernel/trace/ring_buffer.c                          |   4 +
 net/8021q/vlan_core.c                               |  10 +-
 net/core/dev.c                                      |   7 +-
 net/core/neighbour.c                                |   6 +-
 net/core/skbuff.c                                   |  47 -------
 net/ipv4/fib_frontend.c                             |   3 +-
 net/ipv4/fib_semantics.c                            |   2 +
 net/ipv4/inet_connection_sock.c                     |   4 +-
 net/ipv4/ip_forward.c                               |   2 +-
 net/ipv4/ip_output.c                                |   4 +-
 net/ipv4/route.c                                    | 146 ++++++++++++---------
 net/ipv4/tcp_ipv4.c                                 |   7 +-
 net/ipv4/xfrm4_policy.c                             |   1 +
 net/ipv6/addrconf.c                                 |  15 ++-
 net/ipv6/af_inet6.c                                 |  11 +-
 net/ipv6/tcp_ipv6.c                                 |   3 +-
 net/mac80211/mesh_sync.c                            |   3 +-
 net/netfilter/ipvs/ip_vs_xmit.c                     |   8 +-
 net/netlink/af_netlink.c                            |  29 ++--
 net/rds/send.c                                      |   2 +-
 net/sunrpc/cache.c                                  |   4 +-
 net/sunrpc/xprtsock.c                               |   1 +
 103 files changed, 1061 insertions(+), 1007 deletions(-)
author maintainer
#1 lore raw

PATCH 1/85 ext4: race-condition protection for ext4_convert_unwritten_extents_endio

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Dmitry Monakhov <[email protected]>

commit dee1f973ca341c266229faa5a1a5bb268bed3531 upstream.

We assumed that at the time we call ext4_convert_unwritten_extents_endio() extent in question is fully inside [map.m_lblk, map->m_len] because it was already split during submission. But this may not be true due to a race between writeback vs fallocate.

If extent in question is larger than requested we will split it again. Special precautions should being done if zeroout required because [map.m_lblk, map->m_len] already contains valid data.

---
 fs/ext4/extents.c |   57 +++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 46 insertions(+), 11 deletions(-)
fs/ext4/extents.c +46 -11
@@ -52,6 +52,9 @@
 #define EXT4_EXT_MARK_UNINIT1	0x2  /* mark first half uninitialized */
 #define EXT4_EXT_MARK_UNINIT2	0x4  /* mark second half uninitialized */
 
+#define EXT4_EXT_DATA_VALID1	0x8  /* first half contains valid data */
+#define EXT4_EXT_DATA_VALID2	0x10 /* second half contains valid data */
+
 static __le32 ext4_extent_block_csum(struct inode *inode,
 				     struct ext4_extent_header *eh)
 {
@@ -2895,6 +2898,9 @@ static int ext4_split_extent_at(handle_t
 	unsigned int ee_len, depth;
 	int err = 0;
 
+	BUG_ON((split_flag & (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2)) ==
+	       (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2));
+
 	ext_debug("ext4_split_extents_at: inode %lu, logical"
 		"block %llu\n", inode->i_ino, (unsigned long long)split);
 
@@ -2953,7 +2959,14 @@ static int ext4_split_extent_at(handle_t
 
 	err = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
 	if (err == -ENOSPC && (EXT4_EXT_MAY_ZEROOUT & split_flag)) {
-		err = ext4_ext_zeroout(inode, &orig_ex);
+		if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) {
+			if (split_flag & EXT4_EXT_DATA_VALID1)
+				err = ext4_ext_zeroout(inode, ex2);
+			else
+				err = ext4_ext_zeroout(inode, ex);
+		} else
+			err = ext4_ext_zeroout(inode, &orig_ex);
+
 		if (err)
 			goto fix_extent_len;
 		/* update the extent length and mark as initialized */
@@ -3006,12 +3019,13 @@ static int ext4_split_extent(handle_t *h
 	uninitialized = ext4_ext_is_uninitialized(ex);
 
 	if (map->m_lblk + map->m_len < ee_block + ee_len) {
-		split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ?
-			      EXT4_EXT_MAY_ZEROOUT : 0;
+		split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT;
 		flags1 = flags | EXT4_GET_BLOCKS_PRE_IO;
 		if (uninitialized)
 			split_flag1 |= EXT4_EXT_MARK_UNINIT1 |
 				       EXT4_EXT_MARK_UNINIT2;
+		if (split_flag & EXT4_EXT_DATA_VALID2)
+			split_flag1 |= EXT4_EXT_DATA_VALID1;
 		err = ext4_split_extent_at(handle, inode, path,
 				map->m_lblk + map->m_len, split_flag1, flags1);
 		if (err)
@@ -3024,8 +3038,8 @@ static int ext4_split_extent(handle_t *h
 		return PTR_ERR(path);
 
 	if (map->m_lblk >= ee_block) {
-		split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ?
-			      EXT4_EXT_MAY_ZEROOUT : 0;
+		split_flag1 = split_flag & (EXT4_EXT_MAY_ZEROOUT |
+					    EXT4_EXT_DATA_VALID2);
 		if (uninitialized)
 			split_flag1 |= EXT4_EXT_MARK_UNINIT1;
 		if (split_flag & EXT4_EXT_MARK_UNINIT2)
@@ -3303,26 +3317,47 @@ static int ext4_split_unwritten_extents(
 
 	split_flag |= ee_block + ee_len <= eof_block ? EXT4_EXT_MAY_ZEROOUT : 0;
 	split_flag |= EXT4_EXT_MARK_UNINIT2;
-
+	if (flags & EXT4_GET_BLOCKS_CONVERT)
+		split_flag |= EXT4_EXT_DATA_VALID2;
 	flags |= EXT4_GET_BLOCKS_PRE_IO;
 	return ext4_split_extent(handle, inode, path, map, split_flag, flags);
 }
 
 static int ext4_convert_unwritten_extents_endio(handle_t *handle,
-					      struct inode *inode,
-					      struct ext4_ext_path *path)
+						struct inode *inode,
+						struct ext4_map_blocks *map,
+						struct ext4_ext_path *path)
 {
 	struct ext4_extent *ex;
+	ext4_lblk_t ee_block;
+	unsigned int ee_len;
 	int depth;
 	int err = 0;
 
 	depth = ext_depth(inode);
 	ex = path[depth].p_ext;
+	ee_block = le32_to_cpu(ex->ee_block);
+	ee_len = ext4_ext_get_actual_len(ex);
 
 	ext_debug("ext4_convert_unwritten_extents_endio: inode %lu, logical"
 		"block %llu, max_blocks %u\n", inode->i_ino,
-		(unsigned long long)le32_to_cpu(ex->ee_block),
-		ext4_ext_get_actual_len(ex));
+		  (unsigned long long)ee_block, ee_len);
+
+	/* If extent is larger than requested then split is required */
+	if (ee_block != map->m_lblk || ee_len > map->m_len) {
+		err = ext4_split_unwritten_extents(handle, inode, map, path,
+						   EXT4_GET_BLOCKS_CONVERT);
+		if (err < 0)
+			goto out;
+		ext4_ext_drop_refs(path);
+		path = ext4_ext_find_extent(inode, map->m_lblk, path);
+		if (IS_ERR(path)) {
+			err = PTR_ERR(path);
+			goto out;
+		}
+		depth = ext_depth(inode);
+		ex = path[depth].p_ext;
+	}
 
 	err = ext4_ext_get_access(handle, inode, path + depth);
 	if (err)
@@ -3630,7 +3665,7 @@ ext4_ext_handle_uninitialized_extents(ha
 	}
 	/* IO end_io complete, convert the filled extent to written */
 	if ((flags & EXT4_GET_BLOCKS_CONVERT)) {
-		ret = ext4_convert_unwritten_extents_endio(handle, inode,
+		ret = ext4_convert_unwritten_extents_endio(handle, inode, map,
 							path);
 		if (ret >= 0) {
 			ext4_update_inode_fsync_trans(handle, inode, 1);
author maintainer
#2 lore raw

PATCH 2/85 ext4: Checksum the block bitmap properly with bigalloc enabled

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Tao Ma <[email protected]>

commit 79f1ba49569e5aec919b653c55b03274c2331701 upstream.

In mke2fs, we only checksum the whole bitmap block and it is right. While in the kernel, we use EXT4_BLOCKS_PER_GROUP to indicate the size of the checksumed bitmap which is wrong when we enable bigalloc. The right size should be EXT4_CLUSTERS_PER_GROUP and this patch fixes it.

Also as every caller of ext4_block_bitmap_csum_set and ext4_block_bitmap_csum_verify pass in EXT4_BLOCKS_PER_GROUP(sb)/8, we'd better removes this parameter and sets it in the function itself.

---
 fs/ext4/balloc.c  |    8 +++-----
 fs/ext4/bitmap.c  |    6 ++++--
 fs/ext4/ext4.h    |    4 ++--
 fs/ext4/ialloc.c  |    4 +---
 fs/ext4/mballoc.c |    9 +++------
 fs/ext4/resize.c  |    3 +--
 6 files changed, 14 insertions(+), 20 deletions(-)
fs/ext4/balloc.c +3 -5
@@ -174,8 +174,7 @@ void ext4_init_block_bitmap(struct super
 		ext4_free_inodes_set(sb, gdp, 0);
 		ext4_itable_unused_set(sb, gdp, 0);
 		memset(bh->b_data, 0xff, sb->s_blocksize);
-		ext4_block_bitmap_csum_set(sb, block_group, gdp, bh,
-					   EXT4_BLOCKS_PER_GROUP(sb) / 8);
+		ext4_block_bitmap_csum_set(sb, block_group, gdp, bh);
 		return;
 	}
 	memset(bh->b_data, 0, sb->s_blocksize);
@@ -212,8 +211,7 @@ void ext4_init_block_bitmap(struct super
 	 */
 	ext4_mark_bitmap_end(num_clusters_in_group(sb, block_group),
 			     sb->s_blocksize * 8, bh->b_data);
-	ext4_block_bitmap_csum_set(sb, block_group, gdp, bh,
-				   EXT4_BLOCKS_PER_GROUP(sb) / 8);
+	ext4_block_bitmap_csum_set(sb, block_group, gdp, bh);
 	ext4_group_desc_csum_set(sb, block_group, gdp);
 }
 
@@ -350,7 +348,7 @@ void ext4_validate_block_bitmap(struct s
 		return;
 	}
 	if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group,
-			desc, bh, EXT4_BLOCKS_PER_GROUP(sb) / 8))) {
+			desc, bh))) {
 		ext4_unlock_group(sb, block_group);
 		ext4_error(sb, "bg %u: bad block bitmap checksum", block_group);
 		return;
fs/ext4/bitmap.c +4 -2
@@ -58,11 +58,12 @@ void ext4_inode_bitmap_csum_set(struct s
 
 int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
 				  struct ext4_group_desc *gdp,
-				  struct buffer_head *bh, int sz)
+				  struct buffer_head *bh)
 {
 	__u32 hi;
 	__u32 provided, calculated;
 	struct ext4_sb_info *sbi = EXT4_SB(sb);
+	int sz = EXT4_CLUSTERS_PER_GROUP(sb) / 8;
 
 	if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
 					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
@@ -84,8 +85,9 @@ int ext4_block_bitmap_csum_verify(struct
 
 void ext4_block_bitmap_csum_set(struct super_block *sb, ext4_group_t group,
 				struct ext4_group_desc *gdp,
-				struct buffer_head *bh, int sz)
+				struct buffer_head *bh)
 {
+	int sz = EXT4_CLUSTERS_PER_GROUP(sb) / 8;
 	__u32 csum;
 	struct ext4_sb_info *sbi = EXT4_SB(sb);
 
fs/ext4/ext4.h +2 -2
@@ -1867,10 +1867,10 @@ int ext4_inode_bitmap_csum_verify(struct
 				  struct buffer_head *bh, int sz);
 void ext4_block_bitmap_csum_set(struct super_block *sb, ext4_group_t group,
 				struct ext4_group_desc *gdp,
-				struct buffer_head *bh, int sz);
+				struct buffer_head *bh);
 int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
 				  struct ext4_group_desc *gdp,
-				  struct buffer_head *bh, int sz);
+				  struct buffer_head *bh);
 
 /* balloc.c */
 extern void ext4_validate_block_bitmap(struct super_block *sb,
fs/ext4/ialloc.c +1 -3
@@ -753,9 +753,7 @@ got:
 			ext4_free_group_clusters_set(sb, gdp,
 				ext4_free_clusters_after_init(sb, group, gdp));
 			ext4_block_bitmap_csum_set(sb, group, gdp,
-						   block_bitmap_bh,
-						   EXT4_BLOCKS_PER_GROUP(sb) /
-						   8);
+						   block_bitmap_bh);
 			ext4_group_desc_csum_set(sb, group, gdp);
 		}
 		ext4_unlock_group(sb, group);
fs/ext4/mballoc.c +3 -6
@@ -2804,8 +2804,7 @@ ext4_mb_mark_diskspace_used(struct ext4_
 	}
 	len = ext4_free_group_clusters(sb, gdp) - ac->ac_b_ex.fe_len;
 	ext4_free_group_clusters_set(sb, gdp, len);
-	ext4_block_bitmap_csum_set(sb, ac->ac_b_ex.fe_group, gdp, bitmap_bh,
-				   EXT4_BLOCKS_PER_GROUP(sb) / 8);
+	ext4_block_bitmap_csum_set(sb, ac->ac_b_ex.fe_group, gdp, bitmap_bh);
 	ext4_group_desc_csum_set(sb, ac->ac_b_ex.fe_group, gdp);
 
 	ext4_unlock_group(sb, ac->ac_b_ex.fe_group);
@@ -4664,8 +4663,7 @@ do_more:
 
 	ret = ext4_free_group_clusters(sb, gdp) + count_clusters;
 	ext4_free_group_clusters_set(sb, gdp, ret);
-	ext4_block_bitmap_csum_set(sb, block_group, gdp, bitmap_bh,
-				   EXT4_BLOCKS_PER_GROUP(sb) / 8);
+	ext4_block_bitmap_csum_set(sb, block_group, gdp, bitmap_bh);
 	ext4_group_desc_csum_set(sb, block_group, gdp);
 	ext4_unlock_group(sb, block_group);
 	percpu_counter_add(&sbi->s_freeclusters_counter, count_clusters);
@@ -4809,8 +4807,7 @@ int ext4_group_add_blocks(handle_t *hand
 	mb_free_blocks(NULL, &e4b, bit, count);
 	blk_free_count = blocks_freed + ext4_free_group_clusters(sb, desc);
 	ext4_free_group_clusters_set(sb, desc, blk_free_count);
-	ext4_block_bitmap_csum_set(sb, block_group, desc, bitmap_bh,
-				   EXT4_BLOCKS_PER_GROUP(sb) / 8);
+	ext4_block_bitmap_csum_set(sb, block_group, desc, bitmap_bh);
 	ext4_group_desc_csum_set(sb, block_group, desc);
 	ext4_unlock_group(sb, block_group);
 	percpu_counter_add(&sbi->s_freeclusters_counter,
fs/ext4/resize.c +1 -2
@@ -1121,8 +1121,7 @@ static int ext4_set_bitmap_checksums(str
 	bh = ext4_get_bitmap(sb, group_data->block_bitmap);
 	if (!bh)
 		return -EIO;
-	ext4_block_bitmap_csum_set(sb, group, gdp, bh,
-				   EXT4_BLOCKS_PER_GROUP(sb) / 8);
+	ext4_block_bitmap_csum_set(sb, group, gdp, bh);
 	brelse(bh);
 
 	return 0;
author maintainer
#3 lore raw

PATCH 3/85 ext4: Avoid underflow in ext4_trim_fs()

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Lukas Czerner <[email protected]>

commit 5de35e8d5c02d271c20e18337e01bc20e6ef472e upstream.

Currently if len argument in ext4_trim_fs() is smaller than one block, the 'end' variable underflow. Avoid that by returning EINVAL if len is smaller than file system block.

Also remove useless unlikely().

---
 fs/ext4/mballoc.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
fs/ext4/mballoc.c +3 -2
@@ -4987,8 +4987,9 @@ int ext4_trim_fs(struct super_block *sb,
 	end = start + (range->len >> sb->s_blocksize_bits) - 1;
 	minlen = range->minlen >> sb->s_blocksize_bits;
 
-	if (unlikely(minlen > EXT4_CLUSTERS_PER_GROUP(sb)) ||
-	    unlikely(start >= max_blks))
+	if (minlen > EXT4_CLUSTERS_PER_GROUP(sb) ||
+	    start >= max_blks ||
+	    range->len < sb->s_blocksize)
 		return -EINVAL;
 	if (end >= max_blks)
 		end = max_blks - 1;
author maintainer
#4 lore raw

PATCH 4/85 usbdevfs: Fix broken scatter-gather transfer

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Henrik Rydberg <[email protected]>

commit 014639003c77a51fc319c9fdf225e7747cb6e18d upstream.

The handling of large output bulk transfers is broken; the same user page is read over and over again. Fixed with this patch.

---
 drivers/usb/core/devio.c |    1 +
 1 file changed, 1 insertion(+)
drivers/usb/core/devio.c +1 -0
@@ -1348,6 +1348,7 @@ static int proc_do_submiturb(struct dev_
 					ret = -EFAULT;
 					goto error;
 				}
+				uurb->buffer += u;
 			}
 			totlen -= u;
 		}
author maintainer
#5 lore raw

PATCH 5/85 hwmon: (coretemp) Add support for Atom CE4110/4150/4170

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Guenter Roeck <[email protected]>

commit 1102dcab849313bd5a340b299b5cf61b518fbc0f upstream.

TjMax for the CE4100 series of Atom CPUs was previously reported to be 110 degrees C.

cpuinfo logs on the web show existing CPU types CE4110, CE4150, and CE4170, reported as "model name : Intel(R) Atom(TM) CPU CE41{1|5|7}0 @ 1.{2|6}0GHz" with model 28 (0x1c) and stepping 10 (0x0a). Add the three known variants to the tjmax table.

---
 Documentation/hwmon/coretemp |    1 +
 drivers/hwmon/coretemp.c     |    7 +++++--
 2 files changed, 6 insertions(+), 2 deletions(-)
Documentation/hwmon/coretemp +1 -0
@@ -105,6 +105,7 @@ Process		Processor					TjMax(C)
 		330/230						125
 		E680/660/640/620				90
 		E680T/660T/640T/620T				110
+		CE4170/4150/4110				110
 
 45nm		Core2 Processors
 		Solo ULV SU3500/3300				100
drivers/hwmon/coretemp.c +5 -2
@@ -205,8 +205,11 @@ static const struct tjmax __cpuinitconst
 	{ "CPU N455", 100000 },
 	{ "CPU N470", 100000 },
 	{ "CPU N475", 100000 },
-	{ "CPU  230", 100000 },
-	{ "CPU  330", 125000 },
+	{ "CPU  230", 100000 },		/* Model 0x1c, stepping 2	*/
+	{ "CPU  330", 125000 },		/* Model 0x1c, stepping 2	*/
+	{ "CPU CE4110", 110000 },	/* Model 0x1c, stepping 10	*/
+	{ "CPU CE4150", 110000 },	/* Model 0x1c, stepping 10	*/
+	{ "CPU CE4170", 110000 },	/* Model 0x1c, stepping 10	*/
 };
 
 static int __cpuinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id,
author maintainer
#6 lore raw

PATCH 6/85 nohz: Fix idle ticks in cpu summary line of /proc/stat

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Michal Hocko <[email protected]>

commit 7386cdbf2f57ea8cff3c9fde93f206e58b9fe13f upstream.

Git commit 09a1d34f8535ecf9 "nohz: Make idle/iowait counter update conditional" introduced a bug in regard to cpu hotplug. The effect is that the number of idle ticks in the cpu summary line in /proc/stat is still counting ticks for offline cpus.

Reproduction is easy, just start a workload that keeps all cpus busy, switch off one or more cpus and then watch the idle field in top. On a dual-core with one cpu 100% busy and one offline cpu you will get something like this:

%Cpu(s): 48.7 us, 1.3 sy, 0.0 ni, 50.0 id, 0.0 wa, 0.0 hi, 0.0 si, %0.0 st

The problem is that an offline cpu still has ts->idle_active == 1. To fix this we should make sure that the cpu is online when calling get_cpu_idle_time_us and get_cpu_iowait_time_us.

[Srivatsa: Rebased to current mainline]

---
 fs/proc/stat.c |   14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)
fs/proc/stat.c +10 -4
@@ -45,10 +45,13 @@ static cputime64_t get_iowait_time(int c
 
 static u64 get_idle_time(int cpu)
 {
-	u64 idle, idle_time = get_cpu_idle_time_us(cpu, NULL);
+	u64 idle, idle_time = -1ULL;
+
+	if (cpu_online(cpu))
+		idle_time = get_cpu_idle_time_us(cpu, NULL);
 
 	if (idle_time == -1ULL)
-		/* !NO_HZ so we can rely on cpustat.idle */
+		/* !NO_HZ or cpu offline so we can rely on cpustat.idle */
 		idle = kcpustat_cpu(cpu).cpustat[CPUTIME_IDLE];
 	else
 		idle = usecs_to_cputime64(idle_time);
@@ -58,10 +61,13 @@ static u64 get_idle_time(int cpu)
 
 static u64 get_iowait_time(int cpu)
 {
-	u64 iowait, iowait_time = get_cpu_iowait_time_us(cpu, NULL);
+	u64 iowait, iowait_time = -1ULL;
+
+	if (cpu_online(cpu))
+		iowait_time = get_cpu_iowait_time_us(cpu, NULL);
 
 	if (iowait_time == -1ULL)
-		/* !NO_HZ so we can rely on cpustat.iowait */
+		/* !NO_HZ or cpu offline so we can rely on cpustat.iowait */
 		iowait = kcpustat_cpu(cpu).cpustat[CPUTIME_IOWAIT];
 	else
 		iowait = usecs_to_cputime64(iowait_time);
author maintainer
#7 lore raw

PATCH 7/85 arch/tile: avoid generating .eh_frame information in modules

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Chris Metcalf <[email protected]>

commit 627072b06c362bbe7dc256f618aaa63351f0cfe6 upstream.

The tile tool chain uses the .eh_frame information for backtracing. The vmlinux build drops any .eh_frame sections at link time, but when present in kernel modules, it causes a module load failure due to the presence of unsupported pc-relative relocations. When compiling to use compiler feedback support, the compiler by default omits .eh_frame information, so we don't see this problem. But when not using feedback, we need to explicitly suppress the .eh_frame.

---
 arch/tile/Makefile |    4 ++++
 1 file changed, 4 insertions(+)
arch/tile/Makefile +4 -0
@@ -26,6 +26,10 @@ $(error Set TILERA_ROOT or CROSS_COMPILE
   endif
 endif
 
+# The tile compiler may emit .eh_frame information for backtracing.
+# In kernel modules, this causes load failures due to unsupported relocations.
+KBUILD_CFLAGS   += -fno-asynchronous-unwind-tables
+
 ifneq ($(CONFIG_DEBUG_EXTRA_FLAGS),"")
 KBUILD_CFLAGS   += $(CONFIG_DEBUG_EXTRA_FLAGS)
 endif
author maintainer
#8 lore raw

PATCH 8/85 NLM: nlm_lookup_file() may return NLMv4-specific error codes

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Trond Myklebust <[email protected]>

commit cd0b16c1c3cda12dbed1f8de8f1a9b0591990724 upstream.

If the filehandle is stale, or open access is denied for some reason, nlm_fopen() may return one of the NLMv4-specific error codes nlm4_stale_fh or nlm4_failed. These get passed right through nlm_lookup_file(), and so when nlmsvc_retrieve_args() calls the latter, it needs to filter the result through the cast_status() machinery.

Failure to do so, will trigger the BUG_ON() in encode_nlm_stat...

---
 fs/lockd/clntxdr.c |    2 +-
 fs/lockd/svcproc.c |    3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)
fs/lockd/clntxdr.c +1 -1
@@ -223,7 +223,7 @@ static void encode_nlm_stat(struct xdr_s
 {
 	__be32 *p;
 
-	BUG_ON(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD);
+	WARN_ON_ONCE(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD);
 	p = xdr_reserve_space(xdr, 4);
 	*p = stat;
 }
fs/lockd/svcproc.c +2 -1
@@ -68,7 +68,8 @@ nlmsvc_retrieve_args(struct svc_rqst *rq
 
 	/* Obtain file pointer. Not used by FREE_ALL call. */
 	if (filp != NULL) {
-		if ((error = nlm_lookup_file(rqstp, &file, &lock->fh)) != 0)
+		error = cast_status(nlm_lookup_file(rqstp, &file, &lock->fh));
+		if (error != 0)
 			goto no_locks;
 		*filp = file;
 
author maintainer
#9 lore raw

PATCH 9/85 oprofile, x86: Fix wrapping bug in op_x86_get_ctrl()

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Dan Carpenter <[email protected]>

commit 44009105081b51417f311f4c3be0061870b6b8ed upstream.

The "event" variable is a u16 so the shift will always wrap to zero making the line a no-op.

---
 arch/x86/oprofile/nmi_int.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/oprofile/nmi_int.c +1 -1
@@ -55,7 +55,7 @@ u64 op_x86_get_ctrl(struct op_x86_model_
 	val |= counter_config->extra;
 	event &= model->event_mask ? model->event_mask : 0xFF;
 	val |= event & 0xFF;
-	val |= (event & 0x0F00) << 24;
+	val |= (u64)(event & 0x0F00) << 24;
 
 	return val;
 }
author maintainer
#10 lore raw

PATCH 10/85 s390: fix linker script for 31 bit builds

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Heiko Carstens <[email protected]>

commit c985cb37f1b39c2c8035af741a2a0b79f1fbaca7 upstream.

Because of a change in the s390 arch backend of binutils (commit 23ecd77 "Pick the default arch depending on the target size" in binutils repo) 31 bit builds will fail since the linker would now try to create 64 bit binary output.
Fix this by setting OUTPUT_ARCH to s390:31-bit instead of s390. Thanks to Andreas Krebbel for figuring out the issue.

Fixes this build error:

LD init/built-in.o
s390x-4.7.2-ld: s390:31-bit architecture of input file
`arch/s390/kernel/head.o' is incompatible with s390:64-bit output

---
 arch/s390/boot/compressed/vmlinux.lds.S |    2 +-
 arch/s390/kernel/vmlinux.lds.S          |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
arch/s390/boot/compressed/vmlinux.lds.S +1 -1
@@ -5,7 +5,7 @@ OUTPUT_FORMAT("elf64-s390", "elf64-s390"
 OUTPUT_ARCH(s390:64-bit)
 #else
 OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390")
-OUTPUT_ARCH(s390)
+OUTPUT_ARCH(s390:31-bit)
 #endif
 
 ENTRY(startup)
arch/s390/kernel/vmlinux.lds.S +1 -1
@@ -8,7 +8,7 @@
 
 #ifndef CONFIG_64BIT
 OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390")
-OUTPUT_ARCH(s390)
+OUTPUT_ARCH(s390:31-bit)
 ENTRY(startup)
 jiffies = jiffies_64 + 4;
 #else
author maintainer
#11 lore raw

PATCH 11/85 SUNRPC: Prevent kernel stack corruption on long values of flush

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sasha Levin <[email protected]>

commit 212ba90696ab4884e2025b0b13726d67aadc2cd4 upstream.

The buffer size in read_flush() is too small for the longest possible values for it. This can lead to a kernel stack corruption:

[   43.047329] Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: ffffffff833e64b4
[   43.047329]
[   43.049030] Pid: 6015, comm: trinity-child18 Tainted: G        W    3.5.0-rc7-next-20120716-sasha #221
[   43.050038] Call Trace:
[   43.050435]  [<ffffffff836c60c2>] panic+0xcd/0x1f4
[   43.050931]  [<ffffffff833e64b4>] ? read_flush.isra.7+0xe4/0x100
[   43.051602]  [<ffffffff810e94e6>] __stack_chk_fail+0x16/0x20
[   43.052206]  [<ffffffff833e64b4>] read_flush.isra.7+0xe4/0x100
[   43.052951]  [<ffffffff833e6500>] ? read_flush_pipefs+0x30/0x30
[   43.053594]  [<ffffffff833e652c>] read_flush_procfs+0x2c/0x30
[   43.053596]  [<ffffffff812b9a8c>] proc_reg_read+0x9c/0xd0
[   43.053596]  [<ffffffff812b99f0>] ? proc_reg_write+0xd0/0xd0
[   43.053596]  [<ffffffff81250d5b>] do_loop_readv_writev+0x4b/0x90
[   43.053596]  [<ffffffff81250fd6>] do_readv_writev+0xf6/0x1d0
[   43.053596]  [<ffffffff812510ee>] vfs_readv+0x3e/0x60
[   43.053596]  [<ffffffff812511b8>] sys_readv+0x48/0xb0
[   43.053596]  [<ffffffff8378167d>] system_call_fastpath+0x1a/0x1f
---
 net/sunrpc/cache.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
net/sunrpc/cache.c +2 -2
@@ -1409,11 +1409,11 @@ static ssize_t read_flush(struct file *f
 			  size_t count, loff_t *ppos,
 			  struct cache_detail *cd)
 {
-	char tbuf[20];
+	char tbuf[22];
 	unsigned long p = *ppos;
 	size_t len;
 
-	sprintf(tbuf, "%lu\n", convert_to_wallclock(cd->flush_time));
+	snprintf(tbuf, sizeof(tbuf), "%lu\n", convert_to_wallclock(cd->flush_time));
 	len = strlen(tbuf);
 	if (p >= len)
 		return 0;
author maintainer
#12 lore raw

PATCH 12/85 SUNRPC: Set alloc_slot for backchannel tcp ops

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Bryan Schumaker <[email protected]>

commit 84e28a307e376f271505af65a7b7e212dd6f61f4 upstream.

f39c1bfb5a03e2d255451bff05be0d7255298fa4 (SUNRPC: Fix a UDP transport regression) introduced the "alloc_slot" function for xprt operations, but never created one for the backchannel operations. This patch fixes a null pointer dereference when mounting NFS over v4.1.

Call Trace:
 [<ffffffffa0207957>] ? xprt_reserve+0x47/0x50 [sunrpc]
 [<ffffffffa02023a4>] call_reserve+0x34/0x60 [sunrpc]
 [<ffffffffa020e280>] __rpc_execute+0x90/0x400 [sunrpc]
 [<ffffffffa020e61a>] rpc_async_schedule+0x2a/0x40 [sunrpc]
 [<ffffffff81073589>] process_one_work+0x139/0x500
 [<ffffffff81070e70>] ? alloc_worker+0x70/0x70
 [<ffffffffa020e5f0>] ? __rpc_execute+0x400/0x400 [sunrpc]
 [<ffffffff81073d1e>] worker_thread+0x15e/0x460
 [<ffffffff8145c839>] ? preempt_schedule+0x49/0x70
 [<ffffffff81073bc0>] ? rescuer_thread+0x230/0x230
 [<ffffffff81079603>] kthread+0x93/0xa0
 [<ffffffff81465d04>] kernel_thread_helper+0x4/0x10
 [<ffffffff81079570>] ? kthread_freezable_should_stop+0x70/0x70
 [<ffffffff81465d00>] ? gs_change+0x13/0x13
---
 net/sunrpc/xprtsock.c |    1 +
 1 file changed, 1 insertion(+)
net/sunrpc/xprtsock.c +1 -0
@@ -2539,6 +2539,7 @@ static struct rpc_xprt_ops xs_tcp_ops =
 static struct rpc_xprt_ops bc_tcp_ops = {
 	.reserve_xprt		= xprt_reserve_xprt,
 	.release_xprt		= xprt_release_xprt,
+	.alloc_slot		= xprt_alloc_slot,
 	.rpcbind		= xs_local_rpcbind,
 	.buf_alloc		= bc_malloc,
 	.buf_free		= bc_free,
author maintainer
#13 lore raw

PATCH 13/85 ring-buffer: Check for uninitialized cpu buffer before resizing

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Vaibhav Nagarnaik <[email protected]>

commit 8e49f418c9632790bf456634742d34d97120a784 upstream.

With a system where, num_present_cpus < num_possible_cpus, even if all CPUs are online, non-present CPUs don't have per_cpu buffers allocated. If per_cpu/<cpu>/buffer_size_kb is modified for such a CPU, it can cause a panic due to NULL dereference in ring_buffer_resize().

To fix this, resize operation is allowed only if the per-cpu buffer has been initialized.

---
 kernel/trace/ring_buffer.c |    4 ++++
 1 file changed, 4 insertions(+)
kernel/trace/ring_buffer.c +4 -0
@@ -1567,6 +1567,10 @@ int ring_buffer_resize(struct ring_buffe
 
 		put_online_cpus();
 	} else {
+		/* Make sure this CPU has been intitialized */
+		if (!cpumask_test_cpu(cpu_id, buffer->cpumask))
+			goto out;
+
 		cpu_buffer = buffer->buffers[cpu_id];
 
 		if (nr_pages == cpu_buffer->nr_pages)
author maintainer
#14 lore raw

PATCH 14/85 pcmcia: sharpsl: dont discard sharpsl_pcmcia_ops

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Arnd Bergmann <[email protected]>

commit fdc858a466b738d35d3492bc7cf77b1dac98bf7c upstream.

The sharpsl_pcmcia_ops structure gets passed into sa11xx_drv_pcmcia_probe, where it gets accessed at run-time, unlike all other pcmcia drivers that pass their structures into platform_device_add_data, which makes a copy.

This means the gcc warning is valid and the structure must not be marked as __initdata.

Without this patch, building collie_defconfig results in:

drivers/pcmcia/pxa2xx_sharpsl.c:22:31: fatal error: mach-pxa/hardware.h: No such file or directory compilation terminated.
make[3]: *** [drivers/pcmcia/pxa2xx_sharpsl.o] Error 1
make[2]: *** [drivers/pcmcia] Error 2
make[1]: *** [drivers] Error 2
make: *** [sub-make] Error 2

Cc Dominik Brodowski <[email protected]>
Cc Russell King <[email protected]>
Cc Pavel Machek <[email protected]>
Cc Jochen Friedrich <[email protected]>
---
 drivers/pcmcia/pxa2xx_sharpsl.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pcmcia/pxa2xx_sharpsl.c +1 -1
@@ -194,7 +194,7 @@ static void sharpsl_pcmcia_socket_suspen
 	sharpsl_pcmcia_init_reset(skt);
 }
 
-static struct pcmcia_low_level sharpsl_pcmcia_ops __initdata = {
+static struct pcmcia_low_level sharpsl_pcmcia_ops = {
 	.owner                  = THIS_MODULE,
 	.hw_init                = sharpsl_pcmcia_hw_init,
 	.socket_state           = sharpsl_pcmcia_socket_state,
author maintainer
#15 lore raw

PATCH 15/85 kernel/sys.c: fix stack memory content leak via UNAME26

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Kees Cook <[email protected]>

commit 2702b1526c7278c4d65d78de209a465d4de2885e upstream.

Calling uname() with the UNAME26 personality set allows a leak of kernel stack contents. This fixes it by defensively calculating the length of copy_to_user() call, making the len argument unsigned, and initializing the stack buffer to zero (now technically unneeded, but hey, overkill).

CVE-2012-0957

---
 kernel/sys.c |   12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)
kernel/sys.c +7 -5
@@ -1265,15 +1265,16 @@ DECLARE_RWSEM(uts_sem);
  * Work around broken programs that cannot handle "Linux 3.0".
  * Instead we map 3.x to 2.6.40+x, so e.g. 3.0 would be 2.6.40
  */
-static int override_release(char __user *release, int len)
+static int override_release(char __user *release, size_t len)
 {
 	int ret = 0;
-	char buf[65];
 
 	if (current->personality & UNAME26) {
-		char *rest = UTS_RELEASE;
+		const char *rest = UTS_RELEASE;
+		char buf[65] = { 0 };
 		int ndots = 0;
 		unsigned v;
+		size_t copy;
 
 		while (*rest) {
 			if (*rest == '.' && ++ndots >= 3)
@@ -1283,8 +1284,9 @@ static int override_release(char __user
 			rest++;
 		}
 		v = ((LINUX_VERSION_CODE >> 8) & 0xff) + 40;
-		snprintf(buf, len, "2.6.%u%s", v, rest);
-		ret = copy_to_user(release, buf, len);
+		copy = min(sizeof(buf), max_t(size_t, 1, len));
+		copy = scnprintf(buf, copy, "2.6.%u%s", v, rest);
+		ret = copy_to_user(release, buf, copy + 1);
 	}
 	return ret;
 }
author maintainer
#16 lore raw

PATCH 16/85 use clamp_t in UNAME26 fix

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Kees Cook <[email protected]>

commit 31fd84b95eb211d5db460a1dda85e004800a7b52 upstream.

The min/max call needed to have explicit types on some architectures (e.g. mn10300). Use clamp_t instead to avoid the warning:

kernel/sys.c: In function 'override_release':
kernel/sys.c:1287:10: warning: comparison of distinct pointer types lacks a cast [enabled by default]

---
 kernel/sys.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/sys.c +1 -1
@@ -1284,7 +1284,7 @@ static int override_release(char __user
 			rest++;
 		}
 		v = ((LINUX_VERSION_CODE >> 8) & 0xff) + 40;
-		copy = min(sizeof(buf), max_t(size_t, 1, len));
+		copy = clamp_t(size_t, len, 1, sizeof(buf));
 		copy = scnprintf(buf, copy, "2.6.%u%s", v, rest);
 		ret = copy_to_user(release, buf, copy + 1);
 	}
#17 lore raw

Re: [ 16/85] use clamp_t in UNAME26 fix

Quoted 6 lines · Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Kees Cook <[email protected]>

Quoted 7 lines

commit 31fd84b95eb211d5db460a1dda85e004800a7b52 upstream.

The min/max call needed to have explicit types on some architectures (e.g. mn10300). Use clamp_t instead to avoid the warning:

kernel/sys.c: In function 'override_release':
kernel/sys.c:1287:10: warning: comparison of distinct pointer types lacks a cast [enabled by default]

While this change makes the code more readable, I think the bug is really in the type definitions for those architectures:

[...]

kernel/sys.c static int override_release(char __user · line 1287

Quoted 2 lines
kernel/sys.c +1 -1
-		copy = min(sizeof(buf), max_t(size_t, 1, len));
+		copy = clamp_t(size_t, len, 1, sizeof(buf));

[...]

1. sizeof(buf) yields a value of type size_t, by definition.
2. max_t(size_t, 1, len) yields a value of type size_t.
3. Therefore min(sizeof(buf), max_t(size_t, 1, len)) is valid.

The only way I see to get this warning is to define size_t wrongly, so that (1) is not true.

Ben.

Signature · 2 lines
Ben Hutchings
Never attribute to conspiracy what can adequately be explained by stupidity.
#18 lore raw

Re: [ 16/85] use clamp_t in UNAME26 fix

Quoted 23 lines · Ben Hutchings
Quoted 6 lines · Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Kees Cook <[email protected]>

Quoted 7 lines

commit 31fd84b95eb211d5db460a1dda85e004800a7b52 upstream.

The min/max call needed to have explicit types on some architectures (e.g. mn10300). Use clamp_t instead to avoid the warning:

kernel/sys.c: In function 'override_release':
kernel/sys.c:1287:10: warning: comparison of distinct pointer types lacks a cast [enabled by default]

While this change makes the code more readable, I think the bug is really in the type definitions for those architectures:

[...]

Quoted 2 lines
kernel/sys.c +1 -1
-		copy = min(sizeof(buf), max_t(size_t, 1, len));
+		copy = clamp_t(size_t, len, 1, sizeof(buf));

[...]

Quoted 6 lines

1. sizeof(buf) yields a value of type size_t, by definition.
2. max_t(size_t, 1, len) yields a value of type size_t.
3. Therefore min(sizeof(buf), max_t(size_t, 1, len)) is valid.

The only way I see to get this warning is to define size_t wrongly, so that (1) is not true.

Agreed. mn10300 and cris seem to have problems with size_t. Here is a related issue:

Re: [next:akpm 155/157] drivers/char/random.c:827:3: warning: format '%zd' expects argument of type 'signed size_t', but argument 7 has type 'size_t'
https://lkml.org/lkml/2012/10/23/792

Thanks,
Fengguang

author maintainer
#19 lore raw

PATCH 17/85 x86, amd, mce: Avoid NULL pointer reference on CPU northbridge lookup

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Daniel J Blueman <[email protected]>

commit 21c5e50e15b1abd797e62f18fd7f90b9cc004cbd upstream.

When booting on a federated multi-server system (NumaScale), the processor Northbridge lookup returns NULL; add guards to prevent this causing an oops.

On those systems, the northbridge is accessed through MMIO and the "normal" northbridge enumeration in amd_nb.c doesn't work since we're generating the northbridge ID from the initial APIC ID and the last is not unique on those systems. Long story short, we end up without northbridge descriptors.

---
 arch/x86/kernel/cpu/mcheck/mce_amd.c |   10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
arch/x86/kernel/cpu/mcheck/mce_amd.c +5 -5
@@ -576,12 +576,10 @@ static __cpuinit int threshold_create_ba
 	int err = 0;
 
 	if (shared_bank[bank]) {
-
 		nb = node_to_amd_nb(amd_get_nb_id(cpu));
-		WARN_ON(!nb);
 
 		/* threshold descriptor already initialized on this node? */
-		if (nb->bank4) {
+		if (nb && nb->bank4) {
 			/* yes, use it */
 			b = nb->bank4;
 			err = kobject_add(b->kobj, &dev->kobj, name);
@@ -615,8 +613,10 @@ static __cpuinit int threshold_create_ba
 		atomic_set(&b->cpus, 1);
 
 		/* nb is already initialized, see above */
-		WARN_ON(nb->bank4);
-		nb->bank4 = b;
+		if (nb) {
+			WARN_ON(nb->bank4);
+			nb->bank4 = b;
+		}
 	}
 
 	err = allocate_threshold_blocks(cpu, bank, 0,
author maintainer
#20 lore raw

PATCH 18/85 x86: Exclude E820_RESERVED regions and memory holes above 4 GB from direct mapping.

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jacob Shin <[email protected]>

commit 1bbbbe779aabe1f0768c2bf8f8c0a5583679b54a upstream.

On systems with very large memory (1 TB in our case), BIOS may report a reserved region or a hole in the E820 map, even above the 4 GB range. Exclude these from the direct mapping.

[ hpa: this should be done not just for > 4 GB but for everything above the legacy
region (1 MB), at the very least. That, however, turns out to require significant restructuring. That work is well underway, but is not suitable for rc/stable. ]

---
 arch/x86/kernel/setup.c |   17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)
arch/x86/kernel/setup.c +15 -2
@@ -919,8 +919,21 @@ void __init setup_arch(char **cmdline_p)
 
 #ifdef CONFIG_X86_64
 	if (max_pfn > max_low_pfn) {
-		max_pfn_mapped = init_memory_mapping(1UL<<32,
-						     max_pfn<<PAGE_SHIFT);
+		int i;
+		for (i = 0; i < e820.nr_map; i++) {
+			struct e820entry *ei = &e820.map[i];
+
+			if (ei->addr + ei->size <= 1UL << 32)
+				continue;
+
+			if (ei->type == E820_RESERVED)
+				continue;
+
+			max_pfn_mapped = init_memory_mapping(
+				ei->addr < 1UL << 32 ? 1UL << 32 : ei->addr,
+				ei->addr + ei->size);
+		}
+
 		/* can we preseve max_low_pfn ?*/
 		max_low_pfn = max_pfn;
 	}
#21 lore raw

Re: [ 18/85] x86: Exclude E820_RESERVED regions and memory holes above 4 GB from direct mapping.

Quoted 15 lines · Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jacob Shin <[email protected]>

commit 1bbbbe779aabe1f0768c2bf8f8c0a5583679b54a upstream.

On systems with very large memory (1 TB in our case), BIOS may report a reserved region or a hole in the E820 map, even above the 4 GB range. Exclude these from the direct mapping.

[ hpa: this should be done not just for > 4 GB but for everything above the legacy
region (1 MB), at the very least. That, however, turns out to require significant restructuring. That work is well underway, but is not suitable for rc/stable. ]

[...]

Quoted 11 lines
arch/x86/kernel/setup.c +3 -2
@@ -919,8 +919,21 @@ void __init setup_arch(char **cmdline_p)
 
 #ifdef CONFIG_X86_64
 	if (max_pfn > max_low_pfn) {
-		max_pfn_mapped = init_memory_mapping(1UL<<32,
-						     max_pfn<<PAGE_SHIFT);
+		int i;
+		for (i = 0; i < e820.nr_map; i++) {
+			struct e820entry *ei = &e820.map[i];

arch/x86/kernel/setup.c void __init setup_arch(char **cmdline_p) · line 934

Quoted 10 lines
arch/x86/kernel/setup.c +10 -0
+
+			if (ei->addr + ei->size <= 1UL << 32)
+				continue;
+
+			if (ei->type == E820_RESERVED)
+				continue;
+
+			max_pfn_mapped = init_memory_mapping(
+				ei->addr < 1UL << 32 ? 1UL << 32 : ei->addr,
+				ei->addr + ei->size);

Is it safe to assume that the e820 entries are sorted? If not, this assignment needs to be conditional.

Ben.

Quoted 5 lines
arch/x86/kernel/setup.c +2 -0
+		}
+
 		/* can we preseve max_low_pfn ?*/
 		max_low_pfn = max_pfn;
 	}
Signature · 2 lines
Ben Hutchings
Never attribute to conspiracy what can adequately be explained by stupidity.
author maintainer
#22 lore raw

PATCH 19/85 xen/x86: dont corrupt %eip when returning from a signal handler

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: David Vrabel <[email protected]>

commit a349e23d1cf746f8bdc603dcc61fae9ee4a695f6 upstream.

In 32 bit guests, if a userspace process has %eax == -ERESTARTSYS (-512) or -ERESTARTNOINTR (-513) when it is interrupted by an event /and/ the process has a pending signal then %eip (and %eax) are corrupted when returning to the main process after handling the signal. The application may then crash with SIGSEGV or a SIGILL or it may have subtly incorrect behaviour (depending on what instruction it returned to).

The occurs because handle_signal() is incorrectly thinking that there is a system call that needs to restarted so it adjusts %eip and %eax to re-execute the system call instruction (even though user space had not done a system call).

If %eax == -514 (-ERESTARTNOHAND (-514) or -ERESTART_RESTARTBLOCK (-516) then handle_signal() only corrupted %eax (by setting it to -EINTR). This may cause the application to crash or have incorrect behaviour.

handle_signal() assumes that regs->orig_ax >= 0 means a system call so any kernel entry point that is not for a system call must push a negative value for orig_ax. For example, for physical interrupts on bare metal the inverse of the vector is pushed and page_fault() sets regs->orig_ax to -1, overwriting the hardware provided error code.

xen_hypervisor_callback() was incorrectly pushing 0 for orig_ax instead of -1.

Classic Xen kernels pushed %eax which works as %eax cannot be both non-negative and -RESTARTSYS (etc.), but using -1 is consistent with other non-system call entry points and avoids some of the tests in handle_signal().

There were similar bugs in xen_failsafe_callback() of both 32 and 64-bit guests. If the fault was corrected and the normal return path was used then 0 was incorrectly pushed as the value for orig_ax.

---
 arch/x86/kernel/entry_32.S |    8 +++++---
 arch/x86/kernel/entry_64.S |    2 +-
 2 files changed, 6 insertions(+), 4 deletions(-)
arch/x86/kernel/entry_32.S +5 -3
@@ -1016,7 +1016,7 @@ ENTRY(xen_sysenter_target)
 
 ENTRY(xen_hypervisor_callback)
 	CFI_STARTPROC
-	pushl_cfi $0
+	pushl_cfi $-1 /* orig_ax = -1 => not a system call */
 	SAVE_ALL
 	TRACE_IRQS_OFF
 
@@ -1058,14 +1058,16 @@ ENTRY(xen_failsafe_callback)
 2:	mov 8(%esp),%es
 3:	mov 12(%esp),%fs
 4:	mov 16(%esp),%gs
+	/* EAX == 0 => Category 1 (Bad segment)
+	   EAX != 0 => Category 2 (Bad IRET) */
 	testl %eax,%eax
 	popl_cfi %eax
 	lea 16(%esp),%esp
 	CFI_ADJUST_CFA_OFFSET -16
 	jz 5f
 	addl $16,%esp
-	jmp iret_exc		# EAX != 0 => Category 2 (Bad IRET)
-5:	pushl_cfi $0		# EAX == 0 => Category 1 (Bad segment)
+	jmp iret_exc
+5:	pushl_cfi $-1 /* orig_ax = -1 => not a system call */
 	SAVE_ALL
 	jmp ret_from_exception
 	CFI_ENDPROC
arch/x86/kernel/entry_64.S +1 -1
@@ -1363,7 +1363,7 @@ ENTRY(xen_failsafe_callback)
 	CFI_RESTORE r11
 	addq $0x30,%rsp
 	CFI_ADJUST_CFA_OFFSET -0x30
-	pushq_cfi $0
+	pushq_cfi $-1 /* orig_ax = -1 => not a system call */
 	SAVE_ALL
 	jmp error_exit
 	CFI_ENDPROC
author maintainer
#23 lore raw

PATCH 20/85 USB: cdc-acm: fix pipe type of write endpoint

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ming Lei <[email protected]>

commit c5211187f7ff8e8dbff4ebf7c011ac4c0ffe319c upstream.

If the write endpoint is interrupt type, usb_sndintpipe() should be passed to usb_fill_int_urb() instead of usb_sndbulkpipe().

---
 drivers/usb/class/cdc-acm.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/class/cdc-acm.c +1 -1
@@ -1234,7 +1234,7 @@ made_compressed_probe:
 
 		if (usb_endpoint_xfer_int(epwrite))
 			usb_fill_int_urb(snd->urb, usb_dev,
-				usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
+				usb_sndintpipe(usb_dev, epwrite->bEndpointAddress),
 				NULL, acm->writesize, acm_write_bulk, snd, epwrite->bInterval);
 		else
 			usb_fill_bulk_urb(snd->urb, usb_dev,
author maintainer
#24 lore raw

PATCH 21/85 usb: acm: fix the computation of the number of data bits

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Nicolas Boullis <[email protected]>

commit 301a29da6e891e7eb95c843af0ecdbe86d01f723 upstream.

The current code assumes that CSIZE is 0000060, which appears to be wrong on some arches (such as powerpc).

---
 drivers/usb/class/cdc-acm.c |   20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)
drivers/usb/class/cdc-acm.c +15 -5
@@ -818,10 +818,6 @@ static const __u32 acm_tty_speed[] = {
 	2500000, 3000000, 3500000, 4000000
 };
 
-static const __u8 acm_tty_size[] = {
-	5, 6, 7, 8
-};
-
 static void acm_tty_set_termios(struct tty_struct *tty,
 						struct ktermios *termios_old)
 {
@@ -835,7 +831,21 @@ static void acm_tty_set_termios(struct t
 	newline.bParityType = termios->c_cflag & PARENB ?
 				(termios->c_cflag & PARODD ? 1 : 2) +
 				(termios->c_cflag & CMSPAR ? 2 : 0) : 0;
-	newline.bDataBits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4];
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		newline.bDataBits = 5;
+		break;
+	case CS6:
+		newline.bDataBits = 6;
+		break;
+	case CS7:
+		newline.bDataBits = 7;
+		break;
+	case CS8:
+	default:
+		newline.bDataBits = 8;
+		break;
+	}
 	/* FIXME: Needs to clear unsupported bits in the termios */
 	acm->clocal = ((termios->c_cflag & CLOCAL) != 0);
 
author maintainer
#25 lore raw

PATCH 22/85 USB: io_ti: fix port-data memory leak

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit 003615302a16579531932576bcd9582ddeba9018 upstream.

Fix port-data memory leak by moving port data allocation and deallocation to port_probe and port_remove.

Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible.

Compile-only tested.

---
 drivers/usb/serial/io_ti.c |   91 +++++++++++++++++++++------------------------
 1 file changed, 44 insertions(+), 47 deletions(-)
drivers/usb/serial/io_ti.c +44 -47
@@ -2594,12 +2594,7 @@ static void edge_break(struct tty_struct
 static int edge_startup(struct usb_serial *serial)
 {
 	struct edgeport_serial *edge_serial;
-	struct edgeport_port *edge_port;
-	struct usb_device *dev;
 	int status;
-	int i;
-
-	dev = serial->dev;
 
 	/* create our private serial structure */
 	edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL);
@@ -2617,40 +2612,7 @@ static int edge_startup(struct usb_seria
 		return status;
 	}
 
-	/* set up our port private structures */
-	for (i = 0; i < serial->num_ports; ++i) {
-		edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL);
-		if (edge_port == NULL) {
-			dev_err(&serial->dev->dev, "%s - Out of memory\n",
-								__func__);
-			goto cleanup;
-		}
-		spin_lock_init(&edge_port->ep_lock);
-		if (kfifo_alloc(&edge_port->write_fifo, EDGE_OUT_BUF_SIZE,
-								GFP_KERNEL)) {
-			dev_err(&serial->dev->dev, "%s - Out of memory\n",
-								__func__);
-			kfree(edge_port);
-			goto cleanup;
-		}
-		edge_port->port = serial->port[i];
-		edge_port->edge_serial = edge_serial;
-		usb_set_serial_port_data(serial->port[i], edge_port);
-		edge_port->bUartMode = default_uart_mode;
-	}
-
 	return 0;
-
-cleanup:
-	for (--i; i >= 0; --i) {
-		edge_port = usb_get_serial_port_data(serial->port[i]);
-		kfifo_free(&edge_port->write_fifo);
-		kfree(edge_port);
-		usb_set_serial_port_data(serial->port[i], NULL);
-	}
-	kfree(edge_serial);
-	usb_set_serial_data(serial, NULL);
-	return -ENOMEM;
 }
 
 static void edge_disconnect(struct usb_serial *serial)
@@ -2660,19 +2622,54 @@ static void edge_disconnect(struct usb_s
 
 static void edge_release(struct usb_serial *serial)
 {
-	int i;
+	kfree(usb_get_serial_data(serial));
+}
+
+static int edge_port_probe(struct usb_serial_port *port)
+{
 	struct edgeport_port *edge_port;
+	int ret;
 
-	dbg("%s", __func__);
+	edge_port = kzalloc(sizeof(*edge_port), GFP_KERNEL);
+	if (!edge_port)
+		return -ENOMEM;
+
+	ret = kfifo_alloc(&edge_port->write_fifo, EDGE_OUT_BUF_SIZE,
+								GFP_KERNEL);
+	if (ret) {
+		kfree(edge_port);
+		return -ENOMEM;
+	}
 
-	for (i = 0; i < serial->num_ports; ++i) {
-		edge_port = usb_get_serial_port_data(serial->port[i]);
+	ret = edge_create_sysfs_attrs(port);
+	if (ret) {
 		kfifo_free(&edge_port->write_fifo);
 		kfree(edge_port);
+		return ret;
 	}
-	kfree(usb_get_serial_data(serial));
+
+	spin_lock_init(&edge_port->ep_lock);
+	edge_port->port = port;
+	edge_port->edge_serial = usb_get_serial_data(port->serial);
+	edge_port->bUartMode = default_uart_mode;
+
+	usb_set_serial_port_data(port, edge_port);
+
+	return 0;
 }
 
+static int edge_port_remove(struct usb_serial_port *port)
+{
+	struct edgeport_port *edge_port;
+
+	edge_port = usb_get_serial_port_data(port);
+
+	edge_remove_sysfs_attrs(port);
+	kfifo_free(&edge_port->write_fifo);
+	kfree(edge_port);
+
+	return 0;
+}
 
 /* Sysfs Attributes */
 
@@ -2732,8 +2729,8 @@ static struct usb_serial_driver edgeport
 	.attach			= edge_startup,
 	.disconnect		= edge_disconnect,
 	.release		= edge_release,
-	.port_probe		= edge_create_sysfs_attrs,
-	.port_remove		= edge_remove_sysfs_attrs,
+	.port_probe		= edge_port_probe,
+	.port_remove		= edge_port_remove,
 	.ioctl			= edge_ioctl,
 	.set_termios		= edge_set_termios,
 	.tiocmget		= edge_tiocmget,
@@ -2763,8 +2760,8 @@ static struct usb_serial_driver edgeport
 	.attach			= edge_startup,
 	.disconnect		= edge_disconnect,
 	.release		= edge_release,
-	.port_probe		= edge_create_sysfs_attrs,
-	.port_remove		= edge_remove_sysfs_attrs,
+	.port_probe		= edge_port_probe,
+	.port_remove		= edge_port_remove,
 	.ioctl			= edge_ioctl,
 	.set_termios		= edge_set_termios,
 	.tiocmget		= edge_tiocmget,
author maintainer
#26 lore raw

PATCH 23/85 USB: io_ti: fix sysfs-attribute creation

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit 5d8c61bc283826827e1f06816c146bfc507d3834 upstream.

Make sure port data is initialised before creating sysfs attributes to avoid a race.

A recent patch ("USB: io_ti: fix port-data memory leak") got the sysfs-attribute creation and port-data initialisation ordering wrong.

---
 drivers/usb/serial/io_ti.c |   14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
drivers/usb/serial/io_ti.c +7 -7
@@ -2641,13 +2641,6 @@ static int edge_port_probe(struct usb_se
 		return -ENOMEM;
 	}
 
-	ret = edge_create_sysfs_attrs(port);
-	if (ret) {
-		kfifo_free(&edge_port->write_fifo);
-		kfree(edge_port);
-		return ret;
-	}
-
 	spin_lock_init(&edge_port->ep_lock);
 	edge_port->port = port;
 	edge_port->edge_serial = usb_get_serial_data(port->serial);
@@ -2655,6 +2648,13 @@ static int edge_port_probe(struct usb_se
 
 	usb_set_serial_port_data(port, edge_port);
 
+	ret = edge_create_sysfs_attrs(port);
+	if (ret) {
+		kfifo_free(&edge_port->write_fifo);
+		kfree(edge_port);
+		return ret;
+	}
+
 	return 0;
 }
 
author maintainer
#27 lore raw

PATCH 24/85 USB: cyberjack: fix port-data memory leak

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit a9556040119a63d06fd5238d47f5b683fba4178b upstream.

Fix port-data memory leak by replacing attach and release with port_probe and port_remove.

Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible.

Note that the write waitqueue was initialised but never used.

Compile-only tested.

---
 drivers/usb/serial/cyberjack.c |   48 ++++++++++++++++-------------------------
 1 file changed, 19 insertions(+), 29 deletions(-)
drivers/usb/serial/cyberjack.c +19 -29
@@ -57,9 +57,9 @@ static bool debug;
 #define CYBERJACK_PRODUCT_ID	0x0100
 
 /* Function prototypes */
-static int cyberjack_startup(struct usb_serial *serial);
 static void cyberjack_disconnect(struct usb_serial *serial);
-static void cyberjack_release(struct usb_serial *serial);
+static int cyberjack_port_probe(struct usb_serial_port *port);
+static int cyberjack_port_remove(struct usb_serial_port *port);
 static int  cyberjack_open(struct tty_struct *tty,
 	struct usb_serial_port *port);
 static void cyberjack_close(struct usb_serial_port *port);
@@ -85,9 +85,9 @@ static struct usb_serial_driver cyberjac
 	.description =		"Reiner SCT Cyberjack USB card reader",
 	.id_table =		id_table,
 	.num_ports =		1,
-	.attach =		cyberjack_startup,
 	.disconnect =		cyberjack_disconnect,
-	.release =		cyberjack_release,
+	.port_probe =		cyberjack_port_probe,
+	.port_remove =		cyberjack_port_remove,
 	.open =			cyberjack_open,
 	.close =		cyberjack_close,
 	.write =		cyberjack_write,
@@ -109,55 +109,45 @@ struct cyberjack_private {
 	short		wrsent;		/* Data already sent */
 };
 
-/* do some startup allocations not currently performed by usb_serial_probe() */
-static int cyberjack_startup(struct usb_serial *serial)
+static int cyberjack_port_probe(struct usb_serial_port *port)
 {
 	struct cyberjack_private *priv;
-	int i;
+	int result;
 
-	/* allocate the private data structure */
 	priv = kmalloc(sizeof(struct cyberjack_private), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
-	/* set initial values */
 	spin_lock_init(&priv->lock);
 	priv->rdtodo = 0;
 	priv->wrfilled = 0;
 	priv->wrsent = 0;
-	usb_set_serial_port_data(serial->port[0], priv);
 
-	init_waitqueue_head(&serial->port[0]->write_wait);
+	usb_set_serial_port_data(port, priv);
 
-	for (i = 0; i < serial->num_ports; ++i) {
-		int result;
-		result = usb_submit_urb(serial->port[i]->interrupt_in_urb,
-					GFP_KERNEL);
-		if (result)
-			dev_err(&serial->dev->dev,
-				"usb_submit_urb(read int) failed\n");
-		dbg("%s - usb_submit_urb(int urb)", __func__);
-	}
+	result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+	if (result)
+		dev_err(&port->dev, "usb_submit_urb(read int) failed\n");
 
 	return 0;
 }
 
-static void cyberjack_disconnect(struct usb_serial *serial)
+static int cyberjack_port_remove(struct usb_serial_port *port)
 {
-	int i;
+	struct cyberjack_private *priv;
 
-	for (i = 0; i < serial->num_ports; ++i)
-		usb_kill_urb(serial->port[i]->interrupt_in_urb);
+	priv = usb_get_serial_port_data(port);
+	kfree(priv);
+
+	return 0;
 }
 
-static void cyberjack_release(struct usb_serial *serial)
+static void cyberjack_disconnect(struct usb_serial *serial)
 {
 	int i;
 
-	for (i = 0; i < serial->num_ports; ++i) {
-		/* My special items, the standard routines free my urbs */
-		kfree(usb_get_serial_port_data(serial->port[i]));
-	}
+	for (i = 0; i < serial->num_ports; ++i)
+		usb_kill_urb(serial->port[i]->interrupt_in_urb);
 }
 
 static int  cyberjack_open(struct tty_struct *tty,
author maintainer
#28 lore raw

PATCH 25/85 usb: musb: am35xx: drop spurious unplugging a device

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Stefano Babic <[email protected]>

commit 6ff1f3d3bd7c69c62ca5773b1b684bce42eff06a upstream.

On AM3517, tx and rx interrupt are detected together with the disconnect event. This generates a kernel panic in musb_interrupt, because rx / tx are handled after disconnect.
This issue was seen on a Technexion's TAM3517 SOM. Unplugging a device, tx / rx interrupts together with disconnect are detected. This brings to kernel panic like this:

[   68.526153] Unable to handle kernel NULL pointer dereference at virtual address 00000011
[   68.534698] pgd = c0004000
[   68.537536] [00000011] *pgd=00000000
[   68.541351] Internal error: Oops: 17 [#1] ARM
[   68.545928] Modules linked in:
[   68.549163] CPU: 0    Not tainted  (3.6.0-rc5-00020-g9e05905 #178)
[   68.555694] PC is at rxstate+0x8/0xdc
[   68.559539] LR is at musb_interrupt+0x98/0x858
[   68.564239] pc : [<c035cd88>]    lr : [<c035af1c>]    psr: 40000193
[   68.564239] sp : ce83fb40  ip : d0906410  fp : 00000000
[   68.576293] r10: 00000000  r9 : cf3b0e40  r8 : 00000002
[   68.581817] r7 : 00000019  r6 : 00000001  r5 : 00000001  r4 : 000000d4
[   68.588684] r3 : 00000000  r2 : 00000000  r1 : ffffffcc  r0 : cf23c108
[   68.595550] Flags: nZcv  IRQs off  FIQs on  Mode SVC_32  ISA ARM  Segment ke

Note: this behavior is not seen with a USB hub, while it is easy to reproduce connecting a USB-pen directly to the USB-A of the board.

Drop tx / rx interrupts if disconnect is detected.

---
 drivers/usb/musb/am35x.c |    6 ++++++
 1 file changed, 6 insertions(+)
drivers/usb/musb/am35x.c +6 -0
@@ -312,6 +312,12 @@ static irqreturn_t am35x_musb_interrupt(
 		ret = IRQ_HANDLED;
 	}
 
+	/* Drop spurious RX and TX if device is disconnected */
+	if (musb->int_usb & MUSB_INTR_DISCONNECT) {
+		musb->int_tx = 0;
+		musb->int_rx = 0;
+	}
+
 	if (musb->int_tx || musb->int_rx || musb->int_usb)
 		ret |= musb_interrupt(musb);
 
author maintainer
#29 lore raw

PATCH 26/85 usb: host: xhci: New system added for Compliance Mode Patch on SN65LVPE502CP

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: "Alexis R. Cortes" <[email protected]>

commit 470809741a28c3092279f4e1f3f432e534d46068 upstream.

This minor change adds a new system to which the "Fix Compliance Mode on SN65LVPE502CP Hardware" patch has to be applied also.

System added:
Vendor: Hewlett-Packard. System Model: Z1

---
 drivers/usb/host/xhci.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/usb/host/xhci.c +2 -1
@@ -479,7 +479,8 @@ static bool compliance_mode_recovery_tim
 
 	if (strstr(dmi_product_name, "Z420") ||
 			strstr(dmi_product_name, "Z620") ||
-			strstr(dmi_product_name, "Z820"))
+			strstr(dmi_product_name, "Z820") ||
+			strstr(dmi_product_name, "Z1"))
 		return true;
 
 	return false;
#30 lore raw

Re: [ 26/85] usb: host: xhci: New system added for Compliance Mode Patch on SN65LVPE502CP

Quoted 13 lines · Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: "Alexis R. Cortes" <[email protected]>

commit 470809741a28c3092279f4e1f3f432e534d46068 upstream.

This minor change adds a new system to which the "Fix Compliance Mode on SN65LVPE502CP Hardware" patch has to be applied also.

System added:
Vendor: Hewlett-Packard. System Model: Z1

[...]

drivers/usb/host/xhci.c static bool compliance_mode_recovery_tim · line 483

Quoted 9 lines
drivers/usb/host/xhci.c +2 -1
@@ -479,7 +479,8 @@ static bool compliance_mode_recovery_tim
 
 	if (strstr(dmi_product_name, "Z420") ||
 			strstr(dmi_product_name, "Z620") ||
-			strstr(dmi_product_name, "Z820"))
+			strstr(dmi_product_name, "Z820") ||
+			strstr(dmi_product_name, "Z1"))

This will also match any future models with extra digits after the '1'. It might be worth using a slightly stricter match.

Ben.

Quoted 3 lines
drivers/usb/host/xhci.c +0 -0
 		return true;
 
 	return false;
Signature · 2 lines
Ben Hutchings
Never attribute to conspiracy what can adequately be explained by stupidity.
#31 lore raw

Re: [ 26/85] usb: host: xhci: New system added for Compliance Mode Patch on SN65LVPE502CP

Quoted 19 lines · Ben Hutchings
Quoted 13 lines · Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: "Alexis R. Cortes" <[email protected]>

commit 470809741a28c3092279f4e1f3f432e534d46068 upstream.

This minor change adds a new system to which the "Fix Compliance Mode on SN65LVPE502CP Hardware" patch has to be applied also.

System added:
Vendor: Hewlett-Packard. System Model: Z1

[...]

Quoted 4 lines
drivers/usb/host/xhci.c +0 -0
@@ -479,7 +479,8 @@ static bool compliance_mode_recovery_tim
 
Quoted 8 lines

drivers/usb/host/xhci.c static bool compliance_mode_recovery_tim · line 483

Quoted 5 lines
drivers/usb/host/xhci.c +2 -1
 	if (strstr(dmi_product_name, "Z420") ||
 			strstr(dmi_product_name, "Z620") ||
-			strstr(dmi_product_name, "Z820"))
+			strstr(dmi_product_name, "Z820") ||
+			strstr(dmi_product_name, "Z1"))

This will also match any future models with extra digits after the '1'. It might be worth using a slightly stricter match.

Hmm, Ben has a point. We don't want to have the timer run on a machine that really doesn't need the quirk, or we impact battery life.

Alex, can you make a new patch that fixes this?

Sarah Sharp

author maintainer
#32 lore raw

PATCH 27/85 USB: iuu_phoenix: fix port-data memory leak

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit 53636555b9190f88320d9d46cf142f8797895456 upstream.

Fix port-data memory leak by replacing attach and release with port_probe and port_remove.

Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible.

Compile-only tested.

---
 drivers/usb/serial/iuu_phoenix.c |   70 ++++++++++++++++-----------------------
 1 file changed, 30 insertions(+), 40 deletions(-)
drivers/usb/serial/iuu_phoenix.c +30 -40
@@ -80,64 +80,54 @@ struct iuu_private {
 	u32 clk;
 };
 
-
-static void iuu_free_buf(struct iuu_private *priv)
+static int iuu_port_probe(struct usb_serial_port *port)
 {
-	kfree(priv->buf);
-	kfree(priv->dbgbuf);
-	kfree(priv->writebuf);
-}
+	struct iuu_private *priv;
+
+	priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
 
-static int iuu_alloc_buf(struct iuu_private *priv)
-{
 	priv->buf = kzalloc(256, GFP_KERNEL);
-	priv->dbgbuf = kzalloc(256, GFP_KERNEL);
-	priv->writebuf = kzalloc(256, GFP_KERNEL);
-	if (!priv->buf || !priv->dbgbuf || !priv->writebuf) {
-		iuu_free_buf(priv);
-		dbg("%s problem allocation buffer", __func__);
+	if (!priv->buf) {
+		kfree(priv);
 		return -ENOMEM;
 	}
-	dbg("%s - Privates buffers allocation success", __func__);
-	return 0;
-}
 
-static int iuu_startup(struct usb_serial *serial)
-{
-	struct iuu_private *priv;
-	priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL);
-	dbg("%s- priv allocation success", __func__);
-	if (!priv)
+	priv->writebuf = kzalloc(256, GFP_KERNEL);
+	if (!priv->writebuf) {
+		kfree(priv->buf);
+		kfree(priv);
 		return -ENOMEM;
-	if (iuu_alloc_buf(priv)) {
+	}
+
+	priv->dbgbuf = kzalloc(256, GFP_KERNEL);
+	if (!priv->writebuf) {
+		kfree(priv->writebuf);
+		kfree(priv->buf);
 		kfree(priv);
 		return -ENOMEM;
 	}
+
 	priv->vcc = vcc_default;
 	spin_lock_init(&priv->lock);
 	init_waitqueue_head(&priv->delta_msr_wait);
-	usb_set_serial_port_data(serial->port[0], priv);
+
+	usb_set_serial_port_data(port, priv);
+
 	return 0;
 }
 
-/* Release function */
-static void iuu_release(struct usb_serial *serial)
+static int iuu_port_remove(struct usb_serial_port *port)
 {
-	struct usb_serial_port *port = serial->port[0];
 	struct iuu_private *priv = usb_get_serial_port_data(port);
-	if (!port)
-		return;
-
-	if (priv) {
-		iuu_free_buf(priv);
-		dbg("%s - I will free all", __func__);
-		usb_set_serial_port_data(port, NULL);
 
-		dbg("%s - priv is not anymore in port structure", __func__);
-		kfree(priv);
+	kfree(priv->dbgbuf);
+	kfree(priv->writebuf);
+	kfree(priv->buf);
+	kfree(priv);
 
-		dbg("%s priv is now kfree", __func__);
-	}
+	return 0;
 }
 
 static int iuu_tiocmset(struct tty_struct *tty,
@@ -1241,8 +1231,8 @@ static struct usb_serial_driver iuu_devi
 	.tiocmset = iuu_tiocmset,
 	.set_termios = iuu_set_termios,
 	.init_termios = iuu_init_termios,
-	.attach = iuu_startup,
-	.release = iuu_release,
+	.port_probe = iuu_port_probe,
+	.port_remove = iuu_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
author maintainer
#33 lore raw

PATCH 28/85 USB: iuu_phoenix: fix sysfs-attribute creation

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit 0978c9499944d0670338fd048a3bdb1624dc66dc upstream.

Make sure sysfs attributes are created at port probe.

A recent patch ("USB: iuu_phoenix: fix port-data memory leak") removed the sysfs-attribute creation by mistake.

---
 drivers/usb/serial/iuu_phoenix.c |   14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)
drivers/usb/serial/iuu_phoenix.c +12 -2
@@ -60,6 +60,8 @@ static int iuu_cardout;
 static bool xmas;
 static int vcc_default = 5;
 
+static int iuu_create_sysfs_attrs(struct usb_serial_port *port);
+static int iuu_remove_sysfs_attrs(struct usb_serial_port *port);
 static void read_rxcmd_callback(struct urb *urb);
 
 struct iuu_private {
@@ -83,6 +85,7 @@ struct iuu_private {
 static int iuu_port_probe(struct usb_serial_port *port)
 {
 	struct iuu_private *priv;
+	int ret;
 
 	priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL);
 	if (!priv)
@@ -115,6 +118,14 @@ static int iuu_port_probe(struct usb_ser
 
 	usb_set_serial_port_data(port, priv);
 
+	ret = iuu_create_sysfs_attrs(port);
+	if (ret) {
+		kfree(priv->writebuf);
+		kfree(priv->buf);
+		kfree(priv);
+		return ret;
+	}
+
 	return 0;
 }
 
@@ -122,6 +133,7 @@ static int iuu_port_remove(struct usb_se
 {
 	struct iuu_private *priv = usb_get_serial_port_data(port);
 
+	iuu_remove_sysfs_attrs(port);
 	kfree(priv->dbgbuf);
 	kfree(priv->writebuf);
 	kfree(priv->buf);
@@ -1221,8 +1233,6 @@ static struct usb_serial_driver iuu_devi
 	.num_ports = 1,
 	.bulk_in_size = 512,
 	.bulk_out_size = 512,
-	.port_probe = iuu_create_sysfs_attrs,
-	.port_remove = iuu_remove_sysfs_attrs,
 	.open = iuu_open,
 	.close = iuu_close,
 	.write = iuu_uart_write,
author maintainer
#34 lore raw

PATCH 29/85 USB: ark3116: fix NULL-pointer dereference

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit 7bdce71822f471433dd3014692e9096996c7b5f0 upstream.

Fix NULL-pointer dereference at release by replacing attach and release with port_probe and port_remove.

Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is NULL when release is called.

Compile-only tested.

---
 drivers/usb/serial/ark3116.c |   26 ++++++++++++++------------
 1 file changed, 14 insertions(+), 12 deletions(-)
drivers/usb/serial/ark3116.c +14 -12
@@ -126,9 +126,6 @@ static inline int calc_divisor(int bps)
 
 static int ark3116_attach(struct usb_serial *serial)
 {
-	struct usb_serial_port *port = serial->port[0];
-	struct ark3116_private *priv;
-
 	/* make sure we have our end-points */
 	if ((serial->num_bulk_in == 0) ||
 	    (serial->num_bulk_out == 0) ||
@@ -143,8 +140,15 @@ static int ark3116_attach(struct usb_ser
 		return -EINVAL;
 	}
 
-	priv = kzalloc(sizeof(struct ark3116_private),
-		       GFP_KERNEL);
+	return 0;
+}
+
+static int ark3116_port_probe(struct usb_serial_port *port)
+{
+	struct usb_serial *serial = port->serial;
+	struct ark3116_private *priv;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
@@ -199,18 +203,15 @@ static int ark3116_attach(struct usb_ser
 	return 0;
 }
 
-static void ark3116_release(struct usb_serial *serial)
+static int ark3116_port_remove(struct usb_serial_port *port)
 {
-	struct usb_serial_port *port = serial->port[0];
 	struct ark3116_private *priv = usb_get_serial_port_data(port);
 
 	/* device is closed, so URBs and DMA should be down */
-
-	usb_set_serial_port_data(port, NULL);
-
 	mutex_destroy(&priv->hw_lock);
-
 	kfree(priv);
+
+	return 0;
 }
 
 static void ark3116_init_termios(struct tty_struct *tty)
@@ -725,7 +726,8 @@ static struct usb_serial_driver ark3116_
 	.id_table =		id_table,
 	.num_ports =		1,
 	.attach =		ark3116_attach,
-	.release =		ark3116_release,
+	.port_probe =		ark3116_port_probe,
+	.port_remove =		ark3116_port_remove,
 	.set_termios =		ark3116_set_termios,
 	.init_termios =		ark3116_init_termios,
 	.ioctl =		ark3116_ioctl,
author maintainer
#35 lore raw

PATCH 30/85 USB: f81232: fix port-data memory leak

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit 3124d1d71d3df59d40b913b5481df58099e811d1 upstream.

Fix port-data memory leak by replacing attach and release with port_probe and port_remove.

Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible.

Compile-only tested.

---
 drivers/usb/serial/f81232.c |   43 +++++++++++++++++--------------------------
 1 file changed, 17 insertions(+), 26 deletions(-)
drivers/usb/serial/f81232.c +17 -26
@@ -319,39 +319,30 @@ static int f81232_ioctl(struct tty_struc
 	return -ENOIOCTLCMD;
 }
 
-static int f81232_startup(struct usb_serial *serial)
+static int f81232_port_probe(struct usb_serial_port *port)
 {
 	struct f81232_private *priv;
-	int i;
 
-	for (i = 0; i < serial->num_ports; ++i) {
-		priv = kzalloc(sizeof(struct f81232_private), GFP_KERNEL);
-		if (!priv)
-			goto cleanup;
-		spin_lock_init(&priv->lock);
-		init_waitqueue_head(&priv->delta_msr_wait);
-		usb_set_serial_port_data(serial->port[i], priv);
-	}
-	return 0;
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	spin_lock_init(&priv->lock);
+	init_waitqueue_head(&priv->delta_msr_wait);
+
+	usb_set_serial_port_data(port, priv);
 
-cleanup:
-	for (--i; i >= 0; --i) {
-		priv = usb_get_serial_port_data(serial->port[i]);
-		kfree(priv);
-		usb_set_serial_port_data(serial->port[i], NULL);
-	}
-	return -ENOMEM;
+	return 0;
 }
 
-static void f81232_release(struct usb_serial *serial)
+static int f81232_port_remove(struct usb_serial_port *port)
 {
-	int i;
 	struct f81232_private *priv;
 
-	for (i = 0; i < serial->num_ports; ++i) {
-		priv = usb_get_serial_port_data(serial->port[i]);
-		kfree(priv);
-	}
+	priv = usb_get_serial_port_data(port);
+	kfree(priv);
+
+	return 0;
 }
 
 static struct usb_serial_driver f81232_device = {
@@ -374,8 +365,8 @@ static struct usb_serial_driver f81232_d
 	.tiocmset =		f81232_tiocmset,
 	.process_read_urb =	f81232_process_read_urb,
 	.read_int_callback =	f81232_read_int_callback,
-	.attach =		f81232_startup,
-	.release =		f81232_release,
+	.port_probe =		f81232_port_probe,
+	.port_remove =		f81232_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
author maintainer
#36 lore raw

PATCH 31/85 USB: oti6858: fix port-data memory leak

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit 289b076f89c2c3260e914dad18ae12f193ea86d5 upstream.

Fix port-data memory leak by replacing attach and release with port_probe and port_remove.

Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible.

Compile-only tested.

---
 drivers/usb/serial/oti6858.c |   68 +++++++++++++++++--------------------------
 1 file changed, 28 insertions(+), 40 deletions(-)
drivers/usb/serial/oti6858.c +28 -40
@@ -139,8 +139,8 @@ static int oti6858_chars_in_buffer(struc
 static int oti6858_tiocmget(struct tty_struct *tty);
 static int oti6858_tiocmset(struct tty_struct *tty,
 				unsigned int set, unsigned int clear);
-static int oti6858_startup(struct usb_serial *serial);
-static void oti6858_release(struct usb_serial *serial);
+static int oti6858_port_probe(struct usb_serial_port *port);
+static int oti6858_port_remove(struct usb_serial_port *port);
 
 /* device info */
 static struct usb_serial_driver oti6858_device = {
@@ -163,8 +163,8 @@ static struct usb_serial_driver oti6858_
 	.write_bulk_callback =	oti6858_write_bulk_callback,
 	.write_room =		oti6858_write_room,
 	.chars_in_buffer =	oti6858_chars_in_buffer,
-	.attach =		oti6858_startup,
-	.release =		oti6858_release,
+	.port_probe =		oti6858_port_probe,
+	.port_remove =		oti6858_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
@@ -333,36 +333,33 @@ static void send_data(struct work_struct
 	usb_serial_port_softint(port);
 }
 
-static int oti6858_startup(struct usb_serial *serial)
+static int oti6858_port_probe(struct usb_serial_port *port)
 {
-	struct usb_serial_port *port = serial->port[0];
 	struct oti6858_private *priv;
-	int i;
 
-	for (i = 0; i < serial->num_ports; ++i) {
-		priv = kzalloc(sizeof(struct oti6858_private), GFP_KERNEL);
-		if (!priv)
-			break;
-
-		spin_lock_init(&priv->lock);
-		init_waitqueue_head(&priv->intr_wait);
-/*		INIT_WORK(&priv->setup_work, setup_line, serial->port[i]); */
-/*		INIT_WORK(&priv->write_work, send_data, serial->port[i]); */
-		priv->port = port;
-		INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line);
-		INIT_DELAYED_WORK(&priv->delayed_write_work, send_data);
-
-		usb_set_serial_port_data(serial->port[i], priv);
-	}
-	if (i == serial->num_ports)
-		return 0;
-
-	for (--i; i >= 0; --i) {
-		priv = usb_get_serial_port_data(serial->port[i]);
-		kfree(priv);
-		usb_set_serial_port_data(serial->port[i], NULL);
-	}
-	return -ENOMEM;
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	spin_lock_init(&priv->lock);
+	init_waitqueue_head(&priv->intr_wait);
+	priv->port = port;
+	INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line);
+	INIT_DELAYED_WORK(&priv->delayed_write_work, send_data);
+
+	usb_set_serial_port_data(port, priv);
+
+	return 0;
+}
+
+static int oti6858_port_remove(struct usb_serial_port *port)
+{
+	struct oti6858_private *priv;
+
+	priv = usb_get_serial_port_data(port);
+	kfree(priv);
+
+	return 0;
 }
 
 static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port,
@@ -714,15 +711,6 @@ static int oti6858_ioctl(struct tty_stru
 	return -ENOIOCTLCMD;
 }
 
-
-static void oti6858_release(struct usb_serial *serial)
-{
-	int i;
-
-	for (i = 0; i < serial->num_ports; ++i)
-		kfree(usb_get_serial_port_data(serial->port[i]));
-}
-
 static void oti6858_read_int_callback(struct urb *urb)
 {
 	struct usb_serial_port *port =  urb->context;
author maintainer
#37 lore raw

PATCH 32/85 USB: belkin_sa: fix port-data memory leak

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit fa919751a2d26a88140fc5810124dd81644efe51 upstream.

Fix port-data memory leak by replacing attach and release with port_probe and port_remove.

Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible.

Note that the write waitqueue was initialised but never used.

Compile-only tested.

---
 drivers/usb/serial/belkin_sa.c |   31 +++++++++++++++----------------
 1 file changed, 15 insertions(+), 16 deletions(-)
drivers/usb/serial/belkin_sa.c +15 -16
@@ -47,8 +47,8 @@ static bool debug;
 #define DRIVER_DESC "USB Belkin Serial converter driver"
 
 /* function prototypes for a Belkin USB Serial Adapter F5U103 */
-static int  belkin_sa_startup(struct usb_serial *serial);
-static void belkin_sa_release(struct usb_serial *serial);
+static int belkin_sa_port_probe(struct usb_serial_port *port);
+static int belkin_sa_port_remove(struct usb_serial_port *port);
 static int  belkin_sa_open(struct tty_struct *tty,
 			struct usb_serial_port *port);
 static void belkin_sa_close(struct usb_serial_port *port);
@@ -90,8 +90,8 @@ static struct usb_serial_driver belkin_d
 	.break_ctl =		belkin_sa_break_ctl,
 	.tiocmget =		belkin_sa_tiocmget,
 	.tiocmset =		belkin_sa_tiocmset,
-	.attach =		belkin_sa_startup,
-	.release =		belkin_sa_release,
+	.port_probe =		belkin_sa_port_probe,
+	.port_remove =		belkin_sa_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
@@ -120,17 +120,15 @@ struct belkin_sa_private {
 					    (c), BELKIN_SA_SET_REQUEST_TYPE, \
 					    (v), 0, NULL, 0, WDR_TIMEOUT)
 
-/* do some startup allocations not currently performed by usb_serial_probe() */
-static int belkin_sa_startup(struct usb_serial *serial)
+static int belkin_sa_port_probe(struct usb_serial_port *port)
 {
-	struct usb_device *dev = serial->dev;
+	struct usb_device *dev = port->serial->dev;
 	struct belkin_sa_private *priv;
 
-	/* allocate the private data structure */
 	priv = kmalloc(sizeof(struct belkin_sa_private), GFP_KERNEL);
 	if (!priv)
-		return -1; /* error */
-	/* set initial values for control structures */
+		return -ENOMEM;
+
 	spin_lock_init(&priv->lock);
 	priv->control_state = 0;
 	priv->last_lsr = 0;
@@ -142,18 +140,19 @@ static int belkin_sa_startup(struct usb_
 					le16_to_cpu(dev->descriptor.bcdDevice),
 					priv->bad_flow_control);
 
-	init_waitqueue_head(&serial->port[0]->write_wait);
-	usb_set_serial_port_data(serial->port[0], priv);
+	usb_set_serial_port_data(port, priv);
 
 	return 0;
 }
 
-static void belkin_sa_release(struct usb_serial *serial)
+static int belkin_sa_port_remove(struct usb_serial_port *port)
 {
-	int i;
+	struct belkin_sa_private *priv;
 
-	for (i = 0; i < serial->num_ports; ++i)
-		kfree(usb_get_serial_port_data(serial->port[i]));
+	priv = usb_get_serial_port_data(port);
+	kfree(priv);
+
+	return 0;
 }
 
 static int belkin_sa_open(struct tty_struct *tty,
author maintainer
#38 lore raw

PATCH 33/85 USB: pl2303: fix port-data memory leak

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit 8bf769eb5f6efc33f95088850f33fcc05d28b508 upstream.

Fix port-data memory leak by allocating and freeing port data in port_probe/remove rather than in attach/release, and by introducing serial private data to store the device type which is interface rather than port specific.

Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release.

---
 drivers/usb/serial/pl2303.c |   90 ++++++++++++++++++++++++++------------------
 1 file changed, 54 insertions(+), 36 deletions(-)
drivers/usb/serial/pl2303.c +54 -36
@@ -135,12 +135,15 @@ enum pl2303_type {
 	HX,		/* HX version of the pl2303 chip */
 };
 
+struct pl2303_serial_private {
+	enum pl2303_type type;
+};
+
 struct pl2303_private {
 	spinlock_t lock;
 	wait_queue_head_t delta_msr_wait;
 	u8 line_control;
 	u8 line_status;
-	enum pl2303_type type;
 };
 
 static int pl2303_vendor_read(__u16 value, __u16 index,
@@ -169,14 +172,19 @@ static int pl2303_vendor_write(__u16 val
 
 static int pl2303_startup(struct usb_serial *serial)
 {
-	struct pl2303_private *priv;
+	struct pl2303_serial_private *spriv;
 	enum pl2303_type type = type_0;
 	unsigned char *buf;
-	int i;
+
+	spriv = kzalloc(sizeof(*spriv), GFP_KERNEL);
+	if (!spriv)
+		return -ENOMEM;
 
 	buf = kmalloc(10, GFP_KERNEL);
-	if (buf == NULL)
+	if (!buf) {
+		kfree(spriv);
 		return -ENOMEM;
+	}
 
 	if (serial->dev->descriptor.bDeviceClass == 0x02)
 		type = type_0;
@@ -188,15 +196,8 @@ static int pl2303_startup(struct usb_ser
 		type = type_1;
 	dev_dbg(&serial->interface->dev, "device type: %d\n", type);
 
-	for (i = 0; i < serial->num_ports; ++i) {
-		priv = kzalloc(sizeof(struct pl2303_private), GFP_KERNEL);
-		if (!priv)
-			goto cleanup;
-		spin_lock_init(&priv->lock);
-		init_waitqueue_head(&priv->delta_msr_wait);
-		priv->type = type;
-		usb_set_serial_port_data(serial->port[i], priv);
-	}
+	spriv->type = type;
+	usb_set_serial_data(serial, spriv);
 
 	pl2303_vendor_read(0x8484, 0, serial, buf);
 	pl2303_vendor_write(0x0404, 0, serial);
@@ -215,15 +216,40 @@ static int pl2303_startup(struct usb_ser
 
 	kfree(buf);
 	return 0;
+}
 
-cleanup:
-	kfree(buf);
-	for (--i; i >= 0; --i) {
-		priv = usb_get_serial_port_data(serial->port[i]);
-		kfree(priv);
-		usb_set_serial_port_data(serial->port[i], NULL);
-	}
-	return -ENOMEM;
+static void pl2303_release(struct usb_serial *serial)
+{
+	struct pl2303_serial_private *spriv;
+
+	spriv = usb_get_serial_data(serial);
+	kfree(spriv);
+}
+
+static int pl2303_port_probe(struct usb_serial_port *port)
+{
+	struct pl2303_private *priv;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	spin_lock_init(&priv->lock);
+	init_waitqueue_head(&priv->delta_msr_wait);
+
+	usb_set_serial_port_data(port, priv);
+
+	return 0;
+}
+
+static int pl2303_port_remove(struct usb_serial_port *port)
+{
+	struct pl2303_private *priv;
+
+	priv = usb_get_serial_port_data(port);
+	kfree(priv);
+
+	return 0;
 }
 
 static int set_control_lines(struct usb_device *dev, u8 value)
@@ -242,6 +268,7 @@ static void pl2303_set_termios(struct tt
 		struct usb_serial_port *port, struct ktermios *old_termios)
 {
 	struct usb_serial *serial = port->serial;
+	struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 	unsigned int cflag;
@@ -325,7 +352,7 @@ static void pl2303_set_termios(struct tt
 		}
 		if (baud > 1228800) {
 			/* type_0, type_1 only support up to 1228800 baud */
-			if (priv->type != HX)
+			if (spriv->type != HX)
 				baud = 1228800;
 			else if (baud > 6000000)
 				baud = 6000000;
@@ -428,7 +455,7 @@ static void pl2303_set_termios(struct tt
 	     buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
 
 	if (cflag & CRTSCTS) {
-		if (priv->type == HX)
+		if (spriv->type == HX)
 			pl2303_vendor_write(0x0, 0x61, serial);
 		else
 			pl2303_vendor_write(0x0, 0x41, serial);
@@ -470,10 +497,10 @@ static int pl2303_open(struct tty_struct
 {
 	struct ktermios tmp_termios;
 	struct usb_serial *serial = port->serial;
-	struct pl2303_private *priv = usb_get_serial_port_data(port);
+	struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
 	int result;
 
-	if (priv->type != HX) {
+	if (spriv->type != HX) {
 		usb_clear_halt(serial->dev, port->write_urb->pipe);
 		usb_clear_halt(serial->dev, port->read_urb->pipe);
 	} else {
@@ -657,17 +684,6 @@ static void pl2303_break_ctl(struct tty_
 		dev_err(&port->dev, "error sending break = %d\n", result);
 }
 
-static void pl2303_release(struct usb_serial *serial)
-{
-	int i;
-	struct pl2303_private *priv;
-
-	for (i = 0; i < serial->num_ports; ++i) {
-		priv = usb_get_serial_port_data(serial->port[i]);
-		kfree(priv);
-	}
-}
-
 static void pl2303_update_line_status(struct usb_serial_port *port,
 				      unsigned char *data,
 				      unsigned int actual_length)
@@ -829,6 +845,8 @@ static struct usb_serial_driver pl2303_d
 	.read_int_callback =	pl2303_read_int_callback,
 	.attach =		pl2303_startup,
 	.release =		pl2303_release,
+	.port_probe =		pl2303_port_probe,
+	.port_remove =		pl2303_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
author maintainer
#39 lore raw

PATCH 34/85 USB: ssu100: fix port-data memory leak

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit 638b9e15233c9570bce65301aa9877235316b9f0 upstream.

Fix port-data memory leak by replacing attach and release with port_probe and port_remove.

Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible.

Compile-only tested.

---
 drivers/usb/serial/ssu100.c |   34 ++++++++++++++++++++--------------
 1 file changed, 20 insertions(+), 14 deletions(-)
drivers/usb/serial/ssu100.c +20 -14
@@ -69,13 +69,6 @@ struct ssu100_port_private {
 	struct async_icount icount;
 };
 
-static void ssu100_release(struct usb_serial *serial)
-{
-	struct ssu100_port_private *priv = usb_get_serial_port_data(*serial->port);
-
-	kfree(priv);
-}
-
 static inline int ssu100_control_msg(struct usb_device *dev,
 				     u8 request, u16 data, u16 index)
 {
@@ -444,21 +437,33 @@ static int ssu100_ioctl(struct tty_struc
 
 static int ssu100_attach(struct usb_serial *serial)
 {
+	return ssu100_initdevice(serial->dev);
+}
+
+static int ssu100_port_probe(struct usb_serial_port *port)
+{
 	struct ssu100_port_private *priv;
-	struct usb_serial_port *port = *serial->port;
 
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-	if (!priv) {
-		dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", __func__,
-			sizeof(*priv));
+	if (!priv)
 		return -ENOMEM;
-	}
 
 	spin_lock_init(&priv->status_lock);
 	init_waitqueue_head(&priv->delta_msr_wait);
+
 	usb_set_serial_port_data(port, priv);
 
-	return ssu100_initdevice(serial->dev);
+	return 0;
+}
+
+static int ssu100_port_remove(struct usb_serial_port *port)
+{
+	struct ssu100_port_private *priv;
+
+	priv = usb_get_serial_port_data(port);
+	kfree(priv);
+
+	return 0;
 }
 
 static int ssu100_tiocmget(struct tty_struct *tty)
@@ -649,7 +654,8 @@ static struct usb_serial_driver ssu100_d
 	.open		     = ssu100_open,
 	.close		     = ssu100_close,
 	.attach              = ssu100_attach,
-	.release             = ssu100_release,
+	.port_probe          = ssu100_port_probe,
+	.port_remove         = ssu100_port_remove,
 	.dtr_rts             = ssu100_dtr_rts,
 	.process_read_urb    = ssu100_process_read_urb,
 	.tiocmget            = ssu100_tiocmget,
author maintainer
#40 lore raw

PATCH 35/85 USB: kobil_sct: fix port-data memory leak

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit 95940a04bfe8a4d246f4ca17c6a3b00148bdead0 upstream.

Fix port-data memory leak by replacing attach and release with port_probe and port_remove.

Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible.

Compile-only tested.

---
 drivers/usb/serial/kobil_sct.c |   23 +++++++++++++----------
 1 file changed, 13 insertions(+), 10 deletions(-)
drivers/usb/serial/kobil_sct.c +13 -10
@@ -56,8 +56,8 @@ static bool debug;
 
 
 /* Function prototypes */
-static int  kobil_startup(struct usb_serial *serial);
-static void kobil_release(struct usb_serial *serial);
+static int kobil_port_probe(struct usb_serial_port *probe);
+static int kobil_port_remove(struct usb_serial_port *probe);
 static int  kobil_open(struct tty_struct *tty, struct usb_serial_port *port);
 static void kobil_close(struct usb_serial_port *port);
 static int  kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
@@ -91,8 +91,8 @@ static struct usb_serial_driver kobil_de
 	.description =		"KOBIL USB smart card terminal",
 	.id_table =		id_table,
 	.num_ports =		1,
-	.attach =		kobil_startup,
-	.release =		kobil_release,
+	.port_probe =		kobil_port_probe,
+	.port_remove =		kobil_port_remove,
 	.ioctl =		kobil_ioctl,
 	.set_termios =		kobil_set_termios,
 	.init_termios =		kobil_init_termios,
@@ -119,9 +119,10 @@ struct kobil_private {
 };
 
 
-static int kobil_startup(struct usb_serial *serial)
+static int kobil_port_probe(struct usb_serial_port *port)
 {
 	int i;
+	struct usb_serial *serial = port->serial;
 	struct kobil_private *priv;
 	struct usb_device *pdev;
 	struct usb_host_config *actconfig;
@@ -152,7 +153,7 @@ static int kobil_startup(struct usb_seri
 		printk(KERN_DEBUG "KOBIL KAAN SIM detected\n");
 		break;
 	}
-	usb_set_serial_port_data(serial->port[0], priv);
+	usb_set_serial_port_data(port, priv);
 
 	/* search for the necessary endpoints */
 	pdev = serial->dev;
@@ -180,12 +181,14 @@ static int kobil_startup(struct usb_seri
 }
 
 
-static void kobil_release(struct usb_serial *serial)
+static int kobil_port_remove(struct usb_serial_port *port)
 {
-	int i;
+	struct kobil_private *priv;
 
-	for (i = 0; i < serial->num_ports; ++i)
-		kfree(usb_get_serial_port_data(serial->port[i]));
+	priv = usb_get_serial_port_data(port);
+	kfree(priv);
+
+	return 0;
 }
 
 static void kobil_init_termios(struct tty_struct *tty)
author maintainer
#41 lore raw

PATCH 36/85 USB: cypress_m8: fix port-data memory leak

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit 5c1a0f418d8d985f3a62849bcac43fc5404cc592 upstream.

Fix port-data memory leak by replacing attach and release with port_probe and port_remove.

Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible.

Compile-only tested.

---
 drivers/usb/serial/cypress_m8.c |   82 ++++++++++++++++++++--------------------
 1 file changed, 41 insertions(+), 41 deletions(-)
drivers/usb/serial/cypress_m8.c +41 -41
@@ -124,10 +124,10 @@ struct cypress_private {
 };
 
 /* function prototypes for the Cypress USB to serial device */
-static int  cypress_earthmate_startup(struct usb_serial *serial);
-static int  cypress_hidcom_startup(struct usb_serial *serial);
-static int  cypress_ca42v2_startup(struct usb_serial *serial);
-static void cypress_release(struct usb_serial *serial);
+static int  cypress_earthmate_port_probe(struct usb_serial_port *port);
+static int  cypress_hidcom_port_probe(struct usb_serial_port *port);
+static int  cypress_ca42v2_port_probe(struct usb_serial_port *port);
+static int  cypress_port_remove(struct usb_serial_port *port);
 static int  cypress_open(struct tty_struct *tty, struct usb_serial_port *port);
 static void cypress_close(struct usb_serial_port *port);
 static void cypress_dtr_rts(struct usb_serial_port *port, int on);
@@ -157,8 +157,8 @@ static struct usb_serial_driver cypress_
 	.description =			"DeLorme Earthmate USB",
 	.id_table =			id_table_earthmate,
 	.num_ports =			1,
-	.attach =			cypress_earthmate_startup,
-	.release =			cypress_release,
+	.port_probe =			cypress_earthmate_port_probe,
+	.port_remove =			cypress_port_remove,
 	.open =				cypress_open,
 	.close =			cypress_close,
 	.dtr_rts =			cypress_dtr_rts,
@@ -183,8 +183,8 @@ static struct usb_serial_driver cypress_
 	.description =			"HID->COM RS232 Adapter",
 	.id_table =			id_table_cyphidcomrs232,
 	.num_ports =			1,
-	.attach =			cypress_hidcom_startup,
-	.release =			cypress_release,
+	.port_probe =			cypress_hidcom_port_probe,
+	.port_remove =			cypress_port_remove,
 	.open =				cypress_open,
 	.close =			cypress_close,
 	.dtr_rts =			cypress_dtr_rts,
@@ -209,8 +209,8 @@ static struct usb_serial_driver cypress_
 	.description =			"Nokia CA-42 V2 Adapter",
 	.id_table =			id_table_nokiaca42v2,
 	.num_ports =			1,
-	.attach =			cypress_ca42v2_startup,
-	.release =			cypress_release,
+	.port_probe =			cypress_ca42v2_port_probe,
+	.port_remove =			cypress_port_remove,
 	.open =				cypress_open,
 	.close =			cypress_close,
 	.dtr_rts =			cypress_dtr_rts,
@@ -437,10 +437,10 @@ static void cypress_set_dead(struct usb_
  *****************************************************************************/
 
 
-static int generic_startup(struct usb_serial *serial)
+static int cypress_generic_port_probe(struct usb_serial_port *port)
 {
+	struct usb_serial *serial = port->serial;
 	struct cypress_private *priv;
-	struct usb_serial_port *port = serial->port[0];
 
 	priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL);
 	if (!priv)
@@ -489,15 +489,17 @@ static int generic_startup(struct usb_se
 }
 
 
-static int cypress_earthmate_startup(struct usb_serial *serial)
+static int cypress_earthmate_port_probe(struct usb_serial_port *port)
 {
+	struct usb_serial *serial = port->serial;
 	struct cypress_private *priv;
-	struct usb_serial_port *port = serial->port[0];
+	int ret;
 
-	if (generic_startup(serial)) {
+	ret = cypress_generic_port_probe(port);
+	if (ret) {
 		dbg("%s - Failed setting up port %d", __func__,
 				port->number);
-		return 1;
+		return ret;
 	}
 
 	priv = usb_get_serial_port_data(port);
@@ -517,54 +519,52 @@ static int cypress_earthmate_startup(str
 	}
 
 	return 0;
-} /* cypress_earthmate_startup */
-
+}
 
-static int cypress_hidcom_startup(struct usb_serial *serial)
+static int cypress_hidcom_port_probe(struct usb_serial_port *port)
 {
 	struct cypress_private *priv;
+	int ret;
 
-	if (generic_startup(serial)) {
-		dbg("%s - Failed setting up port %d", __func__,
-				serial->port[0]->number);
-		return 1;
+	ret = cypress_generic_port_probe(port);
+	if (ret) {
+ 		dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__);
+		return ret;
 	}
 
-	priv = usb_get_serial_port_data(serial->port[0]);
+	priv = usb_get_serial_port_data(port);
 	priv->chiptype = CT_CYPHIDCOM;
 
 	return 0;
-} /* cypress_hidcom_startup */
-
+}
 
-static int cypress_ca42v2_startup(struct usb_serial *serial)
+static int cypress_ca42v2_port_probe(struct usb_serial_port *port)
 {
 	struct cypress_private *priv;
+	int ret;
 
-	if (generic_startup(serial)) {
-		dbg("%s - Failed setting up port %d", __func__,
-				serial->port[0]->number);
-		return 1;
+	ret = cypress_generic_port_probe(port);
+	if (ret) {
+ 		dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__);
+		return ret;
 	}
 
-	priv = usb_get_serial_port_data(serial->port[0]);
+	priv = usb_get_serial_port_data(port);
 	priv->chiptype = CT_CA42V2;
 
 	return 0;
-} /* cypress_ca42v2_startup */
-
+}
 
-static void cypress_release(struct usb_serial *serial)
+static int cypress_port_remove(struct usb_serial_port *port)
 {
 	struct cypress_private *priv;
 
-	/* all open ports are closed at this point */
-	priv = usb_get_serial_port_data(serial->port[0]);
+	priv = usb_get_serial_port_data(port);
 
-	if (priv) {
-		kfifo_free(&priv->write_fifo);
-		kfree(priv);
-	}
+	kfifo_free(&priv->write_fifo);
+	kfree(priv);
+
+	return 0;
 }
 
 
author maintainer
#42 lore raw

PATCH 37/85 USB: cp210x: fix port-data memory leak

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit 4295fe7791a1b20c90cbaaa6f23f2fb94218b8a7 upstream.

Fix port data memory leak by replacing port private data with serial private data.

Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release.

The private data is used to store the control interface number, but as this is the same for all ports on an interface it should be stored as usb-serial data anyway.

---
 drivers/usb/serial/cp210x.c |   43 ++++++++++++++++++-------------------------
 1 file changed, 18 insertions(+), 25 deletions(-)
drivers/usb/serial/cp210x.c +18 -25
@@ -164,7 +164,7 @@ static const struct usb_device_id id_tab
 
 MODULE_DEVICE_TABLE(usb, id_table);
 
-struct cp210x_port_private {
+struct cp210x_serial_private {
 	__u8			bInterfaceNumber;
 };
 
@@ -278,7 +278,7 @@ static int cp210x_get_config(struct usb_
 		unsigned int *data, int size)
 {
 	struct usb_serial *serial = port->serial;
-	struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
+	struct cp210x_serial_private *spriv = usb_get_serial_data(serial);
 	__le32 *buf;
 	int result, i, length;
 
@@ -294,7 +294,7 @@ static int cp210x_get_config(struct usb_
 	/* Issue the request, attempting to read 'size' bytes */
 	result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
 				request, REQTYPE_INTERFACE_TO_HOST, 0x0000,
-				port_priv->bInterfaceNumber, buf, size,
+				spriv->bInterfaceNumber, buf, size,
 				USB_CTRL_GET_TIMEOUT);
 
 	/* Convert data into an array of integers */
@@ -326,7 +326,7 @@ static int cp210x_set_config(struct usb_
 		unsigned int *data, int size)
 {
 	struct usb_serial *serial = port->serial;
-	struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
+	struct cp210x_serial_private *spriv = usb_get_serial_data(serial);
 	__le32 *buf;
 	int result, i, length;
 
@@ -348,13 +348,13 @@ static int cp210x_set_config(struct usb_
 		result = usb_control_msg(serial->dev,
 				usb_sndctrlpipe(serial->dev, 0),
 				request, REQTYPE_HOST_TO_INTERFACE, 0x0000,
-				port_priv->bInterfaceNumber, buf, size,
+				spriv->bInterfaceNumber, buf, size,
 				USB_CTRL_SET_TIMEOUT);
 	} else {
 		result = usb_control_msg(serial->dev,
 				usb_sndctrlpipe(serial->dev, 0),
 				request, REQTYPE_HOST_TO_INTERFACE, data[0],
-				port_priv->bInterfaceNumber, NULL, 0,
+				spriv->bInterfaceNumber, NULL, 0,
 				USB_CTRL_SET_TIMEOUT);
 	}
 
@@ -854,37 +854,30 @@ static void cp210x_break_ctl (struct tty
 
 static int cp210x_startup(struct usb_serial *serial)
 {
-	struct cp210x_port_private *port_priv;
-	int i;
+	struct usb_host_interface *cur_altsetting;
+	struct cp210x_serial_private *spriv;
 
 	/* cp210x buffers behave strangely unless device is reset */
 	usb_reset_device(serial->dev);
 
-	for (i = 0; i < serial->num_ports; i++) {
-		port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
-		if (!port_priv)
-			return -ENOMEM;
-
-		memset(port_priv, 0x00, sizeof(*port_priv));
-		port_priv->bInterfaceNumber =
-		    serial->interface->cur_altsetting->desc.bInterfaceNumber;
+	spriv = kzalloc(sizeof(*spriv), GFP_KERNEL);
+	if (!spriv)
+		return -ENOMEM;
 
-		usb_set_serial_port_data(serial->port[i], port_priv);
-	}
+	cur_altsetting = serial->interface->cur_altsetting;
+	spriv->bInterfaceNumber = cur_altsetting->desc.bInterfaceNumber;
+
+	usb_set_serial_data(serial, spriv);
 
 	return 0;
 }
 
 static void cp210x_release(struct usb_serial *serial)
 {
-	struct cp210x_port_private *port_priv;
-	int i;
+	struct cp210x_serial_private *spriv;
 
-	for (i = 0; i < serial->num_ports; i++) {
-		port_priv = usb_get_serial_port_data(serial->port[i]);
-		kfree(port_priv);
-		usb_set_serial_port_data(serial->port[i], NULL);
-	}
+	spriv = usb_get_serial_data(serial);
+	kfree(spriv);
 }
 
 module_usb_serial_driver(serial_drivers, id_table);
author maintainer
#43 lore raw

PATCH 38/85 USB: spcp8x5: fix port-data memory leak

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit bf90ff5f3b8f67e5b42df4ea4fd543f8010a2676 upstream.

Fix port-data memory leak by replacing attach and release with port_probe and port_remove.

Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible.

Compile-only tested.

---
 drivers/usb/serial/spcp8x5.c |   48 +++++++++++++++++--------------------------
 1 file changed, 19 insertions(+), 29 deletions(-)
drivers/usb/serial/spcp8x5.c +19 -29
@@ -159,13 +159,10 @@ struct spcp8x5_private {
 	u8 			line_status;
 };
 
-/* desc : when device plug in,this function would be called.
- * thanks to usb_serial subsystem,then do almost every things for us. And what
- * we should do just alloc the buffer */
-static int spcp8x5_startup(struct usb_serial *serial)
+static int spcp8x5_port_probe(struct usb_serial_port *port)
 {
+	struct usb_serial *serial = port->serial;
 	struct spcp8x5_private *priv;
-	int i;
 	enum spcp8x5_type type = SPCP825_007_TYPE;
 	u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
 
@@ -182,34 +179,27 @@ static int spcp8x5_startup(struct usb_se
 		type = SPCP825_PHILIP_TYPE;
 	dev_dbg(&serial->dev->dev, "device type = %d\n", (int)type);
 
-	for (i = 0; i < serial->num_ports; ++i) {
-		priv = kzalloc(sizeof(struct spcp8x5_private), GFP_KERNEL);
-		if (!priv)
-			goto cleanup;
-
-		spin_lock_init(&priv->lock);
-		init_waitqueue_head(&priv->delta_msr_wait);
-		priv->type = type;
-		usb_set_serial_port_data(serial->port[i] , priv);
-	}
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	spin_lock_init(&priv->lock);
+	init_waitqueue_head(&priv->delta_msr_wait);
+	priv->type = type;
+
+	usb_set_serial_port_data(port , priv);
 
 	return 0;
-cleanup:
-	for (--i; i >= 0; --i) {
-		priv = usb_get_serial_port_data(serial->port[i]);
-		kfree(priv);
-		usb_set_serial_port_data(serial->port[i] , NULL);
-	}
-	return -ENOMEM;
 }
 
-/* call when the device plug out. free all the memory alloced by probe */
-static void spcp8x5_release(struct usb_serial *serial)
+static int spcp8x5_port_remove(struct usb_serial_port *port)
 {
-	int i;
+	struct spcp8x5_private *priv;
 
-	for (i = 0; i < serial->num_ports; i++)
-		kfree(usb_get_serial_port_data(serial->port[i]));
+	priv = usb_get_serial_port_data(port);
+	kfree(priv);
+
+	return 0;
 }
 
 /* set the modem control line of the device.
@@ -651,8 +641,8 @@ static struct usb_serial_driver spcp8x5_
 	.ioctl 			= spcp8x5_ioctl,
 	.tiocmget 		= spcp8x5_tiocmget,
 	.tiocmset 		= spcp8x5_tiocmset,
-	.attach 		= spcp8x5_startup,
-	.release 		= spcp8x5_release,
+	.port_probe		= spcp8x5_port_probe,
+	.port_remove		= spcp8x5_port_remove,
 	.process_read_urb	= spcp8x5_process_read_urb,
 };
 
author maintainer
#44 lore raw

PATCH 39/85 USB: ti_usb_3410_5052: fix port-data memory leak

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit 51ef847df74632e7cfdf952afc3887de105b8b35 upstream.

Fix port-data memory leak by moving port data allocation and deallocation to port_probe and port_remove.

Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible.

Compile-only tested.

---
 drivers/usb/serial/ti_usb_3410_5052.c |   88 ++++++++++++++++------------------
 1 file changed, 43 insertions(+), 45 deletions(-)
drivers/usb/serial/ti_usb_3410_5052.c +43 -45
@@ -98,6 +98,8 @@ struct ti_device {
 
 static int ti_startup(struct usb_serial *serial);
 static void ti_release(struct usb_serial *serial);
+static int ti_port_probe(struct usb_serial_port *port);
+static int ti_port_remove(struct usb_serial_port *port);
 static int ti_open(struct tty_struct *tty, struct usb_serial_port *port);
 static void ti_close(struct usb_serial_port *port);
 static int ti_write(struct tty_struct *tty, struct usb_serial_port *port,
@@ -223,6 +225,8 @@ static struct usb_serial_driver ti_1port
 	.num_ports		= 1,
 	.attach			= ti_startup,
 	.release		= ti_release,
+	.port_probe		= ti_port_probe,
+	.port_remove		= ti_port_remove,
 	.open			= ti_open,
 	.close			= ti_close,
 	.write			= ti_write,
@@ -251,6 +255,8 @@ static struct usb_serial_driver ti_2port
 	.num_ports		= 2,
 	.attach			= ti_startup,
 	.release		= ti_release,
+	.port_probe		= ti_port_probe,
+	.port_remove		= ti_port_remove,
 	.open			= ti_open,
 	.close			= ti_close,
 	.write			= ti_write,
@@ -358,11 +364,8 @@ module_exit(ti_exit);
 static int ti_startup(struct usb_serial *serial)
 {
 	struct ti_device *tdev;
-	struct ti_port *tport;
 	struct usb_device *dev = serial->dev;
 	int status;
-	int i;
-
 
 	dbg("%s - product 0x%4X, num configurations %d, configuration value %d",
 	    __func__, le16_to_cpu(dev->descriptor.idProduct),
@@ -409,42 +412,8 @@ static int ti_startup(struct usb_serial
 		goto free_tdev;
 	}
 
-	/* set up port structures */
-	for (i = 0; i < serial->num_ports; ++i) {
-		tport = kzalloc(sizeof(struct ti_port), GFP_KERNEL);
-		if (tport == NULL) {
-			dev_err(&dev->dev, "%s - out of memory\n", __func__);
-			status = -ENOMEM;
-			goto free_tports;
-		}
-		spin_lock_init(&tport->tp_lock);
-		tport->tp_uart_base_addr = (i == 0 ?
-				TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR);
-		tport->tp_closing_wait = closing_wait;
-		init_waitqueue_head(&tport->tp_msr_wait);
-		init_waitqueue_head(&tport->tp_write_wait);
-		if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE,
-								GFP_KERNEL)) {
-			dev_err(&dev->dev, "%s - out of memory\n", __func__);
-			kfree(tport);
-			status = -ENOMEM;
-			goto free_tports;
-		}
-		tport->tp_port = serial->port[i];
-		tport->tp_tdev = tdev;
-		usb_set_serial_port_data(serial->port[i], tport);
-		tport->tp_uart_mode = 0;	/* default is RS232 */
-	}
-
 	return 0;
 
-free_tports:
-	for (--i; i >= 0; --i) {
-		tport = usb_get_serial_port_data(serial->port[i]);
-		kfifo_free(&tport->write_fifo);
-		kfree(tport);
-		usb_set_serial_port_data(serial->port[i], NULL);
-	}
 free_tdev:
 	kfree(tdev);
 	usb_set_serial_data(serial, NULL);
@@ -454,21 +423,50 @@ free_tdev:
 
 static void ti_release(struct usb_serial *serial)
 {
-	int i;
 	struct ti_device *tdev = usb_get_serial_data(serial);
+
+	kfree(tdev);
+}
+
+static int ti_port_probe(struct usb_serial_port *port)
+{
 	struct ti_port *tport;
 
-	for (i = 0; i < serial->num_ports; ++i) {
-		tport = usb_get_serial_port_data(serial->port[i]);
-		if (tport) {
-			kfifo_free(&tport->write_fifo);
-			kfree(tport);
-		}
+	tport = kzalloc(sizeof(*tport), GFP_KERNEL);
+	if (!tport)
+		return -ENOMEM;
+
+	spin_lock_init(&tport->tp_lock);
+	if (port == port->serial->port[0])
+		tport->tp_uart_base_addr = TI_UART1_BASE_ADDR;
+	else
+		tport->tp_uart_base_addr = TI_UART2_BASE_ADDR;
+	tport->tp_closing_wait = closing_wait;
+	init_waitqueue_head(&tport->tp_msr_wait);
+	init_waitqueue_head(&tport->tp_write_wait);
+	if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, GFP_KERNEL)) {
+		kfree(tport);
+		return -ENOMEM;
 	}
+	tport->tp_port = port;
+	tport->tp_tdev = usb_get_serial_data(port->serial);
+	tport->tp_uart_mode = 0;	/* default is RS232 */
 
-	kfree(tdev);
+	usb_set_serial_port_data(port, tport);
+
+	return 0;
 }
 
+static int ti_port_remove(struct usb_serial_port *port)
+{
+	struct ti_port *tport;
+
+	tport = usb_get_serial_port_data(port);
+	kfifo_free(&tport->write_fifo);
+	kfree(tport);
+
+	return 0;
+}
 
 static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
author maintainer
#45 lore raw

PATCH 40/85 USB: kl5kusb105: fix port-data memory leak

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit 99a6f73c495c420df826e5b267fb073fd6766fc3 upstream.

Fix port-data memory leak by replacing attach and release with port_probe and port_remove.

Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible.

Note that the write waitqueue was initialised but never used.

Compile-only tested.

---
 drivers/usb/serial/kl5kusb105.c |   68 ++++++++++++++--------------------------
 1 file changed, 25 insertions(+), 43 deletions(-)
drivers/usb/serial/kl5kusb105.c +25 -43
@@ -62,8 +62,8 @@ static bool debug;
 /*
  * Function prototypes
  */
-static int  klsi_105_startup(struct usb_serial *serial);
-static void klsi_105_release(struct usb_serial *serial);
+static int klsi_105_port_probe(struct usb_serial_port *port);
+static int klsi_105_port_remove(struct usb_serial_port *port);
 static int  klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port);
 static void klsi_105_close(struct usb_serial_port *port);
 static void klsi_105_set_termios(struct tty_struct *tty,
@@ -101,8 +101,8 @@ static struct usb_serial_driver kl5kusb1
 	/*.break_ctl =		klsi_105_break_ctl,*/
 	.tiocmget =		klsi_105_tiocmget,
 	.tiocmset =		klsi_105_tiocmset,
-	.attach =		klsi_105_startup,
-	.release =		klsi_105_release,
+	.port_probe =		klsi_105_port_probe,
+	.port_remove =		klsi_105_port_remove,
 	.throttle =		usb_serial_generic_throttle,
 	.unthrottle =		usb_serial_generic_unthrottle,
 	.process_read_urb =	klsi_105_process_read_urb,
@@ -225,58 +225,40 @@ static int klsi_105_get_line_state(struc
  * Driver's tty interface functions
  */
 
-static int klsi_105_startup(struct usb_serial *serial)
+static int klsi_105_port_probe(struct usb_serial_port *port)
 {
 	struct klsi_105_private *priv;
-	int i;
 
-	/* check if we support the product id (see keyspan.c)
-	 * FIXME
-	 */
-
-	/* allocate the private data structure */
-	for (i = 0; i < serial->num_ports; i++) {
-		priv = kmalloc(sizeof(struct klsi_105_private),
-						   GFP_KERNEL);
-		if (!priv) {
-			dbg("%skmalloc for klsi_105_private failed.", __func__);
-			i--;
-			goto err_cleanup;
-		}
-		/* set initial values for control structures */
-		priv->cfg.pktlen    = 5;
-		priv->cfg.baudrate  = kl5kusb105a_sio_b9600;
-		priv->cfg.databits  = kl5kusb105a_dtb_8;
-		priv->cfg.unknown1  = 0;
-		priv->cfg.unknown2  = 1;
+	priv = kmalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
 
-		priv->line_state    = 0;
+	/* set initial values for control structures */
+	priv->cfg.pktlen    = 5;
+	priv->cfg.baudrate  = kl5kusb105a_sio_b9600;
+	priv->cfg.databits  = kl5kusb105a_dtb_8;
+	priv->cfg.unknown1  = 0;
+	priv->cfg.unknown2  = 1;
 
-		usb_set_serial_port_data(serial->port[i], priv);
+	priv->line_state    = 0;
 
-		spin_lock_init(&priv->lock);
+	spin_lock_init(&priv->lock);
 
-		/* priv->termios is left uninitialized until port opening */
-		init_waitqueue_head(&serial->port[i]->write_wait);
-	}
+	/* priv->termios is left uninitialized until port opening */
 
-	return 0;
+	usb_set_serial_port_data(port, priv);
 
-err_cleanup:
-	for (; i >= 0; i--) {
-		priv = usb_get_serial_port_data(serial->port[i]);
-		kfree(priv);
-		usb_set_serial_port_data(serial->port[i], NULL);
-	}
-	return -ENOMEM;
+	return 0;
 }
 
-static void klsi_105_release(struct usb_serial *serial)
+static int klsi_105_port_remove(struct usb_serial_port *port)
 {
-	int i;
+	struct klsi_105_private *priv;
 
-	for (i = 0; i < serial->num_ports; ++i)
-		kfree(usb_get_serial_port_data(serial->port[i]));
+	priv = usb_get_serial_port_data(port);
+	kfree(priv);
+
+	return 0;
 }
 
 static int  klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
author maintainer
#46 lore raw

PATCH 41/85 USB: io_edgeport: fix port-data memory leak

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit c27f3efc56080a246f6ab7f57f0a6f56d256d769 upstream.

Fix port-data memory leak by moving port data allocation and deallocation to port_probe and port_remove.

Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible.

Compile-only tested.

---
 drivers/usb/serial/io_edgeport.c |   54 ++++++++++++++++++++-------------------
 drivers/usb/serial/io_tables.h   |    8 +++++
 2 files changed, 37 insertions(+), 25 deletions(-)
drivers/usb/serial/io_edgeport.c +29 -25
@@ -228,6 +228,8 @@ static int  edge_get_icount(struct tty_s
 static int  edge_startup(struct usb_serial *serial);
 static void edge_disconnect(struct usb_serial *serial);
 static void edge_release(struct usb_serial *serial);
+static int edge_port_probe(struct usb_serial_port *port);
+static int edge_port_remove(struct usb_serial_port *port);
 
 #include "io_tables.h"	/* all of the devices that this driver supports */
 
@@ -2921,9 +2923,8 @@ static void load_application_firmware(st
 static int edge_startup(struct usb_serial *serial)
 {
 	struct edgeport_serial *edge_serial;
-	struct edgeport_port *edge_port;
 	struct usb_device *dev;
-	int i, j;
+	int i;
 	int response;
 	bool interrupt_in_found;
 	bool bulk_in_found;
@@ -3007,26 +3008,6 @@ static int edge_startup(struct usb_seria
 	/* we set up the pointers to the endpoints in the edge_open function,
 	 * as the structures aren't created yet. */
 
-	/* set up our port private structures */
-	for (i = 0; i < serial->num_ports; ++i) {
-		edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL);
-		if (edge_port == NULL) {
-			dev_err(&serial->dev->dev, "%s - Out of memory\n",
-								   __func__);
-			for (j = 0; j < i; ++j) {
-				kfree(usb_get_serial_port_data(serial->port[j]));
-				usb_set_serial_port_data(serial->port[j],
-									NULL);
-			}
-			usb_set_serial_data(serial, NULL);
-			kfree(edge_serial);
-			return -ENOMEM;
-		}
-		spin_lock_init(&edge_port->ep_lock);
-		edge_port->port = serial->port[i];
-		usb_set_serial_port_data(serial->port[i], edge_port);
-	}
-
 	response = 0;
 
 	if (edge_serial->is_epic) {
@@ -3175,12 +3156,35 @@ static void edge_release(struct usb_seri
 
 	dbg("%s", __func__);
 
-	for (i = 0; i < serial->num_ports; ++i)
-		kfree(usb_get_serial_port_data(serial->port[i]));
-
 	kfree(edge_serial);
 }
 
+static int edge_port_probe(struct usb_serial_port *port)
+{
+	struct edgeport_port *edge_port;
+
+	edge_port = kzalloc(sizeof(*edge_port), GFP_KERNEL);
+	if (!edge_port)
+		return -ENOMEM;
+
+	spin_lock_init(&edge_port->ep_lock);
+	edge_port->port = port;
+
+	usb_set_serial_port_data(port, edge_port);
+
+	return 0;
+}
+
+static int edge_port_remove(struct usb_serial_port *port)
+{
+	struct edgeport_port *edge_port;
+
+	edge_port = usb_get_serial_port_data(port);
+	kfree(edge_port);
+
+	return 0;
+}
+
 module_usb_serial_driver(serial_drivers, id_table_combined);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
drivers/usb/serial/io_tables.h +8 -0
@@ -110,6 +110,8 @@ static struct usb_serial_driver edgeport
 	.attach			= edge_startup,
 	.disconnect		= edge_disconnect,
 	.release		= edge_release,
+	.port_probe		= edge_port_probe,
+	.port_remove		= edge_port_remove,
 	.ioctl			= edge_ioctl,
 	.set_termios		= edge_set_termios,
 	.tiocmget		= edge_tiocmget,
@@ -139,6 +141,8 @@ static struct usb_serial_driver edgeport
 	.attach			= edge_startup,
 	.disconnect		= edge_disconnect,
 	.release		= edge_release,
+	.port_probe		= edge_port_probe,
+	.port_remove		= edge_port_remove,
 	.ioctl			= edge_ioctl,
 	.set_termios		= edge_set_termios,
 	.tiocmget		= edge_tiocmget,
@@ -168,6 +172,8 @@ static struct usb_serial_driver edgeport
 	.attach			= edge_startup,
 	.disconnect		= edge_disconnect,
 	.release		= edge_release,
+	.port_probe		= edge_port_probe,
+	.port_remove		= edge_port_remove,
 	.ioctl			= edge_ioctl,
 	.set_termios		= edge_set_termios,
 	.tiocmget		= edge_tiocmget,
@@ -197,6 +203,8 @@ static struct usb_serial_driver epic_dev
 	.attach			= edge_startup,
 	.disconnect		= edge_disconnect,
 	.release		= edge_release,
+	.port_probe		= edge_port_probe,
+	.port_remove		= edge_port_remove,
 	.ioctl			= edge_ioctl,
 	.set_termios		= edge_set_termios,
 	.tiocmget		= edge_tiocmget,
author maintainer
#47 lore raw

PATCH 42/85 USB: keyspan_pda: fix port-data memory leak

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <[email protected]>

commit 94ab71ce288921490ca857e25ad174e1921b1e29 upstream.

Fix port-data memory leak by replacing attach and release with port_probe and port_remove.

Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no driver is bound) the port private data is no longer freed at release as it is no longer accessible.

Note that the write waitqueue was initialised but never used.

Compile-only tested.

---
 drivers/usb/serial/keyspan_pda.c |   30 +++++++++++++++++-------------
 1 file changed, 17 insertions(+), 13 deletions(-)
drivers/usb/serial/keyspan_pda.c +17 -13
@@ -735,29 +735,33 @@ MODULE_FIRMWARE("keyspan_pda/keyspan_pda
 MODULE_FIRMWARE("keyspan_pda/xircom_pgs.fw");
 #endif
 
-static int keyspan_pda_startup(struct usb_serial *serial)
+static int keyspan_pda_port_probe(struct usb_serial_port *port)
 {
 
 	struct keyspan_pda_private *priv;
 
-	/* allocate the private data structures for all ports. Well, for all
-	   one ports. */
-
 	priv = kmalloc(sizeof(struct keyspan_pda_private), GFP_KERNEL);
 	if (!priv)
-		return 1; /* error */
-	usb_set_serial_port_data(serial->port[0], priv);
-	init_waitqueue_head(&serial->port[0]->write_wait);
+		return -ENOMEM;
+
 	INIT_WORK(&priv->wakeup_work, keyspan_pda_wakeup_write);
 	INIT_WORK(&priv->unthrottle_work, keyspan_pda_request_unthrottle);
-	priv->serial = serial;
-	priv->port = serial->port[0];
+	priv->serial = port->serial;
+	priv->port = port;
+
+	usb_set_serial_port_data(port, priv);
+
 	return 0;
 }
 
-static void keyspan_pda_release(struct usb_serial *serial)
+static int keyspan_pda_port_remove(struct usb_serial_port *port)
 {
-	kfree(usb_get_serial_port_data(serial->port[0]));
+	struct keyspan_pda_private *priv;
+
+	priv = usb_get_serial_port_data(port);
+	kfree(priv);
+
+	return 0;
 }
 
 #ifdef KEYSPAN
@@ -808,8 +812,8 @@ static struct usb_serial_driver keyspan_
 	.break_ctl =		keyspan_pda_break_ctl,
 	.tiocmget =		keyspan_pda_tiocmget,
 	.tiocmset =		keyspan_pda_tiocmset,
-	.attach =		keyspan_pda_startup,
-	.release =		keyspan_pda_release,
+	.port_probe =		keyspan_pda_port_probe,
+	.port_remove =		keyspan_pda_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
author maintainer
#48 lore raw

PATCH 43/85 USB: option: blacklist net interface on ZTE devices

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Bjørn Mork <[email protected]>

commit 1452df6f1b7e396d89c2a1fdbdc0e0e839f97671 upstream.

Based on information from the ZTE Windows drivers.

---
 drivers/usb/serial/option.c |   68 +++++++++++++++++++++++++++++++-------------
 1 file changed, 48 insertions(+), 20 deletions(-)
drivers/usb/serial/option.c +48 -20
@@ -503,11 +503,19 @@ static const struct option_blacklist_inf
 	.reserved = BIT(5),
 };
 
+static const struct option_blacklist_info net_intf6_blacklist = {
+	.reserved = BIT(6),
+};
+
 static const struct option_blacklist_info zte_mf626_blacklist = {
 	.sendsetup = BIT(0) | BIT(1),
 	.reserved = BIT(4),
 };
 
+static const struct option_blacklist_info zte_1255_blacklist = {
+	.reserved = BIT(3) | BIT(4),
+};
+
 static const struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -853,13 +861,19 @@ static const struct usb_device_id option
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0113, 0xff, 0xff, 0xff),
 		.driver_info = (kernel_ulong_t)&net_intf5_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0117, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff),
+		.driver_info = (kernel_ulong_t)&net_intf5_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff),
+		.driver_info = (kernel_ulong_t)&net_intf5_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0122, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff),
+		.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff),
+		.driver_info = (kernel_ulong_t)&net_intf5_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff),
+		.driver_info = (kernel_ulong_t)&net_intf6_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff),
+		.driver_info = (kernel_ulong_t)&net_intf5_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0128, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0142, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0143, 0xff, 0xff, 0xff) },
@@ -872,7 +886,8 @@ static const struct usb_device_id option
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff),
 	  .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff),
+	  .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0159, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) },
@@ -886,7 +901,8 @@ static const struct usb_device_id option
 	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff),
 	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff),
+	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) },
@@ -1002,18 +1018,24 @@ static const struct usb_device_id option
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1169, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1170, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1244, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1245, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1245, 0xff, 0xff, 0xff),
+	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1246, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1247, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1247, 0xff, 0xff, 0xff),
+	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1248, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1249, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1250, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1251, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1252, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1252, 0xff, 0xff, 0xff),
+	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1253, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1254, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1255, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1256, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1254, 0xff, 0xff, 0xff),
+	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1255, 0xff, 0xff, 0xff),
+	  .driver_info = (kernel_ulong_t)&zte_1255_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1256, 0xff, 0xff, 0xff),
+	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1257, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1258, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1259, 0xff, 0xff, 0xff) },
@@ -1071,15 +1093,21 @@ static const struct usb_device_id option
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0094, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff),
+		.driver_info = (kernel_ulong_t)&net_intf1_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff),
+		.driver_info = (kernel_ulong_t)&net_intf3_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff),
+		.driver_info = (kernel_ulong_t)&net_intf5_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0147, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff),
+		.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0170, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff),
+		.driver_info = (kernel_ulong_t)&net_intf3_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff),
+		.driver_info = (kernel_ulong_t)&net_intf3_blacklist },
 
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) },
author maintainer
#49 lore raw

PATCH 44/85 USB: option: add more ZTE devices

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Bjørn Mork <[email protected]>

commit 4b35f1c52943851b310afb09047bfe991ac8f5ae upstream.

---
 drivers/usb/serial/option.c |   16 ++++++++++++++++
 1 file changed, 16 insertions(+)
drivers/usb/serial/option.c +16 -0
@@ -895,6 +895,12 @@ static const struct usb_device_id option
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff),
 	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0191, 0xff, 0xff, 0xff), /* ZTE EuFi890 */
+	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0199, 0xff, 0xff, 0xff), /* ZTE MF820S */
+	  .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */
+	  .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff),
 	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff),
@@ -903,6 +909,8 @@ static const struct usb_device_id option
 	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff),
 	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1021, 0xff, 0xff, 0xff),
+	  .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) },
@@ -1080,8 +1088,16 @@ static const struct usb_device_id option
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1401, 0xff, 0xff, 0xff),
+		.driver_info = (kernel_ulong_t)&net_intf2_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1402, 0xff, 0xff, 0xff),
 		.driver_info = (kernel_ulong_t)&net_intf2_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1424, 0xff, 0xff, 0xff),
+		.driver_info = (kernel_ulong_t)&net_intf2_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1425, 0xff, 0xff, 0xff),
+		.driver_info = (kernel_ulong_t)&net_intf2_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1426, 0xff, 0xff, 0xff),  /* ZTE MF91 */
+		.driver_info = (kernel_ulong_t)&net_intf2_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff,
 	  0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
author maintainer
#50 lore raw

PATCH 45/85 usb: dwc3: gadget: fix endpoint always busy bug

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Felipe Balbi <[email protected]>

commit 041d81f493d90c940ec41f0ec98bc7c4f2fba431 upstream.

If a USB transfer has already been started, meaning we have already issued StartTransfer command to that particular endpoint, DWC3_EP_BUSY flag has also already been set.

When we try to cancel this transfer which is already in controller's cache, we will not receive XferComplete event and we must clear DWC3_EP_BUSY in order to allow subsequent requests to be properly started.

The best place to clear that flag is right after issuing DWC3_DEPCMD_ENDTRANSFER.

---
 drivers/usb/dwc3/gadget.c |    1 +
 1 file changed, 1 insertion(+)
drivers/usb/dwc3/gadget.c +1 -0
@@ -1899,6 +1899,7 @@ static void dwc3_stop_active_transfer(st
 	ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, &params);
 	WARN_ON_ONCE(ret);
 	dep->resource_index = 0;
+	dep->flags &= ~DWC3_EP_BUSY;
 }
 
 static void dwc3_stop_active_transfers(struct dwc3 *dwc)
author maintainer
#51 lore raw

PATCH 46/85 usb: Dont enable LPM if the exit latency is zero.

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sarah Sharp <[email protected]>

commit ae8963adb4ad8c5f2a89ca1d99fb7bb721e7599f upstream.

Some USB 3.0 devices signal that they don't implement Link PM by having all zeroes in the U1/U2 exit latencies in their SuperSpeed BOS descriptor. Don found that a Western Digital device he has experiences transfer errors when LPM is enabled. The lsusb shows the U1/U2 exit latencies are set to zero:

Binary Object Store Descriptor:
bLength 5
bDescriptorType 15
wTotalLength 22
bNumDeviceCaps 2
SuperSpeed USB Device Capability:
bLength 10
bDescriptorType 16
bDevCapabilityType 3
bmAttributes 0x00
Latency Tolerance Messages (LTM) Supported
wSpeedsSupported 0x000e
Device can operate at Full Speed (12Mbps)
Device can operate at High Speed (480Mbps)
Device can operate at SuperSpeed (5Gbps)
bFunctionalitySupport 1
Lowest fully-functional device speed is Full Speed (12Mbps)
bU1DevExitLat 0 micro seconds
bU2DevExitLat 0 micro seconds

The fix is to not enable LPM for a particular link state if we find its corresponding exit latency is zero.

This patch should be backported to kernels as old as 3.5, that contain the commit 1ea7e0e8e3d0f50901d335ea4178ab2aa8c88201 "USB: Add support to enable/disable USB3 link states."

---
 drivers/usb/core/hub.c |   10 ++++++++++
 1 file changed, 10 insertions(+)
drivers/usb/core/hub.c +10 -0
@@ -3353,6 +3353,16 @@ static void usb_enable_link_state(struct
 		enum usb3_link_state state)
 {
 	int timeout;
+	__u8 u1_mel = udev->bos->ss_cap->bU1devExitLat;
+	__le16 u2_mel = udev->bos->ss_cap->bU2DevExitLat;
+
+	/* If the device says it doesn't have *any* exit latency to come out of
+	 * U1 or U2, it's probably lying.  Assume it doesn't implement that link
+	 * state.
+	 */
+	if ((state == USB3_LPM_U1 && u1_mel == 0) ||
+			(state == USB3_LPM_U2 && u2_mel == 0))
+		return;
 
 	/* We allow the host controller to set the U1/U2 timeout internally
 	 * first, so that it can change its schedule to account for the
author maintainer
#52 lore raw

PATCH 47/85 USB: Enable LPM after a failed probe.

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sarah Sharp <[email protected]>

commit d01f87c0ffa96cb44faa78710711eb6e974b891c upstream.

Before a driver is probed, we want to disable USB 3.0 Link Power Management (LPM), in case the driver needs hub-initiated LPM disabled. After the probe finishes, we want to attempt to re-enable LPM, order to balance the LPM ref count.

When a probe fails (such as when libusual doesn't want to bind to a USB 3.0 mass storage device), make sure to balance the LPM ref counts by re-enabling LPM.

This patch should be backported to kernels as old as 3.5, that contain the commit 8306095fd2c1100e8244c09bf560f97aca5a311d "USB: Disable USB 3.0 LPM in critical sections."

---
 drivers/usb/core/driver.c |    4 ++++
 1 file changed, 4 insertions(+)
drivers/usb/core/driver.c +4 -0
@@ -372,6 +372,10 @@ static int usb_probe_interface(struct de
 	intf->condition = USB_INTERFACE_UNBOUND;
 	usb_cancel_queued_reset(intf);
 
+	/* If the LPM disable succeeded, balance the ref counts. */
+	if (!lpm_disable_error)
+		usb_unlocked_enable_lpm(udev);
+
 	/* Unbound interfaces are always runtime-PM-disabled and -suspended */
 	if (driver->supports_autosuspend)
 		pm_runtime_disable(dev);
author maintainer
#53 lore raw

PATCH 48/85 usb: Send Set SEL before enabling parent U1/U2 timeout.

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sarah Sharp <[email protected]>

commit 65a95b75bc5afa7bbb844e222481044c1c4767eb upstream.

The Set SEL control transfer tells a device the exit latencies associated with a device-initated U1 or U2 exit. Since a parent hub may initiate a transition to U1 soon after a downstream port's U1 timeout is set, we need to make sure the device receives the Set SEL transfer before the parent hub timeout is set.

This patch should be backported to kernels as old as 3.5, that contain the commit 1ea7e0e8e3d0f50901d335ea4178ab2aa8c88201 "USB: Add support to enable/disable USB3 link states."

---
 drivers/usb/core/hub.c |   23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)
drivers/usb/core/hub.c +12 -11
@@ -3258,16 +3258,6 @@ static int usb_set_device_initiated_lpm(
 
 	if (enable) {
 		/*
-		 * First, let the device know about the exit latencies
-		 * associated with the link state we're about to enable.
-		 */
-		ret = usb_req_set_sel(udev, state);
-		if (ret < 0) {
-			dev_warn(&udev->dev, "Set SEL for device-initiated "
-					"%s failed.\n", usb3_lpm_names[state]);
-			return -EBUSY;
-		}
-		/*
 		 * Now send the control transfer to enable device-initiated LPM
 		 * for either U1 or U2.
 		 */
@@ -3352,7 +3342,7 @@ static int usb_set_lpm_timeout(struct us
 static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev,
 		enum usb3_link_state state)
 {
-	int timeout;
+	int timeout, ret;
 	__u8 u1_mel = udev->bos->ss_cap->bU1devExitLat;
 	__le16 u2_mel = udev->bos->ss_cap->bU2DevExitLat;
 
@@ -3364,6 +3354,17 @@ static void usb_enable_link_state(struct
 			(state == USB3_LPM_U2 && u2_mel == 0))
 		return;
 
+	/*
+	 * First, let the device know about the exit latencies
+	 * associated with the link state we're about to enable.
+	 */
+	ret = usb_req_set_sel(udev, state);
+	if (ret < 0) {
+		dev_warn(&udev->dev, "Set SEL for device-initiated %s failed.\n",
+				usb3_lpm_names[state]);
+		return;
+	}
+
 	/* We allow the host controller to set the U1/U2 timeout internally
 	 * first, so that it can change its schedule to account for the
 	 * additional latency to send data to a device in a lower power
author maintainer
#54 lore raw

PATCH 49/85 USB: fix port probing and removal in garmin_gps

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Alan Stern <[email protected]>

commit db5c8b524444d4fc6b1f32d368a50a3729e50002 upstream.

This patch (as1615) fixes a bug in the Garmin USB serial driver. It uses attach, disconnect, and release routines to carry out actions that should be handled by port_probe and port_remove routines, because they access port-specific data.

The bug causes an oops when the device in unplugged, because the private data for each port structure now gets erased when the port is unbound from the driver, resulting in a null-pointer dereference.

---
 drivers/usb/serial/garmin_gps.c |   24 +++++++-----------------
 1 file changed, 7 insertions(+), 17 deletions(-)
drivers/usb/serial/garmin_gps.c +7 -17
@@ -1414,11 +1414,10 @@ static void timeout_handler(unsigned lon
 
 
 
-static int garmin_attach(struct usb_serial *serial)
+static int garmin_port_probe(struct usb_serial_port *port)
 {
-	int status = 0;
-	struct usb_serial_port *port = serial->port[0];
-	struct garmin_data *garmin_data_p = NULL;
+	int status;
+	struct garmin_data *garmin_data_p;
 
 	garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL);
 	if (garmin_data_p == NULL) {
@@ -1443,22 +1442,14 @@ static int garmin_attach(struct usb_seri
 }
 
 
-static void garmin_disconnect(struct usb_serial *serial)
+static int garmin_port_remove(struct usb_serial_port *port)
 {
-	struct usb_serial_port *port = serial->port[0];
 	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
 
 	usb_kill_urb(port->interrupt_in_urb);
 	del_timer_sync(&garmin_data_p->timer);
-}
-
-
-static void garmin_release(struct usb_serial *serial)
-{
-	struct usb_serial_port *port = serial->port[0];
-	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
-
 	kfree(garmin_data_p);
+	return 0;
 }
 
 
@@ -1475,9 +1466,8 @@ static struct usb_serial_driver garmin_d
 	.close               = garmin_close,
 	.throttle            = garmin_throttle,
 	.unthrottle          = garmin_unthrottle,
-	.attach              = garmin_attach,
-	.disconnect          = garmin_disconnect,
-	.release             = garmin_release,
+	.port_probe		= garmin_port_probe,
+	.port_remove		= garmin_port_remove,
 	.write               = garmin_write,
 	.write_room          = garmin_write_room,
 	.write_bulk_callback = garmin_write_bulk_callback,
author maintainer
#55 lore raw

PATCH 50/85 cgroup: notify_on_release may not be triggered in some cases

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Daisuke Nishimura <[email protected]>

commit 1f5320d5972aa50d3e8d2b227b636b370e608359 upstream.

notify_on_release must be triggered when the last process in a cgroup is move to another. But if the first(and only) process in a cgroup is moved to another, notify_on_release is not triggered.

	# mkdir /cgroup/cpu/SRC
	# mkdir /cgroup/cpu/DST
	#
	# echo 1 >/cgroup/cpu/SRC/notify_on_release
	# echo 1 >/cgroup/cpu/DST/notify_on_release
	#
	# sleep 300 &
	[1] 8629
	#
	# echo 8629 >/cgroup/cpu/SRC/tasks
	# echo 8629 >/cgroup/cpu/DST/tasks
	-> notify_on_release for /SRC must be triggered at this point,
	   but it isn't.

This is because put_css_set() is called before setting CGRP_RELEASABLE in cgroup_task_migrate(), and is a regression introduce by the commit:74a1166d(cgroups: make procs file writable), which was merged into v3.0.

---
 kernel/cgroup.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
kernel/cgroup.c +1 -2
@@ -1923,9 +1923,8 @@ static void cgroup_task_migrate(struct c
 	 * trading it for newcg is protected by cgroup_mutex, we're safe to drop
 	 * it here; it will be freed under RCU.
 	 */
-	put_css_set(oldcg);
-
 	set_bit(CGRP_RELEASABLE, &oldcgrp->flags);
+	put_css_set(oldcg);
 }
 
 /**
author maintainer
#56 lore raw

PATCH 51/85 Revert "cgroup: Remove task_lock() from cgroup_post_fork()"

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Tejun Heo <[email protected]>

commit d87838321124061f6c935069d97f37010fa417e6 upstream.

This reverts commit 7e3aa30ac8c904a706518b725c451bb486daaae9.

The commit incorrectly assumed that fork path always performed threadgroup_change_begin/end() and depended on that for synchronization against task exit and cgroup migration paths instead of explicitly grabbing task_lock().

threadgroup_change is not locked when forking a new process (as opposed to a new thread in the same process) and even if it were it wouldn't be effective as different processes use different threadgroup locks.

Revert the incorrect optimization.

LKML-Reference: <20121008020000.GB2575@localhost>

---
 kernel/cgroup.c |   15 +++------------
 1 file changed, 3 insertions(+), 12 deletions(-)
kernel/cgroup.c +3 -12
@@ -4771,19 +4771,10 @@ void cgroup_post_fork(struct task_struct
 	 */
 	if (use_task_css_set_links) {
 		write_lock(&css_set_lock);
-		if (list_empty(&child->cg_list)) {
-			/*
-			 * It's safe to use child->cgroups without task_lock()
-			 * here because we are protected through
-			 * threadgroup_change_begin() against concurrent
-			 * css_set change in cgroup_task_migrate(). Also
-			 * the task can't exit at that point until
-			 * wake_up_new_task() is called, so we are protected
-			 * against cgroup_exit() setting child->cgroup to
-			 * init_css_set.
-			 */
+		task_lock(child);
+		if (list_empty(&child->cg_list))
 			list_add(&child->cg_list, &child->cgroups->tasks);
-		}
+		task_unlock(child);
 		write_unlock(&css_set_lock);
 	}
 }
author maintainer
#57 lore raw

PATCH 52/85 Revert "cgroup: Drop task_lock(parent) on cgroup_fork()"

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Tejun Heo <[email protected]>

commit 9bb71308b8133d643648776243e4d5599b1c193d upstream.

This reverts commit 7e381b0eb1e1a9805c37335562e8dc02e7d7848c.

The commit incorrectly assumed that fork path always performed threadgroup_change_begin/end() and depended on that for synchronization against task exit and cgroup migration paths instead of explicitly grabbing task_lock().

threadgroup_change is not locked when forking a new process (as opposed to a new thread in the same process) and even if it were it wouldn't be effective as different processes use different threadgroup locks.

Revert the incorrect optimization.

LKML-Reference: <20121008020000.GB2575@localhost>

---
 kernel/cgroup.c |   23 ++++++-----------------
 1 file changed, 6 insertions(+), 17 deletions(-)
kernel/cgroup.c +6 -17
@@ -4694,31 +4694,20 @@ static const struct file_operations proc
  *
  * A pointer to the shared css_set was automatically copied in
  * fork.c by dup_task_struct().  However, we ignore that copy, since
- * it was not made under the protection of RCU, cgroup_mutex or
- * threadgroup_change_begin(), so it might no longer be a valid
- * cgroup pointer.  cgroup_attach_task() might have already changed
- * current->cgroups, allowing the previously referenced cgroup
- * group to be removed and freed.
- *
- * Outside the pointer validity we also need to process the css_set
- * inheritance between threadgoup_change_begin() and
- * threadgoup_change_end(), this way there is no leak in any process
- * wide migration performed by cgroup_attach_proc() that could otherwise
- * miss a thread because it is too early or too late in the fork stage.
+ * it was not made under the protection of RCU or cgroup_mutex, so
+ * might no longer be a valid cgroup pointer.  cgroup_attach_task() might
+ * have already changed current->cgroups, allowing the previously
+ * referenced cgroup group to be removed and freed.
  *
  * At the point that cgroup_fork() is called, 'current' is the parent
  * task, and the passed argument 'child' points to the child task.
  */
 void cgroup_fork(struct task_struct *child)
 {
-	/*
-	 * We don't need to task_lock() current because current->cgroups
-	 * can't be changed concurrently here. The parent obviously hasn't
-	 * exited and called cgroup_exit(), and we are synchronized against
-	 * cgroup migration through threadgroup_change_begin().
-	 */
+	task_lock(current);
 	child->cgroups = current->cgroups;
 	get_css_set(child->cgroups);
+	task_unlock(current);
 	INIT_LIST_HEAD(&child->cg_list);
 }
 
author maintainer
#58 lore raw

PATCH 53/85 pinctrl: tegra: correct bank for pingroup and drv pingroup

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Pritesh Raithatha <[email protected]>

commit a03690e44468dcd3088f6600ab036d17bd2130ff upstream.

---
 drivers/pinctrl/pinctrl-tegra30.c |   24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)
drivers/pinctrl/pinctrl-tegra30.c +12 -12
@@ -3345,10 +3345,10 @@ static const struct tegra_function tegra
 	FUNCTION(vi_alt3),
 };
 
-#define MUXCTL_REG_A	0x3000
-#define PINGROUP_REG_A	0x868
+#define DRV_PINGROUP_REG_A	0x868	/* bank 0 */
+#define PINGROUP_REG_A		0x3000	/* bank 1 */
 
-#define PINGROUP_REG_Y(r) ((r) - MUXCTL_REG_A)
+#define PINGROUP_REG_Y(r) ((r) - PINGROUP_REG_A)
 #define PINGROUP_REG_N(r) -1
 
 #define PINGROUP(pg_name, f0, f1, f2, f3, f_safe, r, od, ior)	\
@@ -3364,25 +3364,25 @@ static const struct tegra_function tegra
 		},						\
 		.func_safe = TEGRA_MUX_ ## f_safe,		\
 		.mux_reg = PINGROUP_REG_Y(r),			\
-		.mux_bank = 0,					\
+		.mux_bank = 1,					\
 		.mux_bit = 0,					\
 		.pupd_reg = PINGROUP_REG_Y(r),			\
-		.pupd_bank = 0,					\
+		.pupd_bank = 1,					\
 		.pupd_bit = 2,					\
 		.tri_reg = PINGROUP_REG_Y(r),			\
-		.tri_bank = 0,					\
+		.tri_bank = 1,					\
 		.tri_bit = 4,					\
 		.einput_reg = PINGROUP_REG_Y(r),		\
-		.einput_bank = 0,				\
+		.einput_bank = 1,				\
 		.einput_bit = 5,				\
 		.odrain_reg = PINGROUP_REG_##od(r),		\
-		.odrain_bank = 0,				\
+		.odrain_bank = 1,				\
 		.odrain_bit = 6,				\
 		.lock_reg = PINGROUP_REG_Y(r),			\
-		.lock_bank = 0,					\
+		.lock_bank = 1,					\
 		.lock_bit = 7,					\
 		.ioreset_reg = PINGROUP_REG_##ior(r),		\
-		.ioreset_bank = 0,				\
+		.ioreset_bank = 1,				\
 		.ioreset_bit = 8,				\
 		.drv_reg = -1,					\
 	}
@@ -3401,8 +3401,8 @@ static const struct tegra_function tegra
 		.odrain_reg = -1,				\
 		.lock_reg = -1,					\
 		.ioreset_reg = -1,				\
-		.drv_reg = ((r) - PINGROUP_REG_A),		\
-		.drv_bank = 1,					\
+		.drv_reg = ((r) - DRV_PINGROUP_REG_A),		\
+		.drv_bank = 0,					\
 		.hsm_bit = hsm_b,				\
 		.schmitt_bit = schmitt_b,			\
 		.lpmd_bit = lpmd_b,				\
author maintainer
#59 lore raw

PATCH 54/85 dt: Document: correct tegra20/30 pinctrl slew-rate name

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Pritesh Raithatha <[email protected]>

commit d6ec6b60a56a1e7d99da1fc69c031fa5ab54ba94 upstream.

change nvidia,slew_rate* to nvidia,slew-rate*

---
 Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt |    2 +-
 Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt +1 -1
@@ -93,7 +93,7 @@ Valid values for pin and group names are
 
     With some exceptions, these support nvidia,high-speed-mode,
     nvidia,schmitt, nvidia,low-power-mode, nvidia,pull-down-strength,
-    nvidia,pull-up-strength, nvidia,slew_rate-rising, nvidia,slew_rate-falling.
+    nvidia,pull-up-strength, nvidia,slew-rate-rising, nvidia,slew-rate-falling.
 
     drive_ao1, drive_ao2, drive_at1, drive_at2, drive_cdev1, drive_cdev2,
     drive_csus, drive_dap1, drive_dap2, drive_dap3, drive_dap4, drive_dbg,
Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt +1 -1
@@ -83,7 +83,7 @@ Valid values for pin and group names are
   drive groups:
 
     These all support nvidia,pull-down-strength, nvidia,pull-up-strength,
-    nvidia,slew_rate-rising, nvidia,slew_rate-falling. Most but not all
+    nvidia,slew-rate-rising, nvidia,slew-rate-falling. Most but not all
     support nvidia,high-speed-mode, nvidia,schmitt, nvidia,low-power-mode.
 
     ao1, ao2, at1, at2, at3, at4, at5, cdev1, cdev2, cec, crt, csus, dap1,
author maintainer
#60 lore raw

PATCH 55/85 pinctrl: tegra: set low power mode bank width to 2

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Pritesh Raithatha <[email protected]>

commit 154f3ebf53edcfbe28728452b4ab37a118581125 upstream.

---
 drivers/pinctrl/pinctrl-tegra.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pinctrl/pinctrl-tegra.c +1 -1
@@ -466,7 +466,7 @@ static int tegra_pinconf_reg(struct tegr
 		*bank = g->drv_bank;
 		*reg = g->drv_reg;
 		*bit = g->lpmd_bit;
-		*width = 1;
+		*width = 2;
 		break;
 	case TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH:
 		*bank = g->drv_bank;
author maintainer
#61 lore raw

PATCH 56/85 pinctrl: remove mutex lock in groups show

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Haojian Zhuang <[email protected]>

commit 7ae9d71e8df27a3ab60a05ae3add08728debc09c upstream.

Mutex is locked duplicatly by pinconf_groups_show() and pin_config_group_get(). It results dead lock. So avoid to lock mutex in pinconf_groups_show().

---
 drivers/pinctrl/pinconf.c |    4 ----
 1 file changed, 4 deletions(-)
drivers/pinctrl/pinconf.c +0 -4
@@ -537,8 +537,6 @@ static int pinconf_groups_show(struct se
 	seq_puts(s, "Pin config settings per pin group\n");
 	seq_puts(s, "Format: group (name): configs\n");
 
-	mutex_lock(&pinctrl_mutex);
-
 	while (selector < ngroups) {
 		const char *gname = pctlops->get_group_name(pctldev, selector);
 
@@ -549,8 +547,6 @@ static int pinconf_groups_show(struct se
 		selector++;
 	}
 
-	mutex_unlock(&pinctrl_mutex);
-
 	return 0;
 }
 
author maintainer
#62 lore raw

PATCH 57/85 pinctrl: fix missing unlock on error in pinctrl_groups_show()

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Wei Yongjun <[email protected]>

commit b4dd784ba8af03bf1f9ee5118c792d7abd4919bd upstream.

Add the missing unlock on the error handle path in function pinctrl_groups_show().

---
 drivers/pinctrl/core.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/pinctrl/core.c +3 -1
@@ -1059,8 +1059,10 @@ static int pinctrl_groups_show(struct se
 			seq_printf(s, "group: %s\n", gname);
 			for (i = 0; i < num_pins; i++) {
 				pname = pin_get_name(pctldev, pins[i]);
-				if (WARN_ON(!pname))
+				if (WARN_ON(!pname)) {
+					mutex_unlock(&pinctrl_mutex);
 					return -EINVAL;
+				}
 				seq_printf(s, "pin %d (%s)\n", pins[i], pname);
 			}
 			seq_puts(s, "\n");
author maintainer
#63 lore raw

PATCH 58/85 iommu/tegra: smmu: Fix deadly typo

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Hiro Sugawara <[email protected]>

commit d0078e72314df2e5ede03f2102cddde06767c374 upstream.

Fix a deadly typo in macro definition.

---
 drivers/iommu/tegra-smmu.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/iommu/tegra-smmu.c +1 -1
@@ -146,7 +146,7 @@
 
 #define SMMU_ADDR_TO_PFN(addr)	((addr) >> 12)
 #define SMMU_ADDR_TO_PDN(addr)	((addr) >> 22)
-#define SMMU_PDN_TO_ADDR(addr)	((pdn) << 22)
+#define SMMU_PDN_TO_ADDR(pdn)	((pdn) << 22)
 
 #define _READABLE	(1 << SMMU_PTB_DATA_ASID_READABLE_SHIFT)
 #define _WRITABLE	(1 << SMMU_PTB_DATA_ASID_WRITABLE_SHIFT)
author maintainer
#64 lore raw

PATCH 59/85 amd64_edac:__amd64_set_scrub_rate(): avoid overindexing scrubrates[]

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Andrew Morton <[email protected]>

commit 168bfeef7bba3f9784f7540b053e4ac72b769ce9 upstream.

If none of the elements in scrubrates[] matches, this loop will cause __amd64_set_scrub_rate() to incorrectly use the n+1th element.

As the function is designed to use the final scrubrates[] element in the case of no match, we can fix this bug by simply terminating the array search at the n-1th element.

Boris: this code is fragile anyway, see here why:
http://marc.info/?l=linux-kernel&m=135102834131236&w=2

It will be rewritten more robustly soonish.

---
 drivers/edac/amd64_edac.c |   11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)
drivers/edac/amd64_edac.c +4 -7
@@ -170,8 +170,11 @@ static int __amd64_set_scrub_rate(struct
 	 * memory controller and apply to register. Search for the first
 	 * bandwidth entry that is greater or equal than the setting requested
 	 * and program that. If at last entry, turn off DRAM scrubbing.
+	 *
+	 * If no suitable bandwidth is found, turn off DRAM scrubbing entirely
+	 * by falling back to the last element in scrubrates[].
 	 */
-	for (i = 0; i < ARRAY_SIZE(scrubrates); i++) {
+	for (i = 0; i < ARRAY_SIZE(scrubrates) - 1; i++) {
 		/*
 		 * skip scrub rates which aren't recommended
 		 * (see F10 BKDG, F3x58)
@@ -181,12 +184,6 @@ static int __amd64_set_scrub_rate(struct
 
 		if (scrubrates[i].bandwidth <= new_bw)
 			break;
-
-		/*
-		 * if no suitable bandwidth found, turn off DRAM scrubbing
-		 * entirely by falling back to the last element in the
-		 * scrubrates array.
-		 */
 	}
 
 	scrubval = scrubrates[i].scrubval;
author maintainer
#65 lore raw

PATCH 60/85 xtensa: add missing system calls to the syscall table

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Chris Zankel <[email protected]>

commit 7216cabfff5149670445cd65d415ed5db21314b4 upstream.

Add the following system calls to the syscall table:

fallocate
sendmmsg
umount2
syncfs
epoll_create1
inotify_init1
signalfd4
dup3
pipe2
timerfd_create
timerfd_settime
timerfd_gettime
eventfd2
preadv
pwritev
fanotify_init
fanotify_mark
process_vm_readv
process_vm_writev
name_to_handle_at
open_by_handle_at
sync_file_range
perf_event_open
rt_tgsigqueueinfo
clock_adjtime
prlimit64
kcmp

Note that we have to use the 'sys_sync_file_range2' version, so that the 64-bit arguments are aligned correctly to the argument registers.

---
 arch/xtensa/include/asm/unistd.h |   89 +++++++++++++++++++++++++++++++--------
 1 file changed, 71 insertions(+), 18 deletions(-)
arch/xtensa/include/asm/unistd.h +71 -18
@@ -148,8 +148,8 @@ __SYSCALL( 59, sys_getdents, 3)
 __SYSCALL( 60, sys_getdents64, 3)
 #define __NR_fcntl64 				 61
 __SYSCALL( 61, sys_fcntl64, 3)
-#define __NR_available62			 62
-__SYSCALL( 62, sys_ni_syscall, 0)
+#define __NR_fallocate				 62
+__SYSCALL( 62, sys_fallocate, 6)
 #define __NR_fadvise64_64 			 63
 __SYSCALL( 63, xtensa_fadvise64_64, 6)
 #define __NR_utime				 64	/* glibc 2.3.3 ?? */
@@ -264,8 +264,8 @@ __SYSCALL(112, sys_socketpair, 4)
 __SYSCALL(113, sys_sendfile, 4)
 #define __NR_sendfile64 			114
 __SYSCALL(114, sys_sendfile64, 4)
-#define __NR_available115			115
-__SYSCALL(115, sys_ni_syscall, 0)
+#define __NR_sendmmsg				115
+__SYSCALL(115, sys_sendmmsg, 4)
 
 /* Process Operations */
 
@@ -380,11 +380,11 @@ __SYSCALL(168, sys_msgrcv, 4)
 __SYSCALL(169, sys_msgctl, 4)
 #define __NR_available170			170
 __SYSCALL(170, sys_ni_syscall, 0)
-#define __NR_available171			171
-__SYSCALL(171, sys_ni_syscall, 0)
 
 /* File System */
 
+#define __NR_umount2				171
+__SYSCALL(171, sys_umount, 2)
 #define __NR_mount 				172
 __SYSCALL(172, sys_mount, 5)
 #define __NR_swapon 				173
@@ -399,8 +399,8 @@ __SYSCALL(176, sys_umount, 2)
 __SYSCALL(177, sys_swapoff, 1)
 #define __NR_sync 				178
 __SYSCALL(178, sys_sync, 0)
-#define __NR_available179			179
-__SYSCALL(179, sys_ni_syscall, 0)
+#define __NR_syncfs				179
+__SYSCALL(179, sys_syncfs, 1)
 #define __NR_setfsuid 				180
 __SYSCALL(180, sys_setfsuid, 1)
 #define __NR_setfsgid 				181
@@ -455,7 +455,7 @@ __SYSCALL(203, sys_reboot, 3)
 #define __NR_quotactl 				204
 __SYSCALL(204, sys_quotactl, 4)
 #define __NR_nfsservctl 			205
-__SYSCALL(205, sys_ni_syscall, 0)
+__SYSCALL(205, sys_ni_syscall, 0)			/* old nfsservctl */
 #define __NR__sysctl 				206
 __SYSCALL(206, sys_sysctl, 1)
 #define __NR_bdflush 				207
@@ -562,7 +562,7 @@ __SYSCALL(252, sys_timer_getoverrun, 1)
 
 /* System */
 
-#define __NR_reserved244 			253
+#define __NR_reserved253			253
 __SYSCALL(253, sys_ni_syscall, 0)
 #define __NR_lookup_dcookie 			254
 __SYSCALL(254, sys_lookup_dcookie, 4)
@@ -609,8 +609,8 @@ __SYSCALL(272, sys_pselect6, 0)
 __SYSCALL(273, sys_ppoll, 0)
 #define __NR_epoll_pwait			274
 __SYSCALL(274, sys_epoll_pwait, 0)
-#define __NR_available275			275
-__SYSCALL(275, sys_ni_syscall, 0)
+#define __NR_epoll_create1		275
+__SYSCALL(275, sys_epoll_create1, 1)
 
 #define __NR_inotify_init			276
 __SYSCALL(276, sys_inotify_init, 0)
@@ -618,8 +618,8 @@ __SYSCALL(276, sys_inotify_init, 0)
 __SYSCALL(277, sys_inotify_add_watch, 3)
 #define __NR_inotify_rm_watch			278
 __SYSCALL(278, sys_inotify_rm_watch, 2)
-#define __NR_available279			279
-__SYSCALL(279, sys_ni_syscall, 0)
+#define __NR_inotify_init1			279
+__SYSCALL(279, sys_inotify_init1, 1)
 
 #define __NR_getcpu				280
 __SYSCALL(280, sys_getcpu, 0)
@@ -635,10 +635,10 @@ __SYSCALL(283, sys_ioprio_get, 3)
 __SYSCALL(284, sys_set_robust_list, 3)
 #define __NR_get_robust_list			285
 __SYSCALL(285, sys_get_robust_list, 3)
-#define __NR_reserved286			286	/* sync_file_rangeX */
-__SYSCALL(286, sys_ni_syscall, 3)
+#define __NR_available286			286
+__SYSCALL(286, sys_ni_syscall, 0)
 #define __NR_available287			287
-__SYSCALL(287, sys_faccessat, 0)
+__SYSCALL(287, sys_ni_syscall, 0)
 
 /* Relative File Operations */
 
@@ -683,10 +683,63 @@ __SYSCALL(305, sys_ni_syscall, 0)
 __SYSCALL(306, sys_eventfd, 1)
 #define __NR_recvmmsg				307
 __SYSCALL(307, sys_recvmmsg, 5)
+
 #define __NR_setns				308
 __SYSCALL(308, sys_setns, 2)
+#define __NR_signalfd4				309
+__SYSCALL(309, sys_signalfd4, 4)
+#define __NR_dup3				310
+__SYSCALL(310, sys_dup3, 3)
+#define __NR_pipe2				311
+__SYSCALL(311, sys_pipe2, 2)
+
+#define __NR_timerfd_create			312
+__SYSCALL(312, sys_timerfd_create, 2)
+#define __NR_timerfd_settime			313
+__SYSCALL(313, sys_timerfd_settime, 4)
+#define __NR_timerfd_gettime			314
+__SYSCALL(314, sys_timerfd_gettime, 2)
+#define __NR_available315			315
+__SYSCALL(315, sys_ni_syscall, 0)
+
+#define __NR_eventfd2				316
+__SYSCALL(316, sys_eventfd2, 2)
+#define __NR_preadv				317
+__SYSCALL(317, sys_preadv, 5)
+#define __NR_pwritev				318
+__SYSCALL(318, sys_pwritev, 5)
+#define __NR_available319			319
+__SYSCALL(319, sys_ni_syscall, 0)
+
+#define __NR_fanotify_init			320
+__SYSCALL(320, sys_fanotify_init, 2)
+#define __NR_fanotify_mark			321
+__SYSCALL(321, sys_fanotify_mark, 6)
+#define __NR_process_vm_readv			322
+__SYSCALL(322, sys_process_vm_readv, 6)
+#define __NR_process_vm_writev			323
+__SYSCALL(323, sys_process_vm_writev, 6)
+
+#define __NR_name_to_handle_at			324
+__SYSCALL(324, sys_name_to_handle_at, 5)
+#define __NR_open_by_handle_at			325
+__SYSCALL(325, sys_open_by_handle_at, 3)
+#define __NR_sync_file_range			326
+__SYSCALL(326, sys_sync_file_range2, 6)
+#define __NR_perf_event_open			327
+__SYSCALL(327, sys_perf_event_open, 5)
+
+#define __NR_rt_tgsigqueueinfo			328
+__SYSCALL(328, sys_rt_tgsigqueueinfo, 4)
+#define __NR_clock_adjtime			329
+__SYSCALL(329, sys_clock_adjtime, 2)
+#define __NR_prlimit64				330
+__SYSCALL(330, sys_prlimit64, 4)
+#define __NR_kcmp				331
+__SYSCALL(331, sys_kcmp, 5)
+
 
-#define __NR_syscall_count			309
+#define __NR_syscall_count			332
 
 /*
  * sysxtensa syscall handler
#66 lore raw

Re: [ 60/85] xtensa: add missing system calls to the syscall table

Quoted 9 lines · Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Chris Zankel <[email protected]>

commit 7216cabfff5149670445cd65d415ed5db21314b4 upstream.

Add the following system calls to the syscall table:

[...]

arch/xtensa/include/asm/unistd.h __SYSCALL(283, sys_ioprio_get, 3) · line 641

Quoted 3 lines

#define __NR_available287 287

arch/xtensa/include/asm/unistd.h +1 -1
-__SYSCALL(287, sys_faccessat, 0)
+__SYSCALL(287, sys_ni_syscall, 0)

[...]

Why was this one un-plumbed rather than properly numbered (#define __NR_faccessat)?

Ben.

Signature · 2 lines
Ben Hutchings
Never attribute to conspiracy what can adequately be explained by stupidity.
maintainer
#67 lore raw

Re: [ 60/85] xtensa: add missing system calls to the syscall table

Hi Ben,

Quoted 9 lines · Ben Hutchings

On Thu, 2012-10-25 at 17:06 -0700, Greg Kroah-Hartman wrote:
[...]

arch/xtensa/include/asm/unistd.h __SYSCALL(283, sys_ioprio_get, 3) · line 641

Quoted 3 lines

#define __NR_available287 287

arch/xtensa/include/asm/unistd.h +1 -1
-__SYSCALL(287, sys_faccessat, 0)
+__SYSCALL(287, sys_ni_syscall, 0)

[...]

Why was this one un-plumbed rather than properly numbered (#define __NR_faccessat)?

I can only speculate, that this was probably a copy/paste error that has been there for a long time. __NR_faccessat is (and was) defined as number 301. Given that 287 was never defined, it's save to fix the table entry and set it to sys_ni_syscall.

unistd.h:
[...]
#define __NR_faccessat 301
__SYSCALL(301, sys_faccessat, 4)
[...]

Thanks,
-Chris

author maintainer
#68 lore raw

PATCH 61/85 media: au0828: fix case where STREAMOFF being called on stopped stream causes BUG()

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Devin Heitmueller <[email protected]>

commit a595c1ce4c9d572cf53513570b9f1a263d7867f2 upstream.

We weren't checking whether the resource was in use before calling res_free(), so applications which called STREAMOFF on a v4l2 device that wasn't already streaming would cause a BUG() to be hit (MythTV).

---
 drivers/media/video/au0828/au0828-video.c |   12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)
drivers/media/video/au0828/au0828-video.c +8 -4
@@ -1692,14 +1692,18 @@ static int vidioc_streamoff(struct file
 			(AUVI_INPUT(i).audio_setup)(dev, 0);
 		}
 
-		videobuf_streamoff(&fh->vb_vidq);
-		res_free(fh, AU0828_RESOURCE_VIDEO);
+		if (res_check(fh, AU0828_RESOURCE_VIDEO)) {
+			videobuf_streamoff(&fh->vb_vidq);
+			res_free(fh, AU0828_RESOURCE_VIDEO);
+		}
 	} else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
 		dev->vbi_timeout_running = 0;
 		del_timer_sync(&dev->vbi_timeout);
 
-		videobuf_streamoff(&fh->vb_vbiq);
-		res_free(fh, AU0828_RESOURCE_VBI);
+		if (res_check(fh, AU0828_RESOURCE_VBI)) {
+			videobuf_streamoff(&fh->vb_vbiq);
+			res_free(fh, AU0828_RESOURCE_VBI);
+		}
 	}
 
 	return 0;
author maintainer
#69 lore raw

PATCH 62/85 drm/i915: Use cpu relocations if the object is in the GTT but not mappable

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Chris Wilson <[email protected]>

commit 504c7267a1e84b157cbd7e9c1b805e1bc0c2c846 upstream.

This prevents the case of unbinding the object in order to process the relocations through the GTT and then rebinding it only to then proceed to use cpu relocations as the object is now in the CPU write domain. By choosing to use cpu relocations up front, we can therefore avoid the rebind penalty.

---
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |    1 +
 1 file changed, 1 insertion(+)
drivers/gpu/drm/i915/i915_gem_execbuffer.c +1 -0
@@ -269,6 +269,7 @@ eb_destroy(struct eb_objects *eb)
 static inline int use_cpu_reloc(struct drm_i915_gem_object *obj)
 {
 	return (obj->base.write_domain == I915_GEM_DOMAIN_CPU ||
+		!obj->map_and_fenceable ||
 		obj->cache_level != I915_CACHE_NONE);
 }
 
author maintainer
#70 lore raw

PATCH 63/85 netlink: add reference of module in netlink_dump_start

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Gao feng <[email protected]>

[ Upstream commit 6dc878a8ca39e93f70c42f3dd7260bde10c1e0f1 ]

I get a panic when I use ss -a and rmmod inet_diag at the same time.

It's because netlink_dump uses inet_diag_dump which belongs to module inet_diag.

I search the codes and find many modules have the same problem. We need to add a reference to the module which the cb->dump belongs to.

Thanks for all help from Stephen,Jan,Eric,Steffen and Pablo.

Change From v3:
change netlink_dump_start to inline,suggestion from Pablo and Eric.

Change From v2:
delete netlink_dump_done,and call module_put in netlink_dump and netlink_sock_destruct.

---
 include/linux/netlink.h  |   21 +++++++++++++++++----
 net/netlink/af_netlink.c |   29 +++++++++++++++++++++--------
 2 files changed, 38 insertions(+), 12 deletions(-)
include/linux/netlink.h +17 -4
@@ -153,6 +153,7 @@ struct nlattr {
 
 #include <linux/capability.h>
 #include <linux/skbuff.h>
+#include <linux/export.h>
 
 struct net;
 
@@ -232,6 +233,8 @@ struct netlink_callback {
 					struct netlink_callback *cb);
 	int			(*done)(struct netlink_callback *cb);
 	void			*data;
+	/* the module that dump function belong to */
+	struct module		*module;
 	u16			family;
 	u16			min_dump_alloc;
 	unsigned int		prev_seq, seq;
@@ -249,14 +252,24 @@ __nlmsg_put(struct sk_buff *skb, u32 pid
 
 struct netlink_dump_control {
 	int (*dump)(struct sk_buff *skb, struct netlink_callback *);
-	int (*done)(struct netlink_callback*);
+	int (*done)(struct netlink_callback *);
 	void *data;
+	struct module *module;
 	u16 min_dump_alloc;
 };
 
-extern int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
-			      const struct nlmsghdr *nlh,
-			      struct netlink_dump_control *control);
+extern int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
+				const struct nlmsghdr *nlh,
+				struct netlink_dump_control *control);
+static inline int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
+				     const struct nlmsghdr *nlh,
+				     struct netlink_dump_control *control)
+{
+	if (!control->module)
+		control->module = THIS_MODULE;
+
+	return __netlink_dump_start(ssk, skb, nlh, control);
+}
 
 
 #define NL_NONROOT_RECV 0x1
net/netlink/af_netlink.c +21 -8
@@ -169,6 +169,8 @@ static void netlink_sock_destruct(struct
 	if (nlk->cb) {
 		if (nlk->cb->done)
 			nlk->cb->done(nlk->cb);
+
+		module_put(nlk->cb->module);
 		netlink_destroy_callback(nlk->cb);
 	}
 
@@ -1760,6 +1762,7 @@ static int netlink_dump(struct sock *sk)
 	nlk->cb = NULL;
 	mutex_unlock(nlk->cb_mutex);
 
+	module_put(cb->module);
 	netlink_consume_callback(cb);
 	return 0;
 
@@ -1769,9 +1772,9 @@ errout_skb:
 	return err;
 }
 
-int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
-		       const struct nlmsghdr *nlh,
-		       struct netlink_dump_control *control)
+int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
+			 const struct nlmsghdr *nlh,
+			 struct netlink_dump_control *control)
 {
 	struct netlink_callback *cb;
 	struct sock *sk;
@@ -1786,6 +1789,7 @@ int netlink_dump_start(struct sock *ssk,
 	cb->done = control->done;
 	cb->nlh = nlh;
 	cb->data = control->data;
+	cb->module = control->module;
 	cb->min_dump_alloc = control->min_dump_alloc;
 	atomic_inc(&skb->users);
 	cb->skb = skb;
@@ -1796,19 +1800,28 @@ int netlink_dump_start(struct sock *ssk,
 		return -ECONNREFUSED;
 	}
 	nlk = nlk_sk(sk);
-	/* A dump is in progress... */
+
 	mutex_lock(nlk->cb_mutex);
+	/* A dump is in progress... */
 	if (nlk->cb) {
 		mutex_unlock(nlk->cb_mutex);
 		netlink_destroy_callback(cb);
-		sock_put(sk);
-		return -EBUSY;
+		ret = -EBUSY;
+		goto out;
 	}
+	/* add reference of module which cb->dump belongs to */
+	if (!try_module_get(cb->module)) {
+		mutex_unlock(nlk->cb_mutex);
+		netlink_destroy_callback(cb);
+		ret = -EPROTONOSUPPORT;
+		goto out;
+	}
+
 	nlk->cb = cb;
 	mutex_unlock(nlk->cb_mutex);
 
 	ret = netlink_dump(sk);
-
+out:
 	sock_put(sk);
 
 	if (ret)
@@ -1819,7 +1832,7 @@ int netlink_dump_start(struct sock *ssk,
 	 */
 	return -EINTR;
 }
-EXPORT_SYMBOL(netlink_dump_start);
+EXPORT_SYMBOL(__netlink_dump_start);
 
 void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err)
 {
author maintainer
#71 lore raw

PATCH 64/85 infiniband: pass rdma_cm module to netlink_dump_start

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Gao feng <[email protected]>

[ Upstream commit 809d5fc9bf6589276a12bd4fd611e4c7ff9940c3 ]

set netlink_dump_control.module to avoid panic.

---
 drivers/infiniband/core/cma.c     |    3 ++-
 drivers/infiniband/core/netlink.c |    1 +
 include/rdma/rdma_netlink.h       |    1 +
 3 files changed, 4 insertions(+), 1 deletion(-)
drivers/infiniband/core/cma.c +2 -1
@@ -3495,7 +3495,8 @@ out:
 }
 
 static const struct ibnl_client_cbs cma_cb_table[] = {
-	[RDMA_NL_RDMA_CM_ID_STATS] = { .dump = cma_get_id_stats },
+	[RDMA_NL_RDMA_CM_ID_STATS] = { .dump = cma_get_id_stats,
+				       .module = THIS_MODULE },
 };
 
 static int __init cma_init(void)
drivers/infiniband/core/netlink.c +1 -0
@@ -154,6 +154,7 @@ static int ibnl_rcv_msg(struct sk_buff *
 			{
 				struct netlink_dump_control c = {
 					.dump = client->cb_table[op].dump,
+					.module = client->cb_table[op].module,
 				};
 				return netlink_dump_start(nls, skb, nlh, &c);
 			}
include/rdma/rdma_netlink.h +1 -0
@@ -39,6 +39,7 @@ struct rdma_cm_id_stats {
 
 struct ibnl_client_cbs {
 	int (*dump)(struct sk_buff *skb, struct netlink_callback *nlcb);
+	struct module *module;
 };
 
 int ibnl_init(void);
author maintainer
#72 lore raw

PATCH 65/85 net: remove skb recycling

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Eric Dumazet <[email protected]>

[ Upstream commits acb600def2110b1310466c0e485c0d26299898ae
and 66eef59f22275002f621ff9d951886b513d011b3. ]

Over time, skb recycling infrastructure got litle interest and many bugs. Generic rx path skb allocation is now using page fragments for efficient GRO / TCP coalescing, and recyling a tx skb for rx path is not worth the pain.

Last identified bug is that fat skbs can be recycled and it can endup using high order pages after few iterations.

With help from Maxime Bizon, who pointed out that commit 87151b8689d (net: allow pskb_expand_head() to get maximum tailroom) introduced this regression for recycled skbs.

Instead of fixing this bug, lets remove skb recycling.

Drivers wanting really hot skbs should use build_skb() anyway, to allocate/populate sk_buff right before netif_receive_skb()

---
 drivers/net/ethernet/calxeda/xgmac.c              |   19 --------
 drivers/net/ethernet/freescale/gianfar.c          |   27 +-----------
 drivers/net/ethernet/freescale/gianfar.h          |    2 
 drivers/net/ethernet/freescale/ucc_geth.c         |   29 ++-----------
 drivers/net/ethernet/freescale/ucc_geth.h         |    2 
 drivers/net/ethernet/marvell/mv643xx_eth.c        |   18 --------
 drivers/net/ethernet/stmicro/stmmac/stmmac.h      |    1 
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c |   20 ---------
 include/linux/skbuff.h                            |   24 -----------
 net/core/skbuff.c                                 |   47 ----------------------
 10 files changed, 16 insertions(+), 173 deletions(-)
drivers/net/ethernet/calxeda/xgmac.c +2 -17
@@ -375,7 +375,6 @@ struct xgmac_priv {
 	unsigned int tx_tail;
 
 	void __iomem *base;
-	struct sk_buff_head rx_recycle;
 	unsigned int dma_buf_sz;
 	dma_addr_t dma_rx_phy;
 	dma_addr_t dma_tx_phy;
@@ -672,9 +671,7 @@ static void xgmac_rx_refill(struct xgmac
 		p = priv->dma_rx + entry;
 
 		if (priv->rx_skbuff[entry] == NULL) {
-			skb = __skb_dequeue(&priv->rx_recycle);
-			if (skb == NULL)
-				skb = netdev_alloc_skb(priv->dev, priv->dma_buf_sz);
+			skb = netdev_alloc_skb(priv->dev, priv->dma_buf_sz);
 			if (unlikely(skb == NULL))
 				break;
 
@@ -887,17 +884,7 @@ static void xgmac_tx_complete(struct xgm
 				       desc_get_buf_len(p), DMA_TO_DEVICE);
 		}
 
-		/*
-		 * If there's room in the queue (limit it to size)
-		 * we add this skb back into the pool,
-		 * if it's the right size.
-		 */
-		if ((skb_queue_len(&priv->rx_recycle) <
-			DMA_RX_RING_SZ) &&
-			skb_recycle_check(skb, priv->dma_buf_sz))
-			__skb_queue_head(&priv->rx_recycle, skb);
-		else
-			dev_kfree_skb(skb);
+		dev_kfree_skb(skb);
 	}
 
 	if (dma_ring_space(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ) >
@@ -1016,7 +1003,6 @@ static int xgmac_open(struct net_device
 			dev->dev_addr);
 	}
 
-	skb_queue_head_init(&priv->rx_recycle);
 	memset(&priv->xstats, 0, sizeof(struct xgmac_extra_stats));
 
 	/* Initialize the XGMAC and descriptors */
@@ -1053,7 +1039,6 @@ static int xgmac_stop(struct net_device
 		napi_disable(&priv->napi);
 
 	writel(0, priv->base + XGMAC_DMA_INTR_ENA);
-	skb_queue_purge(&priv->rx_recycle);
 
 	/* Disable the MAC core */
 	xgmac_mac_disable(priv->base);
drivers/net/ethernet/freescale/gianfar.c +4 -23
@@ -1757,7 +1757,6 @@ static void free_skb_resources(struct gf
 			  sizeof(struct rxbd8) * priv->total_rx_ring_size,
 			  priv->tx_queue[0]->tx_bd_base,
 			  priv->tx_queue[0]->tx_bd_dma_base);
-	skb_queue_purge(&priv->rx_recycle);
 }
 
 void gfar_start(struct net_device *dev)
@@ -1935,8 +1934,6 @@ static int gfar_enet_open(struct net_dev
 
 	enable_napi(priv);
 
-	skb_queue_head_init(&priv->rx_recycle);
-
 	/* Initialize a bunch of registers */
 	init_registers(dev);
 
@@ -2525,16 +2522,7 @@ static int gfar_clean_tx_ring(struct gfa
 
 		bytes_sent += skb->len;
 
-		/* If there's room in the queue (limit it to rx_buffer_size)
-		 * we add this skb back into the pool, if it's the right size
-		 */
-		if (skb_queue_len(&priv->rx_recycle) < rx_queue->rx_ring_size &&
-		    skb_recycle_check(skb, priv->rx_buffer_size +
-				      RXBUF_ALIGNMENT)) {
-			gfar_align_skb(skb);
-			skb_queue_head(&priv->rx_recycle, skb);
-		} else
-			dev_kfree_skb_any(skb);
+		dev_kfree_skb_any(skb);
 
 		tx_queue->tx_skbuff[skb_dirtytx] = NULL;
 
@@ -2600,7 +2588,7 @@ static void gfar_new_rxbdp(struct gfar_p
 static struct sk_buff *gfar_alloc_skb(struct net_device *dev)
 {
 	struct gfar_private *priv = netdev_priv(dev);
-	struct sk_buff *skb = NULL;
+	struct sk_buff *skb;
 
 	skb = netdev_alloc_skb(dev, priv->rx_buffer_size + RXBUF_ALIGNMENT);
 	if (!skb)
@@ -2613,14 +2601,7 @@ static struct sk_buff *gfar_alloc_skb(st
 
 struct sk_buff *gfar_new_skb(struct net_device *dev)
 {
-	struct gfar_private *priv = netdev_priv(dev);
-	struct sk_buff *skb = NULL;
-
-	skb = skb_dequeue(&priv->rx_recycle);
-	if (!skb)
-		skb = gfar_alloc_skb(dev);
-
-	return skb;
+	return gfar_alloc_skb(dev);
 }
 
 static inline void count_errors(unsigned short status, struct net_device *dev)
@@ -2779,7 +2760,7 @@ int gfar_clean_rx_ring(struct gfar_priv_
 			if (unlikely(!newskb))
 				newskb = skb;
 			else if (skb)
-				skb_queue_head(&priv->rx_recycle, skb);
+				dev_kfree_skb(skb);
 		} else {
 			/* Increment the number of packets */
 			rx_queue->stats.rx_packets++;
drivers/net/ethernet/freescale/gianfar.h +0 -2
@@ -1072,8 +1072,6 @@ struct gfar_private {
 
 	u32 cur_filer_idx;
 
-	struct sk_buff_head rx_recycle;
-
 	/* RX queue filer rule set*/
 	struct ethtool_rx_list rx_list;
 	struct mutex rx_queue_access;
drivers/net/ethernet/freescale/ucc_geth.c +6 -23
@@ -210,14 +210,12 @@ static struct list_head *dequeue(struct
 static struct sk_buff *get_new_skb(struct ucc_geth_private *ugeth,
 		u8 __iomem *bd)
 {
-	struct sk_buff *skb = NULL;
+	struct sk_buff *skb;
 
-	skb = __skb_dequeue(&ugeth->rx_recycle);
+	skb = netdev_alloc_skb(ugeth->ndev,
+			       ugeth->ug_info->uf_info.max_rx_buf_length +
+			       UCC_GETH_RX_DATA_BUF_ALIGNMENT);
 	if (!skb)
-		skb = netdev_alloc_skb(ugeth->ndev,
-				      ugeth->ug_info->uf_info.max_rx_buf_length +
-				      UCC_GETH_RX_DATA_BUF_ALIGNMENT);
-	if (skb == NULL)
 		return NULL;
 
 	/* We need the data buffer to be aligned properly.  We will reserve
@@ -2021,8 +2019,6 @@ static void ucc_geth_memclean(struct ucc
 		iounmap(ugeth->ug_regs);
 		ugeth->ug_regs = NULL;
 	}
-
-	skb_queue_purge(&ugeth->rx_recycle);
 }
 
 static void ucc_geth_set_multi(struct net_device *dev)
@@ -2231,8 +2227,6 @@ static int ucc_struct_init(struct ucc_ge
 		return -ENOMEM;
 	}
 
-	skb_queue_head_init(&ugeth->rx_recycle);
-
 	return 0;
 }
 
@@ -3275,12 +3269,7 @@ static int ucc_geth_rx(struct ucc_geth_p
 			if (netif_msg_rx_err(ugeth))
 				ugeth_err("%s, %d: ERROR!!! skb - 0x%08x",
 					   __func__, __LINE__, (u32) skb);
-			if (skb) {
-				skb->data = skb->head + NET_SKB_PAD;
-				skb->len = 0;
-				skb_reset_tail_pointer(skb);
-				__skb_queue_head(&ugeth->rx_recycle, skb);
-			}
+			dev_kfree_skb(skb);
 
 			ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]] = NULL;
 			dev->stats.rx_dropped++;
@@ -3350,13 +3339,7 @@ static int ucc_geth_tx(struct net_device
 
 		dev->stats.tx_packets++;
 
-		if (skb_queue_len(&ugeth->rx_recycle) < RX_BD_RING_LEN &&
-			     skb_recycle_check(skb,
-				    ugeth->ug_info->uf_info.max_rx_buf_length +
-				    UCC_GETH_RX_DATA_BUF_ALIGNMENT))
-			__skb_queue_head(&ugeth->rx_recycle, skb);
-		else
-			dev_kfree_skb(skb);
+		dev_kfree_skb(skb);
 
 		ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]] = NULL;
 		ugeth->skb_dirtytx[txQ] =
drivers/net/ethernet/freescale/ucc_geth.h +0 -2
@@ -1214,8 +1214,6 @@ struct ucc_geth_private {
 	/* index of the first skb which hasn't been transmitted yet. */
 	u16 skb_dirtytx[NUM_TX_QUEUES];
 
-	struct sk_buff_head rx_recycle;
-
 	struct ugeth_mii_info *mii_info;
 	struct phy_device *phydev;
 	phy_interface_t phy_interface;
drivers/net/ethernet/marvell/mv643xx_eth.c +2 -16
@@ -412,7 +412,6 @@ struct mv643xx_eth_private {
 	u8 work_rx_refill;
 
 	int skb_size;
-	struct sk_buff_head rx_recycle;
 
 	/*
 	 * RX state.
@@ -673,9 +672,7 @@ static int rxq_refill(struct rx_queue *r
 		struct rx_desc *rx_desc;
 		int size;
 
-		skb = __skb_dequeue(&mp->rx_recycle);
-		if (skb == NULL)
-			skb = netdev_alloc_skb(mp->dev, mp->skb_size);
+		skb = netdev_alloc_skb(mp->dev, mp->skb_size);
 
 		if (skb == NULL) {
 			mp->oom = 1;
@@ -989,14 +986,7 @@ static int txq_reclaim(struct tx_queue *
 				       desc->byte_cnt, DMA_TO_DEVICE);
 		}
 
-		if (skb != NULL) {
-			if (skb_queue_len(&mp->rx_recycle) <
-					mp->rx_ring_size &&
-			    skb_recycle_check(skb, mp->skb_size))
-				__skb_queue_head(&mp->rx_recycle, skb);
-			else
-				dev_kfree_skb(skb);
-		}
+		dev_kfree_skb(skb);
 	}
 
 	__netif_tx_unlock(nq);
@@ -2349,8 +2339,6 @@ static int mv643xx_eth_open(struct net_d
 
 	napi_enable(&mp->napi);
 
-	skb_queue_head_init(&mp->rx_recycle);
-
 	mp->int_mask = INT_EXT;
 
 	for (i = 0; i < mp->rxq_count; i++) {
@@ -2445,8 +2433,6 @@ static int mv643xx_eth_stop(struct net_d
 	mib_counters_update(mp);
 	del_timer_sync(&mp->mib_counters_timer);
 
-	skb_queue_purge(&mp->rx_recycle);
-
 	for (i = 0; i < mp->rxq_count; i++)
 		rxq_deinit(mp->rxq + i);
 	for (i = 0; i < mp->txq_count; i++)
drivers/net/ethernet/stmicro/stmmac/stmmac.h +0 -1
@@ -50,7 +50,6 @@ struct stmmac_priv {
 	unsigned int dirty_rx;
 	struct sk_buff **rx_skbuff;
 	dma_addr_t *rx_skbuff_dma;
-	struct sk_buff_head rx_recycle;
 
 	struct net_device *dev;
 	dma_addr_t dma_rx_phy;
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +2 -18
@@ -747,18 +747,7 @@ static void stmmac_tx(struct stmmac_priv
 		priv->hw->ring->clean_desc3(p);
 
 		if (likely(skb != NULL)) {
-			/*
-			 * If there's room in the queue (limit it to size)
-			 * we add this skb back into the pool,
-			 * if it's the right size.
-			 */
-			if ((skb_queue_len(&priv->rx_recycle) <
-				priv->dma_rx_size) &&
-				skb_recycle_check(skb, priv->dma_buf_sz))
-				__skb_queue_head(&priv->rx_recycle, skb);
-			else
-				dev_kfree_skb(skb);
-
+			dev_kfree_skb(skb);
 			priv->tx_skbuff[entry] = NULL;
 		}
 
@@ -1169,7 +1158,6 @@ static int stmmac_open(struct net_device
 	priv->eee_enabled = stmmac_eee_init(priv);
 
 	napi_enable(&priv->napi);
-	skb_queue_head_init(&priv->rx_recycle);
 	netif_start_queue(dev);
 
 	return 0;
@@ -1222,7 +1210,6 @@ static int stmmac_release(struct net_dev
 		kfree(priv->tm);
 #endif
 	napi_disable(&priv->napi);
-	skb_queue_purge(&priv->rx_recycle);
 
 	/* Free the IRQ lines */
 	free_irq(dev->irq, dev);
@@ -1388,10 +1375,7 @@ static inline void stmmac_rx_refill(stru
 		if (likely(priv->rx_skbuff[entry] == NULL)) {
 			struct sk_buff *skb;
 
-			skb = __skb_dequeue(&priv->rx_recycle);
-			if (skb == NULL)
-				skb = netdev_alloc_skb_ip_align(priv->dev,
-								bfsize);
+			skb = netdev_alloc_skb_ip_align(priv->dev, bfsize);
 
 			if (unlikely(skb == NULL))
 				break;
include/linux/skbuff.h +0 -24
@@ -589,9 +589,6 @@ static inline struct sk_buff *alloc_skb_
 	return __alloc_skb(size, priority, SKB_ALLOC_FCLONE, NUMA_NO_NODE);
 }
 
-extern void skb_recycle(struct sk_buff *skb);
-extern bool skb_recycle_check(struct sk_buff *skb, int skb_size);
-
 extern struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src);
 extern int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask);
 extern struct sk_buff *skb_clone(struct sk_buff *skb,
@@ -2642,27 +2639,6 @@ static inline void skb_checksum_none_ass
 
 bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off);
 
-static inline bool skb_is_recycleable(const struct sk_buff *skb, int skb_size)
-{
-	if (irqs_disabled())
-		return false;
-
-	if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY)
-		return false;
-
-	if (skb_is_nonlinear(skb) || skb->fclone != SKB_FCLONE_UNAVAILABLE)
-		return false;
-
-	skb_size = SKB_DATA_ALIGN(skb_size + NET_SKB_PAD);
-	if (skb_end_offset(skb) < skb_size)
-		return false;
-
-	if (skb_shared(skb) || skb_cloned(skb))
-		return false;
-
-	return true;
-}
-
 /**
  * skb_head_is_locked - Determine if the skb->head is locked down
  * @skb: skb to check
net/core/skbuff.c +0 -47

53 lines not on this page · raw message

author maintainer
#73 lore raw

PATCH 66/85 net: Fix skb_under_panic oops in neigh_resolve_output

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: "[email protected]" <[email protected]>

[ Upstream commit e1f165032c8bade3a6bdf546f8faf61fda4dd01c ]

The retry loop in neigh_resolve_output() and neigh_connected_output() call dev_hard_header() with out reseting the skb to network_header. This causes the retry to fail with skb_under_panic. The fix is to reset the network_header within the retry loop.

---
 net/core/neighbour.c |    6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
net/core/neighbour.c +2 -4
@@ -1301,8 +1301,6 @@ int neigh_resolve_output(struct neighbou
 	if (!dst)
 		goto discard;
 
-	__skb_pull(skb, skb_network_offset(skb));
-
 	if (!neigh_event_send(neigh, skb)) {
 		int err;
 		struct net_device *dev = neigh->dev;
@@ -1312,6 +1310,7 @@ int neigh_resolve_output(struct neighbou
 			neigh_hh_init(neigh, dst);
 
 		do {
+			__skb_pull(skb, skb_network_offset(skb));
 			seq = read_seqbegin(&neigh->ha_lock);
 			err = dev_hard_header(skb, dev, ntohs(skb->protocol),
 					      neigh->ha, NULL, skb->len);
@@ -1342,9 +1341,8 @@ int neigh_connected_output(struct neighb
 	unsigned int seq;
 	int err;
 
-	__skb_pull(skb, skb_network_offset(skb));
-
 	do {
+		__skb_pull(skb, skb_network_offset(skb));
 		seq = read_seqbegin(&neigh->ha_lock);
 		err = dev_hard_header(skb, dev, ntohs(skb->protocol),
 				      neigh->ha, NULL, skb->len);
author maintainer
#74 lore raw

PATCH 67/85 ipv6: GRO should be ECN friendly

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Eric Dumazet <[email protected]>

[ Upstream commit 51ec04038c113a811b177baa85d293feff9ce995 ]

IPv4 side of the problem was addressed in commit a9e050f4e7f9d (net: tcp: GRO should be ECN friendly)

This patch does the same, but for IPv6 : A Traffic Class mismatch doesnt mean flows are different, but instead should force a flush of previous packets.

This patch removes artificial packet reordering problem.

---
 net/ipv6/af_inet6.c |   11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)
net/ipv6/af_inet6.c +7 -4
@@ -880,22 +880,25 @@ static struct sk_buff **ipv6_gro_receive
 	nlen = skb_network_header_len(skb);
 
 	for (p = *head; p; p = p->next) {
-		struct ipv6hdr *iph2;
+		const struct ipv6hdr *iph2;
+		__be32 first_word; /* <Version:4><Traffic_Class:8><Flow_Label:20> */
 
 		if (!NAPI_GRO_CB(p)->same_flow)
 			continue;
 
 		iph2 = ipv6_hdr(p);
+		first_word = *(__be32 *)iph ^ *(__be32 *)iph2 ;
 
-		/* All fields must match except length. */
+		/* All fields must match except length and Traffic Class. */
 		if (nlen != skb_network_header_len(p) ||
-		    memcmp(iph, iph2, offsetof(struct ipv6hdr, payload_len)) ||
+		    (first_word & htonl(0xF00FFFFF)) ||
 		    memcmp(&iph->nexthdr, &iph2->nexthdr,
 			   nlen - offsetof(struct ipv6hdr, nexthdr))) {
 			NAPI_GRO_CB(p)->same_flow = 0;
 			continue;
 		}
-
+		/* flush if Traffic Class fields are different */
+		NAPI_GRO_CB(p)->flush |= !!(first_word & htonl(0x0FF00000));
 		NAPI_GRO_CB(p)->flush |= flush;
 	}
 
author maintainer
#75 lore raw

PATCH 68/85 ipv4: Always invalidate or update the route on pmtu events

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Steffen Klassert <[email protected]>

[ Upstream commit d851c12b60471188e15e5c8405b289073e8dd025 ]

Some protocols, like IPsec still cache routes. So we need to invalidate the old route on pmtu events to avoid the reuse of stale routes. We also need to update the mtu and expire time of the route if we already use a nh exception route, otherwise we ignore newly learned pmtu values after the first expiration.

With this patch we always invalidate or update the route on pmtu events.

---
 net/ipv4/route.c |   22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)
net/ipv4/route.c +11 -11
@@ -904,22 +904,29 @@ out:	kfree_skb(skb);
 	return 0;
 }
 
-static u32 __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
+static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
 {
+	struct dst_entry *dst = &rt->dst;
 	struct fib_result res;
 
 	if (mtu < ip_rt_min_pmtu)
 		mtu = ip_rt_min_pmtu;
 
+	if (!rt->rt_pmtu) {
+		dst->obsolete = DST_OBSOLETE_KILL;
+	} else {
+		rt->rt_pmtu = mtu;
+		dst->expires = max(1UL, jiffies + ip_rt_mtu_expires);
+	}
+
 	rcu_read_lock();
-	if (fib_lookup(dev_net(rt->dst.dev), fl4, &res) == 0) {
+	if (fib_lookup(dev_net(dst->dev), fl4, &res) == 0) {
 		struct fib_nh *nh = &FIB_RES_NH(res);
 
 		update_or_create_fnhe(nh, fl4->daddr, 0, mtu,
 				      jiffies + ip_rt_mtu_expires);
 	}
 	rcu_read_unlock();
-	return mtu;
 }
 
 static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
@@ -929,14 +936,7 @@ static void ip_rt_update_pmtu(struct dst
 	struct flowi4 fl4;
 
 	ip_rt_build_flow_key(&fl4, sk, skb);
-	mtu = __ip_rt_update_pmtu(rt, &fl4, mtu);
-
-	if (!rt->rt_pmtu) {
-		dst->obsolete = DST_OBSOLETE_KILL;
-	} else {
-		rt->rt_pmtu = mtu;
-		rt->dst.expires = max(1UL, jiffies + ip_rt_mtu_expires);
-	}
+	__ip_rt_update_pmtu(rt, &fl4, mtu);
 }
 
 void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu,
author maintainer
#76 lore raw

PATCH 69/85 ipv4: Dont create nh exeption when the device mtu is smaller than the reported pmtu

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Steffen Klassert <[email protected]>

[ Upstream commit 7f92d334ba19a0d8e96f8f8f092219553367d921 ]

When a local tool like tracepath tries to send packets bigger than the device mtu, we create a nh exeption and set the pmtu to device mtu. The device mtu does not expire, so check if the device mtu is smaller than the reported pmtu and don't crerate a nh exeption in that case.

---
 net/ipv4/route.c |    3 +++
 1 file changed, 3 insertions(+)
net/ipv4/route.c +3 -0
@@ -909,6 +909,9 @@ static void __ip_rt_update_pmtu(struct r
 	struct dst_entry *dst = &rt->dst;
 	struct fib_result res;
 
+	if (dst->dev->mtu < mtu)
+		return;
+
 	if (mtu < ip_rt_min_pmtu)
 		mtu = ip_rt_min_pmtu;
 
author maintainer
#77 lore raw

PATCH 70/85 ipv4: Dont report stale pmtu values to userspace

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Steffen Klassert <[email protected]>

[ Upstream commit ee9a8f7ab2edf801b8b514c310455c94acc232f6 ]

We report cached pmtu values even if they are already expired. Change this to not report these values after they are expired and fix a race in the expire time calculation, as suggested by Eric Dumazet.

---
 net/ipv4/route.c |   19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)
net/ipv4/route.c +11 -8
@@ -2187,8 +2187,18 @@ static int rt_fill_info(struct net *net,
 	    nla_put_be32(skb, RTA_GATEWAY, rt->rt_gateway))
 		goto nla_put_failure;
 
+	expires = rt->dst.expires;
+	if (expires) {
+		unsigned long now = jiffies;
+
+		if (time_before(now, expires))
+			expires -= now;
+		else
+			expires = 0;
+	}
+
 	memcpy(metrics, dst_metrics_ptr(&rt->dst), sizeof(metrics));
-	if (rt->rt_pmtu)
+	if (rt->rt_pmtu && expires)
 		metrics[RTAX_MTU - 1] = rt->rt_pmtu;
 	if (rtnetlink_put_metrics(skb, metrics) < 0)
 		goto nla_put_failure;
@@ -2198,13 +2208,6 @@ static int rt_fill_info(struct net *net,
 		goto nla_put_failure;
 
 	error = rt->dst.error;
-	expires = rt->dst.expires;
-	if (expires) {
-		if (time_before(jiffies, expires))
-			expires -= jiffies;
-		else
-			expires = 0;
-	}
 
 	if (rt_is_input_route(rt)) {
 		if (nla_put_u32(skb, RTA_IIF, rt->rt_iif))
author maintainer
#78 lore raw

PATCH 71/85 skge: Add DMA mask quirk for Marvell 88E8001 on ASUS P5NSLI motherboard

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Graham Gower <[email protected]>

[ Upstream commit a2af139ff1cd85df586690ff626619ab1ee88b0a ]

Marvell 88E8001 on an ASUS P5NSLI motherboard is unable to send/receive packets on a system with >4gb ram unless a 32bit DMA mask is used.

This issue has been around for years and a fix was sent 3.5 years ago, but there was some debate as to whether it should instead be fixed as a PCI quirk.
http://www.spinics.net/lists/netdev/msg88670.html

However, 18 months later a similar workaround was introduced for another chipset exhibiting the same problem.
http://www.spinics.net/lists/netdev/msg142287.html

---
 drivers/net/ethernet/marvell/skge.c |    7 +++++++
 1 file changed, 7 insertions(+)
drivers/net/ethernet/marvell/skge.c +7 -0
@@ -4153,6 +4153,13 @@ static struct dmi_system_id skge_32bit_d
 			DMI_MATCH(DMI_BOARD_NAME, "nForce"),
 		},
 	},
+	{
+		.ident = "ASUS P5NSLI",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "P5NSLI")
+		},
+	},
 	{}
 };
 
author maintainer
#79 lore raw

PATCH 72/85 vlan: dont deliver frames for unknown vlans to protocols

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Florian Zumbiehl <[email protected]>

[ Upstream commit 48cc32d38a52d0b68f91a171a8d00531edc6a46e ]

6a32e4f9dd9219261f8856f817e6655114cfec2f made the vlan code skip marking vlan-tagged frames for not locally configured vlans as PACKET_OTHERHOST if there was an rx_handler, as the rx_handler could cause the frame to be received on a different (virtual) vlan-capable interface where that vlan might be configured.

As rx_handlers do not necessarily return RX_HANDLER_ANOTHER, this could cause frames for unknown vlans to be delivered to the protocol stack as if they had been received untagged.

For example, if an ipv6 router advertisement that's tagged for a locally not configured vlan is received on an interface with macvlan interfaces attached, macvlan's rx_handler returns RX_HANDLER_PASS after delivering the frame to the macvlan interfaces, which caused it to be passed to the protocol stack, leading to ipv6 addresses for the announced prefix being configured even though those are completely unusable on the underlying interface.

The fix moves marking as PACKET_OTHERHOST after the rx_handler so the rx_handler, if there is one, sees the frame unchanged, but afterwards, before the frame is delivered to the protocol stack, it gets marked whether there is an rx_handler or not.

---
 include/linux/if_vlan.h |    8 ++++----
 net/8021q/vlan_core.c   |   10 ++--------
 net/core/dev.c          |    7 +++++--
 3 files changed, 11 insertions(+), 14 deletions(-)
include/linux/if_vlan.h +4 -4
@@ -82,6 +82,8 @@ static inline int is_vlan_dev(struct net
 }
 
 #define vlan_tx_tag_present(__skb)	((__skb)->vlan_tci & VLAN_TAG_PRESENT)
+#define vlan_tx_nonzero_tag_present(__skb) \
+	(vlan_tx_tag_present(__skb) && ((__skb)->vlan_tci & VLAN_VID_MASK))
 #define vlan_tx_tag_get(__skb)		((__skb)->vlan_tci & ~VLAN_TAG_PRESENT)
 
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
@@ -91,7 +93,7 @@ extern struct net_device *__vlan_find_de
 extern struct net_device *vlan_dev_real_dev(const struct net_device *dev);
 extern u16 vlan_dev_vlan_id(const struct net_device *dev);
 
-extern bool vlan_do_receive(struct sk_buff **skb, bool last_handler);
+extern bool vlan_do_receive(struct sk_buff **skb);
 extern struct sk_buff *vlan_untag(struct sk_buff *skb);
 
 extern int vlan_vid_add(struct net_device *dev, unsigned short vid);
@@ -120,10 +122,8 @@ static inline u16 vlan_dev_vlan_id(const
 	return 0;
 }
 
-static inline bool vlan_do_receive(struct sk_buff **skb, bool last_handler)
+static inline bool vlan_do_receive(struct sk_buff **skb)
 {
-	if (((*skb)->vlan_tci & VLAN_VID_MASK) && last_handler)
-		(*skb)->pkt_type = PACKET_OTHERHOST;
 	return false;
 }
 
net/8021q/vlan_core.c +2 -8
@@ -5,7 +5,7 @@
 #include <linux/export.h>
 #include "vlan.h"
 
-bool vlan_do_receive(struct sk_buff **skbp, bool last_handler)
+bool vlan_do_receive(struct sk_buff **skbp)
 {
 	struct sk_buff *skb = *skbp;
 	u16 vlan_id = skb->vlan_tci & VLAN_VID_MASK;
@@ -13,14 +13,8 @@ bool vlan_do_receive(struct sk_buff **sk
 	struct vlan_pcpu_stats *rx_stats;
 
 	vlan_dev = vlan_find_dev(skb->dev, vlan_id);
-	if (!vlan_dev) {
-		/* Only the last call to vlan_do_receive() should change
-		 * pkt_type to PACKET_OTHERHOST
-		 */
-		if (vlan_id && last_handler)
-			skb->pkt_type = PACKET_OTHERHOST;
+	if (!vlan_dev)
 		return false;
-	}
 
 	skb = *skbp = skb_share_check(skb, GFP_ATOMIC);
 	if (unlikely(!skb))
net/core/dev.c +5 -2
@@ -3275,18 +3275,18 @@ ncls:
 				&& !skb_pfmemalloc_protocol(skb))
 		goto drop;
 
-	rx_handler = rcu_dereference(skb->dev->rx_handler);
 	if (vlan_tx_tag_present(skb)) {
 		if (pt_prev) {
 			ret = deliver_skb(skb, pt_prev, orig_dev);
 			pt_prev = NULL;
 		}
-		if (vlan_do_receive(&skb, !rx_handler))
+		if (vlan_do_receive(&skb))
 			goto another_round;
 		else if (unlikely(!skb))
 			goto unlock;
 	}
 
+	rx_handler = rcu_dereference(skb->dev->rx_handler);
 	if (rx_handler) {
 		if (pt_prev) {
 			ret = deliver_skb(skb, pt_prev, orig_dev);
@@ -3306,6 +3306,9 @@ ncls:
 		}
 	}
 
+	if (vlan_tx_nonzero_tag_present(skb))
+		skb->pkt_type = PACKET_OTHERHOST;
+
 	/* deliver only exact match when indicated */
 	null_or_dev = deliver_exact ? skb->dev : NULL;
 
author maintainer
#80 lore raw

PATCH 73/85 ipv4: fix sending of redirects

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Julian Anastasov <[email protected]>

[ Upstream commit e81da0e113a1b7fc7449ae6213f65f89ccac6d06 ]

After "Cache input routes in fib_info nexthops" (commit d2d68ba9fe) and "Elide fib_validate_source() completely when possible" (commit 7a9bc9b81a) we can not send ICMP redirects. It seems we should not cache the RTCF_DOREDIRECT flag in nh_rth_input because the same fib_info can be used for traffic that is not redirected, eg. from other input devices or from sources that are not in same subnet.

As result, we have to disable the caching of RTCF_DOREDIRECT
flag and to force source validation for the case when forwarding traffic to the input device. If traffic comes from directly connected source we allow redirection as it was done before both changes.

Avoid setting RTCF_DOREDIRECT if IN_DEV_TX_REDIRECTS
is disabled, this can avoid source address validation and to help caching the routes.

	After the change "Adjust semantics of rt->rt_gateway"

(commit f8126f1d51) we should make sure our ICMP_REDIR_HOST messages contain daddr instead of 0.0.0.0 when target is directly connected.

---
 net/ipv4/fib_frontend.c |    3 ++-
 net/ipv4/route.c        |   30 ++++++++++++++++--------------
 2 files changed, 18 insertions(+), 15 deletions(-)
net/ipv4/fib_frontend.c +2 -1
@@ -322,7 +322,8 @@ int fib_validate_source(struct sk_buff *
 {
 	int r = secpath_exists(skb) ? 0 : IN_DEV_RPFILTER(idev);
 
-	if (!r && !fib_num_tclassid_users(dev_net(dev))) {
+	if (!r && !fib_num_tclassid_users(dev_net(dev)) &&
+	    (dev->ifindex != oif || !IN_DEV_TX_REDIRECTS(idev))) {
 		*itag = 0;
 		return 0;
 	}
net/ipv4/route.c +16 -14
@@ -802,7 +802,8 @@ void ip_rt_send_redirect(struct sk_buff
 	net = dev_net(rt->dst.dev);
 	peer = inet_getpeer_v4(net->ipv4.peers, ip_hdr(skb)->saddr, 1);
 	if (!peer) {
-		icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway);
+		icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST,
+			  rt_nexthop(rt, ip_hdr(skb)->daddr));
 		return;
 	}
 
@@ -827,7 +828,9 @@ void ip_rt_send_redirect(struct sk_buff
 	    time_after(jiffies,
 		       (peer->rate_last +
 			(ip_rt_redirect_load << peer->rate_tokens)))) {
-		icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway);
+		__be32 gw = rt_nexthop(rt, ip_hdr(skb)->daddr);
+
+		icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, gw);
 		peer->rate_last = jiffies;
 		++peer->rate_tokens;
 #ifdef CONFIG_IP_ROUTE_VERBOSE
@@ -835,7 +838,7 @@ void ip_rt_send_redirect(struct sk_buff
 		    peer->rate_tokens == ip_rt_redirect_number)
 			net_warn_ratelimited("host %pI4/if%d ignores redirects for %pI4 to %pI4\n",
 					     &ip_hdr(skb)->saddr, inet_iif(skb),
-					     &ip_hdr(skb)->daddr, &rt->rt_gateway);
+					     &ip_hdr(skb)->daddr, &gw);
 #endif
 	}
 out_put_peer:
@@ -1445,10 +1448,13 @@ static int __mkroute_input(struct sk_buf
 		goto cleanup;
 	}
 
-	if (out_dev == in_dev && err &&
+	do_cache = res->fi && !itag;
+	if (out_dev == in_dev && err && IN_DEV_TX_REDIRECTS(out_dev) &&
 	    (IN_DEV_SHARED_MEDIA(out_dev) ||
-	     inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res))))
+	     inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res)))) {
 		flags |= RTCF_DOREDIRECT;
+		do_cache = false;
+	}
 
 	if (skb->protocol != htons(ETH_P_IP)) {
 		/* Not IP (i.e. ARP). Do not create route, if it is
@@ -1465,15 +1471,11 @@ static int __mkroute_input(struct sk_buf
 		}
 	}
 
-	do_cache = false;
-	if (res->fi) {
-		if (!itag) {
-			rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input);
-			if (rt_cache_valid(rth)) {
-				skb_dst_set_noref(skb, &rth->dst);
-				goto out;
-			}
-			do_cache = true;
+	if (do_cache) {
+		rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input);
+		if (rt_cache_valid(rth)) {
+			skb_dst_set_noref(skb, &rth->dst);
+			goto out;
 		}
 	}
 
author maintainer
#81 lore raw

PATCH 74/85 ipv4: fix forwarding for strict source routes

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Julian Anastasov <[email protected]>

[ Upstream commit e0adef0f7456d5d3a3bfe8ea61c7dddf146b40e1 ]

After the change "Adjust semantics of rt->rt_gateway" (commit f8126f1d51) rt_gateway can be 0 but ip_forward() compares it directly with nexthop. What we want here is to check if traffic is to directly connected nexthop and to fail if using gateway.

---
 net/ipv4/ip_forward.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv4/ip_forward.c +1 -1
@@ -85,7 +85,7 @@ int ip_forward(struct sk_buff *skb)
 
 	rt = skb_rtable(skb);
 
-	if (opt->is_strictroute && opt->nexthop != rt->rt_gateway)
+	if (opt->is_strictroute && rt->rt_gateway)
 		goto sr_failed;
 
 	if (unlikely(skb->len > dst_mtu(&rt->dst) && !skb_is_gso(skb) &&
author maintainer
#82 lore raw

PATCH 75/85 ipv4: make sure nh_pcpu_rth_output is always allocated

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Julian Anastasov <[email protected]>

[ Upstream commit f8a17175c63fd3e8b573719f7538816f8c96abf4 ]

Avoid checking nh_pcpu_rth_output in fast path, abort fib_info creation on alloc_percpu failure.

---
 net/ipv4/fib_semantics.c |    2 ++
 net/ipv4/route.c         |    3 ---
 2 files changed, 2 insertions(+), 3 deletions(-)
net/ipv4/fib_semantics.c +2 -0
@@ -840,6 +840,8 @@ struct fib_info *fib_create_info(struct
 	change_nexthops(fi) {
 		nexthop_nh->nh_parent = fi;
 		nexthop_nh->nh_pcpu_rth_output = alloc_percpu(struct rtable __rcu *);
+		if (!nexthop_nh->nh_pcpu_rth_output)
+			goto failure;
 	} endfor_nexthops(fi)
 
 	if (cfg->fc_mx) {
net/ipv4/route.c +0 -3
@@ -1210,8 +1210,6 @@ static bool rt_cache_route(struct fib_nh
 	if (rt_is_input_route(rt)) {
 		p = (struct rtable **)&nh->nh_rth_input;
 	} else {
-		if (!nh->nh_pcpu_rth_output)
-			goto nocache;
 		p = (struct rtable **)__this_cpu_ptr(nh->nh_pcpu_rth_output);
 	}
 	orig = *p;
@@ -1226,7 +1224,6 @@ static bool rt_cache_route(struct fib_nh
 		 * unsuccessful at storing this route into the cache
 		 * we really need to set it.
 		 */
-nocache:
 		rt->dst.flags |= DST_NOCACHE;
 		ret = false;
 	}
author maintainer
#83 lore raw

PATCH 76/85 ipv4: introduce rt_uses_gateway

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Julian Anastasov <[email protected]>

[ Upstream commit 155e8336c373d14d87a7f91e356d85ef4b93b8f9 ]

Add new flag to remember when route is via gateway. We will use it to allow rt_gateway to contain address of directly connected host for the cases when DST_NOCACHE is used or when the NH exception caches per-destination route without DST_NOCACHE flag, i.e. when routes are not used for other destinations. By this way we force the neighbour resolving to work with the routed destination but we can use different address in the packet, feature needed for IPVS-DR where original packet for virtual IP is routed via route to real IP.

---
 include/net/route.h             |    3 +-
 net/ipv4/inet_connection_sock.c |    4 +--
 net/ipv4/ip_forward.c           |    2 -
 net/ipv4/ip_output.c            |    4 +--
 net/ipv4/route.c                |   48 +++++++++++++++++++++-------------------
 net/ipv4/xfrm4_policy.c         |    1 
 6 files changed, 34 insertions(+), 28 deletions(-)
include/net/route.h +2 -1
@@ -48,7 +48,8 @@ struct rtable {
 	int			rt_genid;
 	unsigned int		rt_flags;
 	__u16			rt_type;
-	__u16			rt_is_input;
+	__u8			rt_is_input;
+	__u8			rt_uses_gateway;
 
 	int			rt_iif;
 
net/ipv4/inet_connection_sock.c +2 -2
@@ -386,7 +386,7 @@ struct dst_entry *inet_csk_route_req(str
 	rt = ip_route_output_flow(net, fl4, sk);
 	if (IS_ERR(rt))
 		goto no_route;
-	if (opt && opt->opt.is_strictroute && rt->rt_gateway)
+	if (opt && opt->opt.is_strictroute && rt->rt_uses_gateway)
 		goto route_err;
 	return &rt->dst;
 
@@ -422,7 +422,7 @@ struct dst_entry *inet_csk_route_child_s
 	rt = ip_route_output_flow(net, fl4, sk);
 	if (IS_ERR(rt))
 		goto no_route;
-	if (opt && opt->opt.is_strictroute && rt->rt_gateway)
+	if (opt && opt->opt.is_strictroute && rt->rt_uses_gateway)
 		goto route_err;
 	rcu_read_unlock();
 	return &rt->dst;
net/ipv4/ip_forward.c +1 -1
@@ -85,7 +85,7 @@ int ip_forward(struct sk_buff *skb)
 
 	rt = skb_rtable(skb);
 
-	if (opt->is_strictroute && rt->rt_gateway)
+	if (opt->is_strictroute && rt->rt_uses_gateway)
 		goto sr_failed;
 
 	if (unlikely(skb->len > dst_mtu(&rt->dst) && !skb_is_gso(skb) &&
net/ipv4/ip_output.c +2 -2
@@ -193,7 +193,7 @@ static inline int ip_finish_output2(stru
 	}
 
 	rcu_read_lock_bh();
-	nexthop = rt->rt_gateway ? rt->rt_gateway : ip_hdr(skb)->daddr;
+	nexthop = (__force u32) rt_nexthop(rt, ip_hdr(skb)->daddr);
 	neigh = __ipv4_neigh_lookup_noref(dev, nexthop);
 	if (unlikely(!neigh))
 		neigh = __neigh_create(&arp_tbl, &nexthop, dev, false);
@@ -371,7 +371,7 @@ int ip_queue_xmit(struct sk_buff *skb, s
 	skb_dst_set_noref(skb, &rt->dst);
 
 packet_routed:
-	if (inet_opt && inet_opt->opt.is_strictroute && rt->rt_gateway)
+	if (inet_opt && inet_opt->opt.is_strictroute && rt->rt_uses_gateway)
 		goto no_route;
 
 	/* OK, we know where to send it, allocate and build IP header. */
net/ipv4/route.c +26 -22

128 lines not on this page · raw message

net/ipv4/xfrm4_policy.c +1 -0
@@ -91,6 +91,7 @@ static int xfrm4_fill_dst(struct xfrm_ds
 					      RTCF_LOCAL);
 	xdst->u.rt.rt_type = rt->rt_type;
 	xdst->u.rt.rt_gateway = rt->rt_gateway;
+	xdst->u.rt.rt_uses_gateway = rt->rt_uses_gateway;
 	xdst->u.rt.rt_pmtu = rt->rt_pmtu;
 	INIT_LIST_HEAD(&xdst->u.rt.rt_uncached);
 
author maintainer
#84 lore raw

PATCH 77/85 ipv4: Add FLOWI_FLAG_KNOWN_NH

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Julian Anastasov <[email protected]>

[ Upstream commit c92b96553a80c1dbe2ebe128bbe37c8f98f148bf ]

Add flag to request that output route should be returned with known rt_gateway, in case we want to use it as nexthop for neighbour resolving.

The returned route can be cached as follows:

- in NH exception: because the cached routes are not shared with other destinations
- in FIB NH: when using gateway because all destinations for

	NH share same gateway

	As last option, to return rt_gateway!=0 we have to

set DST_NOCACHE.

---
 include/net/flow.h |    1 +
 net/ipv4/route.c   |   21 +++++++++++++++++----
 2 files changed, 18 insertions(+), 4 deletions(-)
include/net/flow.h +1 -0
@@ -21,6 +21,7 @@ struct flowi_common {
 	__u8	flowic_flags;
 #define FLOWI_FLAG_ANYSRC		0x01
 #define FLOWI_FLAG_CAN_SLEEP		0x02
+#define FLOWI_FLAG_KNOWN_NH		0x04
 	__u32	flowic_secid;
 };
 
net/ipv4/route.c +17 -4
@@ -1762,6 +1762,7 @@ static struct rtable *__mkroute_output(c
 	struct in_device *in_dev;
 	u16 type = res->type;
 	struct rtable *rth;
+	bool do_cache;
 
 	in_dev = __in_dev_get_rcu(dev_out);
 	if (!in_dev)
@@ -1798,24 +1799,36 @@ static struct rtable *__mkroute_output(c
 	}
 
 	fnhe = NULL;
+	do_cache = fi != NULL;
 	if (fi) {
 		struct rtable __rcu **prth;
+		struct fib_nh *nh = &FIB_RES_NH(*res);
 
-		fnhe = find_exception(&FIB_RES_NH(*res), fl4->daddr);
+		fnhe = find_exception(nh, fl4->daddr);
 		if (fnhe)
 			prth = &fnhe->fnhe_rth;
-		else
-			prth = __this_cpu_ptr(FIB_RES_NH(*res).nh_pcpu_rth_output);
+		else {
+			if (unlikely(fl4->flowi4_flags &
+				     FLOWI_FLAG_KNOWN_NH &&
+				     !(nh->nh_gw &&
+				       nh->nh_scope == RT_SCOPE_LINK))) {
+				do_cache = false;
+				goto add;
+			}
+			prth = __this_cpu_ptr(nh->nh_pcpu_rth_output);
+		}
 		rth = rcu_dereference(*prth);
 		if (rt_cache_valid(rth)) {
 			dst_hold(&rth->dst);
 			return rth;
 		}
 	}
+
+add:
 	rth = rt_dst_alloc(dev_out,
 			   IN_DEV_CONF_GET(in_dev, NOPOLICY),
 			   IN_DEV_CONF_GET(in_dev, NOXFRM),
-			   fi);
+			   do_cache);
 	if (!rth)
 		return ERR_PTR(-ENOBUFS);
 
author maintainer
#85 lore raw

PATCH 78/85 ipvs: fix ARP resolving for direct routing mode

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Julian Anastasov <[email protected]>

[ Upstream commit ad4d3ef8b7eb527cca478dc08c02c10936e64115 ]

After the change "Make neigh lookups directly in output packet path" (commit a263b30936) IPVS can not reach the real server for DR mode because we resolve the destination address from IP header, not from route neighbour. Use the new FLOWI_FLAG_KNOWN_NH flag to request output routes with known nexthop, so that it has preference on resolving.

---
 net/netfilter/ipvs/ip_vs_xmit.c |    8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
net/netfilter/ipvs/ip_vs_xmit.c +7 -1
@@ -49,6 +49,7 @@ enum {
 	IP_VS_RT_MODE_RDR	= 4, /* Allow redirect from remote daddr to
 				      * local
 				      */
+	IP_VS_RT_MODE_KNOWN_NH	= 16,/* Route via remote addr */
 };
 
 /*
@@ -103,6 +104,8 @@ __ip_vs_get_out_rt(struct sk_buff *skb,
 			memset(&fl4, 0, sizeof(fl4));
 			fl4.daddr = dest->addr.ip;
 			fl4.flowi4_tos = rtos;
+			fl4.flowi4_flags = (rt_mode & IP_VS_RT_MODE_KNOWN_NH) ?
+					   FLOWI_FLAG_KNOWN_NH : 0;
 			rt = ip_route_output_key(net, &fl4);
 			if (IS_ERR(rt)) {
 				spin_unlock(&dest->dst_lock);
@@ -127,6 +130,8 @@ __ip_vs_get_out_rt(struct sk_buff *skb,
 		memset(&fl4, 0, sizeof(fl4));
 		fl4.daddr = daddr;
 		fl4.flowi4_tos = rtos;
+		fl4.flowi4_flags = (rt_mode & IP_VS_RT_MODE_KNOWN_NH) ?
+				   FLOWI_FLAG_KNOWN_NH : 0;
 		rt = ip_route_output_key(net, &fl4);
 		if (IS_ERR(rt)) {
 			IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n",
@@ -1014,7 +1019,8 @@ ip_vs_dr_xmit(struct sk_buff *skb, struc
 	if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip,
 				      RT_TOS(iph->tos),
 				      IP_VS_RT_MODE_LOCAL |
-					IP_VS_RT_MODE_NON_LOCAL, NULL)))
+				      IP_VS_RT_MODE_NON_LOCAL |
+				      IP_VS_RT_MODE_KNOWN_NH, NULL)))
 		goto tx_error_icmp;
 	if (rt->rt_flags & RTCF_LOCAL) {
 		ip_rt_put(rt);
author maintainer
#86 lore raw

PATCH 79/85 RDS: fix rds-ping spinlock recursion

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: "jeff.liu" <[email protected]>

[ Upstream commit 5175a5e76bbdf20a614fb47ce7a38f0f39e70226 ]

This is the revised patch for fixing rds-ping spinlock recursion according to Venkat's suggestions.

RDS ping/pong over TCP feature has been broken for years(2.6.39 to 3.6.0) since we have to set TCP cork and call kernel_sendmsg() between ping/pong which both need to lock "struct sock *sk". However, this lock has already been hold before rds_tcp_data_ready() callback is triggerred. As a result, we always facing spinlock resursion which would resulting in system panic.

Given that RDS ping is only used to test the connectivity and not for serious performance measurements, we can queue the pong transmit to rds_wq as a delayed response.

---
 net/rds/send.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/rds/send.c +1 -1
@@ -1122,7 +1122,7 @@ rds_send_pong(struct rds_connection *con
 	rds_stats_inc(s_send_pong);
 
 	if (!test_bit(RDS_LL_SEND_FULL, &conn->c_flags))
-		rds_send_xmit(conn);
+		queue_delayed_work(rds_wq, &conn->c_send_w, 0);
 
 	rds_message_put(rm);
 	return 0;
author maintainer
#87 lore raw

PATCH 80/85 tcp: resets are misrouted

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Alexey Kuznetsov <[email protected]>

[ Upstream commit 4c67525849e0b7f4bd4fab2487ec9e43ea52ef29 ]

After commit e2446eaa ("tcp_v4_send_reset: binding oif to iif in no sock case").. tcp resets are always lost, when routing is asymmetric. Yes, backing out that patch will result in misrouting of resets for dead connections which used interface binding when were alive, but we actually cannot do anything here. What's died that's died and correct handling normal unbound connections is obviously a priority.

Comment to comment:

Quoted 2 lines

This has few benefits:
1. tcp_v6_send_reset already did that.

It was done to route resets for IPv6 link local addresses. It was a mistake to do so for global addresses. The patch fixes this as well.

Actually, the problem appears to be even more serious than guaranteed loss of resets. As reported by Sergey Soloviev <[email protected]>, those misrouted resets create a lot of arp traffic and huge amount of unresolved arp entires putting down to knees NAT firewalls which use asymmetric routing.

---
 net/ipv4/tcp_ipv4.c |    7 ++++---
 net/ipv6/tcp_ipv6.c |    3 ++-
 2 files changed, 6 insertions(+), 4 deletions(-)
net/ipv4/tcp_ipv4.c +4 -3
@@ -693,10 +693,11 @@ static void tcp_v4_send_reset(struct soc
 	arg.csumoffset = offsetof(struct tcphdr, check) / 2;
 	arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0;
 	/* When socket is gone, all binding information is lost.
-	 * routing might fail in this case. using iif for oif to
-	 * make sure we can deliver it
+	 * routing might fail in this case. No choice here, if we choose to force
+	 * input interface, we will misroute in case of asymmetric route.
 	 */
-	arg.bound_dev_if = sk ? sk->sk_bound_dev_if : inet_iif(skb);
+	if (sk)
+		arg.bound_dev_if = sk->sk_bound_dev_if;
 
 	net = dev_net(skb_dst(skb)->dev);
 	arg.tos = ip_hdr(skb)->tos;
net/ipv6/tcp_ipv6.c +2 -1
@@ -863,7 +863,8 @@ static void tcp_v6_send_response(struct
 	__tcp_v6_send_check(buff, &fl6.saddr, &fl6.daddr);
 
 	fl6.flowi6_proto = IPPROTO_TCP;
-	fl6.flowi6_oif = inet6_iif(skb);
+	if (ipv6_addr_type(&fl6.daddr) & IPV6_ADDR_LINKLOCAL)
+		fl6.flowi6_oif = inet6_iif(skb);
 	fl6.fl6_dport = t1->dest;
 	fl6.fl6_sport = t1->source;
 	security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
author maintainer
#88 lore raw

PATCH 81/85 ipv6: addrconf: fix /proc/net/if_inet6

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Eric Dumazet <[email protected]>

[ Upstream commit 9f0d3c2781baa1102108e16efbe640dd74564a7c ]

Commit 1d5783030a1 (ipv6/addrconf: speedup /proc/net/if_inet6 filling) added bugs hiding some devices from if_inet6 and breaking applications.

"ip -6 addr" could still display all IPv6 addresses, while "ifconfig -a" couldnt.

One way to reproduce the bug is by starting in a shell :

unshare -n /bin/bash
ifconfig lo up

And in original net namespace, lo device disappeared from if_inet6

---
 net/ipv6/addrconf.c |   15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)
net/ipv6/addrconf.c +9 -6
@@ -3088,14 +3088,15 @@ static struct inet6_ifaddr *if6_get_firs
 		struct hlist_node *n;
 		hlist_for_each_entry_rcu_bh(ifa, n, &inet6_addr_lst[state->bucket],
 					 addr_lst) {
+			if (!net_eq(dev_net(ifa->idev->dev), net))
+				continue;
 			/* sync with offset */
 			if (p < state->offset) {
 				p++;
 				continue;
 			}
 			state->offset++;
-			if (net_eq(dev_net(ifa->idev->dev), net))
-				return ifa;
+			return ifa;
 		}
 
 		/* prepare for next bucket */
@@ -3113,18 +3114,20 @@ static struct inet6_ifaddr *if6_get_next
 	struct hlist_node *n = &ifa->addr_lst;
 
 	hlist_for_each_entry_continue_rcu_bh(ifa, n, addr_lst) {
+		if (!net_eq(dev_net(ifa->idev->dev), net))
+			continue;
 		state->offset++;
-		if (net_eq(dev_net(ifa->idev->dev), net))
-			return ifa;
+		return ifa;
 	}
 
 	while (++state->bucket < IN6_ADDR_HSIZE) {
 		state->offset = 0;
 		hlist_for_each_entry_rcu_bh(ifa, n,
 				     &inet6_addr_lst[state->bucket], addr_lst) {
+			if (!net_eq(dev_net(ifa->idev->dev), net))
+				continue;
 			state->offset++;
-			if (net_eq(dev_net(ifa->idev->dev), net))
-				return ifa;
+			return ifa;
 		}
 	}
 
author maintainer
#89 lore raw

PATCH 82/85 sparc64: fix ptrace interaction with force_successful_syscall_return()

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Al Viro <[email protected]>

[ Upstream commit 55c2770e413e96871147b9406a9c41fe9bc5209c ]

we want syscall_trace_leave() called on exit from any syscall; skipping its call in case we'd done force_successful_syscall_return() is broken...

---
 arch/sparc/kernel/syscalls.S |   32 ++++++++++++++------------------
 1 file changed, 14 insertions(+), 18 deletions(-)
arch/sparc/kernel/syscalls.S +14 -18
@@ -212,24 +212,20 @@ linux_sparc_syscall:
 3:	stx	%o0, [%sp + PTREGS_OFF + PT_V9_I0]
 ret_sys_call:
 	ldx	[%sp + PTREGS_OFF + PT_V9_TSTATE], %g3
-	ldx	[%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
 	sra	%o0, 0, %o0
 	mov	%ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
 	sllx	%g2, 32, %g2
 
-	/* Check if force_successful_syscall_return()
-	 * was invoked.
-	 */
-	ldub	[%g6 + TI_SYS_NOERROR], %l2
-	brnz,a,pn %l2, 80f
-	 stb	%g0, [%g6 + TI_SYS_NOERROR]
-
 	cmp	%o0, -ERESTART_RESTARTBLOCK
 	bgeu,pn	%xcc, 1f
-	 andcc	%l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %l6
-80:
+	 andcc	%l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0
+	ldx	[%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
+
+2:
+	stb	%g0, [%g6 + TI_SYS_NOERROR]
 	/* System call success, clear Carry condition code. */
 	andn	%g3, %g2, %g3
+3:
 	stx	%g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]	
 	bne,pn	%icc, linux_syscall_trace2
 	 add	%l1, 0x4, %l2			! npc = npc+4
@@ -238,20 +234,20 @@ ret_sys_call:
 	 stx	%l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
 
 1:
+	/* Check if force_successful_syscall_return()
+	 * was invoked.
+	 */
+	ldub	[%g6 + TI_SYS_NOERROR], %l2
+	brnz,pn %l2, 2b
+	 ldx	[%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
 	/* System call failure, set Carry condition code.
 	 * Also, get abs(errno) to return to the process.
 	 */
-	andcc	%l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %l6	
 	sub	%g0, %o0, %o0
-	or	%g3, %g2, %g3
 	stx	%o0, [%sp + PTREGS_OFF + PT_V9_I0]
-	stx	%g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]
-	bne,pn	%icc, linux_syscall_trace2
-	 add	%l1, 0x4, %l2			! npc = npc+4
-	stx	%l1, [%sp + PTREGS_OFF + PT_V9_TPC]
+	ba,pt	%xcc, 3b
+	 or	%g3, %g2, %g3
 
-	b,pt	%xcc, rtrap
-	 stx	%l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
 linux_syscall_trace2:
 	call	syscall_trace_leave
 	 add	%sp, PTREGS_OFF, %o0
author maintainer
#90 lore raw

PATCH 83/85 sparc64: Like x86 we should check current->mm during perf backtrace generation.

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: "David S. Miller" <[email protected]>

[ Upstream commit 08280e6c4c2e8049ac61d9e8e3536ec1df629c0d ]

If the MM is not active, only report the top-level PC. Do not try to access the address space.

---
 arch/sparc/kernel/perf_event.c |    9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)
arch/sparc/kernel/perf_event.c +5 -4
@@ -1426,8 +1426,6 @@ static void perf_callchain_user_64(struc
 {
 	unsigned long ufp;
 
-	perf_callchain_store(entry, regs->tpc);
-
 	ufp = regs->u_regs[UREG_I6] + STACK_BIAS;
 	do {
 		struct sparc_stackf *usf, sf;
@@ -1448,8 +1446,6 @@ static void perf_callchain_user_32(struc
 {
 	unsigned long ufp;
 
-	perf_callchain_store(entry, regs->tpc);
-
 	ufp = regs->u_regs[UREG_I6] & 0xffffffffUL;
 	do {
 		struct sparc_stackf32 *usf, sf;
@@ -1468,6 +1464,11 @@ static void perf_callchain_user_32(struc
 void
 perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
 {
+	perf_callchain_store(entry, regs->tpc);
+
+	if (!current->mm)
+		return;
+
 	flushw_user();
 	if (test_thread_flag(TIF_32BIT))
 		perf_callchain_user_32(entry, regs);
author maintainer
#91 lore raw

PATCH 84/85 sparc64: Fix bit twiddling in sparc_pmu_enable_event().

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: "David S. Miller" <[email protected]>

[ Upstream commit e793d8c6740f8fe704fa216e95685f4d92c4c4b9 ]

There was a serious disconnect in the logic happening in sparc_pmu_disable_event() vs. sparc_pmu_enable_event().

Event disable is implemented by programming a NOP event into the PCR.

However, event enable was not reversing this operation. Instead, it was setting the User/Priv/Hypervisor trace enable bits.

That's not sparc_pmu_enable_event()'s job, that's what sparc_pmu_enable() and sparc_pmu_disable() do .

The intent of sparc_pmu_enable_event() is clear, since it first clear out the event type encoding field. So fix this by OR'ing in the event encoding rather than the trace enable bits.

---
 arch/sparc/kernel/perf_event.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
arch/sparc/kernel/perf_event.c +4 -2
@@ -557,11 +557,13 @@ static u64 nop_for_index(int idx)
 
 static inline void sparc_pmu_enable_event(struct cpu_hw_events *cpuc, struct hw_perf_event *hwc, int idx)
 {
-	u64 val, mask = mask_for_index(idx);
+	u64 enc, val, mask = mask_for_index(idx);
+
+	enc = perf_event_get_enc(cpuc->events[idx]);
 
 	val = cpuc->pcr;
 	val &= ~mask;
-	val |= hwc->config;
+	val |= event_encoding(enc, idx);
 	cpuc->pcr = val;
 
 	pcr_ops->write(cpuc->pcr);
author maintainer
#92 lore raw

PATCH 85/85 mac80211: call drv_get_tsf() in sleepable context

In reply to Greg Kroah-Hartman

3.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Thomas Pedersen <[email protected]>

commit 55fabefe3695241e6ccfa0cd4974f3fa497693dc upstream.

The call to drv_get/set_tsf() was put on the workqueue to perform tsf adjustments since that function might sleep. However it ended up inside a spinlock, whose critical section must be atomic. Do tsf adjustment outside the spinlock instead, and get rid of a warning.

---
 net/mac80211/mesh_sync.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
net/mac80211/mesh_sync.c +1 -2
@@ -56,7 +56,6 @@ void mesh_sync_adjust_tbtt(struct ieee80
 	u64 tsfdelta;
 
 	spin_lock_bh(&ifmsh->sync_offset_lock);
-
 	if (ifmsh->sync_offset_clockdrift_max < beacon_int_fraction) {
 		msync_dbg(sdata, "TBTT : max clockdrift=%lld; adjusting\n",
 			  (long long) ifmsh->sync_offset_clockdrift_max);
@@ -69,11 +68,11 @@ void mesh_sync_adjust_tbtt(struct ieee80
 		tsfdelta = -beacon_int_fraction;
 		ifmsh->sync_offset_clockdrift_max -= beacon_int_fraction;
 	}
+	spin_unlock_bh(&ifmsh->sync_offset_lock);
 
 	tsf = drv_get_tsf(local, sdata);
 	if (tsf != -1ULL)
 		drv_set_tsf(local, sdata, tsf + tsfdelta);
-	spin_unlock_bh(&ifmsh->sync_offset_lock);
 }
 
 static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,