Skip to contentSkip to conversation

3.3.1-stable review

PATCH In review Greg KH 10 participants 194 messages Mar 30, 2012 – Jun 27, 2012 Page 1 of 2

Subsystems (101)
lore
Share & tools
lore

Greg KH

author maintainer
#0 lore raw

cover 3.3.1-stable review

This is the start of the stable review cycle for the 3.3.1 release. There are 175 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 Sun Apr 1 19:48:16 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.3.1-rc1.gz

and the diffstat can be found below.

thanks,

greg k-h

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

 Makefile                                          |    4 +-
 arch/arm/mach-shmobile/setup-sh7372.c             |    2 +
 arch/arm/mach-tegra/Kconfig                       |   12 ++
 arch/arm/mach-tegra/board-dt-tegra20.c            |    6 +-
 arch/arm/mach-tegra/devices.c                     |    7 +-
 arch/arm/mach-tegra/devices.h                     |    5 +
 arch/x86/kernel/apic/io_apic.c                    |   40 ++++-
 arch/x86/kernel/entry_32.S                        |   17 +-
 arch/x86/kernel/tls.c                             |    4 +-
 arch/x86/kernel/tsc.c                             |   10 ++
 arch/x86/kernel/vm86_32.c                         |    2 +
 arch/x86/net/bpf_jit_comp.c                       |   14 +-
 arch/x86/syscalls/syscall_32.tbl                  |    2 +-
 drivers/ata/ahci.c                                |    2 -
 drivers/ata/ahci.h                                |    6 +
 drivers/ata/ahci_platform.c                       |   11 ++
 drivers/ata/libahci.c                             |    5 +
 drivers/ata/pata_legacy.c                         |    3 +-
 drivers/base/power/domain.c                       |   67 ++++++--
 drivers/bluetooth/ath3k.c                         |    1 +
 drivers/bluetooth/btusb.c                         |    1 +
 drivers/char/tpm/Kconfig                          |    1 -
 drivers/char/tpm/tpm.c                            |    3 +-
 drivers/clocksource/sh_cmt.c                      |    4 +
 drivers/clocksource/sh_mtu2.c                     |    4 +
 drivers/clocksource/sh_tmu.c                      |    4 +
 drivers/firewire/ohci.c                           |    5 +-
 drivers/gpio/gpio-davinci.c                       |   26 +--
 drivers/gpio/gpio-omap.c                          |    5 +-
 drivers/gpu/drm/gma500/framebuffer.c              |    2 +-
 drivers/gpu/drm/i915/i915_drv.c                   |    7 +
 drivers/gpu/drm/i915/i915_gem.c                   |    7 +-
 drivers/gpu/drm/i915/intel_drv.h                  |    2 +-
 drivers/gpu/drm/i915/intel_fb.c                   |   10 ++
 drivers/gpu/drm/radeon/atombios_crtc.c            |    8 +-
 drivers/gpu/drm/radeon/atombios_dp.c              |    3 +
 drivers/gpu/drm/radeon/atombios_encoders.c        |    4 +-
 drivers/gpu/drm/radeon/radeon_atombios.c          |   14 ++
 drivers/gpu/drm/radeon/radeon_connectors.c        |    4 +
 drivers/gpu/drm/radeon/radeon_cursor.c            |   13 +-
 drivers/gpu/drm/radeon/radeon_object.c            |   18 ++-
 drivers/gpu/drm/radeon/radeon_object.h            |    2 +
 drivers/hid/hid-chicony.c                         |    7 +
 drivers/hid/hid-core.c                            |    1 +
 drivers/hid/hid-ids.h                             |    1 +
 drivers/hwmon/fam15h_power.c                      |    2 +-
 drivers/infiniband/ulp/iser/iscsi_iser.c          |   18 +--
 drivers/infiniband/ulp/iser/iscsi_iser.h          |    1 +
 drivers/infiniband/ulp/iser/iser_initiator.c      |   30 ++--
 drivers/infiniband/ulp/srpt/ib_srpt.c             |   19 ++-
 drivers/iommu/amd_iommu.c                         |    2 +-
 drivers/iommu/amd_iommu_init.c                    |   30 ++--
 drivers/md/bitmap.c                               |    2 +
 drivers/md/dm-crypt.c                             |   38 ++---
 drivers/md/dm-exception-store.c                   |    2 +-
 drivers/md/dm-thin.c                              |  124 +++++++++------
 drivers/md/md.c                                   |   40 ++---
 drivers/md/persistent-data/dm-btree-remove.c      |  174 ++++++++++++---------
 drivers/md/raid1.c                                |   17 +-
 drivers/md/raid10.c                               |   17 +-
 drivers/media/dvb/dvb-usb/mxl111sf.c              |    6 +-
 drivers/media/dvb/frontends/au8522_dig.c          |   10 +-
 drivers/media/dvb/frontends/lgdt330x.c            |    6 +-
 drivers/media/dvb/frontends/tda10071.c            |    2 +-
 drivers/media/video/pvrusb2/pvrusb2-devattr.c     |   10 ++
 drivers/mfd/wm8994-core.c                         |   14 ++
 drivers/mtd/ubi/scan.c                            |    8 +-
 drivers/mtd/ubi/wl.c                              |   10 +-
 drivers/net/ethernet/marvell/sky2.c               |   11 ++
 drivers/net/ethernet/mellanox/mlx4/main.c         |    2 +-
 drivers/net/usb/usbnet.c                          |   10 +-
 drivers/net/wireless/ath/ath9k/main.c             |    8 +-
 drivers/net/wireless/iwlwifi/iwl-core.c           |   18 +--
 drivers/net/wireless/p54/p54spi.c                 |   14 +-
 drivers/net/wireless/rt2x00/rt2800usb.c           |    1 +
 drivers/net/wireless/rtlwifi/base.c               |    1 +
 drivers/net/wireless/rtlwifi/core.c               |   42 +++++
 drivers/net/wireless/rtlwifi/core.h               |    4 +-
 drivers/net/wireless/rtlwifi/pci.c                |   46 +++---
 drivers/net/wireless/rtlwifi/pci.h                |    1 -
 drivers/net/wireless/rtlwifi/ps.c                 |    3 +-
 drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c |   15 +-
 drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c |   12 +-
 drivers/net/wireless/rtlwifi/rtl8192ce/hw.c       |    6 +-
 drivers/net/wireless/rtlwifi/rtl8192ce/sw.c       |   24 +--
 drivers/net/wireless/rtlwifi/rtl8192cu/hw.c       |   33 ++--
 drivers/net/wireless/rtlwifi/rtl8192cu/sw.c       |   29 ++--
 drivers/net/wireless/rtlwifi/rtl8192de/fw.c       |   22 ++-
 drivers/net/wireless/rtlwifi/rtl8192de/hw.c       |    3 -
 drivers/net/wireless/rtlwifi/rtl8192de/sw.c       |   38 ++---
 drivers/net/wireless/rtlwifi/rtl8192se/fw.c       |    2 +-
 drivers/net/wireless/rtlwifi/rtl8192se/hw.c       |   16 +-
 drivers/net/wireless/rtlwifi/rtl8192se/led.c      |    5 +-
 drivers/net/wireless/rtlwifi/rtl8192se/sw.c       |   65 ++++++--
 drivers/net/wireless/rtlwifi/usb.c                |   48 +++---
 drivers/net/wireless/rtlwifi/wifi.h               |    4 +-
 drivers/rtc/interface.c                           |   20 ++-
 drivers/rtc/rtc-mpc5121.c                         |    2 +
 drivers/scsi/scsi_transport_iscsi.c               |    4 +-
 drivers/staging/android/lowmemorykiller.c         |   14 +-
 drivers/staging/media/as102/as102_fw.h            |    2 +-
 drivers/staging/media/as102/as10x_cmd.h           |   80 +++++-----
 drivers/staging/media/as102/as10x_types.h         |    2 +-
 drivers/staging/octeon/ethernet-mdio.c            |    4 +-
 drivers/staging/rtl8712/Kconfig                   |    7 -
 drivers/staging/rtl8712/os_intfs.c                |    2 -
 drivers/staging/rtl8712/rtl871x_ioctl_linux.c     |    8 +-
 drivers/staging/rtl8712/rtl871x_sta_mgt.c         |    4 -
 drivers/staging/rtl8712/sta_info.h                |    4 -
 drivers/staging/vme/devices/vme_pio2.h            |    4 +-
 drivers/staging/vme/devices/vme_pio2_gpio.c       |    4 +-
 drivers/staging/zcache/zcache-main.c              |    4 +-
 drivers/target/iscsi/iscsi_target.c               |   14 +-
 drivers/target/iscsi/iscsi_target_configfs.c      |    6 +-
 drivers/target/loopback/tcm_loop.c                |    6 +
 drivers/target/target_core_alua.c                 |    7 +-
 drivers/target/target_core_cdb.c                  |  170 ++++++--------------
 drivers/target/target_core_device.c               |    6 +-
 drivers/target/tcm_fc/tfc_cmd.c                   |    6 +-
 drivers/tty/moxa.c                                |    2 +-
 drivers/tty/serial/amba-pl011.c                   |   15 +-
 drivers/tty/serial/omap-serial.c                  |    6 +-
 drivers/tty/serial/sh-sci.c                       |   15 +-
 drivers/tty/vt/consolemap.c                       |   51 +++++-
 drivers/usb/class/cdc-wdm.c                       |   17 +-
 drivers/usb/dwc3/core.c                           |    2 +-
 drivers/usb/dwc3/gadget.c                         |   33 ++--
 drivers/usb/gadget/amd5536udc.c                   |    1 +
 drivers/usb/gadget/at91_udc.c                     |    1 +
 drivers/usb/gadget/atmel_usba_udc.c               |    1 +
 drivers/usb/gadget/ci13xxx_udc.c                  |    1 +
 drivers/usb/gadget/f_subset.c                     |   34 ++--
 drivers/usb/gadget/fsl_qe_udc.c                   |    1 +
 drivers/usb/gadget/fsl_udc_core.c                 |   19 ++-
 drivers/usb/gadget/goku_udc.c                     |    1 +
 drivers/usb/gadget/hid.c                          |    6 +-
 drivers/usb/gadget/inode.c                        |    2 +
 drivers/usb/gadget/langwell_udc.c                 |    1 +
 drivers/usb/gadget/mv_udc_core.c                  |    1 +
 drivers/usb/gadget/omap_udc.c                     |    1 +
 drivers/usb/gadget/pch_udc.c                      |    1 +
 drivers/usb/gadget/pxa25x_udc.c                   |    2 +
 drivers/usb/gadget/s3c-hsudc.c                    |    2 +
 drivers/usb/gadget/s3c2410_udc.c                  |    2 +
 drivers/usb/host/ehci-fsl.c                       |    4 +
 drivers/usb/host/ehci-fsl.h                       |    1 +
 drivers/usb/host/fsl-mph-dr-of.c                  |    1 -
 drivers/usb/musb/musb_gadget.c                    |   18 +++
 drivers/usb/renesas_usbhs/mod_gadget.c            |    6 +
 drivers/usb/serial/cp210x.c                       |   44 +++++-
 drivers/usb/serial/ftdi_sio.c                     |   32 +++-
 drivers/usb/serial/ftdi_sio.h                     |    3 +-
 drivers/usb/serial/ftdi_sio_ids.h                 |   19 ++-
 drivers/usb/serial/generic.c                      |    4 +-
 drivers/usb/serial/mos7840.c                      |   83 +++++++---
 drivers/usb/serial/option.c                       |   16 ++
 drivers/usb/serial/qcserial.c                     |  105 ++++++++-----
 drivers/usb/storage/realtek_cr.c                  |    8 +-
 drivers/video/backlight/tosa_lcd.c                |    2 +-
 drivers/video/fbmem.c                             |   18 ++-
 drivers/video/udlfb.c                             |    2 +-
 fs/cifs/cifsfs.c                                  |    8 +-
 fs/cifs/cifsglob.h                                |   10 +-
 fs/cifs/cifssmb.c                                 |    9 +-
 fs/cifs/connect.c                                 |   14 +-
 fs/cifs/dir.c                                     |    6 +-
 fs/cifs/file.c                                    |   23 +--
 fs/cifs/transport.c                               |    4 +-
 fs/dcache.c                                       |    3 +-
 fs/ext4/ext4.h                                    |    2 +
 fs/ext4/ext4_jbd2.h                               |   56 +++----
 fs/ext4/extents.c                                 |    2 +
 fs/ext4/fsync.c                                   |    2 +
 fs/ext4/inode.c                                   |   46 +++---
 fs/ext4/page-io.c                                 |   11 +-
 fs/hugetlbfs/inode.c                              |   25 ++-
 fs/jbd2/transaction.c                             |    2 +
 fs/lockd/svc.c                                    |    2 +-
 fs/nfs/callback_xdr.c                             |    4 +-
 fs/nfs/delegation.c                               |   11 ++
 fs/nfs/delegation.h                               |    1 +
 fs/nfs/nfs4_fs.h                                  |    3 +
 fs/nfs/nfs4proc.c                                 |   64 +++++---
 fs/nfs/nfs4state.c                                |   33 +++-
 fs/proc/namespaces.c                              |    2 +-
 fs/proc/proc_sysctl.c                             |   17 +-
 fs/proc/task_mmu.c                                |    9 ++
 fs/sysfs/inode.c                                  |   11 +-
 fs/xfs/xfs_iget.c                                 |   18 ++-
 fs/xfs/xfs_log_recover.c                          |   33 ++--
 include/asm-generic/pgtable.h                     |   61 ++++++++
 include/asm-generic/unistd.h                      |    2 +-
 include/linux/fb.h                                |    1 +
 include/linux/math64.h                            |    4 +
 include/linux/pm_domain.h                         |    3 +
 include/linux/rtc.h                               |    3 +-
 include/target/target_core_base.h                 |    2 +-
 kernel/futex.c                                    |   19 ++-
 kernel/irq/chip.c                                 |    3 +-
 kernel/irq/manage.c                               |    2 +-
 kernel/module.c                                   |    3 +-
 kernel/power/hibernate.c                          |    7 +-
 kernel/time/ntp.c                                 |    2 +-
 lib/kobject_uevent.c                              |   19 ++-
 mm/bootmem.c                                      |    5 +-
 mm/memcontrol.c                                   |    4 +
 mm/memory.c                                       |   16 +-
 mm/mempolicy.c                                    |    2 +-
 mm/mincore.c                                      |    2 +-
 mm/pagewalk.c                                     |    2 +-
 mm/slub.c                                         |    3 +-
 mm/sparse.c                                       |   30 ++--
 mm/swapfile.c                                     |    4 +-
 mm/vmscan.c                                       |   42 +++--
 net/core/dev.c                                    |    3 +-
 net/core/rtnetlink.c                              |    2 +
 net/ipv6/ip6_output.c                             |   11 +-
 net/ipv6/route.c                                  |    8 +-
 net/l2tp/l2tp_ppp.c                               |    2 +-
 net/rds/send.c                                    |    1 -
 net/sunrpc/cache.c                                |    2 +
 net/sunrpc/sched.c                                |   15 +-
 net/xfrm/xfrm_replay.c                            |    6 +-
 security/integrity/ima/Kconfig                    |    2 +-
 sound/pci/hda/hda_eld.c                           |    4 +-
 sound/soc/fsl/p1022_ds.c                          |   24 ++-
 sound/soc/pxa/pxa-ssp.c                           |   61 +++++---
 227 files changed, 2009 insertions(+), 1209 deletions(-)
author maintainer
#1 lore raw

PATCH 1/175 USB: option: Add MediaTek MT6276M modem&app interfaces

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

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

From: Meng Zhang <[email protected]>

commit 0d8520a1d7f43328bc7085d4244d93c595064157 upstream.

Add MEDIATEK products to Option driver

---
 drivers/usb/serial/option.c |    7 +++++++
 1 file changed, 7 insertions(+)
drivers/usb/serial/option.c +7 -0
@@ -484,6 +484,9 @@ static void option_instat_callback(struc
 #define LG_VENDOR_ID				0x1004
 #define LG_PRODUCT_L02C				0x618f
 
+/* MediaTek products */
+#define MEDIATEK_VENDOR_ID			0x0e8d
+
 /* some devices interfaces need special handling due to a number of reasons */
 enum option_blacklist_reason {
 		OPTION_BLACKLIST_NONE = 0,
@@ -1198,6 +1201,10 @@ static const struct usb_device_id option
 	{ USB_DEVICE_AND_INTERFACE_INFO(VIETTEL_VENDOR_ID, VIETTEL_PRODUCT_VT1000, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZD_VENDOR_ID, ZD_PRODUCT_7000, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE(LG_VENDOR_ID, LG_PRODUCT_L02C) }, /* docomo L-02C modem */
+	{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a1, 0xff, 0x00, 0x00) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a1, 0xff, 0x02, 0x01) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x00, 0x00) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x02, 0x01) },        /* MediaTek MT6276M modem & app port */
 	{ } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
author maintainer
#2 lore raw

PATCH 2/175 USB: option driver: adding support for Telit CC864-SINGLE, CC864-DUAL and DE910-DUAL modems

In reply to Greg KH

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

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

From: Daniele Palmas <[email protected]>

commit 7204cf584836c24b4b06e4ad4a8e6bb8ea84908e upstream.

Adding PID for Telit CC864-SINGLE, CC864-DUAL and DE910-DUAL modems

---
 drivers/usb/serial/option.c |    6 ++++++
 1 file changed, 6 insertions(+)
drivers/usb/serial/option.c +6 -0
@@ -307,6 +307,9 @@ static void option_instat_callback(struc
 #define TELIT_VENDOR_ID				0x1bc7
 #define TELIT_PRODUCT_UC864E			0x1003
 #define TELIT_PRODUCT_UC864G			0x1004
+#define TELIT_PRODUCT_CC864_DUAL		0x1005
+#define TELIT_PRODUCT_CC864_SINGLE		0x1006
+#define TELIT_PRODUCT_DE910_DUAL		0x1010
 
 /* ZTE PRODUCTS */
 #define ZTE_VENDOR_ID				0x19d2
@@ -771,6 +774,9 @@ static const struct usb_device_id option
 	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6008) },
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) },
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864G) },
+	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_DUAL) },
+	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) },
+	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff),
 		.driver_info = (kernel_ulong_t)&net_intf1_blacklist },
author maintainer
#3 lore raw

PATCH 3/175 USB: option: make interface blacklist work again

In reply to Greg KH

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

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

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

commit 963940cf472d76eca2d36296e461202cc6997352 upstream.

commit 0d905fd "USB: option: convert Huawei K3765, K4505, K4605 reservered interface to blacklist" accidentally ANDed two blacklist tests by leaving out a return. This was not noticed because the two consecutive bracketless if statements made it syntactically correct.

---
 drivers/usb/serial/option.c |    1 +
 1 file changed, 1 insertion(+)
drivers/usb/serial/option.c +1 -0
@@ -1373,6 +1373,7 @@ static int option_probe(struct usb_seria
 		serial->interface->cur_altsetting->desc.bInterfaceNumber,
 		OPTION_BLACKLIST_RESERVED_IF,
 		(const struct option_blacklist_info *) id->driver_info))
+		return -ENODEV;
 
 	/* Don't bind network interface on Samsung GT-B3730, it is handled by a separate module */
 	if (serial->dev->descriptor.idVendor == SAMSUNG_VENDOR_ID &&
author maintainer
#4 lore raw

PATCH 4/175 USB: option: add ZTE MF820D

In reply to Greg KH

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

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

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

commit 5889d3d4209c1050b4a3c96c41faf6c0976a4acf upstream.

This device presents a total of 5 interfaces with ff/ff/ff class/subclass/protocol. The last one of these is verified to be a QMI/wwan combined interface which should be handled by the qmi_wwan driver, so we blacklist it here.

---
 drivers/usb/serial/option.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/usb/serial/option.c +2 -0
@@ -901,6 +901,8 @@ static const struct usb_device_id option
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0164, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff),
+	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) },
author maintainer
#5 lore raw

PATCH 5/175 staging: android/lowmemorykiller: Dont unregister notifier from atomic context

In reply to Greg KH

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

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

From: "Paul E. McKenney" <[email protected]>

commit 1eda5166c7640092f512138be6899d050c3d62ed upstream.

The lowmemorykiller registers an atomic notifier for notfication of when the task is freed. From this atomic notifier callback, it removes the atomic notifier via task_free_unregister(). This is incorrect because atomic_notifier_chain_unregister() calls syncronize_rcu(), which can sleep, which shouldn't be done from an atomic notifier.

Fix this by registering the notifier during init, and only unregister it if the lowmemorykiller is unloaded.

Rebased to -next by Paul E. McKenney.
Rebased to -next again by Anton Vorontsov.

---
 drivers/staging/android/lowmemorykiller.c |   14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
drivers/staging/android/lowmemorykiller.c +7 -7
@@ -73,10 +73,10 @@ static int
 task_notify_func(struct notifier_block *self, unsigned long val, void *data)
 {
 	struct task_struct *task = data;
-	if (task == lowmem_deathpending) {
+
+	if (task == lowmem_deathpending)
 		lowmem_deathpending = NULL;
-		task_handoff_unregister(&task_nb);
-	}
+
 	return NOTIFY_OK;
 }
 
@@ -174,14 +174,12 @@ static int lowmem_shrink(struct shrinker
 			     selected->pid, selected->comm,
 			     selected_oom_adj, selected_tasksize);
 		/*
-		 * If CONFIG_PROFILING is off, then task_handoff_register()
-		 * is a nop. In that case we don't want to stall the killer
-		 * by setting lowmem_deathpending.
+		 * If CONFIG_PROFILING is off, then we don't want to stall
+		 * the killer by setting lowmem_deathpending.
 		 */
 #ifdef CONFIG_PROFILING
 		lowmem_deathpending = selected;
 		lowmem_deathpending_timeout = jiffies + HZ;
-		task_handoff_register(&task_nb);
 #endif
 		force_sig(SIGKILL, selected);
 		rem -= selected_tasksize;
@@ -199,6 +197,7 @@ static struct shrinker lowmem_shrinker =
 
 static int __init lowmem_init(void)
 {
+	task_handoff_register(&task_nb);
 	register_shrinker(&lowmem_shrinker);
 	return 0;
 }
@@ -206,6 +205,7 @@ static int __init lowmem_init(void)
 static void __exit lowmem_exit(void)
 {
 	unregister_shrinker(&lowmem_shrinker);
+	task_handoff_unregister(&task_nb);
 }
 
 module_param_named(cost, lowmem_shrinker.seeks, int, S_IRUGO | S_IWUSR);
author maintainer
#6 lore raw

PATCH 6/175 staging: zcache: avoid AB-BA deadlock condition

In reply to Greg KH

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

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

From: Andrea Righi <[email protected]>

commit cfbc6a92212e74b07aa76c9e2f20c542e36077fb upstream.

Commit 9256a47 fixed a deadlock condition, being sure that the buddy list spinlock is always taken before the page spinlock.

However in zbud_free_and_delist() locking order is the opposite (page lock -> list lock).

Possible unsafe locking scenario (reported by lockdep):
        CPU0                    CPU1
        ----                    ----
   lock(&(&zbpg->lock)->rlock);
                                lock(zbud_budlists_spinlock);
                                lock(&(&zbpg->lock)->rlock);

lock(zbud_budlists_spinlock);

Fix by grabbing the locks in opposite order in zbud_free_and_delist().

---
 drivers/staging/zcache/zcache-main.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/staging/zcache/zcache-main.c +2 -2
@@ -299,10 +299,12 @@ static void zbud_free_and_delist(struct
 	struct zbud_page *zbpg =
 		container_of(zh, struct zbud_page, buddy[budnum]);
 
+	spin_lock(&zbud_budlists_spinlock);
 	spin_lock(&zbpg->lock);
 	if (list_empty(&zbpg->bud_list)) {
 		/* ignore zombie page... see zbud_evict_pages() */
 		spin_unlock(&zbpg->lock);
+		spin_unlock(&zbud_budlists_spinlock);
 		return;
 	}
 	size = zbud_free(zh);
@@ -310,7 +312,6 @@ static void zbud_free_and_delist(struct
 	zh_other = &zbpg->buddy[(budnum == 0) ? 1 : 0];
 	if (zh_other->size == 0) { /* was unbuddied: unlist and free */
 		chunks = zbud_size_to_chunks(size) ;
-		spin_lock(&zbud_budlists_spinlock);
 		BUG_ON(list_empty(&zbud_unbuddied[chunks].list));
 		list_del_init(&zbpg->bud_list);
 		zbud_unbuddied[chunks].count--;
@@ -318,7 +319,6 @@ static void zbud_free_and_delist(struct
 		zbud_free_raw_page(zbpg);
 	} else { /* was buddied: move remaining buddy to unbuddied list */
 		chunks = zbud_size_to_chunks(zh_other->size) ;
-		spin_lock(&zbud_budlists_spinlock);
 		list_del_init(&zbpg->bud_list);
 		zcache_zbud_buddied_count--;
 		list_add_tail(&zbpg->bud_list, &zbud_unbuddied[chunks].list);
author maintainer
#7 lore raw

PATCH 7/175 staging/octeon: Fix PHY binding in octeon-ethernet driver.

In reply to Greg KH

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

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

From: David Daney <[email protected]>

commit b5c19ca8014aa5151712274d5e70c3666a8918c1 upstream.

Commit d6c25be (mdio-octeon: use an unique MDIO bus name.) changed the names used to refer to MDIO buses. The ethernet driver must be changed to match, so that the PHY drivers can be attached.

---
 drivers/staging/octeon/ethernet-mdio.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/staging/octeon/ethernet-mdio.c +2 -2
@@ -164,9 +164,9 @@ int cvm_oct_phy_setup_device(struct net_
 
 	int phy_addr = cvmx_helper_board_get_mii_address(priv->port);
 	if (phy_addr != -1) {
-		char phy_id[20];
+		char phy_id[MII_BUS_ID_SIZE + 3];
 
-		snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "0", phy_addr);
+		snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "mdio-octeon-0", phy_addr);
 
 		priv->phydev = phy_connect(dev, phy_id, cvm_oct_adjust_link, 0,
 					PHY_INTERFACE_MODE_GMII);
author maintainer
#8 lore raw

PATCH 8/175 USB: ftdi_sio: fix problem when the manufacture is a NULL string

In reply to Greg KH

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

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

From: Greg Kroah-Hartman <[email protected]>

commit 656d2b3964a9d0f9864d472f8dfa2dd7dd42e6c0 upstream.

On some misconfigured ftdi_sio devices, if the manufacturer string is NULL, the kernel will oops when the device is plugged in. This patch fixes the problem.

---
 drivers/usb/serial/ftdi_sio.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/usb/serial/ftdi_sio.c +2 -1
@@ -1763,7 +1763,8 @@ static int ftdi_8u2232c_probe(struct usb
 
 	dbg("%s", __func__);
 
-	if (strcmp(udev->manufacturer, "CALAO Systems") == 0)
+	if ((udev->manufacturer) &&
+	    (strcmp(udev->manufacturer, "CALAO Systems") == 0))
 		return ftdi_jtag_probe(serial);
 
 	return 0;
author maintainer
#9 lore raw

PATCH 9/175 USB: ftdi_sio: add support for BeagleBone rev A5+

In reply to Greg KH

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

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

From: Peter Korsgaard <[email protected]>

commit 444aa7fa9bd752d19ce472d3e02558b987c3cc67 upstream.

BeagleBone changed to the default FTDI 0403:6010 id in rev A5 to make life easier for Windows users, so we need a similar workaround as the Calao board to support it.

---
 drivers/usb/serial/ftdi_sio.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/usb/serial/ftdi_sio.c +2 -2
@@ -1763,8 +1763,8 @@ static int ftdi_8u2232c_probe(struct usb
 
 	dbg("%s", __func__);
 
-	if ((udev->manufacturer) &&
-	    (strcmp(udev->manufacturer, "CALAO Systems") == 0))
+	if ((udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) ||
+	    (udev->product && !strcmp(udev->product, "BeagleBone/XDS100")))
 		return ftdi_jtag_probe(serial);
 
 	return 0;
author maintainer
#10 lore raw

PATCH 10/175 USB: Microchip VID mislabeled as Hornby VID in ftdi_sio.

In reply to Greg KH

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

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

From: Bruno Thomsen <[email protected]>

commit c1cee1d84001815a1b4321c49b995254c0df3100 upstream.

Microchip VID (0x04d8) was mislabeled as Hornby VID according to USB-IDs.

A Full Speed USB Demo Board PID (0x000a) was mislabeled as Hornby Elite (an Digital Command Controller Console for model railways).

Most likely the Hornby based their design on
PIC18F87J50 Full Speed USB Demo Board.

---
 drivers/usb/serial/ftdi_sio.c     |    2 +-
 drivers/usb/serial/ftdi_sio_ids.h |   10 +++++++---
 2 files changed, 8 insertions(+), 4 deletions(-)
drivers/usb/serial/ftdi_sio.c +1 -1
@@ -797,7 +797,7 @@ static struct usb_device_id id_table_com
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	{ USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
-	{ USB_DEVICE(HORNBY_VID, HORNBY_ELITE_PID) },
+	{ USB_DEVICE(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID) },
 	{ USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
 	{ USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
drivers/usb/serial/ftdi_sio_ids.h +7 -3
@@ -532,10 +532,14 @@
 #define ADI_GNICEPLUS_PID	0xF001
 
 /*
- * Hornby Elite
+ * Microchip Technology, Inc.
+ *
+ * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are also used by:
+ * Hornby Elite - Digital Command Control Console
+ * http://www.hornby.com/hornby-dcc/controllers/
  */
-#define HORNBY_VID		0x04D8
-#define HORNBY_ELITE_PID	0x000A
+#define MICROCHIP_VID		0x04D8
+#define MICROCHIP_USB_BOARD_PID	0x000A /* CDC RS-232 Emulation Demo */
 
 /*
  * RATOC REX-USB60F
author maintainer
#11 lore raw

PATCH 11/175 USB: ftdi_sio: new PID: Distortec JTAG-lock-pick

In reply to Greg KH

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

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

From: Michał Wróbel <[email protected]>

commit 47594d5528f28a4c025c2955c68104c75815637c upstream.

---
 drivers/usb/serial/ftdi_sio.c     |    2 ++
 drivers/usb/serial/ftdi_sio_ids.h |    2 ++
 2 files changed, 4 insertions(+)
drivers/usb/serial/ftdi_sio.c +2 -0
@@ -846,6 +846,8 @@ static struct usb_device_id id_table_com
 	{ USB_DEVICE(ST_VID, ST_STMCLT1030_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk },
 	{ USB_DEVICE(FTDI_VID, FTDI_RF_R106) },
+	{ USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID),
+		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	{ },					/* Optional parameter entry */
 	{ }					/* Terminating entry */
 };
drivers/usb/serial/ftdi_sio_ids.h +2 -0
@@ -97,6 +97,8 @@
 #define FTDI_TACTRIX_OPENPORT_13S_PID	0xCC49	/* OpenPort 1.3 Subaru */
 #define FTDI_TACTRIX_OPENPORT_13U_PID	0xCC4A	/* OpenPort 1.3 Universal */
 
+#define FTDI_DISTORTEC_JTAG_LOCK_PICK_PID	0xCFF8
+
 /* SCS HF Radio Modems PID's (http://www.scs-ptc.com) */
 /* the VID is the standard ftdi vid (FTDI_VID) */
 #define FTDI_SCS_DEVICE_0_PID 0xD010    /* SCS PTC-IIusb */
author maintainer
#12 lore raw

PATCH 12/175 USB: ftdi_sio: add support for FT-X series devices

In reply to Greg KH

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

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

From: Jim Paris <[email protected]>

commit dc0827c128c0ee5a58b822b99d662b59f4b8e970 upstream.

Add PID 0x6015, corresponding to the new series of FT-X chips (FT220XD, FT201X, FT220X, FT221X, FT230X, FT231X, FT240X). They all appear as serial devices, and seem indistinguishable except for the default product string stored in their EEPROM. The baudrate generation matches FT232RL devices.

Tested with a FT201X and FT230X at various baudrates (100 - 3000000).

Sample dmesg:
ftdi_sio: v1.6.0:USB FTDI Serial Converters Driver
usb 2-1: new full-speed USB device number 6 using ohci_hcd
usb 2-1: New USB device found, idVendor=0403, idProduct=6015
usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 2-1: Product: FT230X USB Half UART
usb 2-1: Manufacturer: FTDI
usb 2-1: SerialNumber: DC001WI6
ftdi_sio 2-1:1.0: FTDI USB Serial Device converter detected drivers/usb/serial/ftdi_sio.c: ftdi_sio_port_probe drivers/usb/serial/ftdi_sio.c: ftdi_determine_type: bcdDevice = 0x1000, bNumInterfaces = 1 usb 2-1: Detected FT-X
usb 2-1: Number of endpoints 2
usb 2-1: Endpoint 1 MaxPacketSize 64
usb 2-1: Endpoint 2 MaxPacketSize 64
usb 2-1: Setting MaxPacketSize 64
drivers/usb/serial/ftdi_sio.c: read_latency_timer drivers/usb/serial/ftdi_sio.c: write_latency_timer: setting latency timer = 1 drivers/usb/serial/ftdi_sio.c: create_sysfs_attrs drivers/usb/serial/ftdi_sio.c: sysfs attributes for FT-X
usb 2-1: FTDI USB Serial Device converter now attached to ttyUSB0

---
 drivers/usb/serial/ftdi_sio.c     |   20 +++++++++++++++-----
 drivers/usb/serial/ftdi_sio.h     |    3 ++-
 drivers/usb/serial/ftdi_sio_ids.h |    1 +
 3 files changed, 18 insertions(+), 6 deletions(-)
drivers/usb/serial/ftdi_sio.c +15 -5
@@ -188,6 +188,7 @@ static struct usb_device_id id_table_com
 		.driver_info = (kernel_ulong_t)&ftdi_8u2232c_quirk },
 	{ USB_DEVICE(FTDI_VID, FTDI_4232H_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_232H_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_FTX_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) },
@@ -870,7 +871,8 @@ static const char *ftdi_chip_name[] = {
 	[FT232RL] = "FT232RL",
 	[FT2232H] = "FT2232H",
 	[FT4232H] = "FT4232H",
-	[FT232H]  = "FT232H"
+	[FT232H]  = "FT232H",
+	[FTX]     = "FT-X"
 };
 
 
@@ -1171,7 +1173,8 @@ static __u32 get_ftdi_divisor(struct tty
 		break;
 	case FT232BM: /* FT232BM chip */
 	case FT2232C: /* FT2232C chip */
-	case FT232RL:
+	case FT232RL: /* FT232RL chip */
+	case FTX:     /* FT-X series */
 		if (baud <= 3000000) {
 			__u16 product_id = le16_to_cpu(
 				port->serial->dev->descriptor.idProduct);
@@ -1460,10 +1463,14 @@ static void ftdi_determine_type(struct u
 	} else if (version < 0x900) {
 		/* Assume it's an FT232RL */
 		priv->chip_type = FT232RL;
-	} else {
+	} else if (version < 0x1000) {
 		/* Assume it's an FT232H */
 		priv->chip_type = FT232H;
+	} else {
+		/* Assume it's an FT-X series device */
+		priv->chip_type = FTX;
 	}
+
 	dev_info(&udev->dev, "Detected %s\n", ftdi_chip_name[priv->chip_type]);
 }
 
@@ -1591,7 +1598,8 @@ static int create_sysfs_attrs(struct usb
 		     priv->chip_type == FT232RL ||
 		     priv->chip_type == FT2232H ||
 		     priv->chip_type == FT4232H ||
-		     priv->chip_type == FT232H)) {
+		     priv->chip_type == FT232H ||
+		     priv->chip_type == FTX)) {
 			retval = device_create_file(&port->dev,
 						    &dev_attr_latency_timer);
 		}
@@ -1613,7 +1621,8 @@ static void remove_sysfs_attrs(struct us
 		    priv->chip_type == FT232RL ||
 		    priv->chip_type == FT2232H ||
 		    priv->chip_type == FT4232H ||
-                    priv->chip_type == FT232H) {
+		    priv->chip_type == FT232H ||
+		    priv->chip_type == FTX) {
 			device_remove_file(&port->dev, &dev_attr_latency_timer);
 		}
 	}
@@ -2291,6 +2300,7 @@ static int ftdi_tiocmget(struct tty_stru
 	case FT2232H:
 	case FT4232H:
 	case FT232H:
+	case FTX:
 		len = 2;
 		break;
 	default:
drivers/usb/serial/ftdi_sio.h +2 -1
@@ -157,7 +157,8 @@ enum ftdi_chip_type {
 	FT232RL = 5,
 	FT2232H = 6,
 	FT4232H = 7,
-	FT232H  = 8
+	FT232H  = 8,
+	FTX     = 9,
 };
 
 enum ftdi_sio_baudrate {
drivers/usb/serial/ftdi_sio_ids.h +1 -0
@@ -23,6 +23,7 @@
 #define FTDI_8U2232C_PID 0x6010 /* Dual channel device */
 #define FTDI_4232H_PID 0x6011 /* Quad channel hi-speed device */
 #define FTDI_232H_PID  0x6014 /* Single channel hi-speed device */
+#define FTDI_FTX_PID   0x6015 /* FT-X series (FT201X, FT230X, FT231X, etc) */
 #define FTDI_SIO_PID	0x8372	/* Product Id SIO application of 8U100AX */
 #define FTDI_232RL_PID  0xFBFA  /* Product ID for FT232RL */
 
author maintainer
#13 lore raw

PATCH 13/175 USB: ftdi_sio: new PID: LUMEL PD12

In reply to Greg KH

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

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

From: Michał Wróbel <[email protected]>

commit 57e596f3af88ef52dea9640ed5e34ecd38893a02 upstream.

---
 drivers/usb/serial/ftdi_sio.c     |    1 +
 drivers/usb/serial/ftdi_sio_ids.h |    2 ++
 2 files changed, 3 insertions(+)
drivers/usb/serial/ftdi_sio.c +1 -0
@@ -849,6 +849,7 @@ static struct usb_device_id id_table_com
 	{ USB_DEVICE(FTDI_VID, FTDI_RF_R106) },
 	{ USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+	{ USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) },
 	{ },					/* Optional parameter entry */
 	{ }					/* Terminating entry */
 };
drivers/usb/serial/ftdi_sio_ids.h +2 -0
@@ -30,6 +30,8 @@
 
 /*** third-party PIDs (using FTDI_VID) ***/
 
+#define FTDI_LUMEL_PD12_PID	0x6002
+
 /*
  * Marvell OpenRD Base, Client
  * http://www.open-rd.org
author maintainer
#14 lore raw

PATCH 14/175 powerpc/usb: fix bug of kernel hang when initializing usb

In reply to Greg KH

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

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

From: Shengzhou Liu <[email protected]>

commit 28c56ea1431421dec51b7b229369e991481453df upstream.

If USB UTMI PHY is not enable, writing to portsc register will lead to kernel hang during boot up.

---
 drivers/usb/host/ehci-fsl.c |    4 ++++
 drivers/usb/host/ehci-fsl.h |    1 +
 2 files changed, 5 insertions(+)
drivers/usb/host/ehci-fsl.c +4 -0
@@ -216,6 +216,8 @@ static void ehci_fsl_setup_phy(struct eh
 			       unsigned int port_offset)
 {
 	u32 portsc;
+	struct usb_hcd *hcd = ehci_to_hcd(ehci);
+	void __iomem *non_ehci = hcd->regs;
 
 	portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]);
 	portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW);
@@ -231,6 +233,8 @@ static void ehci_fsl_setup_phy(struct eh
 		portsc |= PORT_PTS_PTW;
 		/* fall through */
 	case FSL_USB2_PHY_UTMI:
+		/* enable UTMI PHY */
+		setbits32(non_ehci + FSL_SOC_USB_CTRL, CTRL_UTMI_PHY_EN);
 		portsc |= PORT_PTS_UTMI;
 		break;
 	case FSL_USB2_PHY_NONE:
drivers/usb/host/ehci-fsl.h +1 -0
@@ -45,5 +45,6 @@
 #define FSL_SOC_USB_PRICTRL	0x40c	/* NOTE: big-endian */
 #define FSL_SOC_USB_SICTRL	0x410	/* NOTE: big-endian */
 #define FSL_SOC_USB_CTRL	0x500	/* NOTE: big-endian */
+#define CTRL_UTMI_PHY_EN	(1<<9)
 #define SNOOP_SIZE_2GB		0x1e
 #endif				/* _EHCI_FSL_H */
author maintainer
#15 lore raw

PATCH 15/175 staging: r8712u: Fix regression introduced by commit a5ee652

In reply to Greg KH

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

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

From: Larry Finger <[email protected]>

commit 9f4bc8cf3fe750ed093856a5f5d41c11cc12ad22 upstream.

In commit a5ee652 "staging: r8712u: Interface-state not fully tracked", the private boolean "bup" was set false when the interface was brought down, as that seemed appropriate. This change has not caused any problems when using NetworkManager or manual control of the device; however, when wicd control is used, there is a locking problem in wpa_supplicant, as shown in
https://bugzilla.kernel.org/show_bug.cgi?id=42818.

This fix reverts the only code change in commit a5ee652. My analysis is that "bup" is badly named. In its present form, it seems to indicate the up/down state of the device, but its usage is more consistent with an initialized/uninitialized state. That problem will be addressed in a later patch.

Note: Commit 8c213fa, which introdued asynchronous firmware loading for this driver, exposed this bug to a greater extent. That bug is addressed in the next patch in this series.

This bug is also responsible for the bug in
https://bugzilla.kernel.org/show_bug.cgi?id=42815. and this bug is
also part of the problems discussed at https://bugs.archlinux.org/task/27996#comment89950.

---
 drivers/staging/rtl8712/os_intfs.c |    2 --
 1 file changed, 2 deletions(-)
drivers/staging/rtl8712/os_intfs.c +0 -2
@@ -476,8 +476,6 @@ static int netdev_close(struct net_devic
 	r8712_free_assoc_resources(padapter);
 	/*s2-4.*/
 	r8712_free_network_queue(padapter);
-	/* The interface is no longer Up: */
-	padapter->bup = false;
 	release_firmware(padapter->fw);
 	/* never exit with a firmware callback pending */
 	wait_for_completion(&padapter->rtl8712_fw_ready);
author maintainer
#16 lore raw

PATCH 16/175 staging: r8712u: Fix regression in signal level after commit c6dc001

In reply to Greg KH

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

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

From: Larry Finger <[email protected]>

commit da3e6ec2f443ac00aa623c5921e3521f5f38efe4 upstream.

In commit c6dc001 "staging: r8712u: Merging Realtek's latest (v2.6.6). Various fixes", the returned qual.qual member of the iw_statistics struct was changed. For strong signals, this change made no difference; however for medium and weak signals it results in a low signal that shows considerable fluctuation, When using wicd for a medium-strength AP, the value reported in the status line is reduced from 100% to 60% by this bug.

This problem is reported in https://bugzilla.kernel.org/show_bug.cgi?id=42826.

---
 drivers/staging/rtl8712/rtl871x_ioctl_linux.c |    8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)
drivers/staging/rtl8712/rtl871x_ioctl_linux.c +1 -7
@@ -2380,13 +2380,7 @@ static struct iw_statistics *r871x_get_w
 		tmp_qual = padapter->recvpriv.signal;
 		tmp_noise = padapter->recvpriv.noise;
 		piwstats->qual.level = tmp_level;
-		/*piwstats->qual.qual = tmp_qual;
-		 * The NetworkManager of Fedora 10, 13 will use the link
-		 * quality for its display.
-		 * So, use the fw_rssi on link quality variable because
-		 * fw_rssi will be updated per 2 seconds.
-		 */
-		piwstats->qual.qual = tmp_level;
+		piwstats->qual.qual = tmp_qual;
 		piwstats->qual.noise = tmp_noise;
 	}
 	piwstats->qual.updated = IW_QUAL_ALL_UPDATED;
author maintainer
#17 lore raw

PATCH 17/175 usb: dwc3: make dwc3_get_device_id() return the id

In reply to Greg KH

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

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

From: Dan Carpenter <[email protected]>

commit 075cd14d2a8d35afc39ad28fc7b968275881266b upstream.

We always return zero instead of the id we found.

---
 drivers/usb/dwc3/core.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/dwc3/core.c +1 -1
@@ -86,7 +86,7 @@ again:
 		id = -ENOMEM;
 	}
 
-	return 0;
+	return id;
 }
 EXPORT_SYMBOL_GPL(dwc3_get_device_id);
 
author maintainer
#18 lore raw

PATCH 18/175 usb: dwc3: gadget: dont wrap around the TRB poll on non-ISOC

In reply to Greg KH

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

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

From: Paul Zimmerman <[email protected]>

commit 8d62cd65d74d0e241b3a152f7347bb66126b705b upstream.

If we have a non-ISOC endpoint, we will not have a Link TRB pointing to the beginning of the TRB pool. On such endpoints, we don't want to let the driver wrap around the TRB pool otherwise controller will hang waiting for a valid TRB.

---
 drivers/usb/dwc3/gadget.c |    8 ++++++++
 1 file changed, 8 insertions(+)
drivers/usb/dwc3/gadget.c +8 -0
@@ -667,6 +667,7 @@ static void dwc3_prepare_trbs(struct dwc
 {
 	struct dwc3_request	*req, *n;
 	u32			trbs_left;
+	u32			max;
 	unsigned int		last_one = 0;
 
 	BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM);
@@ -674,6 +675,13 @@ static void dwc3_prepare_trbs(struct dwc
 	/* the first request must not be queued */
 	trbs_left = (dep->busy_slot - dep->free_slot) & DWC3_TRB_MASK;
 
+	/* Can't wrap around on a non-isoc EP since there's no link TRB */
+	if (!usb_endpoint_xfer_isoc(dep->desc)) {
+		max = DWC3_TRB_NUM - (dep->free_slot & DWC3_TRB_MASK);
+		if (trbs_left > max)
+			trbs_left = max;
+	}
+
 	/*
 	 * if busy & slot are equal than it is either full or empty. If we are
 	 * starting to proceed requests then we are empty. Otherwise we ar
author maintainer
#19 lore raw

PATCH 19/175 usb: dwc3: fix bogus test in dwc3_gadget_start_isoc

In reply to Greg KH

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

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

From: Paul Zimmerman <[email protected]>

commit 9bafa56c7cee5c6fa68de5924220abb220c7e229 upstream.

Zero is a valid value for a microframe number. So remove the bogus test for non-zero in dwc3_gadget_start_isoc().

---
 drivers/usb/dwc3/gadget.c |   16 +++++-----------
 1 file changed, 5 insertions(+), 11 deletions(-)
drivers/usb/dwc3/gadget.c +5 -11
@@ -1498,7 +1498,7 @@ static void dwc3_endpoint_transfer_compl
 static void dwc3_gadget_start_isoc(struct dwc3 *dwc,
 		struct dwc3_ep *dep, const struct dwc3_event_depevt *event)
 {
-	u32 uf;
+	u32 uf, mask;
 
 	if (list_empty(&dep->request_list)) {
 		dev_vdbg(dwc->dev, "ISOC ep %s run out for requests.\n",
@@ -1506,16 +1506,10 @@ static void dwc3_gadget_start_isoc(struc
 		return;
 	}
 
-	if (event->parameters) {
-		u32 mask;
-
-		mask = ~(dep->interval - 1);
-		uf = event->parameters & mask;
-		/* 4 micro frames in the future */
-		uf += dep->interval * 4;
-	} else {
-		uf = 0;
-	}
+	mask = ~(dep->interval - 1);
+	uf = event->parameters & mask;
+	/* 4 micro frames in the future */
+	uf += dep->interval * 4;
 
 	__dwc3_gadget_kick_transfer(dep, uf, 1);
 }
author maintainer
#20 lore raw

PATCH 20/175 usb: dwc3: use proper function for setting endpoint name

In reply to Greg KH

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

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

From: Anton Tikhomirov <[email protected]>

commit 27a78d6a283d6782438f72306746afe4bf44c215 upstream.

It's wrong to use the size of array as an argument for strncat. Memory corruption is possible. strlcat is exactly what we need here.

---
 drivers/usb/dwc3/gadget.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/usb/dwc3/gadget.c +4 -4
@@ -485,16 +485,16 @@ static int dwc3_gadget_ep_enable(struct
 
 	switch (usb_endpoint_type(desc)) {
 	case USB_ENDPOINT_XFER_CONTROL:
-		strncat(dep->name, "-control", sizeof(dep->name));
+		strlcat(dep->name, "-control", sizeof(dep->name));
 		break;
 	case USB_ENDPOINT_XFER_ISOC:
-		strncat(dep->name, "-isoc", sizeof(dep->name));
+		strlcat(dep->name, "-isoc", sizeof(dep->name));
 		break;
 	case USB_ENDPOINT_XFER_BULK:
-		strncat(dep->name, "-bulk", sizeof(dep->name));
+		strlcat(dep->name, "-bulk", sizeof(dep->name));
 		break;
 	case USB_ENDPOINT_XFER_INT:
-		strncat(dep->name, "-int", sizeof(dep->name));
+		strlcat(dep->name, "-int", sizeof(dep->name));
 		break;
 	default:
 		dev_err(dwc->dev, "invalid endpoint transfer type\n");
author maintainer
#21 lore raw

PATCH 21/175 staging: vme: fix section mismatches in linux-next 20120314

In reply to Greg KH

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

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

From: Gerard Snitselaar <[email protected]>

commit bf3a85be67068a0f55804349e6e1dce80008c45c upstream.

pio2_gpio_init() annotated with __init, but called by pio2_probe() which is annotated __devinit. pio2_gpio_exit() is annotated __exit, but is called by pio2_probe() and by pio2_remove() which is annotated __devexit.

---
 drivers/staging/vme/devices/vme_pio2.h      |    4 ++--
 drivers/staging/vme/devices/vme_pio2_gpio.c |    4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)
drivers/staging/vme/devices/vme_pio2.h +2 -2
@@ -243,7 +243,7 @@ struct pio2_card {
 int pio2_cntr_reset(struct pio2_card *);
 
 int pio2_gpio_reset(struct pio2_card *);
-int __init pio2_gpio_init(struct pio2_card *);
-void __exit pio2_gpio_exit(struct pio2_card *);
+int __devinit pio2_gpio_init(struct pio2_card *);
+void pio2_gpio_exit(struct pio2_card *);
 
 #endif /* _VME_PIO2_H_ */
drivers/staging/vme/devices/vme_pio2_gpio.c +2 -2
@@ -187,7 +187,7 @@ int pio2_gpio_reset(struct pio2_card *ca
 	return 0;
 }
 
-int __init pio2_gpio_init(struct pio2_card *card)
+int __devinit pio2_gpio_init(struct pio2_card *card)
 {
 	int retval = 0;
 	char *label;
@@ -220,7 +220,7 @@ int __init pio2_gpio_init(struct pio2_ca
 	return retval;
 };
 
-void __exit pio2_gpio_exit(struct pio2_card *card)
+void pio2_gpio_exit(struct pio2_card *card)
 {
 	const char *label = card->gc.label;
 
author maintainer
#22 lore raw

PATCH 22/175 usb: musb: Reselect index reg in interrupt context

In reply to Greg KH

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

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

From: Supriya Karanth <[email protected]>

commit 39287076e46d2c19aaceaa6f0a44168ae4d257ec upstream.

musb INDEX register is getting modified/corrupted during temporary un-locking in a SMP system. Set this register with proper value after re-acquiring the lock

Scenario:
---------
CPU1 is handling a data transfer completion interrupt received for the CLASS1 EP
CPU2 is handling a CLASS2 thread which is queuing data to musb for transfer

Below is the error sequence:

CPU1 | CPU2
--------------------------------------------------------------------

Data transfer completion inter- |
rupt recieved.                  |
                                |
musb INDEX reg set to CLASS1 EP |
                                |
musb LOCK is acquired.          |
                                |
                                | CLASS2 thread queues data.
                                |
                                | CLASS2 thread tries to acquire musb
                                | LOCK but lock is already taken by
                                | CLASS1, so CLASS2 thread is
                                | spinning.
                                |
Quoted 1 line
Quoted 1 line

From Interrupt Context musb |

giveback function is called     |
                                |
The giveback function releases  | CLASS2 thread now acquires LOCK
LOCK                            |
                                |
ClASS1 Request's completion cal-| ClASS2 schedules the data transfer and
lback is called                 | sets the MUSB INDEX to Class2 EP number
                                |
Interrupt handler for CLASS1 EP |
tries to acquire LOCK and is    |
spinning                        |
                                |
Interrupt for Class1 EP acquires| Class2 completes the scheduling etc and
the MUSB LOCK                   | releases the musb LOCK
                                |
Interrupt for Class1 EP schedul-|
es the next data transfer       |
but musb INDEX register is still|
set to CLASS2 EP                |

Since the MUSB INDEX register is set to a different endpoint, we read and modify the wrong registers. Hence data transfer will not happen properly. This results in unpredictable behavior

So, the MUSB INDEX register is set to proper value again when interrupt re-acquires the lock

---
 drivers/usb/musb/musb_gadget.c |   18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
drivers/usb/musb/musb_gadget.c +18 -0
@@ -574,6 +574,15 @@ void musb_g_tx(struct musb *musb, u8 epn
 
 		if (request->actual == request->length) {
 			musb_g_giveback(musb_ep, request, 0);
+			/*
+			 * In the giveback function the MUSB lock is
+			 * released and acquired after sometime. During
+			 * this time period the INDEX register could get
+			 * changed by the gadget_queue function especially
+			 * on SMP systems. Reselect the INDEX to be sure
+			 * we are reading/modifying the right registers
+			 */
+			musb_ep_select(mbase, epnum);
 			req = musb_ep->desc ? next_request(musb_ep) : NULL;
 			if (!req) {
 				dev_dbg(musb->controller, "%s idle now\n",
@@ -983,6 +992,15 @@ void musb_g_rx(struct musb *musb, u8 epn
 		}
 #endif
 		musb_g_giveback(musb_ep, request, 0);
+		/*
+		 * In the giveback function the MUSB lock is
+		 * released and acquired after sometime. During
+		 * this time period the INDEX register could get
+		 * changed by the gadget_queue function especially
+		 * on SMP systems. Reselect the INDEX to be sure
+		 * we are reading/modifying the right registers
+		 */
+		musb_ep_select(mbase, epnum);
 
 		req = next_request(musb_ep);
 		if (!req)
author maintainer
#23 lore raw

PATCH 23/175 usb: gadget: Clear usb_endpoint_descriptor inside the struct usb_ep on disable

In reply to Greg KH

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

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

From: Ido Shayevitz <[email protected]>

commit f9c56cdd3905c96c600456203637bd7ec8ec6383 upstream.

This fix a bug in f_serial, which expect the ep->desc to be NULL after disabling an endpoint.

---
 drivers/usb/dwc3/gadget.c           |    1 +
 drivers/usb/gadget/amd5536udc.c     |    1 +
 drivers/usb/gadget/at91_udc.c       |    1 +
 drivers/usb/gadget/atmel_usba_udc.c |    1 +
 drivers/usb/gadget/ci13xxx_udc.c    |    1 +
 drivers/usb/gadget/fsl_qe_udc.c     |    1 +
 drivers/usb/gadget/fsl_udc_core.c   |    1 +
 drivers/usb/gadget/goku_udc.c       |    1 +
 drivers/usb/gadget/langwell_udc.c   |    1 +
 drivers/usb/gadget/mv_udc_core.c    |    1 +
 drivers/usb/gadget/omap_udc.c       |    1 +
 drivers/usb/gadget/pch_udc.c        |    1 +
 drivers/usb/gadget/pxa25x_udc.c     |    2 ++
 drivers/usb/gadget/s3c-hsudc.c      |    2 ++
 drivers/usb/gadget/s3c2410_udc.c    |    2 ++
 15 files changed, 18 insertions(+)
drivers/usb/dwc3/gadget.c +1 -0
@@ -440,6 +440,7 @@ static int __dwc3_gadget_ep_disable(stru
 
 	dep->stream_capable = false;
 	dep->desc = NULL;
+	dep->endpoint.desc = NULL;
 	dep->comp_desc = NULL;
 	dep->type = 0;
 	dep->flags = 0;
drivers/usb/gadget/amd5536udc.c +1 -0
@@ -445,6 +445,7 @@ static void ep_init(struct udc_regs __io
 
 	VDBG(ep->dev, "ep-%d reset\n", ep->num);
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->ep.ops = &udc_ep_ops;
 	INIT_LIST_HEAD(&ep->queue);
 
drivers/usb/gadget/at91_udc.c +1 -0
@@ -558,6 +558,7 @@ static int at91_ep_disable (struct usb_e
 
 	/* restore the endpoint's pristine config */
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->ep.maxpacket = ep->maxpacket;
 
 	/* reset fifos and endpoint */
drivers/usb/gadget/atmel_usba_udc.c +1 -0
@@ -659,6 +659,7 @@ static int usba_ep_disable(struct usb_ep
 		return -EINVAL;
 	}
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 
 	list_splice_init(&ep->queue, &req_list);
 	if (ep->can_dma) {
drivers/usb/gadget/ci13xxx_udc.c +1 -0
@@ -2181,6 +2181,7 @@ static int ep_disable(struct usb_ep *ep)
 	} while (mEp->dir != direction);
 
 	mEp->desc = NULL;
+	mEp->ep.desc = NULL;
 
 	spin_unlock_irqrestore(mEp->lock, flags);
 	return retval;
drivers/usb/gadget/fsl_qe_udc.c +1 -0
@@ -1638,6 +1638,7 @@ static int qe_ep_disable(struct usb_ep *
 	/* Nuke all pending requests (does flush) */
 	nuke(ep, -ESHUTDOWN);
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->stopped = 1;
 	ep->tx_req = NULL;
 	qe_ep_reset(udc, ep->epnum);
drivers/usb/gadget/fsl_udc_core.c +1 -0
@@ -659,6 +659,7 @@ static int fsl_ep_disable(struct usb_ep
 	nuke(ep, -ESHUTDOWN);
 
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->stopped = 1;
 	spin_unlock_irqrestore(&udc->lock, flags);
 
drivers/usb/gadget/goku_udc.c +1 -0
@@ -235,6 +235,7 @@ static void ep_reset(struct goku_udc_reg
 
 	ep->ep.maxpacket = MAX_FIFO_SIZE;
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->stopped = 1;
 	ep->irqs = 0;
 	ep->dma = 0;
drivers/usb/gadget/langwell_udc.c +1 -0
@@ -487,6 +487,7 @@ static int langwell_ep_disable(struct us
 	nuke(ep, -ESHUTDOWN);
 
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->stopped = 1;
 
 	spin_unlock_irqrestore(&dev->lock, flags);
drivers/usb/gadget/mv_udc_core.c +1 -0
@@ -608,6 +608,7 @@ static int  mv_ep_disable(struct usb_ep
 	nuke(ep, -ESHUTDOWN);
 
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->stopped = 1;
 
 	spin_unlock_irqrestore(&udc->lock, flags);
drivers/usb/gadget/omap_udc.c +1 -0
@@ -251,6 +251,7 @@ static int omap_ep_disable(struct usb_ep
 
 	spin_lock_irqsave(&ep->udc->lock, flags);
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	nuke (ep, -ESHUTDOWN);
 	ep->ep.maxpacket = ep->maxpacket;
 	ep->has_dma = 0;
drivers/usb/gadget/pch_udc.c +1 -0
@@ -1493,6 +1493,7 @@ static int pch_udc_pcd_ep_disable(struct
 	pch_udc_ep_disable(ep);
 	pch_udc_disable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num));
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	INIT_LIST_HEAD(&ep->queue);
 	spin_unlock_irqrestore(&ep->dev->lock, iflags);
 	return 0;
drivers/usb/gadget/pxa25x_udc.c +2 -0
@@ -283,6 +283,7 @@ static int pxa25x_ep_disable (struct usb
 	pxa25x_ep_fifo_flush (_ep);
 
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->stopped = 1;
 
 	local_irq_restore(flags);
@@ -1192,6 +1193,7 @@ static void udc_reinit(struct pxa25x_udc
 			list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
 
 		ep->desc = NULL;
+		ep->ep.desc = NULL;
 		ep->stopped = 0;
 		INIT_LIST_HEAD (&ep->queue);
 		ep->pio_irqs = 0;
drivers/usb/gadget/s3c-hsudc.c +2 -0
@@ -816,6 +816,7 @@ static int s3c_hsudc_ep_disable(struct u
 	s3c_hsudc_nuke_ep(hsep, -ESHUTDOWN);
 
 	hsep->desc = 0;
+	hsep->ep.desc = NULL;
 	hsep->stopped = 1;
 
 	spin_unlock_irqrestore(&hsudc->lock, flags);
@@ -1005,6 +1006,7 @@ static void s3c_hsudc_initep(struct s3c_
 	hsep->ep.ops = &s3c_hsudc_ep_ops;
 	hsep->fifo = hsudc->regs + S3C_BR(epnum);
 	hsep->desc = 0;
+	hsep->ep.desc = NULL;
 	hsep->stopped = 0;
 	hsep->wedge = 0;
 
drivers/usb/gadget/s3c2410_udc.c +2 -0
@@ -1148,6 +1148,7 @@ static int s3c2410_udc_ep_disable(struct
 	dprintk(DEBUG_NORMAL, "ep_disable: %s\n", _ep->name);
 
 	ep->desc = NULL;
+	ep->ep.desc = NULL;
 	ep->halted = 1;
 
 	s3c2410_udc_nuke (ep->dev, ep, -ESHUTDOWN);
@@ -1630,6 +1631,7 @@ static void s3c2410_udc_reinit(struct s3
 
 		ep->dev = dev;
 		ep->desc = NULL;
+		ep->ep.desc = NULL;
 		ep->halted = 0;
 		INIT_LIST_HEAD (&ep->queue);
 	}
author maintainer
#24 lore raw

PATCH 24/175 usb: renesas_usbhs: bugfix: add .release function to gpriv->gadget.dev

In reply to Greg KH

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

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

From: Kuninori Morimoto <[email protected]>

commit 3b2a2e47174cd978258bbb0fdf2e2b1b5ec2144c upstream.

This patch fixup below warning on device_unregister()

renesas_usbhs renesas_usbhs.1: host probed
renesas_usbhs renesas_usbhs.1: gadget probed
renesas_usbhs renesas_usbhs.1: irq request err

------------[ cut here ]------------
WARNING: at ${LINUX}/drivers/base/core.c:1)
Device 'gadget' does not have a release() function, it is broken and must be fi.
Modules linked in:
[<c000e25c>] (unwind_backtrace+0x0/0xe4) from [<c0016960>] (warn_slowpath_commo)
[<c0016960>] (warn_slowpath_common+0x4c/0x64) from [<c00169f8>] (warn_slowpath_)
[<c00169f8>] (warn_slowpath_fmt+0x2c/0x3c) from [<c0185b80>] (device_release+0x)
[<c0185b80>] (device_release+0x70/0x84) from [<c013e300>] (kobject_cleanup+0x58)
[<c013e300>] (kobject_cleanup+0x58/0x6c) from [<c01cba14>] (usbhs_mod_gadget_re)
[<c01cba14>] (usbhs_mod_gadget_remove+0x3c/0x6c) from [<c01c8384>] (usbhs_mod_p)
[<c01c8384>] (usbhs_mod_probe+0x68/0x80) from [<c01c7f84>] (usbhs_probe+0x1cc/0)

...

---
 drivers/usb/renesas_usbhs/mod_gadget.c |    6 ++++++
 1 file changed, 6 insertions(+)
drivers/usb/renesas_usbhs/mod_gadget.c +6 -0
@@ -941,6 +941,11 @@ static int usbhsg_stop(struct usbhs_priv
 	return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED);
 }
 
+static void usbhs_mod_gadget_release(struct device *pdev)
+{
+	/* do nothing */
+}
+
 int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
 {
 	struct usbhsg_gpriv *gpriv;
@@ -989,6 +994,7 @@ int usbhs_mod_gadget_probe(struct usbhs_
 	 */
 	dev_set_name(&gpriv->gadget.dev, "gadget");
 	gpriv->gadget.dev.parent	= dev;
+	gpriv->gadget.dev.release	= usbhs_mod_gadget_release;
 	gpriv->gadget.name		= "renesas_usbhs_udc";
 	gpriv->gadget.ops		= &usbhsg_gadget_ops;
 	gpriv->gadget.max_speed		= USB_SPEED_HIGH;
author maintainer
#25 lore raw

PATCH 25/175 usb: gadgetfs: return number of bytes on ep0 read request

In reply to Greg KH

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

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

From: Thomas Faber <[email protected]>

commit 85b4b3c8c189e0159101f7628a71411af072ff69 upstream.

A read from GadgetFS endpoint 0 during the data stage of a control request would always return 0 on success (as returned by wait_event_interruptible) despite having written data into the user buffer.
This patch makes it correctly set the return value to the number of bytes read.

---
 drivers/usb/gadget/inode.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/usb/gadget/inode.c +2 -0
@@ -1043,6 +1043,8 @@ ep0_read (struct file *fd, char __user *
 // FIXME don't call this with the spinlock held ...
 				if (copy_to_user (buf, dev->req->buf, len))
 					retval = -EFAULT;
+				else
+					retval = len;
 				clean_req (dev->gadget->ep0, dev->req);
 				/* NOTE userspace can't yet choose to stall */
 			}
author maintainer
#26 lore raw

PATCH 26/175 USB: gadget: Make g_hid device class conform to spec.

In reply to Greg KH

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

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

From: Orjan Friberg <[email protected]>

commit 33d2832ab0149a26418d360af3c444969a63fb28 upstream.

HID devices should specify this in their interface descriptors, not in the device descriptor. This fixes a "missing hardware id" bug under Windows 7 with a VIA VL800 (3.0) controller.

---
 drivers/usb/gadget/hid.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/usb/gadget/hid.c +3 -3
@@ -60,9 +60,9 @@ static struct usb_device_descriptor devi
 	/* .bDeviceClass =		USB_CLASS_COMM, */
 	/* .bDeviceSubClass =	0, */
 	/* .bDeviceProtocol =	0, */
-	.bDeviceClass =		0xEF,
-	.bDeviceSubClass =	2,
-	.bDeviceProtocol =	1,
+	.bDeviceClass =		USB_CLASS_PER_INTERFACE,
+	.bDeviceSubClass =	0,
+	.bDeviceProtocol =	0,
 	/* .bMaxPacketSize0 = f(hardware) */
 
 	/* Vendor and product id can be overridden by module parameters.  */
author maintainer
#27 lore raw

PATCH 27/175 futex: Cover all PI opcodes with cmpxchg enabled check

In reply to Greg KH

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

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

From: Thomas Gleixner <[email protected]>

commit 59263b513c11398cd66a52d4c5b2b118ce1e0359 upstream.

Some of the newer futex PI opcodes do not check the cmpxchg enabled variable and call unconditionally into the handling functions. Cover all PI opcodes in a separate check.

---
 kernel/futex.c |   19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)
kernel/futex.c +13 -6
@@ -2641,6 +2641,16 @@ long do_futex(u32 __user *uaddr, int op,
 	}
 
 	switch (cmd) {
+	case FUTEX_LOCK_PI:
+	case FUTEX_UNLOCK_PI:
+	case FUTEX_TRYLOCK_PI:
+	case FUTEX_WAIT_REQUEUE_PI:
+	case FUTEX_CMP_REQUEUE_PI:
+		if (!futex_cmpxchg_enabled)
+			return -ENOSYS;
+	}
+
+	switch (cmd) {
 	case FUTEX_WAIT:
 		val3 = FUTEX_BITSET_MATCH_ANY;
 	case FUTEX_WAIT_BITSET:
@@ -2661,16 +2671,13 @@ long do_futex(u32 __user *uaddr, int op,
 		ret = futex_wake_op(uaddr, flags, uaddr2, val, val2, val3);
 		break;
 	case FUTEX_LOCK_PI:
-		if (futex_cmpxchg_enabled)
-			ret = futex_lock_pi(uaddr, flags, val, timeout, 0);
+		ret = futex_lock_pi(uaddr, flags, val, timeout, 0);
 		break;
 	case FUTEX_UNLOCK_PI:
-		if (futex_cmpxchg_enabled)
-			ret = futex_unlock_pi(uaddr, flags);
+		ret = futex_unlock_pi(uaddr, flags);
 		break;
 	case FUTEX_TRYLOCK_PI:
-		if (futex_cmpxchg_enabled)
-			ret = futex_lock_pi(uaddr, flags, 0, timeout, 1);
+		ret = futex_lock_pi(uaddr, flags, 0, timeout, 1);
 		break;
 	case FUTEX_WAIT_REQUEUE_PI:
 		val3 = FUTEX_BITSET_MATCH_ANY;
author maintainer
#28 lore raw

PATCH 28/175 sysfs: Fix memory leak in sysfs_sd_setsecdata().

In reply to Greg KH

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

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

From: Masami Ichikawa <[email protected]>

commit 93518dd2ebafcc761a8637b2877008cfd748c202 upstream.

This patch fixies follwing two memory leak patterns that reported by kmemleak. sysfs_sd_setsecdata() is called during sys_lsetxattr() operation. It checks sd->s_iattr is NULL or not. Then if it is NULL, it calls sysfs_init_inode_attrs() to allocate memory.
That code is this.

iattrs = sd->s_iattr;
if (!iattrs)

                iattrs = sysfs_init_inode_attrs(sd);

The iattrs recieves sysfs_init_inode_attrs()'s result, but sd->s_iattr doesn't know the address. so it needs to set correct address to sd->s_iattr to free memory in other function.

unreferenced object 0xffff880250b73e60 (size 32):
comm "systemd", pid 1, jiffies 4294683888 (age 94.553s) hex dump (first 32 bytes):

    73 79 73 74 65 6d 5f 75 3a 6f 62 6a 65 63 74 5f  system_u:object_
    72 3a 73 79 73 66 73 5f 74 3a 73 30 00 00 00 00  r:sysfs_t:s0....
  backtrace:
    [<ffffffff814cb1d0>] kmemleak_alloc+0x73/0x98
    [<ffffffff811270ab>] __kmalloc+0x100/0x12c
    [<ffffffff8120775a>] context_struct_to_string+0x106/0x210
    [<ffffffff81207cc1>] security_sid_to_context_core+0x10b/0x129
    [<ffffffff812090ef>] security_sid_to_context+0x10/0x12
    [<ffffffff811fb0da>] selinux_inode_getsecurity+0x7d/0xa8
    [<ffffffff811fb127>] selinux_inode_getsecctx+0x22/0x2e
    [<ffffffff811f4d62>] security_inode_getsecctx+0x16/0x18
    [<ffffffff81191dad>] sysfs_setxattr+0x96/0x117
    [<ffffffff811542f0>] __vfs_setxattr_noperm+0x73/0xd9
    [<ffffffff811543d9>] vfs_setxattr+0x83/0xa1
    [<ffffffff811544c6>] setxattr+0xcf/0x101
    [<ffffffff81154745>] sys_lsetxattr+0x6a/0x8f
    [<ffffffff814efda9>] system_call_fastpath+0x16/0x1b
    [<ffffffffffffffff>] 0xffffffffffffffff
unreferenced object 0xffff88024163c5a0 (size 96):
  comm "systemd", pid 1, jiffies 4294683888 (age 94.553s)
  hex dump (first 32 bytes):
    00 00 00 00 ed 41 00 00 00 00 00 00 00 00 00 00  .....A..........
    00 00 00 00 00 00 00 00 0c 64 42 4f 00 00 00 00  .........dBO....
  backtrace:
    [<ffffffff814cb1d0>] kmemleak_alloc+0x73/0x98
    [<ffffffff81127402>] kmem_cache_alloc_trace+0xc4/0xee
    [<ffffffff81191cbe>] sysfs_init_inode_attrs+0x2a/0x83
    [<ffffffff81191dd6>] sysfs_setxattr+0xbf/0x117
    [<ffffffff811542f0>] __vfs_setxattr_noperm+0x73/0xd9
    [<ffffffff811543d9>] vfs_setxattr+0x83/0xa1
    [<ffffffff811544c6>] setxattr+0xcf/0x101
    [<ffffffff81154745>] sys_lsetxattr+0x6a/0x8f
    [<ffffffff814efda9>] system_call_fastpath+0x16/0x1b
    [<ffffffffffffffff>] 0xffffffffffffffff

`

---
 fs/sysfs/inode.c |   11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)
fs/sysfs/inode.c +6 -5
@@ -136,12 +136,13 @@ static int sysfs_sd_setsecdata(struct sy
 	void *old_secdata;
 	size_t old_secdata_len;
 
-	iattrs = sd->s_iattr;
-	if (!iattrs)
-		iattrs = sysfs_init_inode_attrs(sd);
-	if (!iattrs)
-		return -ENOMEM;
+	if (!sd->s_iattr) {
+		sd->s_iattr = sysfs_init_inode_attrs(sd);
+		if (!sd->s_iattr)
+			return -ENOMEM;
+	}
 
+	iattrs = sd->s_iattr;
 	old_secdata = iattrs->ia_secdata;
 	old_secdata_len = iattrs->ia_secdata_len;
 
author maintainer
#29 lore raw

PATCH 29/175 tty: serial: OMAP: Fix oops due to NULL pdata in DT boot

In reply to Greg KH

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

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

From: "Cousson, Benoit" <[email protected]>

commit a5f43138da9beddc46b00ec31d167143a7176683 upstream.

The following commit: be4b0281956c5cae4f63f31f11d07625a6988766 (tty: serial: OMAP: block idle while the UART is transferring data in PIO mode), is introducing an oops if OMAP is booted using device tree blob because the pdata will not be initialized.

Check if pdata is set before de-referencing it.

---
 drivers/tty/serial/omap-serial.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/tty/serial/omap-serial.c +3 -3
@@ -159,7 +159,7 @@ static void serial_omap_stop_tx(struct u
 		serial_out(up, UART_IER, up->ier);
 	}
 
-	if (!up->use_dma && pdata->set_forceidle)
+	if (!up->use_dma && pdata && pdata->set_forceidle)
 		pdata->set_forceidle(up->pdev);
 
 	pm_runtime_mark_last_busy(&up->pdev->dev);
@@ -298,7 +298,7 @@ static void serial_omap_start_tx(struct
 	if (!up->use_dma) {
 		pm_runtime_get_sync(&up->pdev->dev);
 		serial_omap_enable_ier_thri(up);
-		if (pdata->set_noidle)
+		if (pdata && pdata->set_noidle)
 			pdata->set_noidle(up->pdev);
 		pm_runtime_mark_last_busy(&up->pdev->dev);
 		pm_runtime_put_autosuspend(&up->pdev->dev);
@@ -1613,7 +1613,7 @@ static int serial_omap_runtime_resume(st
 	struct uart_omap_port *up = dev_get_drvdata(dev);
 	struct omap_uart_port_info *pdata = dev->platform_data;
 
-	if (up) {
+	if (up && pdata) {
 		if (pdata->get_context_loss_count) {
 			u32 loss_cnt = pdata->get_context_loss_count(dev);
 
author maintainer
#30 lore raw

PATCH 30/175 tty: moxa: fix bit test in moxa_start()

In reply to Greg KH

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

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

From: Dan Carpenter <[email protected]>

commit 58112dfbfe02d803566a2c6c8bd97b5fa3c62cdc upstream.

This is supposed to be doing a shift before the comparison instead of just doing a bitwise AND directly. The current code means the start() just returns without doing anything.

---
 drivers/tty/moxa.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/tty/moxa.c +1 -1
@@ -1331,7 +1331,7 @@ static void moxa_start(struct tty_struct
 	if (ch == NULL)
 		return;
 
-	if (!(ch->statusflags & TXSTOPPED))
+	if (!test_bit(TXSTOPPED, &ch->statusflags))
 		return;
 
 	MoxaPortTxEnable(ch);
author maintainer
#31 lore raw

PATCH 31/175 TTY: Wrong unicode value copied in con_set_unimap()

In reply to Greg KH

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

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

From: Liz Clark <[email protected]>

commit 4a4c61b7ce26bfc9d49ea4bd121d52114bad9f99 upstream.

Bugzilla 40012: PIO_UNIMAP bug: error updating Unicode-to-font map
https://bugzilla.kernel.org/show_bug.cgi?id=40012

The unicode font map for the virtual console is a 32x32x64 table which allocates rows dynamically as entries are added. The unicode value increases sequentially and should count all entries even in empty rows. The defect is when copying the unicode font map in con_set_unimap(), the unicode value is not incremented properly. The wrong unicode value is entered in the new font map.

---
 drivers/tty/vt/consolemap.c |   51 +++++++++++++++++++++++++++++++++++++-------
 1 file changed, 43 insertions(+), 8 deletions(-)
drivers/tty/vt/consolemap.c +43 -8
@@ -516,6 +516,7 @@ int con_set_unimap(struct vc_data *vc, u
 	int err = 0, err1, i;
 	struct uni_pagedir *p, *q;
 
+	/* Save original vc_unipagdir_loc in case we allocate a new one */
 	p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
 	if (p->readonly) return -EIO;
 	
@@ -528,26 +529,57 @@ int con_set_unimap(struct vc_data *vc, u
 		err1 = con_clear_unimap(vc, NULL);
 		if (err1) return err1;
 		
+		/*
+		 * Since refcount was > 1, con_clear_unimap() allocated a
+		 * a new uni_pagedir for this vc.  Re: p != q
+		 */
 		q = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
-		for (i = 0, l = 0; i < 32; i++)
+
+		/*
+		 * uni_pgdir is a 32*32*64 table with rows allocated
+		 * when its first entry is added.  The unicode value must
+		 * still be incremented for empty rows.  We are copying
+		 * entries from "p" (old) to "q" (new).
+		 */
+		l = 0;		/* unicode value */
+		for (i = 0; i < 32; i++)
 		if ((p1 = p->uni_pgdir[i]))
 			for (j = 0; j < 32; j++)
-			if ((p2 = p1[j]))
+			if ((p2 = p1[j])) {
 				for (k = 0; k < 64; k++, l++)
 				if (p2[k] != 0xffff) {
+					/*
+					 * Found one, copy entry for unicode
+					 * l with fontpos value p2[k].
+					 */
 					err1 = con_insert_unipair(q, l, p2[k]);
 					if (err1) {
 						p->refcount++;
 						*vc->vc_uni_pagedir_loc = (unsigned long)p;
 						con_release_unimap(q);
 						kfree(q);
-						return err1; 
+						return err1;
 					}
-              			}
-              	p = q;
-	} else if (p == dflt)
+				}
+			} else {
+				/* Account for row of 64 empty entries */
+				l += 64;
+			}
+		else
+			/* Account for empty table */
+			l += 32 * 64;
+
+		/*
+		 * Finished copying font table, set vc_uni_pagedir to new table
+		 */
+		p = q;
+	} else if (p == dflt) {
 		dflt = NULL;
-	
+	}
+
+	/*
+	 * Insert user specified unicode pairs into new table.
+	 */
 	while (ct--) {
 		unsigned short unicode, fontpos;
 		__get_user(unicode, &list->unicode);
@@ -557,11 +589,14 @@ int con_set_unimap(struct vc_data *vc, u
 		list++;
 	}
 	
+	/*
+	 * Merge with fontmaps of any other virtual consoles.
+	 */
 	if (con_unify_unimap(vc, p))
 		return err;
 
 	for (i = 0; i <= 3; i++)
-		set_inverse_transl(vc, p, i); /* Update all inverse translations */
+		set_inverse_transl(vc, p, i); /* Update inverse translations */
 	set_inverse_trans_unicode(vc, p);
   
 	return err;
author maintainer
#32 lore raw

PATCH 32/175 USB: serial: fix console error reporting

In reply to Greg KH

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

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

From: Johan Hovold <[email protected]>

commit 548dd4b6da8a8e428453d55f7fa7b8a46498d147 upstream.

Do not report errors in write path if port is used as a console as this may trigger the same error (and error report) resulting in a loop.

---
 drivers/usb/serial/generic.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/usb/serial/generic.c +3 -1
@@ -217,8 +217,10 @@ retry:
 	clear_bit(i, &port->write_urbs_free);
 	result = usb_submit_urb(urb, GFP_ATOMIC);
 	if (result) {
-		dev_err(&port->dev, "%s - error submitting urb: %d\n",
+		if (!port->port.console) {
+			dev_err(&port->dev, "%s - error submitting urb: %d\n",
 						__func__, result);
+		}
 		set_bit(i, &port->write_urbs_free);
 		spin_lock_irqsave(&port->lock, flags);
 		port->tx_bytes -= count;
author maintainer
#33 lore raw

PATCH 33/175 cdc-wdm: Fix more races on the read path

In reply to Greg KH

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

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

From: Ben Hutchings <[email protected]>

commit 711c68b3c0f7a924ffbee4aa962d8f62b85188ff upstream.

We must not allow the input buffer length to change while we're shuffling the buffer contents. We also mustn't clear the WDM_READ flag after more data might have arrived. Therefore move both of these into the spinlocked region at the bottom of wdm_read().

When reading desc->length without holding the iuspin lock, use ACCESS_ONCE() to ensure the compiler doesn't re-read it with inconsistent results.

---
 drivers/usb/class/cdc-wdm.c |   16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)
drivers/usb/class/cdc-wdm.c +11 -5
@@ -397,7 +397,7 @@ outnl:
 static ssize_t wdm_read
 (struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
-	int rv, cntr = 0;
+	int rv, cntr;
 	int i = 0;
 	struct wdm_device *desc = file->private_data;
 
@@ -406,7 +406,8 @@ static ssize_t wdm_read
 	if (rv < 0)
 		return -ERESTARTSYS;
 
-	if (desc->length == 0) {
+	cntr = ACCESS_ONCE(desc->length);
+	if (cntr == 0) {
 		desc->read = 0;
 retry:
 		if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
@@ -457,25 +458,30 @@ retry:
 			goto retry;
 		}
 		clear_bit(WDM_READ, &desc->flags);
+		cntr = desc->length;
 		spin_unlock_irq(&desc->iuspin);
 	}
 
-	cntr = count > desc->length ? desc->length : count;
+	if (cntr > count)
+		cntr = count;
 	rv = copy_to_user(buffer, desc->ubuf, cntr);
 	if (rv > 0) {
 		rv = -EFAULT;
 		goto err;
 	}
 
+	spin_lock_irq(&desc->iuspin);
+
 	for (i = 0; i < desc->length - cntr; i++)
 		desc->ubuf[i] = desc->ubuf[i + cntr];
 
-	spin_lock_irq(&desc->iuspin);
 	desc->length -= cntr;
-	spin_unlock_irq(&desc->iuspin);
 	/* in case we had outstanding data */
 	if (!desc->length)
 		clear_bit(WDM_READ, &desc->flags);
+
+	spin_unlock_irq(&desc->iuspin);
+
 	rv = cntr;
 
 err:
author maintainer
#34 lore raw

PATCH 34/175 cdc-wdm: Dont clear WDM_READ unless entire read buffer is emptied

In reply to Greg KH

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

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

From: Ben Hutchings <[email protected]>

commit b7a205545345578712611106b371538992e142ff upstream.

The WDM_READ flag is cleared later iff desc->length is reduced to 0.

---
 drivers/usb/class/cdc-wdm.c |    1 -
 1 file changed, 1 deletion(-)
drivers/usb/class/cdc-wdm.c +0 -1
@@ -457,7 +457,6 @@ retry:
 			spin_unlock_irq(&desc->iuspin);
 			goto retry;
 		}
-		clear_bit(WDM_READ, &desc->flags);
 		cntr = desc->length;
 		spin_unlock_irq(&desc->iuspin);
 	}
author maintainer
#35 lore raw

PATCH 35/175 usb: fsl_udc_core: Fix scheduling while atomic dump message

In reply to Greg KH

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

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

From: Peter Chen <[email protected]>

commit c5cc5ed86667d4ae74fe40ee4ed893f4b46aba05 upstream.

When loading g_ether gadget, there is below message:

Backtrace:
[<80012248>] (dump_backtrace+0x0/0x10c) from [<803cb42c>] (dump_stack+0x18/0x1c)
r7:00000000 r6:80512000 r5:8052bef8 r4:80513f30
[<803cb414>] (dump_stack+0x0/0x1c) from [<8000feb4>] (show_regs+0x44/0x50)
[<8000fe70>] (show_regs+0x0/0x50) from [<8004c840>] (__schedule_bug+0x68/0x84)
r5:8052bef8 r4:80513f30
[<8004c7d8>] (__schedule_bug+0x0/0x84) from [<803cd0e4>] (__schedule+0x4b0/0x528)
r5:8052bef8 r4:809aad00
[<803ccc34>] (__schedule+0x0/0x528) from [<803cd214>] (_cond_resched+0x44/0x58)
[<803cd1d0>] (_cond_resched+0x0/0x58) from [<800a9488>] (dma_pool_alloc+0x184/0x250)
 r5:9f9b4000 r4:9fb4fb80
 [<800a9304>] (dma_pool_alloc+0x0/0x250) from [<802a8ad8>] (fsl_req_to_dtd+0xac/0x180)
[<802a8a2c>] (fsl_req_to_dtd+0x0/0x180) from [<802a8ce4>] (fsl_ep_queue+0x138/0x274)
[<802a8bac>] (fsl_ep_queue+0x0/0x274) from [<7f004328>] (composite_setup+0x2d4/0xfac [g_ether])
[<7f004054>] (composite_setup+0x0/0xfac [g_ether]) from [<802a9bb4>] (fsl_udc_irq+0x8dc/0xd38)
[<802a92d8>] (fsl_udc_irq+0x0/0xd38) from [<800704f8>] (handle_irq_event_percpu+0x54/0x188)
[<800704a4>] (handle_irq_event_percpu+0x0/0x188) from [<80070674>] (handle_irq_event+0x48/0x68)
[<8007062c>] (handle_irq_event+0x0/0x68) from [<800738ec>] (handle_level_irq+0xb4/0x138)
 r5:80514f94 r4:80514f40
 [<80073838>] (handle_level_irq+0x0/0x138) from [<8006ffa4>] (generic_handle_irq+0x38/0x44)
 r7:00000012 r6:80510b1c r5:80529860 r4:80512000
 [<8006ff6c>] (generic_handle_irq+0x0/0x44) from [<8000f4c4>] (handle_IRQ+0x54/0xb4)
[<8000f470>] (handle_IRQ+0x0/0xb4) from [<800085b8>] (tzic_handle_irq+0x64/0x94)
 r9:412fc085 r8:00000000 r7:80513f30 r6:00000001 r5:00000000
 r4:00000000
 [<80008554>] (tzic_handle_irq+0x0/0x94) from [<8000e680>] (__irq_svc+0x40/0x60)

The reason of above dump message is calling dma_poll_alloc with can-schedule mem_flags at atomic context.

To fix this problem, below changes are made:
- fsl_req_to_dtd doesn't need to be protected by spin_lock_irqsave, as struct usb_request can be access at process context. Move lock to beginning of hardware visit (fsl_queue_td).
- Change the memory flag which using to allocate dTD descriptor buffer, the memory flag can be from gadget layer.

It is tested at i.mx51 bbg board with g_mass_storage, g_ether, g_serial.

---
 drivers/usb/gadget/fsl_udc_core.c |   18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)
drivers/usb/gadget/fsl_udc_core.c +8 -10
@@ -769,7 +769,7 @@ static void fsl_queue_td(struct fsl_ep *
  * @is_last: return flag if it is the last dTD of the request
  * return: pointer to the built dTD */
 static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,
-		dma_addr_t *dma, int *is_last)
+		dma_addr_t *dma, int *is_last, gfp_t gfp_flags)
 {
 	u32 swap_temp;
 	struct ep_td_struct *dtd;
@@ -778,7 +778,7 @@ static struct ep_td_struct *fsl_build_dt
 	*length = min(req->req.length - req->req.actual,
 			(unsigned)EP_MAX_LENGTH_TRANSFER);
 
-	dtd = dma_pool_alloc(udc_controller->td_pool, GFP_KERNEL, dma);
+	dtd = dma_pool_alloc(udc_controller->td_pool, gfp_flags, dma);
 	if (dtd == NULL)
 		return dtd;
 
@@ -828,7 +828,7 @@ static struct ep_td_struct *fsl_build_dt
 }
 
 /* Generate dtd chain for a request */
-static int fsl_req_to_dtd(struct fsl_req *req)
+static int fsl_req_to_dtd(struct fsl_req *req, gfp_t gfp_flags)
 {
 	unsigned	count;
 	int		is_last;
@@ -837,7 +837,7 @@ static int fsl_req_to_dtd(struct fsl_req
 	dma_addr_t dma;
 
 	do {
-		dtd = fsl_build_dtd(req, &count, &dma, &is_last);
+		dtd = fsl_build_dtd(req, &count, &dma, &is_last, gfp_flags);
 		if (dtd == NULL)
 			return -ENOMEM;
 
@@ -911,13 +911,11 @@ fsl_ep_queue(struct usb_ep *_ep, struct
 	req->req.actual = 0;
 	req->dtd_count = 0;
 
-	spin_lock_irqsave(&udc->lock, flags);
-
 	/* build dtds and push them to device queue */
-	if (!fsl_req_to_dtd(req)) {
+	if (!fsl_req_to_dtd(req, gfp_flags)) {
+		spin_lock_irqsave(&udc->lock, flags);
 		fsl_queue_td(ep, req);
 	} else {
-		spin_unlock_irqrestore(&udc->lock, flags);
 		return -ENOMEM;
 	}
 
@@ -1296,7 +1294,7 @@ static int ep0_prime_status(struct fsl_u
 			ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 	req->mapped = 1;
 
-	if (fsl_req_to_dtd(req) == 0)
+	if (fsl_req_to_dtd(req, GFP_ATOMIC) == 0)
 		fsl_queue_td(ep, req);
 	else
 		return -ENOMEM;
@@ -1380,7 +1378,7 @@ static void ch9getstatus(struct fsl_udc
 	req->mapped = 1;
 
 	/* prime the data phase */
-	if ((fsl_req_to_dtd(req) == 0))
+	if ((fsl_req_to_dtd(req, GFP_ATOMIC) == 0))
 		fsl_queue_td(ep, req);
 	else			/* no mem */
 		goto stall;
author maintainer
#36 lore raw

PATCH 36/175 usb: Fix build error due to dma_mask is not at pdev_archdata at ARM

In reply to Greg KH

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

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

From: Peter Chen <[email protected]>

commit e90fc3cb087ce5c5f81e814358222cd6d197b5db upstream.

When build i.mx platform with imx_v6_v7_defconfig, and after adding USB Gadget support, it has below build error:

CC drivers/usb/host/fsl-mph-dr-of.o
drivers/usb/host/fsl-mph-dr-of.c: In function 'fsl_usb2_device_register':
drivers/usb/host/fsl-mph-dr-of.c:97: error: 'struct pdev_archdata' has no member named 'dma_mask'

It has discussed at: http://www.spinics.net/lists/linux-usb/msg57302.html

For PowerPC, there is dma_mask at struct pdev_archdata, but there is no dma_mask at struct pdev_archdata for ARM. The pdev_archdata is related to specific platform, it should NOT be accessed by cross platform drivers, like USB.

The code for pdev_archdata should be useless, as for PowerPC, it has already gotten the value for pdev->dev.dma_mask at function arch_setup_pdev_archdata of arch/powerpc/kernel/setup-common.c.

---
 drivers/usb/host/fsl-mph-dr-of.c |    1 -
 1 file changed, 1 deletion(-)
drivers/usb/host/fsl-mph-dr-of.c +0 -1
@@ -94,7 +94,6 @@ struct platform_device * __devinit fsl_u
 	pdev->dev.parent = &ofdev->dev;
 
 	pdev->dev.coherent_dma_mask = ofdev->dev.coherent_dma_mask;
-	pdev->dev.dma_mask = &pdev->archdata.dma_mask;
 	*pdev->dev.dma_mask = *ofdev->dev.dma_mask;
 
 	retval = platform_device_add_data(pdev, pdata, sizeof(*pdata));
author maintainer
#37 lore raw

PATCH 37/175 USB: ums_realtek: do not use stack memory for DMA in __do_config_autodelink

In reply to Greg KH

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

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

From: Josh Boyer <[email protected]>

commit 4898e07174b79013afd2b422ef6c4336ef8e6783 upstream.

__do_config_autodelink passes the data variable to the transport function. If the calling functions pass a stack variable, this will eventually trigger a DMA-API debug backtrace for mapping stack memory in the DMA buffer. Fix this by calling kmemdup for the passed data instead.

---
 drivers/usb/storage/realtek_cr.c |    8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/usb/storage/realtek_cr.c +7 -1
@@ -507,9 +507,14 @@ static int __do_config_autodelink(struct
 {
 	int retval;
 	u8 cmnd[12] = {0};
+	u8 *buf;
 
 	US_DEBUGP("%s, addr = 0xfe47, len = %d\n", __FUNCTION__, len);
 
+	buf = kmemdup(data, len, GFP_NOIO);
+	if (!buf)
+		return USB_STOR_TRANSPORT_ERROR;
+
 	cmnd[0] = 0xF0;
 	cmnd[1] = 0x0E;
 	cmnd[2] = 0xfe;
@@ -517,7 +522,8 @@ static int __do_config_autodelink(struct
 	cmnd[4] = (u8)(len >> 8);
 	cmnd[5] = (u8)len;
 
-	retval = rts51x_bulk_transport_special(us, 0, cmnd, 12, data, len, DMA_TO_DEVICE, NULL);
+	retval = rts51x_bulk_transport_special(us, 0, cmnd, 12, buf, len, DMA_TO_DEVICE, NULL);
+	kfree(buf);
 	if (retval != USB_STOR_TRANSPORT_GOOD) {
 		return -EIO;
 	}
author maintainer
#38 lore raw

PATCH 38/175 USB: qcserial: dont grab QMI port on Gobi 1000 devices

In reply to Greg KH

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

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

From: Dan Williams <[email protected]>

commit c192c8e71a2ded01170c1a992cd21aaedc822756 upstream.

Gobi 1000 devices have a different port layout, which wasn't respected by the current driver, and thus it grabbed the QMI/net port. In the near future we'll be attaching another driver to the QMI/net port for these devices (cdc-wdm and qmi_wwan) so make sure the qcserial driver doesn't claim them. This patch also prevents qcserial from binding to interfaces 0 and 1 on 1K devices because those interfaces do not respond.

---
 drivers/usb/serial/qcserial.c |  105 ++++++++++++++++++++++++------------------
 1 file changed, 62 insertions(+), 43 deletions(-)
drivers/usb/serial/qcserial.c +62 -43
@@ -24,39 +24,44 @@
 
 static bool debug;
 
+#define DEVICE_G1K(v, p) \
+	USB_DEVICE(v, p), .driver_info = 1
+
 static const struct usb_device_id id_table[] = {
-	{USB_DEVICE(0x05c6, 0x9211)},	/* Acer Gobi QDL device */
-	{USB_DEVICE(0x05c6, 0x9212)},	/* Acer Gobi Modem Device */
-	{USB_DEVICE(0x03f0, 0x1f1d)},	/* HP un2400 Gobi Modem Device */
-	{USB_DEVICE(0x03f0, 0x201d)},	/* HP un2400 Gobi QDL Device */
-	{USB_DEVICE(0x03f0, 0x371d)},	/* HP un2430 Mobile Broadband Module */
-	{USB_DEVICE(0x04da, 0x250d)},	/* Panasonic Gobi Modem device */
-	{USB_DEVICE(0x04da, 0x250c)},	/* Panasonic Gobi QDL device */
-	{USB_DEVICE(0x413c, 0x8172)},	/* Dell Gobi Modem device */
-	{USB_DEVICE(0x413c, 0x8171)},	/* Dell Gobi QDL device */
-	{USB_DEVICE(0x1410, 0xa001)},	/* Novatel Gobi Modem device */
-	{USB_DEVICE(0x1410, 0xa008)},	/* Novatel Gobi QDL device */
-	{USB_DEVICE(0x1410, 0xa010)},	/* Novatel Gobi QDL device */
-	{USB_DEVICE(0x1410, 0xa011)},	/* Novatel Gobi QDL device */
-	{USB_DEVICE(0x1410, 0xa012)},	/* Novatel Gobi QDL device */
-	{USB_DEVICE(0x1410, 0xa013)},	/* Novatel Gobi QDL device */
-	{USB_DEVICE(0x1410, 0xa014)},	/* Novatel Gobi QDL device */
-	{USB_DEVICE(0x0b05, 0x1776)},	/* Asus Gobi Modem device */
-	{USB_DEVICE(0x0b05, 0x1774)},	/* Asus Gobi QDL device */
-	{USB_DEVICE(0x19d2, 0xfff3)},	/* ONDA Gobi Modem device */
-	{USB_DEVICE(0x19d2, 0xfff2)},	/* ONDA Gobi QDL device */
-	{USB_DEVICE(0x1557, 0x0a80)},	/* OQO Gobi QDL device */
-	{USB_DEVICE(0x05c6, 0x9001)},   /* Generic Gobi Modem device */
-	{USB_DEVICE(0x05c6, 0x9002)},	/* Generic Gobi Modem device */
-	{USB_DEVICE(0x05c6, 0x9202)},	/* Generic Gobi Modem device */
-	{USB_DEVICE(0x05c6, 0x9203)},	/* Generic Gobi Modem device */
-	{USB_DEVICE(0x05c6, 0x9222)},	/* Generic Gobi Modem device */
-	{USB_DEVICE(0x05c6, 0x9008)},	/* Generic Gobi QDL device */
-	{USB_DEVICE(0x05c6, 0x9009)},	/* Generic Gobi Modem device */
-	{USB_DEVICE(0x05c6, 0x9201)},	/* Generic Gobi QDL device */
-	{USB_DEVICE(0x05c6, 0x9221)},	/* Generic Gobi QDL device */
-	{USB_DEVICE(0x05c6, 0x9231)},	/* Generic Gobi QDL device */
-	{USB_DEVICE(0x1f45, 0x0001)},	/* Unknown Gobi QDL device */
+	/* Gobi 1000 devices */
+	{DEVICE_G1K(0x05c6, 0x9211)},	/* Acer Gobi QDL device */
+	{DEVICE_G1K(0x05c6, 0x9212)},	/* Acer Gobi Modem Device */
+	{DEVICE_G1K(0x03f0, 0x1f1d)},	/* HP un2400 Gobi Modem Device */
+	{DEVICE_G1K(0x03f0, 0x201d)},	/* HP un2400 Gobi QDL Device */
+	{DEVICE_G1K(0x04da, 0x250d)},	/* Panasonic Gobi Modem device */
+	{DEVICE_G1K(0x04da, 0x250c)},	/* Panasonic Gobi QDL device */
+	{DEVICE_G1K(0x413c, 0x8172)},	/* Dell Gobi Modem device */
+	{DEVICE_G1K(0x413c, 0x8171)},	/* Dell Gobi QDL device */
+	{DEVICE_G1K(0x1410, 0xa001)},	/* Novatel Gobi Modem device */
+	{DEVICE_G1K(0x1410, 0xa008)},	/* Novatel Gobi QDL device */
+	{DEVICE_G1K(0x0b05, 0x1776)},	/* Asus Gobi Modem device */
+	{DEVICE_G1K(0x0b05, 0x1774)},	/* Asus Gobi QDL device */
+	{DEVICE_G1K(0x19d2, 0xfff3)},	/* ONDA Gobi Modem device */
+	{DEVICE_G1K(0x19d2, 0xfff2)},	/* ONDA Gobi QDL device */
+	{DEVICE_G1K(0x1557, 0x0a80)},	/* OQO Gobi QDL device */
+	{DEVICE_G1K(0x05c6, 0x9001)},   /* Generic Gobi Modem device */
+	{DEVICE_G1K(0x05c6, 0x9002)},	/* Generic Gobi Modem device */
+	{DEVICE_G1K(0x05c6, 0x9202)},	/* Generic Gobi Modem device */
+	{DEVICE_G1K(0x05c6, 0x9203)},	/* Generic Gobi Modem device */
+	{DEVICE_G1K(0x05c6, 0x9222)},	/* Generic Gobi Modem device */
+	{DEVICE_G1K(0x05c6, 0x9008)},	/* Generic Gobi QDL device */
+	{DEVICE_G1K(0x05c6, 0x9009)},	/* Generic Gobi Modem device */
+	{DEVICE_G1K(0x05c6, 0x9201)},	/* Generic Gobi QDL device */
+	{DEVICE_G1K(0x05c6, 0x9221)},	/* Generic Gobi QDL device */
+	{DEVICE_G1K(0x05c6, 0x9231)},	/* Generic Gobi QDL device */
+	{DEVICE_G1K(0x1f45, 0x0001)},	/* Unknown Gobi QDL device */
+
+	/* Gobi 2000 devices */
+	{USB_DEVICE(0x1410, 0xa010)},	/* Novatel Gobi 2000 QDL device */
+	{USB_DEVICE(0x1410, 0xa011)},	/* Novatel Gobi 2000 QDL device */
+	{USB_DEVICE(0x1410, 0xa012)},	/* Novatel Gobi 2000 QDL device */
+	{USB_DEVICE(0x1410, 0xa013)},	/* Novatel Gobi 2000 QDL device */
+	{USB_DEVICE(0x1410, 0xa014)},	/* Novatel Gobi 2000 QDL device */
 	{USB_DEVICE(0x413c, 0x8185)},	/* Dell Gobi 2000 QDL device (N0218, VU936) */
 	{USB_DEVICE(0x413c, 0x8186)},	/* Dell Gobi 2000 Modem device (N0218, VU936) */
 	{USB_DEVICE(0x05c6, 0x9208)},	/* Generic Gobi 2000 QDL device */
@@ -92,6 +97,8 @@ static const struct usb_device_id id_tab
 	{USB_DEVICE(0x05c6, 0x9204)},	/* Gobi 2000 QDL device */
 	{USB_DEVICE(0x05c6, 0x9205)},	/* Gobi 2000 Modem device */
 
+	/* Gobi 3000 devices */
+	{USB_DEVICE(0x03f0, 0x371d)},	/* HP un2430 Gobi 3000 QDL */
 	{USB_DEVICE(0x05c6, 0x920c)},	/* Gobi 3000 QDL */
 	{USB_DEVICE(0x05c6, 0x920d)},	/* Gobi 3000 Composite */
 	{USB_DEVICE(0x1410, 0xa020)},   /* Novatel Gobi 3000 QDL */
@@ -122,8 +129,10 @@ static int qcprobe(struct usb_serial *se
 	int retval = -ENODEV;
 	__u8 nintf;
 	__u8 ifnum;
+	bool is_gobi1k = id->driver_info ? true : false;
 
 	dbg("%s", __func__);
+	dbg("Is Gobi 1000 = %d", is_gobi1k);
 
 	nintf = serial->dev->actconfig->desc.bNumInterfaces;
 	dbg("Num Interfaces = %d", nintf);
@@ -169,15 +178,25 @@ static int qcprobe(struct usb_serial *se
 
 	case 3:
 	case 4:
-		/* Composite mode */
-		/* ifnum == 0 is a broadband network adapter */
-		if (ifnum == 1) {
-			/*
-			 * Diagnostics Monitor (serial line 9600 8N1)
-			 * Qualcomm DM protocol
-			 * use "libqcdm" (ModemManager) for communication
-			 */
-			dbg("Diagnostics Monitor found");
+		/* Composite mode; don't bind to the QMI/net interface as that
+		 * gets handled by other drivers.
+		 */
+
+		/* Gobi 1K USB layout:
+		 * 0: serial port (doesn't respond)
+		 * 1: serial port (doesn't respond)
+		 * 2: AT-capable modem port
+		 * 3: QMI/net
+		 *
+		 * Gobi 2K+ USB layout:
+		 * 0: QMI/net
+		 * 1: DM/DIAG (use libqcdm from ModemManager for communication)
+		 * 2: AT-capable modem port
+		 * 3: NMEA
+		 */
+
+		if (ifnum == 1 && !is_gobi1k) {
+			dbg("Gobi 2K+ DM/DIAG interface found");
 			retval = usb_set_interface(serial->dev, ifnum, 0);
 			if (retval < 0) {
 				dev_err(&serial->dev->dev,
@@ -196,13 +215,13 @@ static int qcprobe(struct usb_serial *se
 				retval = -ENODEV;
 				kfree(data);
 			}
-		} else if (ifnum==3) {
+		} else if (ifnum==3 && !is_gobi1k) {
 			/*
 			 * NMEA (serial line 9600 8N1)
 			 * # echo "\$GPS_START" > /dev/ttyUSBx
 			 * # echo "\$GPS_STOP"  > /dev/ttyUSBx
 			 */
-			dbg("NMEA GPS interface found");
+			dbg("Gobi 2K+ NMEA GPS interface found");
 			retval = usb_set_interface(serial->dev, ifnum, 0);
 			if (retval < 0) {
 				dev_err(&serial->dev->dev,
author maintainer
#39 lore raw

PATCH 39/175 usb-serial: Add support for the Sealevel SeaLINK+8 2038-ROHS device

In reply to Greg KH

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

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

From: Scott Dial <[email protected]>

commit 6d161b99f875269ad4ffa44375e1e54bca6fd02e upstream.

This patch adds new device IDs to the ftdi_sio module to support the new Sealevel SeaLINK+8 2038-ROHS device.

---
 drivers/usb/serial/ftdi_sio.c     |    4 ++++
 drivers/usb/serial/ftdi_sio_ids.h |    4 ++++
 2 files changed, 8 insertions(+)
drivers/usb/serial/ftdi_sio.c +4 -0
@@ -537,6 +537,10 @@ static struct usb_device_id id_table_com
 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_6_PID) },
 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_7_PID) },
 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_1_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_2_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_3_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_4_PID) },
 	{ USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) },
 	{ USB_DEVICE(OCT_VID, OCT_US101_PID) },
 	{ USB_DEVICE(OCT_VID, OCT_DK201_PID) },
drivers/usb/serial/ftdi_sio_ids.h +4 -0
@@ -689,6 +689,10 @@
 #define SEALEVEL_2803_6_PID	0X2863	/* SeaLINK+8 (2803) Port 6 */
 #define SEALEVEL_2803_7_PID	0X2873	/* SeaLINK+8 (2803) Port 7 */
 #define SEALEVEL_2803_8_PID	0X2883	/* SeaLINK+8 (2803) Port 8 */
+#define SEALEVEL_2803R_1_PID	0Xa02a	/* SeaLINK+8 (2803-ROHS) Port 1+2 */
+#define SEALEVEL_2803R_2_PID	0Xa02b	/* SeaLINK+8 (2803-ROHS) Port 3+4 */
+#define SEALEVEL_2803R_3_PID	0Xa02c	/* SeaLINK+8 (2803-ROHS) Port 5+6 */
+#define SEALEVEL_2803R_4_PID	0Xa02d	/* SeaLINK+8 (2803-ROHS) Port 7+8 */
 
 /*
  * JETI SPECTROMETER SPECBOS 1201
author maintainer
#40 lore raw

PATCH 40/175 usb: cp210x: Update to support CP2105 and multiple interface devices

In reply to Greg KH

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

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

From: Preston Fick <[email protected]>

commit a5360a53a7ccad5ed9ccef210b94fef13c6e5529 upstream.

This patch updates the cp210x driver to support CP210x multiple interface devices devices from Silicon Labs. The existing driver always sends control requests to interface 0, which is hardcoded in the usb_control_msg function calls. This only allows for single interface devices to be used, and causes a bug when using ports on an interface other than 0 in the multiple interface devices.

Here are the changes included in this patch:
- Updated the device list to contain the Silicon Labs factory default VID/PID for multiple interface CP210x devices
- Created a cp210x_port_private struct created for each port on startup, this struct holds the interface number
- Added a cp210x_release function to clean up the cp210x_port_private memory created on startup
- Modified usb_get_config and usb_set_config to get a pointer to the cp210x_port_private struct, and use the interface number there in the usb_control_message wIndex param

---
 drivers/usb/serial/cp210x.c |   44 +++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 41 insertions(+), 3 deletions(-)
drivers/usb/serial/cp210x.c +41 -3
@@ -49,6 +49,7 @@ static int cp210x_tiocmset_port(struct u
 		unsigned int, unsigned int);
 static void cp210x_break_ctl(struct tty_struct *, int);
 static int cp210x_startup(struct usb_serial *);
+static void cp210x_release(struct usb_serial *);
 static void cp210x_dtr_rts(struct usb_serial_port *p, int on);
 
 static bool debug;
@@ -121,6 +122,8 @@ static const struct usb_device_id id_tab
 	{ USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */
 	{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
 	{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
+	{ USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */
+	{ USB_DEVICE(0x10C4, 0xEA80) }, /* Silicon Labs factory default */
 	{ USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */
 	{ USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */
 	{ USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */
@@ -149,6 +152,10 @@ static const struct usb_device_id id_tab
 
 MODULE_DEVICE_TABLE(usb, id_table);
 
+struct cp210x_port_private {
+	__u8			bInterfaceNumber;
+};
+
 static struct usb_driver cp210x_driver = {
 	.name		= "cp210x",
 	.probe		= usb_serial_probe,
@@ -174,6 +181,7 @@ static struct usb_serial_driver cp210x_d
 	.tiocmget 		= cp210x_tiocmget,
 	.tiocmset		= cp210x_tiocmset,
 	.attach			= cp210x_startup,
+	.release		= cp210x_release,
 	.dtr_rts		= cp210x_dtr_rts
 };
 
@@ -261,6 +269,7 @@ static int cp210x_get_config(struct usb_
 		unsigned int *data, int size)
 {
 	struct usb_serial *serial = port->serial;
+	struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
 	__le32 *buf;
 	int result, i, length;
 
@@ -276,7 +285,7 @@ static int cp210x_get_config(struct usb_
 	/* Issue the request, attempting to read 'size' bytes */
 	result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
 				request, REQTYPE_DEVICE_TO_HOST, 0x0000,
-				0, buf, size, 300);
+				port_priv->bInterfaceNumber, buf, size, 300);
 
 	/* Convert data into an array of integers */
 	for (i = 0; i < length; i++)
@@ -307,6 +316,7 @@ static int cp210x_set_config(struct usb_
 		unsigned int *data, int size)
 {
 	struct usb_serial *serial = port->serial;
+	struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
 	__le32 *buf;
 	int result, i, length;
 
@@ -328,12 +338,12 @@ static int cp210x_set_config(struct usb_
 		result = usb_control_msg(serial->dev,
 				usb_sndctrlpipe(serial->dev, 0),
 				request, REQTYPE_HOST_TO_DEVICE, 0x0000,
-				0, buf, size, 300);
+				port_priv->bInterfaceNumber, buf, size, 300);
 	} else {
 		result = usb_control_msg(serial->dev,
 				usb_sndctrlpipe(serial->dev, 0),
 				request, REQTYPE_HOST_TO_DEVICE, data[0],
-				0, NULL, 0, 300);
+				port_priv->bInterfaceNumber, NULL, 0, 300);
 	}
 
 	kfree(buf);
@@ -844,11 +854,39 @@ static void cp210x_break_ctl (struct tty
 
 static int cp210x_startup(struct usb_serial *serial)
 {
+	struct cp210x_port_private *port_priv;
+	int i;
+
 	/* cp210x buffers behave strangely unless device is reset */
 	usb_reset_device(serial->dev);
+
+	for (i = 0; i < serial->num_ports; i++) {
+		port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
+		if (!port_priv)
+			return -ENOMEM;
+
+		memset(port_priv, 0x00, sizeof(*port_priv));
+		port_priv->bInterfaceNumber =
+		    serial->interface->cur_altsetting->desc.bInterfaceNumber;
+
+		usb_set_serial_port_data(serial->port[i], port_priv);
+	}
+
 	return 0;
 }
 
+static void cp210x_release(struct usb_serial *serial)
+{
+	struct cp210x_port_private *port_priv;
+	int i;
+
+	for (i = 0; i < serial->num_ports; i++) {
+		port_priv = usb_get_serial_port_data(serial->port[i]);
+		kfree(port_priv);
+		usb_set_serial_port_data(serial->port[i], NULL);
+	}
+}
+
 static int __init cp210x_init(void)
 {
 	int retval;
author maintainer
#41 lore raw

PATCH 41/175 USB: serial: mos7840: Fixed MCS7820 device attach problem

In reply to Greg KH

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

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

From: Donald Lee <[email protected]>

commit 093ea2d3a766cb8a4c4de57efec6c0a127a58792 upstream.

A MCS7820 device supports two serial ports and a MCS7840 device supports four serial ports. Both devices use the same driver, but the attach function in driver was unable to correctly handle the port numbers for MCS7820 device. This problem has been fixed in this patch and this fix has been verified on x86 Linux kernel 3.2.9 with both MCS7820 and MCS7840 devices.

---
 drivers/usb/serial/mos7840.c |   81 +++++++++++++++++++++++++++++--------------
 1 file changed, 56 insertions(+), 25 deletions(-)
drivers/usb/serial/mos7840.c +56 -25
@@ -174,6 +174,7 @@
 
 #define CLK_MULTI_REGISTER         ((__u16)(0x02))
 #define CLK_START_VALUE_REGISTER   ((__u16)(0x03))
+#define GPIO_REGISTER              ((__u16)(0x07))
 
 #define SERIAL_LCR_DLAB            ((__u16)(0x0080))
 
@@ -1101,14 +1102,25 @@ static int mos7840_open(struct tty_struc
 	mos7840_port->read_urb = port->read_urb;
 
 	/* set up our bulk in urb */
-
-	usb_fill_bulk_urb(mos7840_port->read_urb,
-			  serial->dev,
-			  usb_rcvbulkpipe(serial->dev,
-					  port->bulk_in_endpointAddress),
-			  port->bulk_in_buffer,
-			  mos7840_port->read_urb->transfer_buffer_length,
-			  mos7840_bulk_in_callback, mos7840_port);
+	if ((serial->num_ports == 2)
+		&& ((((__u16)port->number -
+			(__u16)(port->serial->minor)) % 2) != 0)) {
+		usb_fill_bulk_urb(mos7840_port->read_urb,
+			serial->dev,
+			usb_rcvbulkpipe(serial->dev,
+				(port->bulk_in_endpointAddress) + 2),
+			port->bulk_in_buffer,
+			mos7840_port->read_urb->transfer_buffer_length,
+			mos7840_bulk_in_callback, mos7840_port);
+	} else {
+		usb_fill_bulk_urb(mos7840_port->read_urb,
+			serial->dev,
+			usb_rcvbulkpipe(serial->dev,
+				port->bulk_in_endpointAddress),
+			port->bulk_in_buffer,
+			mos7840_port->read_urb->transfer_buffer_length,
+			mos7840_bulk_in_callback, mos7840_port);
+	}
 
 	dbg("mos7840_open: bulkin endpoint is %d",
 	    port->bulk_in_endpointAddress);
@@ -1519,13 +1531,25 @@ static int mos7840_write(struct tty_stru
 	memcpy(urb->transfer_buffer, current_position, transfer_size);
 
 	/* fill urb with data and submit  */
-	usb_fill_bulk_urb(urb,
-			  serial->dev,
-			  usb_sndbulkpipe(serial->dev,
-					  port->bulk_out_endpointAddress),
-			  urb->transfer_buffer,
-			  transfer_size,
-			  mos7840_bulk_out_data_callback, mos7840_port);
+	if ((serial->num_ports == 2)
+		&& ((((__u16)port->number -
+			(__u16)(port->serial->minor)) % 2) != 0)) {
+		usb_fill_bulk_urb(urb,
+			serial->dev,
+			usb_sndbulkpipe(serial->dev,
+				(port->bulk_out_endpointAddress) + 2),
+			urb->transfer_buffer,
+			transfer_size,
+			mos7840_bulk_out_data_callback, mos7840_port);
+	} else {
+		usb_fill_bulk_urb(urb,
+			serial->dev,
+			usb_sndbulkpipe(serial->dev,
+				port->bulk_out_endpointAddress),
+			urb->transfer_buffer,
+			transfer_size,
+			mos7840_bulk_out_data_callback, mos7840_port);
+	}
 
 	data1 = urb->transfer_buffer;
 	dbg("bulkout endpoint is %d", port->bulk_out_endpointAddress);
@@ -1838,7 +1862,7 @@ static int mos7840_send_cmd_write_baud_r
 
 	} else {
 #ifdef HW_flow_control
-		/ *setting h/w flow control bit to 0 */
+		/* setting h/w flow control bit to 0 */
 		Data = 0xb;
 		mos7840_port->shadowMCR = Data;
 		status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
@@ -2305,19 +2329,26 @@ static int mos7840_ioctl(struct tty_stru
 
 static int mos7840_calc_num_ports(struct usb_serial *serial)
 {
-	int mos7840_num_ports = 0;
+	__u16 Data = 0x00;
+	int ret = 0;
+	int mos7840_num_ports;
 
-	dbg("numberofendpoints: cur %d, alt %d",
-	    (int)serial->interface->cur_altsetting->desc.bNumEndpoints,
-	    (int)serial->interface->altsetting->desc.bNumEndpoints);
-	if (serial->interface->cur_altsetting->desc.bNumEndpoints == 5) {
-		mos7840_num_ports = serial->num_ports = 2;
-	} else if (serial->interface->cur_altsetting->desc.bNumEndpoints == 9) {
+	ret = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+		MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, &Data,
+		VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
+
+	if ((Data & 0x01) == 0) {
+		mos7840_num_ports = 2;
+		serial->num_bulk_in = 2;
+		serial->num_bulk_out = 2;
+		serial->num_ports = 2;
+	} else {
+		mos7840_num_ports = 4;
 		serial->num_bulk_in = 4;
 		serial->num_bulk_out = 4;
-		mos7840_num_ports = serial->num_ports = 4;
+		serial->num_ports = 4;
 	}
-	dbg ("mos7840_num_ports = %d", mos7840_num_ports);
+
 	return mos7840_num_ports;
 }
 
author maintainer
#42 lore raw

PATCH 42/175 rt2x00: Add support for D-Link DWA-127 to rt2800usb.

In reply to Greg KH

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

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

From: Gertjan van Wingerde <[email protected]>

commit d42a179b941a9e4cc6cf41d0f3cbadd75fc48a89 upstream.

This is an RT3070 based device.

---
 drivers/net/wireless/rt2x00/rt2800usb.c |    1 +
 1 file changed, 1 insertion(+)
drivers/net/wireless/rt2x00/rt2800usb.c +1 -0
@@ -922,6 +922,7 @@ static struct usb_device_id rt2800usb_de
 	{ USB_DEVICE(0x07d1, 0x3c13) },
 	{ USB_DEVICE(0x07d1, 0x3c15) },
 	{ USB_DEVICE(0x07d1, 0x3c16) },
+	{ USB_DEVICE(0x2001, 0x3c1b) },
 	/* Draytek */
 	{ USB_DEVICE(0x07fa, 0x7712) },
 	/* DVICO */
author maintainer
#43 lore raw

PATCH 43/175 rtlwifi: rtl8192c_common: rtl8192de: Check for allocation failures

In reply to Greg KH

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

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

From: Larry Finger <[email protected]>

commit 76a92be537f1c8c259e393632301446257ca3ea9 upstream.

In https://bugzilla.redhat.com/show_bug.cgi?id=771656, a kernel bug was triggered due to a failed skb allocation that was not checked. This event lead to an audit of all memory allocations in the complete rtlwifi family of drivers. This patch fixes the rest.

---
 drivers/net/wireless/rtlwifi/pci.c                |    2 ++
 drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c |    2 ++
 drivers/net/wireless/rtlwifi/rtl8192de/fw.c       |   14 +++++++++-----
 drivers/net/wireless/rtlwifi/usb.c                |   12 +++++++-----
 4 files changed, 20 insertions(+), 10 deletions(-)
drivers/net/wireless/rtlwifi/pci.c +2 -0
@@ -657,6 +657,8 @@ static void _rtl_receive_one(struct ieee
 		return;
 
 	uskb = dev_alloc_skb(skb->len + 128);
+	if (!uskb)
+		return;		/* exit if allocation failed */
 	memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status, sizeof(rx_status));
 	pdata = (u8 *)skb_put(uskb, skb->len);
 	memcpy(pdata, skb->data, skb->len);
drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +2 -0
@@ -788,6 +788,8 @@ void rtl92c_set_fw_rsvdpagepkt(struct ie
 
 
 	skb = dev_alloc_skb(totalpacketlen);
+	if (!skb)
+		return;
 	memcpy((u8 *) skb_put(skb, totalpacketlen),
 	       &reserved_page_packet, totalpacketlen);
 
drivers/net/wireless/rtlwifi/rtl8192de/fw.c +9 -5
@@ -763,12 +763,16 @@ void rtl92d_set_fw_rsvdpagepkt(struct ie
 		      "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
 		      u1RsvdPageLoc, 3);
 	skb = dev_alloc_skb(totalpacketlen);
-	memcpy((u8 *) skb_put(skb, totalpacketlen), &reserved_page_packet,
-		totalpacketlen);
-	rtstatus = _rtl92d_cmd_send_packet(hw, skb);
+	if (!skb) {
+		dlok = false;
+	} else {
+		memcpy((u8 *) skb_put(skb, totalpacketlen),
+			&reserved_page_packet, totalpacketlen);
+		rtstatus = _rtl92d_cmd_send_packet(hw, skb);
 
-	if (rtstatus)
-		dlok = true;
+		if (rtstatus)
+			dlok = true;
+	}
 	if (dlok) {
 		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
 			("Set RSVD page location to Fw.\n"));
drivers/net/wireless/rtlwifi/usb.c +7 -5
@@ -520,12 +520,14 @@ static void _rtl_usb_rx_process_noagg(st
 			u8 *pdata;
 
 			uskb = dev_alloc_skb(skb->len + 128);
-			memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status,
-			       sizeof(rx_status));
-			pdata = (u8 *)skb_put(uskb, skb->len);
-			memcpy(pdata, skb->data, skb->len);
+			if (uskb) {	/* drop packet on allocation failure */
+				memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status,
+				       sizeof(rx_status));
+				pdata = (u8 *)skb_put(uskb, skb->len);
+				memcpy(pdata, skb->data, skb->len);
+				ieee80211_rx_irqsafe(hw, uskb);
+			}
 			dev_kfree_skb_any(skb);
-			ieee80211_rx_irqsafe(hw, uskb);
 		} else {
 			dev_kfree_skb_any(skb);
 		}
author maintainer
#44 lore raw

PATCH 44/175 rtlwifi: Handle previous allocation failures when freeing device memory

In reply to Greg KH

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

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

From: Simon Graham <[email protected]>

commit 7f66c2f93e5779625c10d262c84537427a2673ca upstream.

Handle previous allocation failures when freeing device memory

---
 drivers/net/wireless/rtlwifi/pci.c |   16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)
drivers/net/wireless/rtlwifi/pci.c +10 -6
@@ -1157,10 +1157,12 @@ static void _rtl_pci_free_tx_ring(struct
 		ring->idx = (ring->idx + 1) % ring->entries;
 	}
 
-	pci_free_consistent(rtlpci->pdev,
-			    sizeof(*ring->desc) * ring->entries,
-			    ring->desc, ring->dma);
-	ring->desc = NULL;
+	if (ring->desc) {
+		pci_free_consistent(rtlpci->pdev,
+				    sizeof(*ring->desc) * ring->entries,
+				    ring->desc, ring->dma);
+		ring->desc = NULL;
+	}
 }
 
 static void _rtl_pci_free_rx_ring(struct rtl_pci *rtlpci)
@@ -1184,12 +1186,14 @@ static void _rtl_pci_free_rx_ring(struct
 			kfree_skb(skb);
 		}
 
-		pci_free_consistent(rtlpci->pdev,
+		if (rtlpci->rx_ring[rx_queue_idx].desc) {
+			pci_free_consistent(rtlpci->pdev,
 				    sizeof(*rtlpci->rx_ring[rx_queue_idx].
 					   desc) * rtlpci->rxringcount,
 				    rtlpci->rx_ring[rx_queue_idx].desc,
 				    rtlpci->rx_ring[rx_queue_idx].dma);
-		rtlpci->rx_ring[rx_queue_idx].desc = NULL;
+			rtlpci->rx_ring[rx_queue_idx].desc = NULL;
+		}
 	}
 }
 
author maintainer
#45 lore raw

PATCH 45/175 rtlwifi: rtl8192c: Prevent sleeping from invalid context in rtl8192cu

In reply to Greg KH

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

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

From: Larry Finger <[email protected]>

commit ebecdcc12fed5d3c81853dea61a0a78a5aefab52 upstream.

When driver rtl8192cu is used with the debug level set to 3 or greater, the result is "sleeping function called from invalid context" due to an rcu_read_lock() call in the DM refresh routine in driver rtl8192c. This lock is not necessary as the USB driver does not use the struct being protected, thus the lock is set only when a PCI interface is active.

This bug is reported in https://bugzilla.kernel.org/show_bug.cgi?id=42775.

---
 drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c |   11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)
drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +8 -3
@@ -1219,13 +1219,18 @@ static void rtl92c_dm_refresh_rate_adapt
 				 ("PreState = %d, CurState = %d\n",
 				  p_ra->pre_ratr_state, p_ra->ratr_state));
 
-			rcu_read_lock();
-			sta = ieee80211_find_sta(mac->vif, mac->bssid);
+			/* Only the PCI card uses sta in the update rate table
+			 * callback routine */
+			if (rtlhal->interface == INTF_PCI) {
+				rcu_read_lock();
+				sta = ieee80211_find_sta(mac->vif, mac->bssid);
+			}
 			rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
 					p_ra->ratr_state);
 
 			p_ra->pre_ratr_state = p_ra->ratr_state;
-			rcu_read_unlock();
+			if (rtlhal->interface == INTF_PCI)
+				rcu_read_unlock();
 		}
 	}
 }
author maintainer
#46 lore raw

PATCH 46/175 rtlwifi: rtl8192ce: Fix loss of receive performance

In reply to Greg KH

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

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

From: Jingjun Wu <[email protected]>

commit a9b89e2567c743483e6354f64d7a7e3a8c101e9e upstream.

Driver rtl8192ce when used with the RTL8188CE device would start at about 20 Mbps on a 54 Mbps connection, but quickly drop to 1 Mbps. One of the symptoms is that the AP would need to retransmit each packet 4 of 5 times before the driver would acknowledge it. Recovery is possible only by unloading and reloading the driver. This problem was reported at
https://bugzilla.redhat.com/show_bug.cgi?id=770207.

The problem is due to a missing update of the gain setting.

---
 drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c |    4 ++++
 1 file changed, 4 insertions(+)
drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +4 -0
@@ -524,6 +524,10 @@ void rtl92c_dm_write_dig(struct ieee8021
 		  dm_digtable.cur_igvalue, dm_digtable.pre_igvalue,
 		  dm_digtable.backoff_val));
 
+	dm_digtable.cur_igvalue += 2;
+	if (dm_digtable.cur_igvalue > 0x3f)
+		dm_digtable.cur_igvalue = 0x3f;
+
 	if (dm_digtable.pre_igvalue != dm_digtable.cur_igvalue) {
 		rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
 			      dm_digtable.cur_igvalue);
author maintainer
#47 lore raw

PATCH 47/175 serial: PL011: clear pending interrupts

In reply to Greg KH

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

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

From: Linus Walleij <[email protected]>

commit 9b96fbacda34079dea0638ee1e92c56286f6114a upstream.

Chanho Min reported that when the boot loader transfers control to the kernel, there may be pending interrupts causing the UART to lock up in an eternal loop trying to pick tokens from the FIFO (since the RX interrupt flag indicates there are tokens) while in practice there are no tokens - in fact there is only a pending IRQ flag.

This patch address the issue with a combination of two patches suggested by Russell King that clears and mask all interrupts at probe() and clears any pending error and RX interrupts at port startup time.

We suspect the spurious interrupts are a side-effect of switching the UART from FIFO to non-FIFO mode.

---
 drivers/tty/serial/amba-pl011.c |   15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)
drivers/tty/serial/amba-pl011.c +11 -4
@@ -1381,6 +1381,10 @@ static int pl011_startup(struct uart_por
 
 	uap->port.uartclk = clk_get_rate(uap->clk);
 
+	/* Clear pending error and receive interrupts */
+	writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS |
+	       UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR);
+
 	/*
 	 * Allocate the IRQ
 	 */
@@ -1417,10 +1421,6 @@ static int pl011_startup(struct uart_por
 	cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
 	writew(cr, uap->port.membase + UART011_CR);
 
-	/* Clear pending error interrupts */
-	writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS,
-	       uap->port.membase + UART011_ICR);
-
 	/*
 	 * initialise the old status of the modem signals
 	 */
@@ -1435,6 +1435,9 @@ static int pl011_startup(struct uart_por
 	 * as well.
 	 */
 	spin_lock_irq(&uap->port.lock);
+	/* Clear out any spuriously appearing RX interrupts */
+	 writew(UART011_RTIS | UART011_RXIS,
+		uap->port.membase + UART011_ICR);
 	uap->im = UART011_RTIM;
 	if (!pl011_dma_rx_running(uap))
 		uap->im |= UART011_RXIM;
@@ -1927,6 +1930,10 @@ static int pl011_probe(struct amba_devic
 		goto unmap;
 	}
 
+	/* Ensure interrupts from this UART are masked and cleared */
+	writew(0, uap->port.membase + UART011_IMSC);
+	writew(0xffff, uap->port.membase + UART011_ICR);
+
 	uap->vendor = vendor;
 	uap->lcrh_rx = vendor->lcrh_rx;
 	uap->lcrh_tx = vendor->lcrh_tx;
author maintainer
#48 lore raw

PATCH 48/175 iwlwifi: always monitor for stuck queues

In reply to Greg KH

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

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

From: Johannes Berg <[email protected]>

commit 342bbf3fee2fa9a18147e74b2e3c4229a4564912 upstream.

If we only monitor while associated, the following can happen:
- we're associated, and the queue stuck check runs, setting the queue "touch" time to X
- we disassociate, stopping the monitoring, which leaves the time set to X
- almost 2s later, we associate, and enqueue a frame
- before the frame is transmitted, we monitor for stuck queues, and find the time set to X, although it is now later than X + 2000ms, so we decide that the queue is stuck and erroneously restart the device

It happens more with P2P because there we can go between associated/unassociated frequently.

---
 drivers/net/wireless/iwlwifi/iwl-core.c |   18 ++++--------------
 1 file changed, 4 insertions(+), 14 deletions(-)
drivers/net/wireless/iwlwifi/iwl-core.c +4 -14
@@ -1465,20 +1465,10 @@ void iwl_bg_watchdog(unsigned long data)
 	if (timeout == 0)
 		return;
 
-	/* monitor and check for stuck cmd queue */
-	if (iwl_check_stuck_queue(priv, priv->shrd->cmd_queue))
-		return;
-
-	/* monitor and check for other stuck queues */
-	if (iwl_is_any_associated(priv)) {
-		for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) {
-			/* skip as we already checked the command queue */
-			if (cnt == priv->shrd->cmd_queue)
-				continue;
-			if (iwl_check_stuck_queue(priv, cnt))
-				return;
-		}
-	}
+	/* monitor and check for stuck queues */
+	for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++)
+		if (iwl_check_stuck_queue(priv, cnt))
+			return;
 
 	mod_timer(&priv->watchdog, jiffies +
 		  msecs_to_jiffies(IWL_WD_TICK(timeout)));
author maintainer
#49 lore raw

PATCH 49/175 ath9k: fix going to full-sleep on PS idle

In reply to Greg KH

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

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

From: Felix Fietkau <[email protected]>

commit c1afdaff90538ef085b756454f12b29575411214 upstream.

The check for PS_WAIT_FOR_TX_ACK was inverted, the hardware should only go to full sleep if no tx is pending.

---
 drivers/net/wireless/ath/ath9k/main.c |    8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/net/wireless/ath/ath9k/main.c +5 -3
@@ -118,13 +118,15 @@ void ath9k_ps_restore(struct ath_softc *
 	if (--sc->ps_usecount != 0)
 		goto unlock;
 
-	if (sc->ps_idle && (sc->ps_flags & PS_WAIT_FOR_TX_ACK))
+	if (sc->ps_flags & PS_WAIT_FOR_TX_ACK)
+		goto unlock;
+
+	if (sc->ps_idle)
 		mode = ATH9K_PM_FULL_SLEEP;
 	else if (sc->ps_enabled &&
 		 !(sc->ps_flags & (PS_WAIT_FOR_BEACON |
 			      PS_WAIT_FOR_CAB |
-			      PS_WAIT_FOR_PSPOLL_DATA |
-			      PS_WAIT_FOR_TX_ACK)))
+			      PS_WAIT_FOR_PSPOLL_DATA)))
 		mode = ATH9K_PM_NETWORK_SLEEP;
 	else
 		goto unlock;
author maintainer
#50 lore raw

PATCH 50/175 math: Introduce div64_long

In reply to Greg KH

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

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

From: Sasha Levin <[email protected]>

commit f910381a55cdaa097030291f272f6e6e4380c39a upstream.

Add a div64_long macro which is used to devide a 64bit number by a long (which can be 4 bytes on 32bit systems and 8 bytes on 64bit systems).

---
 include/linux/math64.h |    4 ++++
 1 file changed, 4 insertions(+)
include/linux/math64.h +4 -0
@@ -6,6 +6,8 @@
 
 #if BITS_PER_LONG == 64
 
+#define div64_long(x,y) div64_s64((x),(y))
+
 /**
  * div_u64_rem - unsigned 64bit divide with 32bit divisor with remainder
  *
@@ -45,6 +47,8 @@ static inline s64 div64_s64(s64 dividend
 
 #elif BITS_PER_LONG == 32
 
+#define div64_long(x,y) div_s64((x),(y))
+
 #ifndef div_u64_rem
 static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
 {
author maintainer
#51 lore raw

PATCH 51/175 ntp: Fix integer overflow when setting time

In reply to Greg KH

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

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

From: Sasha Levin <[email protected]>

commit a078c6d0e6288fad6d83fb6d5edd91ddb7b6ab33 upstream.

'long secs' is passed as divisor to div_s64, which accepts a 32bit divisor. On 64bit machines that value is trimmed back from 8 bytes back to 4, causing a divide by zero when the number is bigger than (1 << 32) - 1 and all 32 lower bits are 0.

Use div64_long() instead.

---
 kernel/time/ntp.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/time/ntp.c +1 -1
@@ -275,7 +275,7 @@ static inline s64 ntp_update_offset_fll(
 
 	time_status |= STA_MODE;
 
-	return div_s64(offset64 << (NTP_SCALE_SHIFT - SHIFT_FLL), secs);
+	return div64_long(offset64 << (NTP_SCALE_SHIFT - SHIFT_FLL), secs);
 }
 
 static void ntp_update_offset(long offset)
author maintainer
#52 lore raw

PATCH 52/175 uevent: send events in correct order according to seqnum (v3)

In reply to Greg KH

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

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

From: Andrew Vagin <[email protected]>

commit 7b60a18da393ed70db043a777fd9e6d5363077c4 upstream.

The queue handling in the udev daemon assumes that the events are ordered.

Before this patch uevent_seqnum is incremented under sequence_lock, than an event is send uner uevent_sock_mutex. I want to say that code contained a window between incrementing seqnum and sending an event.

This patch locks uevent_sock_mutex before incrementing uevent_seqnum.

v2: delete sequence_lock, uevent_seqnum is protected by uevent_sock_mutex
v3: unlock the mutex before the goto exit

Thanks for Kay for the comments.

---
 lib/kobject_uevent.c |   19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)
lib/kobject_uevent.c +9 -10
@@ -29,16 +29,17 @@
 
 u64 uevent_seqnum;
 char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
-static DEFINE_SPINLOCK(sequence_lock);
 #ifdef CONFIG_NET
 struct uevent_sock {
 	struct list_head list;
 	struct sock *sk;
 };
 static LIST_HEAD(uevent_sock_list);
-static DEFINE_MUTEX(uevent_sock_mutex);
 #endif
 
+/* This lock protects uevent_seqnum and uevent_sock_list */
+static DEFINE_MUTEX(uevent_sock_mutex);
+
 /* the strings here must match the enum in include/linux/kobject.h */
 static const char *kobject_actions[] = {
 	[KOBJ_ADD] =		"add",
@@ -136,7 +137,6 @@ int kobject_uevent_env(struct kobject *k
 	struct kobject *top_kobj;
 	struct kset *kset;
 	const struct kset_uevent_ops *uevent_ops;
-	u64 seq;
 	int i = 0;
 	int retval = 0;
 #ifdef CONFIG_NET
@@ -243,17 +243,16 @@ int kobject_uevent_env(struct kobject *k
 	else if (action == KOBJ_REMOVE)
 		kobj->state_remove_uevent_sent = 1;
 
+	mutex_lock(&uevent_sock_mutex);
 	/* we will send an event, so request a new sequence number */
-	spin_lock(&sequence_lock);
-	seq = ++uevent_seqnum;
-	spin_unlock(&sequence_lock);
-	retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq);
-	if (retval)
+	retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)++uevent_seqnum);
+	if (retval) {
+		mutex_unlock(&uevent_sock_mutex);
 		goto exit;
+	}
 
 #if defined(CONFIG_NET)
 	/* send netlink message */
-	mutex_lock(&uevent_sock_mutex);
 	list_for_each_entry(ue_sk, &uevent_sock_list, list) {
 		struct sock *uevent_sock = ue_sk->sk;
 		struct sk_buff *skb;
@@ -290,8 +289,8 @@ int kobject_uevent_env(struct kobject *k
 		} else
 			retval = -ENOMEM;
 	}
-	mutex_unlock(&uevent_sock_mutex);
 #endif
+	mutex_unlock(&uevent_sock_mutex);
 
 	/* call uevent_helper, usually only enabled during early boot */
 	if (uevent_helper[0] && !kobj_usermode_filter(kobj)) {
author maintainer
#53 lore raw

PATCH 53/175 genirq: Fix long-term regression in genirq irq_set_irq_type() handling

In reply to Greg KH

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

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

From: Russell King <[email protected]>

commit a09b659cd68c10ec6a30cb91ebd2c327fcd5bfe5 upstream.

In 2008, commit 0c5d1eb77a8be ("genirq: record trigger type") modified the way set_irq_type() handles the 'no trigger' condition. However, this has an adverse effect on PCMCIA support on Intel StrongARM and probably PXA platforms.

PCMCIA has several status signals on the socket which can trigger interrupts; some of these status signals depend on the card's mode (whether it is configured in memory or IO mode). For example, cards have a 'Ready/IRQ' signal: in memory mode, this provides an indication to PCMCIA that the card has finished its power up initialization. In IO mode, it provides the device interrupt signal. Other status signals switch between on-board battery status and loud speaker output.

In classical PCMCIA implementations, where you have a specific socket controller, the controller provides a method to mask interrupts from the socket, and importantly ignore any state transitions on the pins which correspond with interrupts once masked. This masking prevents unwanted events caused by the removal and application of socket power being forwarded.

However, on platforms where there is no socket controller, the PCMCIA status and interrupt signals are routed to standard edge-triggered GPIOs. These GPIOs can be configured to interrupt on rising edge, falling edge, or never. This is where the problems start.

Edge triggered interrupts are required to record events while disabled via the usual methods of {free,request,disable,enable}_irq() to prevent problems with dropped interrupts (eg, the 8390 driver uses disable_irq() to defer the delivery of interrupts). As a result, these interfaces can not be used to implement the desired behaviour.

The side effect of this is that if the 'Ready/IRQ' GPIO is disabled via disable_irq() on suspend, and enabled via enable_irq() after resume, we will record the state transitions caused by powering events as valid interrupts, and foward them to the card driver, which may attempt to access a card which is not powered up.

This leads delays resume while drivers spin in their interrupt handlers, and complaints from drivers before they realize what's happened.

Moreover, in the case of the 'Ready/IRQ' signal, this is requested and freed by the card driver itself; the PCMCIA core has no idea whether the interrupt is requested, and, therefore, whether a call to disable_irq() would be valid. (We tried this around 2.4.17 / 2.5.1 kernel era, and ended up throwing it out because of this problem.)

Therefore, it was decided back in around 2002 to disable the edge triggering instead, resulting in all state transitions on the GPIO being ignored. That's what we actually need the hardware to do.

The commit above changes this behaviour; it explicitly prevents the 'no trigger' state being selected.

The reason that request_irq() does not accept the 'no trigger' state is for compatibility with existing drivers which do not provide their desired triggering configuration. The set_irq_type() function is 'new' and not used by non-trigger aware drivers.

Therefore, revert this change, and restore previously working platforms back to their former state.

---
 kernel/irq/chip.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
kernel/irq/chip.c +1 -2
@@ -61,8 +61,7 @@ int irq_set_irq_type(unsigned int irq, u
 		return -EINVAL;
 
 	type &= IRQ_TYPE_SENSE_MASK;
-	if (type != IRQ_TYPE_NONE)
-		ret = __irq_set_trigger(desc, irq, type);
+	ret = __irq_set_trigger(desc, irq, type);
 	irq_put_desc_busunlock(desc, flags);
 	return ret;
 }
author maintainer
#54 lore raw

PATCH 54/175 genirq: Fix incorrect check for forced IRQ thread handler

In reply to Greg KH

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

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

From: Alexander Gordeev <[email protected]>

commit 540b60e24f3f4781d80e47122f0c4486a03375b8 upstream.

We do not want a bitwise AND between boolean operands

---
 kernel/irq/manage.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/irq/manage.c +1 -1
@@ -773,7 +773,7 @@ static int irq_thread(void *data)
 			struct irqaction *action);
 	int wake;
 
-	if (force_irqthreads & test_bit(IRQTF_FORCED_THREAD,
+	if (force_irqthreads && test_bit(IRQTF_FORCED_THREAD,
 					&action->thread_flags))
 		handler_fn = irq_forced_thread_fn;
 	else
author maintainer
#55 lore raw

PATCH 55/175 rtc: Disable the alarm in the hardware (v2)

In reply to Greg KH

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

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

From: Rabin Vincent <[email protected]>

commit 41c7f7424259ff11009449f87c95656f69f9b186 upstream.

Currently, the RTC code does not disable the alarm in the hardware.

This means that after a sequence such as the one below (the files are in the RTC sysfs), the box will boot up after 2 minutes even though we've asked for the alarm to be turned off.

	# echo $((`cat since_epoch`)+120) > wakealarm
	# echo 0 > wakealarm
	# poweroff

Fix this by disabling the alarm when there are no timers to run.

The original version of this patch was reverted. This version disables the irq directly instead of setting a disabled timer in the future.

Cc John Stultz <[email protected]>
[Merged in the second revision from Rabin]
---
 drivers/rtc/interface.c |   15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)
drivers/rtc/interface.c +13 -2
@@ -763,6 +763,14 @@ static int rtc_timer_enqueue(struct rtc_
 	return 0;
 }
 
+static void rtc_alarm_disable(struct rtc_device *rtc)
+{
+	if (!rtc->ops || !rtc->ops->alarm_irq_enable)
+		return;
+
+	rtc->ops->alarm_irq_enable(rtc->dev.parent, false);
+}
+
 /**
  * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue
  * @rtc rtc device
@@ -784,8 +792,10 @@ static void rtc_timer_remove(struct rtc_
 		struct rtc_wkalrm alarm;
 		int err;
 		next = timerqueue_getnext(&rtc->timerqueue);
-		if (!next)
+		if (!next) {
+			rtc_alarm_disable(rtc);
 			return;
+		}
 		alarm.time = rtc_ktime_to_tm(next->expires);
 		alarm.enabled = 1;
 		err = __rtc_set_alarm(rtc, &alarm);
@@ -847,7 +857,8 @@ again:
 		err = __rtc_set_alarm(rtc, &alarm);
 		if (err == -ETIME)
 			goto again;
-	}
+	} else
+		rtc_alarm_disable(rtc);
 
 	mutex_unlock(&rtc->ops_lock);
 }
author maintainer
#56 lore raw

PATCH 56/175 p54spi: Release GPIO lines and IRQ on error in p54spi_probe

In reply to Greg KH

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

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

From: Max Filippov <[email protected]>

commit 62ebeed8d00aef75eac4fd6c161cae75a41965ca upstream.

This makes it possible to reload driver if insmod has failed due to missing firmware.

---
 drivers/net/wireless/p54/p54spi.c |   14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)
drivers/net/wireless/p54/p54spi.c +10 -4
@@ -618,19 +618,19 @@ static int __devinit p54spi_probe(struct
 	ret = spi_setup(spi);
 	if (ret < 0) {
 		dev_err(&priv->spi->dev, "spi_setup failed");
-		goto err_free_common;
+		goto err_free;
 	}
 
 	ret = gpio_request(p54spi_gpio_power, "p54spi power");
 	if (ret < 0) {
 		dev_err(&priv->spi->dev, "power GPIO request failed: %d", ret);
-		goto err_free_common;
+		goto err_free;
 	}
 
 	ret = gpio_request(p54spi_gpio_irq, "p54spi irq");
 	if (ret < 0) {
 		dev_err(&priv->spi->dev, "irq GPIO request failed: %d", ret);
-		goto err_free_common;
+		goto err_free_gpio_power;
 	}
 
 	gpio_direction_output(p54spi_gpio_power, 0);
@@ -641,7 +641,7 @@ static int __devinit p54spi_probe(struct
 			  priv->spi);
 	if (ret < 0) {
 		dev_err(&priv->spi->dev, "request_irq() failed");
-		goto err_free_common;
+		goto err_free_gpio_irq;
 	}
 
 	irq_set_irq_type(gpio_to_irq(p54spi_gpio_irq), IRQ_TYPE_EDGE_RISING);
@@ -673,6 +673,12 @@ static int __devinit p54spi_probe(struct
 	return 0;
 
 err_free_common:
+	free_irq(gpio_to_irq(p54spi_gpio_irq), spi);
+err_free_gpio_irq:
+	gpio_free(p54spi_gpio_irq);
+err_free_gpio_power:
+	gpio_free(p54spi_gpio_power);
+err_free:
 	p54_free_common(priv->hw);
 	return ret;
 }
author maintainer
#57 lore raw

PATCH 57/175 rtnetlink: Fix VF IFLA policy

In reply to Greg KH

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

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

From: Greg Rose <[email protected]>

commit 48752f6513012a1b078da08b145d5c40a644f058 upstream.

Add VF spoof check to IFLA policy. The original patch I submitted to add the spoof checking feature to rtnl failed to add the proper policy rule that identifies the data type and len. This patch corrects that oversight. No bugs have been reported against this but it may cause some problem for the netlink message parsing that uses the policy table.

---
 net/core/rtnetlink.c |    2 ++
 1 file changed, 2 insertions(+)
net/core/rtnetlink.c +2 -0
@@ -1133,6 +1133,8 @@ static const struct nla_policy ifla_vf_p
 				    .len = sizeof(struct ifla_vf_vlan) },
 	[IFLA_VF_TX_RATE]	= { .type = NLA_BINARY,
 				    .len = sizeof(struct ifla_vf_tx_rate) },
+	[IFLA_VF_SPOOFCHK]	= { .type = NLA_BINARY,
+				    .len = sizeof(struct ifla_vf_spoofchk) },
 };
 
 static const struct nla_policy ifla_port_policy[IFLA_PORT_MAX+1] = {
author maintainer
#58 lore raw

PATCH 58/175 IB/iser: Post initial receive buffers before sending the final login request

In reply to Greg KH

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

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

From: Or Gerlitz <[email protected]>

commit 89e984e2c2cd14f77ccb26c47726ac7f13b70ae8 upstream.

An iser target may send iscsi NO-OP PDUs as soon as it marks the iSER iSCSI session as fully operative. This means that there is window where there are no posted receive buffers on the initiator side, so it's possible for the iSER RC connection to break because of RNR NAK / retry errors. To fix this, rely on the flags bits in the login request to have FFP (0x3) in the lower nibble as a marker for the final login request, and post an initial chunk of receive buffers before sending that login request instead of after getting the login response.

---
 drivers/infiniband/ulp/iser/iscsi_iser.c     |   18 +++-------------
 drivers/infiniband/ulp/iser/iscsi_iser.h     |    1 
 drivers/infiniband/ulp/iser/iser_initiator.c |   30 +++++++++++++++------------
 3 files changed, 22 insertions(+), 27 deletions(-)
drivers/infiniband/ulp/iser/iscsi_iser.c +4 -14
@@ -364,6 +364,9 @@ iscsi_iser_conn_bind(struct iscsi_cls_se
 	}
 	ib_conn = ep->dd_data;
 
+	if (iser_alloc_rx_descriptors(ib_conn))
+		return -ENOMEM;
+
 	/* binds the iSER connection retrieved from the previously
 	 * connected ep_handle to the iSCSI layer connection. exchanges
 	 * connection pointers */
@@ -398,19 +401,6 @@ iscsi_iser_conn_stop(struct iscsi_cls_co
 	iser_conn->ib_conn = NULL;
 }
 
-static int
-iscsi_iser_conn_start(struct iscsi_cls_conn *cls_conn)
-{
-	struct iscsi_conn *conn = cls_conn->dd_data;
-	int err;
-
-	err = iser_conn_set_full_featured_mode(conn);
-	if (err)
-		return err;
-
-	return iscsi_conn_start(cls_conn);
-}
-
 static void iscsi_iser_session_destroy(struct iscsi_cls_session *cls_session)
 {
 	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
@@ -724,7 +714,7 @@ static struct iscsi_transport iscsi_iser
 	.get_conn_param		= iscsi_conn_get_param,
 	.get_ep_param		= iscsi_iser_get_ep_param,
 	.get_session_param	= iscsi_session_get_param,
-	.start_conn             = iscsi_iser_conn_start,
+	.start_conn             = iscsi_conn_start,
 	.stop_conn              = iscsi_iser_conn_stop,
 	/* iscsi host params */
 	.get_host_param		= iscsi_host_get_param,
drivers/infiniband/ulp/iser/iscsi_iser.h +1 -0
@@ -366,4 +366,5 @@ int iser_dma_map_task_data(struct iscsi_
 void iser_dma_unmap_task_data(struct iscsi_iser_task *iser_task);
 int  iser_initialize_task_headers(struct iscsi_task *task,
 			struct iser_tx_desc *tx_desc);
+int iser_alloc_rx_descriptors(struct iser_conn *ib_conn);
 #endif
drivers/infiniband/ulp/iser/iser_initiator.c +17 -13
@@ -170,7 +170,7 @@ static void iser_create_send_desc(struct
 }
 
 
-static int iser_alloc_rx_descriptors(struct iser_conn *ib_conn)
+int iser_alloc_rx_descriptors(struct iser_conn *ib_conn)
 {
 	int i, j;
 	u64 dma_addr;
@@ -242,23 +242,24 @@ void iser_free_rx_descriptors(struct ise
 	kfree(ib_conn->rx_descs);
 }
 
-/**
- *  iser_conn_set_full_featured_mode - (iSER API)
- */
-int iser_conn_set_full_featured_mode(struct iscsi_conn *conn)
+static int iser_post_rx_bufs(struct iscsi_conn *conn, struct iscsi_hdr *req)
 {
 	struct iscsi_iser_conn *iser_conn = conn->dd_data;
 
-	iser_dbg("Initially post: %d\n", ISER_MIN_POSTED_RX);
+	iser_dbg("req op %x flags %x\n", req->opcode, req->flags);
+	/* check if this is the last login - going to full feature phase */
+	if ((req->flags & ISCSI_FULL_FEATURE_PHASE) != ISCSI_FULL_FEATURE_PHASE)
+		return 0;
 
-	/* Check that there is no posted recv or send buffers left - */
-	/* they must be consumed during the login phase */
-	BUG_ON(iser_conn->ib_conn->post_recv_buf_count != 0);
-	BUG_ON(atomic_read(&iser_conn->ib_conn->post_send_buf_count) != 0);
-
-	if (iser_alloc_rx_descriptors(iser_conn->ib_conn))
-		return -ENOMEM;
+	/*
+	 * Check that there is one posted recv buffer (for the last login
+	 * response) and no posted send buffers left - they must have been
+	 * consumed during previous login phases.
+	 */
+	WARN_ON(iser_conn->ib_conn->post_recv_buf_count != 1);
+	WARN_ON(atomic_read(&iser_conn->ib_conn->post_send_buf_count) != 0);
 
+	iser_dbg("Initially post: %d\n", ISER_MIN_POSTED_RX);
 	/* Initial post receive buffers */
 	if (iser_post_recvm(iser_conn->ib_conn, ISER_MIN_POSTED_RX))
 		return -ENOMEM;
@@ -438,6 +439,9 @@ int iser_send_control(struct iscsi_conn
 		err = iser_post_recvl(iser_conn->ib_conn);
 		if (err)
 			goto send_control_error;
+		err = iser_post_rx_bufs(conn, task->hdr);
+		if (err)
+			goto send_control_error;
 	}
 
 	err = iser_post_send(iser_conn->ib_conn, mdesc);
author maintainer
#59 lore raw

PATCH 59/175 mlx4_core: Fix one more static exported function

In reply to Greg KH

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

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

From: Roland Dreier <[email protected]>

commit e10903b087e425298fb86c6ad4b1a88735480db7 upstream.

Commit 22c8bff6face ("mlx4_core: Exported functions can't be static") fixed most of this up, but forgot about mlx4_is_slave_active(). Fix this one too.

---
 drivers/net/ethernet/mellanox/mlx4/main.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/mellanox/mlx4/main.c +1 -1
@@ -394,7 +394,7 @@ static int mlx4_how_many_lives_vf(struct
 	return ret;
 }
 
-static int mlx4_is_slave_active(struct mlx4_dev *dev, int slave)
+int mlx4_is_slave_active(struct mlx4_dev *dev, int slave)
 {
 	struct mlx4_priv *priv = mlx4_priv(dev);
 	struct mlx4_slave_state *s_slave;
author maintainer
#60 lore raw

PATCH 60/175 ima: fix Kconfig dependencies

In reply to Greg KH

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

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

From: Fabio Estevam <[email protected]>

commit f4a0391dfa91155bd961673b31eb42d9d45c799d upstream.

Fix the following build warning:
warning: (IMA) selects TCG_TPM which has unmet direct dependencies (HAS_IOMEM && EXPERIMENTAL)

---
 drivers/char/tpm/Kconfig       |    1 -
 security/integrity/ima/Kconfig |    2 +-
 2 files changed, 1 insertion(+), 2 deletions(-)
drivers/char/tpm/Kconfig +0 -1
@@ -5,7 +5,6 @@
 menuconfig TCG_TPM
 	tristate "TPM Hardware Support"
 	depends on HAS_IOMEM
-	depends on EXPERIMENTAL
 	select SECURITYFS
 	---help---
 	  If you have a TPM security chip in your system, which
security/integrity/ima/Kconfig +1 -1
@@ -9,7 +9,7 @@ config IMA
 	select CRYPTO_HMAC
 	select CRYPTO_MD5
 	select CRYPTO_SHA1
-	select TCG_TPM if !S390 && !UML
+	select TCG_TPM if HAS_IOMEM && !UML
 	select TCG_TIS if TCG_TPM
 	help
 	  The Trusted Computing Group(TCG) runtime Integrity
author maintainer
#61 lore raw

PATCH 61/175 x86/ioapic: Add register level checks to detect bogus io-apic entries

In reply to Greg KH

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

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

From: Suresh Siddha <[email protected]>

commit 73d63d038ee9f769f5e5b46792d227fe20e442c5 upstream.

With the recent changes to clear_IO_APIC_pin() which tries to clear remoteIRR bit explicitly, some of the users started to see "Unable to reset IRR for apic .." messages.

Close look shows that these are related to bogus IO-APIC entries which return's all 1's for their io-apic registers. And the above mentioned error messages are benign. But kernel should have ignored such io-apic's in the first place.

Check if register 0, 1, 2 of the listed io-apic are all 1's and ignore such io-apic.

---
 arch/x86/kernel/apic/io_apic.c |   40 ++++++++++++++++++++++++++++++++--------
 1 file changed, 32 insertions(+), 8 deletions(-)
arch/x86/kernel/apic/io_apic.c +32 -8
@@ -3967,18 +3967,36 @@ int mp_find_ioapic_pin(int ioapic, u32 g
 static __init int bad_ioapic(unsigned long address)
 {
 	if (nr_ioapics >= MAX_IO_APICS) {
-		printk(KERN_WARNING "WARNING: Max # of I/O APICs (%d) exceeded "
-		       "(found %d), skipping\n", MAX_IO_APICS, nr_ioapics);
+		pr_warn("WARNING: Max # of I/O APICs (%d) exceeded (found %d), skipping\n",
+			MAX_IO_APICS, nr_ioapics);
 		return 1;
 	}
 	if (!address) {
-		printk(KERN_WARNING "WARNING: Bogus (zero) I/O APIC address"
-		       " found in table, skipping!\n");
+		pr_warn("WARNING: Bogus (zero) I/O APIC address found in table, skipping!\n");
 		return 1;
 	}
 	return 0;
 }
 
+static __init int bad_ioapic_register(int idx)
+{
+	union IO_APIC_reg_00 reg_00;
+	union IO_APIC_reg_01 reg_01;
+	union IO_APIC_reg_02 reg_02;
+
+	reg_00.raw = io_apic_read(idx, 0);
+	reg_01.raw = io_apic_read(idx, 1);
+	reg_02.raw = io_apic_read(idx, 2);
+
+	if (reg_00.raw == -1 && reg_01.raw == -1 && reg_02.raw == -1) {
+		pr_warn("I/O APIC 0x%x registers return all ones, skipping!\n",
+			mpc_ioapic_addr(idx));
+		return 1;
+	}
+
+	return 0;
+}
+
 void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
 {
 	int idx = 0;
@@ -3995,6 +4013,12 @@ void __init mp_register_ioapic(int id, u
 	ioapics[idx].mp_config.apicaddr = address;
 
 	set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
+
+	if (bad_ioapic_register(idx)) {
+		clear_fixmap(FIX_IO_APIC_BASE_0 + idx);
+		return;
+	}
+
 	ioapics[idx].mp_config.apicid = io_apic_unique_id(id);
 	ioapics[idx].mp_config.apicver = io_apic_get_version(idx);
 
@@ -4015,10 +4039,10 @@ void __init mp_register_ioapic(int id, u
 	if (gsi_cfg->gsi_end >= gsi_top)
 		gsi_top = gsi_cfg->gsi_end + 1;
 
-	printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
-	       "GSI %d-%d\n", idx, mpc_ioapic_id(idx),
-	       mpc_ioapic_ver(idx), mpc_ioapic_addr(idx),
-	       gsi_cfg->gsi_base, gsi_cfg->gsi_end);
+	pr_info("IOAPIC[%d]: apic_id %d, version %d, address 0x%x, GSI %d-%d\n",
+		idx, mpc_ioapic_id(idx),
+		mpc_ioapic_ver(idx), mpc_ioapic_addr(idx),
+		gsi_cfg->gsi_base, gsi_cfg->gsi_end);
 
 	nr_ioapics++;
 }
author maintainer
#62 lore raw

PATCH 62/175 mm: thp: fix pmd_bad() triggering in code paths holding mmap_sem read mode

In reply to Greg KH

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

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

From: Andrea Arcangeli <[email protected]>

commit 1a5a9906d4e8d1976b701f889d8f35d54b928f25 upstream.

In some cases it may happen that pmd_none_or_clear_bad() is called with the mmap_sem hold in read mode. In those cases the huge page faults can allocate hugepmds under pmd_none_or_clear_bad() and that can trigger a false positive from pmd_bad() that will not like to see a pmd materializing as trans huge.

It's not khugepaged causing the problem, khugepaged holds the mmap_sem in write mode (and all those sites must hold the mmap_sem in read mode to prevent pagetables to go away from under them, during code review it seems vm86 mode on 32bit kernels requires that too unless it's restricted to 1 thread per process or UP builds). The race is only with the huge pagefaults that can convert a pmd_none() into a pmd_trans_huge().

Effectively all these pmd_none_or_clear_bad() sites running with mmap_sem in read mode are somewhat speculative with the page faults, and the result is always undefined when they run simultaneously. This is probably why it wasn't common to run into this. For example if the madvise(MADV_DONTNEED) runs zap_page_range() shortly before the page fault, the hugepage will not be zapped, if the page fault runs first it will be zapped.

Altering pmd_bad() not to error out if it finds hugepmds won't be enough to fix this, because zap_pmd_range would then proceed to call zap_pte_range (which would be incorrect if the pmd become a pmd_trans_huge()).

The simplest way to fix this is to read the pmd in the local stack (regardless of what we read, no need of actual CPU barriers, only compiler barrier needed), and be sure it is not changing under the code that computes its value. Even if the real pmd is changing under the value we hold on the stack, we don't care. If we actually end up in zap_pte_range it means the pmd was not none already and it was not huge, and it can't become huge from under us (khugepaged locking explained above).

All we need is to enforce that there is no way anymore that in a code path like below, pmd_trans_huge can be false, but pmd_none_or_clear_bad can run into a hugepmd. The overhead of a barrier() is just a compiler tweak and should not be measurable (I only added it for THP builds). I don't exclude different compiler versions may have prevented the race too by caching the value of *pmd on the stack (that hasn't been verified, but it wouldn't be impossible considering pmd_none_or_clear_bad, pmd_bad, pmd_trans_huge, pmd_none are all inlines and there's no external function called in between pmd_trans_huge and pmd_none_or_clear_bad).

		if (pmd_trans_huge(*pmd)) {
			if (next-addr != HPAGE_PMD_SIZE) {
				VM_BUG_ON(!rwsem_is_locked(&tlb->mm->mmap_sem));
				split_huge_page_pmd(vma->vm_mm, pmd);
			} else if (zap_huge_pmd(tlb, vma, pmd, addr))
				continue;
			/* fall through */
		}
		if (pmd_none_or_clear_bad(pmd))

Because this race condition could be exercised without special privileges this was reported in CVE-2012-1179.

The race was identified and fully explained by Ulrich who debugged it. I'm quoting his accurate explanation below, for reference.

====== start quote =======

      mapcount 0 page_mapcount 1
      kernel BUG at mm/huge_memory.c:1384!

    At some point prior to the panic, a "bad pmd ..." message similar to the
    following is logged on the console:

      mm/memory.c:145: bad pmd ffff8800376e1f98(80000000314000e7).

    The "bad pmd ..." message is logged by pmd_clear_bad() before it clears
    the page's PMD table entry.

        143 void pmd_clear_bad(pmd_t *pmd)
        144 {
    ->  145         pmd_ERROR(*pmd);
        146         pmd_clear(pmd);
        147 }

    After the PMD table entry has been cleared, there is an inconsistency
    between the actual number of PMD table entries that are mapping the page
    and the page's map count (_mapcount field in struct page). When the page
    is subsequently reclaimed, __split_huge_page() detects this inconsistency.

       1381         if (mapcount != page_mapcount(page))
       1382                 printk(KERN_ERR "mapcount %d page_mapcount %d\n",
       1383                        mapcount, page_mapcount(page));
    -> 1384         BUG_ON(mapcount != page_mapcount(page));

    The root cause of the problem is a race of two threads in a multithreaded
    process. Thread B incurs a page fault on a virtual address that has never
    been accessed (PMD entry is zero) while Thread A is executing an madvise()
    system call on a virtual address within the same 2 MB (huge page) range.

               virtual address space
              .---------------------.
              |                     |
              |                     |
            .-|---------------------|
            | |                     |
            | |                     |<-- B(fault)
            | |                     |
      2 MB  | |/////////////////////|-.
      huge <  |/////////////////////|  > A(range)
      page  | |/////////////////////|-'
            | |                     |
            | |                     |
            '-|---------------------|
              |                     |
              |                     |
              '---------------------'

    - Thread A is executing an madvise(..., MADV_DONTNEED) system call
      on the virtual address range "A(range)" shown in the picture.

    sys_madvise
      // Acquire the semaphore in shared mode.
      down_read(&current->mm->mmap_sem)
      ...
      madvise_vma
        switch (behavior)
        case MADV_DONTNEED:
             madvise_dontneed
               zap_page_range
                 unmap_vmas
                   unmap_page_range
                     zap_pud_range
                       zap_pmd_range
                         //
                         // Assume that this huge page has never been accessed.
                         // I.e. content of the PMD entry is zero (not mapped).
                         //
                         if (pmd_trans_huge(*pmd)) {
                             // We don't get here due to the above assumption.
                         }
                         //
                         // Assume that Thread B incurred a page fault and
             .---------> // sneaks in here as shown below.
             |           //
             |           if (pmd_none_or_clear_bad(pmd))
             |               {
             |                 if (unlikely(pmd_bad(*pmd)))
             |                     pmd_clear_bad
             |                     {
             |                       pmd_ERROR
             |                         // Log "bad pmd ..." message here.
             |                       pmd_clear
             |                         // Clear the page's PMD entry.
             |                         // Thread B incremented the map count
             |                         // in page_add_new_anon_rmap(), but
             |                         // now the page is no longer mapped
             |                         // by a PMD entry (-> inconsistency).
             |                     }
             |               }
             |
             v
    - Thread B is handling a page fault on virtual address "B(fault)" shown
      in the picture.

    ...
    do_page_fault
      __do_page_fault
        // Acquire the semaphore in shared mode.
        down_read_trylock(&mm->mmap_sem)
        ...
        handle_mm_fault
          if (pmd_none(*pmd) && transparent_hugepage_enabled(vma))
              // We get here due to the above assumption (PMD entry is zero).
              do_huge_pmd_anonymous_page
                alloc_hugepage_vma
                  // Allocate a new transparent huge page here.
                ...
                __do_huge_pmd_anonymous_page
                  ...
                  spin_lock(&mm->page_table_lock)
                  ...
                  page_add_new_anon_rmap
                    // Here we increment the page's map count (starts at -1).
                    atomic_set(&page->_mapcount, 0)
                  set_pmd_at
                    // Here we set the page's PMD entry which will be cleared
                    // when Thread A calls pmd_clear_bad().
                  ...
                  spin_unlock(&mm->page_table_lock)

    The mmap_sem does not prevent the race because both threads are acquiring
    it in shared mode (down_read).  Thread B holds the page_table_lock while
    the page's map count and PMD table entry are updated.  However, Thread A
    does not synchronize on that lock.

====== end quote =======

---
 arch/x86/kernel/vm86_32.c     |    2 +
 fs/proc/task_mmu.c            |    9 ++++++
 include/asm-generic/pgtable.h |   61 ++++++++++++++++++++++++++++++++++++++++++
 mm/memcontrol.c               |    4 ++
 mm/memory.c                   |   16 ++++++++---
 mm/mempolicy.c                |    2 -
 mm/mincore.c                  |    2 -
 mm/pagewalk.c                 |    2 -
 mm/swapfile.c                 |    4 --
 9 files changed, 92 insertions(+), 10 deletions(-)
arch/x86/kernel/vm86_32.c +2 -0
@@ -172,6 +172,7 @@ static void mark_screen_rdonly(struct mm
 	spinlock_t *ptl;
 	int i;
 
+	down_write(&mm->mmap_sem);
 	pgd = pgd_offset(mm, 0xA0000);
 	if (pgd_none_or_clear_bad(pgd))
 		goto out;
@@ -190,6 +191,7 @@ static void mark_screen_rdonly(struct mm
 	}
 	pte_unmap_unlock(pte, ptl);
 out:
+	up_write(&mm->mmap_sem);
 	flush_tlb();
 }
 
fs/proc/task_mmu.c +9 -0
@@ -409,6 +409,9 @@ static int smaps_pte_range(pmd_t *pmd, u
 	} else {
 		spin_unlock(&walk->mm->page_table_lock);
 	}
+
+	if (pmd_trans_unstable(pmd))
+		return 0;
 	/*
 	 * The mmap_sem held all the way back in m_start() is what
 	 * keeps khugepaged out of here and from collapsing things
@@ -507,6 +510,8 @@ static int clear_refs_pte_range(pmd_t *p
 	struct page *page;
 
 	split_huge_page_pmd(walk->mm, pmd);
+	if (pmd_trans_unstable(pmd))
+		return 0;
 
 	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
 	for (; addr != end; pte++, addr += PAGE_SIZE) {
@@ -670,6 +675,8 @@ static int pagemap_pte_range(pmd_t *pmd,
 	int err = 0;
 
 	split_huge_page_pmd(walk->mm, pmd);
+	if (pmd_trans_unstable(pmd))
+		return 0;
 
 	/* find the first VMA at or above 'addr' */
 	vma = find_vma(walk->mm, addr);
@@ -961,6 +968,8 @@ static int gather_pte_stats(pmd_t *pmd,
 		spin_unlock(&walk->mm->page_table_lock);
 	}
 
+	if (pmd_trans_unstable(pmd))
+		return 0;
 	orig_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl);
 	do {
 		struct page *page = can_gather_numa_stats(*pte, md->vma, addr);
include/asm-generic/pgtable.h +61 -0

74 lines not on this page · raw message

mm/memcontrol.c +4 -0
@@ -5234,6 +5234,8 @@ static int mem_cgroup_count_precharge_pt
 	spinlock_t *ptl;
 
 	split_huge_page_pmd(walk->mm, pmd);
+	if (pmd_trans_unstable(pmd))
+		return 0;
 
 	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
 	for (; addr != end; pte++, addr += PAGE_SIZE)
@@ -5396,6 +5398,8 @@ static int mem_cgroup_move_charge_pte_ra
 	spinlock_t *ptl;
 
 	split_huge_page_pmd(walk->mm, pmd);
+	if (pmd_trans_unstable(pmd))
+		return 0;
 retry:
 	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
 	for (; addr != end; addr += PAGE_SIZE) {
mm/memory.c +12 -4
@@ -1247,16 +1247,24 @@ static inline unsigned long zap_pmd_rang
 	do {
 		next = pmd_addr_end(addr, end);
 		if (pmd_trans_huge(*pmd)) {
-			if (next-addr != HPAGE_PMD_SIZE) {
+			if (next - addr != HPAGE_PMD_SIZE) {
 				VM_BUG_ON(!rwsem_is_locked(&tlb->mm->mmap_sem));
 				split_huge_page_pmd(vma->vm_mm, pmd);
 			} else if (zap_huge_pmd(tlb, vma, pmd, addr))
-				continue;
+				goto next;
 			/* fall through */
 		}
-		if (pmd_none_or_clear_bad(pmd))
-			continue;
+		/*
+		 * Here there can be other concurrent MADV_DONTNEED or
+		 * trans huge page faults running, and if the pmd is
+		 * none or trans huge it can change under us. This is
+		 * because MADV_DONTNEED holds the mmap_sem in read
+		 * mode.
+		 */
+		if (pmd_none_or_trans_huge_or_clear_bad(pmd))
+			goto next;
 		next = zap_pte_range(tlb, vma, pmd, addr, next, details);
+next:
 		cond_resched();
 	} while (pmd++, addr = next, addr != end);
 
mm/mempolicy.c +1 -1
@@ -512,7 +512,7 @@ static inline int check_pmd_range(struct
 	do {
 		next = pmd_addr_end(addr, end);
 		split_huge_page_pmd(vma->vm_mm, pmd);
-		if (pmd_none_or_clear_bad(pmd))
+		if (pmd_none_or_trans_huge_or_clear_bad(pmd))
 			continue;
 		if (check_pte_range(vma, pmd, addr, next, nodes,
 				    flags, private))
mm/mincore.c +1 -1
@@ -164,7 +164,7 @@ static void mincore_pmd_range(struct vm_
 			}
 			/* fall through */
 		}
-		if (pmd_none_or_clear_bad(pmd))
+		if (pmd_none_or_trans_huge_or_clear_bad(pmd))
 			mincore_unmapped_range(vma, addr, next, vec);
 		else
 			mincore_pte_range(vma, pmd, addr, next, vec);
mm/pagewalk.c +1 -1
@@ -59,7 +59,7 @@ again:
 			continue;
 
 		split_huge_page_pmd(walk->mm, pmd);
-		if (pmd_none_or_clear_bad(pmd))
+		if (pmd_none_or_trans_huge_or_clear_bad(pmd))
 			goto again;
 		err = walk_pte_range(pmd, addr, next, walk);
 		if (err)
mm/swapfile.c +1 -3
@@ -932,9 +932,7 @@ static inline int unuse_pmd_range(struct
 	pmd = pmd_offset(pud, addr);
 	do {
 		next = pmd_addr_end(addr, end);
-		if (unlikely(pmd_trans_huge(*pmd)))
-			continue;
-		if (pmd_none_or_clear_bad(pmd))
+		if (pmd_none_or_trans_huge_or_clear_bad(pmd))
 			continue;
 		ret = unuse_pte_range(vma, pmd, addr, next, entry, page);
 		if (ret)
author maintainer
#63 lore raw

PATCH 63/175 TPM: Zero buffer whole after copying to userspace

In reply to Greg KH

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

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

From: Tim Gardner <[email protected]>

commit 3ab1aff89477dafb1aaeafe8c8669114a02b7226 upstream.

Commit 3321c07ae5068568cd61ac9f4ba749006a7185c9 correctly clears the TPM buffer if the user specified read length is >= the TPM buffer length. However, if the user specified read length is < the TPM buffer length, then part of the TPM buffer is left uncleared.

---
 drivers/char/tpm/tpm.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/char/tpm/tpm.c +2 -1
@@ -1221,12 +1221,13 @@ ssize_t tpm_read(struct file *file, char
 	ret_size = atomic_read(&chip->data_pending);
 	atomic_set(&chip->data_pending, 0);
 	if (ret_size > 0) {	/* relay data */
+		ssize_t orig_ret_size = ret_size;
 		if (size < ret_size)
 			ret_size = size;
 
 		mutex_lock(&chip->buffer_mutex);
 		rc = copy_to_user(buf, chip->data_buffer, ret_size);
-		memset(chip->data_buffer, 0, ret_size);
+		memset(chip->data_buffer, 0, orig_ret_size);
 		if (rc)
 			ret_size = -EFAULT;
 
author maintainer
#64 lore raw

PATCH 64/175 PM / Domains: Fix handling of wakeup devices during system resume

In reply to Greg KH

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

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

From: "Rafael J. Wysocki" <[email protected]>

commit cc85b20780562d404e18a47b9b55b4a5102ae53e upstream.

During system suspend pm_genpd_suspend_noirq() checks if the given device is in a wakeup path (i.e. it appears to be needed for one or more wakeup devices to work or is a wakeup device itself) and if it needs to be "active" for wakeup to work. If that is the case, the function returns 0 without incrementing the device domain's counter of suspended devices and without executing genpd_stop_dev() for the device. In consequence, the device is not stopped (e.g. its clock isn't disabled) and power is always supplied to its domain in the resulting system sleep state.

However, pm_genpd_resume_noirq() doesn't repeat that check and it runs genpd_start_dev() and decrements the domain's counter of suspended devices even for the wakeup device that weren't stopped by pm_genpd_suspend_noirq(). As a result, the start callback may be run unnecessarily for them and their domains' counters of suspended devices may become negative. Both outcomes aren't desirable, so fix pm_genpd_resume_noirq() to look for wakeup devices that might not be stopped by during system suspend.

---
 drivers/base/power/domain.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/base/power/domain.c +2 -1
@@ -880,7 +880,8 @@ static int pm_genpd_resume_noirq(struct
 	if (IS_ERR(genpd))
 		return -EINVAL;
 
-	if (genpd->suspend_power_off)
+	if (genpd->suspend_power_off
+	    || (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev)))
 		return 0;
 
 	/*
author maintainer
#65 lore raw

PATCH 65/175 bootmem/sparsemem: remove limit constraint in alloc_bootmem_section

In reply to Greg KH

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

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

From: Nishanth Aravamudan <[email protected]>

commit f5bf18fa22f8c41a13eb8762c7373eb3a93a7333 upstream.

While testing AMS (Active Memory Sharing) / CMO (Cooperative Memory Overcommit) on powerpc, we tripped the following:

kernel BUG at mm/bootmem.c:483!
cpu 0x0: Vector: 700 (Program Check) at [c000000000c03940]

      pc: c000000000a62bd8: .alloc_bootmem_core+0x90/0x39c
      lr: c000000000a64bcc: .sparse_early_usemaps_alloc_node+0x84/0x29c
      sp: c000000000c03bc0
     msr: 8000000000021032
    current = 0xc000000000b0cce0
    paca    = 0xc000000001d80000
      pid   = 0, comm = swapper
  kernel BUG at mm/bootmem.c:483!
  enter ? for help
  [c000000000c03c80] c000000000a64bcc
  .sparse_early_usemaps_alloc_node+0x84/0x29c
  [c000000000c03d50] c000000000a64f10 .sparse_init+0x12c/0x28c
  [c000000000c03e20] c000000000a474f4 .setup_arch+0x20c/0x294
  [c000000000c03ee0] c000000000a4079c .start_kernel+0xb4/0x460
  [c000000000c03f90] c000000000009670 .start_here_common+0x1c/0x2c

This is

        BUG_ON(limit && goal + size > limit);

and after some debugging, it seems that

	goal = 0x7ffff000000
	limit = 0x80000000000

and sparse_early_usemaps_alloc_node ->
sparse_early_usemaps_alloc_pgdat_section calls

	return alloc_bootmem_section(usemap_size() * count, section_nr);

This is on a system with 8TB available via the AMS pool, and as a quirk of AMS in firmware, all of that memory shows up in node 0. So, we end up with an allocation that will fail the goal/limit constraints.

In theory, we could "fall-back" to alloc_bootmem_node() in sparse_early_usemaps_alloc_node(), but since we actually have HOTREMOVE defined, we'll BUG_ON() instead. A simple solution appears to be to unconditionally remove the limit condition in alloc_bootmem_section, meaning allocations are allowed to cross section boundaries (necessary for systems of this size).

Johannes Weiner pointed out that if alloc_bootmem_section() no longer guarantees section-locality, we need check_usemap_section_nr() to print possible cross-dependencies between node descriptors and the usemaps allocated through it. That makes the two loops in sparse_early_usemaps_alloc_node() identical, so re-factor the code a bit.

---
 mm/bootmem.c |    5 ++---
 mm/sparse.c  |   30 +++++++++++-------------------
 2 files changed, 13 insertions(+), 22 deletions(-)
mm/bootmem.c +2 -3
@@ -766,14 +766,13 @@ void * __init alloc_bootmem_section(unsi
 				    unsigned long section_nr)
 {
 	bootmem_data_t *bdata;
-	unsigned long pfn, goal, limit;
+	unsigned long pfn, goal;
 
 	pfn = section_nr_to_pfn(section_nr);
 	goal = pfn << PAGE_SHIFT;
-	limit = section_nr_to_pfn(section_nr + 1) << PAGE_SHIFT;
 	bdata = &bootmem_node_data[early_pfn_to_nid(pfn)];
 
-	return alloc_bootmem_core(bdata, size, SMP_CACHE_BYTES, goal, limit);
+	return alloc_bootmem_core(bdata, size, SMP_CACHE_BYTES, goal, 0);
 }
 #endif
 
mm/sparse.c +11 -19
@@ -353,29 +353,21 @@ static void __init sparse_early_usemaps_
 
 	usemap = sparse_early_usemaps_alloc_pgdat_section(NODE_DATA(nodeid),
 								 usemap_count);
-	if (usemap) {
-		for (pnum = pnum_begin; pnum < pnum_end; pnum++) {
-			if (!present_section_nr(pnum))
-				continue;
-			usemap_map[pnum] = usemap;
-			usemap += size;
+	if (!usemap) {
+		usemap = alloc_bootmem_node(NODE_DATA(nodeid), size * usemap_count);
+		if (!usemap) {
+			printk(KERN_WARNING "%s: allocation failed\n", __func__);
+			return;
 		}
-		return;
 	}
 
-	usemap = alloc_bootmem_node(NODE_DATA(nodeid), size * usemap_count);
-	if (usemap) {
-		for (pnum = pnum_begin; pnum < pnum_end; pnum++) {
-			if (!present_section_nr(pnum))
-				continue;
-			usemap_map[pnum] = usemap;
-			usemap += size;
-			check_usemap_section_nr(nodeid, usemap_map[pnum]);
-		}
-		return;
+	for (pnum = pnum_begin; pnum < pnum_end; pnum++) {
+		if (!present_section_nr(pnum))
+			continue;
+		usemap_map[pnum] = usemap;
+		usemap += size;
+		check_usemap_section_nr(nodeid, usemap_map[pnum]);
 	}
-
-	printk(KERN_WARNING "%s: allocation failed\n", __func__);
 }
 
 #ifndef CONFIG_SPARSEMEM_VMEMMAP
author maintainer
#66 lore raw

PATCH 66/175 hugetlbfs: avoid taking i_mutex from hugetlbfs_read()

In reply to Greg KH

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

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

From: "Aneesh Kumar K.V" <[email protected]>

commit a05b0855fd15504972dba2358e5faa172a1e50ba upstream.

Taking i_mutex in hugetlbfs_read() can result in deadlock with mmap as explained below

Thread A:
read() on hugetlbfs
hugetlbfs_read() called
i_mutex grabbed
hugetlbfs_read_actor() called
__copy_to_user() called
page fault is triggered
Thread B, sharing address space with A:
mmap() the same file
->mmap_sem is grabbed on task_B->mm->mmap_sem
hugetlbfs_file_mmap() is called
attempt to grab ->i_mutex and block waiting for A to give it up
Thread A:
pagefault handled blocked on attempt to grab task_A->mm->mmap_sem,
which happens to be the same thing as task_B->mm->mmap_sem. Block waiting for B to give it up.

AFAIU the i_mutex locking was added to hugetlbfs_read() as per
http://lkml.indiana.edu/hypermail/linux/kernel/0707.2/3066.html to take care of the race between truncate and read. This patch fixes this by looking at page->mapping under lock_page() (find_lock_page()) to ensure that the inode didn't get truncated in the range during a parallel read.

Ideally we can extend the patch to make sure we don't increase i_size in mmap. But that will break userspace, because applications will now have to use truncate(2) to increase i_size in hugetlbfs.

Based on the original patch from Hillf Danton.

---
 fs/hugetlbfs/inode.c |   25 +++++++++----------------
 1 file changed, 9 insertions(+), 16 deletions(-)
fs/hugetlbfs/inode.c +9 -16
@@ -238,17 +238,10 @@ static ssize_t hugetlbfs_read(struct fil
 	loff_t isize;
 	ssize_t retval = 0;
 
-	mutex_lock(&inode->i_mutex);
-
 	/* validate length */
 	if (len == 0)
 		goto out;
 
-	isize = i_size_read(inode);
-	if (!isize)
-		goto out;
-
-	end_index = (isize - 1) >> huge_page_shift(h);
 	for (;;) {
 		struct page *page;
 		unsigned long nr, ret;
@@ -256,18 +249,21 @@ static ssize_t hugetlbfs_read(struct fil
 
 		/* nr is the maximum number of bytes to copy from this page */
 		nr = huge_page_size(h);
+		isize = i_size_read(inode);
+		if (!isize)
+			goto out;
+		end_index = (isize - 1) >> huge_page_shift(h);
 		if (index >= end_index) {
 			if (index > end_index)
 				goto out;
 			nr = ((isize - 1) & ~huge_page_mask(h)) + 1;
-			if (nr <= offset) {
+			if (nr <= offset)
 				goto out;
-			}
 		}
 		nr = nr - offset;
 
 		/* Find the page */
-		page = find_get_page(mapping, index);
+		page = find_lock_page(mapping, index);
 		if (unlikely(page == NULL)) {
 			/*
 			 * We have a HOLE, zero out the user-buffer for the
@@ -279,17 +275,18 @@ static ssize_t hugetlbfs_read(struct fil
 			else
 				ra = 0;
 		} else {
+			unlock_page(page);
+
 			/*
 			 * We have the page, copy it to user space buffer.
 			 */
 			ra = hugetlbfs_read_actor(page, offset, buf, len, nr);
 			ret = ra;
+			page_cache_release(page);
 		}
 		if (ra < 0) {
 			if (retval == 0)
 				retval = ra;
-			if (page)
-				page_cache_release(page);
 			goto out;
 		}
 
@@ -299,16 +296,12 @@ static ssize_t hugetlbfs_read(struct fil
 		index += offset >> huge_page_shift(h);
 		offset &= ~huge_page_mask(h);
 
-		if (page)
-			page_cache_release(page);
-
 		/* short read or no more work */
 		if ((ret != nr) || (len == 0))
 			break;
 	}
 out:
 	*ppos = ((loff_t)index << huge_page_shift(h)) + offset;
-	mutex_unlock(&inode->i_mutex);
 	return retval;
 }
 
author maintainer
#67 lore raw

PATCH 67/175 ASoC: fsl: p1022ds: tell the WM8776 codec driver that its the master

In reply to Greg KH

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

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

From: Timur Tabi <[email protected]>

commit 70ac07bb633dee75ac554195b9a4d69adfa7803c upstream.

The WM8776 codec driver requires the machine driver to set one of the SND_SOC_DAIFMT_CBx_xxx values. The P1022DS machine driver should be setting SND_SOC_DAIFMT_CBM_CFM, but since that value was zero, no one noticed.

Commit 75d9ac46 ("ASoC: Allow DAI formats to be specified in the dai_link"), however, changed the value of SND_SOC_DAIFMT_CBM_CFM from zero to a non-zero value, which means that it now needs to be specifically set by the machine driver.

We also set SND_SOC_DAIFMT_NB_NF, for the same reason.

---
 sound/soc/fsl/p1022_ds.c |   24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)
sound/soc/fsl/p1022_ds.c +16 -8
@@ -395,7 +395,8 @@ static int p1022_ds_probe(struct platfor
 	}
 
 	if (strcasecmp(sprop, "i2s-slave") == 0) {
-		mdata->dai_format = SND_SOC_DAIFMT_I2S;
+		mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM;
 		mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
 		mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
 
@@ -412,31 +413,38 @@ static int p1022_ds_probe(struct platfor
 		}
 		mdata->clk_frequency = be32_to_cpup(iprop);
 	} else if (strcasecmp(sprop, "i2s-master") == 0) {
-		mdata->dai_format = SND_SOC_DAIFMT_I2S;
+		mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS;
 		mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
 		mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
 	} else if (strcasecmp(sprop, "lj-slave") == 0) {
-		mdata->dai_format = SND_SOC_DAIFMT_LEFT_J;
+		mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM;
 		mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
 		mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
 	} else if (strcasecmp(sprop, "lj-master") == 0) {
-		mdata->dai_format = SND_SOC_DAIFMT_LEFT_J;
+		mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBS_CFS;
 		mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
 		mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
 	} else if (strcasecmp(sprop, "rj-slave") == 0) {
-		mdata->dai_format = SND_SOC_DAIFMT_RIGHT_J;
+		mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBM_CFM;
 		mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
 		mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
 	} else if (strcasecmp(sprop, "rj-master") == 0) {
-		mdata->dai_format = SND_SOC_DAIFMT_RIGHT_J;
+		mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBS_CFS;
 		mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
 		mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
 	} else if (strcasecmp(sprop, "ac97-slave") == 0) {
-		mdata->dai_format = SND_SOC_DAIFMT_AC97;
+		mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBM_CFM;
 		mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
 		mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
 	} else if (strcasecmp(sprop, "ac97-master") == 0) {
-		mdata->dai_format = SND_SOC_DAIFMT_AC97;
+		mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBS_CFS;
 		mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
 		mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
 	} else {
author maintainer
#68 lore raw

PATCH 68/175 ASoC: pxa-ssp: atomically set stream active masks

In reply to Greg KH

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

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

From: Daniel Mack <[email protected]>

commit 273b72c8ce6b28df6b49423d775c3e59072c73c5 upstream.

PXA's SSP engine fails to take its current channel phase into account when enabling a stream while the engine is already running. This results in randomly swapped left/right channels on either the record or the playback side, depending on which one was enabled first.

The following patch fixes this by factoring out the bit field modifications in question to a separate function that pauses the engine temporarily, modifies the bits and kicks it off again afterwards. Appearantly, a transition of SSCR0_SSE syncs both directions properly.

The patch has been rolled out to quite a number of devices over the last weeks and seems to fix the issue reliably.

---
 sound/soc/pxa/pxa-ssp.c |   61 ++++++++++++++++++++++++++++--------------------
 1 file changed, 36 insertions(+), 25 deletions(-)
sound/soc/pxa/pxa-ssp.c +36 -25
@@ -668,6 +668,38 @@ static int pxa_ssp_hw_params(struct snd_
 	return 0;
 }
 
+static void pxa_ssp_set_running_bit(struct snd_pcm_substream *substream,
+				    struct ssp_device *ssp, int value)
+{
+	uint32_t sscr0 = pxa_ssp_read_reg(ssp, SSCR0);
+	uint32_t sscr1 = pxa_ssp_read_reg(ssp, SSCR1);
+	uint32_t sspsp = pxa_ssp_read_reg(ssp, SSPSP);
+	uint32_t sssr = pxa_ssp_read_reg(ssp, SSSR);
+
+	if (value && (sscr0 & SSCR0_SSE))
+		pxa_ssp_write_reg(ssp, SSCR0, sscr0 & ~SSCR0_SSE);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		if (value)
+			sscr1 |= SSCR1_TSRE;
+		else
+			sscr1 &= ~SSCR1_TSRE;
+	} else {
+		if (value)
+			sscr1 |= SSCR1_RSRE;
+		else
+			sscr1 &= ~SSCR1_RSRE;
+	}
+
+	pxa_ssp_write_reg(ssp, SSCR1, sscr1);
+
+	if (value) {
+		pxa_ssp_write_reg(ssp, SSSR, sssr);
+		pxa_ssp_write_reg(ssp, SSPSP, sspsp);
+		pxa_ssp_write_reg(ssp, SSCR0, sscr0 | SSCR0_SSE);
+	}
+}
+
 static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
 			   struct snd_soc_dai *cpu_dai)
 {
@@ -681,42 +713,21 @@ static int pxa_ssp_trigger(struct snd_pc
 		pxa_ssp_enable(ssp);
 		break;
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		val = pxa_ssp_read_reg(ssp, SSCR1);
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-			val |= SSCR1_TSRE;
-		else
-			val |= SSCR1_RSRE;
-		pxa_ssp_write_reg(ssp, SSCR1, val);
+		pxa_ssp_set_running_bit(substream, ssp, 1);
 		val = pxa_ssp_read_reg(ssp, SSSR);
 		pxa_ssp_write_reg(ssp, SSSR, val);
 		break;
 	case SNDRV_PCM_TRIGGER_START:
-		val = pxa_ssp_read_reg(ssp, SSCR1);
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-			val |= SSCR1_TSRE;
-		else
-			val |= SSCR1_RSRE;
-		pxa_ssp_write_reg(ssp, SSCR1, val);
-		pxa_ssp_enable(ssp);
+		pxa_ssp_set_running_bit(substream, ssp, 1);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
-		val = pxa_ssp_read_reg(ssp, SSCR1);
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-			val &= ~SSCR1_TSRE;
-		else
-			val &= ~SSCR1_RSRE;
-		pxa_ssp_write_reg(ssp, SSCR1, val);
+		pxa_ssp_set_running_bit(substream, ssp, 0);
 		break;
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 		pxa_ssp_disable(ssp);
 		break;
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		val = pxa_ssp_read_reg(ssp, SSCR1);
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-			val &= ~SSCR1_TSRE;
-		else
-			val &= ~SSCR1_RSRE;
-		pxa_ssp_write_reg(ssp, SSCR1, val);
+		pxa_ssp_set_running_bit(substream, ssp, 0);
 		break;
 
 	default:
author maintainer
#69 lore raw

PATCH 69/175 tcm_loop: Set residual field for SCSI commands

In reply to Greg KH

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

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

From: Roland Dreier <[email protected]>

commit 6cf3fa6918baab0c447f1206f1cef9166ad04864 upstream.

If the target core signals an over- or under-run, tcm_loop should call scsi_set_resid() to tell the SCSI midlayer about the residual data length.

The difference can be seen by doing something like

    strace -eioctl sg_raw -r 1024 /dev/sda 8 0 0 0 1 0 > /dev/null

and looking at the "resid=" part of the SG_IO ioctl -- after this patch, the field is correctly reported as 512.

---
 drivers/target/loopback/tcm_loop.c |    6 ++++++
 1 file changed, 6 insertions(+)
drivers/target/loopback/tcm_loop.c +6 -0
@@ -855,6 +855,9 @@ static int tcm_loop_queue_data_in(struct
 
 	sc->result = SAM_STAT_GOOD;
 	set_host_byte(sc, DID_OK);
+	if ((se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) ||
+	    (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT))
+		scsi_set_resid(sc, se_cmd->residual_count);
 	sc->scsi_done(sc);
 	return 0;
 }
@@ -880,6 +883,9 @@ static int tcm_loop_queue_status(struct
 		sc->result = se_cmd->scsi_status;
 
 	set_host_byte(sc, DID_OK);
+	if ((se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) ||
+	    (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT))
+		scsi_set_resid(sc, se_cmd->residual_count);
 	sc->scsi_done(sc);
 	return 0;
 }
author maintainer
#70 lore raw

PATCH 70/175 SCSI: iscsi: fix setting of pid from netlink skb

In reply to Greg KH

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

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

From: Mike Christie <[email protected]>

commit df1c7baba1b7b3053950f3845a6575aca47ba9ce upstream.

NETLINK_CREDS's pid now returns 0, so I guess we are supposed to be using NETLINK_CB. This changed while the patch to export the pid was getting merged upstream, so it was not noticed until both the network and iscsi changes were in the same tree.

---
 drivers/scsi/scsi_transport_iscsi.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/scsi/scsi_transport_iscsi.c +2 -2
@@ -1941,7 +1941,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, s
 	switch (nlh->nlmsg_type) {
 	case ISCSI_UEVENT_CREATE_SESSION:
 		err = iscsi_if_create_session(priv, ep, ev,
-					      NETLINK_CREDS(skb)->pid,
+					      NETLINK_CB(skb).pid,
 					      ev->u.c_session.initial_cmdsn,
 					      ev->u.c_session.cmds_max,
 					      ev->u.c_session.queue_depth);
@@ -1954,7 +1954,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, s
 		}
 
 		err = iscsi_if_create_session(priv, ep, ev,
-					NETLINK_CREDS(skb)->pid,
+					NETLINK_CB(skb).pid,
 					ev->u.c_bound_session.initial_cmdsn,
 					ev->u.c_bound_session.cmds_max,
 					ev->u.c_bound_session.queue_depth);
author maintainer
#71 lore raw

PATCH 71/175 iscsi-target: Fix iscsit_alloc_buffs() failure cases

In reply to Greg KH

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

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

From: Nicholas Bellinger <[email protected]>

commit d335e6054db616bce3f040e659fa38440518ad1d upstream.

Make iscsit_alloc_buffs() failure case for page_alloc_failed use correct __free_page() SGL pointer, and return -ENOMEM for iscsit_allocate_iovecs failure to push se_cmd->t_mem_sg release into iscsit_release_cmd() callback during iscsit_add_reject_from_cmd() connection reset.

Also drop cmd->t_mem_sg = NULL assignment from page_alloc_failed failure case.

---
 drivers/target/iscsi/iscsi_target.c |   14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)
drivers/target/iscsi/iscsi_target.c +6 -8
@@ -780,7 +780,7 @@ static int iscsit_alloc_buffs(struct isc
 	struct scatterlist *sgl;
 	u32 length = cmd->se_cmd.data_length;
 	int nents = DIV_ROUND_UP(length, PAGE_SIZE);
-	int i = 0, ret;
+	int i = 0, j = 0, ret;
 	/*
 	 * If no SCSI payload is present, allocate the default iovecs used for
 	 * iSCSI PDU Header
@@ -821,17 +821,15 @@ static int iscsit_alloc_buffs(struct isc
 	 */
         ret = iscsit_allocate_iovecs(cmd);
         if (ret < 0)
-		goto page_alloc_failed;
+		return -ENOMEM;
 
 	return 0;
 
 page_alloc_failed:
-	while (i >= 0) {
-		__free_page(sg_page(&sgl[i]));
-		i--;
-	}
-	kfree(cmd->t_mem_sg);
-	cmd->t_mem_sg = NULL;
+	while (j < i)
+		__free_page(sg_page(&sgl[j++]));
+
+	kfree(sgl);
 	return -ENOMEM;
 }
 
author maintainer
#72 lore raw

PATCH 72/175 iscsi-target: Fix dynamic -> explict NodeACL pointer reference

In reply to Greg KH

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

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

From: Nicholas Bellinger <[email protected]>

commit d06283341aee9e48eff1b068779d340785c635ce upstream.

This patch fixes a free after use in lio_target_make_nodeacl() where iscsi_node_acl was referenced from the original se_nacl_new allocation, instead of from core_tpg_add_initiator_node_acl() in the case of dynamic -> explict NodeACL conversion.

---
 drivers/target/iscsi/iscsi_target_configfs.c |    6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/target/iscsi/iscsi_target_configfs.c +2 -4
@@ -812,9 +812,6 @@ static struct se_node_acl *lio_target_ma
 	if (!se_nacl_new)
 		return ERR_PTR(-ENOMEM);
 
-	acl = container_of(se_nacl_new, struct iscsi_node_acl,
-				se_node_acl);
-
 	cmdsn_depth = ISCSI_TPG_ATTRIB(tpg)->default_cmdsn_depth;
 	/*
 	 * se_nacl_new may be released by core_tpg_add_initiator_node_acl()
@@ -825,7 +822,8 @@ static struct se_node_acl *lio_target_ma
 	if (IS_ERR(se_nacl))
 		return se_nacl;
 
-	stats_cg = &acl->se_node_acl.acl_fabric_stat_group;
+	acl = container_of(se_nacl, struct iscsi_node_acl, se_node_acl);
+	stats_cg = &se_nacl->acl_fabric_stat_group;
 
 	stats_cg->default_groups = kzalloc(sizeof(struct config_group) * 2,
 				GFP_KERNEL);
author maintainer
#73 lore raw

PATCH 73/175 ALSA: hda - fix printing of high HDMI sample rates

In reply to Greg KH

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

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

From: Anssi Hannula <[email protected]>

commit 25dc16f69892182192b1234594fd3cf342ad4195 upstream.

A previous commit af65cbf296 (ALSA: hdmi: fix printout of SAD sampling rates) fixed the sample rates shown in /proc/asound/cardX/eldY and kernel log to not be entirely wrong. However, a missing rate from the array added in the patch causes HDMI rates 88.2 kHz, 96 kHz, 176.4 kHz, and 192 kHz to be shown as 96 kHz, 176.4 kHz, 192 kHz, and 384 kHz, respectively.

Fix the reporting by adding the ALSA rate 64 kHz into the conversion array between 48 kHz and 88.2 kHz.

---
 sound/pci/hda/hda_eld.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
sound/pci/hda/hda_eld.c +2 -2
@@ -385,8 +385,8 @@ error:
 static void hdmi_print_pcm_rates(int pcm, char *buf, int buflen)
 {
 	static unsigned int alsa_rates[] = {
-		5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
-		96000, 176400, 192000, 384000
+		5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
+		88200, 96000, 176400, 192000, 384000
 	};
 	int i, j;
 
author maintainer
#74 lore raw

PATCH 74/175 usb gadget: fix a section mismatch when compiling g_ffs with CONFIG_USB_FUNCTIONFS_ETH

In reply to Greg KH

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

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

From: Lothar Waßmann <[email protected]>

commit 8d0698428822ce63f7269e7fe81fc4580807b9ac upstream.

commit 28824b18ac4705e876a282a15ea0de8fc957551f:

 |Author: Michal Nazarewicz <[email protected]>
 |Date:   Wed May 5 12:53:13 2010 +0200
 |
 |    USB: gadget: __init and __exit tags removed
 |
 |    __init, __initdata and __exit tags have have been removed from
 |    various files to make it possible for gadgets that do not use
 |    the __init/__exit tags to use those.

obviously missed (at least) this case leading to a section mismatch in g_ffs.c when compiling with CONFIG_USB_FUNCTIONFS_ETH enabled.

---
 drivers/usb/gadget/f_subset.c |   34 +++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 17 deletions(-)
drivers/usb/gadget/f_subset.c +17 -17
@@ -74,7 +74,7 @@ static inline struct f_gether *func_to_g
 
 /* interface descriptor: */
 
-static struct usb_interface_descriptor subset_data_intf __initdata = {
+static struct usb_interface_descriptor subset_data_intf = {
 	.bLength =		sizeof subset_data_intf,
 	.bDescriptorType =	USB_DT_INTERFACE,
 
@@ -87,7 +87,7 @@ static struct usb_interface_descriptor s
 	/* .iInterface = DYNAMIC */
 };
 
-static struct usb_cdc_header_desc mdlm_header_desc __initdata = {
+static struct usb_cdc_header_desc mdlm_header_desc = {
 	.bLength =		sizeof mdlm_header_desc,
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
@@ -95,7 +95,7 @@ static struct usb_cdc_header_desc mdlm_h
 	.bcdCDC =		cpu_to_le16(0x0110),
 };
 
-static struct usb_cdc_mdlm_desc mdlm_desc __initdata = {
+static struct usb_cdc_mdlm_desc mdlm_desc = {
 	.bLength =		sizeof mdlm_desc,
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubType =	USB_CDC_MDLM_TYPE,
@@ -111,7 +111,7 @@ static struct usb_cdc_mdlm_desc mdlm_des
  * can't really use its struct.  All we do here is say that we're using
  * the submode of "SAFE" which directly matches the CDC Subset.
  */
-static u8 mdlm_detail_desc[] __initdata = {
+static u8 mdlm_detail_desc[] = {
 	6,
 	USB_DT_CS_INTERFACE,
 	USB_CDC_MDLM_DETAIL_TYPE,
@@ -121,7 +121,7 @@ static u8 mdlm_detail_desc[] __initdata
 	0,	/* network data capabilities ("raw" encapsulation) */
 };
 
-static struct usb_cdc_ether_desc ether_desc __initdata = {
+static struct usb_cdc_ether_desc ether_desc = {
 	.bLength =		sizeof ether_desc,
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubType =	USB_CDC_ETHERNET_TYPE,
@@ -136,7 +136,7 @@ static struct usb_cdc_ether_desc ether_d
 
 /* full speed support: */
 
-static struct usb_endpoint_descriptor fs_subset_in_desc __initdata = {
+static struct usb_endpoint_descriptor fs_subset_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -144,7 +144,7 @@ static struct usb_endpoint_descriptor fs
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 };
 
-static struct usb_endpoint_descriptor fs_subset_out_desc __initdata = {
+static struct usb_endpoint_descriptor fs_subset_out_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -152,7 +152,7 @@ static struct usb_endpoint_descriptor fs
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 };
 
-static struct usb_descriptor_header *fs_eth_function[] __initdata = {
+static struct usb_descriptor_header *fs_eth_function[] = {
 	(struct usb_descriptor_header *) &subset_data_intf,
 	(struct usb_descriptor_header *) &mdlm_header_desc,
 	(struct usb_descriptor_header *) &mdlm_desc,
@@ -165,7 +165,7 @@ static struct usb_descriptor_header *fs_
 
 /* high speed support: */
 
-static struct usb_endpoint_descriptor hs_subset_in_desc __initdata = {
+static struct usb_endpoint_descriptor hs_subset_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -173,7 +173,7 @@ static struct usb_endpoint_descriptor hs
 	.wMaxPacketSize =	cpu_to_le16(512),
 };
 
-static struct usb_endpoint_descriptor hs_subset_out_desc __initdata = {
+static struct usb_endpoint_descriptor hs_subset_out_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -181,7 +181,7 @@ static struct usb_endpoint_descriptor hs
 	.wMaxPacketSize =	cpu_to_le16(512),
 };
 
-static struct usb_descriptor_header *hs_eth_function[] __initdata = {
+static struct usb_descriptor_header *hs_eth_function[] = {
 	(struct usb_descriptor_header *) &subset_data_intf,
 	(struct usb_descriptor_header *) &mdlm_header_desc,
 	(struct usb_descriptor_header *) &mdlm_desc,
@@ -194,7 +194,7 @@ static struct usb_descriptor_header *hs_
 
 /* super speed support: */
 
-static struct usb_endpoint_descriptor ss_subset_in_desc __initdata = {
+static struct usb_endpoint_descriptor ss_subset_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -202,7 +202,7 @@ static struct usb_endpoint_descriptor ss
 	.wMaxPacketSize =	cpu_to_le16(1024),
 };
 
-static struct usb_endpoint_descriptor ss_subset_out_desc __initdata = {
+static struct usb_endpoint_descriptor ss_subset_out_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -210,7 +210,7 @@ static struct usb_endpoint_descriptor ss
 	.wMaxPacketSize =	cpu_to_le16(1024),
 };
 
-static struct usb_ss_ep_comp_descriptor ss_subset_bulk_comp_desc __initdata = {
+static struct usb_ss_ep_comp_descriptor ss_subset_bulk_comp_desc = {
 	.bLength =		sizeof ss_subset_bulk_comp_desc,
 	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
 
@@ -219,7 +219,7 @@ static struct usb_ss_ep_comp_descriptor
 	/* .bmAttributes =	0, */
 };
 
-static struct usb_descriptor_header *ss_eth_function[] __initdata = {
+static struct usb_descriptor_header *ss_eth_function[] = {
 	(struct usb_descriptor_header *) &subset_data_intf,
 	(struct usb_descriptor_header *) &mdlm_header_desc,
 	(struct usb_descriptor_header *) &mdlm_desc,
@@ -290,7 +290,7 @@ static void geth_disable(struct usb_func
 
 /* serial function driver setup/binding */
 
-static int __init
+static int
 geth_bind(struct usb_configuration *c, struct usb_function *f)
 {
 	struct usb_composite_dev *cdev = c->cdev;
@@ -404,7 +404,7 @@ geth_unbind(struct usb_configuration *c,
  * Caller must have called @gether_setup().  Caller is also responsible
  * for calling @gether_cleanup() before module unload.
  */
-int __init geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 {
 	struct f_gether	*geth;
 	int		status;
author maintainer
#75 lore raw

PATCH 75/175 gma500: Fix mmap frambuffer

In reply to Greg KH

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

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

From: Yoichi Yuasa <[email protected]>

commit 1278f7de7fa5606ed513a5271f7fb63910ef1b8b upstream.

It cannot map correctly if page fault begins from a intermediate address.

[The driver prefaults the mapping, so we need to work from the correct
base address not the faulting address otherwise the map appears offset by the fault offset]

---
 drivers/gpu/drm/gma500/framebuffer.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/gma500/framebuffer.c +1 -1
@@ -158,7 +158,7 @@ static int psbfb_vm_fault(struct vm_area
 	unsigned long phys_addr = (unsigned long)dev_priv->stolen_base;
 
 	page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
-	address = (unsigned long)vmf->virtual_address;
+	address = (unsigned long)vmf->virtual_address - (vmf->pgoff << PAGE_SHIFT);
 
 	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 
author maintainer
#76 lore raw

PATCH 76/175 udlfb: remove sysfs framebuffer device with USB .disconnect()

In reply to Greg KH

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

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

From: Kay Sievers <[email protected]>

commit ce880cb860f36694d2cdebfac9e6ae18176fe4c4 upstream.

The USB graphics card driver delays the unregistering of the framebuffer device to a workqueue, which breaks the userspace visible remove uevent sequence. Recent userspace tools started to support USB graphics card hotplug out-of-the-box and rely on proper events sent by the kernel.

The framebuffer device is a direct child of the USB interface which is removed immediately after the USB .disconnect() callback. But the fb device in /sys stays around until its final cleanup, at a time where all the parent devices have been removed already.

To work around that, we remove the sysfs fb device directly in the USB .disconnect() callback and leave only the cleanup of the internal fb data to the delayed work.

Before:

 add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2 (usb)
 add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0 (usb)
 add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/graphics/fb0 (graphics)
 remove   /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0 (usb)
 remove   /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2 (usb)
 remove   /2-1.2:1.0/graphics/fb0 (graphics)

After:

 add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2 (usb)
 add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0 (usb)
 add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/graphics/fb1 (graphics)
 remove   /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/graphics/fb1 (graphics)
 remove   /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0 (usb)
 remove   /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2 (usb)
---
 drivers/video/fbmem.c |   18 +++++++++++++++++-
 drivers/video/udlfb.c |    2 +-
 include/linux/fb.h    |    1 +
 3 files changed, 19 insertions(+), 2 deletions(-)
drivers/video/fbmem.c +17 -1
@@ -1665,6 +1665,7 @@ static int do_unregister_framebuffer(str
 	if (ret)
 		return -EINVAL;
 
+	unlink_framebuffer(fb_info);
 	if (fb_info->pixmap.addr &&
 	    (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
 		kfree(fb_info->pixmap.addr);
@@ -1672,7 +1673,6 @@ static int do_unregister_framebuffer(str
 	registered_fb[i] = NULL;
 	num_registered_fb--;
 	fb_cleanup_device(fb_info);
-	device_destroy(fb_class, MKDEV(FB_MAJOR, i));
 	event.info = fb_info;
 	fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
 
@@ -1681,6 +1681,22 @@ static int do_unregister_framebuffer(str
 	return 0;
 }
 
+int unlink_framebuffer(struct fb_info *fb_info)
+{
+	int i;
+
+	i = fb_info->node;
+	if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)
+		return -EINVAL;
+
+	if (fb_info->dev) {
+		device_destroy(fb_class, MKDEV(FB_MAJOR, i));
+		fb_info->dev = NULL;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(unlink_framebuffer);
+
 void remove_conflicting_framebuffers(struct apertures_struct *a,
 				     const char *name, bool primary)
 {
drivers/video/udlfb.c +1 -1
@@ -1739,7 +1739,7 @@ static void dlfb_usb_disconnect(struct u
 	for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++)
 		device_remove_file(info->dev, &fb_device_attrs[i]);
 	device_remove_bin_file(info->dev, &edid_attr);
-
+	unlink_framebuffer(info);
 	usb_set_intfdata(interface, NULL);
 
 	/* if clients still have us open, will be freed on last close */
include/linux/fb.h +1 -0
@@ -1003,6 +1003,7 @@ extern ssize_t fb_sys_write(struct fb_in
 /* drivers/video/fbmem.c */
 extern int register_framebuffer(struct fb_info *fb_info);
 extern int unregister_framebuffer(struct fb_info *fb_info);
+extern int unlink_framebuffer(struct fb_info *fb_info);
 extern void remove_conflicting_framebuffers(struct apertures_struct *a,
 				const char *name, bool primary);
 extern int fb_prepare_logo(struct fb_info *fb_info, int rotate);
author maintainer
#77 lore raw

PATCH 77/175 tcm_fc: Fix fc_exch memory leak in ft_send_resp_status

In reply to Greg KH

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

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

From: Nicholas Bellinger <[email protected]>

commit 031ed4d565b31880a4136bb7366bc89f5b1dba7d upstream.

This patch fixes a bug in tcm_fc where fc_exch memory from fc_exch_mgr->ep_pool is currently being leaked by ft_send_resp_status() usage. Following current code in ft_queue_status() response path, using lport->tt.seq_send() needs to be followed by a lport->tt.exch_done() in order to release fc_exch memory back into libfc_em kmem_cache.

ft_send_resp_status() code is currently used in pre submit se_cmd ft_send_work() error exceptions, TM request setup exceptions, and main TM response callback path in ft_queue_tm_resp(). This bugfix addresses the leak in these cases.

---
 drivers/target/tcm_fc/tfc_cmd.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/target/tcm_fc/tfc_cmd.c +4 -2
@@ -325,10 +325,12 @@ static void ft_send_resp_status(struct f
 
 	fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_DD_CMD_STATUS, 0);
 	sp = fr_seq(fp);
-	if (sp)
+	if (sp) {
 		lport->tt.seq_send(lport, sp, fp);
-	else
+		lport->tt.exch_done(sp);
+	} else {
 		lport->tt.frame_send(lport, fp);
+	}
 }
 
 /*
author maintainer
#78 lore raw

PATCH 78/175 ib_srpt: Fix srpt_handle_cmd send_ioctx->ioctx_kref leak on exception

In reply to Greg KH

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

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

From: Nicholas Bellinger <[email protected]>

commit 187e70a554e0f0717a65998bc9199945cbbd4692 upstream.

This patch addresses a bug in srpt_handle_cmd() failure handling where send_ioctx->kref is being leaked with the local extra reference after init, causing the expected kref_put() in srpt_handle_send_comp() to not be the final call to invoke srpt_put_send_ioctx_kref() -> transport_generic_free_cmd() and perform se_cmd descriptor memory release.

It also fixes a SCF_SCSI_RESERVATION_CONFLICT handling bug where this code is incorrectly falling through to transport_handle_cdb_direct() after invoking srpt_queue_status() to send SAM_STAT_RESERVATION_CONFLICT status.

Note this patch is for >= v3.3 mainline code, and current lio-core.git code has already been converted to target_submit_cmd() + se_cmd->cmd_kref usage, and internal ioctx->kref usage has been removed. I'm including this patch now into target-pending/for-next with a CC' for v3.3 stable.

---
 drivers/infiniband/ulp/srpt/ib_srpt.c |   19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)
drivers/infiniband/ulp/srpt/ib_srpt.c +12 -7
@@ -1750,6 +1750,7 @@ static int srpt_handle_cmd(struct srpt_r
 		       srp_cmd->tag);
 		cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
 		cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
+		kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref);
 		goto send_sense;
 	}
 
@@ -1757,15 +1758,19 @@ static int srpt_handle_cmd(struct srpt_r
 	cmd->data_direction = dir;
 	unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_cmd->lun,
 				       sizeof(srp_cmd->lun));
-	if (transport_lookup_cmd_lun(cmd, unpacked_lun) < 0)
+	if (transport_lookup_cmd_lun(cmd, unpacked_lun) < 0) {
+		kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref);
 		goto send_sense;
+	}
 	ret = transport_generic_allocate_tasks(cmd, srp_cmd->cdb);
-	if (cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT)
-		srpt_queue_status(cmd);
-	else if (cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION)
-		goto send_sense;
-	else
-		WARN_ON_ONCE(ret);
+	if (ret < 0) {
+		kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref);
+		if (cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT) {
+			srpt_queue_status(cmd);
+			return 0;
+		} else
+			goto send_sense;
+	}
 
 	transport_handle_cdb_direct(cmd);
 	return 0;
author maintainer
#79 lore raw

PATCH 79/175 md/bitmap: ensure to load bitmap when creating via sysfs.

In reply to Greg KH

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

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

From: NeilBrown <[email protected]>

commit 4474ca42e2577563a919fd3ed782e2ec55bf11a2 upstream.

When commit 69e51b449d383e (md/bitmap: separate out loading a bitmap...) created bitmap_load, it missed calling it after bitmap_create when a bitmap is created through the sysfs interface.
So if a bitmap is added this way, we don't allocate memory properly and can crash.

This is suitable for any -stable release since 2.6.35.

---
 drivers/md/bitmap.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/md/bitmap.c +2 -0
@@ -1904,6 +1904,8 @@ location_store(struct mddev *mddev, cons
 			if (mddev->pers) {
 				mddev->pers->quiesce(mddev, 1);
 				rv = bitmap_create(mddev);
+				if (!rv)
+					rv = bitmap_load(mddev);
 				if (rv) {
 					bitmap_destroy(mddev);
 					mddev->bitmap_info.offset = 0;
author maintainer
#80 lore raw

PATCH 80/175 md: dont set md arrays to readonly on shutdown.

In reply to Greg KH

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

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

From: NeilBrown <[email protected]>

commit c744a65c1e2d59acc54333ce80a5b0702a98010b upstream.

It seems that with recent kernel, writeback can still be happening while shutdown is happening, and consequently data can be written after the md reboot notifier switches all arrays to read-only. This causes a BUG.

So don't switch them to read-only - just mark them clean and set 'safemode' to '2' which mean that immediately after any write the array will be switch back to 'clean'.

This could result in the shutdown happening when array is marked dirty, thus forcing a resync on reboot. However if you reboot without performing a "sync" first, you get to keep both halves.

This is suitable for any stable kernel (though there might be some conflicts with obvious fixes in earlier kernels).

---
 drivers/md/md.c |   37 +++++++++++++++----------------------
 1 file changed, 15 insertions(+), 22 deletions(-)
drivers/md/md.c +15 -22
@@ -8157,30 +8157,23 @@ static int md_notify_reboot(struct notif
 	struct mddev *mddev;
 	int need_delay = 0;
 
-	if ((code == SYS_DOWN) || (code == SYS_HALT) || (code == SYS_POWER_OFF)) {
-
-		printk(KERN_INFO "md: stopping all md devices.\n");
-
-		for_each_mddev(mddev, tmp) {
-			if (mddev_trylock(mddev)) {
-				/* Force a switch to readonly even array
-				 * appears to still be in use.  Hence
-				 * the '100'.
-				 */
-				md_set_readonly(mddev, 100);
-				mddev_unlock(mddev);
-			}
-			need_delay = 1;
+	for_each_mddev(mddev, tmp) {
+		if (mddev_trylock(mddev)) {
+			__md_stop_writes(mddev);
+			mddev->safemode = 2;
+			mddev_unlock(mddev);
 		}
-		/*
-		 * certain more exotic SCSI devices are known to be
-		 * volatile wrt too early system reboots. While the
-		 * right place to handle this issue is the given
-		 * driver, we do want to have a safe RAID driver ...
-		 */
-		if (need_delay)
-			mdelay(1000*1);
+		need_delay = 1;
 	}
+	/*
+	 * certain more exotic SCSI devices are known to be
+	 * volatile wrt too early system reboots. While the
+	 * right place to handle this issue is the given
+	 * driver, we do want to have a safe RAID driver ...
+	 */
+	if (need_delay)
+		mdelay(1000*1);
+
 	return NOTIFY_DONE;
 }
 
author maintainer
#81 lore raw

PATCH 81/175 md/raid1,raid10: avoid deadlock during resync/recovery.

In reply to Greg KH

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

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

From: NeilBrown <[email protected]>

commit d6b42dcb995e6acd7cc276774e751ffc9f0ef4bf upstream.

If RAID1 or RAID10 is used under LVM or some other stacking block device, it is possible to enter a deadlock during resync or recovery.
This can happen if the upper level block device creates two requests to the RAID1 or RAID10. The first request gets processed, blocks recovery and queue requests for underlying requests in current->bio_list. A resync request then starts which will wait for those requests and block new IO.

But then the second request to the RAID1/10 will be attempted and it cannot progress until the resync request completes, which cannot progress until the underlying device requests complete, which are on a queue behind that second request.

So allow that second request to proceed even though there is a resync request about to start.

This is suitable for any -stable kernel.

---
 drivers/md/raid1.c  |   17 +++++++++++++++--
 drivers/md/raid10.c |   17 +++++++++++++++--
 2 files changed, 30 insertions(+), 4 deletions(-)
drivers/md/raid1.c +15 -2
@@ -737,9 +737,22 @@ static void wait_barrier(struct r1conf *
 	spin_lock_irq(&conf->resync_lock);
 	if (conf->barrier) {
 		conf->nr_waiting++;
-		wait_event_lock_irq(conf->wait_barrier, !conf->barrier,
+		/* Wait for the barrier to drop.
+		 * However if there are already pending
+		 * requests (preventing the barrier from
+		 * rising completely), and the
+		 * pre-process bio queue isn't empty,
+		 * then don't wait, as we need to empty
+		 * that queue to get the nr_pending
+		 * count down.
+		 */
+		wait_event_lock_irq(conf->wait_barrier,
+				    !conf->barrier ||
+				    (conf->nr_pending &&
+				     current->bio_list &&
+				     !bio_list_empty(current->bio_list)),
 				    conf->resync_lock,
-				    );
+			);
 		conf->nr_waiting--;
 	}
 	conf->nr_pending++;
drivers/md/raid10.c +15 -2
@@ -863,9 +863,22 @@ static void wait_barrier(struct r10conf
 	spin_lock_irq(&conf->resync_lock);
 	if (conf->barrier) {
 		conf->nr_waiting++;
-		wait_event_lock_irq(conf->wait_barrier, !conf->barrier,
+		/* Wait for the barrier to drop.
+		 * However if there are already pending
+		 * requests (preventing the barrier from
+		 * rising completely), and the
+		 * pre-process bio queue isn't empty,
+		 * then don't wait, as we need to empty
+		 * that queue to get the nr_pending
+		 * count down.
+		 */
+		wait_event_lock_irq(conf->wait_barrier,
+				    !conf->barrier ||
+				    (conf->nr_pending &&
+				     current->bio_list &&
+				     !bio_list_empty(current->bio_list)),
 				    conf->resync_lock,
-				    );
+			);
 		conf->nr_waiting--;
 	}
 	conf->nr_pending++;
author maintainer
#82 lore raw

PATCH 82/175 md: fix clearing of the changed flags for the bad blocks list.

In reply to Greg KH

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

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

From: NeilBrown <[email protected]>

commit d0962936bff659d20522555b517582a2715fd23f upstream.

In super_1_sync (the first hunk) we need to clear 'changed' before checking read_seqretry(), otherwise we might race with other code adding a bad block and so won't retry later.

In md_update_sb (the second hunk), in the case where there is no metadata (neither persistent nor external), we treat any bad blocks as an error. However we need to clear the 'changed' flag before calling md_ack_all_badblocks, else it won't do anything.

This patch is suitable for -stable release 3.0 and later.

---
 drivers/md/md.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/md/md.c +2 -1
@@ -1805,13 +1805,13 @@ retry:
 						| BB_LEN(internal_bb));
 				*bbp++ = cpu_to_le64(store_bb);
 			}
+			bb->changed = 0;
 			if (read_seqretry(&bb->lock, seq))
 				goto retry;
 
 			bb->sector = (rdev->sb_start +
 				      (int)le32_to_cpu(sb->bblog_offset));
 			bb->size = le16_to_cpu(sb->bblog_size);
-			bb->changed = 0;
 		}
 	}
 
@@ -2366,6 +2366,7 @@ repeat:
 			clear_bit(MD_CHANGE_PENDING, &mddev->flags);
 			list_for_each_entry(rdev, &mddev->disks, same_set) {
 				if (rdev->badblocks.changed) {
+					rdev->badblocks.changed = 0;
 					md_ack_all_badblocks(&rdev->badblocks);
 					md_error(mddev, rdev);
 				}
author maintainer
#83 lore raw

PATCH 83/175 drm/i915: Only clear the GPU domains upon a successful finish

In reply to Greg KH

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

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

From: Chris Wilson <[email protected]>

commit c501ae7f332cdaf42e31af30b72b4b66cbbb1604 upstream.

By clearing the GPU read domains before waiting upon the buffer, we run the risk of the wait being interrupted and the domains prematurely cleared. The next time we attempt to wait upon the buffer (after userspace handles the signal), we believe that the buffer is idle and so skip the wait.

There are a number of bugs across all generations which show signs of an overly haste reuse of active buffers.

Such as:

https://bugs.freedesktop.org/show_bug.cgi?id=29046
https://bugs.freedesktop.org/show_bug.cgi?id=35863
https://bugs.freedesktop.org/show_bug.cgi?id=38952
https://bugs.freedesktop.org/show_bug.cgi?id=40282
https://bugs.freedesktop.org/show_bug.cgi?id=41098
https://bugs.freedesktop.org/show_bug.cgi?id=41102
https://bugs.freedesktop.org/show_bug.cgi?id=41284
https://bugs.freedesktop.org/show_bug.cgi?id=42141

A couple of those pre-date i915_gem_object_finish_gpu(), so may be unrelated (such as a wild write from a userspace command buffer), but this does look like a convincing cause for most of those bugs.

---
 drivers/gpu/drm/i915/i915_gem.c |    7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/i915_gem.c +5 -2
@@ -3084,10 +3084,13 @@ i915_gem_object_finish_gpu(struct drm_i9
 			return ret;
 	}
 
+	ret = i915_gem_object_wait_rendering(obj);
+	if (ret)
+		return ret;
+
 	/* Ensure that we invalidate the GPU's caches and TLBs. */
 	obj->base.read_domains &= ~I915_GEM_GPU_DOMAINS;
-
-	return i915_gem_object_wait_rendering(obj);
+	return 0;
 }
 
 /**
author maintainer
#84 lore raw

PATCH 84/175 drm/radeon: Restrict offset for legacy hardware cursor.

In reply to Greg KH

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

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

From: Michel Dänzer <[email protected]>

commit c4353016dac10133fa5d8535af83f0c4845a2915 upstream.

The hardware only takes 27 bits for the offset, so larger offsets are truncated, and the hardware cursor shows random bits other than the intended ones.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=46796

---
 drivers/gpu/drm/radeon/radeon_cursor.c |   13 +++++++++++--
 drivers/gpu/drm/radeon/radeon_object.c |   18 +++++++++++++++++-
 drivers/gpu/drm/radeon/radeon_object.h |    2 ++
 3 files changed, 30 insertions(+), 3 deletions(-)
drivers/gpu/drm/radeon/radeon_cursor.c +11 -2
@@ -151,7 +151,9 @@ int radeon_crtc_cursor_set(struct drm_cr
 			   uint32_t height)
 {
 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct radeon_device *rdev = crtc->dev->dev_private;
 	struct drm_gem_object *obj;
+	struct radeon_bo *robj;
 	uint64_t gpu_addr;
 	int ret;
 
@@ -173,7 +175,15 @@ int radeon_crtc_cursor_set(struct drm_cr
 		return -ENOENT;
 	}
 
-	ret = radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
+	robj = gem_to_radeon_bo(obj);
+	ret = radeon_bo_reserve(robj, false);
+	if (unlikely(ret != 0))
+		goto fail;
+	/* Only 27 bit offset for legacy cursor */
+	ret = radeon_bo_pin_restricted(robj, RADEON_GEM_DOMAIN_VRAM,
+				       ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27,
+				       &gpu_addr);
+	radeon_bo_unreserve(robj);
 	if (ret)
 		goto fail;
 
@@ -181,7 +191,6 @@ int radeon_crtc_cursor_set(struct drm_cr
 	radeon_crtc->cursor_height = height;
 
 	radeon_lock_cursor(crtc, true);
-	/* XXX only 27 bit offset for legacy cursor */
 	radeon_set_cursor(crtc, obj, gpu_addr);
 	radeon_show_cursor(crtc);
 	radeon_lock_cursor(crtc, false);
drivers/gpu/drm/radeon/radeon_object.c +17 -1
@@ -224,7 +224,8 @@ void radeon_bo_unref(struct radeon_bo **
 		*bo = NULL;
 }
 
-int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr)
+int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain, u64 max_offset,
+			     u64 *gpu_addr)
 {
 	int r, i;
 
@@ -232,6 +233,7 @@ int radeon_bo_pin(struct radeon_bo *bo,
 		bo->pin_count++;
 		if (gpu_addr)
 			*gpu_addr = radeon_bo_gpu_offset(bo);
+		WARN_ON_ONCE(max_offset != 0);
 		return 0;
 	}
 	radeon_ttm_placement_from_domain(bo, domain);
@@ -239,6 +241,15 @@ int radeon_bo_pin(struct radeon_bo *bo,
 		/* force to pin into visible video ram */
 		bo->placement.lpfn = bo->rdev->mc.visible_vram_size >> PAGE_SHIFT;
 	}
+	if (max_offset) {
+		u64 lpfn = max_offset >> PAGE_SHIFT;
+
+		if (!bo->placement.lpfn)
+			bo->placement.lpfn = bo->rdev->mc.gtt_size >> PAGE_SHIFT;
+
+		if (lpfn < bo->placement.lpfn)
+			bo->placement.lpfn = lpfn;
+	}
 	for (i = 0; i < bo->placement.num_placement; i++)
 		bo->placements[i] |= TTM_PL_FLAG_NO_EVICT;
 	r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false, false);
@@ -252,6 +263,11 @@ int radeon_bo_pin(struct radeon_bo *bo,
 	return r;
 }
 
+int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr)
+{
+	return radeon_bo_pin_restricted(bo, domain, 0, gpu_addr);
+}
+
 int radeon_bo_unpin(struct radeon_bo *bo)
 {
 	int r, i;
drivers/gpu/drm/radeon/radeon_object.h +2 -0
@@ -118,6 +118,8 @@ extern int radeon_bo_kmap(struct radeon_
 extern void radeon_bo_kunmap(struct radeon_bo *bo);
 extern void radeon_bo_unref(struct radeon_bo **bo);
 extern int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr);
+extern int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain,
+				    u64 max_offset, u64 *gpu_addr);
 extern int radeon_bo_unpin(struct radeon_bo *bo);
 extern int radeon_bo_evict_vram(struct radeon_device *rdev);
 extern void radeon_bo_force_delete(struct radeon_device *rdev);
author maintainer
#85 lore raw

PATCH 85/175 drm/radeon/kms: fix analog load detection on DVI-I connectors

In reply to Greg KH

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

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

From: Alex Deucher <[email protected]>

commit e00e8b5e760cbbe9067daeae5454d67c44c8d035 upstream.

We digital encoders have a detect function as well (for DP to VGA bridges), so we make sure we choose the analog one here.

Fixes:
https://bugs.freedesktop.org/show_bug.cgi?id=47007

---
 drivers/gpu/drm/radeon/radeon_connectors.c |    4 ++++
 1 file changed, 4 insertions(+)
drivers/gpu/drm/radeon/radeon_connectors.c +4 -0
@@ -946,6 +946,10 @@ radeon_dvi_detect(struct drm_connector *
 
 			encoder = obj_to_encoder(obj);
 
+			if (encoder->encoder_type != DRM_MODE_ENCODER_DAC ||
+			    encoder->encoder_type != DRM_MODE_ENCODER_TVDAC)
+				continue;
+
 			encoder_funcs = encoder->helper_private;
 			if (encoder_funcs->detect) {
 				if (ret != connector_status_connected) {
author maintainer
#86 lore raw

PATCH 86/175 drm/radeon/kms: add connector quirk for Fujitsu D3003-S2 board

In reply to Greg KH

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

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

From: Alex Deucher <[email protected]>

commit 4c1b2d2da3451f5c8dd59bd7e05bd9729d2aee05 upstream.

vbios lists DVI-I port as VGA and DVI-D.

Fixes:
https://bugs.freedesktop.org/show_bug.cgi?id=47007

---
 drivers/gpu/drm/radeon/radeon_atombios.c |   14 ++++++++++++++
 1 file changed, 14 insertions(+)
drivers/gpu/drm/radeon/radeon_atombios.c +14 -0
@@ -442,6 +442,20 @@ static bool radeon_atom_apply_quirks(str
 		struct radeon_device *rdev = dev->dev_private;
 		*i2c_bus = radeon_lookup_i2c_gpio(rdev, 0x93);
 	}
+
+	/* Fujitsu D3003-S2 board lists DVI-I as DVI-D and VGA */
+	if ((dev->pdev->device == 0x9802) &&
+	    (dev->pdev->subsystem_vendor == 0x1734) &&
+	    (dev->pdev->subsystem_device == 0x11bd)) {
+		if (*connector_type == DRM_MODE_CONNECTOR_VGA) {
+			*connector_type = DRM_MODE_CONNECTOR_DVII;
+			*line_mux = 0x3103;
+		} else if (*connector_type == DRM_MODE_CONNECTOR_DVID) {
+			*connector_type = DRM_MODE_CONNECTOR_DVII;
+		}
+	}
+
+
 	return true;
 }
 
author maintainer
#87 lore raw

PATCH 87/175 target: Fix up handling of short INQUIRY buffers

In reply to Greg KH

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

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

From: Roland Dreier <[email protected]>

commit d95b82461c56a6ff8ff248b101049a69ebb20278 upstream.

If the initiator sends us an INQUIRY command with an allocation length that's shorter than what we want to return, we're simply supposed to truncate our response and return what the initiator gave us space for, without signaling any error. Current target code has various tests that don't fill out the full response if the buffer is too short and sometimes return errors incorrectly.

Fix this up by allocating a bounce buffer for INQUIRY responses if we need to, ie if we have cmd->data_length too small as well as SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC set in cmd->se_cmd_flags -- for most fabrics, we always allocate at least a full page, but for tcm_loop we may have a small buffer coming directly from the SCSI stack.

This lets us delete a lot of cmd->data_length checking, and also makes our INQUIRY handling correct per SPC in a lot more cases.

---
 drivers/target/target_core_cdb.c  |  150 +++++++++-----------------------------
 include/target/target_core_base.h |    2 
 2 files changed, 37 insertions(+), 115 deletions(-)
drivers/target/target_core_cdb.c +36 -114
@@ -66,24 +66,11 @@ target_fill_alua_data(struct se_port *po
 }
 
 static int
-target_emulate_inquiry_std(struct se_cmd *cmd)
+target_emulate_inquiry_std(struct se_cmd *cmd, char *buf)
 {
 	struct se_lun *lun = cmd->se_lun;
 	struct se_device *dev = cmd->se_dev;
 	struct se_portal_group *tpg = lun->lun_sep->sep_tpg;
-	unsigned char *buf;
-
-	/*
-	 * Make sure we at least have 6 bytes of INQUIRY response
-	 * payload going back for EVPD=0
-	 */
-	if (cmd->data_length < 6) {
-		pr_err("SCSI Inquiry payload length: %u"
-			" too small for EVPD=0\n", cmd->data_length);
-		return -EINVAL;
-	}
-
-	buf = transport_kmap_data_sg(cmd);
 
 	if (dev == tpg->tpg_virt_lun0.lun_se_dev) {
 		buf[0] = 0x3f; /* Not connected */
@@ -112,29 +99,13 @@ target_emulate_inquiry_std(struct se_cmd
 	if (dev->se_sub_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED)
 		target_fill_alua_data(lun->lun_sep, buf);
 
-	if (cmd->data_length < 8) {
-		buf[4] = 1; /* Set additional length to 1 */
-		goto out;
-	}
-
 	buf[7] = 0x32; /* Sync=1 and CmdQue=1 */
 
-	/*
-	 * Do not include vendor, product, reversion info in INQUIRY
-	 * response payload for cdbs with a small allocation length.
-	 */
-	if (cmd->data_length < 36) {
-		buf[4] = 3; /* Set additional length to 3 */
-		goto out;
-	}
-
 	snprintf(&buf[8], 8, "LIO-ORG");
 	snprintf(&buf[16], 16, "%s", dev->se_sub_dev->t10_wwn.model);
 	snprintf(&buf[32], 4, "%s", dev->se_sub_dev->t10_wwn.revision);
 	buf[4] = 31; /* Set additional length to 31 */
 
-out:
-	transport_kunmap_data_sg(cmd);
 	return 0;
 }
 
@@ -152,12 +123,6 @@ target_emulate_evpd_80(struct se_cmd *cm
 		unit_serial_len = strlen(dev->se_sub_dev->t10_wwn.unit_serial);
 		unit_serial_len++; /* For NULL Terminator */
 
-		if (((len + 4) + unit_serial_len) > cmd->data_length) {
-			len += unit_serial_len;
-			buf[2] = ((len >> 8) & 0xff);
-			buf[3] = (len & 0xff);
-			return 0;
-		}
 		len += sprintf(&buf[4], "%s",
 			dev->se_sub_dev->t10_wwn.unit_serial);
 		len++; /* Extra Byte for NULL Terminator */
@@ -229,9 +194,6 @@ target_emulate_evpd_83(struct se_cmd *cm
 	if (!(dev->se_sub_dev->su_dev_flags & SDF_EMULATED_VPD_UNIT_SERIAL))
 		goto check_t10_vend_desc;
 
-	if (off + 20 > cmd->data_length)
-		goto check_t10_vend_desc;
-
 	/* CODE SET == Binary */
 	buf[off++] = 0x1;
 
@@ -283,12 +245,6 @@ check_t10_vend_desc:
 			strlen(&dev->se_sub_dev->t10_wwn.unit_serial[0]);
 		unit_serial_len++; /* For NULL Terminator */
 
-		if ((len + (id_len + 4) +
-		    (prod_len + unit_serial_len)) >
-				cmd->data_length) {
-			len += (prod_len + unit_serial_len);
-			goto check_port;
-		}
 		id_len += sprintf(&buf[off+12], "%s:%s", prod,
 				&dev->se_sub_dev->t10_wwn.unit_serial[0]);
 	}
@@ -306,7 +262,6 @@ check_t10_vend_desc:
 	/*
 	 * struct se_port is only set for INQUIRY VPD=1 through $FABRIC_MOD
 	 */
-check_port:
 	port = lun->lun_sep;
 	if (port) {
 		struct t10_alua_lu_gp *lu_gp;
@@ -323,10 +278,6 @@ check_port:
 		 * Get the PROTOCOL IDENTIFIER as defined by spc4r17
 		 * section 7.5.1 Table 362
 		 */
-		if (((len + 4) + 8) > cmd->data_length) {
-			len += 8;
-			goto check_tpgi;
-		}
 		buf[off] =
 			(tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4);
 		buf[off++] |= 0x1; /* CODE SET == Binary */
@@ -350,15 +301,10 @@ check_port:
 		 * Get the PROTOCOL IDENTIFIER as defined by spc4r17
 		 * section 7.5.1 Table 362
 		 */
-check_tpgi:
 		if (dev->se_sub_dev->t10_alua.alua_type !=
 				SPC3_ALUA_EMULATED)
 			goto check_scsi_name;
 
-		if (((len + 4) + 8) > cmd->data_length) {
-			len += 8;
-			goto check_lu_gp;
-		}
 		tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
 		if (!tg_pt_gp_mem)
 			goto check_lu_gp;
@@ -391,10 +337,6 @@ check_tpgi:
 		 * section 7.7.3.8
 		 */
 check_lu_gp:
-		if (((len + 4) + 8) > cmd->data_length) {
-			len += 8;
-			goto check_scsi_name;
-		}
 		lu_gp_mem = dev->dev_alua_lu_gp_mem;
 		if (!lu_gp_mem)
 			goto check_scsi_name;
@@ -435,10 +377,6 @@ check_scsi_name:
 		/* Header size + Designation descriptor */
 		scsi_name_len += 4;
 
-		if (((len + 4) + scsi_name_len) > cmd->data_length) {
-			len += scsi_name_len;
-			goto set_len;
-		}
 		buf[off] =
 			(tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4);
 		buf[off++] |= 0x3; /* CODE SET == UTF-8 */
@@ -474,7 +412,6 @@ check_scsi_name:
 		/* Header size + Designation descriptor */
 		len += (scsi_name_len + 4);
 	}
-set_len:
 	buf[2] = ((len >> 8) & 0xff);
 	buf[3] = (len & 0xff); /* Page Length for VPD 0x83 */
 	return 0;
@@ -484,9 +421,6 @@ set_len:
 static int
 target_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf)
 {
-	if (cmd->data_length < 60)
-		return 0;
-
 	buf[3] = 0x3c;
 	/* Set HEADSUP, ORDSUP, SIMPSUP */
 	buf[5] = 0x07;
@@ -512,20 +446,6 @@ target_emulate_evpd_b0(struct se_cmd *cm
 	if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
 		have_tp = 1;
 
-	if (cmd->data_length < (0x10 + 4)) {
-		pr_debug("Received data_length: %u"
-			" too small for EVPD 0xb0\n",
-			cmd->data_length);
-		return -EINVAL;
-	}
-
-	if (have_tp && cmd->data_length < (0x3c + 4)) {
-		pr_debug("Received data_length: %u"
-			" too small for TPE=1 EVPD 0xb0\n",
-			cmd->data_length);
-		have_tp = 0;
-	}
-
 	buf[0] = dev->transport->get_device_type(dev);
 	buf[3] = have_tp ? 0x3c : 0x10;
 
@@ -548,10 +468,9 @@ target_emulate_evpd_b0(struct se_cmd *cm
 	put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.optimal_sectors, &buf[12]);
 
 	/*
-	 * Exit now if we don't support TP or the initiator sent a too
-	 * short buffer.
+	 * Exit now if we don't support TP.
 	 */
-	if (!have_tp || cmd->data_length < (0x3c + 4))
+	if (!have_tp)
 		return 0;
 
 	/*
@@ -589,10 +508,7 @@ target_emulate_evpd_b1(struct se_cmd *cm
 
 	buf[0] = dev->transport->get_device_type(dev);
 	buf[3] = 0x3c;
-
-	if (cmd->data_length >= 5 &&
-	    dev->se_sub_dev->se_dev_attrib.is_nonrot)
-		buf[5] = 1;
+	buf[5] = dev->se_sub_dev->se_dev_attrib.is_nonrot ? 1 : 0;
 
 	return 0;
 }
@@ -671,8 +587,6 @@ target_emulate_evpd_00(struct se_cmd *cm
 {
 	int p;
 
-	if (cmd->data_length < 8)
-		return 0;
 	/*
 	 * Only report the INQUIRY EVPD=1 pages after a valid NAA
 	 * Registered Extended LUN WWN has been set via ConfigFS
@@ -681,8 +595,7 @@ target_emulate_evpd_00(struct se_cmd *cm
 	if (cmd->se_dev->se_sub_dev->su_dev_flags &
 			SDF_EMULATED_VPD_UNIT_SERIAL) {
 		buf[3] = ARRAY_SIZE(evpd_handlers);
-		for (p = 0; p < min_t(int, ARRAY_SIZE(evpd_handlers),
-				      cmd->data_length - 4); ++p)
+		for (p = 0; p < ARRAY_SIZE(evpd_handlers); ++p)
 			buf[p + 4] = evpd_handlers[p].page;
 	}
 
@@ -693,45 +606,50 @@ int target_emulate_inquiry(struct se_tas
 {
 	struct se_cmd *cmd = task->task_se_cmd;
 	struct se_device *dev = cmd->se_dev;
-	unsigned char *buf;
+	unsigned char *buf, *map_buf;
 	unsigned char *cdb = cmd->t_task_cdb;
 	int p, ret;
 
+	map_buf = transport_kmap_data_sg(cmd);
+	/*
+	 * If SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC is not set, then we
+	 * know we actually allocated a full page.  Otherwise, if the
+	 * data buffer is too small, allocate a temporary buffer so we
+	 * don't have to worry about overruns in all our INQUIRY
+	 * emulation handling.
+	 */
+	if (cmd->data_length < SE_INQUIRY_BUF &&
+	    (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC)) {
+		buf = kzalloc(SE_INQUIRY_BUF, GFP_KERNEL);
+		if (!buf) {
+			transport_kunmap_data_sg(cmd);
+			cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+			return -ENOMEM;
+		}
+	} else {
+		buf = map_buf;
+	}
+
 	if (!(cdb[1] & 0x1)) {
 		if (cdb[2]) {
 			pr_err("INQUIRY with EVPD==0 but PAGE CODE=%02x\n",
 			       cdb[2]);
 			cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-			return -EINVAL;
+			ret = -EINVAL;
+			goto out;
 		}
 
-		ret = target_emulate_inquiry_std(cmd);
+		ret = target_emulate_inquiry_std(cmd, buf);
 		goto out;
 	}
 
-	/*
-	 * Make sure we at least have 4 bytes of INQUIRY response
-	 * payload for 0x00 going back for EVPD=1.  Note that 0x80
-	 * and 0x83 will check for enough payload data length and
-	 * jump to set_len: label when there is not enough inquiry EVPD
-	 * payload length left for the next outgoing EVPD metadata
-	 */
-	if (cmd->data_length < 4) {
-		pr_err("SCSI Inquiry payload length: %u"
-			" too small for EVPD=1\n", cmd->data_length);
-		cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-		return -EINVAL;
-	}
-
-	buf = transport_kmap_data_sg(cmd);
-
 	buf[0] = dev->transport->get_device_type(dev);
 
 	for (p = 0; p < ARRAY_SIZE(evpd_handlers); ++p) {
 		if (cdb[2] == evpd_handlers[p].page) {
 			buf[1] = cdb[2];
 			ret = evpd_handlers[p].emulate(cmd, buf);
-			goto out_unmap;
+			goto out;
 		}
 	}
 
@@ -739,9 +657,13 @@ int target_emulate_inquiry(struct se_tas
 	cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
 	ret = -EINVAL;
 
-out_unmap:
-	transport_kunmap_data_sg(cmd);
 out:
+	if (buf != map_buf) {
+		memcpy(map_buf, buf, cmd->data_length);
+		kfree(buf);
+	}
+	transport_kunmap_data_sg(cmd);
+
 	if (!ret) {
 		task->task_scsi_status = GOOD;
 		transport_complete_task(task, 1);
include/target/target_core_base.h +1 -1
@@ -118,9 +118,9 @@
 /* Queue Algorithm Modifier default for restricted reordering in control mode page */
 #define DA_EMULATE_REST_REORD			0
 
+#define SE_INQUIRY_BUF				512
 #define SE_MODE_PAGE_BUF			512
 
-
 /* struct se_hba->hba_flags */
 enum hba_flags_table {
 	HBA_FLAGS_INTERNAL_USE	= 0x01,
author maintainer
#88 lore raw

PATCH 88/175 target: Set peripheral device type consistently in INQUIRY response

In reply to Greg KH

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

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

From: Roland Dreier <[email protected]>

commit 089461dda1770c10fea0b988ff74519a9be81d7e upstream.

Current code sets the peripheral device type to 0x3f == "not present unknown" for virtual LUN 0 for standard INQUIRY commands, but leaves it as 0 == "connected direct access block" for VPD INQUIRY commands. This is just because the check for LUN 0 only happens in some code paths.

Make our peripheral device type consistent by moving the LUN 0 check into the common emulate_inquiry() code.

---
 drivers/target/target_core_cdb.c |   20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)
drivers/target/target_core_cdb.c +10 -10
@@ -70,15 +70,11 @@ target_emulate_inquiry_std(struct se_cmd
 {
 	struct se_lun *lun = cmd->se_lun;
 	struct se_device *dev = cmd->se_dev;
-	struct se_portal_group *tpg = lun->lun_sep->sep_tpg;
 
-	if (dev == tpg->tpg_virt_lun0.lun_se_dev) {
-		buf[0] = 0x3f; /* Not connected */
-	} else {
-		buf[0] = dev->transport->get_device_type(dev);
-		if (buf[0] == TYPE_TAPE)
-			buf[1] = 0x80;
-	}
+	/* Set RMB (removable media) for tape devices */
+	if (dev->transport->get_device_type(dev) == TYPE_TAPE)
+		buf[1] = 0x80;
+
 	buf[2] = dev->transport->get_device_rev(dev);
 
 	/*
@@ -606,6 +602,7 @@ int target_emulate_inquiry(struct se_tas
 {
 	struct se_cmd *cmd = task->task_se_cmd;
 	struct se_device *dev = cmd->se_dev;
+	struct se_portal_group *tpg = cmd->se_lun->lun_sep->sep_tpg;
 	unsigned char *buf, *map_buf;
 	unsigned char *cdb = cmd->t_task_cdb;
 	int p, ret;
@@ -630,6 +627,11 @@ int target_emulate_inquiry(struct se_tas
 		buf = map_buf;
 	}
 
+	if (dev == tpg->tpg_virt_lun0.lun_se_dev)
+		buf[0] = 0x3f; /* Not connected */
+	else
+		buf[0] = dev->transport->get_device_type(dev);
+
 	if (!(cdb[1] & 0x1)) {
 		if (cdb[2]) {
 			pr_err("INQUIRY with EVPD==0 but PAGE CODE=%02x\n",
@@ -643,8 +645,6 @@ int target_emulate_inquiry(struct se_tas
 		goto out;
 	}
 
-	buf[0] = dev->transport->get_device_type(dev);
-
 	for (p = 0; p < ARRAY_SIZE(evpd_handlers); ++p) {
 		if (cdb[2] == evpd_handlers[p].page) {
 			buf[1] = cdb[2];
author maintainer
#89 lore raw

PATCH 89/175 target: Dont set WBUS16 or SYNC bits in INQUIRY response

In reply to Greg KH

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

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

From: Roland Dreier <[email protected]>

commit effc6cc8828257c32c37635e737f14fd6e19ecd7 upstream.

SPC-4 says about the WBUS16 and SYNC bits:

The meanings of these fields are specific to SPI-5 (see 6.4.3). For SCSI transport protocols other than the SCSI Parallel Interface, these fields are reserved.

We don't have a SPI fabric module, so we should never set these bits. (The comment was misleading, since it only mentioned Sync but the actual code set WBUS16 too).

---
 drivers/target/target_core_cdb.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/target/target_core_cdb.c +1 -1
@@ -95,7 +95,7 @@ target_emulate_inquiry_std(struct se_cmd
 	if (dev->se_sub_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED)
 		target_fill_alua_data(lun->lun_sep, buf);
 
-	buf[7] = 0x32; /* Sync=1 and CmdQue=1 */
+	buf[7] = 0x2; /* CmdQue=1 */
 
 	snprintf(&buf[8], 8, "LIO-ORG");
 	snprintf(&buf[16], 16, "%s", dev->se_sub_dev->t10_wwn.model);
author maintainer
#90 lore raw

PATCH 90/175 target: fix use after free in target_report_luns

In reply to Greg KH

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

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

From: =?UTF-8?q?J=C3=B6rn=20Engel?= <[email protected]>

commit 382436f8804fe1cb20b9a2a811a10eb2d8554721 upstream.

Fix possible NULL pointer dereference in target_report_luns failure path.

---
 drivers/target/target_core_device.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/target/target_core_device.c +1 -1
@@ -695,12 +695,12 @@ int target_report_luns(struct se_task *s
 	 * See SPC3 r07, page 159.
 	 */
 done:
-	transport_kunmap_data_sg(se_cmd);
 	lun_count *= 8;
 	buf[0] = ((lun_count >> 24) & 0xff);
 	buf[1] = ((lun_count >> 16) & 0xff);
 	buf[2] = ((lun_count >> 8) & 0xff);
 	buf[3] = (lun_count & 0xff);
+	transport_kunmap_data_sg(se_cmd);
 
 	se_task->task_scsi_status = GOOD;
 	transport_complete_task(se_task, 1);
author maintainer
#91 lore raw

PATCH 91/175 target: prevent NULL pointer dereference in target_report_luns

In reply to Greg KH

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

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

From: =?UTF-8?q?J=C3=B6rn=20Engel?= <[email protected]>

commit 47f1b8803e1e358ebbf4f82bfdb98971c912a2c3 upstream.

transport_kmap_data_sg can return NULL. I never saw this trigger, but returning -ENOMEM seems better than a crash. Also removes a pointless case while at it.

---
 drivers/target/target_core_device.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/target/target_core_device.c +3 -1
@@ -657,7 +657,9 @@ int target_report_luns(struct se_task *s
 	unsigned char *buf;
 	u32 cdb_offset = 0, lun_count = 0, offset = 8, i;
 
-	buf = (unsigned char *) transport_kmap_data_sg(se_cmd);
+	buf = transport_kmap_data_sg(se_cmd);
+	if (!buf)
+		return -ENOMEM;
 
 	/*
 	 * If no struct se_session pointer is present, this struct se_cmd is
author maintainer
#92 lore raw

PATCH 92/175 target: Fix 16-bit target ports for SET TARGET PORT GROUPS emulation

In reply to Greg KH

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

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

From: Roland Dreier <[email protected]>

commit 33395fb8a13731c7ef7b175dbf5a4d8a6738fe6c upstream.

The old code did (MSB << 8) & 0xff, which always evaluates to 0. Just use get_unaligned_be16() so we don't have to worry about whether our open-coded version is correct or not.

---
 drivers/target/target_core_alua.c |    7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)
drivers/target/target_core_alua.c +3 -4
@@ -30,6 +30,7 @@
 #include <linux/export.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
+#include <asm/unaligned.h>
 
 #include <target/target_core_base.h>
 #include <target/target_core_backend.h>
@@ -267,8 +268,7 @@ int target_emulate_set_target_port_group
 		 * changed.
 		 */
 		if (primary) {
-			tg_pt_id = ((ptr[2] << 8) & 0xff);
-			tg_pt_id |= (ptr[3] & 0xff);
+			tg_pt_id = get_unaligned_be16(ptr + 2);
 			/*
 			 * Locate the matching target port group ID from
 			 * the global tg_pt_gp list
@@ -312,8 +312,7 @@ int target_emulate_set_target_port_group
 			 * the Target Port in question for the the incoming
 			 * SET_TARGET_PORT_GROUPS op.
 			 */
-			rtpi = ((ptr[2] << 8) & 0xff);
-			rtpi |= (ptr[3] & 0xff);
+			rtpi = get_unaligned_be16(ptr + 2);
 			/*
 			 * Locate the matching relative target port identifer
 			 * for the struct se_device storage object.
author maintainer
#93 lore raw

PATCH 93/175 Bluetooth: Add AR30XX device ID on Asus laptops

In reply to Greg KH

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

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

From: Keng-Yu Lin <[email protected]>

commit 6b6ba88b5bb8779156b21bb957520a448c3642e2 upstream.

The ID is found on Asus K54HR and K53U.
Blacklist the AR3011-based device ID [0489:e03d]
and add to ath3k.c for firmware loading.

Below is the output of usb-devices script:

Before the fiwmware loading:

T:  Bus=01 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=12  MxCh= 0
D:  Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs=  1
P:  Vendor=0489 ProdID=e03d Rev=00.01
C:  #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA
I:  If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
I:  If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb

After the fiwmware loading:

T:  Bus=01 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  5 Spd=12  MxCh= 0
D:  Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs=  1
P:  Vendor=0cf3 ProdID=3005 Rev=00.01
C:  #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA
I:  If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
I:  If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
---
 drivers/bluetooth/ath3k.c |    1 +
 drivers/bluetooth/btusb.c |    1 +
 2 files changed, 2 insertions(+)
drivers/bluetooth/ath3k.c +1 -0
@@ -65,6 +65,7 @@ static struct usb_device_id ath3k_table[
 	{ USB_DEVICE(0x0CF3, 0x3002) },
 	{ USB_DEVICE(0x13d3, 0x3304) },
 	{ USB_DEVICE(0x0930, 0x0215) },
+	{ USB_DEVICE(0x0489, 0xE03D) },
 
 	/* Atheros AR9285 Malbec with sflash firmware */
 	{ USB_DEVICE(0x03F0, 0x311D) },
drivers/bluetooth/btusb.c +1 -0
@@ -121,6 +121,7 @@ static struct usb_device_id blacklist_ta
 	{ USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
 	{ USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE },
 	{ USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
+	{ USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
 
 	/* Atheros AR9285 Malbec with sflash firmware */
 	{ USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
author maintainer
#94 lore raw

PATCH 94/175 HID: add extra hotkeys in Asus AIO keyboards

In reply to Greg KH

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

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

From: Keng-Yu Lin <[email protected]>

commit 3596bb929f2abd3433c2eaa5755fad48ac207af1 upstream.

The Asus All-In-One PC has a wireless keyboard with wifi toggle, brightness up, brightness down and display off hotkeys.

This patch adds suppoort for these hotkeys.

---
 drivers/hid/hid-chicony.c |    5 +++++
 drivers/hid/hid-core.c    |    1 +
 drivers/hid/hid-ids.h     |    1 +
 3 files changed, 7 insertions(+)
drivers/hid/hid-chicony.c +5 -0
@@ -45,6 +45,10 @@ static int ch_input_mapping(struct hid_d
 	case 0xff09: ch_map_key_clear(BTN_9);	break;
 	case 0xff0a: ch_map_key_clear(BTN_A);	break;
 	case 0xff0b: ch_map_key_clear(BTN_B);	break;
+	case 0x00f1: ch_map_key_clear(KEY_WLAN);	break;
+	case 0x00f2: ch_map_key_clear(KEY_BRIGHTNESSDOWN);	break;
+	case 0x00f3: ch_map_key_clear(KEY_BRIGHTNESSUP);	break;
+	case 0x00f4: ch_map_key_clear(KEY_DISPLAY_OFF);	break;
 	default:
 		return 0;
 	}
@@ -53,6 +57,7 @@ static int ch_input_mapping(struct hid_d
 
 static const struct hid_device_id ch_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, ch_devices);
drivers/hid/hid-core.c +1 -0
@@ -1396,6 +1396,7 @@ static const struct hid_device_id hid_ha
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT, USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, USB_DEVICE_ID_CVTOUCH_SCREEN) },
drivers/hid/hid-ids.h +1 -0
@@ -193,6 +193,7 @@
 #define USB_DEVICE_ID_CHICONY_TACTICAL_PAD	0x0418
 #define USB_DEVICE_ID_CHICONY_MULTI_TOUCH	0xb19d
 #define USB_DEVICE_ID_CHICONY_WIRELESS	0x0618
+#define USB_DEVICE_ID_CHICONY_WIRELESS2	0x1123
 
 #define USB_VENDOR_ID_CHUNGHWAT		0x2247
 #define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH	0x0001
author maintainer
#95 lore raw

PATCH 95/175 HID: add more hotkeys in Asus AIO keyboards

In reply to Greg KH

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

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

From: Keng-Yu Lin <[email protected]>

commit 6c30d5a53229aad22bb675e0bd6eb518ecaa4316 upstream.

Add support for the camera key. The hotkey for
Asus S.H.E(Super Hybrid Engine) mode is mapped to KEY_KEY_PROG1 just for notifying the userspace.

---
 drivers/hid/hid-chicony.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/hid/hid-chicony.c +2 -0
@@ -49,6 +49,8 @@ static int ch_input_mapping(struct hid_d
 	case 0x00f2: ch_map_key_clear(KEY_BRIGHTNESSDOWN);	break;
 	case 0x00f3: ch_map_key_clear(KEY_BRIGHTNESSUP);	break;
 	case 0x00f4: ch_map_key_clear(KEY_DISPLAY_OFF);	break;
+	case 0x00f7: ch_map_key_clear(KEY_CAMERA);	break;
+	case 0x00f8: ch_map_key_clear(KEY_PROG1);	break;
 	default:
 		return 0;
 	}
author maintainer
#96 lore raw

PATCH 96/175 ahci: add AHCI_HFLAG_DELAY_ENGINE host flag

In reply to Greg KH

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

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

From: Brian Norris <[email protected]>

commit 66583c9fa63d05d5580e409f9a58d3cad6d76d17 upstream.

The following commit was intended to fix problems with specific AHCI controller(s) that would become bricks if the AHCI specification was not followed strictly (that is, if ahci_start_engine() was called while the controller was in the wrong state):

commit 7faa33da9b7add01db9f1ad92c6a5d9145e940a7
ahci: start engine only during soft/hard resets

However, some devices currently have issues with that fix, so we must implement a flag that delays the ahci_start_engine() call only for specific controllers.

This commit simply introduces the flag, without enabling it in any driver.

Note that even when AHCI_HFLAG_DELAY_ENGINE is not enabled, this patch does not constitue a full revert to commit 7faa33da; there is still a change in behavior to the ahci_port_suspend() failure path.

---
 drivers/ata/ahci.h    |    3 +++
 drivers/ata/libahci.c |    5 +++++
 2 files changed, 8 insertions(+)
drivers/ata/ahci.h +3 -0
@@ -210,6 +210,9 @@ enum {
 	AHCI_HFLAG_NO_SNTF		= (1 << 12), /* no sntf */
 	AHCI_HFLAG_NO_FPDMA_AA		= (1 << 13), /* no FPDMA AA */
 	AHCI_HFLAG_YES_FBS		= (1 << 14), /* force FBS cap on */
+	AHCI_HFLAG_DELAY_ENGINE		= (1 << 15), /* do not start engine on
+						        port start (wait until
+						        error-handling stage) */
 
 	/* ap->flags bits */
 
drivers/ata/libahci.c +5 -0
@@ -737,6 +737,7 @@ static void ahci_power_down(struct ata_p
 
 static void ahci_start_port(struct ata_port *ap)
 {
+	struct ahci_host_priv *hpriv = ap->host->private_data;
 	struct ahci_port_priv *pp = ap->private_data;
 	struct ata_link *link;
 	struct ahci_em_priv *emp;
@@ -746,6 +747,10 @@ static void ahci_start_port(struct ata_p
 	/* enable FIS reception */
 	ahci_start_fis_rx(ap);
 
+	/* enable DMA */
+	if (!(hpriv->flags & AHCI_HFLAG_DELAY_ENGINE))
+		ahci_start_engine(ap);
+
 	/* turn on LEDs */
 	if (ap->flags & ATA_FLAG_EM) {
 		ata_for_each_link(link, ap, EDGE) {
author maintainer
#97 lore raw

PATCH 97/175 ahci: move AHCI_HFLAGS() macro to ahci.h

In reply to Greg KH

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

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

From: Brian Norris <[email protected]>

commit 55d5ec316627b64c3764e4c1b4b8e1988e272c1f upstream.

We will need this macro in both ahci.c and ahci_platform.c, so just move it to the header.

---
 drivers/ata/ahci.c |    2 --
 drivers/ata/ahci.h |    3 +++
 2 files changed, 3 insertions(+), 2 deletions(-)
drivers/ata/ahci.c +0 -2
@@ -103,8 +103,6 @@ static struct ata_port_operations ahci_p
 	.hardreset		= ahci_p5wdh_hardreset,
 };
 
-#define AHCI_HFLAGS(flags)	.private_data	= (void *)(flags)
-
 static const struct ata_port_info ahci_port_info[] = {
 	/* by features */
 	[board_ahci] =
drivers/ata/ahci.h +3 -0
@@ -195,6 +195,9 @@ enum {
 	PORT_FBS_EN		= (1 << 0), /* Enable FBS */
 
 	/* hpriv->flags bits */
+
+#define AHCI_HFLAGS(flags)		.private_data	= (void *)(flags)
+
 	AHCI_HFLAG_NO_NCQ		= (1 << 0),
 	AHCI_HFLAG_IGN_IRQ_IF_ERR	= (1 << 1), /* ignore IRQ_IF_ERR */
 	AHCI_HFLAG_IGN_SERR_INTERNAL	= (1 << 2), /* ignore SERR_INTERNAL */
author maintainer
#98 lore raw

PATCH 98/175 ahci_platform: add STRICT_AHCI platform type

In reply to Greg KH

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

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

From: Brian Norris <[email protected]>

commit d408e2b14fba4fa214fa5bc24b7baae8a55e563c upstream.

Some platforms need to make use of the AHCI_HFLAG_DELAY_ENGINE flag.

---
 drivers/ata/ahci_platform.c |   11 +++++++++++
 1 file changed, 11 insertions(+)
drivers/ata/ahci_platform.c +11 -0
@@ -26,6 +26,7 @@
 enum ahci_type {
 	AHCI,		/* standard platform ahci */
 	IMX53_AHCI,	/* ahci on i.mx53 */
+	STRICT_AHCI,	/* delayed DMA engine start */
 };
 
 static struct platform_device_id ahci_devtype[] = {
@@ -36,6 +37,9 @@ static struct platform_device_id ahci_de
 		.name = "imx53-ahci",
 		.driver_data = IMX53_AHCI,
 	}, {
+		.name = "strict-ahci",
+		.driver_data = STRICT_AHCI,
+	}, {
 		/* sentinel */
 	}
 };
@@ -56,6 +60,13 @@ static const struct ata_port_info ahci_p
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_pmp_retry_srst_ops,
 	},
+	[STRICT_AHCI] = {
+		AHCI_HFLAGS	(AHCI_HFLAG_DELAY_ENGINE),
+		.flags		= AHCI_FLAG_COMMON,
+		.pio_mask	= ATA_PIO4,
+		.udma_mask	= ATA_UDMA6,
+		.port_ops	= &ahci_ops,
+	},
 };
 
 static struct scsi_host_template ahci_platform_sht = {
author maintainer
#99 lore raw

PATCH 99/175 pata_legacy: correctly mask recovery field for HT6560B

In reply to Greg KH

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

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

From: Sergei Shtylyov <[email protected]>

commit 9716387311c790de381214c03e7f1b72b91a8189 upstream.

According to the HT6560H datasheet, the recovery timing field is 4-bit wide, with a value of 0 meaning 16 cycles. Correct obvious thinko in the recovery field mask.

---
 drivers/ata/pata_legacy.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/ata/pata_legacy.c +1 -2
@@ -401,8 +401,7 @@ static void ht6560b_set_piomode(struct a
 	ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000);
 
 	active = clamp_val(t.active, 2, 15);
-	recover = clamp_val(t.recover, 2, 16);
-	recover &= 0x15;
+	recover = clamp_val(t.recover, 2, 16) & 0x0F;
 
 	inb(0x3E6);
 	inb(0x3E6);
author maintainer
#100 lore raw

PATCH 100/175 firewire: ohci: fix too-early completion of IR multichannel buffers

In reply to Greg KH

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

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

From: Clemens Ladisch <[email protected]>

commit 0c0efbacab8d70700d13301e0ae7975783c0cb0a upstream.

handle_ir_buffer_fill() assumed that a completed descriptor would be indicated by a non-zero transfer_status (as in most other descriptors). However, this field is written by the controller as soon as (the end of) the first packet has been written into the buffer. As a consequence, if we happen to run into such a descriptor when the interrupt handler is executed after such a packet has completed, the descriptor would be taken out of the list of active descriptors as soon as the buffer had been partially filled, so the event for the buffer being completely filled would never be sent.

To fix this, handle descriptors only when they have been completely filled, i.e., when res_count == 0. (This also matches the condition that is reported by the controller with an interrupt.)

---
 drivers/firewire/ohci.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/firewire/ohci.c +2 -3
@@ -2748,7 +2748,7 @@ static int handle_ir_buffer_fill(struct
 		container_of(context, struct iso_context, context);
 	u32 buffer_dma;
 
-	if (!last->transfer_status)
+	if (last->res_count != 0)
 		/* Descriptor(s) not done yet, stop iteration */
 		return 0;
 
@@ -2762,8 +2762,7 @@ static int handle_ir_buffer_fill(struct
 	if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS)
 		ctx->base.callback.mc(&ctx->base,
 				      le32_to_cpu(last->data_address) +
-				      le16_to_cpu(last->req_count) -
-				      le16_to_cpu(last->res_count),
+				      le16_to_cpu(last->req_count),
 				      ctx->base.callback_data);
 
 	return 1;
author maintainer
#101 lore raw

PATCH 101/175 mm: vmscan: forcibly scan highmem if there are too many buffer_heads pinning highmem

In reply to Greg KH

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

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

From: Mel Gorman <[email protected]>

commit cc715d99e529d470dde2f33a6614f255adea71f3 upstream.

Stuart Foster reported on bugzilla that copying large amounts of data from NTFS caused an OOM kill on 32-bit X86 with 16G of memory. Andrew Morton correctly identified that the problem was NTFS was using 512 blocks meaning each page had 8 buffer_heads in low memory pinning it.

In the past, direct reclaim used to scan highmem even if the allocating process did not specify __GFP_HIGHMEM but not any more. kswapd no longer will reclaim from zones that are above the high watermark. The intention in both cases was to minimise unnecessary reclaim. The downside is on machines with large amounts of highmem that lowmem can be fully consumed by buffer_heads with nothing trying to free them.

The following patch is based on a suggestion by Andrew Morton to extend the buffer_heads_over_limit case to force kswapd and direct reclaim to scan the highmem zone regardless of the allocation request or watermarks.

Addresses https://bugzilla.kernel.org/show_bug.cgi?id=42578

[[email protected]: move buffer_heads_over_limit check up]
[[email protected]: buffer_heads_over_limit is unlikely]
Cc Johannes Weiner <[email protected]>
Cc Rik van Riel <[email protected]>
Cc Christoph Lameter <[email protected]>
---
 mm/vmscan.c |   42 +++++++++++++++++++++++++++++-------------
 1 file changed, 29 insertions(+), 13 deletions(-)
mm/vmscan.c +29 -13
@@ -1643,18 +1643,6 @@ static void move_active_pages_to_lru(str
 	unsigned long pgmoved = 0;
 	struct page *page;
 
-	if (buffer_heads_over_limit) {
-		spin_unlock_irq(&zone->lru_lock);
-		list_for_each_entry(page, list, lru) {
-			if (page_has_private(page) && trylock_page(page)) {
-				if (page_has_private(page))
-					try_to_release_page(page, 0);
-				unlock_page(page);
-			}
-		}
-		spin_lock_irq(&zone->lru_lock);
-	}
-
 	while (!list_empty(list)) {
 		struct lruvec *lruvec;
 
@@ -1737,6 +1725,14 @@ static void shrink_active_list(unsigned
 			continue;
 		}
 
+		if (unlikely(buffer_heads_over_limit)) {
+			if (page_has_private(page) && trylock_page(page)) {
+				if (page_has_private(page))
+					try_to_release_page(page, 0);
+				unlock_page(page);
+			}
+		}
+
 		if (page_referenced(page, 0, mz->mem_cgroup, &vm_flags)) {
 			nr_rotated += hpage_nr_pages(page);
 			/*
@@ -2235,6 +2231,14 @@ static bool shrink_zones(int priority, s
 	unsigned long nr_soft_scanned;
 	bool aborted_reclaim = false;
 
+	/*
+	 * If the number of buffer_heads in the machine exceeds the maximum
+	 * allowed level, force direct reclaim to scan the highmem zone as
+	 * highmem pages could be pinning lowmem pages storing buffer_heads
+	 */
+	if (buffer_heads_over_limit)
+		sc->gfp_mask |= __GFP_HIGHMEM;
+
 	for_each_zone_zonelist_nodemask(zone, z, zonelist,
 					gfp_zone(sc->gfp_mask), sc->nodemask) {
 		if (!populated_zone(zone))
@@ -2724,6 +2728,17 @@ loop_again:
 			 */
 			age_active_anon(zone, &sc, priority);
 
+			/*
+			 * If the number of buffer_heads in the machine
+			 * exceeds the maximum allowed level and this node
+			 * has a highmem zone, force kswapd to reclaim from
+			 * it to relieve lowmem pressure.
+			 */
+			if (buffer_heads_over_limit && is_highmem_idx(i)) {
+				end_zone = i;
+				break;
+			}
+
 			if (!zone_watermark_ok_safe(zone, order,
 					high_wmark_pages(zone), 0, 0)) {
 				end_zone = i;
@@ -2786,7 +2801,8 @@ loop_again:
 				(zone->present_pages +
 					KSWAPD_ZONE_BALANCE_GAP_RATIO-1) /
 				KSWAPD_ZONE_BALANCE_GAP_RATIO);
-			if (!zone_watermark_ok_safe(zone, order,
+			if ((buffer_heads_over_limit && is_highmem_idx(i)) ||
+				    !zone_watermark_ok_safe(zone, order,
 					high_wmark_pages(zone) + balance_gap,
 					end_zone, 0)) {
 				shrink_zone(priority, zone, &sc);
#102 lore raw

Re: [ 101/175] mm: vmscan: forcibly scan highmem if there are too many buffer_heads pinning highmem

Quoted 4 lines · Greg KH

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

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

Quoted 8 lines

From: Mel Gorman <[email protected]>

commit cc715d99e529d470dde2f33a6614f255adea71f3 upstream.

Stuart Foster reported on bugzilla that copying large amounts of data from NTFS caused an OOM kill on 32-bit X86 with 16G of memory. Andrew Morton correctly identified that the problem was NTFS was using 512 blocks meaning each page had 8 buffer_heads in low memory pinning it.

I notice that this was not applied to 3.0.26 or 3.2.14.

[...]

Quoted 1 line

Addresses https://bugzilla.kernel.org/show_bug.cgi?id=42578

[...]

but this bug was reported against 3.1.9, so the fix is presumably needed for 3.2 at least.

Presumably the upstream change doesn't apply cleanly and would need to be backported. Is anyone planning to do that?

Ben.

Signature · 2 lines
Ben Hutchings
Reality is just a crutch for people who can't handle science fiction.
#103 lore raw

Re: [ 101/175] mm: vmscan: forcibly scan highmem if there are too many buffer_heads pinning highmem

Sorry for the slow response. I was at LSF/MM and still at Collaboration Summit and not keeping up with mail.

Quoted 7 lines · Ben Hutchings
Quoted 6 lines · Greg KH

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

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

From: Mel Gorman <[email protected]>

Quoted 9 lines
Quoted 6 lines

commit cc715d99e529d470dde2f33a6614f255adea71f3 upstream.

Stuart Foster reported on bugzilla that copying large amounts of data from NTFS caused an OOM kill on 32-bit X86 with 16G of memory. Andrew Morton correctly identified that the problem was NTFS was using 512 blocks meaning each page had 8 buffer_heads in low memory pinning it.

I notice that this was not applied to 3.0.26 or 3.2.14.

True.

Quoted 10 lines

[...]

Quoted 1 line

Addresses https://bugzilla.kernel.org/show_bug.cgi?id=42578

[...]

but this bug was reported against 3.1.9, so the fix is presumably needed for 3.2 at least.

Presumably the upstream change doesn't apply cleanly and would need to be backported. Is anyone planning to do that?

It probably does not apply cleanly and considering how the bug is triggered I was not treating it as a high priority. Nikola Ciprich (added to cc) had said that he might try backporting it and I would review the result. I have not heard anything since. I can take a look at backporting it next week if it is considered a common problem.

Signature · 2 lines
Mel Gorman
SUSE Labs
#104 lore raw

Re: [ 101/175] mm: vmscan: forcibly scan highmem if there are too many buffer_heads pinning highmem

On Thu, 2012-04-05 at 13:31 -0700, Mel Gorman wrote:
[...]

Quoted 10 lines
Quoted 9 lines
Quoted 1 line

Addresses https://bugzilla.kernel.org/show_bug.cgi?id=42578

[...]

but this bug was reported against 3.1.9, so the fix is presumably needed for 3.2 at least.

Presumably the upstream change doesn't apply cleanly and would need to be backported. Is anyone planning to do that?

Quoted 5 lines

It probably does not apply cleanly and considering how the bug is triggered I was not treating it as a high priority. Nikola Ciprich (added to cc) had said that he might try backporting it and I would review the result. I have not heard anything since. I can take a look at backporting it next week if it is considered a common problem.

I really don't know; I'm happy to leave it to you and the other mm maintainers to decide if it's worthwhile.

Ben.

Signature · 2 lines
Ben Hutchings
Reality is just a crutch for people who can't handle science fiction.
#105 lore raw

Re: [ 101/175] mm: vmscan: forcibly scan highmem if there are too many buffer_heads pinning highmem

In reply to Mel Gorman

Hi, sorry it took me a bit longer.

here's my backport, compiles fine, kernel boots without any problems. please review.
n.

(backport of upstream commit cc715d99e529d470dde2f33a6614f255adea71f3)

mm: vmscan: forcibly scan highmem if there are too many buffer_heads pinning highmem

Stuart Foster reported on bugzilla that copying large amounts of data from NTFS caused an OOM kill on 32-bit X86 with 16G of memory. Andrew Morton correctly identified that the problem was NTFS was using 512 blocks meaning each page had 8 buffer_heads in low memory pinning it.

In the past, direct reclaim used to scan highmem even if the allocating process did not specify __GFP_HIGHMEM but not any more. kswapd no longer will reclaim from zones that are above the high watermark. The intention in both cases was to minimise unnecessary reclaim. The downside is on machines with large amounts of highmem that lowmem can be fully consumed by buffer_heads with nothing trying to free them.

The following patch is based on a suggestion by Andrew Morton to extend the buffer_heads_over_limit case to force kswapd and direct reclaim to scan the highmem zone regardless of the allocation request or watermarks.

Addresses https://bugzilla.kernel.org/show_bug.cgi?id=42578

---

mm/vmscan.c +29 -1
diff -Naur linux-3.0/mm/vmscan.c linux-3.0-cc715d99e529d470dde2f33a6614f255adea71f3-backport/mm/vmscan.c
@@ -1581,6 +1581,14 @@
 			putback_lru_page(page);
 			continue;
 		}
+		
+		if (unlikely(buffer_heads_over_limit)) {
+			if (page_has_private(page) && trylock_page(page)) {
+				if (page_has_private(page))
+					try_to_release_page(page, 0);
+				unlock_page(page);
+			}
+		}
 
 		if (page_referenced(page, 0, sc->mem_cgroup, &vm_flags)) {
 			nr_rotated += hpage_nr_pages(page);
@@ -2053,6 +2061,14 @@
 	struct zoneref *z;
 	struct zone *zone;
 
+	/*
+	 * If the number of buffer_heads in the machine exceeds the maximum
+	 * allowed level, force direct reclaim to scan the highmem zone as
+	 * highmem pages could be pinning lowmem pages storing buffer_heads
+	 */
+	if (buffer_heads_over_limit)
+		sc->gfp_mask |= __GFP_HIGHMEM;
+
 	for_each_zone_zonelist_nodemask(zone, z, zonelist,
 			gfp_zone(sc->gfp_mask), sc->nodemask) {
 		if (!populated_zone(zone))
@@ -2514,7 +2530,8 @@
 				(zone->present_pages +
 					KSWAPD_ZONE_BALANCE_GAP_RATIO-1) /
 				KSWAPD_ZONE_BALANCE_GAP_RATIO);
-			if (!zone_watermark_ok_safe(zone, order,
+			if ((buffer_heads_over_limit && is_highmem_idx(i)) ||
+				!zone_watermark_ok_safe(zone, order,
 					high_wmark_pages(zone) + balance_gap,
 					end_zone, 0)) {
 				shrink_zone(priority, zone, &sc);
@@ -2543,6 +2560,17 @@
 				continue;
 			}
 
+			/*
+			 * If the number of buffer_heads in the machine
+			 * exceeds the maximum allowed level and this node
+			 * has a highmem zone, force kswapd to reclaim from
+			 * it to relieve lowmem pressure.
+			 */
+			if (buffer_heads_over_limit && is_highmem_idx(i)) {
+				end_zone = i;
+				break;
+			}
+
 			if (!zone_watermark_ok_safe(zone, order,
 					high_wmark_pages(zone), end_zone, 0)) {
 				all_zones_ok = 0;
#106 lore raw

Re: [ 101/175] mm: vmscan: forcibly scan highmem if there are too many buffer_heads pinning highmem

Quoted 3 lines · Nikola Ciprich

Hi, sorry it took me a bit longer.

here's my backport,

To 3.0.27 I presume; I've not tried it against 3.2.14, haven't checked if that would be much the same or not.

Quoted 2 lines

compiles fine, kernel boots without any problems.
please review.

Thank you for doing the work, but I'm afraid it looks wrong to me. I'd be more confident to leave it to Mel myself. Comments below.

mm/vmscan.c

Quoted 32 lines

n.

(backport of upstream commit cc715d99e529d470dde2f33a6614f255adea71f3)

mm: vmscan: forcibly scan highmem if there are too many buffer_heads pinning highmem

Stuart Foster reported on bugzilla that copying large amounts of data from NTFS caused an OOM kill on 32-bit X86 with 16G of memory. Andrew Morton correctly identified that the problem was NTFS was using 512 blocks meaning each page had 8 buffer_heads in low memory pinning it.

In the past, direct reclaim used to scan highmem even if the allocating process did not specify __GFP_HIGHMEM but not any more. kswapd no longer will reclaim from zones that are above the high watermark. The intention in both cases was to minimise unnecessary reclaim. The downside is on machines with large amounts of highmem that lowmem can be fully consumed by buffer_heads with nothing trying to free them.

The following patch is based on a suggestion by Andrew Morton to extend the buffer_heads_over_limit case to force kswapd and direct reclaim to scan the highmem zone regardless of the allocation request or watermarks.

Addresses https://bugzilla.kernel.org/show_bug.cgi?id=42578

---

diff -Naur linux-3.0/mm/vmscan.c linux-3.0-cc715d99e529d470dde2f33a6614f255adea71f3-backport/mm/vmscan.c

mm/vmscan.c +0 -0
@@ -1581,6 +1581,14 @@

diff -p is often more helpful, and especially so for this patch:
here we are in shrink_active_list().

Quoted 4 lines
mm/vmscan.c +1 -0
 			putback_lru_page(page);
 			continue;
 		}
+		

mm/vmscan.c line 1594

Quoted 10 lines
mm/vmscan.c +7 -0
+		if (unlikely(buffer_heads_over_limit)) {
+			if (page_has_private(page) && trylock_page(page)) {
+				if (page_has_private(page))
+					try_to_release_page(page, 0);
+				unlock_page(page);
+			}
+		}
 
 		if (page_referenced(page, 0, sc->mem_cgroup, &vm_flags)) {
 			nr_rotated += hpage_nr_pages(page);

I don't think this does functional harm, but it duplicates the work done by the pagevec_strip() you left in move_active_pages_to_lru(), so the resulting source would be puzzling.

We could remove the pagevec_strip(), but really, it was just a misunderstanding that led to my little buffer_heads_over_limit cleanup in one place getting merged in with Mel's significant buffer_heads_over_limit fix in another.

My cleanup doesn't deserve backporting to 3.0 or 3.2: I included it in the 3.3 backport to avoid raised eyebrows, but once we get back to kernels with pagevec_strip(), let's just leave this hunk out.

mm/vmscan.c

Quoted 1 line
mm/vmscan.c +0 -0
@@ -2053,6 +2061,14 @@

Here we are in all_unreclaimable().

mm/vmscan.c line 2071

Quoted 11 lines
mm/vmscan.c +8 -0
 	struct zoneref *z;
 	struct zone *zone;
 
+	/*
+	 * If the number of buffer_heads in the machine exceeds the maximum
+	 * allowed level, force direct reclaim to scan the highmem zone as
+	 * highmem pages could be pinning lowmem pages storing buffer_heads
+	 */
+	if (buffer_heads_over_limit)
+		sc->gfp_mask |= __GFP_HIGHMEM;
+

But in Mel's patch that belongs to shrink_zones():
I don't see a reason to move it in the backport.

mm/vmscan.c

Quoted 4 lines
mm/vmscan.c +0 -0
 	for_each_zone_zonelist_nodemask(zone, z, zonelist,
 			gfp_zone(sc->gfp_mask), sc->nodemask) {
 		if (!populated_zone(zone))
@@ -2514,7 +2530,8 @@

I think this hunk in balance_pgdat() is correct.

mm/vmscan.c

Quoted 10 lines
mm/vmscan.c +2 -1
 				(zone->present_pages +
 					KSWAPD_ZONE_BALANCE_GAP_RATIO-1) /
 				KSWAPD_ZONE_BALANCE_GAP_RATIO);
-			if (!zone_watermark_ok_safe(zone, order,
+			if ((buffer_heads_over_limit && is_highmem_idx(i)) ||
+				!zone_watermark_ok_safe(zone, order,
 					high_wmark_pages(zone) + balance_gap,
 					end_zone, 0)) {
 				shrink_zone(priority, zone, &sc);
@@ -2543,6 +2560,17 @@

But this hunk in balance_pgdat() comes too late: it should set end_zone in between the inactive_anon_is_low shrink_active_list and the !zone_watermark_ok_safe() setting of end_zone higher up, before the previous hunk.

Quoted 7 lines
mm/vmscan.c +4 -0
 				continue;
 			}
 
+			/*
+			 * If the number of buffer_heads in the machine
+			 * exceeds the maximum allowed level and this node
+			 * has a highmem zone, force kswapd to reclaim from

mm/vmscan.c line 2576

Quoted 10 lines
mm/vmscan.c +7 -0
+			 * it to relieve lowmem pressure.
+			 */
+			if (buffer_heads_over_limit && is_highmem_idx(i)) {
+				end_zone = i;
+				break;
+			}
+
 			if (!zone_watermark_ok_safe(zone, order,
 					high_wmark_pages(zone), end_zone, 0)) {
 				all_zones_ok = 0;

Hugh

author maintainer
#107 lore raw

PATCH 102/175 NFS: Properly handle the case where the delegation is revoked

In reply to Greg KH

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

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

From: Trond Myklebust <[email protected]>

commit a1d0b5eebc4fd6e0edb02688b35f17f67f42aea5 upstream.

If we know that the delegation stateid is bad or revoked, we need to remove that delegation as soon as possible, and then mark all the stateids that relied on that delegation for recovery. We cannot use the delegation as part of the recovery process.

Also note that NFSv4.1 uses a different error code (NFS4ERR_DELEG_REVOKED) to indicate that the delegation was revoked.

Finally, ensure that setlk() and setattr() can both recover safely from a revoked delegation.

---
 fs/nfs/delegation.c |   11 +++++++++++
 fs/nfs/delegation.h |    1 +
 fs/nfs/nfs4_fs.h    |    2 ++
 fs/nfs/nfs4proc.c   |   18 ++++++++++++++++--
 fs/nfs/nfs4state.c  |   29 +++++++++++++++++++++++++++--
 5 files changed, 57 insertions(+), 4 deletions(-)
fs/nfs/delegation.c +11 -0
@@ -466,6 +466,17 @@ static void nfs_delegation_run_state_man
 		nfs4_schedule_state_manager(clp);
 }
 
+void nfs_remove_bad_delegation(struct inode *inode)
+{
+	struct nfs_delegation *delegation;
+
+	delegation = nfs_detach_delegation(NFS_I(inode), NFS_SERVER(inode));
+	if (delegation) {
+		nfs_inode_find_state_and_recover(inode, &delegation->stateid);
+		nfs_free_delegation(delegation);
+	}
+}
+
 /**
  * nfs_expire_all_delegation_types
  * @clp: client to process
fs/nfs/delegation.h +1 -0
@@ -45,6 +45,7 @@ void nfs_expire_unreferenced_delegations
 void nfs_handle_cb_pathdown(struct nfs_client *clp);
 int nfs_client_return_marked_delegations(struct nfs_client *clp);
 int nfs_delegations_present(struct nfs_client *clp);
+void nfs_remove_bad_delegation(struct inode *inode);
 
 void nfs_delegation_mark_reclaim(struct nfs_client *clp);
 void nfs_delegation_reap_unclaimed(struct nfs_client *clp);
fs/nfs/nfs4_fs.h +2 -0
@@ -327,6 +327,8 @@ extern void nfs4_put_open_state(struct n
 extern void nfs4_close_state(struct nfs4_state *, fmode_t);
 extern void nfs4_close_sync(struct nfs4_state *, fmode_t);
 extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t);
+extern void nfs_inode_find_state_and_recover(struct inode *inode,
+		const nfs4_stateid *stateid);
 extern void nfs4_schedule_lease_recovery(struct nfs_client *);
 extern void nfs4_schedule_state_manager(struct nfs_client *);
 extern void nfs4_schedule_path_down_recovery(struct nfs_client *clp);
fs/nfs/nfs4proc.c +16 -2
@@ -265,8 +265,11 @@ static int nfs4_handle_exception(struct
 	switch(errorcode) {
 		case 0:
 			return 0;
+		case -NFS4ERR_DELEG_REVOKED:
 		case -NFS4ERR_ADMIN_REVOKED:
 		case -NFS4ERR_BAD_STATEID:
+			if (state != NULL)
+				nfs_remove_bad_delegation(state->inode);
 		case -NFS4ERR_OPENMODE:
 			if (state == NULL)
 				break;
@@ -1319,8 +1322,11 @@ int nfs4_open_delegation_recall(struct n
 				 * The show must go on: exit, but mark the
 				 * stateid as needing recovery.
 				 */
+			case -NFS4ERR_DELEG_REVOKED:
 			case -NFS4ERR_ADMIN_REVOKED:
 			case -NFS4ERR_BAD_STATEID:
+				nfs_inode_find_state_and_recover(state->inode,
+						stateid);
 				nfs4_schedule_stateid_recovery(server, state);
 			case -EKEYEXPIRED:
 				/*
@@ -1900,7 +1906,9 @@ static int nfs4_do_setattr(struct inode
 			   struct nfs4_state *state)
 {
 	struct nfs_server *server = NFS_SERVER(inode);
-	struct nfs4_exception exception = { };
+	struct nfs4_exception exception = {
+		.state = state,
+	};
 	int err;
 	do {
 		err = nfs4_handle_exception(server,
@@ -3714,8 +3722,11 @@ nfs4_async_handle_error(struct rpc_task
 	if (task->tk_status >= 0)
 		return 0;
 	switch(task->tk_status) {
+		case -NFS4ERR_DELEG_REVOKED:
 		case -NFS4ERR_ADMIN_REVOKED:
 		case -NFS4ERR_BAD_STATEID:
+			if (state != NULL)
+				nfs_remove_bad_delegation(state->inode);
 		case -NFS4ERR_OPENMODE:
 			if (state == NULL)
 				break;
@@ -4533,7 +4544,9 @@ out:
 
 static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
 {
-	struct nfs4_exception exception = { };
+	struct nfs4_exception exception = {
+		.state = state,
+	};
 	int err;
 
 	do {
@@ -4626,6 +4639,7 @@ int nfs4_lock_delegation_recall(struct n
 				 * The show must go on: exit, but mark the
 				 * stateid as needing recovery.
 				 */
+			case -NFS4ERR_DELEG_REVOKED:
 			case -NFS4ERR_ADMIN_REVOKED:
 			case -NFS4ERR_BAD_STATEID:
 			case -NFS4ERR_OPENMODE:
fs/nfs/nfs4state.c +27 -2
@@ -1132,12 +1132,37 @@ void nfs4_schedule_stateid_recovery(cons
 {
 	struct nfs_client *clp = server->nfs_client;
 
-	if (test_and_clear_bit(NFS_DELEGATED_STATE, &state->flags))
-		nfs_async_inode_return_delegation(state->inode, &state->stateid);
 	nfs4_state_mark_reclaim_nograce(clp, state);
 	nfs4_schedule_state_manager(clp);
 }
 
+void nfs_inode_find_state_and_recover(struct inode *inode,
+		const nfs4_stateid *stateid)
+{
+	struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
+	struct nfs_inode *nfsi = NFS_I(inode);
+	struct nfs_open_context *ctx;
+	struct nfs4_state *state;
+	bool found = false;
+
+	spin_lock(&inode->i_lock);
+	list_for_each_entry(ctx, &nfsi->open_files, list) {
+		state = ctx->state;
+		if (state == NULL)
+			continue;
+		if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
+			continue;
+		if (memcmp(state->stateid.data, stateid->data, sizeof(state->stateid.data)) != 0)
+			continue;
+		nfs4_state_mark_reclaim_nograce(clp, state);
+		found = true;
+	}
+	spin_unlock(&inode->i_lock);
+	if (found)
+		nfs4_schedule_state_manager(clp);
+}
+
+
 static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_recovery_ops *ops)
 {
 	struct inode *inode = state->inode;
author maintainer
#108 lore raw

PATCH 103/175 NFSv4: Return the delegation if the server returns NFS4ERR_OPENMODE

In reply to Greg KH

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

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

From: Trond Myklebust <[email protected]>

commit 3114ea7a24d3264c090556a2444fc6d2c06176d4 upstream.

If a setattr() fails because of an NFS4ERR_OPENMODE error, it is probably due to us holding a read delegation. Ensure that the recovery routines return that delegation in this case.

---
 fs/nfs/nfs4_fs.h  |    1 +
 fs/nfs/nfs4proc.c |   13 ++++++++++++-
 2 files changed, 13 insertions(+), 1 deletion(-)
fs/nfs/nfs4_fs.h +1 -0
@@ -193,6 +193,7 @@ struct nfs4_exception {
 	long timeout;
 	int retry;
 	struct nfs4_state *state;
+	struct inode *inode;
 };
 
 struct nfs4_state_recovery_ops {
fs/nfs/nfs4proc.c +12 -1
@@ -259,18 +259,28 @@ static int nfs4_handle_exception(struct
 {
 	struct nfs_client *clp = server->nfs_client;
 	struct nfs4_state *state = exception->state;
+	struct inode *inode = exception->inode;
 	int ret = errorcode;
 
 	exception->retry = 0;
 	switch(errorcode) {
 		case 0:
 			return 0;
+		case -NFS4ERR_OPENMODE:
+			if (nfs_have_delegation(inode, FMODE_READ)) {
+				nfs_inode_return_delegation(inode);
+				exception->retry = 1;
+				return 0;
+			}
+			if (state == NULL)
+				break;
+			nfs4_schedule_stateid_recovery(server, state);
+			goto wait_on_recovery;
 		case -NFS4ERR_DELEG_REVOKED:
 		case -NFS4ERR_ADMIN_REVOKED:
 		case -NFS4ERR_BAD_STATEID:
 			if (state != NULL)
 				nfs_remove_bad_delegation(state->inode);
-		case -NFS4ERR_OPENMODE:
 			if (state == NULL)
 				break;
 			nfs4_schedule_stateid_recovery(server, state);
@@ -1908,6 +1918,7 @@ static int nfs4_do_setattr(struct inode
 	struct nfs_server *server = NFS_SERVER(inode);
 	struct nfs4_exception exception = {
 		.state = state,
+		.inode = inode,
 	};
 	int err;
 	do {
author maintainer
#109 lore raw

PATCH 104/175 xfs: fix inode lookup race

In reply to Greg KH

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

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

From: Dave Chinner <[email protected]>

commit f30d500f809eca67a21704347ab14bb35877b5ee upstream.

When we get concurrent lookups of the same inode that is not in the per-AG inode cache, there is a race condition that triggers warnings in unlock_new_inode() indicating that we are initialising an inode that isn't in a the correct state for a new inode.

When we do an inode lookup via a file handle or a bulkstat, we don't serialise lookups at a higher level through the dentry cache (i.e. pathless lookup), and so we can get concurrent lookups of the same inode.

The race condition is between the insertion of the inode into the cache in the case of a cache miss and a concurrently lookup:

Thread 1 Thread 2
xfs_iget()
xfs_iget_cache_miss()
xfs_iread()
lock radix tree
radix_tree_insert()
rcu_read_lock radix_tree_lookup lock inode flags XFS_INEW not set igrab()
unlock inode flags rcu_read_unlock use uninitialised inode
.....
lock inode flags
set XFS_INEW
unlock inode flags
unlock radix tree
xfs_setup_inode()
inode flags = I_NEW
unlock_new_inode()
WARNING as inode flags != I_NEW

This can lead to inode corruption, inode list corruption, etc, and is generally a bad thing to occur.

Fix this by setting XFS_INEW before inserting the inode into the radix tree. This will ensure any concurrent lookup will find the new inode with XFS_INEW set and that forces the lookup to wait until the XFS_INEW flag is removed before allowing the lookup to succeed.

---
 fs/xfs/xfs_iget.c |   18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)
fs/xfs/xfs_iget.c +12 -6
@@ -350,9 +350,20 @@ xfs_iget_cache_miss(
 			BUG();
 	}
 
-	spin_lock(&pag->pag_ici_lock);
+	/*
+	 * These values must be set before inserting the inode into the radix
+	 * tree as the moment it is inserted a concurrent lookup (allowed by the
+	 * RCU locking mechanism) can find it and that lookup must see that this
+	 * is an inode currently under construction (i.e. that XFS_INEW is set).
+	 * The ip->i_flags_lock that protects the XFS_INEW flag forms the
+	 * memory barrier that ensures this detection works correctly at lookup
+	 * time.
+	 */
+	ip->i_udquot = ip->i_gdquot = NULL;
+	xfs_iflags_set(ip, XFS_INEW);
 
 	/* insert the new inode */
+	spin_lock(&pag->pag_ici_lock);
 	error = radix_tree_insert(&pag->pag_ici_root, agino, ip);
 	if (unlikely(error)) {
 		WARN_ON(error != -EEXIST);
@@ -360,11 +371,6 @@ xfs_iget_cache_miss(
 		error = EAGAIN;
 		goto out_preload_end;
 	}
-
-	/* These values _must_ be set before releasing the radix tree lock! */
-	ip->i_udquot = ip->i_gdquot = NULL;
-	xfs_iflags_set(ip, XFS_INEW);
-
 	spin_unlock(&pag->pag_ici_lock);
 	radix_tree_preload_end();
 
author maintainer
#110 lore raw

PATCH 105/175 CIFS: Respect negotiated MaxMpxCount

In reply to Greg KH

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

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

From: Pavel Shilovsky <[email protected]>

commit 10b9b98e41ba248a899f6175ce96ee91431b6194 upstream.

Some servers sets this value less than 50 that was hardcoded and we lost the connection if when we exceed this limit. Fix this by respecting this value - not sending more than the server allows.

---
 fs/cifs/cifsfs.c    |    8 ++++----
 fs/cifs/cifsglob.h  |   10 +++-------
 fs/cifs/cifssmb.c   |    9 +++++++--
 fs/cifs/connect.c   |   11 ++++-------
 fs/cifs/dir.c       |    6 ++++--
 fs/cifs/file.c      |    4 ++--
 fs/cifs/transport.c |    4 ++--
 7 files changed, 26 insertions(+), 26 deletions(-)
fs/cifs/cifsfs.c +4 -4
@@ -76,7 +76,7 @@ MODULE_PARM_DESC(cifs_min_small, "Small
 unsigned int cifs_max_pending = CIFS_MAX_REQ;
 module_param(cifs_max_pending, int, 0444);
 MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. "
-				   "Default: 50 Range: 2 to 256");
+				   "Default: 32767 Range: 2 to 32767.");
 unsigned short echo_retries = 5;
 module_param(echo_retries, ushort, 0644);
 MODULE_PARM_DESC(echo_retries, "Number of echo attempts before giving up and "
@@ -1116,9 +1116,9 @@ init_cifs(void)
 	if (cifs_max_pending < 2) {
 		cifs_max_pending = 2;
 		cFYI(1, "cifs_max_pending set to min of 2");
-	} else if (cifs_max_pending > 256) {
-		cifs_max_pending = 256;
-		cFYI(1, "cifs_max_pending set to max of 256");
+	} else if (cifs_max_pending > CIFS_MAX_REQ) {
+		cifs_max_pending = CIFS_MAX_REQ;
+		cFYI(1, "cifs_max_pending set to max of %u", CIFS_MAX_REQ);
 	}
 
 	rc = cifs_fscache_register();
fs/cifs/cifsglob.h +3 -7
@@ -55,14 +55,9 @@
 
 /*
  * MAX_REQ is the maximum number of requests that WE will send
- * on one socket concurrently. It also matches the most common
- * value of max multiplex returned by servers.  We may
- * eventually want to use the negotiated value (in case
- * future servers can handle more) when we are more confident that
- * we will not have problems oveloading the socket with pending
- * write data.
+ * on one socket concurrently.
  */
-#define CIFS_MAX_REQ 50
+#define CIFS_MAX_REQ 32767
 
 #define RFC1001_NAME_LEN 15
 #define RFC1001_NAME_LEN_WITH_NULL (RFC1001_NAME_LEN + 1)
@@ -263,6 +258,7 @@ struct TCP_Server_Info {
 	bool session_estab; /* mark when very first sess is established */
 	u16 dialect; /* dialect index that server chose */
 	enum securityEnum secType;
+	bool oplocks:1; /* enable oplocks */
 	unsigned int maxReq;	/* Clients should submit no more */
 	/* than maxReq distinct unanswered SMBs to the server when using  */
 	/* multiplexed reads or writes */
fs/cifs/cifssmb.c +7 -2
@@ -458,7 +458,10 @@ CIFSSMBNegotiate(unsigned int xid, struc
 			goto neg_err_exit;
 		}
 		server->sec_mode = (__u8)le16_to_cpu(rsp->SecurityMode);
-		server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
+		server->maxReq = min_t(unsigned int,
+				       le16_to_cpu(rsp->MaxMpxCount),
+				       cifs_max_pending);
+		server->oplocks = server->maxReq > 1 ? enable_oplocks : false;
 		server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
 		server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
 		/* even though we do not use raw we might as well set this
@@ -564,7 +567,9 @@ CIFSSMBNegotiate(unsigned int xid, struc
 
 	/* one byte, so no need to convert this or EncryptionKeyLen from
 	   little endian */
-	server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
+	server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
+			       cifs_max_pending);
+	server->oplocks = server->maxReq > 1 ? enable_oplocks : false;
 	/* probably no need to store and check maxvcs */
 	server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
 	server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
fs/cifs/connect.c +4 -7
@@ -642,14 +642,10 @@ static void clean_demultiplex_info(struc
 	spin_unlock(&GlobalMid_Lock);
 	wake_up_all(&server->response_q);
 
-	/*
-	 * Check if we have blocked requests that need to free. Note that
-	 * cifs_max_pending is normally 50, but can be set at module install
-	 * time to as little as two.
-	 */
+	/* Check if we have blocked requests that need to free. */
 	spin_lock(&GlobalMid_Lock);
-	if (atomic_read(&server->inFlight) >= cifs_max_pending)
-		atomic_set(&server->inFlight, cifs_max_pending - 1);
+	if (atomic_read(&server->inFlight) >= server->maxReq)
+		atomic_set(&server->inFlight, server->maxReq - 1);
 	/*
 	 * We do not want to set the max_pending too low or we could end up
 	 * with the counter going negative.
@@ -1910,6 +1906,7 @@ cifs_get_tcp_session(struct smb_vol *vol
 	tcp_ses->noautotune = volume_info->noautotune;
 	tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
 	atomic_set(&tcp_ses->inFlight, 0);
+	tcp_ses->maxReq = 1; /* enough to send negotiate request */
 	init_waitqueue_head(&tcp_ses->response_q);
 	init_waitqueue_head(&tcp_ses->request_q);
 	INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
fs/cifs/dir.c +4 -2
@@ -171,7 +171,7 @@ cifs_create(struct inode *inode, struct
 	}
 	tcon = tlink_tcon(tlink);
 
-	if (enable_oplocks)
+	if (tcon->ses->server->oplocks)
 		oplock = REQ_OPLOCK;
 
 	if (nd)
@@ -492,7 +492,7 @@ cifs_lookup(struct inode *parent_dir_ino
 {
 	int xid;
 	int rc = 0; /* to get around spurious gcc warning, set to zero here */
-	__u32 oplock = enable_oplocks ? REQ_OPLOCK : 0;
+	__u32 oplock;
 	__u16 fileHandle = 0;
 	bool posix_open = false;
 	struct cifs_sb_info *cifs_sb;
@@ -518,6 +518,8 @@ cifs_lookup(struct inode *parent_dir_ino
 	}
 	pTcon = tlink_tcon(tlink);
 
+	oplock = pTcon->ses->server->oplocks ? REQ_OPLOCK : 0;
+
 	/*
 	 * Don't allow the separator character in a path component.
 	 * The VFS will not allow "/", but "\" is allowed by posix.
fs/cifs/file.c +2 -2
@@ -380,7 +380,7 @@ int cifs_open(struct inode *inode, struc
 	cFYI(1, "inode = 0x%p file flags are 0x%x for %s",
 		 inode, file->f_flags, full_path);
 
-	if (enable_oplocks)
+	if (tcon->ses->server->oplocks)
 		oplock = REQ_OPLOCK;
 	else
 		oplock = 0;
@@ -505,7 +505,7 @@ static int cifs_reopen_file(struct cifsF
 	cFYI(1, "inode = 0x%p file flags 0x%x for %s",
 		 inode, pCifsFile->f_flags, full_path);
 
-	if (enable_oplocks)
+	if (tcon->ses->server->oplocks)
 		oplock = REQ_OPLOCK;
 	else
 		oplock = 0;
fs/cifs/transport.c +2 -2
@@ -265,12 +265,12 @@ static int wait_for_free_request(struct
 
 	spin_lock(&GlobalMid_Lock);
 	while (1) {
-		if (atomic_read(&server->inFlight) >= cifs_max_pending) {
+		if (atomic_read(&server->inFlight) >= server->maxReq) {
 			spin_unlock(&GlobalMid_Lock);
 			cifs_num_waiters_inc(server);
 			wait_event(server->request_q,
 				   atomic_read(&server->inFlight)
-				     < cifs_max_pending);
+				     < server->maxReq);
 			cifs_num_waiters_dec(server);
 			spin_lock(&GlobalMid_Lock);
 		} else {
#111 lore raw

Re: [ 105/175] CIFS: Respect negotiated MaxMpxCount

Quoted 2 lines · On Fri, 30 Mar 2012 12:50:10 -0700 Greg KH <[email protected]> wrote:

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

I'm not sure it's a good idea to put this patch into any stable release just yet. I think it's a correct and necessary fix, but it has some potential to cause regressions too (or uncover other preexisting problems with this code). Might it be best to wait until we have some more experience with this before we push it into stable?

Quoted 197 lines

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

From: Pavel Shilovsky <[email protected]>

commit 10b9b98e41ba248a899f6175ce96ee91431b6194 upstream.

Some servers sets this value less than 50 that was hardcoded and we lost the connection if when we exceed this limit. Fix this by respecting this value - not sending more than the server allows.

---
 fs/cifs/cifsfs.c    |    8 ++++----
 fs/cifs/cifsglob.h  |   10 +++-------
 fs/cifs/cifssmb.c   |    9 +++++++--
 fs/cifs/connect.c   |   11 ++++-------
 fs/cifs/dir.c       |    6 ++++--
 fs/cifs/file.c      |    4 ++--
 fs/cifs/transport.c |    4 ++--
 7 files changed, 26 insertions(+), 26 deletions(-)
fs/cifs/cifsfs.c +4 -4
@@ -76,7 +76,7 @@ MODULE_PARM_DESC(cifs_min_small, "Small
 unsigned int cifs_max_pending = CIFS_MAX_REQ;
 module_param(cifs_max_pending, int, 0444);
 MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. "
-				   "Default: 50 Range: 2 to 256");
+				   "Default: 32767 Range: 2 to 32767.");
 unsigned short echo_retries = 5;
 module_param(echo_retries, ushort, 0644);
 MODULE_PARM_DESC(echo_retries, "Number of echo attempts before giving up and "
@@ -1116,9 +1116,9 @@ init_cifs(void)
 	if (cifs_max_pending < 2) {
 		cifs_max_pending = 2;
 		cFYI(1, "cifs_max_pending set to min of 2");
-	} else if (cifs_max_pending > 256) {
-		cifs_max_pending = 256;
-		cFYI(1, "cifs_max_pending set to max of 256");
+	} else if (cifs_max_pending > CIFS_MAX_REQ) {
+		cifs_max_pending = CIFS_MAX_REQ;
+		cFYI(1, "cifs_max_pending set to max of %u", CIFS_MAX_REQ);
 	}
 
 	rc = cifs_fscache_register();
fs/cifs/cifsglob.h +3 -7
@@ -55,14 +55,9 @@
 
 /*
  * MAX_REQ is the maximum number of requests that WE will send
- * on one socket concurrently. It also matches the most common
- * value of max multiplex returned by servers.  We may
- * eventually want to use the negotiated value (in case
- * future servers can handle more) when we are more confident that
- * we will not have problems oveloading the socket with pending
- * write data.
+ * on one socket concurrently.
  */
-#define CIFS_MAX_REQ 50
+#define CIFS_MAX_REQ 32767
 
 #define RFC1001_NAME_LEN 15
 #define RFC1001_NAME_LEN_WITH_NULL (RFC1001_NAME_LEN + 1)
@@ -263,6 +258,7 @@ struct TCP_Server_Info {
 	bool session_estab; /* mark when very first sess is established */
 	u16 dialect; /* dialect index that server chose */
 	enum securityEnum secType;
+	bool oplocks:1; /* enable oplocks */
 	unsigned int maxReq;	/* Clients should submit no more */
 	/* than maxReq distinct unanswered SMBs to the server when using  */
 	/* multiplexed reads or writes */
fs/cifs/cifssmb.c +7 -2
@@ -458,7 +458,10 @@ CIFSSMBNegotiate(unsigned int xid, struc
 			goto neg_err_exit;
 		}
 		server->sec_mode = (__u8)le16_to_cpu(rsp->SecurityMode);
-		server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
+		server->maxReq = min_t(unsigned int,
+				       le16_to_cpu(rsp->MaxMpxCount),
+				       cifs_max_pending);
+		server->oplocks = server->maxReq > 1 ? enable_oplocks : false;
 		server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
 		server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
 		/* even though we do not use raw we might as well set this
@@ -564,7 +567,9 @@ CIFSSMBNegotiate(unsigned int xid, struc
 
 	/* one byte, so no need to convert this or EncryptionKeyLen from
 	   little endian */
-	server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
+	server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
+			       cifs_max_pending);
+	server->oplocks = server->maxReq > 1 ? enable_oplocks : false;
 	/* probably no need to store and check maxvcs */
 	server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
 	server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
fs/cifs/connect.c +4 -7
@@ -642,14 +642,10 @@ static void clean_demultiplex_info(struc
 	spin_unlock(&GlobalMid_Lock);
 	wake_up_all(&server->response_q);
 
-	/*
-	 * Check if we have blocked requests that need to free. Note that
-	 * cifs_max_pending is normally 50, but can be set at module install
-	 * time to as little as two.
-	 */
+	/* Check if we have blocked requests that need to free. */
 	spin_lock(&GlobalMid_Lock);
-	if (atomic_read(&server->inFlight) >= cifs_max_pending)
-		atomic_set(&server->inFlight, cifs_max_pending - 1);
+	if (atomic_read(&server->inFlight) >= server->maxReq)
+		atomic_set(&server->inFlight, server->maxReq - 1);
 	/*
 	 * We do not want to set the max_pending too low or we could end up
 	 * with the counter going negative.
@@ -1910,6 +1906,7 @@ cifs_get_tcp_session(struct smb_vol *vol
 	tcp_ses->noautotune = volume_info->noautotune;
 	tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
 	atomic_set(&tcp_ses->inFlight, 0);
+	tcp_ses->maxReq = 1; /* enough to send negotiate request */
 	init_waitqueue_head(&tcp_ses->response_q);
 	init_waitqueue_head(&tcp_ses->request_q);
 	INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
fs/cifs/dir.c +4 -2
@@ -171,7 +171,7 @@ cifs_create(struct inode *inode, struct
 	}
 	tcon = tlink_tcon(tlink);
 
-	if (enable_oplocks)
+	if (tcon->ses->server->oplocks)
 		oplock = REQ_OPLOCK;
 
 	if (nd)
@@ -492,7 +492,7 @@ cifs_lookup(struct inode *parent_dir_ino
 {
 	int xid;
 	int rc = 0; /* to get around spurious gcc warning, set to zero here */
-	__u32 oplock = enable_oplocks ? REQ_OPLOCK : 0;
+	__u32 oplock;
 	__u16 fileHandle = 0;
 	bool posix_open = false;
 	struct cifs_sb_info *cifs_sb;
@@ -518,6 +518,8 @@ cifs_lookup(struct inode *parent_dir_ino
 	}
 	pTcon = tlink_tcon(tlink);
 
+	oplock = pTcon->ses->server->oplocks ? REQ_OPLOCK : 0;
+
 	/*
 	 * Don't allow the separator character in a path component.
 	 * The VFS will not allow "/", but "\" is allowed by posix.
fs/cifs/file.c +2 -2
@@ -380,7 +380,7 @@ int cifs_open(struct inode *inode, struc
 	cFYI(1, "inode = 0x%p file flags are 0x%x for %s",
 		 inode, file->f_flags, full_path);
 
-	if (enable_oplocks)
+	if (tcon->ses->server->oplocks)
 		oplock = REQ_OPLOCK;
 	else
 		oplock = 0;
@@ -505,7 +505,7 @@ static int cifs_reopen_file(struct cifsF
 	cFYI(1, "inode = 0x%p file flags 0x%x for %s",
 		 inode, pCifsFile->f_flags, full_path);
 
-	if (enable_oplocks)
+	if (tcon->ses->server->oplocks)
 		oplock = REQ_OPLOCK;
 	else
 		oplock = 0;
fs/cifs/transport.c +2 -2
@@ -265,12 +265,12 @@ static int wait_for_free_request(struct
 
 	spin_lock(&GlobalMid_Lock);
 	while (1) {
-		if (atomic_read(&server->inFlight) >= cifs_max_pending) {
+		if (atomic_read(&server->inFlight) >= server->maxReq) {
 			spin_unlock(&GlobalMid_Lock);
 			cifs_num_waiters_inc(server);
 			wait_event(server->request_q,
 				   atomic_read(&server->inFlight)
-				     < cifs_max_pending);
+				     < server->maxReq);
 			cifs_num_waiters_dec(server);
 			spin_lock(&GlobalMid_Lock);
 		} else {
Signature · 1 line
Jeff Layton <[email protected]>
#112 lore raw

Re: [ 105/175] CIFS: Respect negotiated MaxMpxCount

Quoted 11 lines · Jeff Layton
Quoted 2 lines · On Fri, 30 Mar 2012 12:50:10 -0700 Greg KH <[email protected]> wrote:

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

I'm not sure it's a good idea to put this patch into any stable release just yet. I think it's a correct and necessary fix, but it has some potential to cause regressions too (or uncover other preexisting problems with this code). Might it be best to wait until we have some more experience with this before we push it into stable?

Delaying it a little is probably ok, but weigh that against the frequency/severity
of the problem that Pavel's fix addresses: ie sequential writes to some versions of Windows 7 and Windows Vista can fail partway through large file copy (which also causes those servers
to become unresponsive to subsequent connection requests
as well) so the fix does address a hot problem.

Signature · 3 lines
Thanks,

Steve
#113 lore raw

Re: [ 105/175] CIFS: Respect negotiated MaxMpxCount

Quoted 13 lines · On Sun, 1 Apr 2012 02:26:58 -0500 Steve French <[email protected]> wrote:
Quoted 11 lines · Jeff Layton
Quoted 2 lines · On Fri, 30 Mar 2012 12:50:10 -0700 Greg KH <[email protected]> wrote:

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

I'm not sure it's a good idea to put this patch into any stable release just yet. I think it's a correct and necessary fix, but it has some potential to cause regressions too (or uncover other preexisting problems with this code). Might it be best to wait until we have some more experience with this before we push it into stable?

Quoted 10 lines

Delaying it a little is probably ok, but weigh that against the frequency/severity
of the problem that Pavel's fix addresses: ie sequential writes to some versions of Windows 7 and Windows Vista can fail partway through large file copy (which also causes those servers
to become unresponsive to subsequent connection requests
as well) so the fix does address a hot problem.

I'm not disputing whether this patch is correct. It's clearly a bug that cifs.ko has never respected this value, and it's quite problematic with certain servers.

The problem is that we don't have any confirmation that:

a) this fixes any of the problems that we think it will

b) this doesn't introduce any regressions

The request slot allocation code is quite fiddly and fragile, and I think the potential for "b" is somewhat high. I'd feel more comfortable if we waited until we have more experience with this patch before merging it into stable.

Signature · 1 line
Jeff Layton <[email protected]>
author maintainer
#114 lore raw

PATCH 106/175 cifs: fix issue mounting of DFS ROOT when redirecting from one domain controller to the next

In reply to Greg KH

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

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

From: Jeff Layton <[email protected]>

commit 1daaae8fa4afe3df78ca34e724ed7e8187e4eb32 upstream.

This patch fixes an issue when cifs_mount receives a STATUS_BAD_NETWORK_NAME error during cifs_get_tcon but is able to continue after an DFS ROOT referral. In this case, the return code variable is not reset prior to trying to mount from the system referred to. Thus, is_path_accessible is not executed and the final DFS referral is not performed causing a mount error.

Use case: In DNS, example.com resolves to the secondary AD server ad2.example.com Our primary domain controller is ad1.example.com and has a DFS redirection set up from \\ad1\share\Users to \\files\share\Users. Mounting \\example.com\share\Users fails.

Regression introduced by commit 724d9f1.

---
 fs/cifs/connect.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
fs/cifs/connect.c +2 -1
@@ -3368,7 +3368,7 @@ cifs_ra_pages(struct cifs_sb_info *cifs_
 int
 cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
 {
-	int rc = 0;
+	int rc;
 	int xid;
 	struct cifs_ses *pSesInfo;
 	struct cifs_tcon *tcon;
@@ -3395,6 +3395,7 @@ try_mount_again:
 		FreeXid(xid);
 	}
 #endif
+	rc = 0;
 	tcon = NULL;
 	pSesInfo = NULL;
 	srvTcp = NULL;
author maintainer
#115 lore raw

PATCH 107/175 CIFS: Fix a spurious error in cifs_push_posix_locks

In reply to Greg KH

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

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

From: Pavel Shilovsky <[email protected]>

commit ce85852b90a214cf577fc1b4f49d99fd7e98784a upstream.

---
 fs/cifs/file.c |   19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)
fs/cifs/file.c +10 -9
@@ -960,9 +960,9 @@ cifs_push_posix_locks(struct cifsFileInf
 	INIT_LIST_HEAD(&locks_to_send);
 
 	/*
-	 * Allocating count locks is enough because no locks can be added to
-	 * the list while we are holding cinode->lock_mutex that protects
-	 * locking operations of this inode.
+	 * Allocating count locks is enough because no FL_POSIX locks can be
+	 * added to the list while we are holding cinode->lock_mutex that
+	 * protects locking operations of this inode.
 	 */
 	for (; i < count; i++) {
 		lck = kmalloc(sizeof(struct lock_to_push), GFP_KERNEL);
@@ -973,18 +973,20 @@ cifs_push_posix_locks(struct cifsFileInf
 		list_add_tail(&lck->llist, &locks_to_send);
 	}
 
-	i = 0;
 	el = locks_to_send.next;
 	lock_flocks();
 	cifs_for_each_lock(cfile->dentry->d_inode, before) {
+		flock = *before;
+		if ((flock->fl_flags & FL_POSIX) == 0)
+			continue;
 		if (el == &locks_to_send) {
-			/* something is really wrong */
+			/*
+			 * The list ended. We don't have enough allocated
+			 * structures - something is really wrong.
+			 */
 			cERROR(1, "Can't push all brlocks!");
 			break;
 		}
-		flock = *before;
-		if ((flock->fl_flags & FL_POSIX) == 0)
-			continue;
 		length = 1 + flock->fl_end - flock->fl_start;
 		if (flock->fl_type == F_RDLCK || flock->fl_type == F_SHLCK)
 			type = CIFS_RDLCK;
@@ -996,7 +998,6 @@ cifs_push_posix_locks(struct cifsFileInf
 		lck->length = length;
 		lck->type = type;
 		lck->offset = flock->fl_start;
-		i++;
 		el = el->next;
 	}
 	unlock_flocks();
author maintainer
#116 lore raw

PATCH 108/175 UBI: fix error handling in ubi_scan()

In reply to Greg KH

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

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

From: Richard Weinberger <[email protected]>

commit a29852be492d61001d86c6ebf5fff9b93d7b4be9 upstream.

Two bad things can happen in ubi_scan():
1. If kmem_cache_create() fails we jump to out_si and call ubi_scan_destroy_si() which calls kmem_cache_destroy(). But si->scan_leb_slab is NULL.
2. If process_eb() fails we jump to out_vidh, call kmem_cache_destroy() and ubi_scan_destroy_si() which calls again kmem_cache_destroy().

---
 drivers/mtd/ubi/scan.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/mtd/ubi/scan.c +4 -4
@@ -1174,7 +1174,7 @@ struct ubi_scan_info *ubi_scan(struct ub
 
 	ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
 	if (!ech)
-		goto out_slab;
+		goto out_si;
 
 	vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
 	if (!vidh)
@@ -1235,8 +1235,6 @@ out_vidh:
 	ubi_free_vid_hdr(ubi, vidh);
 out_ech:
 	kfree(ech);
-out_slab:
-	kmem_cache_destroy(si->scan_leb_slab);
 out_si:
 	ubi_scan_destroy_si(si);
 	return ERR_PTR(err);
@@ -1325,7 +1323,9 @@ void ubi_scan_destroy_si(struct ubi_scan
 		}
 	}
 
-	kmem_cache_destroy(si->scan_leb_slab);
+	if (si->scan_leb_slab)
+		kmem_cache_destroy(si->scan_leb_slab);
+
 	kfree(si);
 }
 
author maintainer
#117 lore raw

PATCH 109/175 UBI: fix eraseblock picking criteria

In reply to Greg KH

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

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

From: Artem Bityutskiy <[email protected]>

commit 7eb3aa65853e1b223bfc786b023b702018cb76c0 upstream.

The 'find_wl_entry()' function expects the maximum difference as the second argument, not the maximum absolute value. So the "unknown" eraseblock picking was incorrect, as Shmulik Ladkani spotted. This patch fixes the issue.

---
 drivers/mtd/ubi/wl.c |   10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)
drivers/mtd/ubi/wl.c +4 -6
@@ -389,7 +389,7 @@ static struct ubi_wl_entry *find_wl_entr
  */
 int ubi_wl_get_peb(struct ubi_device *ubi, int dtype)
 {
-	int err, medium_ec;
+	int err;
 	struct ubi_wl_entry *e, *first, *last;
 
 	ubi_assert(dtype == UBI_LONGTERM || dtype == UBI_SHORTTERM ||
@@ -427,7 +427,7 @@ retry:
 		 * For unknown data we pick a physical eraseblock with medium
 		 * erase counter. But we by no means can pick a physical
 		 * eraseblock with erase counter greater or equivalent than the
-		 * lowest erase counter plus %WL_FREE_MAX_DIFF.
+		 * lowest erase counter plus %WL_FREE_MAX_DIFF/2.
 		 */
 		first = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry,
 					u.rb);
@@ -436,10 +436,8 @@ retry:
 		if (last->ec - first->ec < WL_FREE_MAX_DIFF)
 			e = rb_entry(ubi->free.rb_node,
 					struct ubi_wl_entry, u.rb);
-		else {
-			medium_ec = (first->ec + WL_FREE_MAX_DIFF)/2;
-			e = find_wl_entry(&ubi->free, medium_ec);
-		}
+		else
+			e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF/2);
 		break;
 	case UBI_SHORTTERM:
 		/*
author maintainer
#118 lore raw

PATCH 110/175 SUNRPC: We must not use list_for_each_entry_safe() in rpc_wake_up()

In reply to Greg KH

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

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

From: Trond Myklebust <[email protected]>

commit 540a0f7584169651f485e8ab67461fcb06934e38 upstream.

The problem is that for the case of priority queues, we
have to assume that __rpc_remove_wait_queue_priority will move new elements from the tk_wait.links lists into the queue->tasks[] list. We therefore cannot use list_for_each_entry_safe() on queue->tasks[], since that will skip these new tasks that __rpc_remove_wait_queue_priority is adding.

Without this fix, rpc_wake_up and rpc_wake_up_status will both fail to wake up all functions on priority wait queues, which can result in some nasty hangs.

---
 net/sunrpc/sched.c |   15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)
net/sunrpc/sched.c +11 -4
@@ -501,14 +501,18 @@ EXPORT_SYMBOL_GPL(rpc_wake_up_next);
  */
 void rpc_wake_up(struct rpc_wait_queue *queue)
 {
-	struct rpc_task *task, *next;
 	struct list_head *head;
 
 	spin_lock_bh(&queue->lock);
 	head = &queue->tasks[queue->maxpriority];
 	for (;;) {
-		list_for_each_entry_safe(task, next, head, u.tk_wait.list)
+		while (!list_empty(head)) {
+			struct rpc_task *task;
+			task = list_first_entry(head,
+					struct rpc_task,
+					u.tk_wait.list);
 			rpc_wake_up_task_queue_locked(queue, task);
+		}
 		if (head == &queue->tasks[0])
 			break;
 		head--;
@@ -526,13 +530,16 @@ EXPORT_SYMBOL_GPL(rpc_wake_up);
  */
 void rpc_wake_up_status(struct rpc_wait_queue *queue, int status)
 {
-	struct rpc_task *task, *next;
 	struct list_head *head;
 
 	spin_lock_bh(&queue->lock);
 	head = &queue->tasks[queue->maxpriority];
 	for (;;) {
-		list_for_each_entry_safe(task, next, head, u.tk_wait.list) {
+		while (!list_empty(head)) {
+			struct rpc_task *task;
+			task = list_first_entry(head,
+					struct rpc_task,
+					u.tk_wait.list);
 			task->tk_status = status;
 			rpc_wake_up_task_queue_locked(queue, task);
 		}
author maintainer
#119 lore raw

PATCH 111/175 usbnet: increase URB reference count before usb_unlink_urb

In reply to Greg KH

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

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

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

commit 0956a8c20b23d429e79ff86d4325583fc06f9eb4 upstream.

Commit 4231d47e6fe69f061f96c98c30eaf9fb4c14b96d(net/usbnet: avoid recursive locking in usbnet_stop()) fixes the recursive locking problem by releasing the skb queue lock, but it makes usb_unlink_urb racing with defer_bh, and the URB to being unlinked may be freed before or during calling usb_unlink_urb, so use-after-free problem may be triggerd inside usb_unlink_urb.

The patch fixes the use-after-free problem by increasing URB reference count with skb queue lock held before calling usb_unlink_urb, so the URB won't be freed until return from usb_unlink_urb.

---
 drivers/net/usb/usbnet.c |    9 +++++++++
 1 file changed, 9 insertions(+)
drivers/net/usb/usbnet.c +9 -0
@@ -589,6 +589,14 @@ static int unlink_urbs (struct usbnet *d
 		entry = (struct skb_data *) skb->cb;
 		urb = entry->urb;
 
+		/*
+		 * Get reference count of the URB to avoid it to be
+		 * freed during usb_unlink_urb, which may trigger
+		 * use-after-free problem inside usb_unlink_urb since
+		 * usb_unlink_urb is always racing with .complete
+		 * handler(include defer_bh).
+		 */
+		usb_get_urb(urb);
 		spin_unlock_irqrestore(&q->lock, flags);
 		// during some PM-driven resume scenarios,
 		// these (async) unlinks complete immediately
@@ -597,6 +605,7 @@ static int unlink_urbs (struct usbnet *d
 			netdev_dbg(dev->net, "unlink urb err, %d\n", retval);
 		else
 			count++;
+		usb_put_urb(urb);
 		spin_lock_irqsave(&q->lock, flags);
 	}
 	spin_unlock_irqrestore (&q->lock, flags);
author maintainer
#120 lore raw

PATCH 112/175 usbnet: dont clear urb->dev in tx_complete

In reply to Greg KH

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

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

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

commit 5d5440a835710d09f0ef18da5000541ec98b537a upstream.

URB unlinking is always racing with its completion and tx_complete may be called before or during running usb_unlink_urb, so tx_complete must not clear urb->dev since it will be used in unlink path, otherwise invalid memory accesses or usb device leak may be caused inside usb_unlink_urb.

---
 drivers/net/usb/usbnet.c |    1 -
 1 file changed, 1 deletion(-)
drivers/net/usb/usbnet.c +0 -1
@@ -1037,7 +1037,6 @@ static void tx_complete (struct urb *urb
 	}
 
 	usb_autopm_put_interface_async(dev->intf);
-	urb->dev = NULL;
 	entry->state = tx_done;
 	defer_bh(dev, skb, &dev->txq);
 }
author maintainer
#121 lore raw

PATCH 113/175 x86-32: Fix typo for mq_getsetattr in syscall table

In reply to Greg KH

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

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

From: Thierry Reding <[email protected]>

commit 13354dc412c36fe554f9904a92f1268c74af7e87 upstream.

Syscall 282 was mistakenly named mq_getsetaddr instead of mq_getsetattr. When building uClibc against the Linux kernel this would result in a shared library that doesn't provide the mq_getattr() and mq_setattr() functions.

---
 arch/x86/syscalls/syscall_32.tbl |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/syscalls/syscall_32.tbl +1 -1
@@ -288,7 +288,7 @@
 279	i386	mq_timedsend		sys_mq_timedsend		compat_sys_mq_timedsend
 280	i386	mq_timedreceive		sys_mq_timedreceive		compat_sys_mq_timedreceive
 281	i386	mq_notify		sys_mq_notify			compat_sys_mq_notify
-282	i386	mq_getsetaddr		sys_mq_getsetattr		compat_sys_mq_getsetattr
+282	i386	mq_getsetattr		sys_mq_getsetattr		compat_sys_mq_getsetattr
 283	i386	kexec_load		sys_kexec_load			compat_sys_kexec_load
 284	i386	waitid			sys_waitid			compat_sys_waitid
 # 285 sys_setaltroot
author maintainer
#122 lore raw

PATCH 114/175 x86-32: Fix endless loop when processing signals for kernel tasks

In reply to Greg KH

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

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

From: Dmitry Adamushko <[email protected]>

commit 29a2e2836ff9ea65a603c89df217f4198973a74f upstream.

The problem occurs on !CONFIG_VM86 kernels [1] when a kernel-mode task returns from a system call with a pending signal.

A real-life scenario is a child of 'khelper' returning from a failed kernel_execve() in ____call_usermodehelper() [ kernel/kmod.c ]. kernel_execve() fails due to a pending SIGKILL, which is the result of "kill -9 -1" (at least, busybox's init does it upon reboot).

The loop is as follows:

* syscall_exit_work:
- work_pending: // start_of_the_loop
- work_notify_sig:
- do_notify_resume()
- do_signal()
- if (!user_mode(regs)) return;
- resume_userspace // TIF_SIGPENDING is still set
- work_pending // so we call work_pending => goto

                            // start_of_the_loop

More information can be found in another LKML thread:
http://www.serverphorums.com/read.php?12,457826

[1] the problem was also seen on MIPS.

---
 arch/x86/kernel/entry_32.S |   17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)
arch/x86/kernel/entry_32.S +10 -7
@@ -98,12 +98,6 @@
 #endif
 .endm
 
-#ifdef CONFIG_VM86
-#define resume_userspace_sig	check_userspace
-#else
-#define resume_userspace_sig	resume_userspace
-#endif
-
 /*
  * User gs save/restore
  *
@@ -327,10 +321,19 @@ ret_from_exception:
 	preempt_stop(CLBR_ANY)
 ret_from_intr:
 	GET_THREAD_INFO(%ebp)
-check_userspace:
+resume_userspace_sig:
+#ifdef CONFIG_VM86
 	movl PT_EFLAGS(%esp), %eax	# mix EFLAGS and CS
 	movb PT_CS(%esp), %al
 	andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax
+#else
+	/*
+	 * We can be coming here from a syscall done in the kernel space,
+	 * e.g. a failed kernel_execve().
+	 */
+	movl PT_CS(%esp), %eax
+	andl $SEGMENT_RPL_MASK, %eax
+#endif
 	cmpl $USER_RPL, %eax
 	jb resume_kernel		# not returning to v8086 or userspace
 
author maintainer
#123 lore raw

PATCH 115/175 proc-ns: use d_set_d_op() API to set dentry ops in proc_ns_instantiate().

In reply to Greg KH

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

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

From: Pravin B Shelar <[email protected]>

commit 1b26c9b334044cff6d1d2698f2be41bc7d9a0864 upstream.

The namespace cleanup path leaks a dentry which holds a reference count on a network namespace. Keeping that network namespace from being freed when the last user goes away. Leaving things like vlan devices in the leaked network namespace.

If you use ip netns add for much real work this problem becomes apparent pretty quickly. It light testing the problem hides because frequently you simply don't notice the leak.

Use d_set_d_op() so that DCACHE_OP_* flags are set correctly.

This issue exists back to 3.0.

---
 fs/proc/namespaces.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/proc/namespaces.c +1 -1
@@ -53,7 +53,7 @@ static struct dentry *proc_ns_instantiat
 	ei->ns_ops    = ns_ops;
 	ei->ns	      = ns;
 
-	dentry->d_op = &pid_dentry_operations;
+	d_set_d_op(dentry, &pid_dentry_operations);
 	d_add(dentry, inode);
 	/* Close the race of the process dying before we return the dentry */
 	if (pid_revalidate(dentry, NULL))
author maintainer
#124 lore raw

PATCH 116/175 iommu/amd: Fix section warning for prealloc_protection_domains

In reply to Greg KH

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

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

From: Steffen Persvold <[email protected]>

commit cebd5fa4d3046d5b43ce1836a0120612822a7fb0 upstream.

Fix the following section warning in drivers/iommu/amd_iommu.c :

WARNING: vmlinux.o(.text+0x526e77): Section mismatch in reference from the function prealloc_protection_domains() to the function .init.text:alloc_passthrough_domain() The function prealloc_protection_domains() references
the function __init alloc_passthrough_domain().
This is often because prealloc_protection_domains lacks a __init
annotation or the annotation of alloc_passthrough_domain is wrong.

---
 drivers/iommu/amd_iommu.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/iommu/amd_iommu.c +1 -1
@@ -2804,7 +2804,7 @@ static int amd_iommu_dma_supported(struc
  * we don't need to preallocate the protection domains anymore.
  * For now we have to.
  */
-static void prealloc_protection_domains(void)
+static void __init prealloc_protection_domains(void)
 {
 	struct iommu_dev_data *dev_data;
 	struct dma_ops_domain *dma_dom;
author maintainer
#125 lore raw

PATCH 117/175 iommu/amd: Make sure IOMMU interrupts are re-enabled on resume

In reply to Greg KH

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

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

From: Joerg Roedel <[email protected]>

commit 9ddd592a191b32f2ee6c4b6ed2bd52665c3a49f5 upstream.

Unfortunatly the interrupts for the event log and the peripheral page-faults are only enabled at boot but not re-enabled at resume. Fix that.

---
 drivers/iommu/amd_iommu_init.c |   30 ++++++++++++++++++++----------
 1 file changed, 20 insertions(+), 10 deletions(-)
drivers/iommu/amd_iommu_init.c +20 -10
@@ -1131,8 +1131,9 @@ static int iommu_setup_msi(struct amd_io
 {
 	int r;
 
-	if (pci_enable_msi(iommu->dev))
-		return 1;
+	r = pci_enable_msi(iommu->dev);
+	if (r)
+		return r;
 
 	r = request_threaded_irq(iommu->dev->irq,
 				 amd_iommu_int_handler,
@@ -1142,27 +1143,36 @@ static int iommu_setup_msi(struct amd_io
 
 	if (r) {
 		pci_disable_msi(iommu->dev);
-		return 1;
+		return r;
 	}
 
 	iommu->int_enabled = true;
-	iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
-
-	if (iommu->ppr_log != NULL)
-		iommu_feature_enable(iommu, CONTROL_PPFINT_EN);
 
 	return 0;
 }
 
 static int iommu_init_msi(struct amd_iommu *iommu)
 {
+	int ret;
+
 	if (iommu->int_enabled)
-		return 0;
+		goto enable_faults;
 
 	if (pci_find_capability(iommu->dev, PCI_CAP_ID_MSI))
-		return iommu_setup_msi(iommu);
+		ret = iommu_setup_msi(iommu);
+	else
+		ret = -ENODEV;
+
+	if (ret)
+		return ret;
 
-	return 1;
+enable_faults:
+	iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
+
+	if (iommu->ppr_log != NULL)
+		iommu_feature_enable(iommu, CONTROL_PPFINT_EN);
+
+	return 0;
 }
 
 /****************************************************************************
#126 lore raw

Re: [ 117/175] iommu/amd: Make sure IOMMU interrupts are re-enabled on resume

Quoted 11 lines · Greg KH

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

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

From: Joerg Roedel <[email protected]>

commit 9ddd592a191b32f2ee6c4b6ed2bd52665c3a49f5 upstream.

Unfortunatly the interrupts for the event log and the peripheral page-faults are only enabled at boot but not re-enabled at resume. Fix that.

[...]

It looks like this should be applicable to 3.0 and 3.2 as well, but only for the event log. I'm attaching my (untested) backports for consideration.

Ben.

Signature · 2 lines
Ben Hutchings
Reality is just a crutch for people who can't handle science fiction.

From ed3845ba84e5dbe3593dddf06b6377960f95712d Mon Sep 17 00:00:00 2001
From: Joerg Roedel <[email protected]>
Date: Thu, 15 Mar 2012 16:29:47 +0100
Subject: [PATCH] iommu/amd: Make sure IOMMU interrupts are re-enabled on
resume

commit 9ddd592a191b32f2ee6c4b6ed2bd52665c3a49f5 upstream.

Unfortunatly the interrupts for the event log and the peripheral page-faults are only enabled at boot but not re-enabled at resume. Fix that.

[bwh: Backport to 3.0:
- Drop change to PPR log which was added in 3.3
- Source is under arch/x86/kernel]

---
 arch/x86/kernel/amd_iommu_init.c |   24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)
arch/x86/kernel/amd_iommu_init.c +17 -7
index bfc8453..33df6e8 100644
@@ -1031,8 +1031,9 @@ static int iommu_setup_msi(struct amd_iommu *iommu)
 {
 	int r;
 
-	if (pci_enable_msi(iommu->dev))
-		return 1;
+	r = pci_enable_msi(iommu->dev);
+	if (r)
+		return r;
 
 	r = request_threaded_irq(iommu->dev->irq,
 				 amd_iommu_int_handler,
@@ -1042,24 +1043,33 @@ static int iommu_setup_msi(struct amd_iommu *iommu)
 
 	if (r) {
 		pci_disable_msi(iommu->dev);
-		return 1;
+		return r;
 	}
 
 	iommu->int_enabled = true;
-	iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
 
 	return 0;
 }
 
 static int iommu_init_msi(struct amd_iommu *iommu)
 {
+	int ret;
+
 	if (iommu->int_enabled)
-		return 0;
+		goto enable_faults;
 
 	if (pci_find_capability(iommu->dev, PCI_CAP_ID_MSI))
-		return iommu_setup_msi(iommu);
+		ret = iommu_setup_msi(iommu);
+	else
+		ret = -ENODEV;
 
-	return 1;
+	if (ret)
+		return ret;
+
+enable_faults:
+	iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
+
+	return 0;
 }
 
 /****************************************************************************
Signature · 1 line
1.7.9.5

From ce1ae4a46ead4899939002d48e23678601ec6969 Mon Sep 17 00:00:00 2001
From: Joerg Roedel <[email protected]>
Date: Thu, 15 Mar 2012 16:29:47 +0100
Subject: [PATCH] iommu/amd: Make sure IOMMU interrupts are re-enabled on
resume

commit 9ddd592a191b32f2ee6c4b6ed2bd52665c3a49f5 upstream.

Unfortunatly the interrupts for the event log and the peripheral page-faults are only enabled at boot but not re-enabled at resume. Fix that.

[bwh: Backport to 3.2: drop change to PPR log which was added in 3.3]
---
 drivers/iommu/amd_iommu_init.c |   24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)
drivers/iommu/amd_iommu_init.c +17 -7
index 5c74179..20d5852 100644
@@ -1033,8 +1033,9 @@ static int iommu_setup_msi(struct amd_iommu *iommu)
 {
 	int r;
 
-	if (pci_enable_msi(iommu->dev))
-		return 1;
+	r = pci_enable_msi(iommu->dev);
+	if (r)
+		return r;
 
 	r = request_threaded_irq(iommu->dev->irq,
 				 amd_iommu_int_handler,
@@ -1044,24 +1045,33 @@ static int iommu_setup_msi(struct amd_iommu *iommu)
 
 	if (r) {
 		pci_disable_msi(iommu->dev);
-		return 1;
+		return r;
 	}
 
 	iommu->int_enabled = true;
-	iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
 
 	return 0;
 }
 
 static int iommu_init_msi(struct amd_iommu *iommu)
 {
+	int ret;
+
 	if (iommu->int_enabled)
-		return 0;
+		goto enable_faults;
 
 	if (pci_find_capability(iommu->dev, PCI_CAP_ID_MSI))
-		return iommu_setup_msi(iommu);
+		ret = iommu_setup_msi(iommu);
+	else
+		ret = -ENODEV;
 
-	return 1;
+	if (ret)
+		return ret;
+
+enable_faults:
+	iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
+
+	return 0;
 }
 
 /****************************************************************************
Signature · 1 line
1.7.9.5
Acked-by
#127 lore raw

Re: [ 117/175] iommu/amd: Make sure IOMMU interrupts are re-enabled on resume

Right, this fix is also required for 3.2 and 3.0.

Quoted 9 lines · Ben Hutchings
Quoted 8 lines · Greg KH

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

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

From: Joerg Roedel <[email protected]>

commit 9ddd592a191b32f2ee6c4b6ed2bd52665c3a49f5 upstream.

Quoted 8 lines
Quoted 3 lines

Unfortunatly the interrupts for the event log and the peripheral page-faults are only enabled at boot but not re-enabled at resume. Fix that.

[...]

It looks like this should be applicable to 3.0 and 3.2 as well, but only for the event log. I'm attaching my (untested) backports for consideration.

The backport looks good.

Quoted 164 lines

Ben.

Signature · 23 lines
Ben Hutchings
Reality is just a crutch for people who can't handle science fiction.

From ed3845ba84e5dbe3593dddf06b6377960f95712d Mon Sep 17 00:00:00 2001
From: Joerg Roedel <[email protected]>
Date: Thu, 15 Mar 2012 16:29:47 +0100
Subject: [PATCH] iommu/amd: Make sure IOMMU interrupts are re-enabled on
 resume

commit 9ddd592a191b32f2ee6c4b6ed2bd52665c3a49f5 upstream.

Unfortunatly the interrupts for the event log and the
peripheral page-faults are only enabled at boot but not
re-enabled at resume. Fix that.

Signed-off-by: Joerg Roedel <[email protected]>
[bwh: Backport to 3.0:
 - Drop change to PPR log which was added in 3.3
 - Source is under arch/x86/kernel]
Signed-off-by: Ben Hutchings <[email protected]>
---
 arch/x86/kernel/amd_iommu_init.c |   24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)
arch/x86/kernel/amd_iommu_init.c +17 -7
index bfc8453..33df6e8 100644
@@ -1031,8 +1031,9 @@ static int iommu_setup_msi(struct amd_iommu *iommu)
 {
 	int r;
 
-	if (pci_enable_msi(iommu->dev))
-		return 1;
+	r = pci_enable_msi(iommu->dev);
+	if (r)
+		return r;
 
 	r = request_threaded_irq(iommu->dev->irq,
 				 amd_iommu_int_handler,
@@ -1042,24 +1043,33 @@ static int iommu_setup_msi(struct amd_iommu *iommu)
 
 	if (r) {
 		pci_disable_msi(iommu->dev);
-		return 1;
+		return r;
 	}
 
 	iommu->int_enabled = true;
-	iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
 
 	return 0;
 }
 
 static int iommu_init_msi(struct amd_iommu *iommu)
 {
+	int ret;
+
 	if (iommu->int_enabled)
-		return 0;
+		goto enable_faults;
 
 	if (pci_find_capability(iommu->dev, PCI_CAP_ID_MSI))
-		return iommu_setup_msi(iommu);
+		ret = iommu_setup_msi(iommu);
+	else
+		ret = -ENODEV;
 
-	return 1;
+	if (ret)
+		return ret;
+
+enable_faults:
+	iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
+
+	return 0;
 }
 
 /****************************************************************************
Signature · 21 lines
1.7.9.5


From ce1ae4a46ead4899939002d48e23678601ec6969 Mon Sep 17 00:00:00 2001
From: Joerg Roedel <[email protected]>
Date: Thu, 15 Mar 2012 16:29:47 +0100
Subject: [PATCH] iommu/amd: Make sure IOMMU interrupts are re-enabled on
 resume

commit 9ddd592a191b32f2ee6c4b6ed2bd52665c3a49f5 upstream.

Unfortunatly the interrupts for the event log and the
peripheral page-faults are only enabled at boot but not
re-enabled at resume. Fix that.

Signed-off-by: Joerg Roedel <[email protected]>
[bwh: Backport to 3.2: drop change to PPR log which was added in 3.3]
Signed-off-by: Ben Hutchings <[email protected]>
---
 drivers/iommu/amd_iommu_init.c |   24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)
drivers/iommu/amd_iommu_init.c +17 -7
index 5c74179..20d5852 100644
@@ -1033,8 +1033,9 @@ static int iommu_setup_msi(struct amd_iommu *iommu)
 {
 	int r;
 
-	if (pci_enable_msi(iommu->dev))
-		return 1;
+	r = pci_enable_msi(iommu->dev);
+	if (r)
+		return r;
 
 	r = request_threaded_irq(iommu->dev->irq,
 				 amd_iommu_int_handler,
@@ -1044,24 +1045,33 @@ static int iommu_setup_msi(struct amd_iommu *iommu)
 
 	if (r) {
 		pci_disable_msi(iommu->dev);
-		return 1;
+		return r;
 	}
 
 	iommu->int_enabled = true;
-	iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
 
 	return 0;
 }
 
 static int iommu_init_msi(struct amd_iommu *iommu)
 {
+	int ret;
+
 	if (iommu->int_enabled)
-		return 0;
+		goto enable_faults;
 
 	if (pci_find_capability(iommu->dev, PCI_CAP_ID_MSI))
-		return iommu_setup_msi(iommu);
+		ret = iommu_setup_msi(iommu);
+	else
+		ret = -ENODEV;
 
-	return 1;
+	if (ret)
+		return ret;
+
+enable_faults:
+	iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
+
+	return 0;
 }
 
 /****************************************************************************
Signature · 1 line
1.7.9.5
Signature · 5 lines
AMD Operating System Research Center

Advanced Micro Devices GmbH Einsteinring 24 85609 Dornach
General Managers: Alberto Bozzo
Registration: Dornach, Landkr. Muenchen; Registerger. Muenchen, HRB Nr. 43632
author maintainer
#128 lore raw

Re: [ 117/175] iommu/amd: Make sure IOMMU interrupts are re-enabled on resume

Quoted 1 line · Joerg Roedel

Right, this fix is also required for 3.2 and 3.0.

Wait, what?

Can someone send me the needed fix, in a new thread as I seem to have lost this one :(

thanks,

greg k-h

#129 lore raw

Re: [ 117/175] iommu/amd: Make sure IOMMU interrupts are re-enabled on resume

Quoted 7 lines · Greg KH
Quoted 1 line · Joerg Roedel

Right, this fix is also required for 3.2 and 3.0.

Wait, what?

Can someone send me the needed fix, in a new thread as I seem to have lost this one :(

No problem. I send you the backported fix for 3.2 and 3.0.

Signature · 5 lines
AMD Operating System Research Center

Advanced Micro Devices GmbH Einsteinring 24 85609 Dornach
General Managers: Alberto Bozzo
Registration: Dornach, Landkr. Muenchen; Registerger. Muenchen, HRB Nr. 43632
author maintainer
#130 lore raw

PATCH 118/175 sysctl: protect poll() in entries that may go away

In reply to Greg KH

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

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

From: Lucas De Marchi <[email protected]>

commit 4e474a00d7ff746ed177ddae14fa8b2d4bad7a00 upstream.

Protect code accessing ctl_table by grabbing the header with grab_header() and after releasing with sysctl_head_finish(). This is needed if poll() is called in entries created by modules: currently only hostname and domainname support poll(), but this bug may be triggered when/if modules use it and if user called poll() in a file that doesn't support it.

Dave Jones reported the following when using a syscall fuzzer while hibernating/resuming:

RIP: 0010:[<ffffffff81233e3e>]  [<ffffffff81233e3e>] proc_sys_poll+0x4e/0x90
RAX: 0000000000000145 RBX: ffff88020cab6940 RCX: 0000000000000000
RDX: ffffffff81233df0 RSI: 6b6b6b6b6b6b6b6b RDI: ffff88020cab6940
[ ... ]
Code: 00 48 89 fb 48 89 f1 48 8b 40 30 4c 8b 60 e8 b8 45 01 00 00 49 83

7c 24 28 00 74 2e 49 8b 74 24 30 48 85 f6 74 24 48 85 c9 75 32 <8b> 16 b8 45 01 00 00 48 63 d2 49 39 d5 74 10 8b 06 48 98 48 89

If an entry goes away while we are polling() it, ctl_table may not exist anymore.

---
 fs/proc/proc_sysctl.c |   17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)
fs/proc/proc_sysctl.c +16 -1
@@ -188,20 +188,32 @@ static ssize_t proc_sys_write(struct fil
 
 static int proc_sys_open(struct inode *inode, struct file *filp)
 {
+	struct ctl_table_header *head = grab_header(inode);
 	struct ctl_table *table = PROC_I(inode)->sysctl_entry;
 
+	/* sysctl was unregistered */
+	if (IS_ERR(head))
+		return PTR_ERR(head);
+
 	if (table->poll)
 		filp->private_data = proc_sys_poll_event(table->poll);
 
+	sysctl_head_finish(head);
+
 	return 0;
 }
 
 static unsigned int proc_sys_poll(struct file *filp, poll_table *wait)
 {
 	struct inode *inode = filp->f_path.dentry->d_inode;
+	struct ctl_table_header *head = grab_header(inode);
 	struct ctl_table *table = PROC_I(inode)->sysctl_entry;
-	unsigned long event = (unsigned long)filp->private_data;
 	unsigned int ret = DEFAULT_POLLMASK;
+	unsigned long event;
+
+	/* sysctl was unregistered */
+	if (IS_ERR(head))
+		return POLLERR | POLLHUP;
 
 	if (!table->proc_handler)
 		goto out;
@@ -209,6 +221,7 @@ static unsigned int proc_sys_poll(struct
 	if (!table->poll)
 		goto out;
 
+	event = (unsigned long)filp->private_data;
 	poll_wait(filp, &table->poll->wait, wait);
 
 	if (event != atomic_read(&table->poll->event)) {
@@ -217,6 +230,8 @@ static unsigned int proc_sys_poll(struct
 	}
 
 out:
+	sysctl_head_finish(head);
+
 	return ret;
 }
 
author maintainer
#131 lore raw

PATCH 119/175 hwmon: (fam15h_power) Correct sign extension of running_avg_capture

In reply to Greg KH

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

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

From: Andreas Herrmann <[email protected]>

commit fc0900cbda9243957d812cd6b4cc87965f9fe75f upstream.

Wrong bit was used for sign extension which caused wrong end results. Thanks to Andre for spotting this bug.

---
 drivers/hwmon/fam15h_power.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/hwmon/fam15h_power.c +1 -1
@@ -60,7 +60,7 @@ static ssize_t show_power(struct device
 	pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5),
 				  REG_TDP_RUNNING_AVERAGE, &val);
 	running_avg_capture = (val >> 4) & 0x3fffff;
-	running_avg_capture = sign_extend32(running_avg_capture, 22);
+	running_avg_capture = sign_extend32(running_avg_capture, 21);
 	running_avg_range = val & 0xf;
 
 	pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5),
author maintainer
#132 lore raw

PATCH 120/175 lgdt330x: fix signedness error in i2c_read_demod_bytes()

In reply to Greg KH

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

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

From: Xi Wang <[email protected]>

commit 34817174fca0c5512c2d5b6ea0fc37a0337ce1d8 upstream.

The error handling in lgdt3303_read_status() and lgdt330x_read_ucblocks() doesn't work, because i2c_read_demod_bytes() returns a u8 and (err < 0) is always false.

        err = i2c_read_demod_bytes(state, 0x58, buf, 1);
        if (err < 0)
                return err;

Change the return type of i2c_read_demod_bytes() to int. Also change the return value on error to -EIO to make (err < 0) work.

---
 drivers/media/dvb/frontends/lgdt330x.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/media/dvb/frontends/lgdt330x.c +4 -2
@@ -104,8 +104,8 @@ static int i2c_write_demod_bytes (struct
  * then reads the data returned for (len) bytes.
  */
 
-static u8 i2c_read_demod_bytes (struct lgdt330x_state* state,
-			       enum I2C_REG reg, u8* buf, int len)
+static int i2c_read_demod_bytes(struct lgdt330x_state *state,
+				enum I2C_REG reg, u8 *buf, int len)
 {
 	u8 wr [] = { reg };
 	struct i2c_msg msg [] = {
@@ -118,6 +118,8 @@ static u8 i2c_read_demod_bytes (struct l
 	ret = i2c_transfer(state->i2c, msg, 2);
 	if (ret != 2) {
 		printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x error (ret == %i)\n", __func__, state->config->demod_address, reg, ret);
+		if (ret >= 0)
+			ret = -EIO;
 	} else {
 		ret = 0;
 	}
author maintainer
#133 lore raw

PATCH 121/175 as102: add __packed attribute to structs defined inside packed structs

In reply to Greg KH

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

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

From: Gianluca Gennari <[email protected]>

commit abf9d005375d6c6160cc9c17e5dcac32e412c8dc upstream.

This patch fixes a regression in kernel 3.3 due to this patch:

http://patchwork.linuxtv.org/patch/8332/

That patch changes "#pragma pack(1)" with "__packed" attributes, but it is not complete. In fact, in the as102 driver there are a lot of structs/unions defined inside other structs/unions.
When the "__packed" attribute is applied only on the external struct, it will not affect the internal struct definitions.
So the regression is fixed by specifiying the "__packed" attribute also on the internal structs.

This patch should go into 3.3, as it fixes a regression introduced in the new kernel version.

---
 drivers/staging/media/as102/as102_fw.h    |    2 
 drivers/staging/media/as102/as10x_cmd.h   |   80 +++++++++++++++---------------
 drivers/staging/media/as102/as10x_types.h |    2 
 3 files changed, 42 insertions(+), 42 deletions(-)
drivers/staging/media/as102/as102_fw.h +1 -1
@@ -29,7 +29,7 @@ struct as10x_fw_pkt_t {
 	union {
 		unsigned char request[2];
 		unsigned char length[2];
-	} u;
+	} __packed u;
 	struct as10x_raw_fw_pkt raw;
 } __packed;
 
drivers/staging/media/as102/as10x_cmd.h +40 -40

314 lines not on this page · raw message

drivers/staging/media/as102/as10x_types.h +1 -1
@@ -181,7 +181,7 @@ struct as10x_register_value {
 		uint8_t  value8;   /* 8 bit value */
 		uint16_t value16;  /* 16 bit value */
 		uint32_t value32;  /* 32 bit value */
-	} u;
+	} __packed u;
 } __packed;
 
 struct as10x_register_addr {
author maintainer
#134 lore raw

PATCH 122/175 tda10071: fix the delivery system

In reply to Greg KH

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

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

From: Antti Palosaari <[email protected]>

commit 2b49fad59513b07f976c9711b99f93ae74d081c5 upstream.

Commit b2a29b578d9c21b2e5c88020f830d3c42115c51d sets accidentally supported delivery systems as DVB-T/T2 whilst it should be DVB-S/S2. Due to that frontend cannot be used at all.

---
 drivers/media/dvb/frontends/tda10071.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/media/dvb/frontends/tda10071.c +1 -1
@@ -1215,7 +1215,7 @@ error:
 EXPORT_SYMBOL(tda10071_attach);
 
 static struct dvb_frontend_ops tda10071_ops = {
-	.delsys = { SYS_DVBT, SYS_DVBT2 },
+	.delsys = { SYS_DVBS, SYS_DVBS2 },
 	.info = {
 		.name = "NXP TDA10071",
 		.frequency_min = 950000,
author maintainer
#135 lore raw

PATCH 123/175 au8522: bug-fix: enable modulation AFTER tune (instead of before tuning)

In reply to Greg KH

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

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

From: Michael Krufky <[email protected]>

commit ef3d2dc366c8c32d58dbbf9898cfd4f853ff8fe0 upstream.

The au8522 driver programs the tuner after programming the demodulator, but the tuner should be programmed first. This patch fixes this behavior.

EDIT: Apparantly Devin created a similar patch some time ago, but hasn't submitted it for merge. I never saw his patch, but I thank him anyhow for his efforts. In addition, Devin pointed out a flaw in my patch:

This newly generated patch takes Devin's comments into account.

Thanks-to: Devin Heitmueller <[email protected]>

---
 drivers/media/dvb/frontends/au8522_dig.c |   10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/media/dvb/frontends/au8522_dig.c +5 -5
@@ -588,11 +588,6 @@ static int au8522_set_frontend(struct dv
 	    (state->current_modulation == c->modulation))
 		return 0;
 
-	au8522_enable_modulation(fe, c->modulation);
-
-	/* Allow the demod to settle */
-	msleep(100);
-
 	if (fe->ops.tuner_ops.set_params) {
 		if (fe->ops.i2c_gate_ctrl)
 			fe->ops.i2c_gate_ctrl(fe, 1);
@@ -604,6 +599,11 @@ static int au8522_set_frontend(struct dv
 	if (ret < 0)
 		return ret;
 
+	/* Allow the tuner to settle */
+	msleep(100);
+
+	au8522_enable_modulation(fe, c->modulation);
+
 	state->current_frequency = c->frequency;
 
 	return 0;
author maintainer
#136 lore raw

PATCH 124/175 pvrusb2: fix 7MHz & 8MHz DVB-T tuner support for HVR1900 rev D1F5

In reply to Greg KH

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

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

From: Michael Krufky <[email protected]>

commit 9ab2393fc3e460cd2040de1483918eb17abb822f upstream.

The D1F5 revision of the WinTV HVR-1900 uses a tda18271c2 tuner instead of a tda18271c1 tuner as used in revision D1E9. To account for this, we must hardcode the frontend configuration to use the same IF frequency configuration for both revisions of the device.

6MHz DVB-T is unaffected by this issue, as the recommended IF Frequency configuration for 6MHz DVB-T is the same on both c1 and c2 revisions of the tda18271 tuner.

---
 drivers/media/video/pvrusb2/pvrusb2-devattr.c |   10 ++++++++++
 1 file changed, 10 insertions(+)
drivers/media/video/pvrusb2/pvrusb2-devattr.c +10 -0
@@ -320,7 +320,17 @@ static struct tda829x_config tda829x_no_
 	.probe_tuner = TDA829X_DONT_PROBE,
 };
 
+static struct tda18271_std_map hauppauge_tda18271_dvbt_std_map = {
+        .dvbt_6   = { .if_freq = 3300, .agc_mode = 3, .std = 4,
+                      .if_lvl = 1, .rfagc_top = 0x37, },
+        .dvbt_7   = { .if_freq = 3800, .agc_mode = 3, .std = 5,
+                      .if_lvl = 1, .rfagc_top = 0x37, },
+        .dvbt_8   = { .if_freq = 4300, .agc_mode = 3, .std = 6,
+                      .if_lvl = 1, .rfagc_top = 0x37, },
+};
+
 static struct tda18271_config hauppauge_tda18271_dvb_config = {
+	.std_map = &hauppauge_tda18271_dvbt_std_map,
 	.gate    = TDA18271_GATE_ANALOG,
 	.output_opt = TDA18271_OUTPUT_LT_OFF,
 };
author maintainer
#137 lore raw

PATCH 125/175 mxl111sf: fix error on stream stop in mxl111sf_ep6_streaming_ctrl()

In reply to Greg KH

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

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

From: Michael Krufky <[email protected]>

commit 3be5bb71fbf18f83cb88b54a62a78e03e5a4f30a upstream.

Remove unnecessary register access in mxl111sf_ep6_streaming_ctrl()

This code breaks driver operation in kernel 3.3 and later, although it works properly in 3.2 Disable register access to 0x12 for now.

---
 drivers/media/dvb/dvb-usb/mxl111sf.c |    6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/media/dvb/dvb-usb/mxl111sf.c +2 -4
@@ -351,15 +351,13 @@ static int mxl111sf_ep6_streaming_ctrl(s
 					      adap_state->ep6_clockphase,
 					      0, 0);
 		mxl_fail(ret);
+#if 0
 	} else {
 		ret = mxl111sf_disable_656_port(state);
 		mxl_fail(ret);
+#endif
 	}
 
-	mxl111sf_read_reg(state, 0x12, &tmp);
-	tmp &= ~0x04;
-	mxl111sf_write_reg(state, 0x12, tmp);
-
 	return ret;
 }
 
author maintainer
#138 lore raw

PATCH 126/175 PM / Domains: Fix hibernation restore of devices, v2

In reply to Greg KH

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

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

From: Rafael J. Wysocki <[email protected]>

This is a backport of mainline commit
65533bbf63b4f37723fdfedc73d0653958973323.

During resume from hibernation pm_genpd_restore_noirq() should only power off domains whose suspend_power_off flags are set once and not every time it is called for a device in the given domain. Moreover, it shouldn't decrement genpd->suspended_count, because that field is not touched during device freezing and therefore it is always equal to 0 when pm_genpd_restore_noirq() runs for the first device in the given domain.

This means pm_genpd_restore_noirq() may use genpd->suspended_count to determine whether or not it it has been called for the domain in question already in this cycle (it only needs to increment that field every time it runs for this purpose) and whether or not it should check if the domain needs to be powered off. For that to work, though, pm_genpd_prepare() has to clear genpd->suspended_count when it runs for the first device in the given domain (in which case that flag need not be cleared during domain initialization).

---
 drivers/base/power/domain.c |   29 +++++++++++++++++++----------
 1 file changed, 19 insertions(+), 10 deletions(-)
drivers/base/power/domain.c +19 -10
@@ -764,8 +764,10 @@ static int pm_genpd_prepare(struct devic
 
 	genpd_acquire_lock(genpd);
 
-	if (genpd->prepared_count++ == 0)
+	if (genpd->prepared_count++ == 0) {
+		genpd->suspended_count = 0;
 		genpd->suspend_power_off = genpd->status == GPD_STATE_POWER_OFF;
+	}
 
 	genpd_release_lock(genpd);
 
@@ -1041,20 +1043,28 @@ static int pm_genpd_restore_noirq(struct
 	 * Since all of the "noirq" callbacks are executed sequentially, it is
 	 * guaranteed that this function will never run twice in parallel for
 	 * the same PM domain, so it is not necessary to use locking here.
+	 *
+	 * At this point suspended_count == 0 means we are being run for the
+	 * first time for the given domain in the present cycle.
 	 */
-	genpd->status = GPD_STATE_POWER_OFF;
-	if (genpd->suspend_power_off) {
+	if (genpd->suspended_count++ == 0) {
 		/*
-		 * The boot kernel might put the domain into the power on state,
-		 * so make sure it really is powered off.
+		 * The boot kernel might put the domain into arbitrary state,
+		 * so make it appear as powered off to pm_genpd_poweron(), so
+		 * that it tries to power it on in case it was really off.
 		 */
-		if (genpd->power_off)
-			genpd->power_off(genpd);
-		return 0;
+		genpd->status = GPD_STATE_POWER_OFF;
+		if (genpd->suspend_power_off) {
+			/*
+			 * If the domain was off before the hibernation, make
+			 * sure it will be off going forward.
+			 */
+			if (genpd->power_off)
+				genpd->power_off(genpd);
+		}
 	}
 
 	pm_genpd_poweron(genpd);
-	genpd->suspended_count--;
 	genpd_start_dev(genpd, dev);
 
 	return genpd_resume_early(genpd, dev);
@@ -1558,7 +1568,6 @@ void pm_genpd_init(struct generic_pm_dom
 	genpd->poweroff_task = NULL;
 	genpd->resume_count = 0;
 	genpd->device_count = 0;
-	genpd->suspended_count = 0;
 	genpd->max_off_time_ns = -1;
 	genpd->domain.ops.runtime_suspend = pm_genpd_runtime_suspend;
 	genpd->domain.ops.runtime_resume = pm_genpd_runtime_resume;
author maintainer
#139 lore raw

PATCH 127/175 PM / Domains: Check domain status during hibernation restore of devices

In reply to Greg KH

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

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

From: Rafael J. Wysocki <[email protected]>

This is a backport of mainline commit
18dd2ece3cde14cfd42e95a89eb14016699a5f15.

Power domains that were off before hibernation shouldn't be turned on during device restore, so prevent that from happening.

This change fixed up mainline commit
65533bbf63b4f37723fdfedc73d0653958973323

PM / Domains: Fix hibernation restore of devices, v2

that didn't include it by mistake.

---
 drivers/base/power/domain.c |    3 +++
 1 file changed, 3 insertions(+)
drivers/base/power/domain.c +3 -0
@@ -1064,6 +1064,9 @@ static int pm_genpd_restore_noirq(struct
 		}
 	}
 
+	if (genpd->suspend_power_off)
+		return 0;
+
 	pm_genpd_poweron(genpd);
 	genpd_start_dev(genpd, dev);
 
author maintainer
#140 lore raw

PATCH 128/175 PM / Domains: Introduce "always on" device flag

In reply to Greg KH

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

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

From: Rafael J. Wysocki <[email protected]>

This is a backport of mainline commit
1e78a0c7fc92aee076965d516cf54475c39e9894.

The TMU device on the Mackerel board belongs to the A4R power domain and loses power when the domain is turned off. Unfortunately, the TMU driver is not prepared to cope with such situations and crashes the system when that happens. To work around this problem introduce a new helper function, pm_genpd_dev_always_on(), allowing a device driver to mark its device as "always on" in case it belongs to a PM domain, which will make the generic PM domains core code avoid powering off the domain containing the device, both at run time and during system suspend.

---
 drivers/base/power/domain.c |   36 ++++++++++++++++++++++++++++++------
 include/linux/pm_domain.h   |    3 +++
 2 files changed, 33 insertions(+), 6 deletions(-)
drivers/base/power/domain.c +30 -6
@@ -366,7 +366,7 @@ static int pm_genpd_poweroff(struct gene
 	not_suspended = 0;
 	list_for_each_entry(pdd, &genpd->dev_list, list_node)
 		if (pdd->dev->driver && (!pm_runtime_suspended(pdd->dev)
-		    || pdd->dev->power.irq_safe))
+		    || pdd->dev->power.irq_safe || to_gpd_data(pdd)->always_on))
 			not_suspended++;
 
 	if (not_suspended > genpd->in_progress)
@@ -503,6 +503,9 @@ static int pm_genpd_runtime_suspend(stru
 
 	might_sleep_if(!genpd->dev_irq_safe);
 
+	if (dev_gpd_data(dev)->always_on)
+		return -EBUSY;
+
 	stop_ok = genpd->gov ? genpd->gov->stop_ok : NULL;
 	if (stop_ok && !stop_ok(dev))
 		return -EBUSY;
@@ -847,7 +850,8 @@ static int pm_genpd_suspend_noirq(struct
 	if (ret)
 		return ret;
 
-	if (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev))
+	if (dev_gpd_data(dev)->always_on
+	    || (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev)))
 		return 0;
 
 	genpd_stop_dev(genpd, dev);
@@ -882,7 +886,7 @@ static int pm_genpd_resume_noirq(struct
 	if (IS_ERR(genpd))
 		return -EINVAL;
 
-	if (genpd->suspend_power_off
+	if (genpd->suspend_power_off || dev_gpd_data(dev)->always_on
 	    || (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev)))
 		return 0;
 
@@ -960,7 +964,7 @@ static int pm_genpd_freeze_noirq(struct
 	if (IS_ERR(genpd))
 		return -EINVAL;
 
-	if (genpd->suspend_power_off)
+	if (genpd->suspend_power_off || dev_gpd_data(dev)->always_on)
 		return 0;
 
 	ret = genpd_freeze_late(genpd, dev);
@@ -991,7 +995,7 @@ static int pm_genpd_thaw_noirq(struct de
 	if (IS_ERR(genpd))
 		return -EINVAL;
 
-	if (genpd->suspend_power_off)
+	if (genpd->suspend_power_off || dev_gpd_data(dev)->always_on)
 		return 0;
 
 	genpd_start_dev(genpd, dev);
@@ -1064,7 +1068,7 @@ static int pm_genpd_restore_noirq(struct
 		}
 	}
 
-	if (genpd->suspend_power_off)
+	if (genpd->suspend_power_off || dev_gpd_data(dev)->always_on)
 		return 0;
 
 	pm_genpd_poweron(genpd);
@@ -1230,6 +1234,26 @@ int pm_genpd_remove_device(struct generi
 }
 
 /**
+ * pm_genpd_dev_always_on - Set/unset the "always on" flag for a given device.
+ * @dev: Device to set/unset the flag for.
+ * @val: The new value of the device's "always on" flag.
+ */
+void pm_genpd_dev_always_on(struct device *dev, bool val)
+{
+	struct pm_subsys_data *psd;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->power.lock, flags);
+
+	psd = dev_to_psd(dev);
+	if (psd && psd->domain_data)
+		to_gpd_data(psd->domain_data)->always_on = val;
+
+	spin_unlock_irqrestore(&dev->power.lock, flags);
+}
+EXPORT_SYMBOL_GPL(pm_genpd_dev_always_on);
+
+/**
  * pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain.
  * @genpd: Master PM domain to add the subdomain to.
  * @subdomain: Subdomain to be added.
include/linux/pm_domain.h +3 -0
@@ -97,6 +97,7 @@ struct generic_pm_domain_data {
 	struct gpd_dev_ops ops;
 	struct gpd_timing_data td;
 	bool need_restore;
+	bool always_on;
 };
 
 static inline struct generic_pm_domain_data *to_gpd_data(struct pm_domain_data *pdd)
@@ -125,6 +126,7 @@ static inline int pm_genpd_add_device(st
 
 extern int pm_genpd_remove_device(struct generic_pm_domain *genpd,
 				  struct device *dev);
+extern void pm_genpd_dev_always_on(struct device *dev, bool val);
 extern int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
 				  struct generic_pm_domain *new_subdomain);
 extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
@@ -163,6 +165,7 @@ static inline int pm_genpd_remove_device
 {
 	return -ENOSYS;
 }
+static inline void pm_genpd_dev_always_on(struct device *dev, bool val) {}
 static inline int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
 					 struct generic_pm_domain *new_sd)
 {
author maintainer
#141 lore raw

PATCH 129/175 PM / shmobile: Make TMU driver use pm_genpd_dev_always_on()

In reply to Greg KH

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

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

From: Rafael J. Wysocki <[email protected]>

Commit 2ee619f9487c2acc1efdf2c78e68e2bd51b635fa upstream.

Make the TMU clocksource driver mark its device as "always on" using pm_genpd_dev_always_on() to protect it from surprise power removals and make sh7372_add_standard_devices() add TMU devices on sh7372 to the A4R power domain so that their "always on" flags are taken into account as appropriate.

---
 arch/arm/mach-shmobile/setup-sh7372.c |    2 ++
 drivers/clocksource/sh_tmu.c          |    4 ++++
 2 files changed, 6 insertions(+)
arch/arm/mach-shmobile/setup-sh7372.c +2 -0
@@ -1043,6 +1043,8 @@ void __init sh7372_add_standard_devices(
 	sh7372_add_device_to_domain(&sh7372_a4r, &veu2_device);
 	sh7372_add_device_to_domain(&sh7372_a4r, &veu3_device);
 	sh7372_add_device_to_domain(&sh7372_a4r, &jpu_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &tmu00_device);
+	sh7372_add_device_to_domain(&sh7372_a4r, &tmu01_device);
 }
 
 void __init sh7372_add_early_devices(void)
drivers/clocksource/sh_tmu.c +4 -0
@@ -32,6 +32,7 @@
 #include <linux/sh_timer.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/pm_domain.h>
 
 struct sh_tmu_priv {
 	void __iomem *mapbase;
@@ -410,6 +411,9 @@ static int __devinit sh_tmu_probe(struct
 	struct sh_tmu_priv *p = platform_get_drvdata(pdev);
 	int ret;
 
+	if (!is_early_platform_device(pdev))
+		pm_genpd_dev_always_on(&pdev->dev, true);
+
 	if (p) {
 		dev_info(&pdev->dev, "kept as earlytimer\n");
 		return 0;
author maintainer
#142 lore raw

PATCH 130/175 PM / shmobile: Make CMT driver use pm_genpd_dev_always_on()

In reply to Greg KH

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

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

From: Rafael J. Wysocki <[email protected]>

Commit 615a445f7f8a077c145e737864ae59a4d8717882 upstream.

Make the CMT clocksource driver mark its device as "always on" using pm_genpd_dev_always_on() to protect it from surprise power removals.

---
 drivers/clocksource/sh_cmt.c |    4 ++++
 1 file changed, 4 insertions(+)
drivers/clocksource/sh_cmt.c +4 -0
@@ -32,6 +32,7 @@
 #include <linux/sh_timer.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/pm_domain.h>
 
 struct sh_cmt_priv {
 	void __iomem *mapbase;
@@ -689,6 +690,9 @@ static int __devinit sh_cmt_probe(struct
 	struct sh_cmt_priv *p = platform_get_drvdata(pdev);
 	int ret;
 
+	if (!is_early_platform_device(pdev))
+		pm_genpd_dev_always_on(&pdev->dev, true);
+
 	if (p) {
 		dev_info(&pdev->dev, "kept as earlytimer\n");
 		return 0;
author maintainer
#143 lore raw

PATCH 131/175 PM / shmobile: Make MTU2 driver use pm_genpd_dev_always_on()

In reply to Greg KH

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

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

From: Rafael J. Wysocki <[email protected]>

Commit 57d13370cfaf6017c68981e66ff5b3bf20a2705c upstream.

Make the MTU2 clocksource driver mark its device as "always on" using pm_genpd_dev_always_on() to protect it from surprise power removals.

---
 drivers/clocksource/sh_mtu2.c |    4 ++++
 1 file changed, 4 insertions(+)
drivers/clocksource/sh_mtu2.c +4 -0
@@ -31,6 +31,7 @@
 #include <linux/sh_timer.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/pm_domain.h>
 
 struct sh_mtu2_priv {
 	void __iomem *mapbase;
@@ -306,6 +307,9 @@ static int __devinit sh_mtu2_probe(struc
 	struct sh_mtu2_priv *p = platform_get_drvdata(pdev);
 	int ret;
 
+	if (!is_early_platform_device(pdev))
+		pm_genpd_dev_always_on(&pdev->dev, true);
+
 	if (p) {
 		dev_info(&pdev->dev, "kept as earlytimer\n");
 		return 0;
author maintainer
#144 lore raw

PATCH 132/175 rtlwifi: Convert to asynchronous firmware load

In reply to Greg KH

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

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

From: Larry Finger <[email protected]>

commit b0302aba812bcc39291cdab9ad7e37008f352a91 upstream.

This patch addresses a kernel bugzilla report and two recent mail threads.

The kernel bugzilla report is https://bugzilla.kernel.org/show_bug.cgi?id=42632,
which reports a udev timeout on boot.

The first mail thread, which was on LKML (http://lkml.indiana.edu/hypermail/
linux/kernel/1112.3/00965.html) was for a WARNING that occurs after a suspend/resume cycle for rtl8192cu.

The scond mail thread (http://marc.info/?l=linux-wireless&m=132655490826766&w=2)
concerned changes in udev that break drivers that delay while firmware is loaded on modprobe.

This patch converts all rtlwifi-based drivers to use the asynchronous firmware loading mechanism. Drivers rtl8192ce, rtl8192cu and rtl8192de share a common callback routine. Driver rtl8192se needs different handling of the firmware, thus it has its own code.

---
 drivers/net/wireless/rtlwifi/base.c               |    1 
 drivers/net/wireless/rtlwifi/core.c               |   42 ++++++++++++++
 drivers/net/wireless/rtlwifi/core.h               |    4 -
 drivers/net/wireless/rtlwifi/pci.c                |   28 +++------
 drivers/net/wireless/rtlwifi/pci.h                |    1 
 drivers/net/wireless/rtlwifi/ps.c                 |    3 -
 drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c |   10 ---
 drivers/net/wireless/rtlwifi/rtl8192ce/hw.c       |    6 --
 drivers/net/wireless/rtlwifi/rtl8192ce/sw.c       |   24 ++------
 drivers/net/wireless/rtlwifi/rtl8192cu/hw.c       |   33 ++++-------
 drivers/net/wireless/rtlwifi/rtl8192cu/sw.c       |   29 +++------
 drivers/net/wireless/rtlwifi/rtl8192de/fw.c       |    8 --
 drivers/net/wireless/rtlwifi/rtl8192de/hw.c       |    3 -
 drivers/net/wireless/rtlwifi/rtl8192de/sw.c       |   38 +++++-------
 drivers/net/wireless/rtlwifi/rtl8192se/fw.c       |    2 
 drivers/net/wireless/rtlwifi/rtl8192se/hw.c       |   16 +++--
 drivers/net/wireless/rtlwifi/rtl8192se/led.c      |    5 +
 drivers/net/wireless/rtlwifi/rtl8192se/sw.c       |   65 ++++++++++++++++------
 drivers/net/wireless/rtlwifi/usb.c                |   36 +++++-------
 drivers/net/wireless/rtlwifi/wifi.h               |    4 +
 20 files changed, 192 insertions(+), 166 deletions(-)
drivers/net/wireless/rtlwifi/base.c +1 -0
@@ -413,6 +413,7 @@ void rtl_init_rfkill(struct ieee80211_hw
 
 	wiphy_rfkill_start_polling(hw->wiphy);
 }
+EXPORT_SYMBOL(rtl_init_rfkill);
 
 void rtl_deinit_rfkill(struct ieee80211_hw *hw)
 {
drivers/net/wireless/rtlwifi/core.c +42 -0

50 lines not on this page · raw message

drivers/net/wireless/rtlwifi/core.h +2 -2
@@ -30,8 +30,6 @@
 #ifndef __RTL_CORE_H__
 #define __RTL_CORE_H__
 
-#include <net/mac80211.h>
-
 #define RTL_SUPPORTED_FILTERS		\
 	(FIF_PROMISC_IN_BSS | \
 	FIF_ALLMULTI | FIF_CONTROL | \
@@ -42,4 +40,6 @@
 #define RTL_SUPPORTED_CTRL_FILTER	0xFF
 
 extern const struct ieee80211_ops rtl_ops;
+void rtl_fw_cb(const struct firmware *firmware, void *context);
+
 #endif
drivers/net/wireless/rtlwifi/pci.c +10 -18
@@ -28,8 +28,8 @@
  *****************************************************************************/
 
 #include <linux/export.h>
-#include "core.h"
 #include "wifi.h"
+#include "core.h"
 #include "pci.h"
 #include "base.h"
 #include "ps.h"
@@ -1579,6 +1579,9 @@ static void rtl_pci_stop(struct ieee8021
 
 	rtlpci->driver_is_goingto_unload = true;
 	rtlpriv->cfg->ops->hw_disable(hw);
+	/* some things are not needed if firmware not available */
+	if (!rtlpriv->max_fw_size)
+		return;
 	rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF);
 
 	spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags);
@@ -1797,6 +1800,7 @@ int __devinit rtl_pci_probe(struct pci_d
 	rtlpriv = hw->priv;
 	pcipriv = (void *)rtlpriv->priv;
 	pcipriv->dev.pdev = pdev;
+	init_completion(&rtlpriv->firmware_loading_complete);
 
 	/* init cfg & intf_ops */
 	rtlpriv->rtlhal.interface = INTF_PCI;
@@ -1817,7 +1821,7 @@ int __devinit rtl_pci_probe(struct pci_d
 	err = pci_request_regions(pdev, KBUILD_MODNAME);
 	if (err) {
 		RT_ASSERT(false, ("Can't obtain PCI resources\n"));
-		return err;
+		goto fail2;
 	}
 
 	pmem_start = pci_resource_start(pdev, rtlpriv->cfg->bar_id);
@@ -1883,15 +1887,6 @@ int __devinit rtl_pci_probe(struct pci_d
 		goto fail3;
 	}
 
-	err = ieee80211_register_hw(hw);
-	if (err) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-			 ("Can't register mac80211 hw.\n"));
-		goto fail3;
-	} else {
-		rtlpriv->mac80211.mac80211_registered = 1;
-	}
-
 	err = sysfs_create_group(&pdev->dev.kobj, &rtl_attribute_group);
 	if (err) {
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
@@ -1899,9 +1894,6 @@ int __devinit rtl_pci_probe(struct pci_d
 		goto fail3;
 	}
 
-	/*init rfkill */
-	rtl_init_rfkill(hw);
-
 	rtlpci = rtl_pcidev(pcipriv);
 	err = request_irq(rtlpci->pdev->irq, &_rtl_pci_interrupt,
 			  IRQF_SHARED, KBUILD_MODNAME, hw);
@@ -1910,24 +1902,22 @@ int __devinit rtl_pci_probe(struct pci_d
 			 ("%s: failed to register IRQ handler\n",
 			  wiphy_name(hw->wiphy)));
 		goto fail3;
-	} else {
-		rtlpci->irq_alloc = 1;
 	}
+	rtlpci->irq_alloc = 1;
 
-	set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
 	return 0;
 
 fail3:
 	pci_set_drvdata(pdev, NULL);
 	rtl_deinit_core(hw);
 	_rtl_pci_io_handler_release(hw);
-	ieee80211_free_hw(hw);
 
 	if (rtlpriv->io.pci_mem_start != 0)
 		pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start);
 
 fail2:
 	pci_release_regions(pdev);
+	complete(&rtlpriv->firmware_loading_complete);
 
 fail1:
 
@@ -1946,6 +1936,8 @@ void rtl_pci_disconnect(struct pci_dev *
 	struct rtl_pci *rtlpci = rtl_pcidev(pcipriv);
 	struct rtl_mac *rtlmac = rtl_mac(rtlpriv);
 
+	/* just in case driver is removed before firmware callback */
+	wait_for_completion(&rtlpriv->firmware_loading_complete);
 	clear_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
 
 	sysfs_remove_group(&pdev->dev.kobj, &rtl_attribute_group);
drivers/net/wireless/rtlwifi/pci.h +0 -1
@@ -239,7 +239,6 @@ int __devinit rtl_pci_probe(struct pci_d
 void rtl_pci_disconnect(struct pci_dev *pdev);
 int rtl_pci_suspend(struct device *dev);
 int rtl_pci_resume(struct device *dev);
-
 static inline u8 pci_read8_sync(struct rtl_priv *rtlpriv, u32 addr)
 {
 	return readb((u8 __iomem *) rtlpriv->io.pci_mem_start + addr);
drivers/net/wireless/rtlwifi/ps.c +2 -1
@@ -47,7 +47,8 @@ bool rtl_ps_enable_nic(struct ieee80211_
 			 ("Driver is already down!\n"));
 
 	/*<2> Enable Adapter */
-	rtlpriv->cfg->ops->hw_init(hw);
+	if (rtlpriv->cfg->ops->hw_init(hw))
+		return 1;
 	RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
 
 	/*<3> Enable Interrupt */
drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +1 -9
@@ -262,10 +262,9 @@ int rtl92c_download_fw(struct ieee80211_
 	u32 fwsize;
 	enum version_8192c version = rtlhal->version;
 
-	if (!rtlhal->pfirmware)
+	if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware)
 		return 1;
 
-	pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name);
 	pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware;
 	pfwdata = (u8 *) rtlhal->pfirmware;
 	fwsize = rtlhal->fwsize;
@@ -518,15 +517,8 @@ static void _rtl92c_fill_h2c_command(str
 void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
 			 u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
 {
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 	u32 tmp_cmdbuf[2];
 
-	if (rtlhal->fw_ready == false) {
-		RT_ASSERT(false, ("return H2C cmd because of Fw "
-				  "download fail!!!\n"));
-		return;
-	}
-
 	memset(tmp_cmdbuf, 0, 8);
 	memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len);
 	_rtl92c_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +1 -5
@@ -921,10 +921,7 @@ int rtl92ce_hw_init(struct ieee80211_hw
 			 ("Failed to download FW. Init HW "
 			  "without FW now..\n"));
 		err = 1;
-		rtlhal->fw_ready = false;
 		return err;
-	} else {
-		rtlhal->fw_ready = true;
 	}
 
 	rtlhal->last_hmeboxnum = 0;
@@ -1199,7 +1196,6 @@ static void _rtl92ce_poweroff_adapter(st
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 	u8 u1b_tmp;
 	u32 u4b_tmp;
 
@@ -1210,7 +1206,7 @@ static void _rtl92ce_poweroff_adapter(st
 	rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
 	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
 	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE0);
-	if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && rtlhal->fw_ready)
+	if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7))
 		rtl92c_firmware_selfreset(hw);
 	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 0x51);
 	rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +8 -16
@@ -92,9 +92,7 @@ int rtl92c_init_sw_vars(struct ieee80211
 	int err;
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
-	const struct firmware *firmware;
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-	char *fw_name = NULL;
 
 	rtl8192ce_bt_reg_init(hw);
 
@@ -166,26 +164,20 @@ int rtl92c_init_sw_vars(struct ieee80211
 	/* request fw */
 	if (IS_VENDOR_UMC_A_CUT(rtlhal->version) &&
 	    !IS_92C_SERIAL(rtlhal->version))
-		fw_name = "rtlwifi/rtl8192cfwU.bin";
+		rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU.bin";
 	else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version))
-		fw_name = "rtlwifi/rtl8192cfwU_B.bin";
-	else
-		fw_name = rtlpriv->cfg->fw_name;
-	err = request_firmware(&firmware, fw_name, rtlpriv->io.dev);
+		rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU_B.bin";
+
+	rtlpriv->max_fw_size = 0x4000;
+	pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name);
+	err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
+				      rtlpriv->io.dev, GFP_KERNEL, hw,
+				      rtl_fw_cb);
 	if (err) {
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 			 ("Failed to request firmware!\n"));
 		return 1;
 	}
-	if (firmware->size > 0x4000) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-			 ("Firmware is too big!\n"));
-		release_firmware(firmware);
-		return 1;
-	}
-	memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size);
-	rtlpriv->rtlhal.fwsize = firmware->size;
-	release_firmware(firmware);
 
 	return 0;
 }
drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +14 -19
@@ -1171,10 +1171,7 @@ int rtl92cu_hw_init(struct ieee80211_hw
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
 			 ("Failed to download FW. Init HW without FW now..\n"));
 		err = 1;
-		rtlhal->fw_ready = false;
 		return err;
-	} else {
-		rtlhal->fw_ready = true;
 	}
 	rtlhal->last_hmeboxnum = 0; /* h2c */
 	_rtl92cu_phy_param_tab_init(hw);
@@ -1270,24 +1267,22 @@ static void  _ResetDigitalProcedure1(str
 		if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(1)) {
 			/* reset MCU ready status */
 			rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
-			if (rtlhal->fw_ready) {
-				/* 8051 reset by self */
-				rtl_write_byte(rtlpriv, REG_HMETFR+3, 0x20);
-				while ((retry_cnts++ < 100) &&
-				       (FEN_CPUEN & rtl_read_word(rtlpriv,
-				       REG_SYS_FUNC_EN))) {
-					udelay(50);
-				}
-				if (retry_cnts >= 100) {
-					RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			/* 8051 reset by self */
+			rtl_write_byte(rtlpriv, REG_HMETFR+3, 0x20);
+			while ((retry_cnts++ < 100) &&
+			       (FEN_CPUEN & rtl_read_word(rtlpriv,
+			       REG_SYS_FUNC_EN))) {
+				udelay(50);
+			}
+			if (retry_cnts >= 100) {
+				RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 						("#####=> 8051 reset failed!.."
 						".......................\n"););
-					/* if 8051 reset fail, reset MAC. */
-					rtl_write_byte(rtlpriv,
-						       REG_SYS_FUNC_EN + 1,
-						       0x50);
-					udelay(100);
-				}
+				/* if 8051 reset fail, reset MAC. */
+				rtl_write_byte(rtlpriv,
+					       REG_SYS_FUNC_EN + 1,
+					       0x50);
+				udelay(100);
 			}
 		}
 		/* Reset MAC and Enable 8051 */
drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +10 -19
@@ -54,7 +54,6 @@ MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin
 static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	const struct firmware *firmware;
 	int err;
 
 	rtlpriv->dm.dm_initialgain_enable = true;
@@ -62,29 +61,21 @@ static int rtl92cu_init_sw_vars(struct i
 	rtlpriv->dm.disable_framebursting = false;
 	rtlpriv->dm.thermalvalue = 0;
 	rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug;
-	rtlpriv->rtlhal.pfirmware = vmalloc(0x4000);
+
+	/* for firmware buf */
+	rtlpriv->rtlhal.pfirmware = vzalloc(0x4000);
 	if (!rtlpriv->rtlhal.pfirmware) {
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 			 ("Can't alloc buffer for fw.\n"));
 		return 1;
 	}
-	/* request fw */
-	err = request_firmware(&firmware, rtlpriv->cfg->fw_name,
-			rtlpriv->io.dev);
-	if (err) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-			 ("Failed to request firmware!\n"));
-		return 1;
-	}
-	if (firmware->size > 0x4000) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-			 ("Firmware is too big!\n"));
-		release_firmware(firmware);
-		return 1;
-	}
-	memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size);
-	rtlpriv->rtlhal.fwsize = firmware->size;
-	release_firmware(firmware);
+
+	pr_info("Loading firmware %s\n", rtlpriv->cfg->fw_name);
+	rtlpriv->max_fw_size = 0x4000;
+	err = request_firmware_nowait(THIS_MODULE, 1,
+				      rtlpriv->cfg->fw_name, rtlpriv->io.dev,
+				      GFP_KERNEL, hw, rtl_fw_cb);
+
 
 	return 0;
 }
drivers/net/wireless/rtlwifi/rtl8192de/fw.c +1 -7
@@ -257,7 +257,7 @@ int rtl92d_download_fw(struct ieee80211_
 	bool fw_downloaded = false, fwdl_in_process = false;
 	unsigned long flags;
 
-	if (!rtlhal->pfirmware)
+	if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware)
 		return 1;
 	fwsize = rtlhal->fwsize;
 	pfwheader = (u8 *) rtlhal->pfirmware;
@@ -539,14 +539,8 @@ static void _rtl92d_fill_h2c_command(str
 void rtl92d_fill_h2c_cmd(struct ieee80211_hw *hw,
 			 u8 element_id, u32 cmd_len, u8 *cmdbuffer)
 {
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 	u32 tmp_cmdbuf[2];
 
-	if (rtlhal->fw_ready == false) {
-		RT_ASSERT(false, ("return H2C cmd because of Fw "
-				  "download fail!!!\n"));
-		return;
-	}
 	memset(tmp_cmdbuf, 0, 8);
 	memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
 	_rtl92d_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
drivers/net/wireless/rtlwifi/rtl8192de/hw.c +0 -3
@@ -932,10 +932,7 @@ int rtl92de_hw_init(struct ieee80211_hw
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
 			 ("Failed to download FW. Init HW "
 			 "without FW..\n"));
-		rtlhal->fw_ready = false;
 		return 1;
-	} else {
-		rtlhal->fw_ready = true;
 	}
 	rtlhal->last_hmeboxnum = 0;
 	rtlpriv->psc.fw_current_inpsmode = false;
drivers/net/wireless/rtlwifi/rtl8192de/sw.c +17 -21
@@ -94,7 +94,6 @@ static int rtl92d_init_sw_vars(struct ie
 	u8 tid;
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
-	const struct firmware *firmware;
 	static int header_print;
 
 	rtlpriv->dm.dm_initialgain_enable = true;
@@ -170,6 +169,15 @@ static int rtl92d_init_sw_vars(struct ie
 	else if (rtlpriv->psc.reg_fwctrl_lps == 3)
 		rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE;
 
+	/* for early mode */
+	rtlpriv->rtlhal.earlymode_enable = true;
+	for (tid = 0; tid < 8; tid++)
+		skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]);
+
+	/* Only load firmware for first MAC */
+	if (header_print)
+		return 0;
+
 	/* for firmware buf */
 	rtlpriv->rtlhal.pfirmware = vzalloc(0x8000);
 	if (!rtlpriv->rtlhal.pfirmware) {
@@ -178,33 +186,21 @@ static int rtl92d_init_sw_vars(struct ie
 		return 1;
 	}
 
-	if (!header_print) {
-		pr_info("Driver for Realtek RTL8192DE WLAN interface\n");
-		pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name);
-		header_print++;
-	}
+	rtlpriv->max_fw_size = 0x8000;
+	pr_info("Driver for Realtek RTL8192DE WLAN interface\n");
+	pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name);
+	header_print++;
+
 	/* request fw */
-	err = request_firmware(&firmware, rtlpriv->cfg->fw_name,
-			       rtlpriv->io.dev);
+	err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
+				      rtlpriv->io.dev, GFP_KERNEL, hw,
+				      rtl_fw_cb);
 	if (err) {
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 			 ("Failed to request firmware!\n"));
 		return 1;
 	}
-	if (firmware->size > 0x8000) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-			 ("Firmware is too big!\n"));
-		release_firmware(firmware);
-		return 1;
-	}
-	memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size);
-	rtlpriv->rtlhal.fwsize = firmware->size;
-	release_firmware(firmware);
 
-	/* for early mode */
-	rtlpriv->rtlhal.earlymode_enable = true;
-	for (tid = 0; tid < 8; tid++)
-		skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]);
 	return 0;
 }
 
drivers/net/wireless/rtlwifi/rtl8192se/fw.c +1 -1
@@ -364,7 +364,7 @@ int rtl92s_download_fw(struct ieee80211_
 	u8 fwstatus = FW_STATUS_INIT;
 	bool rtstatus = true;
 
-	if (!rtlhal->pfirmware)
+	if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware)
 		return 1;
 
 	firmware = (struct rt_firmware *)rtlhal->pfirmware;
drivers/net/wireless/rtlwifi/rtl8192se/hw.c +10 -6
@@ -952,11 +952,10 @@ int rtl92se_hw_init(struct ieee80211_hw
 	if (!rtstatus) {
 		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
 			 ("Failed to download FW. "
-			 "Init HW without FW now.., Please copy FW into"
+			 "Init HW without FW now.., "
+			 "Please copy FW into"
 			 "/lib/firmware/rtlwifi\n"));
-		rtlhal->fw_ready = false;
-	} else {
-		rtlhal->fw_ready = true;
+		return 1;
 	}
 
 	/* After FW download, we have to reset MAC register */
@@ -1219,9 +1218,14 @@ void rtl92se_enable_interrupt(struct iee
 
 void rtl92se_disable_interrupt(struct ieee80211_hw *hw)
 {
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	struct rtl_priv *rtlpriv;
+	struct rtl_pci *rtlpci;
 
+	rtlpriv = rtl_priv(hw);
+	/* if firmware not available, no interrupts */
+	if (!rtlpriv || !rtlpriv->max_fw_size)
+		return;
+	rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 	rtl_write_dword(rtlpriv, INTA_MASK, 0);
 	rtl_write_dword(rtlpriv, INTA_MASK + 4, 0);
 
drivers/net/wireless/rtlwifi/rtl8192se/led.c +4 -1
@@ -76,10 +76,13 @@ void rtl92se_sw_led_on(struct ieee80211_
 
 void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
 {
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_priv *rtlpriv;
 	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
 	u8 ledcfg;
 
+	rtlpriv = rtl_priv(hw);
+	if (!rtlpriv || rtlpriv->max_fw_size)
+		return;
 	RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD,
 		 ("LedAddr:%X ledpin=%d\n", LEDCFG, pled->ledpin));
 
drivers/net/wireless/rtlwifi/rtl8192se/sw.c +50 -15

95 lines not on this page · raw message

drivers/net/wireless/rtlwifi/usb.c +15 -21
@@ -29,8 +29,8 @@
 
 #include <linux/usb.h>
 #include <linux/export.h>
-#include "core.h"
 #include "wifi.h"
+#include "core.h"
 #include "usb.h"
 #include "base.h"
 #include "ps.h"
@@ -667,15 +667,17 @@ static int rtl_usb_start(struct ieee8021
 	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
 
 	err = rtlpriv->cfg->ops->hw_init(hw);
-	rtl_init_rx_config(hw);
+	if (!err) {
+		rtl_init_rx_config(hw);
 
-	/* Enable software */
-	SET_USB_START(rtlusb);
-	/* should after adapter start and interrupt enable. */
-	set_hal_start(rtlhal);
+		/* Enable software */
+		SET_USB_START(rtlusb);
+		/* should after adapter start and interrupt enable. */
+		set_hal_start(rtlhal);
 
-	/* Start bulk IN */
-	_rtl_usb_receive(hw);
+		/* Start bulk IN */
+		_rtl_usb_receive(hw);
+	}
 
 	return err;
 }
@@ -952,6 +954,7 @@ int __devinit rtl_usb_probe(struct usb_i
 		return -ENOMEM;
 	}
 	rtlpriv = hw->priv;
+	init_completion(&rtlpriv->firmware_loading_complete);
 	SET_IEEE80211_DEV(hw, &intf->dev);
 	udev = interface_to_usbdev(intf);
 	usb_get_dev(udev);
@@ -986,24 +989,12 @@ int __devinit rtl_usb_probe(struct usb_i
 		goto error_out;
 	}
 
-	/*init rfkill */
-	/* rtl_init_rfkill(hw); */
-
-	err = ieee80211_register_hw(hw);
-	if (err) {
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG,
-			 ("Can't register mac80211 hw.\n"));
-		goto error_out;
-	} else {
-		rtlpriv->mac80211.mac80211_registered = 1;
-	}
-	set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
 	return 0;
 error_out:
 	rtl_deinit_core(hw);
 	_rtl_usb_io_handler_release(hw);
-	ieee80211_free_hw(hw);
 	usb_put_dev(udev);
+	complete(&rtlpriv->firmware_loading_complete);
 	return -ENODEV;
 }
 EXPORT_SYMBOL(rtl_usb_probe);
@@ -1017,6 +1008,9 @@ void rtl_usb_disconnect(struct usb_inter
 
 	if (unlikely(!rtlpriv))
 		return;
+
+	/* just in case driver is removed before firmware callback */
+	wait_for_completion(&rtlpriv->firmware_loading_complete);
 	/*ieee80211_unregister_hw will call ops_stop */
 	if (rtlmac->mac80211_registered == 1) {
 		ieee80211_unregister_hw(hw);
drivers/net/wireless/rtlwifi/wifi.h +3 -1
@@ -36,6 +36,7 @@
 #include <linux/vmalloc.h>
 #include <linux/usb.h>
 #include <net/mac80211.h>
+#include <linux/completion.h>
 #include "debug.h"
 
 #define RF_CHANGE_BY_INIT			0
@@ -1045,7 +1046,6 @@ struct rtl_hal {
 	u16 fw_subversion;
 	bool h2c_setinprogress;
 	u8 last_hmeboxnum;
-	bool fw_ready;
 	/*Reserve page start offset except beacon in TxQ. */
 	u8 fw_rsvdpage_startoffset;
 	u8 h2c_txcmd_seq;
@@ -1591,6 +1591,7 @@ struct rtl_debug {
 };
 
 struct rtl_priv {
+	struct completion firmware_loading_complete;
 	struct rtl_locks locks;
 	struct rtl_works works;
 	struct rtl_mac mac80211;
@@ -1612,6 +1613,7 @@ struct rtl_priv {
 	struct rtl_rate_priv *rate_priv;
 
 	struct rtl_debug dbg;
+	int max_fw_size;
 
 	/*
 	 *hal_cfg : for diff cards
author maintainer
#145 lore raw

PATCH 133/175 staging: r8712u: Add missing initialization and remove configuration parameter CONFIG_R8712_AP

In reply to Greg KH

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

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

From: Larry Finger <[email protected]>

commit 073863432f7eaa23c7c09733414d4be2eabf5eef upstream.

When this driver was upgraded to the vendor 20100831 version in commit 93c55dda092c7 et al,, one listhead initialization was missed. This broke complete operation of the driver whenever AP mode was enabled. This fixes https://bugs.archlinux.org/task/27996.

The configuration parameter R8712_AP is misleading as the driver cannot function as an AP without a heavily hacked version of hostapd. Thus, it makes sense to remove the parameter; however the code and data configured for the option is left in.

---
 drivers/staging/rtl8712/Kconfig           |    7 -------
 drivers/staging/rtl8712/rtl871x_sta_mgt.c |    4 ----
 drivers/staging/rtl8712/sta_info.h        |    4 ----
 3 files changed, 15 deletions(-)
drivers/staging/rtl8712/Kconfig +0 -7
@@ -9,13 +9,6 @@ config R8712U
 	This option adds the Realtek RTL8712 USB device such as the D-Link DWA-130.
 	If built as a module, it will be called r8712u.
 
-config R8712_AP
-	bool "Realtek RTL8712U AP code"
-	depends on R8712U
-	default N
-	---help---
-	This option allows the Realtek RTL8712 USB device to be an Access Point.
-
 config R8712_TX_AGGR
 	bool "Realtek RTL8712U Transmit Aggregation code"
 	depends on R8712U && BROKEN
drivers/staging/rtl8712/rtl871x_sta_mgt.c +0 -4
@@ -42,10 +42,8 @@ static void _init_stainfo(struct sta_inf
 	_init_listhead(&psta->hash_list);
 	_r8712_init_sta_xmit_priv(&psta->sta_xmitpriv);
 	_r8712_init_sta_recv_priv(&psta->sta_recvpriv);
-#ifdef CONFIG_R8712_AP
 	_init_listhead(&psta->asoc_list);
 	_init_listhead(&psta->auth_list);
-#endif
 }
 
 u32 _r8712_init_sta_priv(struct	sta_priv *pstapriv)
@@ -72,10 +70,8 @@ u32 _r8712_init_sta_priv(struct	sta_priv
 				 get_list_head(&pstapriv->free_sta_queue));
 		psta++;
 	}
-#ifdef CONFIG_R8712_AP
 	_init_listhead(&pstapriv->asoc_list);
 	_init_listhead(&pstapriv->auth_list);
-#endif
 	return _SUCCESS;
 }
 
drivers/staging/rtl8712/sta_info.h +0 -4
@@ -90,7 +90,6 @@ struct sta_info {
 	 * curr_network(mlme_priv/security_priv/qos/ht) : AP CAP/INFO
 	 * sta_info: (AP & STA) CAP/INFO
 	 */
-#ifdef CONFIG_R8712_AP
 	struct list_head asoc_list;
 	struct list_head auth_list;
 	unsigned int expire_to;
@@ -98,7 +97,6 @@ struct sta_info {
 	unsigned int authalg;
 	unsigned char chg_txt[128];
 	unsigned int tx_ra_bitmap;
-#endif
 };
 
 struct	sta_priv {
@@ -111,13 +109,11 @@ struct	sta_priv {
 	struct  __queue sleep_q;
 	struct  __queue wakeup_q;
 	struct _adapter *padapter;
-#ifdef CONFIG_R8712_AP
 	struct list_head asoc_list;
 	struct list_head auth_list;
 	unsigned int auth_to;  /* sec, time to expire in authenticating. */
 	unsigned int assoc_to; /* sec, time to expire before associating. */
 	unsigned int expire_to; /* sec , time to expire after associated. */
-#endif
 };
 
 static inline u32 wifi_mac_hash(u8 *mac)
author maintainer
#146 lore raw

PATCH 134/175 NFSv4: Rate limit the state manager warning messages

In reply to Greg KH

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

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

From: Trond Myklebust <[email protected]>

commit 9a3ba432330e504ac61ff0043dbdaba7cea0e35a upstream.

Prevent the state manager from filling up system logs when recovery fails on the server.

---
 fs/nfs/callback_xdr.c |    4 +++-
 fs/nfs/nfs4proc.c     |    2 +-
 fs/nfs/nfs4state.c    |    4 ++--
 3 files changed, 6 insertions(+), 4 deletions(-)
fs/nfs/callback_xdr.c +3 -1
@@ -9,6 +9,8 @@
 #include <linux/sunrpc/svc.h>
 #include <linux/nfs4.h>
 #include <linux/nfs_fs.h>
+#include <linux/ratelimit.h>
+#include <linux/printk.h>
 #include <linux/slab.h>
 #include <linux/sunrpc/bc_xprt.h>
 #include "nfs4_fs.h"
@@ -167,7 +169,7 @@ static __be32 decode_compound_hdr_arg(st
 	if (hdr->minorversion <= 1) {
 		hdr->cb_ident = ntohl(*p++); /* ignored by v4.1 */
 	} else {
-		printk(KERN_WARNING "%s: NFSv4 server callback with "
+		pr_warn_ratelimited("NFS: %s: NFSv4 server callback with "
 			"illegal minor version %u!\n",
 			__func__, hdr->minorversion);
 		return htonl(NFS4ERR_MINOR_VERS_MISMATCH);
fs/nfs/nfs4proc.c +1 -1
@@ -1845,7 +1845,7 @@ static struct nfs4_state *nfs4_do_open(s
 		 * the user though...
 		 */
 		if (status == -NFS4ERR_BAD_SEQID) {
-			printk(KERN_WARNING "NFS: v4 server %s "
+			pr_warn_ratelimited("NFS: v4 server %s "
 					" returned a bad sequence-id error!\n",
 					NFS_SERVER(dir)->nfs_client->cl_hostname);
 			exception.retry = 1;
fs/nfs/nfs4state.c +2 -2
@@ -996,7 +996,7 @@ static void nfs_increment_seqid(int stat
 		case -NFS4ERR_BAD_SEQID:
 			if (seqid->sequence->flags & NFS_SEQID_CONFIRMED)
 				return;
-			printk(KERN_WARNING "NFS: v4 server returned a bad"
+			pr_warn_ratelimited("NFS: v4 server returned a bad"
 					" sequence-id error on an"
 					" unconfirmed sequence %p!\n",
 					seqid->sequence);
@@ -1826,7 +1826,7 @@ static void nfs4_state_manager(struct nf
 	} while (atomic_read(&clp->cl_count) > 1);
 	return;
 out_error:
-	printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s"
+	pr_warn_ratelimited("NFS: state manager failed on NFSv4 server %s"
 			" with error %d\n", clp->cl_hostname, -status);
 	nfs4_end_drain_session(clp);
 	nfs4_clear_state_manager_bit(clp);
author maintainer
#147 lore raw

PATCH 135/175 PM / Hibernate: Enable usermodehelpers in hibernate() error path

In reply to Greg KH

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

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

From: "Srivatsa S. Bhat" <[email protected]>

commit 05b4877f6a4f1ba4952d1222213d262bf8c132b7 upstream.

If create_basic_memory_bitmaps() fails, usermodehelpers are not re-enabled before returning. Fix this. And while at it, reword the goto labels so that they look more meaningful.

---
 kernel/power/hibernate.c |    7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)
kernel/power/hibernate.c +4 -3
@@ -616,7 +616,7 @@ int hibernate(void)
 	/* Allocate memory management structures */
 	error = create_basic_memory_bitmaps();
 	if (error)
-		goto Exit;
+		goto Enable_umh;
 
 	printk(KERN_INFO "PM: Syncing filesystems ... ");
 	sys_sync();
@@ -624,7 +624,7 @@ int hibernate(void)
 
 	error = freeze_processes();
 	if (error)
-		goto Finish;
+		goto Free_bitmaps;
 
 	error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM);
 	if (error)
@@ -657,8 +657,9 @@ int hibernate(void)
 
  Thaw:
 	thaw_processes();
- Finish:
+ Free_bitmaps:
 	free_basic_memory_bitmaps();
+ Enable_umh:
 	usermodehelper_enable();
  Exit:
 	pm_notifier_call_chain(PM_POST_HIBERNATION);
author maintainer
#148 lore raw

PATCH 136/175 jbd2: clear BH_Delay & BH_Unwritten in journal_unmap_buffer

In reply to Greg KH

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

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

From: Eric Sandeen <[email protected]>

commit 15291164b22a357cb211b618adfef4fa82fc0de3 upstream.

journal_unmap_buffer()'s zap_buffer: code clears a lot of buffer head state ala discard_buffer(), but does not touch _Delay or _Unwritten as discard_buffer() does.

This can be problematic in some areas of the ext4 code which assume that if they have found a buffer marked unwritten or delay, then it's a live one. Perhaps those spots should check whether it is mapped as well, but if jbd2 is going to tear down a buffer, let's really tear it down completely.

Without this I get some fsx failures on sub-page-block filesystems up until v3.2, at which point 4e96b2dbbf1d7e81f22047a50f862555a6cb87cb and 189e868fa8fdca702eb9db9d8afc46b5cb9144c9 make the failures go away, because buried within that large change is some more flag clearing. I still think it's worth doing in jbd2, since ->invalidatepage leads here directly, and it's the right place to clear away these flags.

---
 fs/jbd2/transaction.c |    2 ++
 1 file changed, 2 insertions(+)
fs/jbd2/transaction.c +2 -0
@@ -1949,6 +1949,8 @@ zap_buffer_unlocked:
 	clear_buffer_mapped(bh);
 	clear_buffer_req(bh);
 	clear_buffer_new(bh);
+	clear_buffer_delay(bh);
+	clear_buffer_unwritten(bh);
 	bh->b_bdev = NULL;
 	return may_free;
 }
author maintainer
#149 lore raw

PATCH 137/175 ext4: ignore EXT4_INODE_JOURNAL_DATA flag with delalloc

In reply to Greg KH

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

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

From: Lukas Czerner <[email protected]>

commit 3d2b158262826e8b75bbbfb7b97010838dd92ac7 upstream.

Ext4 does not support data journalling with delayed allocation enabled. We even do not allow to mount the file system with delayed allocation and data journalling enabled, however it can be set via FS_IOC_SETFLAGS so we can hit the inode with EXT4_INODE_JOURNAL_DATA set even on file system mounted with delayed allocation (default) and that's where problem arises. The easies way to reproduce this problem is with the following set of commands:

mkfs.ext4 /dev/sdd
mount /dev/sdd /mnt/test1
dd if=/dev/zero of=/mnt/test1/file bs=1M count=4 chattr +j /mnt/test1/file
dd if=/dev/zero of=/mnt/test1/file bs=1M count=4 conv=notrunc chattr -j /mnt/test1/file

Additionally it can be reproduced quite reliably with xfstests 272 and
269. In fact the above reproducer is a part of test 272.

To fix this we should ignore the EXT4_INODE_JOURNAL_DATA inode flag if the file system is mounted with delayed allocation. This can be easily done by fixing ext4_should_*_data() functions do ignore data journal flag when delalloc is set (suggested by Ted). We also have to set the appropriate address space operations for the inode (again, ignoring data journal flag if delalloc enabled).

Additionally this commit introduces ext4_inode_journal_mode() function because ext4_should_*_data() has already had a lot of common code and this change is putting it all into one function so it is easier to read.

Successfully tested with xfstests in following configurations:

delalloc + data=ordered
delalloc + data=writeback
data=journal
nodelalloc + data=ordered
nodelalloc + data=writeback
nodelalloc + data=journal

---
 fs/ext4/ext4_jbd2.h |   56 ++++++++++++++++++++++++++--------------------------
 fs/ext4/inode.c     |   36 ++++++++++++++++++++-------------
 2 files changed, 51 insertions(+), 41 deletions(-)
fs/ext4/ext4_jbd2.h +29 -27
@@ -261,43 +261,45 @@ static inline void ext4_update_inode_fsy
 /* super.c */
 int ext4_force_commit(struct super_block *sb);
 
-static inline int ext4_should_journal_data(struct inode *inode)
+/*
+ * Ext4 inode journal modes
+ */
+#define EXT4_INODE_JOURNAL_DATA_MODE	0x01 /* journal data mode */
+#define EXT4_INODE_ORDERED_DATA_MODE	0x02 /* ordered data mode */
+#define EXT4_INODE_WRITEBACK_DATA_MODE	0x04 /* writeback data mode */
+
+static inline int ext4_inode_journal_mode(struct inode *inode)
 {
 	if (EXT4_JOURNAL(inode) == NULL)
-		return 0;
-	if (!S_ISREG(inode->i_mode))
-		return 1;
-	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
-		return 1;
-	if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA))
-		return 1;
-	return 0;
+		return EXT4_INODE_WRITEBACK_DATA_MODE;	/* writeback */
+	/* We do not support data journalling with delayed allocation */
+	if (!S_ISREG(inode->i_mode) ||
+	    test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
+		return EXT4_INODE_JOURNAL_DATA_MODE;	/* journal data */
+	if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA) &&
+	    !test_opt(inode->i_sb, DELALLOC))
+		return EXT4_INODE_JOURNAL_DATA_MODE;	/* journal data */
+	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
+		return EXT4_INODE_ORDERED_DATA_MODE;	/* ordered */
+	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
+		return EXT4_INODE_WRITEBACK_DATA_MODE;	/* writeback */
+	else
+		BUG();
+}
+
+static inline int ext4_should_journal_data(struct inode *inode)
+{
+	return ext4_inode_journal_mode(inode) & EXT4_INODE_JOURNAL_DATA_MODE;
 }
 
 static inline int ext4_should_order_data(struct inode *inode)
 {
-	if (EXT4_JOURNAL(inode) == NULL)
-		return 0;
-	if (!S_ISREG(inode->i_mode))
-		return 0;
-	if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA))
-		return 0;
-	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
-		return 1;
-	return 0;
+	return ext4_inode_journal_mode(inode) & EXT4_INODE_ORDERED_DATA_MODE;
 }
 
 static inline int ext4_should_writeback_data(struct inode *inode)
 {
-	if (EXT4_JOURNAL(inode) == NULL)
-		return 1;
-	if (!S_ISREG(inode->i_mode))
-		return 0;
-	if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA))
-		return 0;
-	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
-		return 1;
-	return 0;
+	return ext4_inode_journal_mode(inode) & EXT4_INODE_WRITEBACK_DATA_MODE;
 }
 
 /*
fs/ext4/inode.c +22 -14
@@ -2482,13 +2482,14 @@ static int ext4_da_write_end(struct file
 	int write_mode = (int)(unsigned long)fsdata;
 
 	if (write_mode == FALL_BACK_TO_NONDELALLOC) {
-		if (ext4_should_order_data(inode)) {
+		switch (ext4_inode_journal_mode(inode)) {
+		case EXT4_INODE_ORDERED_DATA_MODE:
 			return ext4_ordered_write_end(file, mapping, pos,
 					len, copied, page, fsdata);
-		} else if (ext4_should_writeback_data(inode)) {
+		case EXT4_INODE_WRITEBACK_DATA_MODE:
 			return ext4_writeback_write_end(file, mapping, pos,
 					len, copied, page, fsdata);
-		} else {
+		default:
 			BUG();
 		}
 	}
@@ -3086,18 +3087,25 @@ static const struct address_space_operat
 
 void ext4_set_aops(struct inode *inode)
 {
-	if (ext4_should_order_data(inode) &&
-		test_opt(inode->i_sb, DELALLOC))
-		inode->i_mapping->a_ops = &ext4_da_aops;
-	else if (ext4_should_order_data(inode))
-		inode->i_mapping->a_ops = &ext4_ordered_aops;
-	else if (ext4_should_writeback_data(inode) &&
-		 test_opt(inode->i_sb, DELALLOC))
-		inode->i_mapping->a_ops = &ext4_da_aops;
-	else if (ext4_should_writeback_data(inode))
-		inode->i_mapping->a_ops = &ext4_writeback_aops;
-	else
+	switch (ext4_inode_journal_mode(inode)) {
+	case EXT4_INODE_ORDERED_DATA_MODE:
+		if (test_opt(inode->i_sb, DELALLOC))
+			inode->i_mapping->a_ops = &ext4_da_aops;
+		else
+			inode->i_mapping->a_ops = &ext4_ordered_aops;
+		break;
+	case EXT4_INODE_WRITEBACK_DATA_MODE:
+		if (test_opt(inode->i_sb, DELALLOC))
+			inode->i_mapping->a_ops = &ext4_da_aops;
+		else
+			inode->i_mapping->a_ops = &ext4_writeback_aops;
+		break;
+	case EXT4_INODE_JOURNAL_DATA_MODE:
 		inode->i_mapping->a_ops = &ext4_journalled_aops;
+		break;
+	default:
+		BUG();
+	}
 }
 
 
author maintainer
#150 lore raw

PATCH 138/175 ext4: fix race between unwritten extent conversion and truncate

In reply to Greg KH

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

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

From: Jeff Moyer <[email protected]>

commit 266991b13890049ee1a6bb95b9817f06339ee3d7 upstream.

The following comment in ext4_end_io_dio caught my attention:

	/* XXX: probably should move into the real I/O completion handler */
        inode_dio_done(inode);

The truncate code takes i_mutex, then calls inode_dio_wait. Because the ext4 code path above will end up dropping the mutex before it is reacquired by the worker thread that does the extent conversion, it seems to me that the truncate can happen out of order. Jan Kara mentioned that this might result in error messages in the system logs, but that should be the extent of the "damage."

The fix is pretty straight-forward: don't call inode_dio_done until the extent conversion is complete.

---
 fs/ext4/ext4.h    |    1 +
 fs/ext4/inode.c   |   10 +++++-----
 fs/ext4/page-io.c |    2 ++
 3 files changed, 8 insertions(+), 5 deletions(-)
fs/ext4/ext4.h +1 -0
@@ -184,6 +184,7 @@ struct mpage_da_data {
 #define	EXT4_IO_END_UNWRITTEN	0x0001
 #define EXT4_IO_END_ERROR	0x0002
 #define EXT4_IO_END_QUEUED	0x0004
+#define EXT4_IO_END_DIRECT	0x0008
 
 struct ext4_io_page {
 	struct page	*p_page;
fs/ext4/inode.c +5 -5
@@ -2796,9 +2796,6 @@ out:
 
 	/* queue the work to convert unwritten extents to written */
 	queue_work(wq, &io_end->work);
-
-	/* XXX: probably should move into the real I/O completion handler */
-	inode_dio_done(inode);
 }
 
 static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate)
@@ -2922,9 +2919,12 @@ static ssize_t ext4_ext_direct_IO(int rw
 		iocb->private = NULL;
 		EXT4_I(inode)->cur_aio_dio = NULL;
 		if (!is_sync_kiocb(iocb)) {
-			iocb->private = ext4_init_io_end(inode, GFP_NOFS);
-			if (!iocb->private)
+			ext4_io_end_t *io_end =
+				ext4_init_io_end(inode, GFP_NOFS);
+			if (!io_end)
 				return -ENOMEM;
+			io_end->flag |= EXT4_IO_END_DIRECT;
+			iocb->private = io_end;
 			/*
 			 * we save the io structure for current async
 			 * direct IO, so that later ext4_map_blocks()
fs/ext4/page-io.c +2 -0
@@ -110,6 +110,8 @@ int ext4_end_io_nolock(ext4_io_end_t *io
 	if (io->iocb)
 		aio_complete(io->iocb, io->result, 0);
 
+	if (io->flag & EXT4_IO_END_DIRECT)
+		inode_dio_done(inode);
 	/* Wake up anyone waiting on unwritten extent conversion */
 	if (atomic_dec_and_test(&EXT4_I(inode)->i_aiodio_unwritten))
 		wake_up_all(ext4_ioend_wq(io->inode));
author maintainer
#151 lore raw

PATCH 139/175 ext4: fix race between sync and completed io work

In reply to Greg KH

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

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

From: Jeff Moyer <[email protected]>

commit 491caa43639abcffaa645fbab372a7ef4ce2975c upstream.

The following command line will leave the aio-stress process unkillable on an ext4 file system (in my case, mounted on /mnt/test):

aio-stress -t 20 -s 10 -O -S -o 2 -I 1000 /mnt/test/aiostress.3561.4 /mnt/test/aiostress.3561.4.20 /mnt/test/aiostress.3561.4.19 /mnt/test/aiostress.3561.4.18 /mnt/test/aiostress.3561.4.17 /mnt/test/aiostress.3561.4.16 /mnt/test/aiostress.3561.4.15 /mnt/test/aiostress.3561.4.14 /mnt/test/aiostress.3561.4.13 /mnt/test/aiostress.3561.4.12 /mnt/test/aiostress.3561.4.11 /mnt/test/aiostress.3561.4.10 /mnt/test/aiostress.3561.4.9 /mnt/test/aiostress.3561.4.8 /mnt/test/aiostress.3561.4.7 /mnt/test/aiostress.3561.4.6 /mnt/test/aiostress.3561.4.5 /mnt/test/aiostress.3561.4.4 /mnt/test/aiostress.3561.4.3 /mnt/test/aiostress.3561.4.2

This is using the aio-stress program from the xfstests test suite. That particular command line tells aio-stress to do random writes to 20 files from 20 threads (one thread per file). The files are NOT preallocated, so you will get writes to random offsets within the file, thus creating holes and extending i_size. It also opens the file with O_DIRECT and O_SYNC.

On to the problem. When an I/O requires unwritten extent conversion, it is queued onto the completed_io_list for the ext4 inode. Two code paths will pull work items from this list. The first is the ext4_end_io_work routine, and the second is ext4_flush_completed_IO, which is called via the fsync path (and O_SYNC handling, as well). There are two issues I've found in these code paths. First, if the fsync path beats the work routine to a particular I/O, the work routine will free the io_end structure! It does not take into account the fact that the io_end may still be in use by the fsync path. I've fixed this issue by adding yet another IO_END flag, indicating that the io_end is being processed by the fsync path.

The second problem is that the work routine will make an assignment to io->flag outside of the lock. I have witnessed this result in a hang at umount. Moving the flag setting inside the lock resolved that problem.

The problem was introduced by commit b82e384c7b ("ext4: optimize locking for end_io extent conversion"), which first appeared in 3.2. As such, the fix should be backported to that release (probably along with the unwritten extent conversion race fix).

---
 fs/ext4/ext4.h    |    1 +
 fs/ext4/fsync.c   |    2 ++
 fs/ext4/page-io.c |    9 +++++++--
 3 files changed, 10 insertions(+), 2 deletions(-)
fs/ext4/ext4.h +1 -0
@@ -185,6 +185,7 @@ struct mpage_da_data {
 #define EXT4_IO_END_ERROR	0x0002
 #define EXT4_IO_END_QUEUED	0x0004
 #define EXT4_IO_END_DIRECT	0x0008
+#define EXT4_IO_END_IN_FSYNC	0x0010
 
 struct ext4_io_page {
 	struct page	*p_page;
fs/ext4/fsync.c +2 -0
@@ -89,6 +89,7 @@ int ext4_flush_completed_IO(struct inode
 		io = list_entry(ei->i_completed_io_list.next,
 				ext4_io_end_t, list);
 		list_del_init(&io->list);
+		io->flag |= EXT4_IO_END_IN_FSYNC;
 		/*
 		 * Calling ext4_end_io_nolock() to convert completed
 		 * IO to written.
@@ -108,6 +109,7 @@ int ext4_flush_completed_IO(struct inode
 		if (ret < 0)
 			ret2 = ret;
 		spin_lock_irqsave(&ei->i_completed_io_lock, flags);
+		io->flag &= ~EXT4_IO_END_IN_FSYNC;
 	}
 	spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
 	return (ret2 < 0) ? ret2 : 0;
fs/ext4/page-io.c +7 -2
@@ -129,12 +129,18 @@ static void ext4_end_io_work(struct work
 	unsigned long		flags;
 
 	spin_lock_irqsave(&ei->i_completed_io_lock, flags);
+	if (io->flag & EXT4_IO_END_IN_FSYNC)
+		goto requeue;
 	if (list_empty(&io->list)) {
 		spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
 		goto free;
 	}
 
 	if (!mutex_trylock(&inode->i_mutex)) {
+		bool was_queued;
+requeue:
+		was_queued = !!(io->flag & EXT4_IO_END_QUEUED);
+		io->flag |= EXT4_IO_END_QUEUED;
 		spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
 		/*
 		 * Requeue the work instead of waiting so that the work
@@ -147,9 +153,8 @@ static void ext4_end_io_work(struct work
 		 * yield the cpu if it sees an end_io request that has already
 		 * been requeued.
 		 */
-		if (io->flag & EXT4_IO_END_QUEUED)
+		if (was_queued)
 			yield();
-		io->flag |= EXT4_IO_END_QUEUED;
 		return;
 	}
 	list_del_init(&io->list);
author maintainer
#152 lore raw

PATCH 140/175 ext4: check for zero length extent

In reply to Greg KH

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

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

From: Theodore Ts'o <[email protected]>

commit 31d4f3a2f3c73f279ff96a7135d7202ef6833f12 upstream.

Explicitly test for an extent whose length is zero, and flag that as a corrupted extent.

This avoids a kernel BUG_ON assertion failure.

Tested: Without this patch, the file system image found in tests/f_ext_zero_len/image.gz in the latest e2fsprogs sources causes a kernel panic. With this patch, an ext4 file system error is noted instead, and the file system is marked as being corrupted.

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

---
 fs/ext4/extents.c |    2 ++
 1 file changed, 2 insertions(+)
fs/ext4/extents.c +2 -0
@@ -300,6 +300,8 @@ static int ext4_valid_extent(struct inod
 	ext4_fsblk_t block = ext4_ext_pblock(ext);
 	int len = ext4_ext_get_actual_len(ext);
 
+	if (len == 0)
+		return 0;
 	return ext4_data_block_valid(EXT4_SB(inode->i_sb), block, len);
 }
 
author maintainer
#153 lore raw

PATCH 141/175 vfs: fix d_ancestor() case in d_materialize_unique

In reply to Greg KH

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

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

From: Michel Lespinasse <[email protected]>

commit b18dafc86bb879d2f38a1743985d7ceb283c2f4d upstream.

In d_materialise_unique() there are 3 subcases to the 'aliased dentry' case; in two subcases the inode i_lock is properly released but this does not occur in the -ELOOP subcase.

This seems to have been introduced by commit 1836750115f2 ("fix loop checks in d_materialise_unique()").

[ Added a comment, and moved the unlock to where we generate the -ELOOP,
which seems to be more natural.

You probably can't actually trigger this without a buggy network file server - d_materialize_unique() is for finding aliases on non-local filesystems, and the d_ancestor() case is for a hardlinked directory loop.

But we should be robust in the case of such buggy servers anyway. ]

---
 fs/dcache.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
fs/dcache.c +2 -1
@@ -2405,6 +2405,7 @@ struct dentry *d_materialise_unique(stru
 			if (d_ancestor(alias, dentry)) {
 				/* Check for loops */
 				actual = ERR_PTR(-ELOOP);
+				spin_unlock(&inode->i_lock);
 			} else if (IS_ROOT(alias)) {
 				/* Is this an anonymous mountpoint that we
 				 * could splice into our tree? */
@@ -2414,7 +2415,7 @@ struct dentry *d_materialise_unique(stru
 				goto found;
 			} else {
 				/* Nope, but we must(!) avoid directory
-				 * aliasing */
+				 * aliasing. This drops inode->i_lock */
 				actual = __d_unalias(inode, dentry, alias);
 			}
 			write_sequnlock(&rename_lock);
author maintainer
#154 lore raw

PATCH 142/175 ARM: tegra: select required CPU and L2 errata options

In reply to Greg KH

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

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

From: Stephen Warren <[email protected]>

commit f35b431dde39fb40944d1024f08d88fbf04a3193 upstream.

The ARM IP revisions in Tegra are:
Tegra20: CPU r1p1, PL310 r2p0
Tegra30: CPU A01=r2p7/>=A02=r2p9, NEON r2p3-50, PL310 r3p1-50

Based on work by Olof Johansson, although the actual list of errata is somewhat different here, since I added a bunch more and removed one PL310 erratum that doesn't seem applicable.

---
 arch/arm/mach-tegra/Kconfig |   12 ++++++++++++
 1 file changed, 12 insertions(+)
arch/arm/mach-tegra/Kconfig +12 -0
@@ -10,6 +10,13 @@ config ARCH_TEGRA_2x_SOC
 	select USB_ARCH_HAS_EHCI if USB_SUPPORT
 	select USB_ULPI if USB_SUPPORT
 	select USB_ULPI_VIEWPORT if USB_SUPPORT
+	select ARM_ERRATA_720789
+	select ARM_ERRATA_742230
+	select ARM_ERRATA_751472
+	select ARM_ERRATA_754327
+	select ARM_ERRATA_764369
+	select PL310_ERRATA_727915 if CACHE_L2X0
+	select PL310_ERRATA_769419 if CACHE_L2X0
 	help
 	  Support for NVIDIA Tegra AP20 and T20 processors, based on the
 	  ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
@@ -23,6 +30,11 @@ config ARCH_TEGRA_3x_SOC
 	select USB_ULPI if USB_SUPPORT
 	select USB_ULPI_VIEWPORT if USB_SUPPORT
 	select USE_OF
+	select ARM_ERRATA_743622
+	select ARM_ERRATA_751472
+	select ARM_ERRATA_754322
+	select ARM_ERRATA_764369
+	select PL310_ERRATA_769419 if CACHE_L2X0
 	help
 	  Support for NVIDIA Tegra T30 processor family, based on the
 	  ARM CortexA9MP CPU and the ARM PL310 L2 cache controller