Skip to contentSkip to conversation

3.6.5-stable review

PATCH New Greg Kroah-Hartman 2 participants 103 messages Oct 29, 2012 – Oct 30, 2012

Subsystems (46)
lore
Share & tools
lore

Greg Kroah-Hartman

author maintainer
#0 lore raw

cover 3.6.5-stable review

This is the start of the stable review cycle for the 3.6.5 release. There are 101 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 Wed Oct 31 21:31:45 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.5-rc1.gz

and the diffstat can be found below.

thanks,

greg k-h

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

Greg Kroah-Hartman <[email protected]>

    Linux 3.6.5-rc1

Peng Tao <[email protected]>
pnfsblock: fix non-aligned DIO write

Peng Tao <[email protected]>
pnfsblock: fix non-aligned DIO read

Yinghai Lu <[email protected]>
x86, mm: Use memblock memory loop instead of e820_RAM

Olof Johansson <[email protected]>
x86: efi: Turn off efi_enabled after setup on mixed fw/kernel

Josh Triplett <[email protected]>
efi: Defer freeing boot services memory until after ACPI init

Stanislaw Gruszka <[email protected]>
cfg80211/mac80211: avoid state mishmash on deauth

Yinghai Lu <[email protected]>
x86, mm: Undo incorrect revert in arch/x86/mm/init.c

Jacob Shin <[email protected]>
x86, mm: Find_early_table_space based on ranges that are actually being mapped

Felix Fietkau <[email protected]>
Revert "ath9k_hw: Updated AR9003 tx gain table for 5GHz"

Andreas Herrmann <[email protected]>
cpufreq / powernow-k8: Remove usage of smp_processor_id() in preemptible code

Stanislav Yakovlev <[email protected]>
net/wireless: ipw2200: Fix panic occurring in ipw_handle_promiscuous_tx()

Piotr Haber <[email protected]>
bcma: fix unregistration of cores

Johannes Berg <[email protected]>
iwlwifi: fix 6000 series channel switch command

Wei Yongjun <[email protected]>
dmaengine: imx-dma: fix missing unlock on error in imxdma_xfer_desc()

Barry Song <[email protected]>
dmaengine: sirf: fix a typo in moving running dma_desc to active queue

Barry Song <[email protected]>
dmaengine: sirf: fix a typo in dma_prep_interleaved

Oleg Nesterov <[email protected]>
freezer: exec should clear PF_NOFREEZE along with PF_KTHREAD

Dan Williams <[email protected]>
qmi_wwan/cdc_ether: move Novatel 551 and E362 to qmi_wwan

Johan Hedberg <[email protected]>
Bluetooth: SMP: Fix setting unknown auth_req bits

Chris Metcalf <[email protected]>
tilegx: fix some issues in the SW TSO support

Larry Finger <[email protected]>
b43: Fix oops on unload when firmware not found

Felix Fietkau <[email protected]>
mac80211: use ieee80211_free_txskb in a few more places

Stanislaw Gruszka <[email protected]>
mac80211: check if key has TKIP type before updating IV

Johannes Berg <[email protected]>
mac80211: connect with HT20 if HT40 is not permitted

Nicolas Ferre <[email protected]>
ARM: at91: fix external interrupt specification in board code

Nicolas Ferre <[email protected]>
ARM: at91: fix external interrupts in non-DT case

Ivan Shugov <[email protected]>
ARM: at91: at91sam9g10: fix SOC type detection

Bo Shen <[email protected]>
ARM: at91/i2c: change id to let i2c-gpio work

Josh Wu <[email protected]>
ARM: at91/tc: fix typo in the DT document

Heiko Stuebner <[email protected]>
ARM: SAMSUNG: Add naming of s3c64xx-spi devices

Michael S. Tsirkin <[email protected]>
vhost: fix mergeable bufs on BE hosts

Johan Hovold <[email protected]>
USB: mos7840: remove invalid disconnect handling

Johan Hovold <[email protected]>
USB: mos7840: remove NULL-urb submission

Johan Hovold <[email protected]>
USB: mos7840: fix port-device leak in error path

Johan Hovold <[email protected]>
USB: mos7840: fix urb leak at release

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

Johan Hovold <[email protected]>
USB: sierra: fix memory leak in probe error path

Johan Hovold <[email protected]>
USB: sierra: fix memory leak in attach error path

Lennart Sorensen <[email protected]>
USB: serial: Fix memory leak in sierra_release()

Johan Hovold <[email protected]>
USB: quatech2: fix io after disconnect

Johan Hovold <[email protected]>
USB: quatech2: fix close and disconnect urb handling

Johan Hovold <[email protected]>
USB: quatech2: fix port-data memory leaks

Johan Hovold <[email protected]>
USB: quatech2: fix memory leak in error path

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

Johan Hovold <[email protected]>
USB: metro-usb: fix io after disconnect

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

Johan Hovold <[email protected]>
USB: opticon: fix memory leak in error path

Johan Hovold <[email protected]>
USB: opticon: fix DMA from stack

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

Johan Hovold <[email protected]>
USB: whiteheat: fix memory leak in error path

Johan Hovold <[email protected]>
USB: qcserial: fix interface-data memory leak in error path

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

Johan Hovold <[email protected]>
USB: keyspan: fix NULL-pointer dereferences and memory leaks

Johan Hovold <[email protected]>
USB: option: fix interface-data memory leak in error path

Johan Hovold <[email protected]>
USB: mct_u232: fix broken close

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

Johan Hovold <[email protected]>
USB: ipw: fix interface-data memory leak in error path

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

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

Octavian Purdila <[email protected]>
usb hub: send clear_tt_buffer_complete events when canceling TT clear work

Johan Hovold <[email protected]>
USB: usb-wwan: fix multiple memory leaks in error paths

Michael Shigorin <[email protected]>
usb-storage: add unusual_devs entry for Casio EX-N1 digital camera

Anisse Astier <[email protected]>
ehci: Add yet-another Lucid nohandoff pci quirk

Anisse Astier <[email protected]>
ehci: fix Lucid nohandoff pci quirk to be more generic with BIOS versions

K. Y. Srinivasan <[email protected]>
Drivers: hv: Cleanup error handling in vmbus_open()

Peter Huewe <[email protected]>
extcon: unregister compat link on cleanup

Peter Huewe <[email protected]>
extcon: Unregister compat class at module unload to fix oops

Ian Abbott <[email protected]>
staging: comedi: amplc_pc236: fix possible NULL deref during detach

Ian Abbott <[email protected]>
staging: comedi: amplc_pc236: fix invalid register access during detach

Ian Abbott <[email protected]>
staging: comedi: amplc_pc263: fix possible NULL deref during detach

Ian Abbott <[email protected]>
staging: comedi: amplc_dio200: fix possible NULL deref during detach

Ian Abbott <[email protected]>
staging: comedi: ni_labpc: fix possible NULL deref during detach

Fred Brooks <[email protected]>
staging: comedi: ni_daq_700: fix dio subdevice regression

Ian Abbott <[email protected]>
staging: comedi: das08: fix possible NULL deref during detach

Nitin Gupta <[email protected]>
staging: zram: Fix handling of incompressible pages

Arve Hjønnevåg <[email protected]>
Staging: android: binder: Allow using highmem for binder buffers

Arve Hjønnevåg <[email protected]>
Staging: android: binder: Fix memory leak on thread/process exit

Geert Uytterhoeven <[email protected]>
sysfs: sysfs_pathname/sysfs_add_one: Use strlcat() instead of strcat()

Oliver Neukum <[email protected]>
xhci: endianness xhci_calculate_intel_u2_timeout

Oliver Neukum <[email protected]>
xhci: fix integer overflow

Sarah Sharp <[email protected]>
xhci: Fix potential NULL ptr deref in command cancellation.

Trond Myklebust <[email protected]>

    LOCKD: Clear ln->nsm_clnt only when ln->nsm_users is zero

Trond Myklebust <[email protected]>
SUNRPC: Prevent races in xs_abort_connection()

Trond Myklebust <[email protected]>
LOCKD: fix races in nsm_client_get

Trond Myklebust <[email protected]>
Revert "SUNRPC: Ensure we close the socket on EPIPE errors too..."

Trond Myklebust <[email protected]>
SUNRPC: Clear the connect flag when socket state is TCP_CLOSE_WAIT

Trond Myklebust <[email protected]>
SUNRPC: Get rid of the xs_error_report socket callback

Jan Kara <[email protected]>
mm: fix XFS oops due to dirty pages without buffers on s390

Yinghai Lu <[email protected]>
x86, mm: Trim memory in memblock to be page aligned

Dave Young <[email protected]>
Revert "x86/mm: Fix the size calculation of mapping tables"

Jan Beulich <[email protected]>
x86-64: Fix page table accounting

Will Deacon <[email protected]>
ARM: 7559/1: smp: switch away from the idmap before updating init_mm.mm_count

Thadeu Lima de Souza Cascardo <[email protected]>
genalloc: stop crashing the system when destroying a pool

Jan Luebbe <[email protected]>
drivers/rtc/rtc-imxdi.c: add missing spin lock initialization

Kees Cook <[email protected]>
fs/compat_ioctl.c: VIDEO_SET_SPU_PALETTE missing error check

Kees Cook <[email protected]>
gen_init_cpio: avoid stack overflow when expanding

Linus Torvalds <[email protected]>
VFS: don't do protected {sym,hard}links by default

Takashi Iwai <[email protected]>
ALSA: hda - Fix silent headphone output from Toshiba P200

Stefán Freyr <[email protected]>
ALSA: hda - add dock support for Thinkpad T430

Alex Deucher <[email protected]>
drm/radeon: add error output if VM CS fails on cayman

Alex Deucher <[email protected]>
drm/radeon: add some new SI PCI ids

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

Diffstat:

 .../devicetree/bindings/arm/atmel-at91.txt         |   2 +-
 Makefile                                           |   4 +-
 arch/arm/kernel/smp.c                              |  14 +-
 arch/arm/mach-at91/at91rm9200_devices.c            |   2 +-
 arch/arm/mach-at91/at91sam9260_devices.c           |   2 +-
 arch/arm/mach-at91/at91sam9261_devices.c           |   2 +-
 arch/arm/mach-at91/at91sam9263_devices.c           |   2 +-
 arch/arm/mach-at91/at91sam9rl_devices.c            |   2 +-
 arch/arm/mach-at91/board-neocore926.c              |   2 +-
 arch/arm/mach-at91/board-sam9261ek.c               |   2 +-
 arch/arm/mach-at91/board-sam9263ek.c               |   2 +-
 arch/arm/mach-at91/generic.h                       |   3 +-
 arch/arm/mach-at91/irq.c                           |   9 +-
 arch/arm/mach-at91/setup.c                         |   4 +-
 arch/arm/mach-exynos/common.c                      |   5 +
 arch/arm/mach-s3c24xx/s3c2416.c                    |   2 +
 arch/arm/mach-s3c24xx/s3c2443.c                    |   4 +
 arch/arm/mach-s5p64x0/common.c                     |   3 +
 arch/arm/mach-s5pc100/common.c                     |   3 +
 arch/arm/mach-s5pv210/common.c                     |   3 +
 arch/arm/plat-samsung/include/plat/spi-core.h      |  30 ++++
 arch/x86/include/asm/efi.h                         |   1 +
 arch/x86/kernel/e820.c                             |   3 +
 arch/x86/kernel/setup.c                            |  27 ++-
 arch/x86/mm/init.c                                 |  58 ++++---
 arch/x86/mm/init_64.c                              |   7 +-
 arch/x86/platform/efi/efi.c                        |  43 +++--
 drivers/bcma/main.c                                |   5 +-
 drivers/cpufreq/powernow-k8.c                      |   9 +-
 drivers/dma/imx-dma.c                              |   4 +-
 drivers/dma/sirf-dma.c                             |   4 +-
 drivers/extcon/extcon_class.c                      |   7 +
 drivers/gpu/drm/radeon/evergreen_cs.c              |   1 +
 drivers/hv/channel.c                               |  24 +--
 drivers/net/ethernet/tile/tilegx.c                 |  35 ++--
 drivers/net/usb/cdc_ether.c                        |  41 +++--
 drivers/net/usb/qmi_wwan.c                         |  14 ++
 .../net/wireless/ath/ath9k/ar9003_2p2_initvals.h   | 164 +++++++++---------
 drivers/net/wireless/b43/main.c                    |   4 +
 drivers/net/wireless/ipw2x00/ipw2200.c             |   2 +-
 drivers/net/wireless/iwlwifi/dvm/devices.c         |  39 +++--
 drivers/rtc/rtc-imxdi.c                            |   2 +
 drivers/staging/android/binder.c                   |  30 +++-
 drivers/staging/comedi/drivers/amplc_dio200.c      |   2 +
 drivers/staging/comedi/drivers/amplc_pc236.c       |   6 +-
 drivers/staging/comedi/drivers/amplc_pc263.c       |   3 +
 drivers/staging/comedi/drivers/das08.c             |   2 +
 drivers/staging/comedi/drivers/ni_daq_700.c        |   2 +-
 drivers/staging/comedi/drivers/ni_labpc.c          |   2 +
 drivers/staging/zram/zram_drv.c                    |  12 +-
 drivers/usb/core/hub.c                             |   7 +-
 drivers/usb/host/pci-quirks.c                      |   9 +-
 drivers/usb/host/xhci-ring.c                       |  11 ++
 drivers/usb/host/xhci.c                            |   4 +-
 drivers/usb/serial/ch341.c                         |  23 ++-
 drivers/usb/serial/digi_acceleport.c               | 117 +++++++------
 drivers/usb/serial/ipw.c                           |   7 +-
 drivers/usb/serial/keyspan.c                       | 183 ++++++++++-----------
 drivers/usb/serial/keyspan.h                       |   8 +
 drivers/usb/serial/mct_u232.c                      |  59 ++++---
 drivers/usb/serial/metro-usb.c                     |  65 +++-----
 drivers/usb/serial/mos7720.c                       |  62 +++----
 drivers/usb/serial/mos7840.c                       |  30 +---
 drivers/usb/serial/omninet.c                       |  36 ++--
 drivers/usb/serial/opticon.c                       |  11 +-
 drivers/usb/serial/option.c                        |  23 ++-
 drivers/usb/serial/qcserial.c                      |  33 ++--
 drivers/usb/serial/quatech2.c                      | 135 +++++++--------
 drivers/usb/serial/sierra.c                        | 133 +++++++--------
 drivers/usb/serial/usb-wwan.h                      |   2 +-
 drivers/usb/serial/usb_wwan.c                      | 130 ++++++---------
 drivers/usb/serial/whiteheat.c                     |  60 +++----
 drivers/usb/storage/unusual_devs.h                 |   6 +
 drivers/vhost/net.c                                |   3 +-
 fs/compat_ioctl.c                                  |   2 +
 fs/exec.c                                          |   3 +-
 fs/lockd/mon.c                                     |  57 ++++---
 fs/namei.c                                         |   4 +-
 fs/nfs/blocklayout/blocklayout.c                   |  93 ++++++++---
 fs/sysfs/dir.c                                     |  16 +-
 include/drm/drm_pciids.h                           |   3 +
 include/linux/efi.h                                |   5 +
 include/linux/memblock.h                           |   1 +
 include/net/cfg80211.h                             |   1 +
 init/main.c                                        |   3 +
 lib/genalloc.c                                     |   2 +-
 mm/memblock.c                                      |  24 +++
 mm/rmap.c                                          |  20 ++-
 net/bluetooth/smp.c                                |   6 +-
 net/mac80211/iface.c                               |   2 +-
 net/mac80211/mlme.c                                |  35 ++--
 net/mac80211/sta_info.c                            |   4 +-
 net/mac80211/util.c                                |   4 +-
 net/mac80211/wpa.c                                 |   3 +-
 net/sunrpc/xprtsock.c                              |  41 ++---
 net/wireless/mlme.c                                |  12 +-
 sound/pci/hda/patch_realtek.c                      |  20 ++-
 usr/gen_init_cpio.c                                |  43 ++---
 98 files changed, 1255 insertions(+), 961 deletions(-)
author maintainer
#1 lore raw

PATCH 1/101 drm/radeon: add some new SI PCI ids

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

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

From: Alex Deucher <[email protected]>

commit b6aa22db7857ab7ed042d6c56b800bfc727cfdff upstream.

---
 include/drm/drm_pciids.h |    3 +++
 1 file changed, 3 insertions(+)
include/drm/drm_pciids.h +3 -0
@@ -205,6 +205,8 @@
 	{0x1002, 0x6788, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x678A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6790, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x6791, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x6792, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6798, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6799, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x679A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
@@ -217,6 +219,7 @@
 	{0x1002, 0x6808, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6809, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6810, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x6811, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6816, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6817, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6818, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
author maintainer
#2 lore raw

PATCH 2/101 drm/radeon: add error output if VM CS fails on cayman

In reply to Greg Kroah-Hartman

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

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

From: Alex Deucher <[email protected]>

commit c71721324c612f7f040657ce9917d87f530f9784 upstream.

So we know why the CS was rejected.

---
 drivers/gpu/drm/radeon/evergreen_cs.c |    1 +
 1 file changed, 1 insertion(+)
drivers/gpu/drm/radeon/evergreen_cs.c +1 -0
@@ -2829,6 +2829,7 @@ static bool evergreen_vm_reg_valid(u32 r
 	case CAYMAN_SQ_EX_ALLOC_TABLE_SLOTS:
 		return true;
 	default:
+		DRM_ERROR("Invalid register 0x%x in CS\n", reg);
 		return false;
 	}
 }
author maintainer
#3 lore raw

PATCH 3/101 ALSA: hda - add dock support for Thinkpad T430

In reply to Greg Kroah-Hartman

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

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

From: =?UTF-8?q?Stef=C3=A1n=20Freyr?= <[email protected]>

commit 84f98fdf7865fbd35b312eb39ea91e5618c514c7 upstream.

I have a Lenovo ThinkPad T430 and an UltraBase Series 3 docking station.

Without this patch, if I plug my headphones into the jack on the computer, everything works fine. The computer speakers mute and the audio is played in the headphones. However, if I plug into the docking station headphone jack the computer speakers are muted but there is no audio in the headphones.

Addresses https://bugs.launchpad.net/bugs/1060372

---
 sound/pci/hda/patch_realtek.c |    1 +
 1 file changed, 1 insertion(+)
sound/pci/hda/patch_realtek.c +1 -0
@@ -6214,6 +6214,7 @@ static const struct snd_pci_quirk alc269
 	SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
 	SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK),
 	SND_PCI_QUIRK(0x17aa, 0x21fa, "Thinkpad X230", ALC269_FIXUP_LENOVO_DOCK),
+	SND_PCI_QUIRK(0x17aa, 0x21f3, "Thinkpad T430", ALC269_FIXUP_LENOVO_DOCK),
 	SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK),
 	SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK),
 	SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
author maintainer
#4 lore raw

PATCH 4/101 ALSA: hda - Fix silent headphone output from Toshiba P200

In reply to Greg Kroah-Hartman

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

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

From: Takashi Iwai <[email protected]>

commit cb766404e6b8c566569eb9ada02ea45d28729864 upstream.

By some reason, Toshiba laptop doesn't like the EAPD turned up for the headphone pin. Add a fix up code to force to turn down EAPD for NID 0x15.

Bugzilla: https://bugzilla.novell.com/show_bug.cgi?id=569991

---
 sound/pci/hda/patch_realtek.c |   19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)
sound/pci/hda/patch_realtek.c +18 -1
@@ -5704,6 +5704,7 @@ static const struct hda_verb alc268_beep
 
 enum {
 	ALC268_FIXUP_INV_DMIC,
+	ALC268_FIXUP_HP_EAPD,
 };
 
 static const struct alc_fixup alc268_fixups[] = {
@@ -5711,10 +5712,26 @@ static const struct alc_fixup alc268_fix
 		.type = ALC_FIXUP_FUNC,
 		.v.func = alc_fixup_inv_dmic_0x12,
 	},
+	[ALC268_FIXUP_HP_EAPD] = {
+		.type = ALC_FIXUP_VERBS,
+		.v.verbs = (const struct hda_verb[]) {
+			{0x15, AC_VERB_SET_EAPD_BTLENABLE, 0},
+			{}
+		}
+	},
 };
 
 static const struct alc_model_fixup alc268_fixup_models[] = {
 	{.id = ALC268_FIXUP_INV_DMIC, .name = "inv-dmic"},
+	{.id = ALC268_FIXUP_HP_EAPD, .name = "hp-eapd"},
+	{}
+};
+
+static const struct snd_pci_quirk alc268_fixup_tbl[] = {
+	/* below is codec SSID since multiple Toshiba laptops have the
+	 * same PCI SSID 1179:ff00
+	 */
+	SND_PCI_QUIRK(0x1179, 0xff06, "Toshiba P200", ALC268_FIXUP_HP_EAPD),
 	{}
 };
 
@@ -5749,7 +5766,7 @@ static int patch_alc268(struct hda_codec
 
 	spec = codec->spec;
 
-	alc_pick_fixup(codec, alc268_fixup_models, NULL, alc268_fixups);
+	alc_pick_fixup(codec, alc268_fixup_models, alc268_fixup_tbl, alc268_fixups);
 	alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
 
 	/* automatic parse from the BIOS config */
author maintainer
#5 lore raw

PATCH 5/101 VFS: dont do protected {sym,hard}links by default

In reply to Greg Kroah-Hartman

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

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

From: Linus Torvalds <[email protected]>

commit 561ec64ae67ef25cac8d72bb9c4bfc955edfd415 upstream.

In commit 800179c9b8a1 ("This adds symlink and hardlink restrictions to the Linux VFS"), the new link protections were enabled by default, in the hope that no actual application would care, despite it being technically against legacy UNIX (and documented POSIX) behavior.

However, it does turn out to break some applications. It's rare, and it's unfortunate, but it's unacceptable to break existing systems, so we'll have to default to legacy behavior.

In particular, it has broken the way AFD distributes files, see

http://www.dwd.de/AFD/

along with some legacy scripts.

Distributions can end up setting this at initrd time or in system
scripts: if you have security problems due to link attacks during your early boot sequence, you have bigger problems than some kernel sysctl setting. Do:

echo 1 > /proc/sys/fs/protected_symlinks
echo 1 > /proc/sys/fs/protected_hardlinks

to re-enable the link protections.

Alternatively, we may at some point introduce a kernel config option that sets these kinds of "more secure but not traditional" behavioural options automatically.

---
 fs/namei.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
fs/namei.c +2 -2
@@ -651,8 +651,8 @@ static inline void put_link(struct namei
 	path_put(link);
 }
 
-int sysctl_protected_symlinks __read_mostly = 1;
-int sysctl_protected_hardlinks __read_mostly = 1;
+int sysctl_protected_symlinks __read_mostly = 0;
+int sysctl_protected_hardlinks __read_mostly = 0;
 
 /**
  * may_follow_link - Check symlink following for unsafe situations
author maintainer
#6 lore raw

PATCH 6/101 gen_init_cpio: avoid stack overflow when expanding

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 20f1de659b77364d55d4e7fad2ef657e7730323f upstream.

Fix possible overflow of the buffer used for expanding environment variables when building file list.

In the extremely unlikely case of an attacker having control over the environment variables visible to gen_init_cpio, control over the contents of the file gen_init_cpio parses, and gen_init_cpio was built without compiler hardening, the attacker can gain arbitrary execution control via a stack buffer overflow.

  $ cat usr/crash.list
  file foo ${BIG}${BIG}${BIG}${BIG}${BIG}${BIG} 0755 0 0
  $ BIG=$(perl -e 'print "A" x 4096;') ./usr/gen_init_cpio usr/crash.list
  *** buffer overflow detected ***: ./usr/gen_init_cpio terminated

This also replaces the space-indenting with tabs.

Patch based on existing fix extracted from grsecurity.

---
 usr/gen_init_cpio.c |   41 ++++++++++++++++++++++-------------------
 1 file changed, 22 insertions(+), 19 deletions(-)
usr/gen_init_cpio.c +22 -19
@@ -303,7 +303,7 @@ static int cpio_mkfile(const char *name,
 	int retval;
 	int rc = -1;
 	int namesize;
-	int i;
+	unsigned int i;
 
 	mode |= S_IFREG;
 
@@ -381,25 +381,28 @@ error:
 
 static char *cpio_replace_env(char *new_location)
 {
-       char expanded[PATH_MAX + 1];
-       char env_var[PATH_MAX + 1];
-       char *start;
-       char *end;
-
-       for (start = NULL; (start = strstr(new_location, "${")); ) {
-               end = strchr(start, '}');
-               if (start < end) {
-                       *env_var = *expanded = '\0';
-                       strncat(env_var, start + 2, end - start - 2);
-                       strncat(expanded, new_location, start - new_location);
-                       strncat(expanded, getenv(env_var), PATH_MAX);
-                       strncat(expanded, end + 1, PATH_MAX);
-                       strncpy(new_location, expanded, PATH_MAX);
-               } else
-                       break;
-       }
+	char expanded[PATH_MAX + 1];
+	char env_var[PATH_MAX + 1];
+	char *start;
+	char *end;
+
+	for (start = NULL; (start = strstr(new_location, "${")); ) {
+		end = strchr(start, '}');
+		if (start < end) {
+			*env_var = *expanded = '\0';
+			strncat(env_var, start + 2, end - start - 2);
+			strncat(expanded, new_location, start - new_location);
+			strncat(expanded, getenv(env_var),
+				PATH_MAX - strlen(expanded));
+			strncat(expanded, end + 1,
+				PATH_MAX - strlen(expanded));
+			strncpy(new_location, expanded, PATH_MAX);
+			new_location[PATH_MAX] = 0;
+		} else
+			break;
+	}
 
-       return new_location;
+	return new_location;
 }
 
 
author maintainer
#7 lore raw

PATCH 7/101 fs/compat_ioctl.c: VIDEO_SET_SPU_PALETTE missing error check

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 12176503366885edd542389eed3aaf94be163fdb upstream.

The compat ioctl for VIDEO_SET_SPU_PALETTE was missing an error check while converting ioctl arguments. This could lead to leaking kernel stack contents into userspace.

Patch extracted from existing fix in grsecurity.

---
 fs/compat_ioctl.c |    2 ++
 1 file changed, 2 insertions(+)
fs/compat_ioctl.c +2 -0
@@ -210,6 +210,8 @@ static int do_video_set_spu_palette(unsi
 
 	err  = get_user(palp, &up->palette);
 	err |= get_user(length, &up->length);
+	if (err)
+		return -EFAULT;
 
 	up_native = compat_alloc_user_space(sizeof(struct video_spu_palette));
 	err  = put_user(compat_ptr(palp), &up_native->palette);
author maintainer
#8 lore raw

PATCH 8/101 drivers/rtc/rtc-imxdi.c: add missing spin lock initialization

In reply to Greg Kroah-Hartman

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

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

From: Jan Luebbe <[email protected]>

commit fee0de7791f967c2c5f0d43eb7b7261761b45e64 upstream.

---
 drivers/rtc/rtc-imxdi.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/rtc/rtc-imxdi.c +2 -0
@@ -392,6 +392,8 @@ static int dryice_rtc_probe(struct platf
 	if (imxdi->ioaddr == NULL)
 		return -ENOMEM;
 
+	spin_lock_init(&imxdi->irq_lock);
+
 	imxdi->irq = platform_get_irq(pdev, 0);
 	if (imxdi->irq < 0)
 		return imxdi->irq;
author maintainer
#9 lore raw

PATCH 9/101 genalloc: stop crashing the system when destroying a pool

In reply to Greg Kroah-Hartman

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

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

From: Thadeu Lima de Souza Cascardo <[email protected]>

commit eedce141cd2dad8d0cefc5468ef41898949a7031 upstream.

The genalloc code uses the bitmap API from include/linux/bitmap.h and lib/bitmap.c, which is based on long values. Both bitmap_set from lib/bitmap.c and bitmap_set_ll, which is the lockless version from genalloc.c, use BITMAP_LAST_WORD_MASK to set the first bits in a long in the bitmap.

That one uses (1 << bits) - 1, 0b111, if you are setting the first three bits. This means that the API counts from the least significant bits (LSB from now on) to the MSB. The LSB in the first long is bit 0, then. The same works for the lookup functions.

The genalloc code uses longs for the bitmap, as it should. In include/linux/genalloc.h, struct gen_pool_chunk has unsigned long bits[0] as its last member. When allocating the struct, genalloc should reserve enough space for the bitmap. This should be a proper number of longs that can fit the amount of bits in the bitmap.

However, genalloc allocates an integer number of bytes that fit the amount of bits, but may not be an integer amount of longs. 9 bytes, for example, could be allocated for 70 bits.

This is a problem in itself if the Least Significat Bit in a long is in the byte with the largest address, which happens in Big Endian machines. This means genalloc is not allocating the byte in which it will try to set or check for a bit.

This may end up in memory corruption, where genalloc will try to set the bits it has not allocated. In fact, genalloc may not set these bits because it may find them already set, because they were not zeroed since they were not allocated. And that's what causes a BUG when gen_pool_destroy is called and check for any set bits.

What really happens is that genalloc uses kmalloc_node with __GFP_ZERO on gen_pool_add_virt. With SLAB and SLUB, this means the whole slab will be cleared, not only the requested bytes. Since struct gen_pool_chunk has a size that is a multiple of 8, and slab sizes are multiples of 8, we get lucky and allocate and clear the right amount of bytes.

Hower, this is not the case with SLOB or with older code that did memset after allocating instead of using __GFP_ZERO.

So, a simple module as this (running 3.6.0), will cause a crash when rmmod'ed.

  [root@phantom-lp2 foo]# cat foo.c
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/genalloc.h>

  MODULE_LICENSE("GPL");
  MODULE_VERSION("0.1");

static struct gen_pool *foo_pool;

  static __init int foo_init(void)
  {
          int ret;
          foo_pool = gen_pool_create(10, -1);
          if (!foo_pool)
                  return -ENOMEM;
          ret = gen_pool_add(foo_pool, 0xa0000000, 32 << 10, -1);
          if (ret) {
                  gen_pool_destroy(foo_pool);
                  return ret;
          }
          return 0;
  }

  static __exit void foo_exit(void)
  {
          gen_pool_destroy(foo_pool);
  }

module_init(foo_init);
module_exit(foo_exit);
[root@phantom-lp2 foo]# zcat /proc/config.gz | grep SLOB CONFIG_SLOB=y
[root@phantom-lp2 foo]# insmod ./foo.ko [root@phantom-lp2 foo]# rmmod foo

  ------------[ cut here ]------------
  kernel BUG at lib/genalloc.c:243!
  cpu 0x4: Vector: 700 (Program Check) at [c0000000bb0e7960]
      pc: c0000000003cb50c: .gen_pool_destroy+0xac/0x110
      lr: c0000000003cb4fc: .gen_pool_destroy+0x9c/0x110
      sp: c0000000bb0e7be0
     msr: 8000000000029032
    current = 0xc0000000bb0e0000
    paca    = 0xc000000006d30e00   softe: 0        irq_happened: 0x01
      pid   = 13044, comm = rmmod
  kernel BUG at lib/genalloc.c:243!
  [c0000000bb0e7ca0] d000000004b00020 .foo_exit+0x20/0x38 [foo]
  [c0000000bb0e7d20] c0000000000dff98 .SyS_delete_module+0x1a8/0x290
  [c0000000bb0e7e30] c0000000000097d4 syscall_exit+0x0/0x94
  --- Exception: c00 (System Call) at 000000800753d1a0
  SP (fffd0b0e640) is in userspace
---
 lib/genalloc.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
lib/genalloc.c +1 -1
@@ -176,7 +176,7 @@ int gen_pool_add_virt(struct gen_pool *p
 	struct gen_pool_chunk *chunk;
 	int nbits = size >> pool->min_alloc_order;
 	int nbytes = sizeof(struct gen_pool_chunk) +
-				(nbits + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
+				BITS_TO_LONGS(nbits) * sizeof(long);
 
 	chunk = kmalloc_node(nbytes, GFP_KERNEL | __GFP_ZERO, nid);
 	if (unlikely(chunk == NULL))
author maintainer
#10 lore raw

PATCH 10/101 ARM: 7559/1: smp: switch away from the idmap before updating init_mm.mm_count

In reply to Greg Kroah-Hartman

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

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

From: Will Deacon <[email protected]>

commit 5f40b909728ad784eb43aa309d3c4e9bdf050781 upstream.

When booting a secondary CPU, the primary CPU hands two sets of page tables via the secondary_data struct:

(1) swapper_pg_dir: a normal, cacheable, shared (if SMP) mapping of the kernel image (i.e. the tables used by init_mm).

(2) idmap_pgd: an uncached mapping of the .idmap.text ELF section.

The idmap is generally used when enabling and disabling the MMU, which includes early CPU boot. In this case, the secondary CPU switches to swapper as soon as it enters C code:

	struct mm_struct *mm = &init_mm;
	unsigned int cpu = smp_processor_id();

	/*
	 * All kernel threads share the same mm context; grab a
	 * reference and switch to it.
	 */
	atomic_inc(&mm->mm_count);
	current->active_mm = mm;
	cpumask_set_cpu(cpu, mm_cpumask(mm));
	cpu_switch_mm(mm->pgd, mm);

This causes a problem on ARMv7, where the identity mapping is treated as strongly-ordered leading to architecturally UNPREDICTABLE behaviour of exclusive accesses, such as those used by atomic_inc.

This patch re-orders the secondary_start_kernel function so that we switch to swapper before performing any exclusive accesses.

---
 arch/arm/kernel/smp.c |   14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)
arch/arm/kernel/smp.c +10 -4
@@ -222,18 +222,24 @@ static void percpu_timer_setup(void);
 asmlinkage void __cpuinit secondary_start_kernel(void)
 {
 	struct mm_struct *mm = &init_mm;
-	unsigned int cpu = smp_processor_id();
+	unsigned int cpu;
+
+	/*
+	 * The identity mapping is uncached (strongly ordered), so
+	 * switch away from it before attempting any exclusive accesses.
+	 */
+	cpu_switch_mm(mm->pgd, mm);
+	enter_lazy_tlb(mm, current);
+	local_flush_tlb_all();
 
 	/*
 	 * All kernel threads share the same mm context; grab a
 	 * reference and switch to it.
 	 */
+	cpu = smp_processor_id();
 	atomic_inc(&mm->mm_count);
 	current->active_mm = mm;
 	cpumask_set_cpu(cpu, mm_cpumask(mm));
-	cpu_switch_mm(mm->pgd, mm);
-	enter_lazy_tlb(mm, current);
-	local_flush_tlb_all();
 
 	printk("CPU%u: Booted secondary processor\n", cpu);
 
author maintainer
#11 lore raw

PATCH 11/101 x86-64: Fix page table accounting

In reply to Greg Kroah-Hartman

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

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

From: Jan Beulich <[email protected]>

commit 876ee61aadf01aa0db981b5d249cbdd53dc28b5e upstream.

Commit 20167d3421a089a1bf1bd680b150dc69c9506810 ("x86-64: Fix accounting in kernel_physical_mapping_init()") went a little too far by entirely removing the counting of pre-populated page
tables: this should be done at boot time (to cover the page tables set up in early boot code), but shouldn't be done during memory hot add.

Hence, re-add the removed increments of "pages", but make them and the one in phys_pte_init() conditional upon !after_bootmem.

---
 arch/x86/mm/init_64.c |    7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
arch/x86/mm/init_64.c +6 -1
@@ -386,7 +386,8 @@ phys_pte_init(pte_t *pte_page, unsigned
 		 * these mappings are more intelligent.
 		 */
 		if (pte_val(*pte)) {
-			pages++;
+			if (!after_bootmem)
+				pages++;
 			continue;
 		}
 
@@ -451,6 +452,8 @@ phys_pmd_init(pmd_t *pmd_page, unsigned
 			 * attributes.
 			 */
 			if (page_size_mask & (1 << PG_LEVEL_2M)) {
+				if (!after_bootmem)
+					pages++;
 				last_map_addr = next;
 				continue;
 			}
@@ -526,6 +529,8 @@ phys_pud_init(pud_t *pud_page, unsigned
 			 * attributes.
 			 */
 			if (page_size_mask & (1 << PG_LEVEL_1G)) {
+				if (!after_bootmem)
+					pages++;
 				last_map_addr = next;
 				continue;
 			}
author maintainer
#12 lore raw

PATCH 12/101 Revert "x86/mm: Fix the size calculation of mapping tables"

In reply to Greg Kroah-Hartman

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

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

From: Dave Young <[email protected]>

commit 7b16bbf97375d9fb7fc107b3f80afeb94a204e44 upstream.

Commit:

722bc6b16771 x86/mm: Fix the size calculation of mapping tables

Tried to address the issue that the first 2/4M should use 4k pages if PSE enabled, but extra counts should only be valid for x86_32.

This commit caused a kdump regression: the kdump kernel hangs.

Work is in progress to fundamentally fix the various page table initialization issues that we have, via the design suggested by H. Peter Anvin, but it's not ready yet to be merged.

So, to get a working kdump revert to the last known working version, which is the revert of this commit and of a followup fix (which was incomplete):

bd2753b2dda7 x86/mm: Only add extra pages count for the first memory range during pre-allocation

Tested kdump on physical and virtual machines.

---
 arch/x86/mm/init.c |   22 +++++++++-------------
 1 file changed, 9 insertions(+), 13 deletions(-)
arch/x86/mm/init.c +9 -13
@@ -29,14 +29,8 @@ int direct_gbpages
 #endif
 ;
 
-struct map_range {
-	unsigned long start;
-	unsigned long end;
-	unsigned page_size_mask;
-};
-
-static void __init find_early_table_space(struct map_range *mr, unsigned long end,
-					  int use_pse, int use_gbpages)
+static void __init find_early_table_space(unsigned long end, int use_pse,
+					  int use_gbpages)
 {
 	unsigned long puds, pmds, ptes, tables, start = 0, good_end = end;
 	phys_addr_t base;
@@ -61,10 +55,6 @@ static void __init find_early_table_spac
 #ifdef CONFIG_X86_32
 		extra += PMD_SIZE;
 #endif
-		/* The first 2/4M doesn't use large pages. */
-		if (mr->start < PMD_SIZE)
-			extra += mr->end - mr->start;
-
 		ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
 	} else
 		ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
@@ -95,6 +85,12 @@ void __init native_pagetable_reserve(u64
 	memblock_reserve(start, end - start);
 }
 
+struct map_range {
+	unsigned long start;
+	unsigned long end;
+	unsigned page_size_mask;
+};
+
 #ifdef CONFIG_X86_32
 #define NR_RANGE_MR 3
 #else /* CONFIG_X86_64 */
@@ -267,7 +263,7 @@ unsigned long __init_refok init_memory_m
 	 * nodes are discovered.
 	 */
 	if (!after_bootmem)
-		find_early_table_space(&mr[0], end, use_pse, use_gbpages);
+		find_early_table_space(end, use_pse, use_gbpages);
 
 	for (i = 0; i < nr_range; i++)
 		ret = kernel_physical_mapping_init(mr[i].start, mr[i].end,
author maintainer
#13 lore raw

PATCH 13/101 x86, mm: Trim memory in memblock to be page aligned

In reply to Greg Kroah-Hartman

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

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

From: Yinghai Lu <[email protected]>

commit 6ede1fd3cb404c0016de6ac529df46d561bd558b upstream.

We will not map partial pages, so need to make sure memblock allocation will not allocate those bytes out.

Also we will use for_each_mem_pfn_range() to loop to map memory range to keep them consistent.

---
 arch/x86/kernel/e820.c   |    3 +++
 include/linux/memblock.h |    1 +
 mm/memblock.c            |   24 ++++++++++++++++++++++++
 3 files changed, 28 insertions(+)
arch/x86/kernel/e820.c +3 -0
@@ -1077,6 +1077,9 @@ void __init memblock_x86_fill(void)
 		memblock_add(ei->addr, ei->size);
 	}
 
+	/* throw away partial pages */
+	memblock_trim_memory(PAGE_SIZE);
+
 	memblock_dump_all();
 }
 
include/linux/memblock.h +1 -0
@@ -57,6 +57,7 @@ int memblock_add(phys_addr_t base, phys_
 int memblock_remove(phys_addr_t base, phys_addr_t size);
 int memblock_free(phys_addr_t base, phys_addr_t size);
 int memblock_reserve(phys_addr_t base, phys_addr_t size);
+void memblock_trim_memory(phys_addr_t align);
 
 #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
 void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn,
mm/memblock.c +24 -0
@@ -929,6 +929,30 @@ int __init_memblock memblock_is_region_r
 	return memblock_overlaps_region(&memblock.reserved, base, size) >= 0;
 }
 
+void __init_memblock memblock_trim_memory(phys_addr_t align)
+{
+	int i;
+	phys_addr_t start, end, orig_start, orig_end;
+	struct memblock_type *mem = &memblock.memory;
+
+	for (i = 0; i < mem->cnt; i++) {
+		orig_start = mem->regions[i].base;
+		orig_end = mem->regions[i].base + mem->regions[i].size;
+		start = round_up(orig_start, align);
+		end = round_down(orig_end, align);
+
+		if (start == orig_start && end == orig_end)
+			continue;
+
+		if (start < end) {
+			mem->regions[i].base = start;
+			mem->regions[i].size = end - start;
+		} else {
+			memblock_remove_region(mem, i);
+			i--;
+		}
+	}
+}
 
 void __init_memblock memblock_set_current_limit(phys_addr_t limit)
 {
author maintainer
#14 lore raw

PATCH 14/101 mm: fix XFS oops due to dirty pages without buffers on s390

In reply to Greg Kroah-Hartman

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

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

From: Jan Kara <[email protected]>

commit ef5d437f71afdf4afdbab99213add99f4b1318fd upstream.

On s390 any write to a page (even from kernel itself) sets architecture specific page dirty bit. Thus when a page is written to via buffered write, HW dirty bit gets set and when we later map and unmap the page, page_remove_rmap() finds the dirty bit and calls set_page_dirty().

Dirtying of a page which shouldn't be dirty can cause all sorts of problems to filesystems. The bug we observed in practice is that buffers from the page get freed, so when the page gets later marked as dirty and writeback writes it, XFS crashes due to an assertion BUG_ON(!PagePrivate(page)) in page_buffers() called from xfs_count_page_state().

Similar problem can also happen when zero_user_segment() call from xfs_vm_writepage() (or block_write_full_page() for that matter) set the hardware dirty bit during writeback, later buffers get freed, and then page unmapped.

Fix the issue by ignoring s390 HW dirty bit for page cache pages of mappings with mapping_cap_account_dirty(). This is safe because for such mappings when a page gets marked as writeable in PTE it is also marked dirty in do_wp_page() or do_page_fault(). When the dirty bit is cleared by clear_page_dirty_for_io(), the page gets writeprotected in page_mkclean(). So pagecache page is writeable if and only if it is dirty.

Thanks to Hugh Dickins for pointing out mapping has to have mapping_cap_account_dirty() for things to work and proposing a cleaned up variant of the patch.

The patch has survived about two hours of running fsx-linux on tmpfs while heavily swapping and several days of running on out build machines where the original problem was triggered.

---
 mm/rmap.c |   20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)
mm/rmap.c +15 -5
@@ -56,6 +56,7 @@
 #include <linux/mmu_notifier.h>
 #include <linux/migrate.h>
 #include <linux/hugetlb.h>
+#include <linux/backing-dev.h>
 
 #include <asm/tlbflush.h>
 
@@ -971,11 +972,8 @@ int page_mkclean(struct page *page)
 
 	if (page_mapped(page)) {
 		struct address_space *mapping = page_mapping(page);
-		if (mapping) {
+		if (mapping)
 			ret = page_mkclean_file(mapping, page);
-			if (page_test_and_clear_dirty(page_to_pfn(page), 1))
-				ret = 1;
-		}
 	}
 
 	return ret;
@@ -1161,6 +1159,7 @@ void page_add_file_rmap(struct page *pag
  */
 void page_remove_rmap(struct page *page)
 {
+	struct address_space *mapping = page_mapping(page);
 	bool anon = PageAnon(page);
 	bool locked;
 	unsigned long flags;
@@ -1183,8 +1182,19 @@ void page_remove_rmap(struct page *page)
 	 * this if the page is anon, so about to be freed; but perhaps
 	 * not if it's in swapcache - there might be another pte slot
 	 * containing the swap entry, but page not yet written to swap.
+	 *
+	 * And we can skip it on file pages, so long as the filesystem
+	 * participates in dirty tracking; but need to catch shm and tmpfs
+	 * and ramfs pages which have been modified since creation by read
+	 * fault.
+	 *
+	 * Note that mapping must be decided above, before decrementing
+	 * mapcount (which luckily provides a barrier): once page is unmapped,
+	 * it could be truncated and page->mapping reset to NULL at any moment.
+	 * Note also that we are relying on page_mapping(page) to set mapping
+	 * to &swapper_space when PageSwapCache(page).
 	 */
-	if ((!anon || PageSwapCache(page)) &&
+	if (mapping && !mapping_cap_account_dirty(mapping) &&
 	    page_test_and_clear_dirty(page_to_pfn(page), 1))
 		set_page_dirty(page);
 	/*
author maintainer
#15 lore raw

PATCH 15/101 SUNRPC: Get rid of the xs_error_report socket callback

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 f878b657ce8e7d3673afe48110ec208a29e38c4a upstream.

Chris Perl reports that we're seeing races between the wakeup call in xs_error_report and the connect attempts. Basically, Chris has shown that in certain circumstances, the call to xs_error_report causes the rpc_task that is responsible for reconnecting to wake up early, thus triggering a disconnect and retry.

Since the sk->sk_error_report() calls in the socket layer are always followed by a tcp_done() in the cases where we care about waking up the rpc_tasks, just let the state_change callbacks take responsibility for those wake ups.

---
 net/sunrpc/xprtsock.c |   25 -------------------------
 1 file changed, 25 deletions(-)
net/sunrpc/xprtsock.c +0 -25
@@ -254,7 +254,6 @@ struct sock_xprt {
 	void			(*old_data_ready)(struct sock *, int);
 	void			(*old_state_change)(struct sock *);
 	void			(*old_write_space)(struct sock *);
-	void			(*old_error_report)(struct sock *);
 };
 
 /*
@@ -781,7 +780,6 @@ static void xs_save_old_callbacks(struct
 	transport->old_data_ready = sk->sk_data_ready;
 	transport->old_state_change = sk->sk_state_change;
 	transport->old_write_space = sk->sk_write_space;
-	transport->old_error_report = sk->sk_error_report;
 }
 
 static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *sk)
@@ -789,7 +787,6 @@ static void xs_restore_old_callbacks(str
 	sk->sk_data_ready = transport->old_data_ready;
 	sk->sk_state_change = transport->old_state_change;
 	sk->sk_write_space = transport->old_write_space;
-	sk->sk_error_report = transport->old_error_report;
 }
 
 static void xs_reset_transport(struct sock_xprt *transport)
@@ -1549,25 +1546,6 @@ static void xs_tcp_state_change(struct s
 	read_unlock_bh(&sk->sk_callback_lock);
 }
 
-/**
- * xs_error_report - callback mainly for catching socket errors
- * @sk: socket
- */
-static void xs_error_report(struct sock *sk)
-{
-	struct rpc_xprt *xprt;
-
-	read_lock_bh(&sk->sk_callback_lock);
-	if (!(xprt = xprt_from_sock(sk)))
-		goto out;
-	dprintk("RPC:       %s client %p...\n"
-			"RPC:       error %d\n",
-			__func__, xprt, sk->sk_err);
-	xprt_wake_pending_tasks(xprt, -EAGAIN);
-out:
-	read_unlock_bh(&sk->sk_callback_lock);
-}
-
 static void xs_write_space(struct sock *sk)
 {
 	struct socket *sock;
@@ -1867,7 +1845,6 @@ static int xs_local_finish_connecting(st
 		sk->sk_user_data = xprt;
 		sk->sk_data_ready = xs_local_data_ready;
 		sk->sk_write_space = xs_udp_write_space;
-		sk->sk_error_report = xs_error_report;
 		sk->sk_allocation = GFP_ATOMIC;
 
 		xprt_clear_connected(xprt);
@@ -1995,7 +1972,6 @@ static void xs_udp_finish_connecting(str
 		sk->sk_user_data = xprt;
 		sk->sk_data_ready = xs_udp_data_ready;
 		sk->sk_write_space = xs_udp_write_space;
-		sk->sk_error_report = xs_error_report;
 		sk->sk_no_check = UDP_CSUM_NORCV;
 		sk->sk_allocation = GFP_ATOMIC;
 
@@ -2113,7 +2089,6 @@ static int xs_tcp_finish_connecting(stru
 		sk->sk_data_ready = xs_tcp_data_ready;
 		sk->sk_state_change = xs_tcp_state_change;
 		sk->sk_write_space = xs_tcp_write_space;
-		sk->sk_error_report = xs_error_report;
 		sk->sk_allocation = GFP_ATOMIC;
 
 		/* socket options */
author maintainer
#16 lore raw

PATCH 16/101 SUNRPC: Clear the connect flag when socket state is TCP_CLOSE_WAIT

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 d0bea455dd48da1ecbd04fedf00eb89437455fdc upstream.

This is needed to ensure that we call xprt_connect() upon the next call to call_connect().

---
 net/sunrpc/xprtsock.c |    1 +
 1 file changed, 1 insertion(+)
net/sunrpc/xprtsock.c +1 -0
@@ -1522,6 +1522,7 @@ static void xs_tcp_state_change(struct s
 	case TCP_CLOSE_WAIT:
 		/* The server initiated a shutdown of the socket */
 		xprt->connect_cookie++;
+		clear_bit(XPRT_CONNECTED, &xprt->state);
 		xs_tcp_force_close(xprt);
 	case TCP_CLOSING:
 		/*
author maintainer
#17 lore raw

PATCH 17/101 Revert "SUNRPC: Ensure we close the socket on EPIPE errors too..."

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 b9d2bb2ee537424a7f855e1f93eed44eb9ee0854 upstream.

This reverts commit 55420c24a0d4d1fce70ca713f84aa00b6b74a70e. Now that we clear the connected flag when entering TCP_CLOSE_WAIT, the deadlock described in this commit is no longer possible. Instead, the resulting call to xs_tcp_shutdown() can interfere with pending reconnection attempts.

---
 net/sunrpc/xprtsock.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/sunrpc/xprtsock.c +1 -1
@@ -736,10 +736,10 @@ static int xs_tcp_send_request(struct rp
 		dprintk("RPC:       sendmsg returned unrecognized error %d\n",
 			-status);
 	case -ECONNRESET:
-	case -EPIPE:
 		xs_tcp_shutdown(xprt);
 	case -ECONNREFUSED:
 	case -ENOTCONN:
+	case -EPIPE:
 		clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
 	}
 
author maintainer
#18 lore raw

PATCH 18/101 LOCKD: fix races in nsm_client_get

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 a4ee8d978e47e79d536226dccb48991f70091168 upstream.

Commit e9406db20fecbfcab646bad157b4cfdc7cadddfb (lockd: per-net NSM client creation and destruction helpers introduced) contains a nasty race on initialisation of the per-net NSM client because it doesn't check whether or not the client is set after grabbing the nsm_create_mutex.

---
 fs/lockd/mon.c |   43 ++++++++++++++++++++++++++-----------------
 1 file changed, 26 insertions(+), 17 deletions(-)
fs/lockd/mon.c +26 -17
@@ -85,29 +85,38 @@ static struct rpc_clnt *nsm_create(struc
 	return rpc_create(&args);
 }
 
+static struct rpc_clnt *nsm_client_set(struct lockd_net *ln,
+		struct rpc_clnt *clnt)
+{
+	spin_lock(&ln->nsm_clnt_lock);
+	if (ln->nsm_users == 0) {
+		if (clnt == NULL)
+			goto out;
+		ln->nsm_clnt = clnt;
+	}
+	clnt = ln->nsm_clnt;
+	ln->nsm_users++;
+out:
+	spin_unlock(&ln->nsm_clnt_lock);
+	return clnt;
+}
+
 static struct rpc_clnt *nsm_client_get(struct net *net)
 {
-	static DEFINE_MUTEX(nsm_create_mutex);
-	struct rpc_clnt	*clnt;
+	struct rpc_clnt	*clnt, *new;
 	struct lockd_net *ln = net_generic(net, lockd_net_id);
 
-	spin_lock(&ln->nsm_clnt_lock);
-	if (ln->nsm_users) {
-		ln->nsm_users++;
-		clnt = ln->nsm_clnt;
-		spin_unlock(&ln->nsm_clnt_lock);
+	clnt = nsm_client_set(ln, NULL);
+	if (clnt != NULL)
 		goto out;
-	}
-	spin_unlock(&ln->nsm_clnt_lock);
 
-	mutex_lock(&nsm_create_mutex);
-	clnt = nsm_create(net);
-	if (!IS_ERR(clnt)) {
-		ln->nsm_clnt = clnt;
-		smp_wmb();
-		ln->nsm_users = 1;
-	}
-	mutex_unlock(&nsm_create_mutex);
+	clnt = new = nsm_create(net);
+	if (IS_ERR(clnt))
+		goto out;
+
+	clnt = nsm_client_set(ln, new);
+	if (clnt != new)
+		rpc_shutdown_client(new);
 out:
 	return clnt;
 }
author maintainer
#19 lore raw

PATCH 19/101 SUNRPC: Prevent races in xs_abort_connection()

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 4bc1e68ed6a8b59be8a79eb719be515a55c7bc68 upstream.

The call to xprt_disconnect_done() that is triggered by a successful connection reset will trigger another automatic wakeup of all tasks on the xprt->pending rpc_wait_queue. In particular it will cause an early wake up of the task that called xprt_connect().

All we really want to do here is clear all the socket-specific state flags, so we split that functionality out of xs_sock_mark_closed() into a helper that can be called by xs_abort_connection()

---
 net/sunrpc/xprtsock.c |   13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)
net/sunrpc/xprtsock.c +8 -5
@@ -1459,7 +1459,7 @@ static void xs_tcp_cancel_linger_timeout
 	xprt_clear_connecting(xprt);
 }
 
-static void xs_sock_mark_closed(struct rpc_xprt *xprt)
+static void xs_sock_reset_connection_flags(struct rpc_xprt *xprt)
 {
 	smp_mb__before_clear_bit();
 	clear_bit(XPRT_CONNECTION_ABORT, &xprt->state);
@@ -1467,6 +1467,11 @@ static void xs_sock_mark_closed(struct r
 	clear_bit(XPRT_CLOSE_WAIT, &xprt->state);
 	clear_bit(XPRT_CLOSING, &xprt->state);
 	smp_mb__after_clear_bit();
+}
+
+static void xs_sock_mark_closed(struct rpc_xprt *xprt)
+{
+	xs_sock_reset_connection_flags(xprt);
 	/* Mark transport as closed and wake up all pending tasks */
 	xprt_disconnect_done(xprt);
 }
@@ -2042,10 +2047,8 @@ static void xs_abort_connection(struct s
 	any.sa_family = AF_UNSPEC;
 	result = kernel_connect(transport->sock, &any, sizeof(any), 0);
 	if (!result)
-		xs_sock_mark_closed(&transport->xprt);
-	else
-		dprintk("RPC:       AF_UNSPEC connect return code %d\n",
-				result);
+		xs_sock_reset_connection_flags(&transport->xprt);
+	dprintk("RPC:       AF_UNSPEC connect return code %d\n", result);
 }
 
 static void xs_tcp_reuse_connection(struct sock_xprt *transport)
author maintainer
#20 lore raw

PATCH 20/101 LOCKD: Clear ln->nsm_clnt only when ln->nsm_users is zero

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 e498daa81295d02f7359af313c2b7f87e1062207 upstream.

The current code is clearing it in all cases _except_ when zero.

---
 fs/lockd/mon.c |   14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)
fs/lockd/mon.c +6 -8
@@ -124,18 +124,16 @@ out:
 static void nsm_client_put(struct net *net)
 {
 	struct lockd_net *ln = net_generic(net, lockd_net_id);
-	struct rpc_clnt	*clnt = ln->nsm_clnt;
-	int shutdown = 0;
+	struct rpc_clnt	*clnt = NULL;
 
 	spin_lock(&ln->nsm_clnt_lock);
-	if (ln->nsm_users) {
-		if (--ln->nsm_users)
-			ln->nsm_clnt = NULL;
-		shutdown = !ln->nsm_users;
+	ln->nsm_users--;
+	if (ln->nsm_users == 0) {
+		clnt = ln->nsm_clnt;
+		ln->nsm_clnt = NULL;
 	}
 	spin_unlock(&ln->nsm_clnt_lock);
-
-	if (shutdown)
+	if (clnt != NULL)
 		rpc_shutdown_client(clnt);
 }
 
author maintainer
#21 lore raw

PATCH 21/101 xhci: Fix potential NULL ptr deref in command cancellation.

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 43a09f7fb01fa1e091416a2aa49b6c666458c1ee upstream.

The command cancellation code doesn't check whether find_trb_seg() couldn't find the segment that contains the TRB to be canceled. This could cause a NULL pointer deference later in the function when next_trb is called. It's unlikely to happen unless something is wrong with the command ring pointers, so add some debugging in case it happens.

This patch should be backported to stable kernels as old as 3.0, that contain the commit b63f4053cc8aa22a98e3f9a97845afe6c15d0a0d "xHCI:
handle command after aborting the command ring".

---
 drivers/usb/host/xhci-ring.c |   11 +++++++++++
 1 file changed, 11 insertions(+)
drivers/usb/host/xhci-ring.c +11 -0
@@ -1228,6 +1228,17 @@ static void xhci_cmd_to_noop(struct xhci
 	cur_seg = find_trb_seg(xhci->cmd_ring->first_seg,
 			xhci->cmd_ring->dequeue, &cycle_state);
 
+	if (!cur_seg) {
+		xhci_warn(xhci, "Command ring mismatch, dequeue = %p %llx (dma)\n",
+				xhci->cmd_ring->dequeue,
+				(unsigned long long)
+				xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
+					xhci->cmd_ring->dequeue));
+		xhci_debug_ring(xhci, xhci->cmd_ring);
+		xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring);
+		return;
+	}
+
 	/* find the command trb matched by cd from command ring */
 	for (cmd_trb = xhci->cmd_ring->dequeue;
 			cmd_trb != xhci->cmd_ring->enqueue;
author maintainer
#22 lore raw

PATCH 22/101 xhci: fix integer overflow

In reply to Greg Kroah-Hartman

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

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

From: Oliver Neukum <[email protected]>

commit 16b45fdf9c4e82f5d3bc53aa70737650e7c8d5ed upstream.

xhci_service_interval_to_ns() returns long long to avoid an overflow. However, the type cast happens too late. The fix is to force ULL from the beginning.

This patch should be backported to kernels as old as 3.5, that contain the commit e3567d2c15a7a8e2f992a5f7c7683453ca406d82 "xhci: Add Intel U1/U2 timeout policy."

---
 drivers/usb/host/xhci.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/host/xhci.c +1 -1
@@ -4020,7 +4020,7 @@ int xhci_update_device(struct usb_hcd *h
 static unsigned long long xhci_service_interval_to_ns(
 		struct usb_endpoint_descriptor *desc)
 {
-	return (1 << (desc->bInterval - 1)) * 125 * 1000;
+	return (1ULL << (desc->bInterval - 1)) * 125 * 1000;
 }
 
 static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev,
author maintainer
#23 lore raw

PATCH 23/101 xhci: endianness xhci_calculate_intel_u2_timeout

In reply to Greg Kroah-Hartman

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

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

From: Oliver Neukum <[email protected]>

commit 966e7a854177097083683176ced871558b631a12 upstream.

An le16 is accessed without conversion.

This patch should be backported to kernels as old as 3.5, that contain the commit e3567d2c15a7a8e2f992a5f7c7683453ca406d82 "xhci: Add Intel U1/U2 timeout policy."

---
 drivers/usb/host/xhci.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/host/xhci.c +1 -1
@@ -4141,7 +4141,7 @@ static u16 xhci_calculate_intel_u2_timeo
 			(xhci_service_interval_to_ns(desc) > timeout_ns))
 		timeout_ns = xhci_service_interval_to_ns(desc);
 
-	u2_del_ns = udev->bos->ss_cap->bU2DevExitLat * 1000;
+	u2_del_ns = le16_to_cpu(udev->bos->ss_cap->bU2DevExitLat) * 1000ULL;
 	if (u2_del_ns > timeout_ns)
 		timeout_ns = u2_del_ns;
 
author maintainer
#24 lore raw

PATCH 24/101 sysfs: sysfs_pathname/sysfs_add_one: Use strlcat() instead of strcat()

In reply to Greg Kroah-Hartman

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

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

From: Geert Uytterhoeven <[email protected]>

commit 66081a72517a131430dcf986775f3268aafcb546 upstream.

The warning check for duplicate sysfs entries can cause a buffer overflow when printing the warning, as strcat() doesn't check buffer sizes. Use strlcat() instead.

Since strlcat() doesn't return a pointer to the passed buffer, unlike strcat(), I had to convert the nested concatenation in sysfs_add_one() to an admittedly more obscure comma operator construct, to avoid emitting code for the concatenation if CONFIG_BUG is disabled.

---
 fs/sysfs/dir.c |   16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)
fs/sysfs/dir.c +8 -8
@@ -485,20 +485,18 @@ int __sysfs_add_one(struct sysfs_addrm_c
 /**
  *	sysfs_pathname - return full path to sysfs dirent
  *	@sd: sysfs_dirent whose path we want
- *	@path: caller allocated buffer
+ *	@path: caller allocated buffer of size PATH_MAX
  *
  *	Gives the name "/" to the sysfs_root entry; any path returned
  *	is relative to wherever sysfs is mounted.
- *
- *	XXX: does no error checking on @path size
  */
 static char *sysfs_pathname(struct sysfs_dirent *sd, char *path)
 {
 	if (sd->s_parent) {
 		sysfs_pathname(sd->s_parent, path);
-		strcat(path, "/");
+		strlcat(path, "/", PATH_MAX);
 	}
-	strcat(path, sd->s_name);
+	strlcat(path, sd->s_name, PATH_MAX);
 	return path;
 }
 
@@ -531,9 +529,11 @@ int sysfs_add_one(struct sysfs_addrm_cxt
 		char *path = kzalloc(PATH_MAX, GFP_KERNEL);
 		WARN(1, KERN_WARNING
 		     "sysfs: cannot create duplicate filename '%s'\n",
-		     (path == NULL) ? sd->s_name :
-		     strcat(strcat(sysfs_pathname(acxt->parent_sd, path), "/"),
-		            sd->s_name));
+		     (path == NULL) ? sd->s_name
+				    : (sysfs_pathname(acxt->parent_sd, path),
+				       strlcat(path, "/", PATH_MAX),
+				       strlcat(path, sd->s_name, PATH_MAX),
+				       path));
 		kfree(path);
 	}
 
author maintainer
#25 lore raw

PATCH 25/101 Staging: android: binder: Fix memory leak on thread/process exit

In reply to Greg Kroah-Hartman

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

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

From: Arve Hjønnevåg <[email protected]>

commit 675d66b0ed5fd170d6a44cf8dbb3fa56a5347bdb upstream.

If a thread or process exited while a reply, one-way transaction or death notification was pending, the struct holding the pending work was leaked.

---
 drivers/staging/android/binder.c |   28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)
drivers/staging/android/binder.c +27 -1
@@ -2507,14 +2507,38 @@ static void binder_release_work(struct l
 			struct binder_transaction *t;
 
 			t = container_of(w, struct binder_transaction, work);
-			if (t->buffer->target_node && !(t->flags & TF_ONE_WAY))
+			if (t->buffer->target_node &&
+			    !(t->flags & TF_ONE_WAY)) {
 				binder_send_failed_reply(t, BR_DEAD_REPLY);
+			} else {
+				binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
+					"binder: undelivered transaction %d\n",
+					t->debug_id);
+				t->buffer->transaction = NULL;
+				kfree(t);
+				binder_stats_deleted(BINDER_STAT_TRANSACTION);
+			}
 		} break;
 		case BINDER_WORK_TRANSACTION_COMPLETE: {
+			binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
+				"binder: undelivered TRANSACTION_COMPLETE\n");
 			kfree(w);
 			binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
 		} break;
+		case BINDER_WORK_DEAD_BINDER_AND_CLEAR:
+		case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: {
+			struct binder_ref_death *death;
+
+			death = container_of(w, struct binder_ref_death, work);
+			binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
+				"binder: undelivered death notification, %p\n",
+				death->cookie);
+			kfree(death);
+			binder_stats_deleted(BINDER_STAT_DEATH);
+		} break;
 		default:
+			pr_err("binder: unexpected work type, %d, not freed\n",
+			       w->type);
 			break;
 		}
 	}
@@ -2984,6 +3008,7 @@ static void binder_deferred_release(stru
 		nodes++;
 		rb_erase(&node->rb_node, &proc->nodes);
 		list_del_init(&node->work.entry);
+		binder_release_work(&node->async_todo);
 		if (hlist_empty(&node->refs)) {
 			kfree(node);
 			binder_stats_deleted(BINDER_STAT_NODE);
@@ -3022,6 +3047,7 @@ static void binder_deferred_release(stru
 		binder_delete_ref(ref);
 	}
 	binder_release_work(&proc->todo);
+	binder_release_work(&proc->delivered_death);
 	buffers = 0;
 
 	while ((n = rb_first(&proc->allocated_buffers))) {
author maintainer
#26 lore raw

PATCH 26/101 Staging: android: binder: Allow using highmem for binder buffers

In reply to Greg Kroah-Hartman

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

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

From: Arve Hjønnevåg <[email protected]>

commit 585650dcec88e704a19bb226a34b6a7166111623 upstream.

The default kernel mapping for the pages allocated for the binder buffers is never used. Set the __GFP_HIGHMEM flag when allocating these pages so we don't needlessly use low memory pages that may be required elsewhere.

---
 drivers/staging/android/binder.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/staging/android/binder.c +1 -1
@@ -655,7 +655,7 @@ static int binder_update_page_range(stru
 		page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];
 
 		BUG_ON(*page);
-		*page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+		*page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO);
 		if (*page == NULL) {
 			pr_err("binder: %d: binder_alloc_buf failed "
 			       "for page at %p\n", proc->pid, page_addr);
author maintainer
#27 lore raw

PATCH 27/101 staging: zram: Fix handling of incompressible pages

In reply to Greg Kroah-Hartman

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

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

From: Nitin Gupta <[email protected]>

commit c8f2f0db1d0294aaf37e8a85bea9bbc4aaf5c0fe upstream.

Change 130f315a (staging: zram: remove special handle of uncompressed page) introduced a bug in the handling of incompressible pages which resulted in memory allocation failure for such pages.

When a page expands on compression, say from 4K to 4K+30, we were trying to do zsmalloc(pool, 4K+30). However, the maximum size which zsmalloc can allocate is PAGE_SIZE (for obvious reasons), so such allocation requests always return failure (0).

For a page that has compressed size larger than the original size (this may happen with already compressed or random data), there is no point storing the compressed version as that would take more space and would also require time for decompression when needed again. So, the fix is to store any page, whose compressed size exceeds a threshold (max_zpage_size), as-it-is i.e. without compression. Memory required for storing this uncompressed page can then be requested from zsmalloc which supports PAGE_SIZE sized allocations.

Lastly, the fix checks that we do not attempt to "decompress" the page which we stored in the uncompressed form -- we just memcpy() out such pages.

---
 drivers/staging/zram/zram_drv.c |   12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)
drivers/staging/zram/zram_drv.c +10 -2
@@ -223,8 +223,13 @@ static int zram_bvec_read(struct zram *z
 	cmem = zs_map_object(zram->mem_pool, zram->table[index].handle,
 				ZS_MM_RO);
 
-	ret = lzo1x_decompress_safe(cmem, zram->table[index].size,
+	if (zram->table[index].size == PAGE_SIZE) {
+		memcpy(uncmem, cmem, PAGE_SIZE);
+		ret = LZO_E_OK;
+	} else {
+		ret = lzo1x_decompress_safe(cmem, zram->table[index].size,
 				    uncmem, &clen);
+	}
 
 	if (is_partial_io(bvec)) {
 		memcpy(user_mem + bvec->bv_offset, uncmem + offset,
@@ -342,8 +347,11 @@ static int zram_bvec_write(struct zram *
 		goto out;
 	}
 
-	if (unlikely(clen > max_zpage_size))
+	if (unlikely(clen > max_zpage_size)) {
 		zram_stat_inc(&zram->stats.bad_compress);
+		src = uncmem;
+		clen = PAGE_SIZE;
+	}
 
 	handle = zs_malloc(zram->mem_pool, clen);
 	if (!handle) {
author maintainer
#28 lore raw

PATCH 28/101 staging: comedi: das08: fix possible NULL deref during detach

In reply to Greg Kroah-Hartman

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

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

From: Ian Abbott <[email protected]>

commit ee280d134f2e05e0172369a53fbe202dbfc527fa upstream.

das08_detach() is called by the comedi core to clean up if either das08_attach() or das08_attach_pci() returns an error. It sets thisboard to the return value of comedi_board(dev) and assumes it is non-null. This is a valid assumption if das08_attach() fails, but not if das08_attach_pci() fails, leading to a possible NULL pointer dereference.

Check thisboard at the top of das08_detach() and return early if it is NULL. This is okay because the only other thing that could have been allocated is dev->private and that is freed by the comedi core, not by this function.

---
 drivers/staging/comedi/drivers/das08.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/staging/comedi/drivers/das08.c +2 -0
@@ -1028,6 +1028,8 @@ static void __maybe_unused das08_detach(
 	const struct das08_board_struct *thisboard = comedi_board(dev);
 	struct das08_private_struct *devpriv = dev->private;
 
+	if (!thisboard)
+		return;
 	das08_common_detach(dev);
 	if (IS_ENABLED(CONFIG_COMEDI_DAS08_ISA) &&
 	    (thisboard->bustype == isa || thisboard->bustype == pc104)) {
author maintainer
#29 lore raw

PATCH 29/101 staging: comedi: ni_daq_700: fix dio subdevice regression

In reply to Greg Kroah-Hartman

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

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

From: Fred Brooks <[email protected]>

commit 6681e63399926651cc29bcb9d92229b6f1cf1daa upstream.

Here is a small patch to fix a problem caused by a previous patch that removed the callback function. The callback remove patch:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=1de02225358988e8fd48d1dc3fd12336bbae258a

I finally booted my dev machine on the latest kernel (running Debian here so it's still on 3.2 normally) to test the ni_daq_700 driver with my test program and noticed this bug.

Shift the DIO_R read result to bits 8..15 Digital direction
configuration: channels 0-7 output, 8-15 input (8225 device emu as port A output, port B input, port C N/A).

---
 drivers/staging/comedi/drivers/ni_daq_700.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/staging/comedi/drivers/ni_daq_700.c +1 -1
@@ -71,7 +71,7 @@ static int subdev_700_insn(struct comedi
 	}
 
 	data[1] = s->state & 0xff;
-	data[1] |= inb(dev->iobase + DIO_R);
+	data[1] |= inb(dev->iobase + DIO_R) << 8;
 
 	return insn->n;
 }
author maintainer
#30 lore raw

PATCH 30/101 staging: comedi: ni_labpc: fix possible NULL deref during detach

In reply to Greg Kroah-Hartman

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

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

From: Ian Abbott <[email protected]>

commit 922b67c1ac53014d80649a961a2fde700cd065d8 upstream.

labpc_common_detach() is called by the comedi core to clean up if either labpc_attach() (including the one in the "ni_labpc_cs" module) or labpc_attach_pci() returns an error. It assumes the thisboard macro (expanding to ((struct labpc_board_struct *)dev->board_ptr)) is non-null. This is a valid assumption if labpc_attach() fails, but not if labpc_attach_pci() fails, leading to a possible NULL pointer dereference.

Check thisboard at the top of labpc_common_detach() and return early if it is NULL. This is okay because the only other thing that could have been allocated is dev->private and that is freed by the comedi core, not by this function.

---
 drivers/staging/comedi/drivers/ni_labpc.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/staging/comedi/drivers/ni_labpc.c +2 -0
@@ -809,6 +809,8 @@ static int labpc_find_device(struct come
 
 void labpc_common_detach(struct comedi_device *dev)
 {
+	if (!thisboard)
+		return;
 	if (dev->subdevices)
 		subdev_8255_cleanup(dev, dev->subdevices + 2);
 #ifdef CONFIG_ISA_DMA_API
author maintainer
#31 lore raw

PATCH 31/101 staging: comedi: amplc_dio200: fix possible NULL deref during detach

In reply to Greg Kroah-Hartman

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

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

From: Ian Abbott <[email protected]>

commit dfb2540e91e1f63765bc3ff497ad0b714d774261 upstream.

dio200_detach() is called by the comedi core to clean up if either dio200_attach() or dio200_attach_pci() return an error. It assigns thisboard to the return value of comedi_board(dev) and assumes it is non-null. In the case of a previous call to dio200_attach() it won't be NULL because the comedi core will have pointed it to one of the elements of dio200_boards[], but in the case of a previous call to dio200_attach_pci() it could be NULL, leading to a null pointer dereference.

Check that thisboard is valid at the top of dio200_detach() and return early if it is NULL. This is okay because the only other thing that could have been allocated is dev->private and that is freed by the comedi core, not by this function.

---
 drivers/staging/comedi/drivers/amplc_dio200.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/staging/comedi/drivers/amplc_dio200.c +2 -0
@@ -1429,6 +1429,8 @@ static void dio200_detach(struct comedi_
 	const struct dio200_layout_struct *layout;
 	unsigned n;
 
+	if (!thisboard)
+		return;
 	if (dev->irq)
 		free_irq(dev->irq, dev);
 	if (dev->subdevices) {
author maintainer
#32 lore raw

PATCH 32/101 staging: comedi: amplc_pc263: fix possible NULL deref during detach

In reply to Greg Kroah-Hartman

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

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

From: Ian Abbott <[email protected]>

commit 1d1171ffda585c1cab7bd7cf4bd8f8fd5923fb4a upstream.

pc263_detach() is called by the comedi core to clean up if either pc263_attach() or pc263_attach_pci() returns an error. It sets thisboard to the return value of comedi_board(dev) and assumes it is non-null. This is a valid assumption if pc263_attach() fails, but not if pc263_attach_pci() fails, leading to a possible NULL pointer dereference.

Check thisboard at the top of pc263_detach() and return early if it is NULL. This is okay because no other resources need cleaning up in this case.

---
 drivers/staging/comedi/drivers/amplc_pc263.c |    3 +++
 1 file changed, 3 insertions(+)
drivers/staging/comedi/drivers/amplc_pc263.c +3 -0
@@ -310,8 +310,11 @@ static int __devinit pc263_attach_pci(st
 
 static void pc263_detach(struct comedi_device *dev)
 {
+	const struct pc263_board *thisboard = comedi_board(dev);
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 
+	if (!thisboard)
+		return;
 	if (pcidev) {
 		if (dev->iobase)
 			comedi_pci_disable(pcidev);
author maintainer
#33 lore raw

PATCH 33/101 staging: comedi: amplc_pc236: fix invalid register access during detach

In reply to Greg Kroah-Hartman

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

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

From: Ian Abbott <[email protected]>

commit aaeb61a97b7159ebe30b18a422d04eeabfa8790b upstream.

pc236_detach() is called by the comedi core if it attempted to attach a device and failed. pc236_detach() calls pc236_intr_disable() if the comedi device private data pointer (devpriv) is non-null. This test is insufficient as pc236_intr_disable() accesses hardware registers and the attach routine may have failed before it has saved their I/O base addresses.

Fix it by checking dev->iobase is non-zero before calling pc236_intr_disable() as that means the I/O base addresses have been saved and the hardware registers can be accessed. It also implies the comedi device private data pointer is valid, so there is no need to check it.

---
 drivers/staging/comedi/drivers/amplc_pc236.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/staging/comedi/drivers/amplc_pc236.c +1 -2
@@ -577,10 +577,9 @@ static int __devinit pc236_attach_pci(st
 
 static void pc236_detach(struct comedi_device *dev)
 {
-	struct pc236_private *devpriv = dev->private;
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 
-	if (devpriv)
+	if (dev->iobase)
 		pc236_intr_disable(dev);
 	if (dev->irq)
 		free_irq(dev->irq, dev);
author maintainer
#34 lore raw

PATCH 34/101 staging: comedi: amplc_pc236: fix possible NULL deref during detach

In reply to Greg Kroah-Hartman

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

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

From: Ian Abbott <[email protected]>

commit 2db012bd40b889d8e5483d3daa07af04c4c109d8 upstream.

pc236_detach() is called by the comedi core to clean up if either pc236_attach() or pc236_attach_pci() returns an error. It sets thisboard to the return value of comedi_board(dev) and assumes it is non-null. This is a valid assumption if pc236_attach() fails, but not if pc236_attach_pci() fails, leading to a possible NULL pointer dereference.

Check thisboard at the top of pc236_detach() and return early if it is NULL. This is okay because the only other thing that could have been allocated is dev->private and that is freed by the comedi core, not by this function.

---
 drivers/staging/comedi/drivers/amplc_pc236.c |    3 +++
 1 file changed, 3 insertions(+)
drivers/staging/comedi/drivers/amplc_pc236.c +3 -0
@@ -577,8 +577,11 @@ static int __devinit pc236_attach_pci(st
 
 static void pc236_detach(struct comedi_device *dev)
 {
+	const struct pc236_board *thisboard = comedi_board(dev);
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 
+	if (!thisboard)
+		return;
 	if (dev->iobase)
 		pc236_intr_disable(dev);
 	if (dev->irq)
author maintainer
#35 lore raw

PATCH 35/101 extcon: Unregister compat class at module unload to fix oops

In reply to Greg Kroah-Hartman

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

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

From: Peter Huewe <[email protected]>

commit 0dc77b6dabec8fd298392018cc0de5214af2dc43 upstream.

If you compile extcon with CONFIG_ANDROID and then load and unload the module you get a simple oops as the driver does not unregister its compat class and thus cannot register it again.

Full trace:

root@(none):~# modprobe extcon_class
root@(none):~# rmmod extcon_class
root@(none):~# modprobe extcon_class
------------[ cut here ]------------
WARNING: at fs/sysfs/dir.c:536 sysfs_add_one+0xde/0x100()
sysfs: cannot create duplicate filename '/class/switch'
Modules linked in: extcon_class(+) [last unloaded: extcon_class]
Call Trace:
9f451a00:  [<602a58bc>] printk+0x0/0xa8
9f451a18:  [<60039b43>] warn_slowpath_common+0x93/0xd0
9f451a28:  [<6012c6de>] sysfs_add_one+0xde/0x100
9f451a50:  [<601d3d90>] strcat+0x0/0x40
9f451a68:  [<60039cdc>] warn_slowpath_fmt+0x9c/0xa0
9f451a90:  [<6002fe32>] unblock_signals+0x0/0x84
9f451ab0:  [<60039c40>] warn_slowpath_fmt+0x0/0xa0
9f451ac0:  [<6002fe32>] unblock_signals+0x0/0x84
9f451ae8:  [<6012bd97>] sysfs_pathname.isra.10+0x57/0x70
9f451b00:  [<601d3d90>] strcat+0x0/0x40
9f451b18:  [<6012bd97>] sysfs_pathname.isra.10+0x57/0x70
9f451b48:  [<6012c6de>] sysfs_add_one+0xde/0x100
9f451b78:  [<6012c96f>] create_dir+0x8f/0x100
9f451bc0:  [<a0861000>] extcon_class_init+0x0/0x12 [extcon_class]
9f451bd8:  [<6012cda6>] sysfs_create_dir+0xa6/0x1c0
9f451be8:  [<601d89f1>] kvasprintf+0x81/0xa0
9f451bf8:  [<601cf0f0>] kobject_get+0x0/0x50
9f451c18:  [<601cf396>] kobject_add_internal+0x96/0x280
9f451c60:  [<a0861000>] extcon_class_init+0x0/0x12 [extcon_class]
9f451c78:  [<601cfb93>] kobject_add+0xd3/0x140
9f451cc0:  [<601cfac0>] kobject_add+0x0/0x140
9f451cd0:  [<6002fe32>] unblock_signals+0x0/0x84
9f451cf8:  [<6002fffc>] set_signals+0x29/0x3f
9f451d28:  [<600c1de1>] kmem_cache_alloc+0xe1/0x100
9f451d78:  [<601cffa0>] kobject_create_and_add+0x50/0xa0
9f451da8:  [<601fbe76>] class_compat_register+0x56/0x80
9f451dc8:  [<a085d118>] create_extcon_class+0x88/0xd0 [extcon_class]
9f451de8:  [<a0861010>] extcon_class_init+0x10/0x12 [extcon_class]
9f451df8:  [<600189a8>] do_one_initcall+0x48/0x1f0
9f451e20:  [<60061920>] blocking_notifier_call_chain+0x0/0x20
9f451e30:  [<60061920>] blocking_notifier_call_chain+0x0/0x20
9f451e58:  [<6007e3c3>] sys_init_module+0xa3/0x280
9f451e88:  [<6001e2ad>] handle_syscall+0x8d/0x90
9f451ea8:  [<60033370>] userspace+0x405/0x531
9f451ee8:  [<6001e380>] copy_chunk_to_user+0x0/0x40
9f451ef8:  [<6001e5cd>] do_op_one_page+0x14d/0x220
9f451fd8:  [<6001a355>] fork_handler+0x95/0xa0
---[ end trace dd512cc03fe1c367 ]---
------------[ cut here ]------------
WARNING: at lib/kobject.c:196 kobject_add_internal+0x26e/0x280()
kobject_add_internal failed for switch with -EEXIST, don't try to
register things with the same name in the same directory.
Modules linked in: extcon_class(+) [last unloaded: extcon_class]
Call Trace:
9f451ad0:  [<602a58bc>] printk+0x0/0xa8
9f451ae8:  [<60039b43>] warn_slowpath_common+0x93/0xd0
9f451af8:  [<601cf56e>] kobject_add_internal+0x26e/0x280
9f451b18:  [<601cf140>] kobject_put+0x0/0x70
9f451b20:  [<a0861000>] extcon_class_init+0x0/0x12 [extcon_class]
9f451b38:  [<60039cdc>] warn_slowpath_fmt+0x9c/0xa0
9f451b88:  [<60039c40>] warn_slowpath_fmt+0x0/0xa0
9f451bc0:  [<a0861000>] extcon_class_init+0x0/0x12 [extcon_class]
9f451bd8:  [<6012cda6>] sysfs_create_dir+0xa6/0x1c0
9f451be8:  [<601d89f1>] kvasprintf+0x81/0xa0
9f451bf8:  [<601cf0f0>] kobject_get+0x0/0x50
9f451c18:  [<601cf56e>] kobject_add_internal+0x26e/0x280
9f451c60:  [<a0861000>] extcon_class_init+0x0/0x12 [extcon_class]
9f451c78:  [<601cfb93>] kobject_add+0xd3/0x140
9f451cc0:  [<601cfac0>] kobject_add+0x0/0x140
9f451cd0:  [<6002fe32>] unblock_signals+0x0/0x84
9f451cf8:  [<6002fffc>] set_signals+0x29/0x3f
9f451d28:  [<600c1de1>] kmem_cache_alloc+0xe1/0x100
9f451d78:  [<601cffa0>] kobject_create_and_add+0x50/0xa0
9f451da8:  [<601fbe76>] class_compat_register+0x56/0x80
9f451dc8:  [<a085d118>] create_extcon_class+0x88/0xd0 [extcon_class]
9f451de8:  [<a0861010>] extcon_class_init+0x10/0x12 [extcon_class]
9f451df8:  [<600189a8>] do_one_initcall+0x48/0x1f0
9f451e20:  [<60061920>] blocking_notifier_call_chain+0x0/0x20
9f451e30:  [<60061920>] blocking_notifier_call_chain+0x0/0x20
9f451e58:  [<6007e3c3>] sys_init_module+0xa3/0x280
9f451e88:  [<6001e2ad>] handle_syscall+0x8d/0x90
9f451ea8:  [<60033370>] userspace+0x405/0x531
9f451ee8:  [<6001e380>] copy_chunk_to_user+0x0/0x40
9f451ef8:  [<6001e5cd>] do_op_one_page+0x14d/0x220
9f451fd8:  [<6001a355>] fork_handler+0x95/0xa0

---[ end trace dd512cc03fe1c368 ]---
kobject_create_and_add: kobject_add error: -17
------------[ cut here ]------------
WARNING: at drivers/extcon/extcon_class.c:545
create_extcon_class+0xbc/0xd0 [extcon_class]()
cannot allocate
Modules linked in: extcon_class(+) [last unloaded: extcon_class]
Call Trace:
9f451c80:  [<602a58bc>] printk+0x0/0xa8
9f451c98:  [<60039b43>] warn_slowpath_common+0x93/0xd0
9f451ca0:  [<6002fe32>] unblock_signals+0x0/0x84
9f451ca8:  [<a085d14c>] create_extcon_class+0xbc/0xd0 [extcon_class]
9f451cd0:  [<a0861000>] extcon_class_init+0x0/0x12 [extcon_class]
9f451ce8:  [<60039cdc>] warn_slowpath_fmt+0x9c/0xa0
9f451d20:  [<6002fe32>] unblock_signals+0x0/0x84
9f451d28:  [<60039c40>] warn_slowpath_fmt+0x0/0xa0
9f451d48:  [<6002fffc>] set_signals+0x29/0x3f
9f451d58:  [<601cf172>] kobject_put+0x32/0x70
9f451d78:  [<600c22c3>] kfree+0xb3/0x100
9f451da8:  [<601fbe9a>] class_compat_register+0x7a/0x80
9f451dc8:  [<a085d14c>] create_extcon_class+0xbc/0xd0 [extcon_class]
9f451de8:  [<a0861010>] extcon_class_init+0x10/0x12 [extcon_class]
9f451df8:  [<600189a8>] do_one_initcall+0x48/0x1f0
9f451e20:  [<60061920>] blocking_notifier_call_chain+0x0/0x20
9f451e30:  [<60061920>] blocking_notifier_call_chain+0x0/0x20
9f451e58:  [<6007e3c3>] sys_init_module+0xa3/0x280
9f451e88:  [<6001e2ad>] handle_syscall+0x8d/0x90
9f451ea8:  [<60033370>] userspace+0x405/0x531
9f451ee8:  [<6001e380>] copy_chunk_to_user+0x0/0x40
9f451ef8:  [<6001e5cd>] do_op_one_page+0x14d/0x220
9f451fd8:  [<6001a355>] fork_handler+0x95/0xa0

---[ end trace dd512cc03fe1c369 ]---

FATAL: Error inserting extcon_class (/lib/modules/3.6.0-rc6-00178-g811315f/kernel/drivers/extcon/extcon_class.ko):
Cannot allocate memory

This patch fixes this.

---
 drivers/extcon/extcon_class.c |    3 +++
 1 file changed, 3 insertions(+)
drivers/extcon/extcon_class.c +3 -0
@@ -821,6 +821,9 @@ module_init(extcon_class_init);
 
 static void __exit extcon_class_exit(void)
 {
+#if defined(CONFIG_ANDROID)
+	class_compat_unregister(switch_class);
+#endif
 	class_destroy(extcon_class);
 }
 module_exit(extcon_class_exit);
author maintainer
#36 lore raw

PATCH 36/101 extcon: unregister compat link on cleanup

In reply to Greg Kroah-Hartman

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

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

From: Peter Huewe <[email protected]>

commit 824a1bc045cef278aec15bef35d8d0b59ce77856 upstream.

Since extcon registers this compat link at device registration (extcon_dev_register), we should probably remove them at deregistration/cleanup.

---
 drivers/extcon/extcon_class.c |    4 ++++
 1 file changed, 4 insertions(+)
drivers/extcon/extcon_class.c +4 -0
@@ -575,6 +575,10 @@ static void extcon_cleanup(struct extcon
 			kfree(edev->cables);
 		}
 
+#if defined(CONFIG_ANDROID)
+		if (switch_class)
+			class_compat_remove_link(switch_class, edev->dev, NULL);
+#endif
 		device_unregister(edev->dev);
 		put_device(edev->dev);
 	}
author maintainer
#37 lore raw

PATCH 37/101 Drivers: hv: Cleanup error handling in vmbus_open()

In reply to Greg Kroah-Hartman

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

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

From: "K. Y. Srinivasan" <[email protected]>

commit 1392550240aaa72ce3a094a38bd23525cd67ce60 upstream.

Fix a memory leak in the error handling path in the function vmbus_open().

---
 drivers/hv/channel.c |   24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)
drivers/hv/channel.c +13 -11
@@ -146,14 +146,14 @@ int vmbus_open(struct vmbus_channel *new
 
 	if (ret != 0) {
 		err = ret;
-		goto errorout;
+		goto error0;
 	}
 
 	ret = hv_ringbuffer_init(
 		&newchannel->inbound, in, recv_ringbuffer_size);
 	if (ret != 0) {
 		err = ret;
-		goto errorout;
+		goto error0;
 	}
 
 
@@ -168,7 +168,7 @@ int vmbus_open(struct vmbus_channel *new
 
 	if (ret != 0) {
 		err = ret;
-		goto errorout;
+		goto error0;
 	}
 
 	/* Create and init the channel open message */
@@ -177,7 +177,7 @@ int vmbus_open(struct vmbus_channel *new
 			   GFP_KERNEL);
 	if (!open_info) {
 		err = -ENOMEM;
-		goto errorout;
+		goto error0;
 	}
 
 	init_completion(&open_info->waitevent);
@@ -193,7 +193,7 @@ int vmbus_open(struct vmbus_channel *new
 
 	if (userdatalen > MAX_USER_DEFINED_BYTES) {
 		err = -EINVAL;
-		goto errorout;
+		goto error0;
 	}
 
 	if (userdatalen)
@@ -208,19 +208,18 @@ int vmbus_open(struct vmbus_channel *new
 			       sizeof(struct vmbus_channel_open_channel));
 
 	if (ret != 0)
-		goto cleanup;
+		goto error1;
 
 	t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ);
 	if (t == 0) {
 		err = -ETIMEDOUT;
-		goto errorout;
+		goto error1;
 	}
 
 
 	if (open_info->response.open_result.status)
 		err = open_info->response.open_result.status;
 
-cleanup:
 	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
 	list_del(&open_info->msglistentry);
 	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
@@ -228,9 +227,12 @@ cleanup:
 	kfree(open_info);
 	return err;
 
-errorout:
-	hv_ringbuffer_cleanup(&newchannel->outbound);
-	hv_ringbuffer_cleanup(&newchannel->inbound);
+error1:
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+	list_del(&open_info->msglistentry);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
+error0:
 	free_pages((unsigned long)out,
 		get_order(send_ringbuffer_size + recv_ringbuffer_size));
 	kfree(open_info);
author maintainer
#38 lore raw

PATCH 38/101 ehci: fix Lucid nohandoff pci quirk to be more generic with BIOS versions

In reply to Greg Kroah-Hartman

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

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

From: Anisse Astier <[email protected]>

commit c323dc023b9501e5d09582ec7efd1d40a9001d99 upstream.

BIOS vendors keep changing the BIOS versions. Only match the beginning of the string to match all Lucid tablets with board name M11JB.

---
 drivers/usb/host/pci-quirks.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/host/pci-quirks.c +1 -1
@@ -545,7 +545,7 @@ static const struct dmi_system_id __devi
 		/*  Pegatron Lucid (Ordissimo AIRIS) */
 		.matches = {
 			DMI_MATCH(DMI_BOARD_NAME, "M11JB"),
-			DMI_MATCH(DMI_BIOS_VERSION, "Lucid-GE-133"),
+			DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"),
 		},
 	},
 	{ }
author maintainer
#39 lore raw

PATCH 39/101 ehci: Add yet-another Lucid nohandoff pci quirk

In reply to Greg Kroah-Hartman

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

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

From: Anisse Astier <[email protected]>

commit 8daf8b6086f9d575200cd0aa3797e26137255609 upstream.

Board name changed on another shipping Lucid tablet.

---
 drivers/usb/host/pci-quirks.c |    7 +++++++
 1 file changed, 7 insertions(+)
drivers/usb/host/pci-quirks.c +7 -0
@@ -548,6 +548,13 @@ static const struct dmi_system_id __devi
 			DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"),
 		},
 	},
+	{
+		/*  Pegatron Lucid (Ordissimo) */
+		.matches = {
+			DMI_MATCH(DMI_BOARD_NAME, "Ordissimo"),
+			DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"),
+		},
+	},
 	{ }
 };
 
author maintainer
#40 lore raw

PATCH 40/101 usb-storage: add unusual_devs entry for Casio EX-N1 digital camera

In reply to Greg Kroah-Hartman

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

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

From: Michael Shigorin <[email protected]>

commit d7870af7e2e3a91b462075ec1ca669b482215187 upstream.

This commit sets removable subclass for Casio EX-N1 digital camera.

The patch has been tested within an ALT Linux kernel:
http://git.altlinux.org/people/led/packages/?p=kernel-image-3.0.git;a=commitdiff;h=c0fd891836e89fe0c93a4d536a59216d90e4e3e7

See also https://bugzilla.kernel.org/show_bug.cgi?id=49221

---
 drivers/usb/storage/unusual_devs.h |    6 ++++++
 1 file changed, 6 insertions(+)
drivers/usb/storage/unusual_devs.h +6 -0
@@ -1004,6 +1004,12 @@ UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9
 		USB_SC_8070, USB_PR_CB, NULL,
 		US_FL_NEED_OVERRIDE | US_FL_FIX_INQUIRY ),
 
+/* Submitted by Oleksandr Chumachenko <[email protected]> */
+UNUSUAL_DEV( 0x07cf, 0x1167, 0x0100, 0x0100,
+		"Casio",
+		"EX-N1 DigitalCamera",
+		USB_SC_8070, USB_PR_DEVICE, NULL, 0),
+
 /* Submitted by Hartmut Wahl <[email protected]>*/
 UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001,
 		"Samsung",
author maintainer
#41 lore raw

PATCH 41/101 USB: usb-wwan: fix multiple memory leaks in error paths

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 b8f0e82044c9ba40e92340c8a6d47d6bd6d819bc upstream.

Fix port-data memory leak in usb-serial probe error path by moving port data allocation to port_probe.

Since commit a1028f0abf ("usb: usb_wwan: replace release and disconnect with a port_remove hook") port data is deallocated in port_remove. This leaves a possibility for memory leaks if usb-serial probe fails after attach but before the port in question has been successfully registered.

Note that this patch also fixes two additional memory leaks in the error path of attach should port initialisation fail for any port as the urbs were never freed and neither was the data of any of the successfully initialised ports.

Compile-only tested.

---
 drivers/usb/serial/ipw.c      |    2 
 drivers/usb/serial/option.c   |    2 
 drivers/usb/serial/qcserial.c |    2 
 drivers/usb/serial/usb-wwan.h |    2 
 drivers/usb/serial/usb_wwan.c |  136 +++++++++++++++++-------------------------
 5 files changed, 60 insertions(+), 84 deletions(-)
drivers/usb/serial/ipw.c +1 -1
@@ -311,8 +311,8 @@ static struct usb_serial_driver ipw_devi
 	.open =			ipw_open,
 	.close =		ipw_close,
 	.probe =		ipw_probe,
-	.attach =		usb_wwan_startup,
 	.release =		ipw_release,
+	.port_probe =		usb_wwan_port_probe,
 	.port_remove =		usb_wwan_port_remove,
 	.dtr_rts =		ipw_dtr_rts,
 	.write =		usb_wwan_write,
drivers/usb/serial/option.c +1 -1
@@ -1288,8 +1288,8 @@ static struct usb_serial_driver option_1
 	.tiocmget          = usb_wwan_tiocmget,
 	.tiocmset          = usb_wwan_tiocmset,
 	.ioctl             = usb_wwan_ioctl,
-	.attach            = usb_wwan_startup,
 	.release           = option_release,
+	.port_probe        = usb_wwan_port_probe,
 	.port_remove	   = usb_wwan_port_remove,
 	.read_int_callback = option_instat_callback,
 #ifdef CONFIG_PM
drivers/usb/serial/qcserial.c +1 -1
@@ -287,8 +287,8 @@ static struct usb_serial_driver qcdevice
 	.write		     = usb_wwan_write,
 	.write_room	     = usb_wwan_write_room,
 	.chars_in_buffer     = usb_wwan_chars_in_buffer,
-	.attach		     = usb_wwan_startup,
 	.release	     = qc_release,
+	.port_probe          = usb_wwan_port_probe,
 	.port_remove	     = usb_wwan_port_remove,
 #ifdef CONFIG_PM
 	.suspend	     = usb_wwan_suspend,
drivers/usb/serial/usb-wwan.h +1 -1
@@ -8,7 +8,7 @@
 extern void usb_wwan_dtr_rts(struct usb_serial_port *port, int on);
 extern int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port);
 extern void usb_wwan_close(struct usb_serial_port *port);
-extern int usb_wwan_startup(struct usb_serial *serial);
+extern int usb_wwan_port_probe(struct usb_serial_port *port);
 extern int usb_wwan_port_remove(struct usb_serial_port *port);
 extern int usb_wwan_write_room(struct tty_struct *tty);
 extern void usb_wwan_set_termios(struct tty_struct *tty,
drivers/usb/serial/usb_wwan.c +56 -80

166 lines not on this page · raw message

author maintainer
#42 lore raw

PATCH 42/101 usb hub: send clear_tt_buffer_complete events when canceling TT clear work

In reply to Greg Kroah-Hartman

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

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

From: Octavian Purdila <[email protected]>

commit 3b6054da68f9b0d5ed6a7ed0f42a79e61904352c upstream.

There is a race condition in the USB hub code with regard to handling TT clear requests that can get the HCD driver in a deadlock. Usually when an TT clear request is scheduled it will be executed immediately:

<7>[    6.077583] usb 2-1.3: unlink qh1-0e01/f4d4db00 start 0 [1/2 us]
<3>[    6.078041] usb 2-1: clear tt buffer port 3, a3 ep2 t04048d82
<7>[    6.078299] hub_tt_work:731
<7>[    9.309089] usb 2-1.5: link qh1-0e01/f4d506c0 start 0 [1/2 us]
<7>[    9.324526] ehci_hcd 0000:00:1d.0: reused qh f4d4db00 schedule
<7>[    9.324539] usb 2-1.3: link qh1-0e01/f4d4db00 start 0 [1/2 us]
<7>[    9.341530] usb 1-1.1: link qh4-0e01/f397aec0 start 2 [1/2 us]
<7>[   10.116159] usb 2-1.3: unlink qh1-0e01/f4d4db00 start 0 [1/2 us]
<3>[   10.116459] usb 2-1: clear tt buffer port 3, a3 ep2 t04048d82
<7>[   10.116537] hub_tt_work:731

However, if a suspend operation is triggered before hub_tt_work is scheduled, hub_quiesce will cancel the work without notifying the HCD driver:

<3>[   35.033941] usb 2-1: clear tt buffer port 3, a3 ep2 t04048d80
<5>[   35.034022] sd 0:0:0:0: [sda] Stopping disk
<7>[   35.034039] hub 2-1:1.0: hub_suspend
<7>[   35.034067] usb 2-1: unlink qh256-0001/f3b1ab00 start 1 [1/0 us]
<7>[   35.035085] hub 1-0:1.0: hub_suspend
<7>[   35.035102] usb usb1: bus suspend, wakeup 0
<7>[   35.035106] ehci_hcd 0000:00:1a.0: suspend root hub
<7>[   35.035298] hub 2-0:1.0: hub_suspend
<7>[   35.035313] usb usb2: bus suspend, wakeup 0
<7>[   35.035315] ehci_hcd 0000:00:1d.0: suspend root hub
<6>[   35.250017] PM: suspend of devices complete after 216.979 msecs
<6>[   35.250822] PM: late suspend of devices complete after 0.799 msecs
<7>[   35.252343] ehci_hcd 0000:00:1d.0: wakeup: 1
<7>[   35.262923] ehci_hcd 0000:00:1d.0: --> PCI D3hot
<7>[   35.263302] ehci_hcd 0000:00:1a.0: wakeup: 1
<7>[   35.273912] ehci_hcd 0000:00:1a.0: --> PCI D3hot
<6>[   35.274254] PM: noirq suspend of devices complete after 23.442 msecs
<6>[   35.274975] ACPI: Preparing to enter system sleep state S3
<6>[   35.292666] PM: Saving platform NVS memory
<7>[   35.295030] Disabling non-boot CPUs ...
<6>[   35.297351] CPU 1 is now offline
<6>[   35.300345] CPU 2 is now offline
<6>[   35.303929] CPU 3 is now offline
<7>[   35.303931] lockdep: fixing up alternatives.
<6>[   35.304825] Extended CMOS year: 2000

When the device will resume the EHCI driver will get stuck in ehci_endpoint_disable waiting for the tt_clearing flag to reset:

<0>[   47.610967] usb 2-1.3: **** DPM device timeout ****
<7>[   47.610972]  f2f11c60 00000092 f2f11c0c c10624a5 00000003 f4c6e880 c1c8a4c0 c1c8a4c0
<7>[   47.610983]  15c55698 0000000b f56b34c0 f2a45b70 f4c6e880 00000082 f2a4602c f2f11c30
<7>[   47.610993]  c10787f8 f4cac000 f2a45b70 00000000 f4cac010 f2f11c58 00000046 00000001
<7>[   47.611004] Call Trace:
<7>[   47.611006]  [<c10624a5>] ? sched_clock_cpu+0xf5/0x160
<7>[   47.611019]  [<c10787f8>] ? lock_release_holdtime.part.22+0x88/0xf0
<7>[   47.611026]  [<c103ed46>] ? lock_timer_base.isra.35+0x26/0x50
<7>[   47.611034]  [<c17592d3>] ? schedule_timeout+0x133/0x290
<7>[   47.611044]  [<c175b43e>] schedule+0x1e/0x50
<7>[   47.611051]  [<c17592d8>] schedule_timeout+0x138/0x290
<7>[   47.611057]  [<c10624a5>] ? sched_clock_cpu+0xf5/0x160
<7>[   47.611063]  [<c103e560>] ? usleep_range+0x40/0x40
<7>[   47.611070]  [<c1759445>] schedule_timeout_uninterruptible+0x15/0x20
<7>[   47.611077]  [<c14935f4>] ehci_endpoint_disable+0x64/0x160
<7>[   47.611084]  [<c147d1ee>] ? usb_hcd_flush_endpoint+0x10e/0x1d0
<7>[   47.611092]  [<c1165663>] ? sysfs_add_file+0x13/0x20
<7>[   47.611100]  [<c147d5a9>] usb_hcd_disable_endpoint+0x29/0x40
<7>[   47.611107]  [<c147fafc>] usb_disable_endpoint+0x5c/0x80
<7>[   47.611111]  [<c147fb57>] usb_disable_interface+0x37/0x50
<7>[   47.611116]  [<c1477650>] usb_reset_and_verify_device+0x4b0/0x640
<7>[   47.611122]  [<c1474665>] ? hub_port_status+0xb5/0x100
<7>[   47.611129]  [<c147a975>] usb_port_resume+0xd5/0x220
<7>[   47.611136]  [<c148877f>] generic_resume+0xf/0x30
<7>[   47.611142]  [<c14821a3>] usb_resume+0x133/0x180
<7>[   47.611147]  [<c1473b10>] ? usb_dev_thaw+0x10/0x10
<7>[   47.611152]  [<c1473b1d>] usb_dev_resume+0xd/0x10
<7>[   47.611157]  [<c13baa60>] dpm_run_callback+0x40/0xb0
<7>[   47.611164]  [<c13bdb03>] ? pm_runtime_enable+0x43/0x70
<7>[   47.611171]  [<c13bafc6>] device_resume+0x1a6/0x2c0
<7>[   47.611177]  [<c13ba940>] ? dpm_show_time+0xe0/0xe0
<7>[   47.611183]  [<c13bb0f9>] async_resume+0x19/0x40
<7>[   47.611189]  [<c10580c4>] async_run_entry_fn+0x64/0x160
<7>[   47.611196]  [<c104a244>] ? process_one_work+0x104/0x480
<7>[   47.611203]  [<c104a24c>] ? process_one_work+0x10c/0x480
<7>[   47.611209]  [<c104a2c0>] process_one_work+0x180/0x480
<7>[   47.611215]  [<c104a244>] ? process_one_work+0x104/0x480
<7>[   47.611220]  [<c1058060>] ? async_schedule+0x10/0x10
<7>[   47.611226]  [<c104c15c>] worker_thread+0x11c/0x2f0
<7>[   47.611233]  [<c104c040>] ? manage_workers.isra.27+0x1f0/0x1f0
<7>[   47.611239]  [<c10507f8>] kthread+0x78/0x80
<7>[   47.611244]  [<c1750000>] ? timer_cpu_notify+0xd6/0x20d
<7>[   47.611253]  [<c1050780>] ? __init_kthread_worker+0x60/0x60
<7>[   47.611258]  [<c176357e>] kernel_thread_helper+0x6/0xd
<7>[   47.611283] ------------[ cut here ]------------

This patch changes hub_quiesce behavior to flush the TT clear work instead of canceling it, to make sure that no TT clear request remains uncompleted before suspend.

---
 drivers/usb/core/hub.c |    7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/usb/core/hub.c +5 -2
@@ -730,13 +730,16 @@ static void hub_tt_work(struct work_stru
 	int			limit = 100;
 
 	spin_lock_irqsave (&hub->tt.lock, flags);
-	while (--limit && !list_empty (&hub->tt.clear_list)) {
+	while (!list_empty(&hub->tt.clear_list)) {
 		struct list_head	*next;
 		struct usb_tt_clear	*clear;
 		struct usb_device	*hdev = hub->hdev;
 		const struct hc_driver	*drv;
 		int			status;
 
+		if (!hub->quiescing && --limit < 0)
+			break;
+
 		next = hub->tt.clear_list.next;
 		clear = list_entry (next, struct usb_tt_clear, clear_list);
 		list_del (&clear->clear_list);
@@ -1201,7 +1204,7 @@ static void hub_quiesce(struct usb_hub *
 	if (hub->has_indicators)
 		cancel_delayed_work_sync(&hub->leds);
 	if (hub->tt.hub)
-		cancel_work_sync(&hub->tt.clear_work);
+		flush_work_sync(&hub->tt.clear_work);
 }
 
 /* caller has locked the hub device */
author maintainer
#43 lore raw

PATCH 43/101 USB: ch341: 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 456c5be56ed070a4d883c60b587bcc1c97a8cf3e upstream.

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

Note that this driver has never even bothered to try to deallocate it's port data...

Compile-only tested.

---
 drivers/usb/serial/ch341.c |   23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)
drivers/usb/serial/ch341.c +16 -7
@@ -241,13 +241,11 @@ out:	kfree(buffer);
 	return r;
 }
 
-/* allocate private data */
-static int ch341_attach(struct usb_serial *serial)
+static int ch341_port_probe(struct usb_serial_port *port)
 {
 	struct ch341_private *priv;
 	int r;
 
-	/* private data */
 	priv = kzalloc(sizeof(struct ch341_private), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
@@ -257,17 +255,27 @@ static int ch341_attach(struct usb_seria
 	priv->baud_rate = DEFAULT_BAUD_RATE;
 	priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
 
-	r = ch341_configure(serial->dev, priv);
+	r = ch341_configure(port->serial->dev, priv);
 	if (r < 0)
 		goto error;
 
-	usb_set_serial_port_data(serial->port[0], priv);
+	usb_set_serial_port_data(port, priv);
 	return 0;
 
 error:	kfree(priv);
 	return r;
 }
 
+static int ch341_port_remove(struct usb_serial_port *port)
+{
+	struct ch341_private *priv;
+
+	priv = usb_get_serial_port_data(port);
+	kfree(priv);
+
+	return 0;
+}
+
 static int ch341_carrier_raised(struct usb_serial_port *port)
 {
 	struct ch341_private *priv = usb_get_serial_port_data(port);
@@ -303,7 +311,7 @@ static void ch341_close(struct usb_seria
 static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
 	struct usb_serial *serial = port->serial;
-	struct ch341_private *priv = usb_get_serial_port_data(serial->port[0]);
+	struct ch341_private *priv = usb_get_serial_port_data(port);
 	int r;
 
 	priv->baud_rate = DEFAULT_BAUD_RATE;
@@ -606,7 +614,8 @@ static struct usb_serial_driver ch341_de
 	.tiocmget          = ch341_tiocmget,
 	.tiocmset          = ch341_tiocmset,
 	.read_int_callback = ch341_read_int_callback,
-	.attach            = ch341_attach,
+	.port_probe        = ch341_port_probe,
+	.port_remove       = ch341_port_remove,
 	.reset_resume      = ch341_reset_resume,
 };
 
author maintainer
#44 lore raw

PATCH 44/101 USB: digi_acceleport: 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 fb44ff854e148bc5c5982dad32da98b7a0989d2d 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.

Note that the oob port is never registered as a port device and should thus be handled in attach and release.

Compile-only tested.

---
 drivers/usb/serial/digi_acceleport.c |  117 ++++++++++++++++++++---------------
 1 file changed, 67 insertions(+), 50 deletions(-)
drivers/usb/serial/digi_acceleport.c +67 -50
@@ -244,6 +244,8 @@ static int digi_startup_device(struct us
 static int digi_startup(struct usb_serial *serial);
 static void digi_disconnect(struct usb_serial *serial);
 static void digi_release(struct usb_serial *serial);
+static int digi_port_probe(struct usb_serial_port *port);
+static int digi_port_remove(struct usb_serial_port *port);
 static void digi_read_bulk_callback(struct urb *urb);
 static int digi_read_inb_callback(struct urb *urb);
 static int digi_read_oob_callback(struct urb *urb);
@@ -298,6 +300,8 @@ static struct usb_serial_driver digi_acc
 	.attach =			digi_startup,
 	.disconnect =			digi_disconnect,
 	.release =			digi_release,
+	.port_probe =			digi_port_probe,
+	.port_remove =			digi_port_remove,
 };
 
 static struct usb_serial_driver digi_acceleport_4_device = {
@@ -324,6 +328,8 @@ static struct usb_serial_driver digi_acc
 	.attach =			digi_startup,
 	.disconnect =			digi_disconnect,
 	.release =			digi_release,
+	.port_probe =			digi_port_probe,
+	.port_remove =			digi_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
@@ -1237,59 +1243,50 @@ static int digi_startup_device(struct us
 	return ret;
 }
 
+static int digi_port_init(struct usb_serial_port *port, unsigned port_num)
+{
+	struct digi_port *priv;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	spin_lock_init(&priv->dp_port_lock);
+	priv->dp_port_num = port_num;
+	init_waitqueue_head(&priv->dp_modem_change_wait);
+	init_waitqueue_head(&priv->dp_transmit_idle_wait);
+	init_waitqueue_head(&priv->dp_flush_wait);
+	init_waitqueue_head(&priv->dp_close_wait);
+	INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock);
+	priv->dp_port = port;
+
+	init_waitqueue_head(&port->write_wait);
+
+	usb_set_serial_port_data(port, priv);
+
+	return 0;
+}
 
 static int digi_startup(struct usb_serial *serial)
 {
-
-	int i;
-	struct digi_port *priv;
 	struct digi_serial *serial_priv;
+	int ret;
 
-	/* allocate the private data structures for all ports */
-	/* number of regular ports + 1 for the out-of-band port */
-	for (i = 0; i < serial->type->num_ports + 1; i++) {
-		/* allocate port private structure */
-		priv = kmalloc(sizeof(struct digi_port), GFP_KERNEL);
-		if (priv == NULL) {
-			while (--i >= 0)
-				kfree(usb_get_serial_port_data(serial->port[i]));
-			return 1;			/* error */
-		}
+	serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL);
+	if (!serial_priv)
+		return -ENOMEM;
 
-		/* initialize port private structure */
-		spin_lock_init(&priv->dp_port_lock);
-		priv->dp_port_num = i;
-		priv->dp_out_buf_len = 0;
-		priv->dp_write_urb_in_use = 0;
-		priv->dp_modem_signals = 0;
-		init_waitqueue_head(&priv->dp_modem_change_wait);
-		priv->dp_transmit_idle = 0;
-		init_waitqueue_head(&priv->dp_transmit_idle_wait);
-		priv->dp_throttled = 0;
-		priv->dp_throttle_restart = 0;
-		init_waitqueue_head(&priv->dp_flush_wait);
-		init_waitqueue_head(&priv->dp_close_wait);
-		INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock);
-		priv->dp_port = serial->port[i];
-		/* initialize write wait queue for this port */
-		init_waitqueue_head(&serial->port[i]->write_wait);
-
-		usb_set_serial_port_data(serial->port[i], priv);
-	}
-
-	/* allocate serial private structure */
-	serial_priv = kmalloc(sizeof(struct digi_serial), GFP_KERNEL);
-	if (serial_priv == NULL) {
-		for (i = 0; i < serial->type->num_ports + 1; i++)
-			kfree(usb_get_serial_port_data(serial->port[i]));
-		return 1;			/* error */
-	}
-
-	/* initialize serial private structure */
 	spin_lock_init(&serial_priv->ds_serial_lock);
 	serial_priv->ds_oob_port_num = serial->type->num_ports;
 	serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num];
-	serial_priv->ds_device_started = 0;
+
+	ret = digi_port_init(serial_priv->ds_oob_port,
+						serial_priv->ds_oob_port_num);
+	if (ret) {
+		kfree(serial_priv);
+		return ret;
+	}
+
 	usb_set_serial_data(serial, serial_priv);
 
 	return 0;
@@ -1310,15 +1307,35 @@ static void digi_disconnect(struct usb_s
 
 static void digi_release(struct usb_serial *serial)
 {
-	int i;
+	struct digi_serial *serial_priv;
+	struct digi_port *priv;
+
+	serial_priv = usb_get_serial_data(serial);
+
+	priv = usb_get_serial_port_data(serial_priv->ds_oob_port);
+	kfree(priv);
 
-	/* free the private data structures for all ports */
-	/* number of regular ports + 1 for the out-of-band port */
-	for (i = 0; i < serial->type->num_ports + 1; i++)
-		kfree(usb_get_serial_port_data(serial->port[i]));
-	kfree(usb_get_serial_data(serial));
+	kfree(serial_priv);
 }
 
+static int digi_port_probe(struct usb_serial_port *port)
+{
+	unsigned port_num;
+
+	port_num = port->number - port->serial->minor;
+
+	return digi_port_init(port, port_num);
+}
+
+static int digi_port_remove(struct usb_serial_port *port)
+{
+	struct digi_port *priv;
+
+	priv = usb_get_serial_port_data(port);
+	kfree(priv);
+
+	return 0;
+}
 
 static void digi_read_bulk_callback(struct urb *urb)
 {
author maintainer
#45 lore raw

PATCH 45/101 USB: ipw: fix interface-data memory leak in error path

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 a997448c89905b80aa4022f734f03685e733d711 upstream.

Move interface data allocation to attach so that it is deallocated should usb-serial probe fail.

---
 drivers/usb/serial/ipw.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/usb/serial/ipw.c +2 -3
@@ -209,8 +209,7 @@ static int ipw_open(struct tty_struct *t
 	return 0;
 }
 
-/* fake probe - only to allocate data structures */
-static int ipw_probe(struct usb_serial *serial, const struct usb_device_id *id)
+static int ipw_attach(struct usb_serial *serial)
 {
 	struct usb_wwan_intf_private *data;
 
@@ -310,7 +309,7 @@ static struct usb_serial_driver ipw_devi
 	.num_ports =		1,
 	.open =			ipw_open,
 	.close =		ipw_close,
-	.probe =		ipw_probe,
+	.attach =		ipw_attach,
 	.release =		ipw_release,
 	.port_probe =		usb_wwan_port_probe,
 	.port_remove =		usb_wwan_port_remove,
author maintainer
#46 lore raw

PATCH 46/101 USB: mct_u232: 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 a8f2ae7a3aa59079d7e7e1ddf5007f03532f458c 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.

Note that the write waitqueue was initialised but never used.

Compile-only tested.

---
 drivers/usb/serial/mct_u232.c |   45 +++++++++++++++++++++++-------------------
 1 file changed, 25 insertions(+), 20 deletions(-)
drivers/usb/serial/mct_u232.c +25 -20
@@ -51,7 +51,8 @@ static bool debug;
  * Function prototypes
  */
 static int  mct_u232_startup(struct usb_serial *serial);
-static void mct_u232_release(struct usb_serial *serial);
+static int  mct_u232_port_probe(struct usb_serial_port *port);
+static int  mct_u232_port_remove(struct usb_serial_port *remove);
 static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port);
 static void mct_u232_close(struct usb_serial_port *port);
 static void mct_u232_dtr_rts(struct usb_serial_port *port, int on);
@@ -101,7 +102,8 @@ static struct usb_serial_driver mct_u232
 	.tiocmget =	     mct_u232_tiocmget,
 	.tiocmset =	     mct_u232_tiocmset,
 	.attach =	     mct_u232_startup,
-	.release =	     mct_u232_release,
+	.port_probe =        mct_u232_port_probe,
+	.port_remove =       mct_u232_port_remove,
 	.ioctl =             mct_u232_ioctl,
 	.get_icount =        mct_u232_get_icount,
 };
@@ -392,18 +394,8 @@ static void mct_u232_msr_to_state(unsign
 
 static int mct_u232_startup(struct usb_serial *serial)
 {
-	struct mct_u232_private *priv;
 	struct usb_serial_port *port, *rport;
 
-	priv = kzalloc(sizeof(struct mct_u232_private), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-	spin_lock_init(&priv->lock);
-	init_waitqueue_head(&priv->msr_wait);
-	usb_set_serial_port_data(serial->port[0], priv);
-
-	init_waitqueue_head(&serial->port[0]->write_wait);
-
 	/* Puh, that's dirty */
 	port = serial->port[0];
 	rport = serial->port[1];
@@ -416,18 +408,31 @@ static int mct_u232_startup(struct usb_s
 	return 0;
 } /* mct_u232_startup */
 
+static int mct_u232_port_probe(struct usb_serial_port *port)
+{
+	struct mct_u232_private *priv;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
 
-static void mct_u232_release(struct usb_serial *serial)
+	spin_lock_init(&priv->lock);
+	init_waitqueue_head(&priv->msr_wait);
+
+	usb_set_serial_port_data(port, priv);
+
+	return 0;
+}
+
+static int mct_u232_port_remove(struct usb_serial_port *port)
 {
 	struct mct_u232_private *priv;
-	int i;
 
-	for (i = 0; i < serial->num_ports; ++i) {
-		/* My special items, the standard routines free my urbs */
-		priv = usb_get_serial_port_data(serial->port[i]);
-		kfree(priv);
-	}
-} /* mct_u232_release */
+	priv = usb_get_serial_port_data(port);
+	kfree(priv);
+
+	return 0;
+}
 
 static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
author maintainer
#47 lore raw

PATCH 47/101 USB: mct_u232: fix broken close

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 5260e458f5eff269a43e4f1e9c47186c57b88ddb upstream.

Make sure generic close is called at close.

The driver relies on the generic write implementation but did not call generic close.

Note that the call to kill the read urb is not redundant, as mct_u232 uses an interrupt urb from the second port as the read urb and that generic close therefore fails to kill it.

Compile-only tested.

---
 drivers/usb/serial/mct_u232.c |   14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)
drivers/usb/serial/mct_u232.c +8 -6
@@ -524,12 +524,14 @@ static void mct_u232_dtr_rts(struct usb_
 
 static void mct_u232_close(struct usb_serial_port *port)
 {
-	if (port->serial->dev) {
-		/* shutdown our urbs */
-		usb_kill_urb(port->write_urb);
-		usb_kill_urb(port->read_urb);
-		usb_kill_urb(port->interrupt_in_urb);
-	}
+	/*
+	 * Must kill the read urb as it is actually an interrupt urb, which
+	 * generic close thus fails to kill.
+	 */
+	usb_kill_urb(port->read_urb);
+	usb_kill_urb(port->interrupt_in_urb);
+
+	usb_serial_generic_close(port);
 } /* mct_u232_close */
 
 
author maintainer
#48 lore raw

PATCH 48/101 USB: option: fix interface-data memory leak in error path

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 c2dd4a8eac7821fed2c2d19e4607d0986b53b0fe upstream.

Move interface data allocation to attach so that it is deallocated should usb-serial probe fail.

Note that the usb device id is stored at probe so that it can be used in attach to determine send-setup blacklisting.

---
 drivers/usb/serial/option.c |   21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)
drivers/usb/serial/option.c +19 -2
@@ -47,6 +47,7 @@
 /* Function prototypes */
 static int  option_probe(struct usb_serial *serial,
 			const struct usb_device_id *id);
+static int option_attach(struct usb_serial *serial);
 static void option_release(struct usb_serial *serial);
 static int option_send_setup(struct usb_serial_port *port);
 static void option_instat_callback(struct urb *urb);
@@ -1288,6 +1289,7 @@ static struct usb_serial_driver option_1
 	.tiocmget          = usb_wwan_tiocmget,
 	.tiocmset          = usb_wwan_tiocmset,
 	.ioctl             = usb_wwan_ioctl,
+	.attach            = option_attach,
 	.release           = option_release,
 	.port_probe        = usb_wwan_port_probe,
 	.port_remove	   = usb_wwan_port_remove,
@@ -1337,8 +1339,6 @@ static bool is_blacklisted(const u8 ifnu
 static int option_probe(struct usb_serial *serial,
 			const struct usb_device_id *id)
 {
-	struct usb_wwan_intf_private *data;
-	struct option_private *priv;
 	struct usb_interface_descriptor *iface_desc =
 				&serial->interface->cur_altsetting->desc;
 	struct usb_device_descriptor *dev_desc = &serial->dev->descriptor;
@@ -1376,6 +1376,19 @@ static int option_probe(struct usb_seria
 		iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA)
 		return -ENODEV;
 
+	/* Store device id so we can use it during attach. */
+	usb_set_serial_data(serial, (void *)id);
+
+	return 0;
+}
+
+static int option_attach(struct usb_serial *serial)
+{
+	struct usb_interface_descriptor *iface_desc;
+	const struct usb_device_id *id;
+	struct usb_wwan_intf_private *data;
+	struct option_private *priv;
+
 	data = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
@@ -1386,6 +1399,10 @@ static int option_probe(struct usb_seria
 		return -ENOMEM;
 	}
 
+	/* Retrieve device id stored at probe. */
+	id = usb_get_serial_data(serial);
+	iface_desc = &serial->interface->cur_altsetting->desc;
+
 	priv->bInterfaceNumber = iface_desc->bInterfaceNumber;
 	data->private = priv;
 
author maintainer
#49 lore raw

PATCH 49/101 USB: keyspan: fix NULL-pointer dereferences and memory leaks

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 f79b2d0fe81eecb412dc48e87a119afc690da8e9 upstream.

Fix NULL-pointer dereference at release by moving port data allocation and deallocation to port_probe and port_remove.

Fix NULL-pointer dereference at disconnect by stopping port urbs at port_remove.

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

Note that this patch also fixes port and interface-data memory leaks in the error path of attach should port initialisation fail for any port.

Compile-only tested.

---
 drivers/usb/serial/keyspan.c |  183 ++++++++++++++++++++-----------------------
 drivers/usb/serial/keyspan.h |    8 +
 2 files changed, 96 insertions(+), 95 deletions(-)
drivers/usb/serial/keyspan.c +88 -95
@@ -1392,13 +1392,9 @@ static struct callbacks {
 	   data in device_details */
 static void keyspan_setup_urbs(struct usb_serial *serial)
 {
-	int				i, j;
 	struct keyspan_serial_private 	*s_priv;
 	const struct keyspan_device_details	*d_details;
-	struct usb_serial_port		*port;
-	struct keyspan_port_private	*p_priv;
 	struct callbacks		*cback;
-	int				endp;
 
 	s_priv = usb_get_serial_data(serial);
 	d_details = s_priv->device_details;
@@ -1422,45 +1418,6 @@ static void keyspan_setup_urbs(struct us
 		(serial, d_details->glocont_endpoint, USB_DIR_OUT,
 		 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
 		 cback->glocont_callback);
-
-	/* Setup endpoints for each port specific thing */
-	for (i = 0; i < d_details->num_ports; i++) {
-		port = serial->port[i];
-		p_priv = usb_get_serial_port_data(port);
-
-		/* Do indat endpoints first, once for each flip */
-		endp = d_details->indat_endpoints[i];
-		for (j = 0; j <= d_details->indat_endp_flip; ++j, ++endp) {
-			p_priv->in_urbs[j] = keyspan_setup_urb
-				(serial, endp, USB_DIR_IN, port,
-				 p_priv->in_buffer[j], 64,
-				 cback->indat_callback);
-		}
-		for (; j < 2; ++j)
-			p_priv->in_urbs[j] = NULL;
-
-		/* outdat endpoints also have flip */
-		endp = d_details->outdat_endpoints[i];
-		for (j = 0; j <= d_details->outdat_endp_flip; ++j, ++endp) {
-			p_priv->out_urbs[j] = keyspan_setup_urb
-				(serial, endp, USB_DIR_OUT, port,
-				 p_priv->out_buffer[j], 64,
-				 cback->outdat_callback);
-		}
-		for (; j < 2; ++j)
-			p_priv->out_urbs[j] = NULL;
-
-		/* inack endpoint */
-		p_priv->inack_urb = keyspan_setup_urb
-			(serial, d_details->inack_endpoints[i], USB_DIR_IN,
-			 port, p_priv->inack_buffer, 1, cback->inack_callback);
-
-		/* outcont endpoint */
-		p_priv->outcont_urb = keyspan_setup_urb
-			(serial, d_details->outcont_endpoints[i], USB_DIR_OUT,
-			 port, p_priv->outcont_buffer, 64,
-			 cback->outcont_callback);
-	}
 }
 
 /* usa19 function doesn't require prescaler */
@@ -2422,9 +2379,7 @@ static void keyspan_send_setup(struct us
 static int keyspan_startup(struct usb_serial *serial)
 {
 	int				i, err;
-	struct usb_serial_port		*port;
 	struct keyspan_serial_private 	*s_priv;
-	struct keyspan_port_private	*p_priv;
 	const struct keyspan_device_details	*d_details;
 
 	for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
@@ -2448,19 +2403,6 @@ static int keyspan_startup(struct usb_se
 	s_priv->device_details = d_details;
 	usb_set_serial_data(serial, s_priv);
 
-	/* Now setup per port private data */
-	for (i = 0; i < serial->num_ports; i++) {
-		port = serial->port[i];
-		p_priv = kzalloc(sizeof(struct keyspan_port_private),
-								GFP_KERNEL);
-		if (!p_priv) {
-			dbg("%s - kmalloc for keyspan_port_private (%d) failed!.", __func__, i);
-			return 1;
-		}
-		p_priv->device_details = d_details;
-		usb_set_serial_port_data(port, p_priv);
-	}
-
 	keyspan_setup_urbs(serial);
 
 	if (s_priv->instat_urb != NULL) {
@@ -2481,61 +2423,112 @@ static int keyspan_startup(struct usb_se
 
 static void keyspan_disconnect(struct usb_serial *serial)
 {
-	int				i, j;
-	struct usb_serial_port		*port;
-	struct keyspan_serial_private 	*s_priv;
-	struct keyspan_port_private	*p_priv;
+	struct keyspan_serial_private *s_priv;
 
 	s_priv = usb_get_serial_data(serial);
 
-	/* Stop reading/writing urbs */
 	stop_urb(s_priv->instat_urb);
 	stop_urb(s_priv->glocont_urb);
 	stop_urb(s_priv->indat_urb);
-	for (i = 0; i < serial->num_ports; ++i) {
-		port = serial->port[i];
-		p_priv = usb_get_serial_port_data(port);
-		stop_urb(p_priv->inack_urb);
-		stop_urb(p_priv->outcont_urb);
-		for (j = 0; j < 2; j++) {
-			stop_urb(p_priv->in_urbs[j]);
-			stop_urb(p_priv->out_urbs[j]);
-		}
-	}
+}
+
+static void keyspan_release(struct usb_serial *serial)
+{
+	struct keyspan_serial_private *s_priv;
+
+	s_priv = usb_get_serial_data(serial);
 
-	/* Now free them */
 	usb_free_urb(s_priv->instat_urb);
 	usb_free_urb(s_priv->indat_urb);
 	usb_free_urb(s_priv->glocont_urb);
-	for (i = 0; i < serial->num_ports; ++i) {
-		port = serial->port[i];
-		p_priv = usb_get_serial_port_data(port);
-		usb_free_urb(p_priv->inack_urb);
-		usb_free_urb(p_priv->outcont_urb);
-		for (j = 0; j < 2; j++) {
-			usb_free_urb(p_priv->in_urbs[j]);
-			usb_free_urb(p_priv->out_urbs[j]);
-		}
-	}
+
+	kfree(s_priv);
 }
 
-static void keyspan_release(struct usb_serial *serial)
+static int keyspan_port_probe(struct usb_serial_port *port)
 {
-	int				i;
-	struct usb_serial_port		*port;
-	struct keyspan_serial_private 	*s_priv;
+	struct usb_serial *serial = port->serial;
+	struct keyspan_port_private *s_priv;
+	struct keyspan_port_private *p_priv;
+	const struct keyspan_device_details *d_details;
+	struct callbacks *cback;
+	int endp;
+	int port_num;
+	int i;
 
 	s_priv = usb_get_serial_data(serial);
+	d_details = s_priv->device_details;
 
-	/*  dbg("Freeing serial->private."); */
-	kfree(s_priv);
+	p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL);
+	if (!p_priv)
+		return -ENOMEM;
+
+	s_priv = usb_get_serial_data(port->serial);
+	p_priv->device_details = d_details;
+
+	/* Setup values for the various callback routines */
+	cback = &keyspan_callbacks[d_details->msg_format];
+
+	port_num = port->number - port->serial->minor;
+
+	/* Do indat endpoints first, once for each flip */
+	endp = d_details->indat_endpoints[port_num];
+	for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) {
+		p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp,
+						USB_DIR_IN, port,
+						p_priv->in_buffer[i], 64,
+						cback->indat_callback);
+	}
+	/* outdat endpoints also have flip */
+	endp = d_details->outdat_endpoints[port_num];
+	for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) {
+		p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp,
+						USB_DIR_OUT, port,
+						p_priv->out_buffer[i], 64,
+						cback->outdat_callback);
+	}
+	/* inack endpoint */
+	p_priv->inack_urb = keyspan_setup_urb(serial,
+					d_details->inack_endpoints[port_num],
+					USB_DIR_IN, port,
+					p_priv->inack_buffer, 1,
+					cback->inack_callback);
+	/* outcont endpoint */
+	p_priv->outcont_urb = keyspan_setup_urb(serial,
+					d_details->outcont_endpoints[port_num],
+					USB_DIR_OUT, port,
+					p_priv->outcont_buffer, 64,
+					 cback->outcont_callback);
+
+	usb_set_serial_port_data(port, p_priv);
 
-	/*  dbg("Freeing port->private."); */
-	/* Now free per port private data */
-	for (i = 0; i < serial->num_ports; i++) {
-		port = serial->port[i];
-		kfree(usb_get_serial_port_data(port));
+	return 0;
+}
+
+static int keyspan_port_remove(struct usb_serial_port *port)
+{
+	struct keyspan_port_private *p_priv;
+	int i;
+
+	p_priv = usb_get_serial_port_data(port);
+
+	stop_urb(p_priv->inack_urb);
+	stop_urb(p_priv->outcont_urb);
+	for (i = 0; i < 2; i++) {
+		stop_urb(p_priv->in_urbs[i]);
+		stop_urb(p_priv->out_urbs[i]);
+	}
+
+	usb_free_urb(p_priv->inack_urb);
+	usb_free_urb(p_priv->outcont_urb);
+	for (i = 0; i < 2; i++) {
+		usb_free_urb(p_priv->in_urbs[i]);
+		usb_free_urb(p_priv->out_urbs[i]);
 	}
+
+	kfree(p_priv);
+
+	return 0;
 }
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
drivers/usb/serial/keyspan.h +8 -0
@@ -42,6 +42,8 @@ static void keyspan_dtr_rts		(struct usb
 static int  keyspan_startup		(struct usb_serial *serial);
 static void keyspan_disconnect		(struct usb_serial *serial);
 static void keyspan_release		(struct usb_serial *serial);
+static int keyspan_port_probe(struct usb_serial_port *port);
+static int keyspan_port_remove(struct usb_serial_port *port);
 static int  keyspan_write_room		(struct tty_struct *tty);
 
 static int  keyspan_write		(struct tty_struct *tty,
@@ -562,6 +564,8 @@ static struct usb_serial_driver keyspan_
 	.attach			= keyspan_startup,
 	.disconnect		= keyspan_disconnect,
 	.release		= keyspan_release,
+	.port_probe		= keyspan_port_probe,
+	.port_remove		= keyspan_port_remove,
 };
 
 static struct usb_serial_driver keyspan_2port_device = {
@@ -584,6 +588,8 @@ static struct usb_serial_driver keyspan_
 	.attach			= keyspan_startup,
 	.disconnect		= keyspan_disconnect,
 	.release		= keyspan_release,
+	.port_probe		= keyspan_port_probe,
+	.port_remove		= keyspan_port_remove,
 };
 
 static struct usb_serial_driver keyspan_4port_device = {
@@ -606,6 +612,8 @@ static struct usb_serial_driver keyspan_
 	.attach			= keyspan_startup,
 	.disconnect		= keyspan_disconnect,
 	.release		= keyspan_release,
+	.port_probe		= keyspan_port_probe,
+	.port_remove		= keyspan_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
author maintainer
#50 lore raw

PATCH 50/101 USB: omninet: 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 feffa7ca6008ab859dd7ab7448a5a899bf0aa98f 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/omninet.c |   36 ++++++++++++++++++------------------
 1 file changed, 18 insertions(+), 18 deletions(-)
drivers/usb/serial/omninet.c +18 -18
@@ -46,8 +46,8 @@ static int  omninet_write(struct tty_str
 				const unsigned char *buf, int count);
 static int  omninet_write_room(struct tty_struct *tty);
 static void omninet_disconnect(struct usb_serial *serial);
-static void omninet_release(struct usb_serial *serial);
-static int omninet_attach(struct usb_serial *serial);
+static int omninet_port_probe(struct usb_serial_port *port);
+static int omninet_port_remove(struct usb_serial_port *port);
 
 static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNINET_ID) },
@@ -64,7 +64,8 @@ static struct usb_serial_driver zyxel_om
 	.description =		"ZyXEL - omni.net lcd plus usb",
 	.id_table =		id_table,
 	.num_ports =		1,
-	.attach =		omninet_attach,
+	.port_probe =		omninet_port_probe,
+	.port_remove =		omninet_port_remove,
 	.open =			omninet_open,
 	.close =		omninet_close,
 	.write =		omninet_write,
@@ -72,7 +73,6 @@ static struct usb_serial_driver zyxel_om
 	.read_bulk_callback =	omninet_read_bulk_callback,
 	.write_bulk_callback =	omninet_write_bulk_callback,
 	.disconnect =		omninet_disconnect,
-	.release =		omninet_release,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
@@ -114,18 +114,26 @@ struct omninet_data {
 	__u8	od_outseq;	/* Sequence number for bulk_out URBs */
 };
 
-static int omninet_attach(struct usb_serial *serial)
+static int omninet_port_probe(struct usb_serial_port *port)
 {
 	struct omninet_data *od;
-	struct usb_serial_port *port = serial->port[0];
 
 	od = kmalloc(sizeof(struct omninet_data), GFP_KERNEL);
-	if (!od) {
-		dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n",
-			__func__, sizeof(struct omninet_data));
+	if (!od)
 		return -ENOMEM;
-	}
+
 	usb_set_serial_port_data(port, od);
+
+	return 0;
+}
+
+static int omninet_port_remove(struct usb_serial_port *port)
+{
+	struct omninet_data *od;
+
+	od = usb_get_serial_port_data(port);
+	kfree(od);
+
 	return 0;
 }
 
@@ -291,14 +299,6 @@ static void omninet_disconnect(struct us
 	usb_kill_urb(wport->write_urb);
 }
 
-
-static void omninet_release(struct usb_serial *serial)
-{
-	struct usb_serial_port *port = serial->port[0];
-
-	kfree(usb_get_serial_port_data(port));
-}
-
 module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
author maintainer
#51 lore raw

PATCH 51/101 USB: qcserial: fix interface-data memory leak in error path

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 961be09e1ead58509ed4bed0d5819a15d8613d8d upstream.

Move interface data allocation to attach so that it is deallocated should usb-serial probe fail.

---
 drivers/usb/serial/qcserial.c |   31 ++++++++++++++++---------------
 1 file changed, 16 insertions(+), 15 deletions(-)
drivers/usb/serial/qcserial.c +16 -15
@@ -140,7 +140,6 @@ MODULE_DEVICE_TABLE(usb, id_table);
 
 static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
 {
-	struct usb_wwan_intf_private *data;
 	struct usb_host_interface *intf = serial->interface->cur_altsetting;
 	struct device *dev = &serial->dev->dev;
 	int retval = -ENODEV;
@@ -156,13 +155,6 @@ static int qcprobe(struct usb_serial *se
 	ifnum = intf->desc.bInterfaceNumber;
 	dev_dbg(dev, "This Interface = %d\n", ifnum);
 
-	data = kzalloc(sizeof(struct usb_wwan_intf_private),
-					 GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	spin_lock_init(&data->susp_lock);
-
 	if (nintf == 1) {
 		/* QDL mode */
 		/* Gobi 2000 has a single altsetting, older ones have two */
@@ -255,20 +247,28 @@ done:
 		}
 	}
 
-	/* Set serial->private if not returning error */
-	if (retval == 0)
-		usb_set_serial_data(serial, data);
-	else
-		kfree(data);
-
 	return retval;
 }
 
+static int qc_attach(struct usb_serial *serial)
+{
+	struct usb_wwan_intf_private *data;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	spin_lock_init(&data->susp_lock);
+
+	usb_set_serial_data(serial, data);
+
+	return 0;
+}
+
 static void qc_release(struct usb_serial *serial)
 {
 	struct usb_wwan_intf_private *priv = usb_get_serial_data(serial);
 
-	/* Free the private data allocated in qcprobe */
 	usb_set_serial_data(serial, NULL);
 	kfree(priv);
 }
@@ -287,6 +287,7 @@ static struct usb_serial_driver qcdevice
 	.write		     = usb_wwan_write,
 	.write_room	     = usb_wwan_write_room,
 	.chars_in_buffer     = usb_wwan_chars_in_buffer,
+	.attach              = qc_attach,
 	.release	     = qc_release,
 	.port_probe          = usb_wwan_port_probe,
 	.port_remove	     = usb_wwan_port_remove,
author maintainer
#52 lore raw

PATCH 52/101 USB: whiteheat: fix memory leak in error path

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 c129197c99550d356cf5f69b046994dd53cd1b9d upstream.

Make sure command buffer is deallocated in case of errors during attach.

---
 drivers/usb/serial/whiteheat.c |    1 +
 1 file changed, 1 insertion(+)
drivers/usb/serial/whiteheat.c +1 -0
@@ -405,6 +405,7 @@ no_firmware:
 		"%s: please contact [email protected]\n",
 		serial->type->description);
 	kfree(result);
+	kfree(command);
 	return -ENODEV;
 
 no_command_private:
author maintainer
#53 lore raw

PATCH 53/101 USB: whiteheat: 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 c467206ed6bcce26c83d0435612cc4fee2527305 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.

Note that the fifth port (command port) is never registered as a port device and thus should be handled in attach and release.

Compile-only tested.

---
 drivers/usb/serial/whiteheat.c |   59 ++++++++++++++++++-----------------------
 1 file changed, 26 insertions(+), 33 deletions(-)
drivers/usb/serial/whiteheat.c +26 -33
@@ -86,6 +86,8 @@ static int  whiteheat_firmware_attach(st
 /* function prototypes for the Connect Tech WhiteHEAT serial converter */
 static int  whiteheat_attach(struct usb_serial *serial);
 static void whiteheat_release(struct usb_serial *serial);
+static int  whiteheat_port_probe(struct usb_serial_port *port);
+static int  whiteheat_port_remove(struct usb_serial_port *port);
 static int  whiteheat_open(struct tty_struct *tty,
 			struct usb_serial_port *port);
 static void whiteheat_close(struct usb_serial_port *port);
@@ -120,6 +122,8 @@ static struct usb_serial_driver whitehea
 	.num_ports =		4,
 	.attach =		whiteheat_attach,
 	.release =		whiteheat_release,
+	.port_probe =		whiteheat_port_probe,
+	.port_remove =		whiteheat_port_remove,
 	.open =			whiteheat_open,
 	.close =		whiteheat_close,
 	.ioctl =		whiteheat_ioctl,
@@ -290,15 +294,12 @@ static int whiteheat_attach(struct usb_s
 {
 	struct usb_serial_port *command_port;
 	struct whiteheat_command_private *command_info;
-	struct usb_serial_port *port;
-	struct whiteheat_private *info;
 	struct whiteheat_hw_info *hw_info;
 	int pipe;
 	int ret;
 	int alen;
 	__u8 *command;
 	__u8 *result;
-	int i;
 
 	command_port = serial->port[COMMAND_PORT];
 
@@ -357,22 +358,6 @@ static int whiteheat_attach(struct usb_s
 		 serial->type->description,
 		 hw_info->sw_major_rev, hw_info->sw_minor_rev);
 
-	for (i = 0; i < serial->num_ports; i++) {
-		port = serial->port[i];
-
-		info = kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL);
-		if (info == NULL) {
-			dev_err(&port->dev,
-				"%s: Out of memory for port structures\n",
-				serial->type->description);
-			goto no_private;
-		}
-
-		info->mcr = 0;
-
-		usb_set_serial_port_data(port, info);
-	}
-
 	command_info = kmalloc(sizeof(struct whiteheat_command_private),
 								GFP_KERNEL);
 	if (command_info == NULL) {
@@ -409,13 +394,6 @@ no_firmware:
 	return -ENODEV;
 
 no_command_private:
-	for (i = serial->num_ports - 1; i >= 0; i--) {
-		port = serial->port[i];
-		info = usb_get_serial_port_data(port);
-		kfree(info);
-no_private:
-		;
-	}
 	kfree(result);
 no_result_buffer:
 	kfree(command);
@@ -423,21 +401,36 @@ no_command_buffer:
 	return -ENOMEM;
 }
 
-
 static void whiteheat_release(struct usb_serial *serial)
 {
 	struct usb_serial_port *command_port;
-	struct whiteheat_private *info;
-	int i;
 
 	/* free up our private data for our command port */
 	command_port = serial->port[COMMAND_PORT];
 	kfree(usb_get_serial_port_data(command_port));
+}
 
-	for (i = 0; i < serial->num_ports; i++) {
-		info = usb_get_serial_port_data(serial->port[i]);
-		kfree(info);
-	}
+static int whiteheat_port_probe(struct usb_serial_port *port)
+{
+	struct whiteheat_private *info;
+
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	usb_set_serial_port_data(port, info);
+
+	return 0;
+}
+
+static int whiteheat_port_remove(struct usb_serial_port *port)
+{
+	struct whiteheat_private *info;
+
+	info = usb_get_serial_port_data(port);
+	kfree(info);
+
+	return 0;
 }
 
 static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port)
author maintainer
#54 lore raw

PATCH 54/101 USB: opticon: fix DMA from stack

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 ea0dbebffe118724cd4df7d9b071ea8ee48d48f0 upstream.

Make sure to allocate the control-message buffer dynamically as some platforms cannot do DMA from stack.

Note that only the first byte of the old buffer was used.

---
 drivers/usb/serial/opticon.c |    7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/usb/serial/opticon.c +6 -1
@@ -158,7 +158,11 @@ static int send_control_msg(struct usb_s
 {
 	struct usb_serial *serial = port->serial;
 	int retval;
-	u8 buffer[2];
+	u8 *buffer;
+
+	buffer = kzalloc(1, GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
 
 	buffer[0] = val;
 	/* Send the message to the vendor control endpoint
@@ -167,6 +171,7 @@ static int send_control_msg(struct usb_s
 				requesttype,
 				USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
 				0, 0, buffer, 1, 0);
+	kfree(buffer);
 
 	return retval;
 }
author maintainer
#55 lore raw

PATCH 55/101 USB: opticon: fix memory leak in error path

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 acbf0e5263de563e25f7c104868e4490b9e72b13 upstream.

Fix memory leak in write error path.

---
 drivers/usb/serial/opticon.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/usb/serial/opticon.c +3 -1
@@ -289,7 +289,7 @@ static int opticon_write(struct tty_stru
 	if (!dr) {
 		dev_err(&port->dev, "out of memory\n");
 		count = -ENOMEM;
-		goto error;
+		goto error_no_dr;
 	}
 
 	dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT;
@@ -319,6 +319,8 @@ static int opticon_write(struct tty_stru
 
 	return count;
 error:
+	kfree(dr);
+error_no_dr:
 	usb_free_urb(urb);
 error_no_urb:
 	kfree(buffer);
author maintainer
#56 lore raw

PATCH 56/101 USB: metro-usb: 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 50dde8686eec41bf3d7cbec7a6f76c073ab01903 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.

Note that the call to metrousb_clean (close) in shutdown was redundant.

Compile-only tested.

---
 drivers/usb/serial/metro-usb.c |   50 ++++++++++-------------------------------
 1 file changed, 13 insertions(+), 37 deletions(-)
drivers/usb/serial/metro-usb.c +13 -37
@@ -280,51 +280,27 @@ static int metrousb_set_modem_ctrl(struc
 	return retval;
 }
 
-static void metrousb_shutdown(struct usb_serial *serial)
+static int metrousb_port_probe(struct usb_serial_port *port)
 {
-	int i = 0;
+	struct metrousb_private *metro_priv;
 
-	dev_dbg(&serial->dev->dev, "%s\n", __func__);
+	metro_priv = kzalloc(sizeof(*metro_priv), GFP_KERNEL);
+	if (!metro_priv)
+		return -ENOMEM;
 
-	/* Stop reading and writing on all ports. */
-	for (i = 0; i < serial->num_ports; ++i) {
-		/* Close any open urbs. */
-		metrousb_cleanup(serial->port[i]);
+	spin_lock_init(&metro_priv->lock);
 
-		/* Free memory. */
-		kfree(usb_get_serial_port_data(serial->port[i]));
-		usb_set_serial_port_data(serial->port[i], NULL);
+	usb_set_serial_port_data(port, metro_priv);
 
-		dev_dbg(&serial->dev->dev, "%s - freed port number=%d\n",
-			__func__, serial->port[i]->number);
-	}
+	return 0;
 }
 
-static int metrousb_startup(struct usb_serial *serial)
+static int metrousb_port_remove(struct usb_serial_port *port)
 {
 	struct metrousb_private *metro_priv;
-	struct usb_serial_port *port;
-	int i = 0;
-
-	dev_dbg(&serial->dev->dev, "%s\n", __func__);
 
-	/* Loop through the serial ports setting up the private structures.
-	 * Currently we only use one port. */
-	for (i = 0; i < serial->num_ports; ++i) {
-		port = serial->port[i];
-
-		/* Declare memory. */
-		metro_priv = kzalloc(sizeof(struct metrousb_private), GFP_KERNEL);
-		if (!metro_priv)
-			return -ENOMEM;
-
-		/* Initialize memory. */
-		spin_lock_init(&metro_priv->lock);
-		usb_set_serial_port_data(port, metro_priv);
-
-		dev_dbg(&serial->dev->dev, "%s - port number=%d\n ",
-			__func__, port->number);
-	}
+	metro_priv = usb_get_serial_port_data(port);
+	kfree(metro_priv);
 
 	return 0;
 }
@@ -423,8 +399,8 @@ static struct usb_serial_driver metrousb
 	.close			= metrousb_cleanup,
 	.read_int_callback	= metrousb_read_int_callback,
 	.write_int_callback	= metrousb_write_int_callback,
-	.attach			= metrousb_startup,
-	.release		= metrousb_shutdown,
+	.port_probe		= metrousb_port_probe,
+	.port_remove		= metrousb_port_remove,
 	.throttle		= metrousb_throttle,
 	.unthrottle		= metrousb_unthrottle,
 	.tiocmget		= metrousb_tiocmget,
author maintainer
#57 lore raw

PATCH 57/101 USB: metro-usb: fix io after disconnect

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 2ee44fbeac92c36e53779a57ee84cfee1affe418 upstream.

Make sure no control urb is submitted during close after a disconnect by checking the disconnected flag.

---
 drivers/usb/serial/metro-usb.c |   13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)
drivers/usb/serial/metro-usb.c +5 -8
@@ -188,16 +188,13 @@ static void metrousb_cleanup(struct usb_
 {
 	dev_dbg(&port->dev, "%s\n", __func__);
 
-	if (port->serial->dev) {
-		/* Shutdown any interrupt in urbs. */
-		if (port->interrupt_in_urb) {
-			usb_unlink_urb(port->interrupt_in_urb);
-			usb_kill_urb(port->interrupt_in_urb);
-		}
+	usb_unlink_urb(port->interrupt_in_urb);
+	usb_kill_urb(port->interrupt_in_urb);
 
-		/* Send deactivate cmd to device */
+	mutex_lock(&port->serial->disc_mutex);
+	if (!port->serial->disconnected)
 		metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port);
-	}
+	mutex_unlock(&port->serial->disc_mutex);
 }
 
 static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port)
author maintainer
#58 lore raw

PATCH 58/101 USB: mos7720: 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 4230af572f95b3115bba1ee6fb95681f3851ab26 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.

Note that this patch also fixes a second port-data memory leak in the error path of attach, should parallel-port initialisation fail.

Compile-only tested.

---
 drivers/usb/serial/mos7720.c |   62 ++++++++++++++++++++++---------------------
 1 file changed, 32 insertions(+), 30 deletions(-)
drivers/usb/serial/mos7720.c +32 -30
@@ -2023,9 +2023,7 @@ static int mos7720_ioctl(struct tty_stru
 
 static int mos7720_startup(struct usb_serial *serial)
 {
-	struct moschip_port *mos7720_port;
 	struct usb_device *dev;
-	int i;
 	char data;
 	u16 product;
 	int ret_val;
@@ -2063,29 +2061,6 @@ static int mos7720_startup(struct usb_se
 		serial->port[1]->interrupt_in_buffer = NULL;
 	}
 
-
-	/* set up serial port private structures */
-	for (i = 0; i < serial->num_ports; ++i) {
-		mos7720_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
-		if (mos7720_port == NULL) {
-			dev_err(&dev->dev, "%s - Out of memory\n", __func__);
-			return -ENOMEM;
-		}
-
-		/* Initialize all port interrupt end point to port 0 int
-		 * endpoint.  Our device has only one interrupt endpoint
-		 * common to all ports */
-		serial->port[i]->interrupt_in_endpointAddress =
-				serial->port[0]->interrupt_in_endpointAddress;
-
-		mos7720_port->port = serial->port[i];
-		usb_set_serial_port_data(serial->port[i], mos7720_port);
-
-		dbg("port number is %d", serial->port[i]->number);
-		dbg("serial number is %d", serial->minor);
-	}
-
-
 	/* setting configuration feature to one */
 	usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
 			(__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5*HZ);
@@ -2113,8 +2088,6 @@ static int mos7720_startup(struct usb_se
 
 static void mos7720_release(struct usb_serial *serial)
 {
-	int i;
-
 #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT
 	/* close the parallel port */
 
@@ -2153,9 +2126,36 @@ static void mos7720_release(struct usb_s
 		kref_put(&mos_parport->ref_count, destroy_mos_parport);
 	}
 #endif
-	/* free private structure allocated for serial port */
-	for (i = 0; i < serial->num_ports; ++i)
-		kfree(usb_get_serial_port_data(serial->port[i]));
+}
+
+static int mos7720_port_probe(struct usb_serial_port *port)
+{
+	struct moschip_port *mos7720_port;
+
+	mos7720_port = kzalloc(sizeof(*mos7720_port), GFP_KERNEL);
+	if (!mos7720_port)
+		return -ENOMEM;
+
+	/* Initialize all port interrupt end point to port 0 int endpoint.
+	 * Our device has only one interrupt endpoint common to all ports.
+	 */
+	port->interrupt_in_endpointAddress =
+		port->serial->port[0]->interrupt_in_endpointAddress;
+	mos7720_port->port = port;
+
+	usb_set_serial_port_data(port, mos7720_port);
+
+	return 0;
+}
+
+static int mos7720_port_remove(struct usb_serial_port *port)
+{
+	struct moschip_port *mos7720_port;
+
+	mos7720_port = usb_get_serial_port_data(port);
+	kfree(mos7720_port);
+
+	return 0;
 }
 
 static struct usb_serial_driver moschip7720_2port_driver = {
@@ -2173,6 +2173,8 @@ static struct usb_serial_driver moschip7
 	.probe			= mos77xx_probe,
 	.attach			= mos7720_startup,
 	.release		= mos7720_release,
+	.port_probe		= mos7720_port_probe,
+	.port_remove		= mos7720_port_remove,
 	.ioctl			= mos7720_ioctl,
 	.tiocmget		= mos7720_tiocmget,
 	.tiocmset		= mos7720_tiocmset,
author maintainer
#59 lore raw

PATCH 59/101 USB: quatech2: fix memory leak in error path

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 b8a0055050b6294826171641b182c09f78f4cc63 upstream.

Fix memory leak in attach error path where the read urb was never freed.

---
 drivers/usb/serial/quatech2.c |    1 +
 1 file changed, 1 insertion(+)
drivers/usb/serial/quatech2.c +1 -0
@@ -825,6 +825,7 @@ static int qt2_setup_urbs(struct usb_ser
 	if (status != 0) {
 		dev_err(&serial->dev->dev,
 			"%s - submit read urb failed %i\n", __func__, status);
+		usb_free_urb(serial_priv->read_urb);
 		return status;
 	}
 
author maintainer
#60 lore raw

PATCH 60/101 USB: quatech2: fix port-data memory leaks

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 40d04738491d7ac1aa708ba434ff3480ec9e1b96 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.

Note that this also fixes memory leaks in the error path of attach where the write urbs were not freed on errors.

Make sure all interface-data deallocation is done in release by moving the read urb deallocation from disconnect.

Note that the write urb is killed during close so that the call in disconnect was superfluous.

Compile-only tested.

---
 drivers/usb/serial/quatech2.c |  121 +++++++++++++++++-------------------------
 1 file changed, 51 insertions(+), 70 deletions(-)
drivers/usb/serial/quatech2.c +51 -70
@@ -145,12 +145,12 @@ static void qt2_read_bulk_callback(struc
 
 static void qt2_release(struct usb_serial *serial)
 {
-	int i;
+	struct qt2_serial_private *serial_priv;
 
-	kfree(usb_get_serial_data(serial));
+	serial_priv = usb_get_serial_data(serial);
 
-	for (i = 0; i < serial->num_ports; i++)
-		kfree(usb_get_serial_port_data(serial->port[i]));
+	usb_free_urb(serial_priv->read_urb);
+	kfree(serial_priv);
 }
 
 static inline int calc_baud_divisor(int baudrate)
@@ -466,21 +466,9 @@ static void qt2_close(struct usb_serial_
 static void qt2_disconnect(struct usb_serial *serial)
 {
 	struct qt2_serial_private *serial_priv = usb_get_serial_data(serial);
-	struct qt2_port_private *port_priv;
-	int i;
 
 	if (serial_priv->read_urb->status == -EINPROGRESS)
 		usb_kill_urb(serial_priv->read_urb);
-
-	usb_free_urb(serial_priv->read_urb);
-
-	for (i = 0; i < serial->num_ports; i++) {
-		port_priv = usb_get_serial_port_data(serial->port[i]);
-
-		if (port_priv->write_urb->status == -EINPROGRESS)
-			usb_kill_urb(port_priv->write_urb);
-		usb_free_urb(port_priv->write_urb);
-	}
 }
 
 static int get_serial_info(struct usb_serial_port *port,
@@ -775,11 +763,9 @@ static void qt2_read_bulk_callback(struc
 
 static int qt2_setup_urbs(struct usb_serial *serial)
 {
-	struct usb_serial_port *port;
 	struct usb_serial_port *port0;
 	struct qt2_serial_private *serial_priv;
-	struct qt2_port_private *port_priv;
-	int pcount, status;
+	int status;
 
 	port0 = serial->port[0];
 
@@ -797,30 +783,6 @@ static int qt2_setup_urbs(struct usb_ser
 			  sizeof(serial_priv->read_buffer),
 			  qt2_read_bulk_callback, serial);
 
-	/* setup write_urb for each port */
-	for (pcount = 0; pcount < serial->num_ports; pcount++) {
-
-		port = serial->port[pcount];
-		port_priv = usb_get_serial_port_data(port);
-
-		port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL);
-		if (!port_priv->write_urb) {
-			dev_err(&serial->dev->dev,
-				"failed to alloc write_urb for port %i\n",
-				pcount);
-			return -ENOMEM;
-		}
-
-		usb_fill_bulk_urb(port_priv->write_urb,
-				  serial->dev,
-				  usb_sndbulkpipe(serial->dev,
-						  port0->
-						  bulk_out_endpointAddress),
-				  port_priv->write_buffer,
-				  sizeof(port_priv->write_buffer),
-				  qt2_write_bulk_callback, port);
-	}
-
 	status = usb_submit_urb(serial_priv->read_urb, GFP_KERNEL);
 	if (status != 0) {
 		dev_err(&serial->dev->dev,
@@ -830,14 +792,12 @@ static int qt2_setup_urbs(struct usb_ser
 	}
 
 	return 0;
-
 }
 
 static int qt2_attach(struct usb_serial *serial)
 {
 	struct qt2_serial_private *serial_priv;
-	struct qt2_port_private *port_priv;
-	int status, pcount;
+	int status;
 
 	/* power on unit */
 	status = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
@@ -857,26 +817,6 @@ static int qt2_attach(struct usb_serial
 
 	usb_set_serial_data(serial, serial_priv);
 
-	for (pcount = 0; pcount < serial->num_ports; pcount++) {
-		port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
-		if (!port_priv) {
-			dev_err(&serial->dev->dev,
-				"%s- kmalloc(%Zd) failed.\n", __func__,
-				sizeof(*port_priv));
-			pcount--;
-			status = -ENOMEM;
-			goto attach_failed;
-		}
-
-		spin_lock_init(&port_priv->lock);
-		spin_lock_init(&port_priv->urb_lock);
-		init_waitqueue_head(&port_priv->delta_msr_wait);
-
-		port_priv->port = serial->port[pcount];
-
-		usb_set_serial_port_data(serial->port[pcount], port_priv);
-	}
-
 	status = qt2_setup_urbs(serial);
 	if (status != 0)
 		goto attach_failed;
@@ -884,14 +824,53 @@ static int qt2_attach(struct usb_serial
 	return 0;
 
 attach_failed:
-	for (/* empty */; pcount >= 0; pcount--) {
-		port_priv = usb_get_serial_port_data(serial->port[pcount]);
-		kfree(port_priv);
-	}
 	kfree(serial_priv);
 	return status;
 }
 
+static int qt2_port_probe(struct usb_serial_port *port)
+{
+	struct usb_serial *serial = port->serial;
+	struct qt2_port_private *port_priv;
+	u8 bEndpointAddress;
+
+	port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
+	if (!port_priv)
+		return -ENOMEM;
+
+	spin_lock_init(&port_priv->lock);
+	spin_lock_init(&port_priv->urb_lock);
+	init_waitqueue_head(&port_priv->delta_msr_wait);
+	port_priv->port = port;
+
+	port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!port_priv->write_urb) {
+		kfree(port_priv);
+		return -ENOMEM;
+	}
+	bEndpointAddress = serial->port[0]->bulk_out_endpointAddress;
+	usb_fill_bulk_urb(port_priv->write_urb, serial->dev,
+				usb_sndbulkpipe(serial->dev, bEndpointAddress),
+				port_priv->write_buffer,
+				sizeof(port_priv->write_buffer),
+				qt2_write_bulk_callback, port);
+
+	usb_set_serial_port_data(port, port_priv);
+
+	return 0;
+}
+
+static int qt2_port_remove(struct usb_serial_port *port)
+{
+	struct qt2_port_private *port_priv;
+
+	port_priv = usb_get_serial_port_data(port);
+	usb_free_urb(port_priv->write_urb);
+	kfree(port_priv);
+
+	return 0;
+}
+
 static int qt2_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -1130,6 +1109,8 @@ static struct usb_serial_driver qt2_devi
 	.attach              = qt2_attach,
 	.release             = qt2_release,
 	.disconnect          = qt2_disconnect,
+	.port_probe          = qt2_port_probe,
+	.port_remove         = qt2_port_remove,
 	.dtr_rts             = qt2_dtr_rts,
 	.break_ctl           = qt2_break_ctl,
 	.tiocmget            = qt2_tiocmget,
author maintainer
#61 lore raw

PATCH 61/101 USB: quatech2: fix close and disconnect urb handling

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 8e512ab0b675da20e023439a5811e3f2554e6852 upstream.

Kill urbs unconditionally at close and disconnect.

Note that URB status is not valid outside of completion handler.

---
 drivers/usb/serial/quatech2.c |    6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/usb/serial/quatech2.c +2 -4
@@ -425,8 +425,7 @@ static void qt2_close(struct usb_serial_
 	port_priv->is_open = false;
 
 	spin_lock_irqsave(&port_priv->urb_lock, flags);
-	if (port_priv->write_urb->status == -EINPROGRESS)
-		usb_kill_urb(port_priv->write_urb);
+	usb_kill_urb(port_priv->write_urb);
 	port_priv->urb_in_use = false;
 	spin_unlock_irqrestore(&port_priv->urb_lock, flags);
 
@@ -467,8 +466,7 @@ static void qt2_disconnect(struct usb_se
 {
 	struct qt2_serial_private *serial_priv = usb_get_serial_data(serial);
 
-	if (serial_priv->read_urb->status == -EINPROGRESS)
-		usb_kill_urb(serial_priv->read_urb);
+	usb_kill_urb(serial_priv->read_urb);
 }
 
 static int get_serial_info(struct usb_serial_port *port,
author maintainer
#62 lore raw

PATCH 62/101 USB: quatech2: fix io after disconnect

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 2f0295adf6438188c4cd0868f2b1976a2b034e1d upstream.

Make sure no control urb is submitted during close after a disconnect by checking the disconnected flag.

---
 drivers/usb/serial/quatech2.c |    7 +++++++
 1 file changed, 7 insertions(+)
drivers/usb/serial/quatech2.c +7 -0
@@ -429,6 +429,12 @@ static void qt2_close(struct usb_serial_
 	port_priv->urb_in_use = false;
 	spin_unlock_irqrestore(&port_priv->urb_lock, flags);
 
+	mutex_lock(&port->serial->disc_mutex);
+	if (port->serial->disconnected) {
+		mutex_unlock(&port->serial->disc_mutex);
+		return;
+	}
+
 	/* flush the port transmit buffer */
 	i = usb_control_msg(serial->dev,
 			    usb_rcvctrlpipe(serial->dev, 0),
@@ -460,6 +466,7 @@ static void qt2_close(struct usb_serial_
 		dev_err(&port->dev, "%s - close port failed %i\n",
 			__func__, i);
 
+	mutex_unlock(&port->serial->disc_mutex);
 }
 
 static void qt2_disconnect(struct usb_serial *serial)
author maintainer
#63 lore raw

PATCH 63/101 USB: serial: Fix memory leak in sierra_release()

In reply to Greg Kroah-Hartman

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

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

From: Lennart Sorensen <[email protected]>

commit f7bc5051667b74c3861f79eed98c60d5c3b883f7 upstream.

I found a memory leak in sierra_release() (well sierra_probe() I guess) that looses 8 bytes each time the driver releases a device.

---
 drivers/usb/serial/sierra.c |    1 +
 1 file changed, 1 insertion(+)
drivers/usb/serial/sierra.c +1 -0
@@ -961,6 +961,7 @@ static void sierra_release(struct usb_se
 			continue;
 		kfree(portdata);
 	}
+	kfree(serial->private);
 }
 
 #ifdef CONFIG_PM
author maintainer
#64 lore raw

PATCH 64/101 USB: sierra: fix memory leak in attach error path

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 7e41f9bcdd2e813ea2a3c40db291d87ea06b559f upstream.

Make sure port private data is deallocated on errors in attach.

---
 drivers/usb/serial/sierra.c |    9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
drivers/usb/serial/sierra.c +8 -1
@@ -907,7 +907,7 @@ static int sierra_startup(struct usb_ser
 			dev_dbg(&port->dev, "%s: kmalloc for "
 				"sierra_port_private (%d) failed!\n",
 				__func__, i);
-			return -ENOMEM;
+			goto err;
 		}
 		spin_lock_init(&portdata->lock);
 		init_usb_anchor(&portdata->active);
@@ -944,6 +944,13 @@ static int sierra_startup(struct usb_ser
 	}
 
 	return 0;
+err:
+	for (--i; i >= 0; --i) {
+		portdata = usb_get_serial_port_data(serial->port[i]);
+		kfree(portdata);
+	}
+
+	return -ENOMEM;
 }
 
 static void sierra_release(struct usb_serial *serial)
author maintainer
#65 lore raw

PATCH 65/101 USB: sierra: fix memory leak in probe error path

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 084817d79399ab5ccab2f90a148b0369912a8369 upstream.

Move interface data allocation to attach so that it is deallocated on errors in usb-serial probe.

---
 drivers/usb/serial/sierra.c |   16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)
drivers/usb/serial/sierra.c +10 -6
@@ -162,7 +162,6 @@ static int sierra_probe(struct usb_seria
 {
 	int result = 0;
 	struct usb_device *udev;
-	struct sierra_intf_private *data;
 	u8 ifnum;
 
 	udev = serial->dev;
@@ -189,11 +188,6 @@ static int sierra_probe(struct usb_seria
 		return -ENODEV;
 	}
 
-	data = serial->private = kzalloc(sizeof(struct sierra_intf_private), GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-	spin_lock_init(&data->susp_lock);
-
 	return result;
 }
 
@@ -887,11 +881,20 @@ static void sierra_dtr_rts(struct usb_se
 static int sierra_startup(struct usb_serial *serial)
 {
 	struct usb_serial_port *port;
+	struct sierra_intf_private *intfdata;
 	struct sierra_port_private *portdata;
 	struct sierra_iface_info *himemoryp = NULL;
 	int i;
 	u8 ifnum;
 
+	intfdata = kzalloc(sizeof(*intfdata), GFP_KERNEL);
+	if (!intfdata)
+		return -ENOMEM;
+
+	spin_lock_init(&intfdata->susp_lock);
+
+	usb_set_serial_data(serial, intfdata);
+
 	/* Set Device mode to D0 */
 	sierra_set_power_state(serial->dev, 0x0000);
 
@@ -949,6 +952,7 @@ err:
 		portdata = usb_get_serial_port_data(serial->port[i]);
 		kfree(portdata);
 	}
+	kfree(intfdata);
 
 	return -ENOMEM;
 }
author maintainer
#66 lore raw

PATCH 66/101 USB: sierra: 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 f525c05babc7938cc1d4236550fd8a659fb05960 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.

Note also that urb-count for multi-port interfaces has not been changed even though the usb-serial port number is now determined from the port and interface minor numbers.

Compile-only tested.

---
 drivers/usb/serial/sierra.c |  127 ++++++++++++++++++++------------------------
 1 file changed, 59 insertions(+), 68 deletions(-)
drivers/usb/serial/sierra.c +59 -68
@@ -880,12 +880,7 @@ static void sierra_dtr_rts(struct usb_se
 
 static int sierra_startup(struct usb_serial *serial)
 {
-	struct usb_serial_port *port;
 	struct sierra_intf_private *intfdata;
-	struct sierra_port_private *portdata;
-	struct sierra_iface_info *himemoryp = NULL;
-	int i;
-	u8 ifnum;
 
 	intfdata = kzalloc(sizeof(*intfdata), GFP_KERNEL);
 	if (!intfdata)
@@ -902,77 +897,71 @@ static int sierra_startup(struct usb_ser
 	if (nmea)
 		sierra_vsc_set_nmea(serial->dev, 1);
 
-	/* Now setup per port private data */
-	for (i = 0; i < serial->num_ports; i++) {
-		port = serial->port[i];
-		portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
-		if (!portdata) {
-			dev_dbg(&port->dev, "%s: kmalloc for "
-				"sierra_port_private (%d) failed!\n",
-				__func__, i);
-			goto err;
-		}
-		spin_lock_init(&portdata->lock);
-		init_usb_anchor(&portdata->active);
-		init_usb_anchor(&portdata->delayed);
-		ifnum = i;
-		/* Assume low memory requirements */
-		portdata->num_out_urbs = N_OUT_URB;
-		portdata->num_in_urbs  = N_IN_URB;
-
-		/* Determine actual memory requirements */
-		if (serial->num_ports == 1) {
-			/* Get interface number for composite device */
-			ifnum = sierra_calc_interface(serial);
-			himemoryp =
-			    (struct sierra_iface_info *)&typeB_interface_list;
-			if (is_himemory(ifnum, himemoryp)) {
-				portdata->num_out_urbs = N_OUT_URB_HM;
-				portdata->num_in_urbs  = N_IN_URB_HM;
-			}
-		}
-		else {
-			himemoryp =
-			    (struct sierra_iface_info *)&typeA_interface_list;
-			if (is_himemory(i, himemoryp)) {
-				portdata->num_out_urbs = N_OUT_URB_HM;
-				portdata->num_in_urbs  = N_IN_URB_HM;
-			}
-		}
-		dev_dbg(&serial->dev->dev,
-			"Memory usage (urbs) interface #%d, in=%d, out=%d\n",
-			ifnum,portdata->num_in_urbs, portdata->num_out_urbs );
-		/* Set the port private data pointer */
-		usb_set_serial_port_data(port, portdata);
-	}
-
 	return 0;
-err:
-	for (--i; i >= 0; --i) {
-		portdata = usb_get_serial_port_data(serial->port[i]);
-		kfree(portdata);
-	}
-	kfree(intfdata);
-
-	return -ENOMEM;
 }
 
 static void sierra_release(struct usb_serial *serial)
 {
-	int i;
-	struct usb_serial_port *port;
+	struct sierra_intf_private *intfdata;
+
+	intfdata = usb_get_serial_data(serial);
+	kfree(intfdata);
+}
+
+static int sierra_port_probe(struct usb_serial_port *port)
+{
+	struct usb_serial *serial = port->serial;
 	struct sierra_port_private *portdata;
+	const struct sierra_iface_info *himemoryp;
+	u8 ifnum;
 
-	for (i = 0; i < serial->num_ports; ++i) {
-		port = serial->port[i];
-		if (!port)
-			continue;
-		portdata = usb_get_serial_port_data(port);
-		if (!portdata)
-			continue;
-		kfree(portdata);
+	portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
+	if (!portdata)
+		return -ENOMEM;
+
+	spin_lock_init(&portdata->lock);
+	init_usb_anchor(&portdata->active);
+	init_usb_anchor(&portdata->delayed);
+
+	/* Assume low memory requirements */
+	portdata->num_out_urbs = N_OUT_URB;
+	portdata->num_in_urbs  = N_IN_URB;
+
+	/* Determine actual memory requirements */
+	if (serial->num_ports == 1) {
+		/* Get interface number for composite device */
+		ifnum = sierra_calc_interface(serial);
+		himemoryp = &typeB_interface_list;
+	} else {
+		/* This is really the usb-serial port number of the interface
+		 * rather than the interface number.
+		 */
+		ifnum = port->number - serial->minor;
+		himemoryp = &typeA_interface_list;
+	}
+
+	if (is_himemory(ifnum, himemoryp)) {
+		portdata->num_out_urbs = N_OUT_URB_HM;
+		portdata->num_in_urbs  = N_IN_URB_HM;
 	}
-	kfree(serial->private);
+
+	dev_dbg(&port->dev,
+			"Memory usage (urbs) interface #%d, in=%d, out=%d\n",
+			ifnum, portdata->num_in_urbs, portdata->num_out_urbs);
+
+	usb_set_serial_port_data(port, portdata);
+
+	return 0;
+}
+
+static int sierra_port_remove(struct usb_serial_port *port)
+{
+	struct sierra_port_private *portdata;
+
+	portdata = usb_get_serial_port_data(port);
+	kfree(portdata);
+
+	return 0;
 }
 
 #ifdef CONFIG_PM
@@ -1076,6 +1065,8 @@ static struct usb_serial_driver sierra_d
 	.tiocmset          = sierra_tiocmset,
 	.attach            = sierra_startup,
 	.release           = sierra_release,
+	.port_probe        = sierra_port_probe,
+	.port_remove       = sierra_port_remove,
 	.suspend	   = sierra_suspend,
 	.resume		   = sierra_resume,
 	.read_int_callback = sierra_instat_callback,
author maintainer
#67 lore raw

PATCH 67/101 USB: mos7840: fix urb leak at release

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 65a4cdbb170e4ec1a7fa0e94936d47e24a17b0e8 upstream.

Make sure control urb is freed at release.

---
 drivers/usb/serial/mos7840.c |    1 +
 1 file changed, 1 insertion(+)
drivers/usb/serial/mos7840.c +1 -0
@@ -2754,6 +2754,7 @@ static void mos7840_release(struct usb_s
 				del_timer_sync(&mos7840_port->led_timer1);
 				del_timer_sync(&mos7840_port->led_timer2);
 			}
+			usb_free_urb(mos7840_port->control_urb);
 			kfree(mos7840_port->ctrl_buf);
 			kfree(mos7840_port->dr);
 			kfree(mos7840_port);
author maintainer
#68 lore raw

PATCH 68/101 USB: mos7840: fix port-device leak in error path

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 3eb55cc4ed88eee3b5230f66abcdbd2a91639eda upstream.

The driver set the usb-serial port pointers to NULL on errors in attach, effectively preventing usb-serial core from decrementing the port ref counters and releasing the port devices and associated data.

---
 drivers/usb/serial/mos7840.c |    1 -
 1 file changed, 1 deletion(-)
drivers/usb/serial/mos7840.c +0 -1
@@ -2684,7 +2684,6 @@ error:
 		kfree(mos7840_port->ctrl_buf);
 		usb_free_urb(mos7840_port->control_urb);
 		kfree(mos7840_port);
-		serial->port[i] = NULL;
 	}
 	return status;
 }
author maintainer
#69 lore raw

PATCH 69/101 USB: mos7840: remove NULL-urb submission

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 28c3ae9a8cf45f439c9a0779ebd0256e2ae72813 upstream.

The private int_urb is never allocated so the submission from the control completion handler will always fail. Remove this odd piece of broken code.

---
 drivers/usb/serial/mos7840.c |   15 +--------------
 1 file changed, 1 insertion(+), 14 deletions(-)
drivers/usb/serial/mos7840.c +1 -14
@@ -218,7 +218,6 @@ struct moschip_port {
 	int port_num;		/*Actual port number in the device(1,2,etc) */
 	struct urb *write_urb;	/* write URB for this port */
 	struct urb *read_urb;	/* read URB for this port */
-	struct urb *int_urb;
 	__u8 shadowLCR;		/* last LCR value received */
 	__u8 shadowMCR;		/* last MCR value received */
 	char open;
@@ -493,7 +492,6 @@ static void mos7840_control_callback(str
 	unsigned char *data;
 	struct moschip_port *mos7840_port;
 	__u8 regval = 0x0;
-	int result = 0;
 	int status = urb->status;
 
 	mos7840_port = urb->context;
@@ -512,7 +510,7 @@ static void mos7840_control_callback(str
 	default:
 		dbg("%s - nonzero urb status received: %d", __func__,
 		    status);
-		goto exit;
+		return;
 	}
 
 	dbg("%s urb buffer size is %d", __func__, urb->actual_length);
@@ -525,17 +523,6 @@ static void mos7840_control_callback(str
 		mos7840_handle_new_msr(mos7840_port, regval);
 	else if (mos7840_port->MsrLsr == 1)
 		mos7840_handle_new_lsr(mos7840_port, regval);
-
-exit:
-	spin_lock(&mos7840_port->pool_lock);
-	if (!mos7840_port->zombie)
-		result = usb_submit_urb(mos7840_port->int_urb, GFP_ATOMIC);
-	spin_unlock(&mos7840_port->pool_lock);
-	if (result) {
-		dev_err(&urb->dev->dev,
-			"%s - Error %d submitting interrupt urb\n",
-			__func__, result);
-	}
 }
 
 static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
author maintainer
#70 lore raw

PATCH 70/101 USB: mos7840: remove invalid disconnect handling

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 e681b66f2e19fadbe8a7e2a17900978cb6bc921f upstream.

Remove private zombie flag used to signal disconnect and to prevent control urb from being submitted from interrupt urb completion handler.

The control urb will not be re-submitted as both the control urb and the interrupt urb is killed on disconnect.

---
 drivers/usb/serial/mos7840.c |   13 +------------
 1 file changed, 1 insertion(+), 12 deletions(-)
drivers/usb/serial/mos7840.c +1 -12
@@ -222,7 +222,6 @@ struct moschip_port {
 	__u8 shadowMCR;		/* last MCR value received */
 	char open;
 	char open_ports;
-	char zombie;
 	wait_queue_head_t wait_chase;	/* for handling sleeping while waiting for chase to finish */
 	wait_queue_head_t delta_msr_wait;	/* for handling sleeping while waiting for msr change to happen */
 	int delta_msr_cond;
@@ -691,14 +690,7 @@ static void mos7840_interrupt_callback(s
 					wreg = MODEM_STATUS_REGISTER;
 					break;
 				}
-				spin_lock(&mos7840_port->pool_lock);
-				if (!mos7840_port->zombie) {
-					rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data);
-				} else {
-					spin_unlock(&mos7840_port->pool_lock);
-					return;
-				}
-				spin_unlock(&mos7840_port->pool_lock);
+				rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data);
 			}
 		}
 	}
@@ -2700,9 +2692,6 @@ static void mos7840_disconnect(struct us
 		mos7840_port = mos7840_get_port_private(serial->port[i]);
 		dbg ("mos7840_port %d = %p", i, mos7840_port);
 		if (mos7840_port) {
-			spin_lock_irqsave(&mos7840_port->pool_lock, flags);
-			mos7840_port->zombie = 1;
-			spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
 			usb_kill_urb(mos7840_port->control_urb);
 		}
 	}
author maintainer
#71 lore raw

PATCH 71/101 vhost: fix mergeable bufs on BE hosts

In reply to Greg Kroah-Hartman

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

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

From: "Michael S. Tsirkin" <[email protected]>

commit 910a578f7e9400a78a3b13aba0b4d2df16a2cb05 upstream.

We copy head count to a 16 bit field, this works by chance on LE but on BE guest gets 0. Fix it up.

---
 drivers/vhost/net.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/vhost/net.c +2 -1
@@ -379,7 +379,8 @@ static void handle_rx(struct vhost_net *
 		.hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE
 	};
 	size_t total_len = 0;
-	int err, headcount, mergeable;
+	int err, mergeable;
+	s16 headcount;
 	size_t vhost_hlen, sock_hlen;
 	size_t vhost_len, sock_len;
 	/* TODO: check that we are running from vhost_worker? */
author maintainer
#72 lore raw

PATCH 72/101 ARM: SAMSUNG: Add naming of s3c64xx-spi devices

In reply to Greg Kroah-Hartman

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

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

From: Heiko Stuebner <[email protected]>

commit 308b3afb97dc342e9c4f958d8b4c459ae0e22bd7 upstream.

Commit a5238e360b71 (spi: s3c64xx: move controller information into driver data) introduced separate device names for the different subtypes of the spi controller but forgot to set these in the relevant machines.

To fix this introduce a s3c64xx_spi_setname function and populate all Samsung arches with the correct names. The function resides in a new header, as the s3c64xx-spi.h contains driver platform data and should therefore at some later point move out of the Samsung include dir.

Tested on a s3c2416-based machine.

---
 arch/arm/mach-exynos/common.c                 |    5 ++++
 arch/arm/mach-s3c24xx/s3c2416.c               |    2 +
 arch/arm/mach-s3c24xx/s3c2443.c               |    4 +++
 arch/arm/mach-s5p64x0/common.c                |    3 ++
 arch/arm/mach-s5pc100/common.c                |    3 ++
 arch/arm/mach-s5pv210/common.c                |    3 ++
 arch/arm/plat-samsung/include/plat/spi-core.h |   30 ++++++++++++++++++++++++++
 7 files changed, 50 insertions(+)
arch/arm/mach-exynos/common.c +5 -0
@@ -47,6 +47,7 @@
 #include <plat/fimc-core.h>
 #include <plat/iic-core.h>
 #include <plat/tv-core.h>
+#include <plat/spi-core.h>
 #include <plat/regs-serial.h>
 
 #include "common.h"
@@ -346,6 +347,8 @@ static void __init exynos4_map_io(void)
 
 	s5p_fb_setname(0, "exynos4-fb");
 	s5p_hdmi_setname("exynos4-hdmi");
+
+	s3c64xx_spi_setname("exynos4210-spi");
 }
 
 static void __init exynos5_map_io(void)
@@ -366,6 +369,8 @@ static void __init exynos5_map_io(void)
 	s3c_i2c0_setname("s3c2440-i2c");
 	s3c_i2c1_setname("s3c2440-i2c");
 	s3c_i2c2_setname("s3c2440-i2c");
+
+	s3c64xx_spi_setname("exynos4210-spi");
 }
 
 static void __init exynos4_init_clocks(int xtal)
arch/arm/mach-s3c24xx/s3c2416.c +2 -0
@@ -61,6 +61,7 @@
 #include <plat/nand-core.h>
 #include <plat/adc-core.h>
 #include <plat/rtc-core.h>
+#include <plat/spi-core.h>
 
 static struct map_desc s3c2416_iodesc[] __initdata = {
 	IODESC_ENT(WATCHDOG),
@@ -132,6 +133,7 @@ void __init s3c2416_map_io(void)
 	/* initialize device information early */
 	s3c2416_default_sdhci0();
 	s3c2416_default_sdhci1();
+	s3c64xx_spi_setname("s3c2443-spi");
 
 	iotable_init(s3c2416_iodesc, ARRAY_SIZE(s3c2416_iodesc));
 }
arch/arm/mach-s3c24xx/s3c2443.c +4 -0
@@ -43,6 +43,7 @@
 #include <plat/nand-core.h>
 #include <plat/adc-core.h>
 #include <plat/rtc-core.h>
+#include <plat/spi-core.h>
 
 static struct map_desc s3c2443_iodesc[] __initdata = {
 	IODESC_ENT(WATCHDOG),
@@ -100,6 +101,9 @@ void __init s3c2443_map_io(void)
 	s3c24xx_gpiocfg_default.set_pull = s3c2443_gpio_setpull;
 	s3c24xx_gpiocfg_default.get_pull = s3c2443_gpio_getpull;
 
+	/* initialize device information early */
+	s3c64xx_spi_setname("s3c2443-spi");
+
 	iotable_init(s3c2443_iodesc, ARRAY_SIZE(s3c2443_iodesc));
 }
 
arch/arm/mach-s5p64x0/common.c +3 -0
@@ -44,6 +44,7 @@
 #include <plat/sdhci.h>
 #include <plat/adc-core.h>
 #include <plat/fb-core.h>
+#include <plat/spi-core.h>
 #include <plat/gpio-cfg.h>
 #include <plat/regs-irqtype.h>
 #include <plat/regs-serial.h>
@@ -179,6 +180,7 @@ void __init s5p6440_map_io(void)
 	/* initialize any device information early */
 	s3c_adc_setname("s3c64xx-adc");
 	s3c_fb_setname("s5p64x0-fb");
+	s3c64xx_spi_setname("s5p64x0-spi");
 
 	s5p64x0_default_sdhci0();
 	s5p64x0_default_sdhci1();
@@ -193,6 +195,7 @@ void __init s5p6450_map_io(void)
 	/* initialize any device information early */
 	s3c_adc_setname("s3c64xx-adc");
 	s3c_fb_setname("s5p64x0-fb");
+	s3c64xx_spi_setname("s5p64x0-spi");
 
 	s5p64x0_default_sdhci0();
 	s5p64x0_default_sdhci1();
arch/arm/mach-s5pc100/common.c +3 -0
@@ -45,6 +45,7 @@
 #include <plat/fb-core.h>
 #include <plat/iic-core.h>
 #include <plat/onenand-core.h>
+#include <plat/spi-core.h>
 #include <plat/regs-serial.h>
 #include <plat/watchdog-reset.h>
 
@@ -165,6 +166,8 @@ void __init s5pc100_map_io(void)
 	s3c_onenand_setname("s5pc100-onenand");
 	s3c_fb_setname("s5pc100-fb");
 	s3c_cfcon_setname("s5pc100-pata");
+
+	s3c64xx_spi_setname("s5pc100-spi");
 }
 
 void __init s5pc100_init_clocks(int xtal)
arch/arm/mach-s5pv210/common.c +3 -0
@@ -43,6 +43,7 @@
 #include <plat/iic-core.h>
 #include <plat/keypad-core.h>
 #include <plat/tv-core.h>
+#include <plat/spi-core.h>
 #include <plat/regs-serial.h>
 
 #include "common.h"
@@ -196,6 +197,8 @@ void __init s5pv210_map_io(void)
 
 	/* setup TV devices */
 	s5p_hdmi_setname("s5pv210-hdmi");
+
+	s3c64xx_spi_setname("s5pv210-spi");
 }
 
 void __init s5pv210_init_clocks(int xtal)
arch/arm/plat-samsung/include/plat/spi-core.h new file +30 -0
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2012 Heiko Stuebner <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __PLAT_S3C_SPI_CORE_H
+#define __PLAT_S3C_SPI_CORE_H
+
+/* These functions are only for use with the core support code, such as
+ * the cpu specific initialisation code
+ */
+
+/* re-define device name depending on support. */
+static inline void s3c64xx_spi_setname(char *name)
+{
+#ifdef CONFIG_S3C64XX_DEV_SPI0
+	s3c64xx_device_spi0.name = name;
+#endif
+#ifdef CONFIG_S3C64XX_DEV_SPI1
+	s3c64xx_device_spi1.name = name;
+#endif
+#ifdef CONFIG_S3C64XX_DEV_SPI2
+	s3c64xx_device_spi2.name = name;
+#endif
+}
+
+#endif /* __PLAT_S3C_SPI_CORE_H */
author maintainer
#73 lore raw

PATCH 73/101 ARM: at91/tc: fix typo in the DT document

In reply to Greg Kroah-Hartman

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

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

From: Josh Wu <[email protected]>

commit 11930c530f3edf81160e4962e363d579f5cdce7e upstream.

---
 Documentation/devicetree/bindings/arm/atmel-at91.txt |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
Documentation/devicetree/bindings/arm/atmel-at91.txt +1 -1
@@ -8,7 +8,7 @@ PIT Timer required properties:
   shared across all System Controller members.
 
 TC/TCLIB Timer required properties:
-- compatible: Should be "atmel,<chip>-pit".
+- compatible: Should be "atmel,<chip>-tcb".
   <chip> can be "at91rm9200" or "at91sam9x5"
 - reg: Should contain registers location and length
 - interrupts: Should contain all interrupts for the TC block
author maintainer
#74 lore raw

PATCH 74/101 ARM: at91/i2c: change id to let i2c-gpio work

In reply to Greg Kroah-Hartman

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

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

From: Bo Shen <[email protected]>

commit 7840487cd6298f9f931103b558290d8d98d41c49 upstream.

The i2c core driver will turn the platform device ID to busnum When using platfrom device ID as -1, it means dynamically assigned the busnum. When writing code, we need to make sure the busnum, and call i2c_register_board_info(int busnum, ...) to register device if using -1, we do not know the value of busnum

In order to solve this issue, set the platform device ID as a fix number Here using 0 to match the busnum used in i2c_regsiter_board_info()

---
 arch/arm/mach-at91/at91rm9200_devices.c  |    2 +-
 arch/arm/mach-at91/at91sam9260_devices.c |    2 +-
 arch/arm/mach-at91/at91sam9261_devices.c |    2 +-
 arch/arm/mach-at91/at91sam9263_devices.c |    2 +-
 arch/arm/mach-at91/at91sam9rl_devices.c  |    2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)
arch/arm/mach-at91/at91rm9200_devices.c +1 -1
@@ -463,7 +463,7 @@ static struct i2c_gpio_platform_data pda
 
 static struct platform_device at91rm9200_twi_device = {
 	.name			= "i2c-gpio",
-	.id			= -1,
+	.id			= 0,
 	.dev.platform_data	= &pdata,
 };
 
arch/arm/mach-at91/at91sam9260_devices.c +1 -1
@@ -471,7 +471,7 @@ static struct i2c_gpio_platform_data pda
 
 static struct platform_device at91sam9260_twi_device = {
 	.name			= "i2c-gpio",
-	.id			= -1,
+	.id			= 0,
 	.dev.platform_data	= &pdata,
 };
 
arch/arm/mach-at91/at91sam9261_devices.c +1 -1
@@ -285,7 +285,7 @@ static struct i2c_gpio_platform_data pda
 
 static struct platform_device at91sam9261_twi_device = {
 	.name			= "i2c-gpio",
-	.id			= -1,
+	.id			= 0,
 	.dev.platform_data	= &pdata,
 };
 
arch/arm/mach-at91/at91sam9263_devices.c +1 -1
@@ -542,7 +542,7 @@ static struct i2c_gpio_platform_data pda
 
 static struct platform_device at91sam9263_twi_device = {
 	.name			= "i2c-gpio",
-	.id			= -1,
+	.id			= 0,
 	.dev.platform_data	= &pdata,
 };
 
arch/arm/mach-at91/at91sam9rl_devices.c +1 -1
@@ -314,7 +314,7 @@ static struct i2c_gpio_platform_data pda
 
 static struct platform_device at91sam9rl_twi_device = {
 	.name			= "i2c-gpio",
-	.id			= -1,
+	.id			= 0,
 	.dev.platform_data	= &pdata,
 };
 
author maintainer
#75 lore raw

PATCH 75/101 ARM: at91: at91sam9g10: fix SOC type detection

In reply to Greg Kroah-Hartman

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

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

From: Ivan Shugov <[email protected]>

commit 3d9a0183dd3423353e9e363bcc261c1220d05f9f upstream.

Newer at91sam9g10 SoC revision can't be detected, so the kernel can't boot with this kind of kernel panic:
"AT91: Impossible to detect the SOC type"

CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177
CPU: VIVT data cache, VIVT instruction cache
Machine: Atmel AT91SAM9G10-EK
Ignoring tag cmdline (using the default kernel command line) bootconsole [earlycon0] enabled
Memory policy: ECC disabled, Data cache writeback

Kernel panic - not syncing: AT91: Impossible to detect the SOC type
[<c00133d4>] (unwind_backtrace+0x0/0xe0) from [<c02366dc>] (panic+0x78/0x1cc)
[<c02366dc>] (panic+0x78/0x1cc) from [<c02fa35c>] (at91_map_io+0x90/0xc8)
[<c02fa35c>] (at91_map_io+0x90/0xc8) from [<c02f9860>] (paging_init+0x564/0x6d0)
[<c02f9860>] (paging_init+0x564/0x6d0) from [<c02f7914>] (setup_arch+0x464/0x704)
[<c02f7914>] (setup_arch+0x464/0x704) from [<c02f44f8>] (start_kernel+0x6c/0x2d4)
[<c02f44f8>] (start_kernel+0x6c/0x2d4) from [<20008040>] (0x20008040)

The reason for this is that the Debug Unit Chip ID Register has changed between Engineering Sample and definitive revision of the SoC. Changing the check of cidr to socid will address the problem. We do not integrate this check to the list just above because we also have to make sure that the extended id is disregarded.

---
 arch/arm/mach-at91/setup.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/mach-at91/setup.c +1 -1
@@ -151,7 +151,7 @@ static void __init soc_detect(u32 dbgu_b
 	}
 
 	/* at91sam9g10 */
-	if ((cidr & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) {
+	if ((socid & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) {
 		at91_soc_initdata.type = AT91_SOC_SAM9G10;
 		at91_boot_soc = at91sam9261_soc;
 	}
author maintainer
#76 lore raw

PATCH 76/101 ARM: at91: fix external interrupts in non-DT case

In reply to Greg Kroah-Hartman

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

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

From: Nicolas Ferre <[email protected]>

commit 738a0fd752dc60e20beeda6f2f0f62e58dc0e344 upstream.

Management of external interrupts has changed but the non-DT code has not integrated these changes. Add a mask to pass external irq specification from SoC specific code to the at91_aic_init() function.

---
 arch/arm/mach-at91/generic.h |    3 ++-
 arch/arm/mach-at91/irq.c     |    9 +++++++--
 arch/arm/mach-at91/setup.c   |    2 +-
 3 files changed, 10 insertions(+), 4 deletions(-)
arch/arm/mach-at91/generic.h +2 -1
@@ -26,7 +26,8 @@ extern void __init at91_dt_initialize(vo
 extern void __init at91_init_irq_default(void);
 extern void __init at91_init_interrupts(unsigned int priority[]);
 extern void __init at91x40_init_interrupts(unsigned int priority[]);
-extern void __init at91_aic_init(unsigned int priority[]);
+extern void __init at91_aic_init(unsigned int priority[],
+				 unsigned int ext_irq_mask);
 extern int  __init at91_aic_of_init(struct device_node *node,
 				    struct device_node *parent);
 extern int  __init at91_aic5_of_init(struct device_node *node,
arch/arm/mach-at91/irq.c +7 -2
@@ -502,14 +502,19 @@ int __init at91_aic5_of_init(struct devi
 /*
  * Initialize the AIC interrupt controller.
  */
-void __init at91_aic_init(unsigned int *priority)
+void __init at91_aic_init(unsigned int *priority, unsigned int ext_irq_mask)
 {
 	unsigned int i;
 	int irq_base;
 
-	if (at91_aic_pm_init())
+	at91_extern_irq = kzalloc(BITS_TO_LONGS(n_irqs)
+				  * sizeof(*at91_extern_irq), GFP_KERNEL);
+
+	if (at91_aic_pm_init() || at91_extern_irq == NULL)
 		panic("Unable to allocate bit maps\n");
 
+	*at91_extern_irq = ext_irq_mask;
+
 	at91_aic_base = ioremap(AT91_AIC, 512);
 	if (!at91_aic_base)
 		panic("Unable to ioremap AIC registers\n");
arch/arm/mach-at91/setup.c +1 -1
@@ -47,7 +47,7 @@ void __init at91_init_irq_default(void)
 void __init at91_init_interrupts(unsigned int *priority)
 {
 	/* Initialize the AIC interrupt controller */
-	at91_aic_init(priority);
+	at91_aic_init(priority, at91_extern_irq);
 
 	/* Enable GPIO interrupts */
 	at91_gpio_irq_setup();
author maintainer
#77 lore raw

PATCH 77/101 ARM: at91: fix external interrupt specification in board code

In reply to Greg Kroah-Hartman

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

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

From: Nicolas Ferre <[email protected]>

commit 69e7ea04c9365626c0963ff09bbaa3a1b49e293a upstream.

Since the switch to sparse irq, we have to add the NR_IRQS_LEGACY offset to static irq numbers. It has been forgotten on these SPI irq definitions in board code.

---
 arch/arm/mach-at91/board-neocore926.c |    2 +-
 arch/arm/mach-at91/board-sam9261ek.c  |    2 +-
 arch/arm/mach-at91/board-sam9263ek.c  |    2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)
arch/arm/mach-at91/board-neocore926.c +1 -1
@@ -129,7 +129,7 @@ static struct spi_board_info neocore926_
 		.max_speed_hz	= 125000 * 16,
 		.bus_num	= 0,
 		.platform_data	= &ads_info,
-		.irq		= AT91SAM9263_ID_IRQ1,
+		.irq		= NR_IRQS_LEGACY + AT91SAM9263_ID_IRQ1,
 	},
 #endif
 };
arch/arm/mach-at91/board-sam9261ek.c +1 -1
@@ -309,7 +309,7 @@ static struct spi_board_info ek_spi_devi
 		.max_speed_hz	= 125000 * 26,	/* (max sample rate @ 3V) * (cmd + data + overhead) */
 		.bus_num	= 0,
 		.platform_data	= &ads_info,
-		.irq		= AT91SAM9261_ID_IRQ0,
+		.irq		= NR_IRQS_LEGACY + AT91SAM9261_ID_IRQ0,
 		.controller_data = (void *) AT91_PIN_PA28,	/* CS pin */
 	},
 #endif
arch/arm/mach-at91/board-sam9263ek.c +1 -1
@@ -132,7 +132,7 @@ static struct spi_board_info ek_spi_devi
 		.max_speed_hz	= 125000 * 26,	/* (max sample rate @ 3V) * (cmd + data + overhead) */
 		.bus_num	= 0,
 		.platform_data	= &ads_info,
-		.irq		= AT91SAM9263_ID_IRQ1,
+		.irq		= NR_IRQS_LEGACY + AT91SAM9263_ID_IRQ1,
 	},
 #endif
 };
author maintainer
#78 lore raw

PATCH 78/101 mac80211: connect with HT20 if HT40 is not permitted

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

commit 3a40414f826a8f1096d9b94c4a53ef91b25ba28d upstream.

Some changes to fix issues with HT40 APs in Korea and follow-up changes to allow using HT40 even if the local regulatory database disallows it caused issues with iwlwifi (and could cause issues with other devices); iwlwifi firmware would assert if you tried to connect to an AP that has an invalid configuration (e.g. using HT40- on channel 140.)

Fix this, while avoiding the "Korean AP" issue by disabling HT40 and advertising HT20 to the AP when connecting.

---
 net/mac80211/mlme.c |   30 ++++++++++++++++++++----------
 1 file changed, 20 insertions(+), 10 deletions(-)
net/mac80211/mlme.c +20 -10
@@ -3065,22 +3065,32 @@ static int ieee80211_prep_connection(str
 				   ht_cfreq, ht_oper->primary_chan,
 				   cbss->channel->band);
 			ht_oper = NULL;
+		} else {
+			channel_type = NL80211_CHAN_HT20;
 		}
 	}
 
-	if (ht_oper) {
-		channel_type = NL80211_CHAN_HT20;
+	if (ht_oper && sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
+		/*
+		 * cfg80211 already verified that the channel itself can
+		 * be used, but it didn't check that we can do the right
+		 * HT type, so do that here as well. If HT40 isn't allowed
+		 * on this channel, disable 40 MHz operation.
+		 */
 
-		if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
-			switch (ht_oper->ht_param &
-					IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
-			case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+		switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
+		case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+			if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40PLUS)
+				ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ;
+			else
 				channel_type = NL80211_CHAN_HT40PLUS;
-				break;
-			case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+			break;
+		case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+			if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40MINUS)
+				ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ;
+			else
 				channel_type = NL80211_CHAN_HT40MINUS;
-				break;
-			}
+			break;
 		}
 	}
 
author maintainer
#79 lore raw

PATCH 79/101 mac80211: check if key has TKIP type before updating IV

In reply to Greg Kroah-Hartman

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

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

From: Stanislaw Gruszka <[email protected]>

commit 4045f72bcf3c293c7c5932ef001742d8bb5ded76 upstream.

This patch fix corruption which can manifest itself by following crash when switching on rfkill switch with rt2x00 driver:
https://bugzilla.redhat.com/attachment.cgi?id=615362

Pointer key->u.ccmp.tfm of group key get corrupted in:

ieee80211_rx_h_michael_mic_verify():

        /* update IV in key information to be able to detect replays */
        rx->key->u.tkip.rx[rx->security_idx].iv32 = rx->tkip_iv32;
        rx->key->u.tkip.rx[rx->security_idx].iv16 = rx->tkip_iv16;

because rt2x00 always set RX_FLAG_MMIC_STRIPPED, even if key is not TKIP.

We already check type of the key in different path in ieee80211_rx_h_michael_mic_verify() function, so adding additional check here is reasonable.

---
 net/mac80211/wpa.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
net/mac80211/wpa.c +2 -1
@@ -106,7 +106,8 @@ ieee80211_rx_h_michael_mic_verify(struct
 		if (status->flag & RX_FLAG_MMIC_ERROR)
 			goto mic_fail;
 
-		if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key)
+		if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key &&
+		    rx->key->conf.cipher == WLAN_CIPHER_SUITE_TKIP)
 			goto update_iv;
 
 		return RX_CONTINUE;
author maintainer
#80 lore raw

PATCH 80/101 mac80211: use ieee80211_free_txskb in a few more places

In reply to Greg Kroah-Hartman

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

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

From: Felix Fietkau <[email protected]>

commit d4fa14cd62bd078c8e3ef39283b9f237e5b2ff0f upstream.

Free tx status skbs when draining power save buffers, pending frames, or when tearing down a vif.
Fixes remaining conditions that can lead to hostapd/wpa_supplicant hangs when running out of socket write memory.

---
 net/mac80211/iface.c    |    2 +-
 net/mac80211/sta_info.c |    4 ++--
 net/mac80211/util.c     |    4 ++--
 3 files changed, 5 insertions(+), 5 deletions(-)
net/mac80211/iface.c +1 -1
@@ -822,7 +822,7 @@ static void ieee80211_do_stop(struct iee
 			struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 			if (info->control.vif == &sdata->vif) {
 				__skb_unlink(skb, &local->pending[i]);
-				dev_kfree_skb_irq(skb);
+				ieee80211_free_txskb(&local->hw, skb);
 			}
 		}
 	}
net/mac80211/sta_info.c +2 -2
@@ -585,7 +585,7 @@ static bool sta_info_cleanup_expire_buff
 		 */
 		if (!skb)
 			break;
-		dev_kfree_skb(skb);
+		ieee80211_free_txskb(&local->hw, skb);
 	}
 
 	/*
@@ -614,7 +614,7 @@ static bool sta_info_cleanup_expire_buff
 		local->total_ps_buffered--;
 		ps_dbg(sta->sdata, "Buffered frame expired (STA %pM)\n",
 		       sta->sta.addr);
-		dev_kfree_skb(skb);
+		ieee80211_free_txskb(&local->hw, skb);
 	}
 
 	/*
net/mac80211/util.c +2 -2
@@ -400,7 +400,7 @@ void ieee80211_add_pending_skb(struct ie
 	int queue = info->hw_queue;
 
 	if (WARN_ON(!info->control.vif)) {
-		kfree_skb(skb);
+		ieee80211_free_txskb(&local->hw, skb);
 		return;
 	}
 
@@ -425,7 +425,7 @@ void ieee80211_add_pending_skbs_fn(struc
 		struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
 		if (WARN_ON(!info->control.vif)) {
-			kfree_skb(skb);
+			ieee80211_free_txskb(&local->hw, skb);
 			continue;
 		}
 
author maintainer
#81 lore raw

PATCH 81/101 b43: Fix oops on unload when firmware not found

In reply to Greg Kroah-Hartman

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

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

From: Larry Finger <[email protected]>

commit f89ff6441df06abc2d95f3ef67525923032d6283 upstream.

When b43 fails to find firmware when loaded, a subsequent unload will oops due to calling ieee80211_unregister_hw() when the corresponding register call was never made.

Commit 2d838bb608e2d1f6cb4280e76748cb812dc822e7 fixed the same problem for b43legacy.

---
 drivers/net/wireless/b43/main.c |    4 ++++
 1 file changed, 4 insertions(+)
drivers/net/wireless/b43/main.c +4 -0
@@ -5374,6 +5374,8 @@ static void b43_bcma_remove(struct bcma_
 	cancel_work_sync(&wldev->restart_work);
 
 	B43_WARN_ON(!wl);
+	if (!wldev->fw.ucode.data)
+		return;			/* NULL if firmware never loaded */
 	if (wl->current_dev == wldev && wl->hw_registred) {
 		b43_leds_stop(wldev);
 		ieee80211_unregister_hw(wl->hw);
@@ -5448,6 +5450,8 @@ static void b43_ssb_remove(struct ssb_de
 	cancel_work_sync(&wldev->restart_work);
 
 	B43_WARN_ON(!wl);
+	if (!wldev->fw.ucode.data)
+		return;			/* NULL if firmware never loaded */
 	if (wl->current_dev == wldev && wl->hw_registred) {
 		b43_leds_stop(wldev);
 		ieee80211_unregister_hw(wl->hw);
author maintainer
#82 lore raw

PATCH 82/101 tilegx: fix some issues in the SW TSO support

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 3da3fff8006c608f19a51859d44ba47ca8b41461 upstream.

This change correctly computes the header length and data length in the fragments to avoid a bug where we would end up with extremely slow performance. Also adopt use of skb_frag_size() accessor.

---
 drivers/net/ethernet/tile/tilegx.c |   35 +++++++++++++++++++----------------
 1 file changed, 19 insertions(+), 16 deletions(-)
drivers/net/ethernet/tile/tilegx.c +19 -16
@@ -1334,11 +1334,11 @@ static int tso_count_edescs(struct sk_bu
 {
 	struct skb_shared_info *sh = skb_shinfo(skb);
 	unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-	unsigned int data_len = skb->data_len + skb->hdr_len - sh_len;
+	unsigned int data_len = skb->len - sh_len;
 	unsigned int p_len = sh->gso_size;
 	long f_id = -1;    /* id of the current fragment */
-	long f_size = skb->hdr_len;  /* size of the current fragment */
-	long f_used = sh_len;  /* bytes used from the current fragment */
+	long f_size = skb_headlen(skb) - sh_len;  /* current fragment size */
+	long f_used = 0;  /* bytes used from the current fragment */
 	long n;            /* size of the current piece of payload */
 	int num_edescs = 0;
 	int segment;
@@ -1353,7 +1353,7 @@ static int tso_count_edescs(struct sk_bu
 			/* Advance as needed. */
 			while (f_used >= f_size) {
 				f_id++;
-				f_size = sh->frags[f_id].size;
+				f_size = skb_frag_size(&sh->frags[f_id]);
 				f_used = 0;
 			}
 
@@ -1384,13 +1384,13 @@ static void tso_headers_prepare(struct s
 	struct iphdr *ih;
 	struct tcphdr *th;
 	unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-	unsigned int data_len = skb->data_len + skb->hdr_len - sh_len;
+	unsigned int data_len = skb->len - sh_len;
 	unsigned char *data = skb->data;
 	unsigned int ih_off, th_off, p_len;
 	unsigned int isum_seed, tsum_seed, id, seq;
 	long f_id = -1;    /* id of the current fragment */
-	long f_size = skb->hdr_len;  /* size of the current fragment */
-	long f_used = sh_len;  /* bytes used from the current fragment */
+	long f_size = skb_headlen(skb) - sh_len;  /* current fragment size */
+	long f_used = 0;  /* bytes used from the current fragment */
 	long n;            /* size of the current piece of payload */
 	int segment;
 
@@ -1405,7 +1405,7 @@ static void tso_headers_prepare(struct s
 	isum_seed = ((0xFFFF - ih->check) +
 		     (0xFFFF - ih->tot_len) +
 		     (0xFFFF - ih->id));
-	tsum_seed = th->check + (0xFFFF ^ htons(sh_len + data_len));
+	tsum_seed = th->check + (0xFFFF ^ htons(skb->len));
 	id = ntohs(ih->id);
 	seq = ntohl(th->seq);
 
@@ -1444,7 +1444,7 @@ static void tso_headers_prepare(struct s
 			/* Advance as needed. */
 			while (f_used >= f_size) {
 				f_id++;
-				f_size = sh->frags[f_id].size;
+				f_size = skb_frag_size(&sh->frags[f_id]);
 				f_used = 0;
 			}
 
@@ -1478,14 +1478,14 @@ static void tso_egress(struct net_device
 	struct tile_net_priv *priv = netdev_priv(dev);
 	struct skb_shared_info *sh = skb_shinfo(skb);
 	unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-	unsigned int data_len = skb->data_len + skb->hdr_len - sh_len;
+	unsigned int data_len = skb->len - sh_len;
 	unsigned int p_len = sh->gso_size;
 	gxio_mpipe_edesc_t edesc_head = { { 0 } };
 	gxio_mpipe_edesc_t edesc_body = { { 0 } };
 	long f_id = -1;    /* id of the current fragment */
-	long f_size = skb->hdr_len;  /* size of the current fragment */
-	long f_used = sh_len;  /* bytes used from the current fragment */
-	void *f_data = skb->data;
+	long f_size = skb_headlen(skb) - sh_len;  /* current fragment size */
+	long f_used = 0;  /* bytes used from the current fragment */
+	void *f_data = skb->data + sh_len;
 	long n;            /* size of the current piece of payload */
 	unsigned long tx_packets = 0, tx_bytes = 0;
 	unsigned int csum_start;
@@ -1516,15 +1516,18 @@ static void tso_egress(struct net_device
 
 		/* Egress the payload. */
 		while (p_used < p_len) {
+			void *va;
 
 			/* Advance as needed. */
 			while (f_used >= f_size) {
 				f_id++;
-				f_size = sh->frags[f_id].size;
-				f_used = 0;
+				f_size = skb_frag_size(&sh->frags[f_id]);
 				f_data = tile_net_frag_buf(&sh->frags[f_id]);
+				f_used = 0;
 			}
 
+			va = f_data + f_used;
+
 			/* Use bytes from the current fragment. */
 			n = p_len - p_used;
 			if (n > f_size - f_used)
@@ -1533,7 +1536,7 @@ static void tso_egress(struct net_device
 			p_used += n;
 
 			/* Egress a piece of the payload. */
-			edesc_body.va = va_to_tile_io_addr(f_data) + f_used;
+			edesc_body.va = va_to_tile_io_addr(va);
 			edesc_body.xfer_size = n;
 			edesc_body.bound = !(p_used < p_len);
 			gxio_mpipe_equeue_put_at(equeue, edesc_body, slot);
author maintainer
#83 lore raw

PATCH 83/101 Bluetooth: SMP: Fix setting unknown auth_req bits

In reply to Greg Kroah-Hartman

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

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

From: Johan Hedberg <[email protected]>

commit 065a13e2cc665f6547dc7e8a9d6b6565badf940a upstream.

When sending a pairing request or response we should not just blindly copy the value that the remote device sent. Instead we should at least make sure to mask out any unknown bits. This is particularly critical from the upcoming LE Secure Connections feature perspective as incorrectly indicating support for it (by copying the remote value) would cause a failure to pair with devices that support it.

---
 net/bluetooth/smp.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
net/bluetooth/smp.c +4 -2
@@ -32,6 +32,8 @@
 
 #define SMP_TIMEOUT	msecs_to_jiffies(30000)
 
+#define AUTH_REQ_MASK   0x07
+
 static inline void swap128(u8 src[16], u8 dst[16])
 {
 	int i;
@@ -230,7 +232,7 @@ static void build_pairing_cmd(struct l2c
 		req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
 		req->init_key_dist = 0;
 		req->resp_key_dist = dist_keys;
-		req->auth_req = authreq;
+		req->auth_req = (authreq & AUTH_REQ_MASK);
 		return;
 	}
 
@@ -239,7 +241,7 @@ static void build_pairing_cmd(struct l2c
 	rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
 	rsp->init_key_dist = 0;
 	rsp->resp_key_dist = req->resp_key_dist & dist_keys;
-	rsp->auth_req = authreq;
+	rsp->auth_req = (authreq & AUTH_REQ_MASK);
 }
 
 static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
author maintainer
#84 lore raw

PATCH 84/101 qmi_wwan/cdc_ether: move Novatel 551 and E362 to qmi_wwan

In reply to Greg Kroah-Hartman

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

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

From: Dan Williams <[email protected]>

commit f8295ec22cb0f1ee6849b862addbfa3ea9320755 upstream.

These devices provide QMI and ethernet functionality via a standard CDC ethernet descriptor. But when driven by cdc_ether, the QMI functionality is unavailable because only cdc_ether can claim the USB interface. Thus blacklist the devices in cdc_ether and add their IDs to qmi_wwan, which enables both QMI and ethernet simultaneously.

---
 drivers/net/usb/cdc_ether.c |   41 ++++++++++++++++++++++++++---------------
 drivers/net/usb/qmi_wwan.c  |   14 ++++++++++++++
 2 files changed, 40 insertions(+), 15 deletions(-)
drivers/net/usb/cdc_ether.c +26 -15
@@ -592,6 +592,32 @@ static const struct usb_device_id	produc
 	.driver_info		= 0,
 },
 
+/* Novatel USB551L and MC551 - handled by qmi_wwan */
+{
+	.match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
+		 | USB_DEVICE_ID_MATCH_PRODUCT
+		 | USB_DEVICE_ID_MATCH_INT_INFO,
+	.idVendor               = NOVATEL_VENDOR_ID,
+	.idProduct		= 0xB001,
+	.bInterfaceClass	= USB_CLASS_COMM,
+	.bInterfaceSubClass	= USB_CDC_SUBCLASS_ETHERNET,
+	.bInterfaceProtocol	= USB_CDC_PROTO_NONE,
+	.driver_info = 0,
+},
+
+/* Novatel E362 - handled by qmi_wwan */
+{
+	.match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
+		 | USB_DEVICE_ID_MATCH_PRODUCT
+		 | USB_DEVICE_ID_MATCH_INT_INFO,
+	.idVendor               = NOVATEL_VENDOR_ID,
+	.idProduct		= 0x9010,
+	.bInterfaceClass	= USB_CLASS_COMM,
+	.bInterfaceSubClass	= USB_CDC_SUBCLASS_ETHERNET,
+	.bInterfaceProtocol	= USB_CDC_PROTO_NONE,
+	.driver_info = 0,
+},
+
 /*
  * WHITELIST!!!
  *
@@ -604,21 +630,6 @@ static const struct usb_device_id	produc
  * because of bugs/quirks in a given product (like Zaurus, above).
  */
 {
-	/* Novatel USB551L */
-	/* This match must come *before* the generic CDC-ETHER match so that
-	 * we get FLAG_WWAN set on the device, since it's descriptors are
-	 * generic CDC-ETHER.
-	 */
-	.match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
-		 | USB_DEVICE_ID_MATCH_PRODUCT
-		 | USB_DEVICE_ID_MATCH_INT_INFO,
-	.idVendor               = NOVATEL_VENDOR_ID,
-	.idProduct		= 0xB001,
-	.bInterfaceClass	= USB_CLASS_COMM,
-	.bInterfaceSubClass	= USB_CDC_SUBCLASS_ETHERNET,
-	.bInterfaceProtocol	= USB_CDC_PROTO_NONE,
-	.driver_info = (unsigned long)&wwan_info,
-}, {
 	/* ZTE (Vodafone) K3805-Z */
 	.match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
 		 | USB_DEVICE_ID_MATCH_PRODUCT
drivers/net/usb/qmi_wwan.c +14 -0
@@ -364,6 +364,20 @@ static const struct usb_device_id produc
 		USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 57),
 		.driver_info        = (unsigned long)&qmi_wwan_info,
 	},
+	{	/* Novatel USB551L and MC551 */
+		USB_DEVICE_AND_INTERFACE_INFO(0x1410, 0xb001,
+		                              USB_CLASS_COMM,
+		                              USB_CDC_SUBCLASS_ETHERNET,
+		                              USB_CDC_PROTO_NONE),
+		.driver_info        = (unsigned long)&qmi_wwan_info,
+	},
+	{	/* Novatel E362 */
+		USB_DEVICE_AND_INTERFACE_INFO(0x1410, 0x9010,
+		                              USB_CLASS_COMM,
+		                              USB_CDC_SUBCLASS_ETHERNET,
+		                              USB_CDC_PROTO_NONE),
+		.driver_info        = (unsigned long)&qmi_wwan_info,
+	},
 
 	/* 2. Combined interface devices matching on class+protocol */
 	{	/* Huawei E367 and possibly others in "Windows mode" */
author maintainer
#85 lore raw

PATCH 85/101 freezer: exec should clear PF_NOFREEZE along with PF_KTHREAD

In reply to Greg Kroah-Hartman

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

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

From: Oleg Nesterov <[email protected]>

commit b40a79591ca918e7b91b0d9b6abd5d00f2e88c19 upstream.

flush_old_exec() clears PF_KTHREAD but forgets about PF_NOFREEZE.

---
 fs/exec.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
fs/exec.c +2 -1
@@ -1110,7 +1110,8 @@ int flush_old_exec(struct linux_binprm *
 	bprm->mm = NULL;		/* We're using it now */
 
 	set_fs(USER_DS);
-	current->flags &= ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD);
+	current->flags &=
+		~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD | PF_NOFREEZE);
 	flush_thread();
 	current->personality &= ~bprm->per_clear;
 
author maintainer
#86 lore raw

PATCH 86/101 dmaengine: sirf: fix a typo in dma_prep_interleaved

In reply to Greg Kroah-Hartman

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

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

From: Barry Song <[email protected]>

commit 5997e089e4c3a7f0958a8fb0a54ec2b5a6f06168 upstream.

either DEV_TO_MEM or MEM_TO_DEV is supported, so change OR to AND.

---
 drivers/dma/sirf-dma.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/dma/sirf-dma.c +1 -1
@@ -428,7 +428,7 @@ static struct dma_async_tx_descriptor *s
 	unsigned long iflags;
 	int ret;
 
-	if ((xt->dir != DMA_MEM_TO_DEV) || (xt->dir != DMA_DEV_TO_MEM)) {
+	if ((xt->dir != DMA_MEM_TO_DEV) && (xt->dir != DMA_DEV_TO_MEM)) {
 		ret = -EINVAL;
 		goto err_dir;
 	}
author maintainer
#87 lore raw

PATCH 87/101 dmaengine: sirf: fix a typo in moving running dma_desc to active queue

In reply to Greg Kroah-Hartman

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

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

From: Barry Song <[email protected]>

commit 26fd12209c08fe947be1828896ef4ffc5bd0e6df upstream.

list_move_tail(&schan->queued, &schan->active) makes the list_empty(schan->queued) undefined, we either should change it to:
list_move_tail(schan->queued.next, &schan->active)
or
list_move_tail(&sdesc->node, &schan->active)

---
 drivers/dma/sirf-dma.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/dma/sirf-dma.c +1 -1
@@ -109,7 +109,7 @@ static void sirfsoc_dma_execute(struct s
 	sdesc = list_first_entry(&schan->queued, struct sirfsoc_dma_desc,
 		node);
 	/* Move the first queued descriptor to active list */
-	list_move_tail(&schan->queued, &schan->active);
+	list_move_tail(&sdesc->node, &schan->active);
 
 	/* Start the DMA transfer */
 	writel_relaxed(sdesc->width, sdma->base + SIRFSOC_DMA_WIDTH_0 +
author maintainer
#88 lore raw

PATCH 88/101 dmaengine: imx-dma: fix missing unlock on error in imxdma_xfer_desc()

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 720dfd250e48a8c7fd1b2b8645955413989c4ee0 upstream.

Add the missing unlock on the error handling path in function imxdma_xfer_desc().

---
 drivers/dma/imx-dma.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/dma/imx-dma.c +3 -1
@@ -474,8 +474,10 @@ static int imxdma_xfer_desc(struct imxdm
 			slot = i;
 			break;
 		}
-		if (slot < 0)
+		if (slot < 0) {
+			spin_unlock_irqrestore(&imxdma->lock, flags);
 			return -EBUSY;
+		}
 
 		imxdma->slots_2d[slot].xsr = d->x;
 		imxdma->slots_2d[slot].ysr = d->y;
author maintainer
#89 lore raw

PATCH 89/101 iwlwifi: fix 6000 series channel switch command

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

commit 8f7b8db6e0557c8437adf9371e020cd89a7e85dc upstream.

The channel switch command for 6000 series devices is larger than the maximum inline command size of 320 bytes. The command is therefore refused with a warning. Fix this by allocating the command and using the NOCOPY mechanism.

---
 drivers/net/wireless/iwlwifi/dvm/devices.c |   39 +++++++++++++++++------------
 1 file changed, 24 insertions(+), 15 deletions(-)
drivers/net/wireless/iwlwifi/dvm/devices.c +24 -15
@@ -518,7 +518,7 @@ static int iwl6000_hw_channel_switch(str
 	 * See iwlagn_mac_channel_switch.
 	 */
 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-	struct iwl6000_channel_switch_cmd cmd;
+	struct iwl6000_channel_switch_cmd *cmd;
 	u32 switch_time_in_usec, ucode_switch_time;
 	u16 ch;
 	u32 tsf_low;
@@ -527,18 +527,25 @@ static int iwl6000_hw_channel_switch(str
 	struct ieee80211_vif *vif = ctx->vif;
 	struct iwl_host_cmd hcmd = {
 		.id = REPLY_CHANNEL_SWITCH,
-		.len = { sizeof(cmd), },
+		.len = { sizeof(*cmd), },
 		.flags = CMD_SYNC,
-		.data = { &cmd, },
+		.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
 	};
+	int err;
 
-	cmd.band = priv->band == IEEE80211_BAND_2GHZ;
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd)
+		return -ENOMEM;
+
+	hcmd.data[0] = cmd;
+
+	cmd->band = priv->band == IEEE80211_BAND_2GHZ;
 	ch = ch_switch->channel->hw_value;
 	IWL_DEBUG_11H(priv, "channel switch from %u to %u\n",
 		      ctx->active.channel, ch);
-	cmd.channel = cpu_to_le16(ch);
-	cmd.rxon_flags = ctx->staging.flags;
-	cmd.rxon_filter_flags = ctx->staging.filter_flags;
+	cmd->channel = cpu_to_le16(ch);
+	cmd->rxon_flags = ctx->staging.flags;
+	cmd->rxon_filter_flags = ctx->staging.filter_flags;
 	switch_count = ch_switch->count;
 	tsf_low = ch_switch->timestamp & 0x0ffffffff;
 	/*
@@ -554,23 +561,25 @@ static int iwl6000_hw_channel_switch(str
 			switch_count = 0;
 	}
 	if (switch_count <= 1)
-		cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
+		cmd->switch_time = cpu_to_le32(priv->ucode_beacon_time);
 	else {
 		switch_time_in_usec =
 			vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
 		ucode_switch_time = iwl_usecs_to_beacons(priv,
 							 switch_time_in_usec,
 							 beacon_interval);
-		cmd.switch_time = iwl_add_beacon_time(priv,
-						      priv->ucode_beacon_time,
-						      ucode_switch_time,
-						      beacon_interval);
+		cmd->switch_time = iwl_add_beacon_time(priv,
+						       priv->ucode_beacon_time,
+						       ucode_switch_time,
+						       beacon_interval);
 	}
 	IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
-		      cmd.switch_time);
-	cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR;
+		      cmd->switch_time);
+	cmd->expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR;
 
-	return iwl_dvm_send_cmd(priv, &hcmd);
+	err = iwl_dvm_send_cmd(priv, &hcmd);
+	kfree(cmd);
+	return err;
 }
 
 struct iwl_lib_ops iwl6000_lib = {
author maintainer
#90 lore raw

PATCH 90/101 bcma: fix unregistration of cores

In reply to Greg Kroah-Hartman

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

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

From: Piotr Haber <[email protected]>

commit 1fffa905adffbf0d3767fc978ef09afb830275eb upstream.

When cores are unregistered, entries
need to be removed from cores list in a safe manner.

---
 drivers/bcma/main.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/bcma/main.c +3 -2
@@ -141,9 +141,10 @@ static int bcma_register_cores(struct bc
 
 static void bcma_unregister_cores(struct bcma_bus *bus)
 {
-	struct bcma_device *core;
+	struct bcma_device *core, *tmp;
 
-	list_for_each_entry(core, &bus->cores, list) {
+	list_for_each_entry_safe(core, tmp, &bus->cores, list) {
+		list_del(&core->list);
 		if (core->dev_registered)
 			device_unregister(&core->dev);
 	}
author maintainer
#91 lore raw

PATCH 91/101 net/wireless: ipw2200: Fix panic occurring in ipw_handle_promiscuous_tx()

In reply to Greg Kroah-Hartman

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

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

From: Stanislav Yakovlev <[email protected]>

commit bf11315eeda510ea4fc1a2bf972d8155d31d89b4 upstream.

The driver does not count space of radiotap fields when allocating skb for radiotap packet. This leads to kernel panic with the following call trace:

...

[67607.676067] [<c152f90f>] error_code+0x67/0x6c
[67607.676067] [<c142f831>] ? skb_put+0x91/0xa0
[67607.676067] [<f8cf5e5b>] ? ipw_handle_promiscuous_tx+0x16b/0x2d0 [ipw2200]
[67607.676067] [<f8cf5e5b>] ipw_handle_promiscuous_tx+0x16b/0x2d0 [ipw2200]
[67607.676067] [<f8cf899b>] ipw_net_hard_start_xmit+0x8b/0x90 [ipw2200]
[67607.676067] [<f8741c5a>] libipw_xmit+0x55a/0x980 [libipw]
[67607.676067] [<c143d3e8>] dev_hard_start_xmit+0x218/0x4d0

...

This bug was found by VittGam.
https://bugzilla.kernel.org/show_bug.cgi?id=43255

---
 drivers/net/wireless/ipw2x00/ipw2200.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/ipw2x00/ipw2200.c +1 -1
@@ -10479,7 +10479,7 @@ static void ipw_handle_promiscuous_tx(st
 		} else
 			len = src->len;
 
-		dst = alloc_skb(len + sizeof(*rt_hdr), GFP_ATOMIC);
+		dst = alloc_skb(len + sizeof(*rt_hdr) + sizeof(u16)*2, GFP_ATOMIC);
 		if (!dst)
 			continue;
 
author maintainer
#92 lore raw

PATCH 92/101 cpufreq / powernow-k8: Remove usage of smp_processor_id() in preemptible code

In reply to Greg Kroah-Hartman

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

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

From: Andreas Herrmann <[email protected]>

commit e4df1cbcc1f329e53a1fff7450b2229e0addff20 upstream.

Commit 6889125b8b4e09c5e53e6ecab3433bed1ce198c9
(cpufreq/powernow-k8: workqueue user shouldn't migrate the kworker to another CPU) causes powernow-k8 to trigger a preempt warning, e.g.:

  BUG: using smp_processor_id() in preemptible [00000000] code: cpufreq/3776
  caller is powernowk8_target+0x20/0x49
  Pid: 3776, comm: cpufreq Not tainted 3.6.0 #9
  Call Trace:
   [<ffffffff8125b447>] debug_smp_processor_id+0xc7/0xe0
   [<ffffffff814877e7>] powernowk8_target+0x20/0x49
   [<ffffffff81482b02>] __cpufreq_driver_target+0x82/0x8a
   [<ffffffff81484fc6>] cpufreq_governor_performance+0x4e/0x54
   [<ffffffff81482c50>] __cpufreq_governor+0x8c/0xc9
   [<ffffffff81482e6f>] __cpufreq_set_policy+0x1a9/0x21e
   [<ffffffff814839af>] store_scaling_governor+0x16f/0x19b
   [<ffffffff81484f16>] ? cpufreq_update_policy+0x124/0x124
   [<ffffffff8162b4a5>] ? _raw_spin_unlock_irqrestore+0x2c/0x49
   [<ffffffff81483640>] store+0x60/0x88
   [<ffffffff811708c0>] sysfs_write_file+0xf4/0x130
   [<ffffffff8111243b>] vfs_write+0xb5/0x151
   [<ffffffff811126e0>] sys_write+0x4a/0x71
   [<ffffffff816319a9>] system_call_fastpath+0x16/0x1b

Fix this by by always using work_on_cpu().

---
 drivers/cpufreq/powernow-k8.c |    9 +--------
 1 file changed, 1 insertion(+), 8 deletions(-)
drivers/cpufreq/powernow-k8.c +1 -8
@@ -1223,14 +1223,7 @@ static int powernowk8_target(struct cpuf
 	struct powernowk8_target_arg pta = { .pol = pol, .targfreq = targfreq,
 					     .relation = relation };
 
-	/*
-	 * Must run on @pol->cpu.  cpufreq core is responsible for ensuring
-	 * that we're bound to the current CPU and pol->cpu stays online.
-	 */
-	if (smp_processor_id() == pol->cpu)
-		return powernowk8_target_fn(&pta);
-	else
-		return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta);
+	return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta);
 }
 
 /* Driver entry point to verify the policy and range of frequencies */
author maintainer
#93 lore raw

PATCH 93/101 Revert "ath9k_hw: Updated AR9003 tx gain table for 5GHz"

In reply to Greg Kroah-Hartman

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

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

From: Felix Fietkau <[email protected]>

commit 73b26df5fa1a6245d6fc982362518b620bc7c2fe upstream.

This reverts commit a240dc7b3c7463bd60cf0a9b2a90f52f78aae0fd.

This commit is reducing tx power by at least 10 db on some devices, e.g. the Buffalo WZR-HP-G450H.

---
 drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h |  164 +++++++++----------
 1 file changed, 82 insertions(+), 82 deletions(-)
drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +82 -82
@@ -534,107 +534,107 @@ static const u32 ar9300_2p2_baseband_cor
 
 static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = {
 	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-	{0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
-	{0x0000a2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
-	{0x0000a2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
+	{0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+	{0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+	{0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
 	{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
 	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
 	{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 	{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
 	{0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
 	{0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
-	{0x0000a510, 0x15000028, 0x15000028, 0x0f000202, 0x0f000202},
-	{0x0000a514, 0x1b00002b, 0x1b00002b, 0x12000400, 0x12000400},
-	{0x0000a518, 0x1f020028, 0x1f020028, 0x16000402, 0x16000402},
-	{0x0000a51c, 0x2502002b, 0x2502002b, 0x19000404, 0x19000404},
-	{0x0000a520, 0x2a04002a, 0x2a04002a, 0x1c000603, 0x1c000603},
-	{0x0000a524, 0x2e06002a, 0x2e06002a, 0x21000a02, 0x21000a02},
-	{0x0000a528, 0x3302202d, 0x3302202d, 0x25000a04, 0x25000a04},
-	{0x0000a52c, 0x3804202c, 0x3804202c, 0x28000a20, 0x28000a20},
-	{0x0000a530, 0x3c06202c, 0x3c06202c, 0x2c000e20, 0x2c000e20},
-	{0x0000a534, 0x4108202d, 0x4108202d, 0x30000e22, 0x30000e22},
-	{0x0000a538, 0x4506402d, 0x4506402d, 0x34000e24, 0x34000e24},
-	{0x0000a53c, 0x4906222d, 0x4906222d, 0x38001640, 0x38001640},
-	{0x0000a540, 0x4d062231, 0x4d062231, 0x3c001660, 0x3c001660},
-	{0x0000a544, 0x50082231, 0x50082231, 0x3f001861, 0x3f001861},
-	{0x0000a548, 0x5608422e, 0x5608422e, 0x43001a81, 0x43001a81},
-	{0x0000a54c, 0x5a08442e, 0x5a08442e, 0x47001a83, 0x47001a83},
-	{0x0000a550, 0x5e0a4431, 0x5e0a4431, 0x4a001c84, 0x4a001c84},
-	{0x0000a554, 0x640a4432, 0x640a4432, 0x4e001ce3, 0x4e001ce3},
-	{0x0000a558, 0x680a4434, 0x680a4434, 0x52001ce5, 0x52001ce5},
-	{0x0000a55c, 0x6c0a6434, 0x6c0a6434, 0x56001ce9, 0x56001ce9},
-	{0x0000a560, 0x6f0a6633, 0x6f0a6633, 0x5a001ceb, 0x5a001ceb},
-	{0x0000a564, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
-	{0x0000a568, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
-	{0x0000a56c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
-	{0x0000a570, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
-	{0x0000a574, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
-	{0x0000a578, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
-	{0x0000a57c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+	{0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+	{0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
+	{0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402},
+	{0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404},
+	{0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
+	{0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
+	{0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
+	{0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
+	{0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
+	{0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
+	{0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
+	{0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
+	{0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
+	{0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861},
+	{0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81},
+	{0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83},
+	{0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84},
+	{0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3},
+	{0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5},
+	{0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9},
+	{0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb},
+	{0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+	{0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+	{0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+	{0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+	{0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+	{0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+	{0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
 	{0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
 	{0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
 	{0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
 	{0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
-	{0x0000a590, 0x15800028, 0x15800028, 0x0f800202, 0x0f800202},
-	{0x0000a594, 0x1b80002b, 0x1b80002b, 0x12800400, 0x12800400},
-	{0x0000a598, 0x1f820028, 0x1f820028, 0x16800402, 0x16800402},
-	{0x0000a59c, 0x2582002b, 0x2582002b, 0x19800404, 0x19800404},
-	{0x0000a5a0, 0x2a84002a, 0x2a84002a, 0x1c800603, 0x1c800603},
-	{0x0000a5a4, 0x2e86002a, 0x2e86002a, 0x21800a02, 0x21800a02},
-	{0x0000a5a8, 0x3382202d, 0x3382202d, 0x25800a04, 0x25800a04},
-	{0x0000a5ac, 0x3884202c, 0x3884202c, 0x28800a20, 0x28800a20},
-	{0x0000a5b0, 0x3c86202c, 0x3c86202c, 0x2c800e20, 0x2c800e20},
-	{0x0000a5b4, 0x4188202d, 0x4188202d, 0x30800e22, 0x30800e22},
-	{0x0000a5b8, 0x4586402d, 0x4586402d, 0x34800e24, 0x34800e24},
-	{0x0000a5bc, 0x4986222d, 0x4986222d, 0x38801640, 0x38801640},
-	{0x0000a5c0, 0x4d862231, 0x4d862231, 0x3c801660, 0x3c801660},
-	{0x0000a5c4, 0x50882231, 0x50882231, 0x3f801861, 0x3f801861},
-	{0x0000a5c8, 0x5688422e, 0x5688422e, 0x43801a81, 0x43801a81},
-	{0x0000a5cc, 0x5a88442e, 0x5a88442e, 0x47801a83, 0x47801a83},
-	{0x0000a5d0, 0x5e8a4431, 0x5e8a4431, 0x4a801c84, 0x4a801c84},
-	{0x0000a5d4, 0x648a4432, 0x648a4432, 0x4e801ce3, 0x4e801ce3},
-	{0x0000a5d8, 0x688a4434, 0x688a4434, 0x52801ce5, 0x52801ce5},
-	{0x0000a5dc, 0x6c8a6434, 0x6c8a6434, 0x56801ce9, 0x56801ce9},
-	{0x0000a5e0, 0x6f8a6633, 0x6f8a6633, 0x5a801ceb, 0x5a801ceb},
-	{0x0000a5e4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
-	{0x0000a5e8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
-	{0x0000a5ec, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
-	{0x0000a5f0, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
-	{0x0000a5f4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
-	{0x0000a5f8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
-	{0x0000a5fc, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+	{0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
+	{0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400},
+	{0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402},
+	{0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404},
+	{0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603},
+	{0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02},
+	{0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04},
+	{0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20},
+	{0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20},
+	{0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22},
+	{0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
+	{0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
+	{0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
+	{0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861},
+	{0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81},
+	{0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83},
+	{0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84},
+	{0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3},
+	{0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5},
+	{0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9},
+	{0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb},
+	{0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+	{0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+	{0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+	{0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+	{0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+	{0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+	{0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
 	{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 	{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-	{0x0000a608, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
-	{0x0000a60c, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
-	{0x0000a610, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
-	{0x0000a614, 0x01804601, 0x01804601, 0x01404000, 0x01404000},
-	{0x0000a618, 0x01804601, 0x01804601, 0x01404501, 0x01404501},
-	{0x0000a61c, 0x01804601, 0x01804601, 0x02008501, 0x02008501},
-	{0x0000a620, 0x03408d02, 0x03408d02, 0x0280ca03, 0x0280ca03},
-	{0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
-	{0x0000a628, 0x03410d04, 0x03410d04, 0x04014c04, 0x04014c04},
-	{0x0000a62c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
-	{0x0000a630, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
-	{0x0000a634, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
-	{0x0000a638, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
-	{0x0000a63c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
-	{0x0000b2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
-	{0x0000b2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
-	{0x0000b2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
+	{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000},
+	{0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501},
+	{0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501},
+	{0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03},
+	{0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04},
+	{0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04},
+	{0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+	{0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+	{0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+	{0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+	{0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+	{0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+	{0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+	{0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
 	{0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
-	{0x0000c2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
-	{0x0000c2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
-	{0x0000c2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
+	{0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+	{0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+	{0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
 	{0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
 	{0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
-	{0x00016048, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
+	{0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
 	{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
 	{0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
-	{0x00016448, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
+	{0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
 	{0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
 	{0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
-	{0x00016848, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
+	{0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
 	{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
 };
 
author maintainer
#94 lore raw

PATCH 94/101 x86, mm: Find_early_table_space based on ranges that are actually being mapped

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 844ab6f993b1d32eb40512503d35ff6ad0c57030 upstream.

Current logic finds enough space for direct mapping page tables from 0 to end. Instead, we only need to find enough space to cover mr[0].start to mr[nr_range].end -- the range that is actually being mapped by init_memory_mapping()

This is needed after 1bbbbe779aabe1f0768c2bf8f8c0a5583679b54a, to address the panic reported here:

https://lkml.org/lkml/2012/10/20/160
https://lkml.org/lkml/2012/10/21/157

---
 arch/x86/mm/init.c |   70 +++++++++++++++++++++++++++++++----------------------
 1 file changed, 41 insertions(+), 29 deletions(-)
arch/x86/mm/init.c +41 -29
@@ -29,36 +29,54 @@ int direct_gbpages
 #endif
 ;
 
-static void __init find_early_table_space(unsigned long end, int use_pse,
-					  int use_gbpages)
+struct map_range {
+	unsigned long start;
+	unsigned long end;
+	unsigned page_size_mask;
+};
+
+/*
+ * First calculate space needed for kernel direct mapping page tables to cover
+ * mr[0].start to mr[nr_range - 1].end, while accounting for possible 2M and 1GB
+ * pages. Then find enough contiguous space for those page tables.
+ */
+static void __init find_early_table_space(struct map_range *mr, int nr_range)
 {
-	unsigned long puds, pmds, ptes, tables, start = 0, good_end = end;
+	int i;
+	unsigned long puds = 0, pmds = 0, ptes = 0, tables;
+	unsigned long start = 0, good_end;
 	phys_addr_t base;
 
-	puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
-	tables = roundup(puds * sizeof(pud_t), PAGE_SIZE);
+	for (i = 0; i < nr_range; i++) {
+		unsigned long range, extra;
 
-	if (use_gbpages) {
-		unsigned long extra;
+		range = mr[i].end - mr[i].start;
+		puds += (range + PUD_SIZE - 1) >> PUD_SHIFT;
 
-		extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT);
-		pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT;
-	} else
-		pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
-
-	tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE);
+		if (mr[i].page_size_mask & (1 << PG_LEVEL_1G)) {
+			extra = range - ((range >> PUD_SHIFT) << PUD_SHIFT);
+			pmds += (extra + PMD_SIZE - 1) >> PMD_SHIFT;
+		} else {
+			pmds += (range + PMD_SIZE - 1) >> PMD_SHIFT;
+		}
 
-	if (use_pse) {
-		unsigned long extra;
-
-		extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT);
+		if (mr[i].page_size_mask & (1 << PG_LEVEL_2M)) {
+			extra = range - ((range >> PMD_SHIFT) << PMD_SHIFT);
 #ifdef CONFIG_X86_32
-		extra += PMD_SIZE;
+			extra += PMD_SIZE;
 #endif
-		ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
-	} else
-		ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
+			/* The first 2/4M doesn't use large pages. */
+			if (mr[i].start < PMD_SIZE)
+				extra += range;
+
+			ptes += (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
+		} else {
+			ptes += (range + PAGE_SIZE - 1) >> PAGE_SHIFT;
+		}
+	}
 
+	tables = roundup(puds * sizeof(pud_t), PAGE_SIZE);
+	tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE);
 	tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE);
 
 #ifdef CONFIG_X86_32
@@ -76,7 +94,7 @@ static void __init find_early_table_spac
 	pgt_buf_top = pgt_buf_start + (tables >> PAGE_SHIFT);
 
 	printk(KERN_DEBUG "kernel direct mapping tables up to %#lx @ [mem %#010lx-%#010lx]\n",
-		end - 1, pgt_buf_start << PAGE_SHIFT,
+		mr[nr_range - 1].end - 1, pgt_buf_start << PAGE_SHIFT,
 		(pgt_buf_top << PAGE_SHIFT) - 1);
 }
 
@@ -85,12 +103,6 @@ void __init native_pagetable_reserve(u64
 	memblock_reserve(start, end - start);
 }
 
-struct map_range {
-	unsigned long start;
-	unsigned long end;
-	unsigned page_size_mask;
-};
-
 #ifdef CONFIG_X86_32
 #define NR_RANGE_MR 3
 #else /* CONFIG_X86_64 */
@@ -263,7 +275,7 @@ unsigned long __init_refok init_memory_m
 	 * nodes are discovered.
 	 */
 	if (!after_bootmem)
-		find_early_table_space(end, use_pse, use_gbpages);
+		find_early_table_space(mr, nr_range);
 
 	for (i = 0; i < nr_range; i++)
 		ret = kernel_physical_mapping_init(mr[i].start, mr[i].end,
author maintainer
#95 lore raw

PATCH 95/101 x86, mm: Undo incorrect revert in arch/x86/mm/init.c

In reply to Greg Kroah-Hartman

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

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

From: Yinghai Lu <[email protected]>

commit f82f64dd9f485e13f29f369772d4a0e868e5633a upstream.

Commit

844ab6f9 x86, mm: Find_early_table_space based on ranges that are actually being mapped

added back some lines back wrongly that has been removed in commit

7b16bbf97 Revert "x86/mm: Fix the size calculation of mapping tables"

remove them again.

---
 arch/x86/mm/init.c |    4 ----
 1 file changed, 4 deletions(-)
arch/x86/mm/init.c +0 -4
@@ -65,10 +65,6 @@ static void __init find_early_table_spac
 #ifdef CONFIG_X86_32
 			extra += PMD_SIZE;
 #endif
-			/* The first 2/4M doesn't use large pages. */
-			if (mr[i].start < PMD_SIZE)
-				extra += range;
-
 			ptes += (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
 		} else {
 			ptes += (range + PAGE_SIZE - 1) >> PAGE_SHIFT;
author maintainer
#96 lore raw

PATCH 96/101 cfg80211/mac80211: avoid state mishmash on deauth

In reply to Greg Kroah-Hartman

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

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

From: Stanislaw Gruszka <[email protected]>

commit 6863255bd0e48bc41ae5a066d5c771801e92735a upstream.

Avoid situation when we are on associate state in mac80211 and on disassociate state in cfg80211. This can results on crash during modules unload (like showed on this thread:
http://marc.info/?t=134373976300001&r=1&w=2) and possibly other problems.

---
 include/net/cfg80211.h |    1 +
 net/mac80211/mlme.c    |    5 +++--
 net/wireless/mlme.c    |   12 +++---------
 3 files changed, 7 insertions(+), 11 deletions(-)
include/net/cfg80211.h +1 -0
@@ -1217,6 +1217,7 @@ struct cfg80211_deauth_request {
 	const u8 *ie;
 	size_t ie_len;
 	u16 reason_code;
+	bool local_state_change;
 };
 
 /**
net/mac80211/mlme.c +3 -2
@@ -3467,6 +3467,7 @@ int ieee80211_mgd_deauth(struct ieee8021
 {
 	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 	u8 frame_buf[DEAUTH_DISASSOC_LEN];
+	bool tx = !req->local_state_change;
 
 	mutex_lock(&ifmgd->mtx);
 
@@ -3483,11 +3484,11 @@ int ieee80211_mgd_deauth(struct ieee8021
 	if (ifmgd->associated &&
 	    ether_addr_equal(ifmgd->associated->bssid, req->bssid))
 		ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
-				       req->reason_code, true, frame_buf);
+				       req->reason_code, tx, frame_buf);
 	else
 		ieee80211_send_deauth_disassoc(sdata, req->bssid,
 					       IEEE80211_STYPE_DEAUTH,
-					       req->reason_code, true,
+					       req->reason_code, tx,
 					       frame_buf);
 	mutex_unlock(&ifmgd->mtx);
 
net/wireless/mlme.c +3 -9
@@ -457,20 +457,14 @@ int __cfg80211_mlme_deauth(struct cfg802
 		.reason_code = reason,
 		.ie = ie,
 		.ie_len = ie_len,
+		.local_state_change = local_state_change,
 	};
 
 	ASSERT_WDEV_LOCK(wdev);
 
-	if (local_state_change) {
-		if (wdev->current_bss &&
-		    ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) {
-			cfg80211_unhold_bss(wdev->current_bss);
-			cfg80211_put_bss(&wdev->current_bss->pub);
-			wdev->current_bss = NULL;
-		}
-
+	if (local_state_change && (!wdev->current_bss ||
+	    !ether_addr_equal(wdev->current_bss->pub.bssid, bssid)))
 		return 0;
-	}
 
 	return rdev->ops->deauth(&rdev->wiphy, dev, &req);
 }
author maintainer
#97 lore raw

PATCH 97/101 efi: Defer freeing boot services memory until after ACPI init

In reply to Greg Kroah-Hartman

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

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

From: Josh Triplett <[email protected]>

commit 785107923a83d8456bbd8564e288a24d84109a46 upstream.

Some new ACPI 5.0 tables reference resources stored in boot services memory, so keep that memory around until we have ACPI and can extract data from it.

---
 arch/x86/platform/efi/efi.c |   31 ++++++++++++++++++-------------
 include/linux/efi.h         |    5 +++++
 init/main.c                 |    3 +++
 3 files changed, 26 insertions(+), 13 deletions(-)
arch/x86/platform/efi/efi.c +18 -13
@@ -419,10 +419,21 @@ void __init efi_reserve_boot_services(vo
 	}
 }
 
-static void __init efi_free_boot_services(void)
+static void __init efi_unmap_memmap(void)
+{
+	if (memmap.map) {
+		early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
+		memmap.map = NULL;
+	}
+}
+
+void __init efi_free_boot_services(void)
 {
 	void *p;
 
+	if (!efi_native)
+		return;
+
 	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
 		efi_memory_desc_t *md = p;
 		unsigned long long start = md->phys_addr;
@@ -438,6 +449,8 @@ static void __init efi_free_boot_service
 
 		free_bootmem_late(start, size);
 	}
+
+	efi_unmap_memmap();
 }
 
 static int __init efi_systab_init(void *phys)
@@ -787,8 +800,10 @@ void __init efi_enter_virtual_mode(void)
 	 * non-native EFI
 	 */
 
-	if (!efi_native)
-		goto out;
+	if (!efi_native) {
+		efi_unmap_memmap();
+		return;
+	}
 
 	/* Merge contiguous regions of the same type and attribute */
 	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
@@ -878,13 +893,6 @@ void __init efi_enter_virtual_mode(void)
 	}
 
 	/*
-	 * Thankfully, it does seem that no runtime services other than
-	 * SetVirtualAddressMap() will touch boot services code, so we can
-	 * get rid of it all at this point
-	 */
-	efi_free_boot_services();
-
-	/*
 	 * Now that EFI is in virtual mode, update the function
 	 * pointers in the runtime service table to the new virtual addresses.
 	 *
@@ -907,9 +915,6 @@ void __init efi_enter_virtual_mode(void)
 	if (__supported_pte_mask & _PAGE_NX)
 		runtime_code_page_mkexec();
 
-out:
-	early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
-	memmap.map = NULL;
 	kfree(new_memmap);
 }
 
include/linux/efi.h +5 -0
@@ -496,6 +496,11 @@ extern void efi_map_pal_code (void);
 extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg);
 extern void efi_gettimeofday (struct timespec *ts);
 extern void efi_enter_virtual_mode (void);	/* switch EFI to virtual mode, if possible */
+#ifdef CONFIG_X86
+extern void efi_free_boot_services(void);
+#else
+static inline void efi_free_boot_services(void) {}
+#endif
 extern u64 efi_get_iobase (void);
 extern u32 efi_mem_type (unsigned long phys_addr);
 extern u64 efi_mem_attributes (unsigned long phys_addr);
init/main.c +3 -0
@@ -631,6 +631,9 @@ asmlinkage void __init start_kernel(void
 	acpi_early_init(); /* before LAPIC and SMP init */
 	sfi_init_late();
 
+	if (efi_enabled)
+		efi_free_boot_services();
+
 	ftrace_init();
 
 	/* Do the rest non-__init'ed, we're now alive */
author maintainer
#98 lore raw

PATCH 98/101 x86: efi: Turn off efi_enabled after setup on mixed fw/kernel

In reply to Greg Kroah-Hartman

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

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

From: Olof Johansson <[email protected]>

commit 5189c2a7c7769ee9d037d76c1a7b8550ccf3481c upstream.

When 32-bit EFI is used with 64-bit kernel (or vice versa), turn off efi_enabled once setup is done. Beyond setup, it is normally used to determine if runtime services are available and we will have none.

This will resolve issues stemming from efivars modprobe panicking on a 32/64-bit setup, as well as some reboot issues on similar setups.

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=45991

---
 arch/x86/include/asm/efi.h  |    1 +
 arch/x86/kernel/setup.c     |   12 ++++++++++++
 arch/x86/platform/efi/efi.c |   18 ++++++++++--------
 3 files changed, 23 insertions(+), 8 deletions(-)
arch/x86/include/asm/efi.h +1 -0
@@ -98,6 +98,7 @@ extern void efi_set_executable(efi_memor
 extern int efi_memblock_x86_reserve_range(void);
 extern void efi_call_phys_prelog(void);
 extern void efi_call_phys_epilog(void);
+extern void efi_unmap_memmap(void);
 
 #ifndef CONFIG_EFI
 /*
arch/x86/kernel/setup.c +12 -0
@@ -1047,6 +1047,18 @@ void __init setup_arch(char **cmdline_p)
 	mcheck_init();
 
 	arch_init_ideal_nops();
+
+#ifdef CONFIG_EFI
+	/* Once setup is done above, disable efi_enabled on mismatched
+	 * firmware/kernel archtectures since there is no support for
+	 * runtime services.
+	 */
+	if (efi_enabled && IS_ENABLED(CONFIG_X86_64) != efi_64bit) {
+		pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n");
+		efi_unmap_memmap();
+		efi_enabled = 0;
+	}
+#endif
 }
 
 #ifdef CONFIG_X86_32
arch/x86/platform/efi/efi.c +10 -8
@@ -69,11 +69,15 @@ EXPORT_SYMBOL(efi);
 struct efi_memory_map memmap;
 
 bool efi_64bit;
-static bool efi_native;
 
 static struct efi efi_phys __initdata;
 static efi_system_table_t efi_systab __initdata;
 
+static inline bool efi_is_native(void)
+{
+	return IS_ENABLED(CONFIG_X86_64) == efi_64bit;
+}
+
 static int __init setup_noefi(char *arg)
 {
 	efi_enabled = 0;
@@ -419,7 +423,7 @@ void __init efi_reserve_boot_services(vo
 	}
 }
 
-static void __init efi_unmap_memmap(void)
+void __init efi_unmap_memmap(void)
 {
 	if (memmap.map) {
 		early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
@@ -431,7 +435,7 @@ void __init efi_free_boot_services(void)
 {
 	void *p;
 
-	if (!efi_native)
+	if (!efi_is_native())
 		return;
 
 	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
@@ -683,12 +687,10 @@ void __init efi_init(void)
 		return;
 	}
 	efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab;
-	efi_native = !efi_64bit;
 #else
 	efi_phys.systab = (efi_system_table_t *)
 			  (boot_params.efi_info.efi_systab |
 			  ((__u64)boot_params.efi_info.efi_systab_hi<<32));
-	efi_native = efi_64bit;
 #endif
 
 	if (efi_systab_init(efi_phys.systab)) {
@@ -722,7 +724,7 @@ void __init efi_init(void)
 	 * that doesn't match the kernel 32/64-bit mode.
 	 */
 
-	if (!efi_native)
+	if (!efi_is_native())
 		pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n");
 	else if (efi_runtime_init()) {
 		efi_enabled = 0;
@@ -734,7 +736,7 @@ void __init efi_init(void)
 		return;
 	}
 #ifdef CONFIG_X86_32
-	if (efi_native) {
+	if (efi_is_native()) {
 		x86_platform.get_wallclock = efi_get_time;
 		x86_platform.set_wallclock = efi_set_rtc_mmss;
 	}
@@ -800,7 +802,7 @@ void __init efi_enter_virtual_mode(void)
 	 * non-native EFI
 	 */
 
-	if (!efi_native) {
+	if (!efi_is_native()) {
 		efi_unmap_memmap();
 		return;
 	}
author maintainer
#99 lore raw

PATCH 99/101 x86, mm: Use memblock memory loop instead of e820_RAM

In reply to Greg Kroah-Hartman

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

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

From: Yinghai Lu <[email protected]>

commit 1f2ff682ac951ed82cc043cf140d2851084512df upstream.

We need to handle E820_RAM and E820_RESERVED_KERNEL at the same time.

Also memblock has page aligned range for ram, so we could avoid mapping partial pages.

---
 arch/x86/kernel/setup.c |   15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)
arch/x86/kernel/setup.c +8 -7
@@ -920,18 +920,19 @@ void __init setup_arch(char **cmdline_p)
 #ifdef CONFIG_X86_64
 	if (max_pfn > max_low_pfn) {
 		int i;
-		for (i = 0; i < e820.nr_map; i++) {
-			struct e820entry *ei = &e820.map[i];
+		unsigned long start, end;
+		unsigned long start_pfn, end_pfn;
 
-			if (ei->addr + ei->size <= 1UL << 32)
-				continue;
+		for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn,
+							 NULL) {
 
-			if (ei->type == E820_RESERVED)
+			end = PFN_PHYS(end_pfn);
+			if (end <= (1UL<<32))
 				continue;
 
+			start = PFN_PHYS(start_pfn);
 			max_pfn_mapped = init_memory_mapping(
-				ei->addr < 1UL << 32 ? 1UL << 32 : ei->addr,
-				ei->addr + ei->size);
+						max((1UL<<32), start), end);
 		}
 
 		/* can we preseve max_low_pfn ?*/
author maintainer
#100 lore raw

PATCH 100/101 pnfsblock: fix non-aligned DIO read

In reply to Greg Kroah-Hartman

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

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

From: Peng Tao <[email protected]>

commit f742dc4a32587bff50b13dde9d8894b96851951a upstream.

For DIO read, if it is not sector aligned, we should reject it and resend via MDS. Otherwise there might be data corruption. Also teach bl_read_pagelist to handle partial page reads for DIO.

---
 fs/nfs/blocklayout/blocklayout.c |   77 +++++++++++++++++++++++----------------
 1 file changed, 46 insertions(+), 31 deletions(-)
fs/nfs/blocklayout/blocklayout.c +46 -31
@@ -242,14 +242,6 @@ bl_end_par_io_read(void *data, int unuse
 	schedule_work(&rdata->task.u.tk_work);
 }
 
-static bool
-bl_check_alignment(u64 offset, u32 len, unsigned long blkmask)
-{
-	if ((offset & blkmask) || (len & blkmask))
-		return false;
-	return true;
-}
-
 static enum pnfs_try_status
 bl_read_pagelist(struct nfs_read_data *rdata)
 {
@@ -260,15 +252,15 @@ bl_read_pagelist(struct nfs_read_data *r
 	sector_t isect, extent_length = 0;
 	struct parallel_io *par;
 	loff_t f_offset = rdata->args.offset;
+	size_t bytes_left = rdata->args.count;
+	unsigned int pg_offset, pg_len;
 	struct page **pages = rdata->args.pages;
 	int pg_index = rdata->args.pgbase >> PAGE_CACHE_SHIFT;
+	const bool is_dio = (header->dreq != NULL);
 
 	dprintk("%s enter nr_pages %u offset %lld count %u\n", __func__,
 	       rdata->pages.npages, f_offset, (unsigned int)rdata->args.count);
 
-	if (!bl_check_alignment(f_offset, rdata->args.count, PAGE_CACHE_MASK))
-		goto use_mds;
-
 	par = alloc_parallel(rdata);
 	if (!par)
 		goto use_mds;
@@ -298,36 +290,53 @@ bl_read_pagelist(struct nfs_read_data *r
 				extent_length = min(extent_length, cow_length);
 			}
 		}
+
+		if (is_dio) {
+			pg_offset = f_offset & ~PAGE_CACHE_MASK;
+			if (pg_offset + bytes_left > PAGE_CACHE_SIZE)
+				pg_len = PAGE_CACHE_SIZE - pg_offset;
+			else
+				pg_len = bytes_left;
+
+			f_offset += pg_len;
+			bytes_left -= pg_len;
+			isect += (pg_offset >> SECTOR_SHIFT);
+		} else {
+			pg_offset = 0;
+			pg_len = PAGE_CACHE_SIZE;
+		}
+
 		hole = is_hole(be, isect);
 		if (hole && !cow_read) {
 			bio = bl_submit_bio(READ, bio);
 			/* Fill hole w/ zeroes w/o accessing device */
 			dprintk("%s Zeroing page for hole\n", __func__);
-			zero_user_segment(pages[i], 0, PAGE_CACHE_SIZE);
+			zero_user_segment(pages[i], pg_offset, pg_len);
 			print_page(pages[i]);
 			SetPageUptodate(pages[i]);
 		} else {
 			struct pnfs_block_extent *be_read;
 
 			be_read = (hole && cow_read) ? cow_read : be;
-			bio = bl_add_page_to_bio(bio, rdata->pages.npages - i,
+			bio = do_add_page_to_bio(bio, rdata->pages.npages - i,
 						 READ,
 						 isect, pages[i], be_read,
-						 bl_end_io_read, par);
+						 bl_end_io_read, par,
+						 pg_offset, pg_len);
 			if (IS_ERR(bio)) {
 				header->pnfs_error = PTR_ERR(bio);
 				bio = NULL;
 				goto out;
 			}
 		}
-		isect += PAGE_CACHE_SECTORS;
+		isect += (pg_len >> SECTOR_SHIFT);
 		extent_length -= PAGE_CACHE_SECTORS;
 	}
 	if ((isect << SECTOR_SHIFT) >= header->inode->i_size) {
 		rdata->res.eof = 1;
-		rdata->res.count = header->inode->i_size - f_offset;
+		rdata->res.count = header->inode->i_size - rdata->args.offset;
 	} else {
-		rdata->res.count = (isect << SECTOR_SHIFT) - f_offset;
+		rdata->res.count = (isect << SECTOR_SHIFT) - rdata->args.offset;
 	}
 out:
 	bl_put_extent(be);
@@ -676,7 +685,7 @@ bl_write_pagelist(struct nfs_write_data
 	struct bio *bio = NULL;
 	struct pnfs_block_extent *be = NULL, *cow_read = NULL;
 	sector_t isect, last_isect = 0, extent_length = 0;
-	struct parallel_io *par = NULL;
+	struct parallel_io *par;
 	loff_t offset = wdata->args.offset;
 	size_t count = wdata->args.count;
 	unsigned int pg_offset, pg_len, saved_len;
@@ -688,10 +697,6 @@ bl_write_pagelist(struct nfs_write_data
 	    NFS_SERVER(header->inode)->pnfs_blksize >> PAGE_CACHE_SHIFT;
 
 	dprintk("%s enter, %Zu@%lld\n", __func__, count, offset);
-	/* Check for alignment first */
-	if (!bl_check_alignment(offset, count, PAGE_CACHE_MASK))
-		goto out_mds;
-
 	/* At this point, wdata->pages is a (sequential) list of nfs_pages.
 	 * We want to write each, and if there is an error set pnfs_error
 	 * to have it redone using nfs.
@@ -1164,32 +1169,42 @@ bl_clear_layoutdriver(struct nfs_server
 	return 0;
 }
 
+static bool
+is_aligned_req(struct nfs_page *req, unsigned int alignment)
+{
+	return IS_ALIGNED(req->wb_offset, alignment) &&
+	       IS_ALIGNED(req->wb_bytes, alignment);
+}
+
 static void
 bl_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
 {
-	if (!bl_check_alignment(req->wb_offset, req->wb_bytes, PAGE_CACHE_MASK))
+	if (pgio->pg_dreq != NULL &&
+	    !is_aligned_req(req, SECTOR_SIZE))
 		nfs_pageio_reset_read_mds(pgio);
 	else
 		pnfs_generic_pg_init_read(pgio, req);
 }
 
-static void
-bl_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
+static bool
+bl_pg_test_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
+		struct nfs_page *req)
 {
-	if (!bl_check_alignment(req->wb_offset, req->wb_bytes, PAGE_CACHE_MASK))
-		nfs_pageio_reset_write_mds(pgio);
-	else
-		pnfs_generic_pg_init_write(pgio, req);
+	if (pgio->pg_dreq != NULL &&
+	    !is_aligned_req(req, SECTOR_SIZE))
+		return false;
+
+	return pnfs_generic_pg_test(pgio, prev, req);
 }
 
 static const struct nfs_pageio_ops bl_pg_read_ops = {
 	.pg_init = bl_pg_init_read,
-	.pg_test = pnfs_generic_pg_test,
+	.pg_test = bl_pg_test_read,
 	.pg_doio = pnfs_generic_pg_readpages,
 };
 
 static const struct nfs_pageio_ops bl_pg_write_ops = {
-	.pg_init = bl_pg_init_write,
+	.pg_init = pnfs_generic_pg_init_write,
 	.pg_test = pnfs_generic_pg_test,
 	.pg_doio = pnfs_generic_pg_writepages,
 };
author maintainer
#101 lore raw

PATCH 101/101 pnfsblock: fix non-aligned DIO write

In reply to Greg Kroah-Hartman

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

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

From: Peng Tao <[email protected]>

commit 96c9eae638765c2bf2ca4f5a6325484f9bb69aa7 upstream.

For DIO writes, if it is not blocksize aligned, we need to do internal serialization. It may slow down writers anyway. So we just bail them out and resend to MDS.

---
 fs/nfs/blocklayout/blocklayout.c |   34 +++++++++++++++++++++++++++++++---
 1 file changed, 31 insertions(+), 3 deletions(-)
fs/nfs/blocklayout/blocklayout.c +31 -3
@@ -685,7 +685,7 @@ bl_write_pagelist(struct nfs_write_data
 	struct bio *bio = NULL;
 	struct pnfs_block_extent *be = NULL, *cow_read = NULL;
 	sector_t isect, last_isect = 0, extent_length = 0;
-	struct parallel_io *par;
+	struct parallel_io *par = NULL;
 	loff_t offset = wdata->args.offset;
 	size_t count = wdata->args.count;
 	unsigned int pg_offset, pg_len, saved_len;
@@ -697,6 +697,13 @@ bl_write_pagelist(struct nfs_write_data
 	    NFS_SERVER(header->inode)->pnfs_blksize >> PAGE_CACHE_SHIFT;
 
 	dprintk("%s enter, %Zu@%lld\n", __func__, count, offset);
+
+	if (header->dreq != NULL &&
+	    (!IS_ALIGNED(offset, NFS_SERVER(header->inode)->pnfs_blksize) ||
+	     !IS_ALIGNED(count, NFS_SERVER(header->inode)->pnfs_blksize))) {
+		dprintk("pnfsblock nonblock aligned DIO writes. Resend MDS\n");
+		goto out_mds;
+	}
 	/* At this point, wdata->pages is a (sequential) list of nfs_pages.
 	 * We want to write each, and if there is an error set pnfs_error
 	 * to have it redone using nfs.
@@ -1197,6 +1204,27 @@ bl_pg_test_read(struct nfs_pageio_descri
 	return pnfs_generic_pg_test(pgio, prev, req);
 }
 
+void
+bl_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
+{
+	if (pgio->pg_dreq != NULL &&
+	    !is_aligned_req(req, PAGE_CACHE_SIZE))
+		nfs_pageio_reset_write_mds(pgio);
+	else
+		pnfs_generic_pg_init_write(pgio, req);
+}
+
+static bool
+bl_pg_test_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
+		 struct nfs_page *req)
+{
+	if (pgio->pg_dreq != NULL &&
+	    !is_aligned_req(req, PAGE_CACHE_SIZE))
+		return false;
+
+	return pnfs_generic_pg_test(pgio, prev, req);
+}
+
 static const struct nfs_pageio_ops bl_pg_read_ops = {
 	.pg_init = bl_pg_init_read,
 	.pg_test = bl_pg_test_read,
@@ -1204,8 +1232,8 @@ static const struct nfs_pageio_ops bl_pg
 };
 
 static const struct nfs_pageio_ops bl_pg_write_ops = {
-	.pg_init = pnfs_generic_pg_init_write,
-	.pg_test = pnfs_generic_pg_test,
+	.pg_init = bl_pg_init_write,
+	.pg_test = bl_pg_test_write,
 	.pg_doio = pnfs_generic_pg_writepages,
 };
 
#102 lore raw

PATCH 1/1 USB: io_edgeport: remove unused variable

In reply to Greg Kroah-Hartman
Quoted 4 lines · Greg Kroah-Hartman

This is the start of the stable review cycle for the 3.6.5 release. There are 101 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.

A (harmless) unused variable warning was introduced in the 3.6.4 release. That variable was apparently missed when adapting an upstream commit to context changes. I do not know whether the stable release process allows for fixing trivial stuff like that. If it does, here's a patch to remove this variable.

Paul Bolle
---
The stable commit 12ddc74e8e25107eda81aceb74e3311c1480b381
("USB: io_edgeport: fix port-data memory leak") left one variable
unused:
drivers/usb/serial/io_edgeport.c: In function 'edge_release':
drivers/usb/serial/io_edgeport.c:3155:6: warning: unused variable 'i' [-Wunused-variable]

Remove this unused variable.

---
 drivers/usb/serial/io_edgeport.c | 1 -
 1 file changed, 1 deletion(-)
drivers/usb/serial/io_edgeport.c +0 -1
index dca27a5..6c22679 100644
@@ -3152,7 +3152,6 @@ static void edge_disconnect(struct usb_serial *serial)
 static void edge_release(struct usb_serial *serial)
 {
 	struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
-	int i;
 
 	dbg("%s", __func__);
 
Signature · 1 line
1.7.11.7