Note from the -stable maintainer on this release:
This release is big. Yeah, really big. There are a number of
areas that needed some rework in order to get things back to
working order. Like the tty layer. Hopefully everyone can now
use their usb to serial devices again without oopsing the
kernel. Xen and KVM also have reasonably big fixes, as does
the ath5k and iwlwifi drivers. One might say that the patches
for the iwlwifi drivers are a bit "bigger" than normal -stable
material, but the wifi maintainer wants them, so he can handle
the fallout. XHCI (the USB 3.0 controller) also has a big
update here, to get it into workable shape to coincide with the
release of the USB 3.0 developer kit. Without it, it wouldn't
be really useful. And there's a whole raft of other important
fixes as well, not to make light of them. A huge system speedup
for large boxes is also in here, for those who like running
benchmarks.
Please test this -rc1 release out. I've been beating on it
here a lot, but there are still a lot of bits in .31 that feel
a bit loose, as backed up by Rafael's bug list. Hopefully this
release smooths it out.
Now back to the regular -stable review announcement:
This is the start of the stable review cycle for the 2.6.31.2 release.
There are 136 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 us know. If anyone is a maintainer of the proper subsystem, and
wants to add a Signed-off-by: line to the patch, please respond with it.
These patches are sent out with a number of different people on the Cc:
line. If you wish to be a reviewer, please email [email protected] to
add your name to the list. If you want to be off the reviewer list,
also email us.
Responses should be made by Saturday, October 3, 2009 23:00:00 UTC.
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/v2.6/stable-review/patch-2.6.31.2-rc1.gz
and the diffstat can be found below.
thanks,
greg k-h
---------------
MAINTAINERS | 6 +
Makefile | 2 +-
arch/alpha/kernel/core_marvel.c | 2 +-
arch/alpha/kernel/core_titan.c | 2 +-
arch/alpha/kernel/pci_impl.h | 2 +-
arch/alpha/kernel/pci_iommu.c | 4 +-
arch/arm/mach-pxa/sharpsl_pm.c | 4 +-
arch/powerpc/include/asm/pte-common.h | 2 +-
arch/powerpc/mm/pgtable.c | 19 ++-
arch/x86/include/asm/elf.h | 2 +
arch/x86/include/asm/uv/uv_hub.h | 2 +-
arch/x86/kernel/cpu/cpufreq/powernow-k8.c | 15 +-
arch/x86/kvm/mmu.c | 6 -
arch/x86/kvm/x86.c | 15 +-
arch/x86/mm/Makefile | 5 +
arch/x86/mm/mmap.c | 17 +-
arch/x86/mm/pageattr.c | 1 +
arch/x86/xen/Makefile | 2 +
arch/x86/xen/enlighten.c | 139 ++++++++--
arch/x86/xen/smp.c | 1 +
arch/x86/xen/spinlock.c | 28 ++-
drivers/acpi/pci_slot.c | 4 +-
drivers/ata/ahci.c | 4 +-
drivers/ata/pata_amd.c | 3 +
drivers/base/base.h | 2 +-
drivers/base/bus.c | 23 +-
drivers/base/core.c | 2 +-
drivers/char/agp/intel-agp.c | 30 ++-
drivers/char/pty.c | 6 +-
drivers/char/tty_io.c | 1 +
drivers/char/tty_port.c | 29 ++-
drivers/gpu/drm/i915/i915_drv.c | 2 -
drivers/gpu/drm/i915/i915_gem.c | 55 ++--
drivers/gpu/drm/i915/i915_gem_tiling.c | 15 +-
drivers/gpu/drm/i915/i915_reg.h | 6 +
drivers/gpu/drm/i915/intel_bios.c | 3 +
drivers/gpu/drm/i915/intel_crt.c | 9 +-
drivers/gpu/drm/i915/intel_display.c | 35 +++-
drivers/gpu/drm/i915/intel_lvds.c | 11 +-
drivers/gpu/drm/i915/intel_sdvo.c | 96 +++++--
drivers/hid/hid-core.c | 1 -
drivers/isdn/gigaset/interface.c | 19 +-
drivers/media/video/em28xx/em28xx-cards.c | 32 +--
drivers/media/video/em28xx/em28xx.h | 4 +
drivers/media/video/saa7134/saa7134-input.c | 56 ++--
drivers/media/video/saa7134/saa7134.h | 4 +
drivers/message/fusion/mptbase.c | 10 +-
drivers/mfd/ab3100-core.c | 2 +-
drivers/mmc/core/mmc.c | 10 +-
drivers/mmc/core/sd.c | 10 +-
drivers/mtd/chips/cfi_cmdset_0002.c | 11 -
drivers/mtd/chips/cfi_util.c | 4 +
drivers/mtd/nand/ndfc.c | 4 +-
drivers/mtd/ofpart.c | 21 +-
drivers/net/can/vcan.c | 2 +-
drivers/net/usb/kaweth.c | 18 +-
drivers/net/wireless/ath/ar9170/usb.c | 2 +
drivers/net/wireless/ath/ath5k/ath5k.h | 1 +
drivers/net/wireless/ath/ath5k/attach.c | 2 +-
drivers/net/wireless/ath/ath5k/base.c | 55 ++---
drivers/net/wireless/ath/ath5k/reset.c | 155 ++++++++---
drivers/net/wireless/iwlwifi/iwl-1000.c | 6 +-
drivers/net/wireless/iwlwifi/iwl-3945.c | 40 +++
drivers/net/wireless/iwlwifi/iwl-4965.c | 39 +++
drivers/net/wireless/iwlwifi/iwl-5000.c | 58 ++++
drivers/net/wireless/iwlwifi/iwl-6000.c | 25 ++-
drivers/net/wireless/iwlwifi/iwl-agn.c | 57 +++--
drivers/net/wireless/iwlwifi/iwl-core.h | 16 ++
drivers/net/wireless/iwlwifi/iwl-dev.h | 43 +++-
drivers/net/wireless/iwlwifi/iwl-eeprom.c | 185 +++++++++++---
drivers/net/wireless/iwlwifi/iwl-eeprom.h | 10 +-
drivers/net/wireless/iwlwifi/iwl-prph.h | 5 +-
drivers/net/wireless/iwlwifi/iwl-scan.c | 3 +-
drivers/net/wireless/iwlwifi/iwl3945-base.c | 45 ++--
drivers/net/wireless/p54/p54usb.c | 1 +
drivers/pcmcia/at91_cf.c | 2 +-
drivers/pcmcia/au1000_generic.c | 2 +-
drivers/pcmcia/bfin_cf_pcmcia.c | 2 +-
drivers/pcmcia/cs.c | 2 +-
drivers/pcmcia/i82092.c | 2 +-
drivers/pcmcia/i82365.c | 2 +-
drivers/pcmcia/m32r_cfc.c | 2 +-
drivers/pcmcia/m32r_pcc.c | 2 +-
drivers/pcmcia/m8xx_pcmcia.c | 2 +-
drivers/pcmcia/omap_cf.c | 2 +-
drivers/pcmcia/pd6729.c | 2 +-
drivers/pcmcia/pxa2xx_base.c | 2 +-
drivers/pcmcia/sa1100_generic.c | 2 +-
drivers/pcmcia/sa1111_generic.c | 2 +-
drivers/pcmcia/tcic.c | 2 +-
drivers/pcmcia/vrc4171_card.c | 2 +-
drivers/pcmcia/yenta_socket.c | 88 ++++---
drivers/platform/x86/sony-laptop.c | 6 +
drivers/platform/x86/thinkpad_acpi.c | 8 +-
drivers/serial/bfin_5xx.c | 4 +
drivers/serial/serial_cs.c | 1 +
drivers/usb/class/cdc-acm.c | 7 +-
drivers/usb/class/cdc-wdm.c | 30 ++-
drivers/usb/class/usbtmc.c | 22 ++-
drivers/usb/core/config.c | 2 +-
drivers/usb/host/sl811-hcd.c | 8 +-
drivers/usb/host/xhci-dbg.c | 5 +-
drivers/usb/host/xhci-hcd.c | 370 +++++++++++++++++++++-----
drivers/usb/host/xhci-mem.c | 64 ++++-
drivers/usb/host/xhci-pci.c | 13 +
drivers/usb/host/xhci-ring.c | 232 +++++++++++++++--
drivers/usb/host/xhci.h | 41 +++-
drivers/usb/serial/ark3116.c | 46 +---
drivers/usb/serial/console.c | 28 ++-
drivers/usb/serial/cp210x.c | 6 -
drivers/usb/serial/cypress_m8.c | 12 +-
drivers/usb/serial/empeg.c | 12 +-
drivers/usb/serial/ftdi_sio.c | 7 +
drivers/usb/serial/ftdi_sio.h | 10 +
drivers/usb/serial/iuu_phoenix.c | 31 +--
drivers/usb/serial/kobil_sct.c | 22 +-
drivers/usb/serial/option.c | 4 +
drivers/usb/serial/oti6858.c | 21 +-
drivers/usb/serial/pl2303.c | 1 +
drivers/usb/serial/pl2303.h | 4 +
drivers/usb/serial/spcp8x5.c | 21 +-
drivers/usb/serial/usb-serial.c | 385 ++++++++++++---------------
drivers/usb/serial/whiteheat.c | 6 +-
drivers/usb/storage/initializers.c | 2 +-
drivers/usb/storage/onetouch.c | 2 +-
drivers/video/console/fbcon.c | 10 +
drivers/video/s3c-fb.c | 2 +-
drivers/video/sis/vstruct.h | 2 +-
drivers/xen/Makefile | 3 +
fs/cifs/cifsglob.h | 4 +-
fs/ecryptfs/crypto.c | 5 +-
fs/ecryptfs/inode.c | 2 +
fs/ecryptfs/keystore.c | 28 ++-
fs/ecryptfs/kthread.c | 24 +--
fs/ecryptfs/main.c | 3 +-
fs/inode.c | 14 +-
fs/nfsd/nfs4callback.c | 4 +-
fs/nilfs2/btnode.c | 1 +
fs/proc/kcore.c | 8 +-
fs/proc/uptime.c | 7 +-
include/linux/tty.h | 8 +-
include/linux/usb/serial.h | 3 +
include/pcmcia/ss.h | 2 +-
kernel/perf_counter.c | 20 +-
mm/hugetlb.c | 2 +-
mm/memory.c | 3 +-
mm/mlock.c | 99 +++----
mm/mmap.c | 4 +-
mm/nommu.c | 34 +--
mm/page_alloc.c | 12 +-
net/ax25/af_ax25.c | 2 +-
net/bridge/br_netfilter.c | 2 +-
net/bridge/netfilter/ebt_ulog.c | 2 +-
net/can/af_can.c | 4 +-
net/ipv4/netfilter/nf_nat_core.c | 2 +-
net/netfilter/nf_conntrack_core.c | 6 +-
net/packet/af_packet.c | 4 +-
scripts/Kbuild.include | 4 +-
scripts/kallsyms.c | 2 +-
tools/perf/builtin-annotate.c | 4 +-
tools/perf/builtin-report.c | 4 +-
tools/perf/util/module.c | 2 +-
162 files changed, 2336 insertions(+), 1127 deletions(-)
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Sheng Yang <[email protected]>
commit 95eb84a7588d7d7afd3096807efc052adc7479e1 upstream
QNX update WP bit when paging enabled, which is not covered yet. This one
fix QNX boot with EPT.
Signed-off-by: Sheng Yang <[email protected]>
Signed-off-by: Avi Kivity <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -1572,7 +1572,6 @@ static void ept_update_paging_mode_cr0(unsigned long *hw_cr0,
vcpu->arch.cr0 = cr0;
vmx_set_cr4(vcpu, vcpu->arch.cr4);
*hw_cr0 |= X86_CR0_PE | X86_CR0_PG;
- *hw_cr0 &= ~X86_CR0_WP;
} else if (!is_paging(vcpu)) {
/* From nonpaging to paging */
vmcs_write32(CPU_BASED_VM_EXEC_CONTROL,
@@ -1581,9 +1580,10 @@ static void ept_update_paging_mode_cr0(unsigned long *hw_cr0,
CPU_BASED_CR3_STORE_EXITING));
vcpu->arch.cr0 = cr0;
vmx_set_cr4(vcpu, vcpu->arch.cr4);
- if (!(vcpu->arch.cr0 & X86_CR0_WP))
- *hw_cr0 &= ~X86_CR0_WP;
}
+
+ if (!(cr0 & X86_CR0_WP))
+ *hw_cr0 &= ~X86_CR0_WP;
}
static void ept_update_paging_mode_cr4(unsigned long *hw_cr4,
--
1.5.4.5
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Robert Hancock <[email protected]>
commit 90950a2504b66d626a73f55ca949a2e79ff4b7c4 upstream.
On a Compaq Presario V3000 laptop (NVIDIA MCP51 chipset), pata_amd selects
PIO0 mode for the PATA DVD-RAM drive instead of MWDMA2 which it supports:
ata4.00: ATAPI: HL-DT-ST DVDRAM GSA-4084N, KQ09, max MWDMA2
ata4: nv_mode_filter: 0x39f&0x7001->0x1, BIOS=0x0 (0x0) ACPI=0x7001 (60:600:0x11)
ata4.00: configured for PIO0
For some reason, the BIOS-set UDMA configuration returns 0 and the ACPI _GTM
reports that UDMA2 and PIO0 are enabled. This causes nv_mode_filter to end up
allowing only PIO0 and UDMA0-2. Since the drive doesn't support UDMA we end up
using PIO0.
Since the controllers should always support PIO4, MWDMA2 and UDMA2 regardless
of what cable type is used, let's make sure we don't filter out these modes
regardless of what wacky settings the BIOS is using.
Signed-off-by: Robert Hancock <[email protected]>
Signed-off-by: Jeff Garzik <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/ata/pata_amd.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/ata/pata_amd.c
+++ b/drivers/ata/pata_amd.c
@@ -307,6 +307,9 @@ static unsigned long nv_mode_filter(stru
limit |= ATA_MASK_PIO;
if (!(limit & (ATA_MASK_MWDMA | ATA_MASK_UDMA)))
limit |= ATA_MASK_MWDMA | ATA_MASK_UDMA;
+ /* PIO4, MWDMA2, UDMA2 should always be supported regardless of
+ cable detection result */
+ limit |= ata_pack_xfermask(ATA_PIO4, ATA_MWDMA2, ATA_UDMA2);
ata_port_printk(ap, KERN_DEBUG, "nv_mode_filter: 0x%lx&0x%lx->0x%lx, "
"BIOS=0x%lx (0x%x) ACPI=0x%lx%s\n",
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Christian Lamparter <[email protected]>
commit f7f71173ea69d4dabf166533beffa9294090b7ef upstream.
This patch adds a new usbid for Zcomax XG-705A to the device table.
Reported-by: Jari Jaakola <[email protected]>
Signed-off-by: Christian Lamparter <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/net/wireless/p54/p54usb.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -66,6 +66,7 @@ static struct usb_device_id p54u_table[]
{USB_DEVICE(0x0bf8, 0x1009)}, /* FUJITSU E-5400 USB D1700*/
{USB_DEVICE(0x0cde, 0x0006)}, /* Medion MD40900 */
{USB_DEVICE(0x0cde, 0x0008)}, /* Sagem XG703A */
+ {USB_DEVICE(0x0cde, 0x0015)}, /* Zcomax XG-705A */
{USB_DEVICE(0x0d8e, 0x3762)}, /* DLink DWL-G120 Cohiba */
{USB_DEVICE(0x124a, 0x4025)}, /* IOGear GWU513 (GW3887IK chip) */
{USB_DEVICE(0x1260, 0xee22)}, /* SMC 2862W-G version 2 */
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Michal Hocko <[email protected]>
commit 80938332d8cf652f6b16e0788cf0ca136befe0b5 upstream.
Currently we are not including randomized stack size when calculating
mmap_base address in arch_pick_mmap_layout for topdown case. This might
cause that mmap_base starts in the stack reserved area because stack is
randomized by 1GB for 64b (8MB for 32b) and the minimum gap is 128MB.
If the stack really grows down to mmap_base then we can get silent mmap
region overwrite by the stack values.
Let's include maximum stack randomization size into MIN_GAP which is
used as the low bound for the gap in mmap.
Signed-off-by: Michal Hocko <[email protected]>
LKML-Reference: <[email protected]>
Acked-by: Jiri Kosina <[email protected]>
Signed-off-by: H. Peter Anvin <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/x86/include/asm/elf.h | 2 ++
arch/x86/mm/mmap.c | 17 +++++++++++++++--
2 files changed, 17 insertions(+), 2 deletions(-)
--- a/arch/x86/include/asm/elf.h
+++ b/arch/x86/include/asm/elf.h
@@ -299,6 +299,8 @@ do { \
#ifdef CONFIG_X86_32
+#define STACK_RND_MASK (0x7ff)
+
#define VDSO_HIGH_BASE (__fix_to_virt(FIX_VDSO))
#define ARCH_DLINFO ARCH_DLINFO_IA32(vdso_enabled)
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -29,13 +29,26 @@
#include <linux/random.h>
#include <linux/limits.h>
#include <linux/sched.h>
+#include <asm/elf.h>
+
+static unsigned int stack_maxrandom_size(void)
+{
+ unsigned int max = 0;
+ if ((current->flags & PF_RANDOMIZE) &&
+ !(current->personality & ADDR_NO_RANDOMIZE)) {
+ max = ((-1U) & STACK_RND_MASK) << PAGE_SHIFT;
+ }
+
+ return max;
+}
+
/*
* Top of mmap area (just below the process stack).
*
- * Leave an at least ~128 MB hole.
+ * Leave an at least ~128 MB hole with possible stack randomization.
*/
-#define MIN_GAP (128*1024*1024)
+#define MIN_GAP (128*1024*1024UL + stack_maxrandom_size())
#define MAX_GAP (TASK_SIZE/6*5)
/*
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Mike Frysinger <[email protected]>
commit 0271edd4b1b16f255162029359bb69c1ee4d9c3b upstream.
Since early printk only makes sense/works when the serial driver is built
into the kernel, disable the option for this driver when it is going to be
built as a module. Otherwise we get build failures due to the ifdef
handling.
Signed-off-by: Mike Frysinger <[email protected]>
Cc: Alan Cox <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/serial/bfin_5xx.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/drivers/serial/bfin_5xx.c
+++ b/drivers/serial/bfin_5xx.c
@@ -42,6 +42,10 @@
# undef CONFIG_EARLY_PRINTK
#endif
+#ifdef CONFIG_SERIAL_BFIN_MODULE
+# undef CONFIG_EARLY_PRINTK
+#endif
+
/* UART name and device definitions */
#define BFIN_SERIAL_NAME "ttyBF"
#define BFIN_SERIAL_MAJOR 204
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Huzaifa Sidhpurwala <[email protected]>
commit a67d8e6c1e49dc919c9d5480583fad8a46fc00aa upstream.
A few days ago i got the latest ZTE EVDO modem shown at:
http://img.alibaba.com/photo/240150115/ZTE_AC2726_EVDO_USB_Data_Modem.jpg
It seems that the latest kernel does not have support for it.
I wrote a small patch for the options.c module to add the relevant usb
ids to it.
From: Huzaifa Sidhpurwala <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -299,6 +299,7 @@ static int option_resume(struct usb_serial *serial);
#define ZTE_PRODUCT_MF626 0x0031
#define ZTE_PRODUCT_CDMA_TECH 0xfffe
#define ZTE_PRODUCT_AC8710 0xfff1
+#define ZTE_PRODUCT_AC2726 0xfff5
#define BENQ_VENDOR_ID 0x04a5
#define BENQ_PRODUCT_H10 0x4068
@@ -571,6 +572,7 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
{ USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
{ USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4512) },
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Manuel Lauss <[email protected]>
commit ce60c48871d2b3a15ab3fa2450e783bebb4ae407 upstream.
Add ID for Telit UC-864G GPS/UMTS/WCDMA modem and GPS receiver
to the option driver.
Signed-off-by: Manuel Lauss <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/serial/option.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -292,6 +292,7 @@ static int option_resume(struct usb_ser
#define TELIT_VENDOR_ID 0x1bc7
#define TELIT_PRODUCT_UC864E 0x1003
+#define TELIT_PRODUCT_UC864G 0x1004
/* ZTE PRODUCTS */
#define ZTE_VENDOR_ID 0x19d2
@@ -504,6 +505,7 @@ static struct usb_device_id option_ids[]
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
{ USB_DEVICE(MAXON_VENDOR_ID, 0x6280) }, /* BP3-USB & BP3-EXT HSDPA */
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864G) },
{ 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) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0003, 0xff, 0xff, 0xff) },
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Peter Korsgaard <[email protected]>
commit 3163eaba34943967aebb1eefa0d4bdc4e5dc197c upstream.
Fixes `s3c_fb_remove' referenced in section `.data' of
drivers/built-in.o: defined in discarded section `.devexit.text' of
drivers/built-in.o
With CONFIG_HOTPLUG=n, functions marked with __devexit gets removed,
so make sure we use __devexit_p when referencing pointers to them.
Signed-off-by: Peter Korsgaard <[email protected]>
Acked-by: Ben Dooks <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/video/s3c-fb.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -1036,7 +1036,7 @@ static int s3c_fb_resume(struct platform
static struct platform_driver s3c_fb_driver = {
.probe = s3c_fb_probe,
- .remove = s3c_fb_remove,
+ .remove = __devexit_p(s3c_fb_remove),
.suspend = s3c_fb_suspend,
.resume = s3c_fb_resume,
.driver = {
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Jory A. Pratt <[email protected]>
commit c47efe5548abbf53c2f66e06dcb46183b11d6b22 upstream.
The arch/*/boot/Makefile use cc-options to check for GCC command options
and cc-options use the hardened specs when checking for GCC command
options. When -fPIE is pass to cc1 it can't use -ffreestanding or
-fno-toplevel-reorder. Then it fail to build stuff with -ffreestanding
and -fno-toplevel-reorder.
Thanks to Fredric Johansson for finding the main problem behind a failed
build using a hardened toolchain.
Signed-off-by: Magnus Granberg <[email protected]>
Signed-off-by: Jory A. Pratt <[email protected]>
Cc: Fredric Johansson <[email protected]>
Cc: "H. Peter Anvin" <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Sam Ravnborg <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
scripts/Kbuild.include | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -105,12 +105,12 @@ as-instr = $(call try-run,\
# Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586)
cc-option = $(call try-run,\
- $(CC) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",$(1),$(2))
+ $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",$(1),$(2))
# cc-option-yn
# Usage: flag := $(call cc-option-yn,-march=winchip-c6)
cc-option-yn = $(call try-run,\
- $(CC) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",y,n)
+ $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",y,n)
# cc-option-align
# Prefix align with either -falign or -malign
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Andrew Morton <[email protected]>
commit 00d3803b656a5f0935518d746f6bb27d5181d29d upstream.
drivers/mfd/ab3100-core.c:647: error: ab3100_init_settings causes a section type conflict
Cc: Anton Vorontsov <[email protected]>
Cc: Samuel Ortiz <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/mfd/ab3100-core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/mfd/ab3100-core.c
+++ b/drivers/mfd/ab3100-core.c
@@ -643,7 +643,7 @@ struct ab3100_init_setting {
u8 setting;
};
-static const struct ab3100_init_setting __initdata
+static const struct ab3100_init_setting __initconst
ab3100_init_settings[] = {
{
.abreg = AB3100_MCA,
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Henrique de Moraes Holschuh <[email protected]>
commit 6da25bf51689a5cc60370d30275dbb9e6852e0cb upstream.
X40 (firmware 1V) and T41 (firmware 1R) have been confirmed to work
well with the new defaults, so we can stop pestering people to confirm
that fact.
For now, whitelist just these two firmware types. It is best to have
at least one more firmware type confirmed for Radeon 9xxx and Intel
GMA-2 ThinkPads before removing the confirmation requests entirely.
Reported-by: Robert de Rooy <[email protected]>
Signed-off-by: Henrique de Moraes Holschuh <[email protected]>
Signed-off-by: Len Brown <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/platform/x86/thinkpad_acpi.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -5655,16 +5655,16 @@ static const struct tpacpi_quirk brightn
/* Models with ATI GPUs known to require ECNVRAM mode */
TPACPI_Q_IBM('1', 'Y', TPACPI_BRGHT_Q_EC), /* T43/p ATI */
- /* Models with ATI GPUs (waiting confirmation) */
- TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
+ /* Models with ATI GPUs that can use ECNVRAM */
+ TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_EC),
TPACPI_Q_IBM('1', 'Q', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
TPACPI_Q_IBM('7', '6', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
TPACPI_Q_IBM('7', '8', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
- /* Models with Intel Extreme Graphics 2 (waiting confirmation) */
+ /* Models with Intel Extreme Graphics 2 */
+ TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_NOEC),
TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC),
TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC),
- TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC),
/* Models with Intel GMA900 */
TPACPI_Q_IBM('7', '0', TPACPI_BRGHT_Q_NOEC), /* T43, R52 */
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Alex Chiang <[email protected]>
commit 7e24bc1ce669b2876ffa475ea1147f2bb9ffdc52 upstream.
Similar to commit b6adc195 (PCI hotplug: acpiphp wants a 64-bit
_SUN), pci_slot.ko reads and creates sysfs directories based on
the _SUN method.
Certain HP platforms return 64 bits in _SUN. This change to
pci_slot.ko allows us to see the correct sysfs directories.
Reported-by: Chad Smith <[email protected]>
Signed-off-by: Alex Chiang <[email protected]>
Signed-off-by: Len Brown <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/acpi/pci_slot.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/acpi/pci_slot.c
+++ b/drivers/acpi/pci_slot.c
@@ -57,7 +57,7 @@ ACPI_MODULE_NAME("pci_slot");
MY_NAME , ## arg); \
} while (0)
-#define SLOT_NAME_SIZE 20 /* Inspired by #define in acpiphp.h */
+#define SLOT_NAME_SIZE 21 /* Inspired by #define in acpiphp.h */
struct acpi_pci_slot {
acpi_handle root_handle; /* handle of the root bridge */
@@ -149,7 +149,7 @@ register_slot(acpi_handle handle, u32 lv
return AE_OK;
}
- snprintf(name, sizeof(name), "%u", (u32)sun);
+ snprintf(name, sizeof(name), "%llu", sun);
pci_slot = pci_create_slot(pci_bus, device, name, NULL);
if (IS_ERR(pci_slot)) {
err("pci_create_slot returned %ld\n", PTR_ERR(pci_slot));
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Ian Armstrong <[email protected]>
commit 2ddce3fd0acbdc1be684fb5f919ae3d2e9518aac upstream.
Attempting to unload a framebuffer module calls unregister_framebuffer()
which in turn gets fbcon to release it. If fbcon has no framebuffers
linked to a console, it will also unbind itself from the console driver.
However, if fbcon never registered itself as a console driver, the unbind
will fail causing the framebuffer device entry to persist. In most cases
this failure will result in an oops when attempting to access the now
non-existent device.
This patch ensures that the fbcon unbind request will succeed even if a
bind was never done. It tracks if a successful bind ever occurred & will
only attempt to unbind if needed. If there never was a bind, it simply
returns with no error.
Signed-off-by: Ian Armstrong <[email protected]>
Cc: Krzysztof Helt <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/video/console/fbcon.c | 10 ++++++++++
1 file changed, 10 insertions(+)
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -114,6 +114,7 @@ static int last_fb_vc = MAX_NR_CONSOLES
static int fbcon_is_default = 1;
static int fbcon_has_exited;
static int primary_device = -1;
+static int fbcon_has_console_bind;
#ifdef CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
static int map_override;
@@ -544,6 +545,8 @@ static int fbcon_takeover(int show_logo)
con2fb_map[i] = -1;
}
info_idx = -1;
+ } else {
+ fbcon_has_console_bind = 1;
}
return err;
@@ -2923,6 +2926,10 @@ static int fbcon_unbind(void)
ret = unbind_con_driver(&fb_con, first_fb_vc, last_fb_vc,
fbcon_is_default);
+
+ if (!ret)
+ fbcon_has_console_bind = 0;
+
return ret;
}
#else
@@ -2936,6 +2943,9 @@ static int fbcon_fb_unbind(int idx)
{
int i, new_idx = -1, ret = 0;
+ if (!fbcon_has_console_bind)
+ return 0;
+
for (i = first_fb_vc; i <= last_fb_vc; i++) {
if (con2fb_map[i] != idx &&
con2fb_map[i] != -1) {
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Paul Mundt <[email protected]>
commit a9ece53c4089ef23d4002d34c4c7148d94622a40 upstream.
Commit b478b782e110fdb4135caa3062b6d687e989d994 "kallsyms, tracing: output
more proper symbol name" introduces a "bugfix" that introduces a segfault
in kallsyms in my configurations.
The cause is the introduction of prefix_underscores_count() which attempts
to count underscores, even in symbols that do not have them. As a result,
it just uselessly runs past the end of the buffer until it crashes:
CC init/version.o
LD init/built-in.o
LD .tmp_vmlinux1
KSYM .tmp_kallsyms1.S
/bin/sh: line 1: 16934 Done sh-linux-gnu-nm -n .tmp_vmlinux1
16935 Segmentation fault | scripts/kallsyms > .tmp_kallsyms1.S
make: *** [.tmp_kallsyms1.S] Error 139
This simplifies the logic and just does a straightforward count.
Signed-off-by: Paul Mundt <[email protected]>
Reviewed-by: Li Zefan <[email protected]>
Cc: Lai Jiangshan <[email protected]>
Cc: Sam Ravnborg <[email protected]>
Cc: Paulo Marques <[email protected]>
Cc: Ingo Molnar <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
scripts/kallsyms.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -585,7 +585,7 @@ static int prefix_underscores_count(cons
{
const char *tail = str;
- while (*tail != '_')
+ while (*tail == '_')
tail++;
return tail - str;
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Aaro Koskinen <[email protected]>
commit 532f649f148bf70e6a5816d95fe55e6a065e8754 upstream.
The patch enables the driver to be used on platforms such as ARM where an
I/O address is a 32-bit memory address.
The patch avoids the following kernel oops:
debian:~# modprobe sisfb
[ 73.070000] sisfb: Video ROM found
[ 73.080000] sisfb: Video RAM at 0x80000000, mapped to 0xe0a00000, size 1024k
[ 73.090000] sisfb: MMIO at 0x84080000, mapped to 0xe0b80000, size 256k
[ 73.090000] sisfb: Memory heap starting at 800K, size 32K
[ 73.360000] Unable to handle kernel paging request at virtual address 6e000844
[ 73.380000] pgd = df230000
[ 73.380000] [6e000844] *pgd=00000000
[ 73.380000] Internal error: Oops: 8f5 [#1]
[ 73.380000] Modules linked in: sisfb(+) fb cfbcopyarea cfbimgblt cfbfillrect
[ 73.380000] CPU: 0 Not tainted (2.6.31-iop32x #1)
[ 73.380000] PC is at SiS_SetRegANDOR+0x10/0x38 [sisfb]
[ 73.380000] LR is at SiS_SetSCLKHigh+0x38/0x94 [sisfb]
[ 73.380000] pc : [<bf01dc00>] lr : [<bf0238f8>] psr: 60000013
[ 73.380000] sp : df38fd00 ip : 6e000000 fp : 00000002
[ 73.380000] r10: 00000108 r9 : 00000000 r8 : 00000108
[ 73.380000] r7 : df064258 r6 : 00000110 r5 : 6e000844 r4 : 0000010a
[ 73.380000] r3 : 00000001 r2 : 0000000e r1 : 00000011 r0 : 00000844
[ 73.380000] Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
[ 73.380000] Control: 0000397f Table: bf230000 DAC: 00000015
[ 73.380000] Process modprobe (pid: 1849, stack limit = 0xdf38e270)
[ 73.380000] Stack: (0xdf38fd00 to 0xdf390000)
[ 73.380000] fd00: 0000010a 00000108 df064258 df064258 df064258 00000000 00000000 bf02c4e0
[ 73.380000] fd20: 00000114 bf02c50c 00000013 00000114 0000010a df064258 00000000 bf02c980
[ 73.380000] fd40: 00009c66 00000004 00000001 df064250 a0010000 a6a2a0a0 df064250 00000003
[ 73.380000] fd60: df064250 00000000 df064258 0000fffd 00000000 00000000 00000000 bf033948
[ 73.380000] fd80: 00000000 00000000 00000000 bf019e2c 00000000 df064a70 bf03b470 00010000
[ 73.380000] fda0: 00000000 df064250 00000000 df831c00 00000012 bf039f70 00000000 c00abed8
[ 73.380000] fdc0: 000008a6 000008a4 df0649b0 df064878 df064258 df064000 00000000 00000000
[ 73.380000] fde0: 00000001 00008000 00000001 00030000 df81c930 bf049f88 df831c00 00000000
[ 73.380000] fe00: bf049f58 df3952a0 c0447708 bf049f88 bf049fe0 c0191980 df831c00 c0191b10
[ 73.380000] fe20: df831c58 bf049f58 df831c00 bf04aca8 df3952a0 df831c58 df831c58 bf049f88
[ 73.380000] fe40: c01ba1b4 c01ba0a0 df831c58 df831c8c bf049f88 c01ba1b4 df3952a0 00000000
[ 73.380000] fe60: c03e265c c01ba240 00000000 df38fe78 bf049f88 c01b990c df812938 df81b8d0
[ 73.380000] fe80: df3952a0 df807780 00000000 00000060 bf049f88 c01b9224 bf0429c8 00000000
[ 73.380000] fea0: bf049f58 00000000 bf049f88 00000000 00000000 bf04aea8 00000000 c01ba4e4
[ 73.380000] fec0: e09861a0 bf049f58 00000000 bf049f88 00000000 c0191f20 00000000 00000000
[ 73.380000] fee0: c03f7bac bf04d418 0000fff2 0000fff1 bf04ad08 0002f260 0002f260 e0986038
[ 73.380000] ff00: e0986150 e098568b df143340 e0990280 00000036 c03d8b00 fffffffd 00000000
[ 73.380000] ff20: bf04acfc 00000000 fffffffc 0003cf4b 00018098 c03f7bac 00000000 bf04d000
[ 73.380000] ff40: df38e000 00000000 bedc0984 c00272a4 ffffffff c005bc88 00000000 00000000
[ 73.380000] ff60: 0003cf4b 0003cf4b 00018098 bf04acfc 00000000 c0027fe8 df38e000 00000000
[ 73.380000] ff80: bedc0984 c006882c 00001000 00000003 00000000 00009064 00000000 00008edc
[ 73.380000] ffa0: 00000080 c0027e20 00009064 00000000 4014e000 0003cf4b 00018098 0003cf4b
[ 73.380000] ffc0: 00009064 00000000 00008edc 00000080 00000000 00000000 40025000 bedc0984
[ 73.380000] ffe0: 00000000 bedc08fc 0000b6b0 400e8f34 60000010 4014e000 00000000 00000000
[ 73.380000] [<bf01dc00>] (SiS_SetRegANDOR+0x10/0x38 [sisfb]) from [<df064258>] (0xdf064258)
[ 73.380000] Code: e92d0030 e20110ff e280546e e3a0c46e (e5c51000)
[ 73.680000] ---[ end trace 62a93e01df37a5f2 ]---
Signed-off-by: Aaro Koskinen <[email protected]>
Cc: Thomas Winischhofer <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/video/sis/vstruct.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/video/sis/vstruct.h
+++ b/drivers/video/sis/vstruct.h
@@ -342,7 +342,7 @@ struct SiS_Private
unsigned short SiS_RY4COE;
unsigned short SiS_LCDHDES;
unsigned short SiS_LCDVDES;
- unsigned short SiS_DDC_Port;
+ SISIOADDRESS SiS_DDC_Port;
unsigned short SiS_DDC_Index;
unsigned short SiS_DDC_Data;
unsigned short SiS_DDC_NData;
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Wolfgang Muees <[email protected]>
commit d08ebeddfb3293fa4bdfca9c610daf1e8ec8b233 upstream.
Some time ago, I have send a patch to the mmc_spi subsystem changing the
error codes. This was after a discussion with Pierre about using EINVAL
only for non-recoverable errors. This patch was accepted as
http://git.kernel.org/linus/fdd858db7113ca64132de390188d7ca00701013d
Unfortunately, several weeks later, I realized that this patch has opened
a little can of worms because there are SD cards on the market which
a) claim that they support the switch command
AND
b) refuse to execute this command if operating in SPI mode.
So, such a card would get unusuable in an embedded linux system in SPI
mode, because the init sequence terminates with an error.
This patch adds the missing error codes to the caller of the switch
command and restores the old behaviour to fail gracefully if these
commands can not execute.
Signed-off-by: Wolfgang Muees <[email protected]>
Cc: <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/mmc/core/mmc.c | 10 +++++-----
drivers/mmc/core/sd.c | 10 +++++-----
2 files changed, 10 insertions(+), 10 deletions(-)
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -180,11 +180,11 @@ static int mmc_read_ext_csd(struct mmc_c
err = mmc_send_ext_csd(card, ext_csd);
if (err) {
- /*
- * We all hosts that cannot perform the command
- * to fail more gracefully
- */
- if (err != -EINVAL)
+ /* If the host or the card can't do the switch,
+ * fail more gracefully. */
+ if ((err != -EINVAL)
+ && (err != -ENOSYS)
+ && (err != -EFAULT))
goto out;
/*
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -210,11 +210,11 @@ static int mmc_read_switch(struct mmc_ca
err = mmc_sd_switch(card, 0, 0, 1, status);
if (err) {
- /*
- * We all hosts that cannot perform the command
- * to fail more gracefully
- */
- if (err != -EINVAL)
+ /* If the host or the card can't do the switch,
+ * fail more gracefully. */
+ if ((err != -EINVAL)
+ && (err != -ENOSYS)
+ && (err != -EFAULT))
goto out;
printk(KERN_WARNING "%s: problem reading switch "
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Ivan Kokshaysky <[email protected]>
commit d68721eb339e9237c11c1fea5f73f86211d14918 upstream.
This brings Alpha AGP platforms in sync with the change to struct
agp_memory (unsigned long *memory => struct page **pages).
Only compile tested (I don't have titan/marvel hardware), but this change
looks pretty straightforward, so hopefully it's ok.
Signed-off-by: Ivan Kokshaysky <[email protected]>
Cc: Richard Henderson <[email protected]>
Cc: Dave Airlie <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/alpha/kernel/core_marvel.c | 2 +-
arch/alpha/kernel/core_titan.c | 2 +-
arch/alpha/kernel/pci_impl.h | 2 +-
arch/alpha/kernel/pci_iommu.c | 4 ++--
4 files changed, 5 insertions(+), 5 deletions(-)
--- a/arch/alpha/kernel/core_marvel.c
+++ b/arch/alpha/kernel/core_marvel.c
@@ -1016,7 +1016,7 @@ marvel_agp_bind_memory(alpha_agp_info *a
{
struct marvel_agp_aperture *aper = agp->aperture.sysdata;
return iommu_bind(aper->arena, aper->pg_start + pg_start,
- mem->page_count, mem->memory);
+ mem->page_count, mem->pages);
}
static int
--- a/arch/alpha/kernel/core_titan.c
+++ b/arch/alpha/kernel/core_titan.c
@@ -680,7 +680,7 @@ titan_agp_bind_memory(alpha_agp_info *ag
{
struct titan_agp_aperture *aper = agp->aperture.sysdata;
return iommu_bind(aper->arena, aper->pg_start + pg_start,
- mem->page_count, mem->memory);
+ mem->page_count, mem->pages);
}
static int
--- a/arch/alpha/kernel/pci_impl.h
+++ b/arch/alpha/kernel/pci_impl.h
@@ -198,7 +198,7 @@ extern unsigned long size_for_memory(uns
extern int iommu_reserve(struct pci_iommu_arena *, long, long);
extern int iommu_release(struct pci_iommu_arena *, long, long);
-extern int iommu_bind(struct pci_iommu_arena *, long, long, unsigned long *);
+extern int iommu_bind(struct pci_iommu_arena *, long, long, struct page **);
extern int iommu_unbind(struct pci_iommu_arena *, long, long);
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -880,7 +880,7 @@ iommu_release(struct pci_iommu_arena *ar
int
iommu_bind(struct pci_iommu_arena *arena, long pg_start, long pg_count,
- unsigned long *physaddrs)
+ struct page **pages)
{
unsigned long flags;
unsigned long *ptes;
@@ -900,7 +900,7 @@ iommu_bind(struct pci_iommu_arena *arena
}
for(i = 0, j = pg_start; i < pg_count; i++, j++)
- ptes[j] = mk_iommu_pte(physaddrs[i]);
+ ptes[j] = mk_iommu_pte(page_to_phys(pages[i]));
spin_unlock_irqrestore(&arena->lock, flags);
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Jan Kara <[email protected]>
commit 580be0837a7a59b207c3d5c661d044d8dd0a6a30 upstream.
In theory it could happen that on one CPU we initialize a new inode but
clearing of I_NEW | I_LOCK gets reordered before some of the
initialization. Thus on another CPU we return not fully uptodate inode
from iget_locked().
This seems to fix a corruption issue on ext3 mounted over NFS.
[[email protected]: add some commentary]
Signed-off-by: Jan Kara <[email protected]>
Cc: Christoph Hellwig <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -695,13 +695,15 @@ void unlock_new_inode(struct inode *inode)
}
#endif
/*
- * This is special! We do not need the spinlock
- * when clearing I_LOCK, because we're guaranteed
- * that nobody else tries to do anything about the
- * state of the inode when it is locked, as we
- * just created it (so there can be no old holders
- * that haven't tested I_LOCK).
+ * This is special! We do not need the spinlock when clearing I_LOCK,
+ * because we're guaranteed that nobody else tries to do anything about
+ * the state of the inode when it is locked, as we just created it (so
+ * there can be no old holders that haven't tested I_LOCK).
+ * However we must emit the memory barrier so that other CPUs reliably
+ * see the clearing of I_LOCK after the other inode initialisation has
+ * completed.
*/
+ smp_mb();
WARN_ON((inode->i_state & (I_LOCK|I_NEW)) != (I_LOCK|I_NEW));
inode->i_state &= ~(I_LOCK|I_NEW);
wake_up_inode(inode);
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Tyler Hicks <[email protected]>
commit b0105eaefa7cce8f4a941d0fc6354b250d30e745 upstream.
Returns an error when an unrecognized cipher code is present in a tag 3
packet or an ecryptfs_crypt_stat cannot be initialized. Also sets an
crypt_stat->tfm error pointer to NULL to ensure that it will not be
incorrectly freed in ecryptfs_destroy_crypt_stat().
Acked-by: Serge Hallyn <[email protected]>
Cc: [email protected]
Signed-off-by: Tyler Hicks <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/ecryptfs/crypto.c | 1 +
fs/ecryptfs/keystore.c | 10 +++++++---
2 files changed, 8 insertions(+), 3 deletions(-)
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -797,6 +797,7 @@ int ecryptfs_init_crypt_ctx(struct ecryp
kfree(full_alg_name);
if (IS_ERR(crypt_stat->tfm)) {
rc = PTR_ERR(crypt_stat->tfm);
+ crypt_stat->tfm = NULL;
ecryptfs_printk(KERN_ERR, "cryptfs: init_crypt_ctx(): "
"Error initializing cipher [%s]\n",
crypt_stat->cipher);
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -1316,8 +1316,10 @@ parse_tag_3_packet(struct ecryptfs_crypt
rc = -EINVAL;
goto out_free;
}
- ecryptfs_cipher_code_to_string(crypt_stat->cipher,
- (u16)data[(*packet_size)]);
+ rc = ecryptfs_cipher_code_to_string(crypt_stat->cipher,
+ (u16)data[(*packet_size)]);
+ if (rc)
+ goto out_free;
/* A little extra work to differentiate among the AES key
* sizes; see RFC2440 */
switch(data[(*packet_size)++]) {
@@ -1328,7 +1330,9 @@ parse_tag_3_packet(struct ecryptfs_crypt
crypt_stat->key_size =
(*new_auth_tok)->session_key.encrypted_key_size;
}
- ecryptfs_init_crypt_ctx(crypt_stat);
+ rc = ecryptfs_init_crypt_ctx(crypt_stat);
+ if (rc)
+ goto out_free;
if (unlikely(data[(*packet_size)++] != 0x03)) {
printk(KERN_WARNING "Only S2K ID 3 is currently supported\n");
rc = -ENOSYS;
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Tyler Hicks <[email protected]>
commit ac22ba23b659e34a5961aec8c945608e471b0d5b upstream.
If the lower inode is read-only, don't attempt to open the lower file
read/write and don't hand off the open request to the privileged
eCryptfs kthread for opening it read/write. Instead, only try an
unprivileged, read-only open of the file and give up if that fails.
This patch fixes an oops when eCryptfs is mounted on top of a read-only
mount.
Acked-by: Serge Hallyn <[email protected]>
Cc: Eric Sandeen <[email protected]>
Cc: Dave Kleikamp <[email protected]>
Cc: [email protected]
Signed-off-by: Tyler Hicks <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/ecryptfs/kthread.c | 24 ++++++++----------------
fs/ecryptfs/main.c | 3 +--
2 files changed, 9 insertions(+), 18 deletions(-)
--- a/fs/ecryptfs/kthread.c
+++ b/fs/ecryptfs/kthread.c
@@ -136,6 +136,7 @@ int ecryptfs_privileged_open(struct file
const struct cred *cred)
{
struct ecryptfs_open_req *req;
+ int flags = O_LARGEFILE;
int rc = 0;
/* Corresponding dput() and mntput() are done when the
@@ -143,10 +144,14 @@ int ecryptfs_privileged_open(struct file
* destroyed. */
dget(lower_dentry);
mntget(lower_mnt);
- (*lower_file) = dentry_open(lower_dentry, lower_mnt,
- (O_RDWR | O_LARGEFILE), cred);
+ flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR;
+ (*lower_file) = dentry_open(lower_dentry, lower_mnt, flags, cred);
if (!IS_ERR(*lower_file))
goto out;
+ if (flags & O_RDONLY) {
+ rc = PTR_ERR((*lower_file));
+ goto out;
+ }
req = kmem_cache_alloc(ecryptfs_open_req_cache, GFP_KERNEL);
if (!req) {
rc = -ENOMEM;
@@ -180,21 +185,8 @@ int ecryptfs_privileged_open(struct file
__func__);
goto out_unlock;
}
- if (IS_ERR(*req->lower_file)) {
+ if (IS_ERR(*req->lower_file))
rc = PTR_ERR(*req->lower_file);
- dget(lower_dentry);
- mntget(lower_mnt);
- (*lower_file) = dentry_open(lower_dentry, lower_mnt,
- (O_RDONLY | O_LARGEFILE), cred);
- if (IS_ERR(*lower_file)) {
- rc = PTR_ERR(*req->lower_file);
- (*lower_file) = NULL;
- printk(KERN_WARNING "%s: Error attempting privileged "
- "open of lower file with either RW or RO "
- "perms; rc = [%d]. Giving up.\n",
- __func__, rc);
- }
- }
out_unlock:
mutex_unlock(&req->mux);
out_free:
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -129,11 +129,10 @@ int ecryptfs_init_persistent_file(struct
lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
rc = ecryptfs_privileged_open(&inode_info->lower_file,
lower_dentry, lower_mnt, cred);
- if (rc || IS_ERR(inode_info->lower_file)) {
+ if (rc) {
printk(KERN_ERR "Error opening lower persistent file "
"for lower_dentry [0x%p] and lower_mnt [0x%p]; "
"rc = [%d]\n", lower_dentry, lower_mnt, rc);
- rc = PTR_ERR(inode_info->lower_file);
inode_info->lower_file = NULL;
}
}
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Tyler Hicks <[email protected]>
commit df6ad33ba1b9846bd5f0e2b9016c30c20bc2d948 upstream.
Returns -ENOTSUPP when attempting to use filename encryption with
something other than a password authentication token, such as a private
token from openssl. Using filename encryption with a userspace eCryptfs
key module is a future goal. Until then, this patch handles the
situation a little better than simply using a BUG_ON().
Acked-by: Serge Hallyn <[email protected]>
Cc: [email protected]
Signed-off-by: Tyler Hicks <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/ecryptfs/crypto.c | 4 ++--
fs/ecryptfs/keystore.c | 14 ++++++++++++--
2 files changed, 14 insertions(+), 4 deletions(-)
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -1703,7 +1703,7 @@ ecryptfs_encrypt_filename(struct ecryptf
} else {
printk(KERN_ERR "%s: No support for requested filename "
"encryption method in this release\n", __func__);
- rc = -ENOTSUPP;
+ rc = -EOPNOTSUPP;
goto out;
}
out:
@@ -2167,7 +2167,7 @@ int ecryptfs_encrypt_and_encode_filename
(*encoded_name)[(*encoded_name_size)] = '\0';
(*encoded_name_size)++;
} else {
- rc = -ENOTSUPP;
+ rc = -EOPNOTSUPP;
}
if (rc) {
printk(KERN_ERR "%s: Error attempting to encode "
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -612,7 +612,12 @@ ecryptfs_write_tag_70_packet(char *dest,
}
/* TODO: Support other key modules than passphrase for
* filename encryption */
- BUG_ON(s->auth_tok->token_type != ECRYPTFS_PASSWORD);
+ if (s->auth_tok->token_type != ECRYPTFS_PASSWORD) {
+ rc = -EOPNOTSUPP;
+ printk(KERN_INFO "%s: Filename encryption only supports "
+ "password tokens\n", __func__);
+ goto out_free_unlock;
+ }
sg_init_one(
&s->hash_sg,
(u8 *)s->auth_tok->token.password.session_key_encryption_key,
@@ -910,7 +915,12 @@ ecryptfs_parse_tag_70_packet(char **file
}
/* TODO: Support other key modules than passphrase for
* filename encryption */
- BUG_ON(s->auth_tok->token_type != ECRYPTFS_PASSWORD);
+ if (s->auth_tok->token_type != ECRYPTFS_PASSWORD) {
+ rc = -EOPNOTSUPP;
+ printk(KERN_INFO "%s: Filename encryption only supports "
+ "password tokens\n", __func__);
+ goto out_free_unlock;
+ }
rc = crypto_blkcipher_setkey(
s->desc.tfm,
s->auth_tok->token.password.session_key_encryption_key,
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Tyler Hicks <[email protected]>
commit 3891959846709a19f76628e33478cd85edb0e79f upstream.
When searching through the global authentication tokens for a given key
signature, verify that a matching key has not been revoked and has not
expired. This allows the `keyctl revoke` command to be properly used on
keys in use by eCryptfs.
Acked-by: Serge Hallyn <[email protected]>
Cc: [email protected]
Signed-off-by: Tyler Hicks <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/ecryptfs/keystore.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -416,7 +416,9 @@ ecryptfs_find_global_auth_tok_for_sig(
&mount_crypt_stat->global_auth_tok_list,
mount_crypt_stat_list) {
if (memcmp(walker->sig, sig, ECRYPTFS_SIG_SIZE_HEX) == 0) {
- (*global_auth_tok) = walker;
+ rc = key_validate(walker->global_auth_tok_key);
+ if (!rc)
+ (*global_auth_tok) = walker;
goto out;
}
}
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Tyler Hicks <[email protected]>
commit 9c2d2056647790c5034d722bd24e9d913ebca73c upstream.
When calling vfs_unlink() on the lower dentry, d_delete() turns the
dentry into a negative dentry when the d_count is 1. This eventually
caused a NULL pointer deref when a read() or write() was done and the
negative dentry's d_inode was dereferenced in
ecryptfs_read_update_atime() or ecryptfs_getxattr().
Placing mutt's tmpdir in an eCryptfs mount is what initially triggered
the oops and I was able to reproduce it with the following sequence:
open("/tmp/upper/foo", O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW, 0600) = 3
link("/tmp/upper/foo", "/tmp/upper/bar") = 0
unlink("/tmp/upper/foo") = 0
open("/tmp/upper/bar", O_RDWR|O_CREAT|O_NOFOLLOW, 0600) = 4
unlink("/tmp/upper/bar") = 0
write(4, "eCryptfs test\n"..., 14 <unfinished ...>
+++ killed by SIGKILL +++
https://bugs.launchpad.net/ecryptfs/+bug/387073
Reported-by: Loïc Minier <[email protected]>
Cc: Serge Hallyn <[email protected]>
Cc: Dave Kleikamp <[email protected]>
Cc: [email protected]
Signed-off-by: Tyler Hicks <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/ecryptfs/inode.c | 2 ++
1 file changed, 2 insertions(+)
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -476,6 +476,7 @@ static int ecryptfs_unlink(struct inode
struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir);
struct dentry *lower_dir_dentry;
+ dget(lower_dentry);
lower_dir_dentry = lock_parent(lower_dentry);
rc = vfs_unlink(lower_dir_inode, lower_dentry);
if (rc) {
@@ -489,6 +490,7 @@ static int ecryptfs_unlink(struct inode
d_drop(dentry);
out_unlock:
unlock_dir(lower_dir_dentry);
+ dput(lower_dentry);
return rc;
}
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Chuck Ebbert <[email protected]>
commit 20d1752f3d6bd32beb90949559e0d14a0b234445 upstream.
commit ac68392460ffefed13020967bae04edc4d3add06 ("[CIFS] Allow raw
ntlmssp code to be enabled with sec=ntlmssp") added a new bit to the
allowed security flags mask but seems to have inadvertently removed
Lanman security from the allowed flags. Add it back.
Signed-off-by: Chuck Ebbert <[email protected]>
Signed-off-by: Steve French <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/cifs/cifsglob.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -572,9 +572,9 @@ require use of the stronger protocol */
#define CIFSSEC_MUST_LANMAN 0x10010
#define CIFSSEC_MUST_PLNTXT 0x20020
#ifdef CONFIG_CIFS_UPCALL
-#define CIFSSEC_MASK 0xAF0AF /* allows weak security but also krb5 */
+#define CIFSSEC_MASK 0xBF0BF /* allows weak security but also krb5 */
#else
-#define CIFSSEC_MASK 0xA70A7 /* current flags supported if weak */
+#define CIFSSEC_MASK 0xB70B7 /* current flags supported if weak */
#endif /* UPCALL */
#else /* do not allow weak pw hash */
#ifdef CONFIG_CIFS_UPCALL
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Jeremy Fitzhardinge <[email protected]>
commit 577eebeae34d340685d8985dfdb7dfe337c511e8 upstream.
-fstack-protector uses a special per-cpu "stack canary" value.
gcc generates special code in each function to test the canary to make
sure that the function's stack hasn't been overrun.
On x86-64, this is simply an offset of %gs, which is the usual per-cpu
base segment register, so setting it up simply requires loading %gs's
base as normal.
On i386, the stack protector segment is %gs (rather than the usual kernel
percpu %fs segment register). This requires setting up the full kernel
GDT and then loading %gs accordingly. We also need to make sure %gs is
initialized when bringing up secondary cpus too.
To keep things consistent, we do the full GDT/segment register setup on
both architectures.
Because we need to avoid -fstack-protected code before setting up the GDT
and because there's no way to disable it on a per-function basis, several
files need to have stack-protector inhibited.
[ Impact: allow Xen booting with stack-protector enabled ]
Signed-off-by: Jeremy Fitzhardinge <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/x86/mm/Makefile | 4 +
arch/x86/xen/Makefile | 2
arch/x86/xen/enlighten.c | 131 ++++++++++++++++++++++++++++++++++++++++-------
arch/x86/xen/smp.c | 1
drivers/xen/Makefile | 3 +
5 files changed, 122 insertions(+), 19 deletions(-)
--- a/arch/x86/mm/Makefile
+++ b/arch/x86/mm/Makefile
@@ -1,6 +1,10 @@
obj-y := init.o init_$(BITS).o fault.o ioremap.o extable.o pageattr.o mmap.o \
pat.o pgtable.o gup.o
+# Make sure __phys_addr has no stackprotector
+nostackp := $(call cc-option, -fno-stack-protector)
+CFLAGS_ioremap.o := $(nostackp)
+
obj-$(CONFIG_SMP) += tlb.o
obj-$(CONFIG_X86_32) += pgtable_32.o iomap_32.o
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -51,6 +51,7 @@
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
#include <asm/reboot.h>
+#include <asm/stackprotector.h>
#include "xen-ops.h"
#include "mmu.h"
@@ -330,18 +331,28 @@ static void xen_load_gdt(const struct de
unsigned long frames[pages];
int f;
- /* A GDT can be up to 64k in size, which corresponds to 8192
- 8-byte entries, or 16 4k pages.. */
+ /*
+ * A GDT can be up to 64k in size, which corresponds to 8192
+ * 8-byte entries, or 16 4k pages..
+ */
BUG_ON(size > 65536);
BUG_ON(va & ~PAGE_MASK);
for (f = 0; va < dtr->address + size; va += PAGE_SIZE, f++) {
int level;
- pte_t *ptep = lookup_address(va, &level);
+ pte_t *ptep;
unsigned long pfn, mfn;
void *virt;
+ /*
+ * The GDT is per-cpu and is in the percpu data area.
+ * That can be virtually mapped, so we need to do a
+ * page-walk to get the underlying MFN for the
+ * hypercall. The page can also be in the kernel's
+ * linear range, so we need to RO that mapping too.
+ */
+ ptep = lookup_address(va, &level);
BUG_ON(ptep == NULL);
pfn = pte_pfn(*ptep);
@@ -358,6 +369,44 @@ static void xen_load_gdt(const struct de
BUG();
}
+/*
+ * load_gdt for early boot, when the gdt is only mapped once
+ */
+static __init void xen_load_gdt_boot(const struct desc_ptr *dtr)
+{
+ unsigned long va = dtr->address;
+ unsigned int size = dtr->size + 1;
+ unsigned pages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
+ unsigned long frames[pages];
+ int f;
+
+ /*
+ * A GDT can be up to 64k in size, which corresponds to 8192
+ * 8-byte entries, or 16 4k pages..
+ */
+
+ BUG_ON(size > 65536);
+ BUG_ON(va & ~PAGE_MASK);
+
+ for (f = 0; va < dtr->address + size; va += PAGE_SIZE, f++) {
+ pte_t pte;
+ unsigned long pfn, mfn;
+
+ pfn = virt_to_pfn(va);
+ mfn = pfn_to_mfn(pfn);
+
+ pte = pfn_pte(pfn, PAGE_KERNEL_RO);
+
+ if (HYPERVISOR_update_va_mapping((unsigned long)va, pte, 0))
+ BUG();
+
+ frames[f] = mfn;
+ }
+
+ if (HYPERVISOR_set_gdt(frames, size / sizeof(struct desc_struct)))
+ BUG();
+}
+
static void load_TLS_descriptor(struct thread_struct *t,
unsigned int cpu, unsigned int i)
{
@@ -581,6 +630,29 @@ static void xen_write_gdt_entry(struct d
preempt_enable();
}
+/*
+ * Version of write_gdt_entry for use at early boot-time needed to
+ * update an entry as simply as possible.
+ */
+static __init void xen_write_gdt_entry_boot(struct desc_struct *dt, int entry,
+ const void *desc, int type)
+{
+ switch (type) {
+ case DESC_LDT:
+ case DESC_TSS:
+ /* ignore */
+ break;
+
+ default: {
+ xmaddr_t maddr = virt_to_machine(&dt[entry]);
+
+ if (HYPERVISOR_update_descriptor(maddr.maddr, *(u64 *)desc))
+ dt[entry] = *(struct desc_struct *)desc;
+ }
+
+ }
+}
+
static void xen_load_sp0(struct tss_struct *tss,
struct thread_struct *thread)
{
@@ -965,6 +1037,23 @@ static const struct machine_ops __initda
.emergency_restart = xen_emergency_restart,
};
+/*
+ * Set up the GDT and segment registers for -fstack-protector. Until
+ * we do this, we have to be careful not to call any stack-protected
+ * function, which is most of the kernel.
+ */
+static void __init xen_setup_stackprotector(void)
+{
+ pv_cpu_ops.write_gdt_entry = xen_write_gdt_entry_boot;
+ pv_cpu_ops.load_gdt = xen_load_gdt_boot;
+
+ setup_stack_canary_segment(0);
+ switch_to_new_gdt(0);
+
+ pv_cpu_ops.write_gdt_entry = xen_write_gdt_entry;
+ pv_cpu_ops.load_gdt = xen_load_gdt;
+}
+
/* First C function to be called on Xen boot */
asmlinkage void __init xen_start_kernel(void)
{
@@ -983,13 +1072,28 @@ asmlinkage void __init xen_start_kernel(
pv_apic_ops = xen_apic_ops;
pv_mmu_ops = xen_mmu_ops;
-#ifdef CONFIG_X86_64
/*
- * Setup percpu state. We only need to do this for 64-bit
- * because 32-bit already has %fs set properly.
+ * Set up some pagetable state before starting to set any ptes.
*/
- load_percpu_segment(0);
-#endif
+
+ /* Prevent unwanted bits from being set in PTEs. */
+ __supported_pte_mask &= ~_PAGE_GLOBAL;
+ if (!xen_initial_domain())
+ __supported_pte_mask &= ~(_PAGE_PWT | _PAGE_PCD);
+
+ __supported_pte_mask |= _PAGE_IOMAP;
+
+ xen_setup_features();
+
+ /* Get mfn list */
+ if (!xen_feature(XENFEAT_auto_translated_physmap))
+ xen_build_dynamic_phys_to_machine();
+
+ /*
+ * Set up kernel GDT and segment registers, mainly so that
+ * -fstack-protector code can be executed.
+ */
+ xen_setup_stackprotector();
xen_init_irq_ops();
xen_init_cpuid_mask();
@@ -1001,8 +1105,6 @@ asmlinkage void __init xen_start_kernel(
set_xen_basic_apic_ops();
#endif
- xen_setup_features();
-
if (xen_feature(XENFEAT_mmu_pt_update_preserve_ad)) {
pv_mmu_ops.ptep_modify_prot_start = xen_ptep_modify_prot_start;
pv_mmu_ops.ptep_modify_prot_commit = xen_ptep_modify_prot_commit;
@@ -1019,17 +1121,8 @@ asmlinkage void __init xen_start_kernel(
xen_smp_init();
- /* Get mfn list */
- if (!xen_feature(XENFEAT_auto_translated_physmap))
- xen_build_dynamic_phys_to_machine();
-
pgd = (pgd_t *)xen_start_info->pt_base;
- /* Prevent unwanted bits from being set in PTEs. */
- __supported_pte_mask &= ~_PAGE_GLOBAL;
- if (!xen_initial_domain())
- __supported_pte_mask &= ~(_PAGE_PWT | _PAGE_PCD);
-
#ifdef CONFIG_X86_64
/* Work out if we support NX */
check_efer();
--- a/arch/x86/xen/Makefile
+++ b/arch/x86/xen/Makefile
@@ -8,6 +8,7 @@ endif
# Make sure early boot has no stackprotector
nostackp := $(call cc-option, -fno-stack-protector)
CFLAGS_enlighten.o := $(nostackp)
+CFLAGS_mmu.o := $(nostackp)
obj-y := enlighten.o setup.o multicalls.o mmu.o irq.o \
time.o xen-asm.o xen-asm_$(BITS).o \
@@ -16,3 +17,4 @@ obj-y := enlighten.o setup.o multicalls
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o
+
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -236,6 +236,7 @@ cpu_initialize_context(unsigned int cpu,
ctxt->user_regs.ss = __KERNEL_DS;
#ifdef CONFIG_X86_32
ctxt->user_regs.fs = __KERNEL_PERCPU;
+ ctxt->user_regs.gs = __KERNEL_STACK_CANARY;
#else
ctxt->gs_base_kernel = per_cpu_offset(cpu);
#endif
--- a/drivers/xen/Makefile
+++ b/drivers/xen/Makefile
@@ -1,6 +1,9 @@
obj-y += grant-table.o features.o events.o manage.o
obj-y += xenbus/
+nostackp := $(call cc-option, -fno-stack-protector)
+CFLAGS_features.o := $(nostackp)
+
obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o
obj-$(CONFIG_XEN_XENCOMM) += xencomm.o
obj-$(CONFIG_XEN_BALLOON) += balloon.o
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Jeremy Fitzhardinge <[email protected]>
commit 4d576b57b50a92801e6493e76e5243d6cff193d2 upstream.
Where possible we enable interrupts while waiting for a spinlock to
become free, in order to reduce big latency spikes in interrupt handling.
However, at present if we manage to pick up the spinlock just before
blocking, we'll end up holding the lock with interrupts enabled for a
while. This will cause a deadlock if we recieve an interrupt in that
window, and the interrupt handler tries to take the lock too.
Solve this by shrinking the interrupt-enabled region to just around the
blocking call.
[ Impact: avoid race/deadlock when using Xen PV spinlocks ]
Reported-by: "Yang, Xiaowei" <[email protected]>
Signed-off-by: Jeremy Fitzhardinge <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/x86/xen/spinlock.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
--- a/arch/x86/xen/spinlock.c
+++ b/arch/x86/xen/spinlock.c
@@ -187,7 +187,6 @@ static noinline int xen_spin_lock_slow(s
struct xen_spinlock *prev;
int irq = __get_cpu_var(lock_kicker_irq);
int ret;
- unsigned long flags;
u64 start;
/* If kicker interrupts not initialized yet, just spin */
@@ -199,16 +198,12 @@ static noinline int xen_spin_lock_slow(s
/* announce we're spinning */
prev = spinning_lock(xl);
- flags = __raw_local_save_flags();
- if (irq_enable) {
- ADD_STATS(taken_slow_irqenable, 1);
- raw_local_irq_enable();
- }
-
ADD_STATS(taken_slow, 1);
ADD_STATS(taken_slow_nested, prev != NULL);
do {
+ unsigned long flags;
+
/* clear pending */
xen_clear_irq_pending(irq);
@@ -228,6 +223,12 @@ static noinline int xen_spin_lock_slow(s
goto out;
}
+ flags = __raw_local_save_flags();
+ if (irq_enable) {
+ ADD_STATS(taken_slow_irqenable, 1);
+ raw_local_irq_enable();
+ }
+
/*
* Block until irq becomes pending. If we're
* interrupted at this point (after the trylock but
@@ -238,13 +239,15 @@ static noinline int xen_spin_lock_slow(s
* pending.
*/
xen_poll_irq(irq);
+
+ raw_local_irq_restore(flags);
+
ADD_STATS(taken_slow_spurious, !xen_test_irq_pending(irq));
} while (!xen_test_irq_pending(irq)); /* check for spurious wakeups */
kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
out:
- raw_local_irq_restore(flags);
unspinning_lock(xl, prev);
spin_time_accum_blocked(start);
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Yang Xiaowei <[email protected]>
commit 2496afbf1e50c70f80992656bcb730c8583ddac3 upstream.
We need to have a stronger barrier between releasing the lock and
checking for any waiting spinners. A compiler barrier is not sufficient
because the CPU's ordering rules do not prevent the read xl->spinners
from happening before the unlock assignment, as they are different
memory locations.
We need to have an explicit barrier to enforce the write-read ordering
to different memory locations.
Because of it, I can't bring up > 4 HVM guests on one SMP machine.
[ Code and commit comments expanded -J ]
[ Impact: avoid deadlock when using Xen PV spinlocks ]
Signed-off-by: Yang Xiaowei <[email protected]>
Signed-off-by: Jeremy Fitzhardinge <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/x86/xen/spinlock.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
--- a/arch/x86/xen/spinlock.c
+++ b/arch/x86/xen/spinlock.c
@@ -326,8 +326,13 @@ static void xen_spin_unlock(struct raw_s
smp_wmb(); /* make sure no writes get moved after unlock */
xl->lock = 0; /* release lock */
- /* make sure unlock happens before kick */
- barrier();
+ /*
+ * Make sure unlock happens before checking for waiting
+ * spinners. We need a strong barrier to enforce the
+ * write-read ordering to different memory locations, as the
+ * CPU makes no implied guarantees about their ordering.
+ */
+ mb();
if (unlikely(xl->spinners))
xen_spin_unlock_slow(xl);
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Jeremy Fitzhardinge <[email protected]>
commit b75fe4e5b869f8dbebd36df64a7fcda0c5b318ed upstream.
x86-64 assumes NX is available by default, so we need to
explicitly check for it before using NX. Some first-generation
Intel x86-64 processors didn't support NX, and even recent systems
allow it to be disabled in BIOS.
[ Impact: prevent Xen crash on NX-less 64-bit machines ]
Signed-off-by: Jeremy Fitzhardinge <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/x86/mm/Makefile | 1 +
arch/x86/xen/enlighten.c | 10 +++++-----
2 files changed, 6 insertions(+), 5 deletions(-)
--- a/arch/x86/mm/Makefile
+++ b/arch/x86/mm/Makefile
@@ -4,6 +4,7 @@ obj-y := init.o init_$(BITS).o fault.o
# Make sure __phys_addr has no stackprotector
nostackp := $(call cc-option, -fno-stack-protector)
CFLAGS_ioremap.o := $(nostackp)
+CFLAGS_init.o := $(nostackp)
obj-$(CONFIG_SMP) += tlb.o
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -1083,6 +1083,11 @@ asmlinkage void __init xen_start_kernel(
__supported_pte_mask |= _PAGE_IOMAP;
+#ifdef CONFIG_X86_64
+ /* Work out if we support NX */
+ check_efer();
+#endif
+
xen_setup_features();
/* Get mfn list */
@@ -1123,11 +1128,6 @@ asmlinkage void __init xen_start_kernel(
pgd = (pgd_t *)xen_start_info->pt_base;
-#ifdef CONFIG_X86_64
- /* Work out if we support NX */
- check_efer();
-#endif
-
/* Don't do the full vcpu_info placement stuff until we have a
possible map and a non-dummy shared_info. */
per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0];
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Ian Schram <[email protected]>
commit cdf8073d6b2c6c5a3cd6ce0e6c1297157f7f99ba upstream.
There is still some weird code in per_copy_attr(). Which supposedly
checks that all bytes trailing a struct are zero.
It doesn't seem to get pointer arithmetic right. Since it
increments an iterating pointer by sizeof(unsigned long) rather
than 1.
Signed-off-by: Ian Schram <[email protected]>
[ v2: clean up the messy PTR_ALIGN logic as well. ]
Signed-off-by: Peter Zijlstra <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
kernel/perf_counter.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
--- a/kernel/perf_counter.c
+++ b/kernel/perf_counter.c
@@ -4143,8 +4143,8 @@ done:
static int perf_copy_attr(struct perf_counter_attr __user *uattr,
struct perf_counter_attr *attr)
{
- int ret;
u32 size;
+ int ret;
if (!access_ok(VERIFY_WRITE, uattr, PERF_ATTR_SIZE_VER0))
return -EFAULT;
@@ -4169,19 +4169,19 @@ static int perf_copy_attr(struct perf_co
/*
* If we're handed a bigger struct than we know of,
- * ensure all the unknown bits are 0.
+ * ensure all the unknown bits are 0 - i.e. new
+ * user-space does not rely on any kernel feature
+ * extensions we dont know about yet.
*/
if (size > sizeof(*attr)) {
- unsigned long val;
- unsigned long __user *addr;
- unsigned long __user *end;
-
- addr = PTR_ALIGN((void __user *)uattr + sizeof(*attr),
- sizeof(unsigned long));
- end = PTR_ALIGN((void __user *)uattr + size,
- sizeof(unsigned long));
+ unsigned char __user *addr;
+ unsigned char __user *end;
+ unsigned char val;
+
+ addr = (void __user *)uattr + sizeof(*attr);
+ end = (void __user *)uattr + size;
- for (; addr < end; addr += sizeof(unsigned long)) {
+ for (; addr < end; addr++) {
ret = get_user(val, addr);
if (ret)
return ret;
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Eric Dumazet <[email protected]>
commit a255a9981a8566a1efabec983b7811e937e662d2 upstream.
"perf top" cores dump on my dev machine, if run from a directory
where vmlinux is present:
*** glibc detected *** malloc(): memory corruption: 0x085670d0 ***
Signed-off-by: Eric Dumazet <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
tools/perf/util/module.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/tools/perf/util/module.c
+++ b/tools/perf/util/module.c
@@ -422,7 +422,7 @@ static int mod_dso__load_module_paths(st
len += strlen(uts.release);
len += strlen("/modules.dep");
- path = calloc(1, len);
+ path = calloc(1, len + 1);
if (path == NULL)
goto out_failure;
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Wolfram Sang <[email protected]>
commit 7a4b23104bd2624d16681158a9b338c502c103a0 upstream.
Add ID as reported in:
http://lists.infradead.org/pipermail/linux-pcmcia/2009-May/006127.html
Reported-by: Kenneth Moorman <[email protected]>
Signed-off-by: Wolfram Sang <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/serial/serial_cs.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -884,6 +884,7 @@ static struct pcmcia_device_id serial_id
PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */
PCMCIA_DEVICE_CIS_MANF_CARD(0x013f, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- post update */
PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "MT5634ZLX.cis"),
+ PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-2", 0x96913a85, 0x27ab5437, "COMpad2.cis"),
PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "COMpad4.cis"),
PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"),
PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "RS-COM-2P.cis"),
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Rafael J. Wysocki <[email protected]>
commit 827b4649d4626bf97b203b4bcd69476bb9b4e760 upstream.
pcmcia_socket_dev_suspend() doesn't use its second argument, so it
may be dropped safely.
This change is necessary for the subsequent yenta suspend/resume fix.
Signed-off-by: Rafael J. Wysocki <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/pcmcia/at91_cf.c | 2 +-
drivers/pcmcia/au1000_generic.c | 2 +-
drivers/pcmcia/bfin_cf_pcmcia.c | 2 +-
drivers/pcmcia/cs.c | 2 +-
drivers/pcmcia/i82092.c | 2 +-
drivers/pcmcia/i82365.c | 2 +-
drivers/pcmcia/m32r_cfc.c | 2 +-
drivers/pcmcia/m32r_pcc.c | 2 +-
drivers/pcmcia/m8xx_pcmcia.c | 2 +-
drivers/pcmcia/omap_cf.c | 2 +-
drivers/pcmcia/pd6729.c | 2 +-
drivers/pcmcia/pxa2xx_base.c | 2 +-
drivers/pcmcia/sa1100_generic.c | 2 +-
drivers/pcmcia/sa1111_generic.c | 2 +-
drivers/pcmcia/tcic.c | 2 +-
drivers/pcmcia/vrc4171_card.c | 2 +-
drivers/pcmcia/yenta_socket.c | 2 +-
include/pcmcia/ss.h | 2 +-
18 files changed, 18 insertions(+), 18 deletions(-)
--- a/drivers/pcmcia/at91_cf.c
+++ b/drivers/pcmcia/at91_cf.c
@@ -363,7 +363,7 @@ static int at91_cf_suspend(struct platfo
struct at91_cf_socket *cf = platform_get_drvdata(pdev);
struct at91_cf_data *board = cf->board;
- pcmcia_socket_dev_suspend(&pdev->dev, mesg);
+ pcmcia_socket_dev_suspend(&pdev->dev);
if (device_may_wakeup(&pdev->dev)) {
enable_irq_wake(board->det_pin);
if (board->irq_pin)
--- a/drivers/pcmcia/au1000_generic.c
+++ b/drivers/pcmcia/au1000_generic.c
@@ -515,7 +515,7 @@ static int au1x00_drv_pcmcia_probe(struc
static int au1x00_drv_pcmcia_suspend(struct platform_device *dev,
pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int au1x00_drv_pcmcia_resume(struct platform_device *dev)
--- a/drivers/pcmcia/bfin_cf_pcmcia.c
+++ b/drivers/pcmcia/bfin_cf_pcmcia.c
@@ -302,7 +302,7 @@ static int __devexit bfin_cf_remove(stru
static int bfin_cf_suspend(struct platform_device *pdev, pm_message_t mesg)
{
- return pcmcia_socket_dev_suspend(&pdev->dev, mesg);
+ return pcmcia_socket_dev_suspend(&pdev->dev);
}
static int bfin_cf_resume(struct platform_device *pdev)
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -101,7 +101,7 @@ EXPORT_SYMBOL(pcmcia_socket_list_rwsem);
static int socket_resume(struct pcmcia_socket *skt);
static int socket_suspend(struct pcmcia_socket *skt);
-int pcmcia_socket_dev_suspend(struct device *dev, pm_message_t state)
+int pcmcia_socket_dev_suspend(struct device *dev)
{
struct pcmcia_socket *socket;
--- a/drivers/pcmcia/i82092.c
+++ b/drivers/pcmcia/i82092.c
@@ -42,7 +42,7 @@ MODULE_DEVICE_TABLE(pci, i82092aa_pci_id
#ifdef CONFIG_PM
static int i82092aa_socket_suspend (struct pci_dev *dev, pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int i82092aa_socket_resume (struct pci_dev *dev)
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -1241,7 +1241,7 @@ static int pcic_init(struct pcmcia_socke
static int i82365_drv_pcmcia_suspend(struct platform_device *dev,
pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int i82365_drv_pcmcia_resume(struct platform_device *dev)
--- a/drivers/pcmcia/m32r_cfc.c
+++ b/drivers/pcmcia/m32r_cfc.c
@@ -699,7 +699,7 @@ static struct pccard_operations pcc_oper
static int cfc_drv_pcmcia_suspend(struct platform_device *dev,
pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int cfc_drv_pcmcia_resume(struct platform_device *dev)
--- a/drivers/pcmcia/m32r_pcc.c
+++ b/drivers/pcmcia/m32r_pcc.c
@@ -675,7 +675,7 @@ static struct pccard_operations pcc_oper
static int pcc_drv_pcmcia_suspend(struct platform_device *dev,
pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int pcc_drv_pcmcia_resume(struct platform_device *dev)
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -1296,7 +1296,7 @@ static int m8xx_remove(struct of_device
#ifdef CONFIG_PM
static int m8xx_suspend(struct platform_device *pdev, pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&pdev->dev, state);
+ return pcmcia_socket_dev_suspend(&pdev->dev);
}
static int m8xx_resume(struct platform_device *pdev)
--- a/drivers/pcmcia/omap_cf.c
+++ b/drivers/pcmcia/omap_cf.c
@@ -334,7 +334,7 @@ static int __exit omap_cf_remove(struct
static int omap_cf_suspend(struct platform_device *pdev, pm_message_t mesg)
{
- return pcmcia_socket_dev_suspend(&pdev->dev, mesg);
+ return pcmcia_socket_dev_suspend(&pdev->dev);
}
static int omap_cf_resume(struct platform_device *pdev)
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -758,7 +758,7 @@ static void __devexit pd6729_pci_remove(
#ifdef CONFIG_PM
static int pd6729_socket_suspend(struct pci_dev *dev, pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int pd6729_socket_resume(struct pci_dev *dev)
--- a/drivers/pcmcia/pxa2xx_base.c
+++ b/drivers/pcmcia/pxa2xx_base.c
@@ -302,7 +302,7 @@ static int pxa2xx_drv_pcmcia_remove(stru
static int pxa2xx_drv_pcmcia_suspend(struct platform_device *dev, pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int pxa2xx_drv_pcmcia_resume(struct platform_device *dev)
--- a/drivers/pcmcia/sa1100_generic.c
+++ b/drivers/pcmcia/sa1100_generic.c
@@ -89,7 +89,7 @@ static int sa11x0_drv_pcmcia_remove(stru
static int sa11x0_drv_pcmcia_suspend(struct platform_device *dev,
pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int sa11x0_drv_pcmcia_resume(struct platform_device *dev)
--- a/drivers/pcmcia/sa1111_generic.c
+++ b/drivers/pcmcia/sa1111_generic.c
@@ -159,7 +159,7 @@ static int __devexit pcmcia_remove(struc
static int pcmcia_suspend(struct sa1111_dev *dev, pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int pcmcia_resume(struct sa1111_dev *dev)
--- a/drivers/pcmcia/tcic.c
+++ b/drivers/pcmcia/tcic.c
@@ -366,7 +366,7 @@ static int __init get_tcic_id(void)
static int tcic_drv_pcmcia_suspend(struct platform_device *dev,
pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int tcic_drv_pcmcia_resume(struct platform_device *dev)
--- a/drivers/pcmcia/vrc4171_card.c
+++ b/drivers/pcmcia/vrc4171_card.c
@@ -707,7 +707,7 @@ __setup("vrc4171_card=", vrc4171_card_se
static int vrc4171_card_suspend(struct platform_device *dev,
pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int vrc4171_card_resume(struct platform_device *dev)
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -1230,7 +1230,7 @@ static int yenta_dev_suspend (struct pci
struct yenta_socket *socket = pci_get_drvdata(dev);
int ret;
- ret = pcmcia_socket_dev_suspend(&dev->dev, state);
+ ret = pcmcia_socket_dev_suspend(&dev->dev);
if (socket) {
if (socket->type && socket->type->save_state)
--- a/include/pcmcia/ss.h
+++ b/include/pcmcia/ss.h
@@ -279,7 +279,7 @@ extern struct pccard_resource_ops pccard
extern struct pccard_resource_ops pccard_nonstatic_ops;
/* socket drivers are expected to use these callbacks in their .drv struct */
-extern int pcmcia_socket_dev_suspend(struct device *dev, pm_message_t state);
+extern int pcmcia_socket_dev_suspend(struct device *dev);
extern int pcmcia_socket_dev_resume(struct device *dev);
/* socket drivers use this callback in their IRQ handler */
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Rafael J. Wysocki <[email protected]>
commit 0c570cdeb8fdfcb354a3e9cd81bfc6a09c19de0c upstream.
Since 2.6.29 the PCI PM core have been restoring the standard
configuration registers of PCI devices in the early phase of
resume. In particular, PCI devices without drivers have been handled
this way since commit 355a72d75b3b4f4877db4c9070c798238028ecb5
(PCI: Rework default handling of suspend and resume). Unfortunately,
this leads to post-resume problems with CardBus devices which cannot
be accessed in the early phase of resume, because the sockets they
are on have not been woken up yet at that point.
To solve this problem, move the yenta socket resume to the early
phase of resume and, analogously, move the suspend of it to the late
phase of suspend. Additionally, remove some unnecessary PCI code
from the yenta socket's resume routine.
Fixes http://bugzilla.kernel.org/show_bug.cgi?id=13092, which is a
post-2.6.28 regression.
Signed-off-by: Rafael J. Wysocki <[email protected]>
Reported-by: Florian <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/pcmcia/yenta_socket.c | 92 ++++++++++++++++++++++--------------------
1 file changed, 50 insertions(+), 42 deletions(-)
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -1225,60 +1225,71 @@ static int __devinit yenta_probe (struct
}
#ifdef CONFIG_PM
-static int yenta_dev_suspend (struct pci_dev *dev, pm_message_t state)
+static int yenta_dev_suspend_noirq(struct device *dev)
{
- struct yenta_socket *socket = pci_get_drvdata(dev);
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct yenta_socket *socket = pci_get_drvdata(pdev);
int ret;
- ret = pcmcia_socket_dev_suspend(&dev->dev);
+ ret = pcmcia_socket_dev_suspend(dev);
- if (socket) {
- if (socket->type && socket->type->save_state)
- socket->type->save_state(socket);
-
- /* FIXME: pci_save_state needs to have a better interface */
- pci_save_state(dev);
- pci_read_config_dword(dev, 16*4, &socket->saved_state[0]);
- pci_read_config_dword(dev, 17*4, &socket->saved_state[1]);
- pci_disable_device(dev);
-
- /*
- * Some laptops (IBM T22) do not like us putting the Cardbus
- * bridge into D3. At a guess, some other laptop will
- * probably require this, so leave it commented out for now.
- */
- /* pci_set_power_state(dev, 3); */
- }
+ if (!socket)
+ return ret;
+
+ if (socket->type && socket->type->save_state)
+ socket->type->save_state(socket);
+
+ pci_save_state(pdev);
+ pci_read_config_dword(pdev, 16*4, &socket->saved_state[0]);
+ pci_read_config_dword(pdev, 17*4, &socket->saved_state[1]);
+ pci_disable_device(pdev);
+
+ /*
+ * Some laptops (IBM T22) do not like us putting the Cardbus
+ * bridge into D3. At a guess, some other laptop will
+ * probably require this, so leave it commented out for now.
+ */
+ /* pci_set_power_state(dev, 3); */
return ret;
}
-
-static int yenta_dev_resume (struct pci_dev *dev)
+static int yenta_dev_resume_noirq(struct device *dev)
{
- struct yenta_socket *socket = pci_get_drvdata(dev);
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct yenta_socket *socket = pci_get_drvdata(pdev);
+ int ret;
- if (socket) {
- int rc;
+ if (!socket)
+ return 0;
- pci_set_power_state(dev, 0);
- /* FIXME: pci_restore_state needs to have a better interface */
- pci_restore_state(dev);
- pci_write_config_dword(dev, 16*4, socket->saved_state[0]);
- pci_write_config_dword(dev, 17*4, socket->saved_state[1]);
+ pci_write_config_dword(pdev, 16*4, socket->saved_state[0]);
+ pci_write_config_dword(pdev, 17*4, socket->saved_state[1]);
- rc = pci_enable_device(dev);
- if (rc)
- return rc;
+ ret = pci_enable_device(pdev);
+ if (ret)
+ return ret;
- pci_set_master(dev);
+ pci_set_master(pdev);
- if (socket->type && socket->type->restore_state)
- socket->type->restore_state(socket);
- }
+ if (socket->type && socket->type->restore_state)
+ socket->type->restore_state(socket);
- return pcmcia_socket_dev_resume(&dev->dev);
+ return pcmcia_socket_dev_resume(dev);
}
+
+static struct dev_pm_ops yenta_pm_ops = {
+ .suspend_noirq = yenta_dev_suspend_noirq,
+ .resume_noirq = yenta_dev_resume_noirq,
+ .freeze_noirq = yenta_dev_suspend_noirq,
+ .thaw_noirq = yenta_dev_resume_noirq,
+ .poweroff_noirq = yenta_dev_suspend_noirq,
+ .restore_noirq = yenta_dev_resume_noirq,
+};
+
+#define YENTA_PM_OPS (¥ta_pm_ops)
+#else
+#define YENTA_PM_OPS NULL
#endif
#define CB_ID(vend,dev,type) \
@@ -1376,10 +1387,7 @@ static struct pci_driver yenta_cardbus_d
.id_table = yenta_table,
.probe = yenta_probe,
.remove = __devexit_p(yenta_close),
-#ifdef CONFIG_PM
- .suspend = yenta_dev_suspend,
- .resume = yenta_dev_resume,
-#endif
+ .driver.pm = YENTA_PM_OPS,
};
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Alan Jenkins <[email protected]>
commit 50fab0760a6c07cded229357a1351c325a575770 upstream.
"I recently (on a flight) I found out that when I boot with the hard-switch
activated, so turning off all wireless activity on my laptop, the state
is not correctly announced in /dev/rfkill (reading it with rfkill command,
or my own gnome applet)...
After turning off and on again the hard-switch the events were right."
We can fix this by querying the firmware at load time and calling
rfkill_set_hw_state().
Signed-off-by: Alan Jenkins <[email protected]>
Tested-by: Norbert Preining <[email protected]>
Acked-by: Johannes Berg <[email protected]>
Acked-by: Mattia Dongili <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/platform/x86/sony-laptop.c | 6 ++++++
1 file changed, 6 insertions(+)
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -1081,6 +1081,8 @@ static int sony_nc_setup_rfkill(struct a
struct rfkill *rfk;
enum rfkill_type type;
const char *name;
+ int result;
+ bool hwblock;
switch (nc_type) {
case SONY_WIFI:
@@ -1108,6 +1110,10 @@ static int sony_nc_setup_rfkill(struct a
if (!rfk)
return -ENOMEM;
+ sony_call_snc_handle(0x124, 0x200, &result);
+ hwblock = !(result & 0x1);
+ rfkill_set_hw_state(rfk, hwblock);
+
err = rfkill_register(rfk);
if (err) {
rfkill_destroy(rfk);
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Ryusuke Konishi <[email protected]>
commit 1f28fcd925b2b3157411bbd08f0024b55b70d8dd upstream.
This will fix file system corruption which infrequently happens after
mount. The problem was reported from users with the title "[NILFS
users] Fail to mount NILFS." (Message-ID:
<[email protected]>), and so forth. I've also
experienced the corruption multiple times on kernel 2.6.30 and 2.6.31.
The problem turned out to be caused due to discordance between
mapping->nrpages of a btree node cache and the actual number of pages
hung on the cache; if the mapping->nrpages becomes zero even as it has
pages, truncate_inode_pages() returns without doing anything. Usually
this is harmless except it may cause page leak, but garbage collection
fairly infrequently sees a stale page remained in the btree node cache
of DAT (i.e. disk address translation file of nilfs), and induces the
corruption.
I identified a missing initialization in btree node caches was the
root cause. This corrects the bug.
I've tested this for kernel 2.6.30 and 2.6.31.
Reported-by: Yuri Chislov <[email protected]>
Signed-off-by: Ryusuke Konishi <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/nilfs2/btnode.c | 1 +
1 file changed, 1 insertion(+)
--- a/fs/nilfs2/btnode.c
+++ b/fs/nilfs2/btnode.c
@@ -36,6 +36,7 @@
void nilfs_btnode_cache_init_once(struct address_space *btnc)
{
+ memset(btnc, 0, sizeof(*btnc));
INIT_RADIX_TREE(&btnc->page_tree, GFP_ATOMIC);
spin_lock_init(&btnc->tree_lock);
INIT_LIST_HEAD(&btnc->private_list);
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Christian Lamparter <[email protected]>
commit fe9f6342c86292aee1941447f22dc5470735e5a1 upstream.
This patch adds the usbid for TP-Link TL-WN821N v2.
Reported-by: Fabian Lenz <[email protected]>
Signed-off-by: Christian Lamparter <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/net/wireless/ath/ar9170/usb.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/net/wireless/ath/ar9170/usb.c
+++ b/drivers/net/wireless/ath/ar9170/usb.c
@@ -64,6 +64,8 @@ static struct usb_device_id ar9170_usb_i
{ USB_DEVICE(0x0cf3, 0x9170) },
/* Atheros TG121N */
{ USB_DEVICE(0x0cf3, 0x1001) },
+ /* TP-Link TL-WN821N v2 */
+ { USB_DEVICE(0x0cf3, 0x1002) },
/* Cace Airpcap NX */
{ USB_DEVICE(0xcace, 0x0300) },
/* D-Link DWA 160A */
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Feng Kan <[email protected]>
commit 76c23c32e3b3ad48e07e07897075ab19ae1ef117 upstream.
Fix ECC Correction bug where the byte offset location were double
fliped causing correction routine to toggle the wrong byte location
in the ECC segment. The ndfc_calculate_ecc routine change the order
of getting the ECC code.
/* The NDFC uses Smart Media (SMC) bytes order */
ecc_code[0] = p[2];
ecc_code[1] = p[1];
ecc_code[2] = p[3];
But in the Correction algorithm when calculating the byte offset
location, the b1 is used as the upper part of the address. Which
again reverse the order making the final byte offset address
location incorrect.
byte_addr = (addressbits[b1] << 4) + addressbits[b0];
The order is change to read it in straight and let the correction
function to revert it to SMC order.
Signed-off-by: Feng Kan <[email protected]>
Acked-by: Victor Gallardo <[email protected]>
Acked-by: Prodyut Hazarika <[email protected]>
Acked-by: Stefan Roese <[email protected]>
Signed-off-by: David Woodhouse <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/mtd/nand/ndfc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -102,8 +102,8 @@ static int ndfc_calculate_ecc(struct mtd
wmb();
ecc = in_be32(ndfc->ndfcbase + NDFC_ECC);
/* The NDFC uses Smart Media (SMC) bytes order */
- ecc_code[0] = p[2];
- ecc_code[1] = p[1];
+ ecc_code[0] = p[1];
+ ecc_code[1] = p[2];
ecc_code[2] = p[3];
return 0;
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Benjamin Krill <[email protected]>
commit ebd5a74db74ee2db833d43ea35108a4be9cab42f upstream.
The previous implementation breaks the dts binding "mtd-physmap.txt". This
implementation fixes the issue by checking the availability of the reg
property instead of the name property.
Signed-off-by: Benjamin Krill <[email protected]>
Signed-off-by: David Woodhouse <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/mtd/ofpart.c | 21 ++++++++++-----------
1 file changed, 10 insertions(+), 11 deletions(-)
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -46,21 +46,12 @@ int __devinit of_mtd_parse_partitions(st
const u32 *reg;
int len;
- /* check if this is a partition node */
- partname = of_get_property(pp, "name", &len);
- if (strcmp(partname, "partition") != 0) {
+ reg = of_get_property(pp, "reg", &len);
+ if (!reg) {
nr_parts--;
continue;
}
- reg = of_get_property(pp, "reg", &len);
- if (!reg || (len != 2 * sizeof(u32))) {
- of_node_put(pp);
- dev_err(dev, "Invalid 'reg' on %s\n", node->full_name);
- kfree(*pparts);
- *pparts = NULL;
- return -EINVAL;
- }
(*pparts)[i].offset = reg[0];
(*pparts)[i].size = reg[1];
@@ -75,6 +66,14 @@ int __devinit of_mtd_parse_partitions(st
i++;
}
+ if (!i) {
+ of_node_put(pp);
+ dev_err(dev, "No valid partition found on %s\n", node->full_name);
+ kfree(*pparts);
+ *pparts = NULL;
+ return -EINVAL;
+ }
+
return nr_parts;
}
EXPORT_SYMBOL(of_mtd_parse_partitions);
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Massimo Cirillo <[email protected]>
commit 23af51ecfb04ff65bae51bd8e2270f4449abc789 upstream.
The M29W128G Numonyx flash devices are intolerant to any 0xFF command:
in the Cfi_util.c the function cfi_qry_mode_off() (that resets the device
after the autoselect mode) must have a 0xF0 command after the 0xFF command.
This fix solves also the cause of the fixup_M29W128G_write_buffer() fix,
that can be removed now.
The following patch applies to 2.6.30 kernel.
Signed-off-by: Massimo Cirillo <[email protected]>
Acked-by: Alexey Korolev <[email protected]>
Signed-off-by: David Woodhouse <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/mtd/chips/cfi_cmdset_0002.c | 11 -----------
drivers/mtd/chips/cfi_util.c | 4 ++++
2 files changed, 4 insertions(+), 11 deletions(-)
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -282,16 +282,6 @@ static void fixup_s29gl032n_sectors(stru
}
}
-static void fixup_M29W128G_write_buffer(struct mtd_info *mtd, void *param)
-{
- struct map_info *map = mtd->priv;
- struct cfi_private *cfi = map->fldrv_priv;
- if (cfi->cfiq->BufWriteTimeoutTyp) {
- pr_warning("Don't use write buffer on ST flash M29W128G\n");
- cfi->cfiq->BufWriteTimeoutTyp = 0;
- }
-}
-
static struct cfi_fixup cfi_fixup_table[] = {
{ CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL },
#ifdef AMD_BOOTLOC_BUG
@@ -308,7 +298,6 @@ static struct cfi_fixup cfi_fixup_table[
{ CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors, NULL, },
{ CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors, NULL, },
{ CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors, NULL, },
- { CFI_MFR_ST, 0x227E, fixup_M29W128G_write_buffer, NULL, },
#if !FORCE_WORD_WRITE
{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, },
#endif
--- a/drivers/mtd/chips/cfi_util.c
+++ b/drivers/mtd/chips/cfi_util.c
@@ -81,6 +81,10 @@ void __xipram cfi_qry_mode_off(uint32_t
{
cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
+ /* M29W128G flashes require an additional reset command
+ when exit qry mode */
+ if ((cfi->mfr == CFI_MFR_ST) && (cfi->id == 0x227E || cfi->id == 0x7E))
+ cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
}
EXPORT_SYMBOL_GPL(cfi_qry_mode_off);
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Pawel Ludwikow <[email protected]>
commit e7d7fcc09ebde1ea1773521ecab5a3f0ad6bef6e upstream.
I'd like to present my small patch enabling to use Hameg HM8143 programmable
power supply with linux.
Signed-off-by: Pawel Ludwikow <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/serial/ftdi_sio.c | 2 ++
drivers/usb/serial/ftdi_sio.h | 6 ++++++
2 files changed, 8 insertions(+)
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -702,6 +702,8 @@ static struct usb_device_id id_table_com
{ USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) },
{ USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(FTDI_VID, HAMEG_HO820_PID) },
+ { USB_DEVICE(FTDI_VID, HAMEG_HO870_PID) },
{ }, /* Optional parameter entry */
{ } /* Terminating entry */
};
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -968,6 +968,12 @@
#define MARVELL_OPENRD_PID 0x9e90
/*
+ * Hameg HO820 and HO870 interface (using VID 0x0403)
+ */
+#define HAMEG_HO820_PID 0xed74
+#define HAMEG_HO870_PID 0xed71
+
+/*
* BmRequestType: 1100 0000b
* bRequest: FTDI_E2_READ
* wValue: 0
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: [email protected] <[email protected]>
commit ec3815c3e14dc68d49428e6505ae99e86e5dd067 upstream.
Some devices from the OpenDCC project are missing in the list
of the FTDI PIDs. These PIDs are listed at
http://www.opendcc.de/elektronik/usb/opendcc_usb.html
(Sorry for the german only page.)
This patch adds the three missing devices.
Signed-off-by: Rainer Keller <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/serial/ftdi_sio.c | 3 +++
drivers/usb/serial/ftdi_sio.h | 3 +++
2 files changed, 6 insertions(+)
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -176,6 +176,9 @@ static struct usb_device_id id_table_com
{ USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_SNIFFER_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_THROTTLE_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GATEWAY_PID) },
{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SPROG_II) },
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -81,6 +81,9 @@
/* OpenDCC (http://www.opendcc.de) product id */
#define FTDI_OPENDCC_PID 0xBFD8
+#define FTDI_OPENDCC_SNIFFER_PID 0xBFD9
+#define FTDI_OPENDCC_THROTTLE_PID 0xBFDA
+#define FTDI_OPENDCC_GATEWAY_PID 0xBFDB
/* Sprog II (Andrew Crosland's SprogII DCC interface) */
#define FTDI_SPROG_II 0xF0C8
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Michael Hennerich <[email protected]>
commit 11eaf170363d264ff587f300e41c927ba5a33967 upstream.
Detect the UART on interface1 and blacklist interface0 (as that is the
JTAG port).
Signed-off-by: Michael Hennerich <[email protected]>
Signed-off-by: Mike Frysinger <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/serial/ftdi_sio.c | 2 ++
drivers/usb/serial/ftdi_sio.h | 1 +
2 files changed, 3 insertions(+)
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -697,6 +697,8 @@ static struct usb_device_id id_table_com
{ USB_DEVICE(DE_VID, WHT_PID) },
{ USB_DEVICE(ADI_VID, ADI_GNICE_PID),
.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(JETI_VID, JETI_SPC1201_PID) },
{ USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -933,6 +933,7 @@
*/
#define ADI_VID 0x0456
#define ADI_GNICE_PID 0xF000
+#define ADI_GNICEPLUS_PID 0xF001
/*
* JETI SPECTROMETER SPECBOS 1201
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Oliver Neukum <[email protected]>
commit 7f1dc313d01f5f0f84c06051343a3b8623932d3c upstream.
support for O_NONBLOCK in read and write path
by simply not waiting for data in read or availability
of the write urb in write but returning -EAGAIN
Signed-off-by: Oliver Neukum <[email protected]>
Tested-by: Marcel Holtmann <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/class/cdc-wdm.c | 30 ++++++++++++++++++++++++------
1 file changed, 24 insertions(+), 6 deletions(-)
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -313,8 +313,13 @@ static ssize_t wdm_write
r = usb_autopm_get_interface(desc->intf);
if (r < 0)
goto outnp;
- r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE,
- &desc->flags));
+
+ if (!file->f_flags && O_NONBLOCK)
+ r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE,
+ &desc->flags));
+ else
+ if (test_bit(WDM_IN_USE, &desc->flags))
+ r = -EAGAIN;
if (r < 0)
goto out;
@@ -377,7 +382,7 @@ outnl:
static ssize_t wdm_read
(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
- int rv, cntr;
+ int rv, cntr = 0;
int i = 0;
struct wdm_device *desc = file->private_data;
@@ -389,10 +394,23 @@ static ssize_t wdm_read
if (desc->length == 0) {
desc->read = 0;
retry:
+ if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
+ rv = -ENODEV;
+ goto err;
+ }
i++;
- rv = wait_event_interruptible(desc->wait,
- test_bit(WDM_READ, &desc->flags));
+ if (file->f_flags & O_NONBLOCK) {
+ if (!test_bit(WDM_READ, &desc->flags)) {
+ rv = cntr ? cntr : -EAGAIN;
+ goto err;
+ }
+ rv = 0;
+ } else {
+ rv = wait_event_interruptible(desc->wait,
+ test_bit(WDM_READ, &desc->flags));
+ }
+ /* may have happened while we slept */
if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
rv = -ENODEV;
goto err;
@@ -448,7 +466,7 @@ retry:
err:
mutex_unlock(&desc->rlock);
- if (rv < 0)
+ if (rv < 0 && rv != -EAGAIN)
dev_err(&desc->intf->dev, "wdm_read: exit error\n");
return rv;
}
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Oliver Neukum <[email protected]>
commit 7af25b4b34a2439020d78da765a3bed0ff73f25c upstream.
cdc-acm needs to set a flag during open to tell the
tty layer that the device is initialized
Signed-off-by: Oliver Neukum <[email protected]>
Cc: Marcel Holtmann <[email protected]>
Cc: Paul Martin <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/class/cdc-acm.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -59,6 +59,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
+#include <linux/serial.h>
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
#include <linux/module.h>
@@ -609,6 +610,7 @@ static int acm_tty_open(struct tty_struc
acm->throttle = 0;
tasklet_schedule(&acm->urb_task);
+ set_bit(ASYNCB_INITIALIZED, &acm->port.flags);
rv = tty_port_block_til_ready(&acm->port, tty, filp);
done:
mutex_unlock(&acm->mutex);
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Alan Cox <[email protected]>
commit 9b80fee149a875a6292b2556ab2c64dc7ab7d6f5 upstream.
This changed in 2006 so its about time the ACM driver caught up
Signed-off-by: Alan Cox <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/class/cdc-acm.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -860,10 +860,7 @@ static void acm_tty_set_termios(struct t
if (!ACM_READY(acm))
return;
- /* FIXME: Needs to support the tty_baud interface */
- /* FIXME: Broken on sparc */
- newline.dwDTERate = cpu_to_le32p(acm_tty_speed +
- (termios->c_cflag & CBAUD & ~CBAUDEX) + (termios->c_cflag & CBAUDEX ? 15 : 0));
+ newline.dwDTERate = cpu_to_le32(tty_get_baud_rate(tty));
newline.bCharFormat = termios->c_cflag & CSTOPB ? 2 : 0;
newline.bParityType = termios->c_cflag & PARENB ?
(termios->c_cflag & PARODD ? 1 : 2) +
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Alan Cox <[email protected]>
commit 9a68e39d4a701fb3be03cae9b462408664ebd205 upstream.
These are handled by the tty_port core code which will raise and lower the
carrier correctly in tty_wait_until_ready
Signed-off-by: Alan Cox <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/serial/cp210x.c | 6 ------
1 file changed, 6 deletions(-)
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -399,12 +399,6 @@ static int cp210x_open(struct tty_struct
/* Configure the termios structure */
cp210x_get_termios(tty, port);
-
- /* Set the DTR and RTS pins low */
- cp210x_tiocmset_port(tty ? (struct usb_serial_port *) tty->driver_data
- : port,
- NULL, TIOCM_DTR | TIOCM_RTS, 0);
-
return 0;
}
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Tilman Schmidt <[email protected]>
commit a4304f2d5a3823deea894026ec95e43b33912357 upstream.
The tty_operation chars_in_buffer() is not allowed to return a negative
value to signal an error. Corrects the problem flagged by commit
23198fda7182969b619613a555f8645fdc3dc334, "tty: fix chars_in_buffers".
Signed-off-by: Tilman Schmidt <[email protected]>
Cc: "David S. Miller" <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/isdn/gigaset/interface.c | 19 +++++++------------
1 file changed, 7 insertions(+), 12 deletions(-)
--- a/drivers/isdn/gigaset/interface.c
+++ b/drivers/isdn/gigaset/interface.c
@@ -408,33 +408,28 @@ static int if_write_room(struct tty_stru
return retval;
}
-/* FIXME: This function does not have error returns */
-
static int if_chars_in_buffer(struct tty_struct *tty)
{
struct cardstate *cs;
- int retval = -ENODEV;
+ int retval = 0;
cs = (struct cardstate *) tty->driver_data;
if (!cs) {
pr_err("%s: no cardstate\n", __func__);
- return -ENODEV;
+ return 0;
}
gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
- if (mutex_lock_interruptible(&cs->mutex))
- return -ERESTARTSYS; // FIXME -EINTR?
+ mutex_lock(&cs->mutex);
- if (!cs->connected) {
+ if (!cs->connected)
gig_dbg(DEBUG_IF, "not connected");
- retval = -ENODEV;
- } else if (!cs->open_count)
+ else if (!cs->open_count)
dev_warn(cs->dev, "%s: device not opened\n", __func__);
- else if (cs->mstate != MS_LOCKED) {
+ else if (cs->mstate != MS_LOCKED)
dev_warn(cs->dev, "can't write to unlocked device\n");
- retval = -EBUSY;
- } else
+ else
retval = cs->ops->chars_in_buffer(cs);
mutex_unlock(&cs->mutex);
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Kevin Cernekee <[email protected]>
commit 051b982bcc620695de629d29c333c95b66e9b95e upstream.
kaweth_control() never frees the buffer that it allocates for the USB
control message. Test case:
while :; do ifconfig eth2 down ; ifconfig eth2 up ; done
This is a tiny buffer so it is a slow leak. If you want to speed up the
process, you can change the allocation size to e.g. 16384 bytes, and it
will consume several megabytes within a few minutes.
Signed-off-by: Kevin Cernekee <[email protected]>
Acked-by: Oliver Neukum <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/net/usb/kaweth.c | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
--- a/drivers/net/usb/kaweth.c
+++ b/drivers/net/usb/kaweth.c
@@ -263,6 +263,7 @@ static int kaweth_control(struct kaweth_
int timeout)
{
struct usb_ctrlrequest *dr;
+ int retval;
dbg("kaweth_control()");
@@ -278,18 +279,21 @@ static int kaweth_control(struct kaweth_
return -ENOMEM;
}
- dr->bRequestType= requesttype;
+ dr->bRequestType = requesttype;
dr->bRequest = request;
dr->wValue = cpu_to_le16(value);
dr->wIndex = cpu_to_le16(index);
dr->wLength = cpu_to_le16(size);
- return kaweth_internal_control_msg(kaweth->dev,
- pipe,
- dr,
- data,
- size,
- timeout);
+ retval = kaweth_internal_control_msg(kaweth->dev,
+ pipe,
+ dr,
+ data,
+ size,
+ timeout);
+
+ kfree(dr);
+ return retval;
}
/****************************************************************
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Jack Steiner <[email protected]>
commit d2374aecda3f6c9b0d13287027132a37311da300 upstream.
The UV BIOS has changed the way interrupt remapping is being done.
This affects the id used for sending IPIs. The upper id bits no
longer need to be masked off.
Signed-off-by: Jack Steiner <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/x86/include/asm/uv/uv_hub.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/x86/include/asm/uv/uv_hub.h
+++ b/arch/x86/include/asm/uv/uv_hub.h
@@ -422,7 +422,7 @@ static inline void uv_hub_send_ipi(int p
unsigned long val;
val = (1UL << UVH_IPI_INT_SEND_SHFT) |
- ((apicid & 0x3f) << UVH_IPI_INT_APIC_ID_SHFT) |
+ ((apicid) << UVH_IPI_INT_APIC_ID_SHFT) |
(vector << UVH_IPI_INT_VECTOR_SHFT);
uv_write_global_mmr64(pnode, UVH_IPI_INT, val);
}
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Pawel Ludwikow <[email protected]>
commit 35904e6b5106fda51b04c8b8080c04466865415f upstream.
I'd like to present my small patch enabling to use Sanwa PC5000
mulitimeter with linux.
Signed-off-by: Pawel Ludwikow <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/serial/pl2303.c | 1 +
drivers/usb/serial/pl2303.h | 4 ++++
2 files changed, 5 insertions(+)
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -96,6 +96,7 @@ static struct usb_device_id id_table []
{ USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) },
{ USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) },
+ { USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) },
{ } /* Terminating entry */
};
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -130,3 +130,7 @@
/* Sony, USB data cable for CMD-Jxx mobile phones */
#define SONY_VENDOR_ID 0x054c
#define SONY_QN3USB_PRODUCT_ID 0x0437
+
+/* Sanwa KB-USB2 multimeter cable (ID: 11ad:0001) */
+#define SANWA_VENDOR_ID 0x11ad
+#define SANWA_PRODUCT_ID 0x0001
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Oliver Neukum <[email protected]>
commit e5dc8ae121592239c2a2521d383bcb789849b2a3 upstream.
In the resume path of a block driver GFP_NOIO must be used to
avoid a possible deadlock. The onetouch subdriver of storage violates
the requirement.
Signed-off-by: Oliver Neukum <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/storage/onetouch.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/usb/storage/onetouch.c
+++ b/drivers/usb/storage/onetouch.c
@@ -163,7 +163,7 @@ static void usb_onetouch_pm_hook(struct
usb_kill_urb(onetouch->irq);
break;
case US_RESUME:
- if (usb_submit_urb(onetouch->irq, GFP_KERNEL) != 0)
+ if (usb_submit_urb(onetouch->irq, GFP_NOIO) != 0)
dev_err(&onetouch->irq->dev->dev,
"usb_submit_urb failed\n");
break;
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: fangxiaozhi <[email protected]>
commit d0defb855c8504c49b92bdc0203689ce9b4cf7ba upstream.
In this patch, we always make the return value of function
usb_stor_huawei_e220_init to be zero. Then it will not prevent usb-storage
driver from attaching to the CDROM device of Huawei Datacard.
Signed-off-by: fangxiaozhi <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/storage/initializers.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/usb/storage/initializers.c
+++ b/drivers/usb/storage/initializers.c
@@ -102,5 +102,5 @@ int usb_stor_huawei_e220_init(struct us_
USB_TYPE_STANDARD | USB_RECIP_DEVICE,
0x01, 0x0, NULL, 0x0, 1000);
US_DEBUGP("Huawei mode set result is %d\n", result);
- return (result ? 0 : -ENODEV);
+ return 0;
}
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Guus Sliepen <[email protected]>
commit 665d7662d15441b4b3e54131a9418a1a198d0d31 upstream.
According to the specifications, an instrument should not return more data in a
DEV_DEP_MSG_IN urb than requested. However, some instruments can send more
than requested. This could cause the kernel to write the extra data past the
end of the buffer provided by read().
Fix this by checking that the value of the TranserSize field is not larger than
the urb itself and not larger than the size of the userspace buffer. Also
correctly decrement the remaining size of the buffer when userspace read()s
more than USBTMC_SIZE_IOBUFFER.
Signed-off-by: Guus Sliepen <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/class/usbtmc.c | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -367,13 +367,13 @@ static ssize_t usbtmc_read(struct file *
{
struct usbtmc_device_data *data;
struct device *dev;
- unsigned long int n_characters;
+ u32 n_characters;
u8 *buffer;
int actual;
- int done;
- int remaining;
+ size_t done;
+ size_t remaining;
int retval;
- int this_part;
+ size_t this_part;
/* Get pointer to private data structure */
data = filp->private_data;
@@ -455,6 +455,18 @@ static ssize_t usbtmc_read(struct file *
(buffer[6] << 16) +
(buffer[7] << 24);
+ /* Ensure the instrument doesn't lie about it */
+ if(n_characters > actual - 12) {
+ dev_err(dev, "Device lies about message size: %zu > %zu\n", n_characters, actual - 12);
+ n_characters = actual - 12;
+ }
+
+ /* Ensure the instrument doesn't send more back than requested */
+ if(n_characters > this_part) {
+ dev_err(dev, "Device returns more than requested: %zu > %zu\n", done + n_characters, done + this_part);
+ n_characters = this_part;
+ }
+
/* Copy buffer to user space */
if (copy_to_user(buf + done, &buffer[12], n_characters)) {
/* There must have been an addressing problem */
@@ -465,6 +477,8 @@ static ssize_t usbtmc_read(struct file *
done += n_characters;
if (n_characters < USBTMC_SIZE_IOBUFFER)
remaining = 0;
+ else
+ remaining -= n_characters;
}
/* Update file position value */
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Hennerich, Michael <[email protected]>
commit eb661bc88252e5c6dc69df732e77e42981dd4d8b upstream.
SL811 Device detected after removal used to be working in linux-2.6.22
but then broke somewhere between 2.6.22 and 2.6.28. Current
hub_port_connect_change() in drivers/usb/core/hub.c won't call
usb_disconnect() in case the SL811 driver sets portstatus
USB_PORT_FEAT_CONNECTION upon removal.
AFAIK the SL811 has only a combined Device Insert/Remove
detection bit, therefore use a count to distinguish insert or remove.
Signed-Off-By: Michael Hennerich <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/host/sl811-hcd.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -719,8 +719,12 @@ retry:
/* port status seems weird until after reset, so
* force the reset and make khubd clean up later.
*/
- sl811->port1 |= (1 << USB_PORT_FEAT_C_CONNECTION)
- | (1 << USB_PORT_FEAT_CONNECTION);
+ if (sl811->stat_insrmv & 1)
+ sl811->port1 |= 1 << USB_PORT_FEAT_CONNECTION;
+ else
+ sl811->port1 &= ~(1 << USB_PORT_FEAT_CONNECTION);
+
+ sl811->port1 |= 1 << USB_PORT_FEAT_C_CONNECTION;
} else if (irqstat & SL11H_INTMASK_RD) {
if (sl811->port1 & (1 << USB_PORT_FEAT_SUSPEND)) {
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Zhenyu Wang <[email protected]>
commit b7e53aba2f0e6abf23e3f07b38b241145c33a005 upstream.
Don't need extra config restore like for intel_agp, which
might cause resume hang issue found by Alan on 845G.
Cc: Stable Team <[email protected]>
Cc: Alan Stern <[email protected]>
Signed-off-by: Zhenyu Wang <[email protected]>
Signed-off-by: Jesse Barnes <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/gpu/drm/i915/i915_drv.c | 2 --
1 file changed, 2 deletions(-)
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -94,8 +94,6 @@ static int i915_resume(struct drm_device
struct drm_i915_private *dev_priv = dev->dev_private;
int ret = 0;
- pci_set_power_state(dev->pdev, PCI_D0);
- pci_restore_state(dev->pdev);
if (pci_enable_device(dev->pdev))
return -1;
pci_set_master(dev->pdev);
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Chris Wilson <[email protected]>
commit 7e61615857c6fb3afbcb43f5c4e97511a923f5a8 upstream.
drm_ht_remove_item() does not handle removing an absent item and the hlist
in particular is incorrectly initialised. The easy remedy is simply skip
calling i915_gem_free_mmap_offset() unless we have actually created the
offset and associated ht entry.
This also fixes the mishandling of a partially constructed offset which
leaves pointers initialized after freeing them along the
i915_gem_create_mmap_offset() error paths.
In particular this should fix the oops found here:
https://bugs.launchpad.net/ubuntu/+source/xserver-xorg-video-intel/+bug/415357/comments/8
Signed-off-by: Chris Wilson <[email protected]>
Signed-off-by: Eric Anholt <[email protected]>
---
drivers/gpu/drm/i915/i915_gem.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -3837,7 +3837,8 @@ void i915_gem_free_object(struct drm_gem
i915_gem_object_unbind(obj);
- i915_gem_free_mmap_offset(obj);
+ if (obj_priv->mmap_offset)
+ i915_gem_free_mmap_offset(obj);
kfree(obj_priv->page_cpu_valid);
kfree(obj_priv->bit_17);
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Jesse Barnes <[email protected]>
commit d660467c3ff2a0b7413e1b7a51452b34ffb49e5f upstream.
A very high dotclock (e.g. 229500kHz as reported by Anton) can cause
the entries_required variable to overflow, potentially leading to a
FIFO watermark value that's too low to support the given mode. Split
the division across the calculation to avoid this.
Reported-by: Anton Khirnov <[email protected]>
Tested-by: Anton Khirnov <[email protected]>
Signed-off-by: Jesse Barnes <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/gpu/drm/i915/intel_display.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1858,7 +1858,14 @@ static unsigned long intel_calculate_wm(
{
long entries_required, wm_size;
- entries_required = (clock_in_khz * pixel_size * latency_ns) / 1000000;
+ /*
+ * Note: we need to make sure we don't overflow for various clock &
+ * latency values.
+ * clocks go from a few thousand to several hundred thousand.
+ * latency is usually a few thousand
+ */
+ entries_required = ((clock_in_khz / 1000) * pixel_size * latency_ns) /
+ 1000;
entries_required /= wm->cacheline_size;
DRM_DEBUG("FIFO entries required for mode: %d\n", entries_required);
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Chris Wilson <[email protected]>
commit 4960aaca14010b9ff92e5726dd178cbd6805d412 upstream.
If we failed to set the domain, the buffer was no longer being tracked
on any list.
Signed-off-by: Chris Wilson <[email protected]>
Signed-off-by: Jesse Barnes <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/gpu/drm/i915/i915_gem.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1155,14 +1155,13 @@ int i915_gem_fault(struct vm_area_struct
mutex_unlock(&dev->struct_mutex);
return VM_FAULT_SIGBUS;
}
+ list_add_tail(&obj_priv->list, &dev_priv->mm.inactive_list);
ret = i915_gem_object_set_to_gtt_domain(obj, write);
if (ret) {
mutex_unlock(&dev->struct_mutex);
return VM_FAULT_SIGBUS;
}
-
- list_add_tail(&obj_priv->list, &dev_priv->mm.inactive_list);
}
/* Need a new fence register? */
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Chris Wilson <[email protected]>
commit cd0b9fb400ba775737bdc3874c4cbee4047e66d8 upstream.
Eric noted a potential concern with the low bits not being strictly used
as part of the absolute offset (instead part of the command stream to the
GPU), but in practice that should not be an issue.
Signed-off-by: Chris Wilson <[email protected]>
Tested-by: Andy Whitcroft <[email protected]>
Cc: Eric Anholt <[email protected]>
Signed-off-by: Jesse Barnes <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/gpu/drm/i915/i915_gem.c | 10 ++++++++++
1 file changed, 10 insertions(+)
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -3006,6 +3006,16 @@ i915_gem_object_pin_and_relocate(struct
return -EINVAL;
}
+ if (reloc->delta >= target_obj->size) {
+ DRM_ERROR("Relocation beyond target object bounds: "
+ "obj %p target %d delta %d size %d.\n",
+ obj, reloc->target_handle,
+ (int) reloc->delta, (int) target_obj->size);
+ drm_gem_object_unreference(target_obj);
+ i915_gem_object_unpin(obj);
+ return -EINVAL;
+ }
+
if (reloc->write_domain & I915_GEM_DOMAIN_CPU ||
reloc->read_domains & I915_GEM_DOMAIN_CPU) {
DRM_ERROR("reloc with read/write CPU domains: "
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Zhenyu Wang <[email protected]>
commit b09aea7fb38f328c02e9f9b79617cabed02455e4 upstream.
New register for PCH LVDS on IGDNG should be used.
This is a copy-n-paste typo. This fixes possible dual
channel LVDS panel failure on IGDNG.
Signed-off-by: Zhenyu Wang <[email protected]>
Signed-off-by: Jesse Barnes <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/gpu/drm/i915/intel_display.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -818,7 +818,7 @@ intel_igdng_find_best_PLL(const intel_li
refclk, best_clock);
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
- if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
+ if ((I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) ==
LVDS_CLKB_POWER_UP)
clock.p2 = limit->p2.p2_fast;
else
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Zhenyu Wang <[email protected]>
commit 339e5a4c78041cd7b473ddf0a81eb06a131127bb upstream.
IGDNG LVDS SSC uses 120Mhz freq. This fixes one
1600x900 LVDS panel black issue on IGDNG with SSC enabled.
Signed-off-by: Zhenyu Wang <[email protected]>
Signed-off-by: Jesse Barnes <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/gpu/drm/i915/intel_bios.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -217,6 +217,9 @@ parse_general_features(struct drm_i915_p
if (IS_I85X(dev_priv->dev))
dev_priv->lvds_ssc_freq =
general->ssc_freq ? 66 : 48;
+ else if (IS_IGDNG(dev_priv->dev))
+ dev_priv->lvds_ssc_freq =
+ general->ssc_freq ? 100 : 120;
else
dev_priv->lvds_ssc_freq =
general->ssc_freq ? 100 : 96;
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Zhenyu Wang <[email protected]>
commit 730915d65f9e763de9dc26c5f1b8abaae775b243 upstream.
This is not required on newer stepping hardware to get
reliable force detect status. Removing this fixes screen
blank flicker in CRT detect on IGDNG.
Signed-off-by: Zhenyu Wang <[email protected]>
Signed-off-by: Jesse Barnes <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/gpu/drm/i915/intel_crt.c | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -151,13 +151,10 @@ static bool intel_igdng_crt_detect_hotpl
{
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 adpa, temp;
+ u32 adpa;
bool ret;
- temp = adpa = I915_READ(PCH_ADPA);
-
- adpa &= ~ADPA_DAC_ENABLE;
- I915_WRITE(PCH_ADPA, adpa);
+ adpa = I915_READ(PCH_ADPA);
adpa &= ~ADPA_CRT_HOTPLUG_MASK;
@@ -184,8 +181,6 @@ static bool intel_igdng_crt_detect_hotpl
else
ret = false;
- /* restore origin register */
- I915_WRITE(PCH_ADPA, temp);
return ret;
}
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Zhenyu Wang <[email protected]>
commit 8dd81a381e8886129c0923f1fe22ff5ca36ae8da upstream.
Arrandale has new window based method for panel fitting.
This one enables full screen aspect scaling on LVDS. It fixes
standard mode display failure on LVDS for Arrandale.
Signed-off-by: Zhenyu Wang <[email protected]>
Signed-off-by: Jesse Barnes <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/gpu/drm/i915/i915_reg.h | 2 ++
drivers/gpu/drm/i915/intel_display.c | 14 ++++++++++++++
drivers/gpu/drm/i915/intel_lvds.c | 11 ++++++++---
3 files changed, 24 insertions(+), 3 deletions(-)
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1867,6 +1867,8 @@
#define PF_ENABLE (1<<31)
#define PFA_WIN_SZ 0x68074
#define PFB_WIN_SZ 0x68874
+#define PFA_WIN_POS 0x68070
+#define PFB_WIN_POS 0x68870
/* legacy palette */
#define LGC_PALETTE_A 0x4a000
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1154,6 +1154,7 @@ static void igdng_crtc_dpms(struct drm_c
int transconf_reg = (pipe == 0) ? TRANSACONF : TRANSBCONF;
int pf_ctl_reg = (pipe == 0) ? PFA_CTL_1 : PFB_CTL_1;
int pf_win_size = (pipe == 0) ? PFA_WIN_SZ : PFB_WIN_SZ;
+ int pf_win_pos = (pipe == 0) ? PFA_WIN_POS : PFB_WIN_POS;
int cpu_htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
int cpu_hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
int cpu_hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
@@ -1205,6 +1206,19 @@ static void igdng_crtc_dpms(struct drm_c
}
}
+ /* Enable panel fitting for LVDS */
+ if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
+ temp = I915_READ(pf_ctl_reg);
+ I915_WRITE(pf_ctl_reg, temp | PF_ENABLE);
+
+ /* currently full aspect */
+ I915_WRITE(pf_win_pos, 0);
+
+ I915_WRITE(pf_win_size,
+ (dev_priv->panel_fixed_mode->hdisplay << 16) |
+ (dev_priv->panel_fixed_mode->vdisplay));
+ }
+
/* Enable CPU pipe */
temp = I915_READ(pipeconf_reg);
if ((temp & PIPEACONF_ENABLE) == 0) {
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -305,6 +305,10 @@ static bool intel_lvds_mode_fixup(struct
goto out;
}
+ /* full screen scale for now */
+ if (IS_IGDNG(dev))
+ goto out;
+
/* 965+ wants fuzzy fitting */
if (IS_I965G(dev))
pfit_control |= (intel_crtc->pipe << PFIT_PIPE_SHIFT) |
@@ -332,8 +336,10 @@ static bool intel_lvds_mode_fixup(struct
* to register description and PRM.
* Change the value here to see the borders for debugging
*/
- I915_WRITE(BCLRPAT_A, 0);
- I915_WRITE(BCLRPAT_B, 0);
+ if (!IS_IGDNG(dev)) {
+ I915_WRITE(BCLRPAT_A, 0);
+ I915_WRITE(BCLRPAT_B, 0);
+ }
switch (lvds_priv->fitting_mode) {
case DRM_MODE_SCALE_NO_SCALE:
@@ -582,7 +588,6 @@ static void intel_lvds_mode_set(struct d
* settings.
*/
- /* No panel fitting yet, fixme */
if (IS_IGDNG(dev))
return;
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Keith Packard <[email protected]>
commit 57cdaf90f5f607eb029356074fefb66c9b1c0659 upstream.
mac Mini's have a single DDC line on the DVI connector, shared between the
analog link and the digital link. So, if DDC isn't detected on GPIOE (the
usual SDVO DDC link), try GPIOA (the usual VGA DDC link) when there isn't a
VGA monitor connected.
Signed-off-by: Keith Packard <[email protected]>
Signed-off-by: Zhao Yakui <[email protected]>
Signed-off-by: Eric Anholt <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/gpu/drm/i915/intel_sdvo.c | 96 +++++++++++++++++++++++++++++---------
1 file changed, 74 insertions(+), 22 deletions(-)
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -114,6 +114,9 @@ struct intel_sdvo_priv {
/* DDC bus used by this SDVO output */
uint8_t ddc_bus;
+ /* Mac mini hack -- use the same DDC as the analog connector */
+ struct i2c_adapter *analog_ddc_bus;
+
int save_sdvo_mult;
u16 save_active_outputs;
struct intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
@@ -1478,6 +1481,36 @@ intel_sdvo_multifunc_encoder(struct inte
return (caps > 1);
}
+static struct drm_connector *
+intel_find_analog_connector(struct drm_device *dev)
+{
+ struct drm_connector *connector;
+ struct intel_output *intel_output;
+
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ intel_output = to_intel_output(connector);
+ if (intel_output->type == INTEL_OUTPUT_ANALOG)
+ return connector;
+ }
+ return NULL;
+}
+
+static int
+intel_analog_is_connected(struct drm_device *dev)
+{
+ struct drm_connector *analog_connector;
+ analog_connector = intel_find_analog_connector(dev);
+
+ if (!analog_connector)
+ return false;
+
+ if (analog_connector->funcs->detect(analog_connector) ==
+ connector_status_disconnected)
+ return false;
+
+ return true;
+}
+
enum drm_connector_status
intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response)
{
@@ -1488,6 +1521,15 @@ intel_sdvo_hdmi_sink_detect(struct drm_c
edid = drm_get_edid(&intel_output->base,
intel_output->ddc_bus);
+
+ /* when there is no edid and no monitor is connected with VGA
+ * port, try to use the CRT ddc to read the EDID for DVI-connector
+ */
+ if (edid == NULL &&
+ sdvo_priv->analog_ddc_bus &&
+ !intel_analog_is_connected(intel_output->base.dev))
+ edid = drm_get_edid(&intel_output->base,
+ sdvo_priv->analog_ddc_bus);
if (edid != NULL) {
/* Don't report the output as connected if it's a DVI-I
* connector with a non-digital EDID coming out.
@@ -1540,31 +1582,32 @@ static enum drm_connector_status intel_s
static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
{
struct intel_output *intel_output = to_intel_output(connector);
+ struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+ int num_modes;
/* set the bus switch and get the modes */
- intel_ddc_get_modes(intel_output);
+ num_modes = intel_ddc_get_modes(intel_output);
-#if 0
- struct drm_device *dev = encoder->dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
- /* Mac mini hack. On this device, I get DDC through the analog, which
- * load-detects as disconnected. I fail to DDC through the SDVO DDC,
- * but it does load-detect as connected. So, just steal the DDC bits
- * from analog when we fail at finding it the right way.
+ /*
+ * Mac mini hack. On this device, the DVI-I connector shares one DDC
+ * link between analog and digital outputs. So, if the regular SDVO
+ * DDC fails, check to see if the analog output is disconnected, in
+ * which case we'll look there for the digital DDC data.
*/
- crt = xf86_config->output[0];
- intel_output = crt->driver_private;
- if (intel_output->type == I830_OUTPUT_ANALOG &&
- crt->funcs->detect(crt) == XF86OutputStatusDisconnected) {
- I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOA, "CRTDDC_A");
- edid_mon = xf86OutputGetEDID(crt, intel_output->pDDCBus);
- xf86DestroyI2CBusRec(intel_output->pDDCBus, true, true);
- }
- if (edid_mon) {
- xf86OutputSetEDID(output, edid_mon);
- modes = xf86OutputGetEDIDModes(output);
+ if (num_modes == 0 &&
+ sdvo_priv->analog_ddc_bus &&
+ !intel_analog_is_connected(intel_output->base.dev)) {
+ struct i2c_adapter *digital_ddc_bus;
+
+ /* Switch to the analog ddc bus and try that
+ */
+ digital_ddc_bus = intel_output->ddc_bus;
+ intel_output->ddc_bus = sdvo_priv->analog_ddc_bus;
+
+ (void) intel_ddc_get_modes(intel_output);
+
+ intel_output->ddc_bus = digital_ddc_bus;
}
-#endif
}
/**
@@ -1748,6 +1791,8 @@ static void intel_sdvo_destroy(struct dr
intel_i2c_destroy(intel_output->i2c_bus);
if (intel_output->ddc_bus)
intel_i2c_destroy(intel_output->ddc_bus);
+ if (sdvo_priv->analog_ddc_bus)
+ intel_i2c_destroy(sdvo_priv->analog_ddc_bus);
if (sdvo_priv->sdvo_lvds_fixed_mode != NULL)
drm_mode_destroy(connector->dev,
@@ -2074,10 +2119,15 @@ bool intel_sdvo_init(struct drm_device *
}
/* setup the DDC bus. */
- if (output_device == SDVOB)
+ if (output_device == SDVOB) {
intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS");
- else
+ sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA,
+ "SDVOB/VGA DDC BUS");
+ } else {
intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS");
+ sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA,
+ "SDVOC/VGA DDC BUS");
+ }
if (intel_output->ddc_bus == NULL)
goto err_i2c;
@@ -2143,6 +2193,8 @@ bool intel_sdvo_init(struct drm_device *
return true;
err_i2c:
+ if (sdvo_priv->analog_ddc_bus != NULL)
+ intel_i2c_destroy(sdvo_priv->analog_ddc_bus);
if (intel_output->ddc_bus != NULL)
intel_i2c_destroy(intel_output->ddc_bus);
if (intel_output->i2c_bus != NULL)
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Zhenyu Wang <[email protected]>
commit 553bd149bb2de7848b2b84642876f27202421368 upstream.
It seems that on IGDNG the same swizzling setup always applys.
And front buffer tiling needs to set address swizzle in display
arb control too.
Fix plane tricle feed setting in v1 which should be disable bit,
and always setup address swizzle to let hardware care for buffer
tiling in all cases.
Signed-off-by: Zhenyu Wang <[email protected]>
Signed-off-by: Eric Anholt <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/gpu/drm/i915/i915_gem_tiling.c | 15 +++++++--------
drivers/gpu/drm/i915/i915_reg.h | 4 ++++
drivers/gpu/drm/i915/intel_display.c | 10 ++++++++++
3 files changed, 21 insertions(+), 8 deletions(-)
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -234,7 +234,13 @@ i915_gem_detect_bit_6_swizzle(struct drm
uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
bool need_disable;
- if (!IS_I9XX(dev)) {
+ if (IS_IGDNG(dev)) {
+ /* On IGDNG whatever DRAM config, GPU always do
+ * same swizzling setup.
+ */
+ swizzle_x = I915_BIT_6_SWIZZLE_9_10;
+ swizzle_y = I915_BIT_6_SWIZZLE_9;
+ } else if (!IS_I9XX(dev)) {
/* As far as we know, the 865 doesn't have these bit 6
* swizzling issues.
*/
@@ -317,13 +323,6 @@ i915_gem_detect_bit_6_swizzle(struct drm
}
}
- /* FIXME: check with memory config on IGDNG */
- if (IS_IGDNG(dev)) {
- DRM_ERROR("disable tiling on IGDNG...\n");
- swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
- swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
- }
-
dev_priv->mm.bit_6_swizzle_x = swizzle_x;
dev_priv->mm.bit_6_swizzle_y = swizzle_y;
}
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1733,6 +1733,7 @@
#define DISPPLANE_NO_LINE_DOUBLE 0
#define DISPPLANE_STEREO_POLARITY_FIRST 0
#define DISPPLANE_STEREO_POLARITY_SECOND (1<<18)
+#define DISPPLANE_TRICKLE_FEED_DISABLE (1<<14) /* IGDNG */
#define DISPPLANE_TILED (1<<10)
#define DSPAADDR 0x70184
#define DSPASTRIDE 0x70188
@@ -1915,6 +1916,9 @@
#define GTIIR 0x44018
#define GTIER 0x4401c
+#define DISP_ARB_CTL 0x45000
+#define DISP_TILE_SURFACE_SWIZZLING (1<<13)
+
/* PCH */
/* south display engine interrupt */
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1008,6 +1008,10 @@ intel_pipe_set_base(struct drm_crtc *crt
dspcntr &= ~DISPPLANE_TILED;
}
+ if (IS_IGDNG(dev))
+ /* must disable */
+ dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
+
I915_WRITE(dspcntr_reg, dspcntr);
Start = obj_priv->gtt_offset;
@@ -2637,6 +2641,12 @@ static int intel_crtc_mode_set(struct dr
intel_wait_for_vblank(dev);
+ if (IS_IGDNG(dev)) {
+ /* enable address swizzle for tiling buffer */
+ temp = I915_READ(DISP_ARB_CTL);
+ I915_WRITE(DISP_ARB_CTL, temp | DISP_TILE_SURFACE_SWIZZLING);
+ }
+
I915_WRITE(dspcntr_reg, dspcntr);
/* Flush the plane changes */
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Eric Anholt <[email protected]>
commit e517a5e97080bbe52857bd0d7df9b66602d53c4d upstream.
Ever since we enabled GEM, the pre-9xx chipsets (particularly 865) have had
serious stability issues. Back in May a wbinvd was added to the DRM to
work around much of the problem. Some failure remained -- easily visible
by dragging a window around on an X -retro desktop, or by looking at bugzilla.
The chipset flush was on the right track -- hitting the right amount of
memory, and it appears to be the only way to flush on these chipsets, but the
flush page was mapped uncached. As a result, the writes trying to clear the
writeback cache ended up bypassing the cache, and not flushing anything! The
wbinvd would flush out other writeback data and often cause the data we wanted
to get flushed, but not always. By removing the setting of the page to UC
and instead just clflushing the data we write to try to flush it, we get the
desired behavior with no wbinvd.
This exports clflush_cache_range(), which was laying around and happened to
basically match the code I was otherwise going to copy from the DRM.
Signed-off-by: Eric Anholt <[email protected]>
Signed-off-by: Brice Goglin <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/x86/mm/pageattr.c | 1 +
drivers/char/agp/intel-agp.c | 30 +++++++++++++++++++++++-------
drivers/gpu/drm/i915/i915_gem.c | 10 ----------
3 files changed, 24 insertions(+), 17 deletions(-)
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -143,6 +143,7 @@ void clflush_cache_range(void *vaddr, un
mb();
}
+EXPORT_SYMBOL_GPL(clflush_cache_range);
static void __cpa_flush_all(void *arg)
{
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -679,23 +679,39 @@ static void intel_i830_setup_flush(void)
if (!intel_private.i8xx_page)
return;
- /* make page uncached */
- map_page_into_agp(intel_private.i8xx_page);
-
intel_private.i8xx_flush_page = kmap(intel_private.i8xx_page);
if (!intel_private.i8xx_flush_page)
intel_i830_fini_flush();
}
+static void
+do_wbinvd(void *null)
+{
+ wbinvd();
+}
+
+/* The chipset_flush interface needs to get data that has already been
+ * flushed out of the CPU all the way out to main memory, because the GPU
+ * doesn't snoop those buffers.
+ *
+ * The 8xx series doesn't have the same lovely interface for flushing the
+ * chipset write buffers that the later chips do. According to the 865
+ * specs, it's 64 octwords, or 1KB. So, to get those previous things in
+ * that buffer out, we just fill 1KB and clflush it out, on the assumption
+ * that it'll push whatever was in there out. It appears to work.
+ */
static void intel_i830_chipset_flush(struct agp_bridge_data *bridge)
{
unsigned int *pg = intel_private.i8xx_flush_page;
- int i;
- for (i = 0; i < 256; i += 2)
- *(pg + i) = i;
+ memset(pg, 0, 1024);
- wmb();
+ if (cpu_has_clflush) {
+ clflush_cache_range(pg, 1024);
+ } else {
+ if (on_each_cpu(do_wbinvd, NULL, 1) != 0)
+ printk(KERN_ERR "Timed out waiting for cache flush.\n");
+ }
}
/* The intel i830 automatically initializes the agp aperture during POST.
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2505,16 +2505,6 @@ i915_gem_clflush_object(struct drm_gem_o
if (obj_priv->pages == NULL)
return;
- /* XXX: The 865 in particular appears to be weird in how it handles
- * cache flushing. We haven't figured it out, but the
- * clflush+agp_chipset_flush doesn't appear to successfully get the
- * data visible to the PGU, while wbinvd + agp_chipset_flush does.
- */
- if (IS_I865G(obj->dev)) {
- wbinvd();
- return;
- }
-
drm_clflush_pages(obj_priv->pages, obj->size / PAGE_SIZE);
}
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: J. Bruce Fields <[email protected]>
commit 886e3b7fe6054230c89ae078a09565ed183ecc73 upstream.
On setting up the callback to the client, we attempt to use the same
authentication flavor the client did. We find an rpc cred to use by
calling rpcauth_lookup_credcache(), which assumes that the given
authentication flavor has a credentials cache. However, this is not
required to be true--in particular, auth_null does not use one.
Instead, we should call the auth's lookup_cred() method.
Without this, a client attempting to mount using nfsv4 and auth_null
triggers a null dereference.
Signed-off-by: J. Bruce Fields <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/nfsd/nfs4callback.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -444,6 +444,7 @@ static struct rpc_cred *lookup_cb_cred(s
struct auth_cred acred = {
.machine_cred = 1
};
+ struct rpc_auth *auth = cb->cb_client->cl_auth;
/*
* Note in the gss case this doesn't actually have to wait for a
@@ -451,8 +452,7 @@ static struct rpc_cred *lookup_cb_cred(s
* non-uptodate cred which the rpc state machine will fill in with
* a refresh_upcall later.
*/
- return rpcauth_lookup_credcache(cb->cb_client->cl_auth, &acred,
- RPCAUTH_LOOKUP_NEW);
+ return auth->au_ops->lookup_cred(auth, &acred, RPCAUTH_LOOKUP_NEW);
}
void do_probe_callback(struct nfs4_client *clp)
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Oliver Hartkopp <[email protected]>
commit 481a8199142c050b72bff8a1956a49fd0a75bbe0 upstream.
When using nanosleep() in an userspace application we get a ratelimit warning
NOHZ: local_softirq_pending 08
for 10 times.
The echo of CAN frames is done from process context and softirq context only.
Therefore the usage of netif_rx() was wrong (for years).
This patch replaces netif_rx() with netif_rx_ni() which has to be used from
process/softirq context. It also adds a missing comment that can_send() must
no be used from hardirq context.
Signed-off-by: Oliver Hartkopp <[email protected]>
Signed-off-by: Urs Thuermann <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/net/can/vcan.c | 2 +-
net/can/af_can.c | 4 +++-
2 files changed, 4 insertions(+), 2 deletions(-)
--- a/drivers/net/can/vcan.c
+++ b/drivers/net/can/vcan.c
@@ -80,7 +80,7 @@ static void vcan_rx(struct sk_buff *skb,
skb->dev = dev;
skb->ip_summed = CHECKSUM_UNNECESSARY;
- netif_rx(skb);
+ netif_rx_ni(skb);
}
static int vcan_tx(struct sk_buff *skb, struct net_device *dev)
--- a/net/can/af_can.c
+++ b/net/can/af_can.c
@@ -199,6 +199,8 @@ static int can_create(struct net *net, s
* @skb: pointer to socket buffer with CAN frame in data section
* @loop: loopback for listeners on local CAN sockets (recommended default!)
*
+ * Due to the loopback this routine must not be called from hardirq context.
+ *
* Return:
* 0 on success
* -ENETDOWN when the selected interface is down
@@ -278,7 +280,7 @@ int can_send(struct sk_buff *skb, int lo
}
if (newskb)
- netif_rx(newskb);
+ netif_rx_ni(newskb);
/* update statistics */
can_stats.tx_frames++;
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Tejun Heo <[email protected]>
commit 31b239ad1ba7225435e13f5afc47e48eb674c0cc upstream.
Commit a5bfc4714b3f01365aef89a92673f2ceb1ccf246 dropped explicit
pci_intx() manipulation from ahci because it seemed unnecessary and
ahci doesn't seem to be the right place to be tweaking it if it were.
This was largely okay but there are exceptions. There was one on an
embedded platform which was fixed via firmware and now bko#14124
reports it on a HP DL320.
http://bugzilla.kernel.org/show_bug.cgi?id=14124
I still think this isn't something libata drivers should be caring
about (the only ones which are calling pci_intx() explicitly are
libata ones and one other driver) but for now reverting the change
seems to be the right thing to do.
Signed-off-by: Tejun Heo <[email protected]>
Reported-by: Thomas Jarosch <[email protected]>
Signed-off-by: Jeff Garzik <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/ata/ahci.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -2861,8 +2861,8 @@ static int ahci_init_one(struct pci_dev
if (ahci_asus_m2a_vm_32bit_only(pdev))
hpriv->flags |= AHCI_HFLAG_32BIT_ONLY;
- if (!(hpriv->flags & AHCI_HFLAG_NO_MSI))
- pci_enable_msi(pdev);
+ if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev))
+ pci_intx(pdev, 1);
/* save initial config */
ahci_save_initial_config(pdev, hpriv);
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Pavel Machek <[email protected]>
commit 99f329a2ba3c2d07cc90ca9309babf27ddf98bff upstream.
sharpsl_pm.c code tries to read battery state very early during
resume, but those battery meters are connected on SPI and that's only
resumed way later.
Replace the check with simple checking of battery fatal signal, that
actually works at this stage.
Signed-off-by: Pavel Machek <[email protected]>
Tested-by: Stanislav Brabec <[email protected]>
Signed-off-by: Eric Miao <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/arm/mach-pxa/sharpsl_pm.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/arch/arm/mach-pxa/sharpsl_pm.c
+++ b/arch/arm/mach-pxa/sharpsl_pm.c
@@ -678,8 +678,8 @@ static int corgi_enter_suspend(unsigned
dev_dbg(sharpsl_pm.dev, "User triggered wakeup in offline charger.\n");
}
- if ((!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_LOCK)) || (sharpsl_fatal_check() < 0) )
- {
+ if ((!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_LOCK)) ||
+ (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_FATAL))) {
dev_err(sharpsl_pm.dev, "Fatal condition. Suspend.\n");
corgi_goto_sleep(alarm_time, alarm_enable, state);
return 1;
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Arjan van de Ven <[email protected]>
fixed upstream in commit b7058842c940ad2c08dd829b21e5c92ebe3b8758 in a different way
The ax25 code tried to use
if (optlen < sizeof(int))
return -EINVAL;
as a security check against optlen being negative (or zero) in the
set socket option.
Unfortunately, "sizeof(int)" is an unsigned property, with the
result that the whole comparison is done in unsigned, letting
negative values slip through.
This patch changes this to
if (optlen < (int)sizeof(int))
return -EINVAL;
so that the comparison is done as signed, and negative values
get properly caught.
Signed-off-by: Arjan van de Ven <[email protected]>
Cc: David S. Miller <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ax25/af_ax25.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -538,7 +538,7 @@ static int ax25_setsockopt(struct socket
if (level != SOL_AX25)
return -ENOPROTOOPT;
- if (optlen < sizeof(int))
+ if (optlen < (int)sizeof(int))
return -EINVAL;
if (get_user(opt, (int __user *)optval))
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Arjan van de Ven <[email protected]>
fixed upstream in commit b7058842c940ad2c08dd829b21e5c92ebe3b8758 in a different way
The length of the to-copy data structure is currently stored in
a signed integer. However many comparisons are done with sizeof(..)
which is unsigned. It's more suitable for this variable to be unsigned
to make these comparisons more naturally right.
Signed-off-by: Arjan van de Ven <[email protected]>
Cc: David S. Miller <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/packet/af_packet.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1836,7 +1836,7 @@ packet_setsockopt(struct socket *sock, i
static int packet_getsockopt(struct socket *sock, int level, int optname,
char __user *optval, int __user *optlen)
{
- int len;
+ unsigned int len;
int val;
struct sock *sk = sock->sk;
struct packet_sock *po = pkt_sk(sk);
@@ -1849,7 +1849,7 @@ static int packet_getsockopt(struct sock
if (get_user(len, optlen))
return -EFAULT;
- if (len < 0)
+ if ((int)len < 0)
return -EINVAL;
switch (optname) {
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Linus Torvalds <[email protected]>
commit 202c4675c55ddf6b443c7e057d2dff6b42ef71aa upstream.
Commit ac89a9174 ("pty: don't limit the writes to 'pty_space()' inside
'pty_write()'") removed the pty_space() checking, in order to let the
regular tty buffer code limit the buffering itself.
That was all good, but as a subtle side effect it meant that we'd be
doing a tty_wakeup() even in the case where the buffers were all filled
up, and didn't actually make any progress on the write.
Which sounds innocuous, but it interacts very badly with the ppp_async
code, which has an infinite loop in ppp_async_push() that tries to push
out data to the tty. When we call tty_wakeup(), that loop ends up
thinking that progress was made (see the subtle interactions between
XMIT_WAKEUP and 'tty_stuffed' for details). End result: one unhappy ppp
user.
Fixed by noticing when tty_insert_flip_string() didn't actually do
anything, and then not doing any more processing (including, very much
not calling tty_wakeup()).
Bisected-and-tested-by: Peter Volkov <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/char/pty.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -120,8 +120,10 @@ static int pty_write(struct tty_struct *
/* Stuff the data into the input queue of the other end */
c = tty_insert_flip_string(to, buf, c);
/* And shovel */
- tty_flip_buffer_push(to);
- tty_wakeup(tty);
+ if (c) {
+ tty_flip_buffer_push(to);
+ tty_wakeup(tty);
+ }
}
return c;
}
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Mark McLoughlin <[email protected]>
(cherry picked from commit cb007648de83cf226d69ec76e1c01848b4e8e49f)
If we run out of cpuid entries for extended request types
we should return -E2BIG, just like we do for the standard
request types.
Signed-off-by: Mark McLoughlin <[email protected]>
Signed-off-by: Avi Kivity <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/x86/kvm/x86.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1448,6 +1448,10 @@ static int kvm_dev_ioctl_get_supported_c
for (func = 0x80000001; func <= limit && nent < cpuid->nent; ++func)
do_cpuid_ent(&cpuid_entries[nent], func, 0,
&nent, cpuid->nent);
+ r = -E2BIG;
+ if (nent >= cpuid->nent)
+ goto out_free;
+
r = -EFAULT;
if (copy_to_user(entries, cpuid_entries,
nent * sizeof(struct kvm_cpuid_entry2)))
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Marcelo Tosatti <[email protected]>
(cherry picked from commit 6a1ac77110ee3e8d8dfdef8442f3b30b3d83e6a2)
n_requested_mmu_pages/n_free_mmu_pages are used by
kvm_mmu_change_mmu_pages to calculate the number of pages to zap.
alloc_mmu_pages, called from the vcpu initialization path, modifies this
variables without proper locking, which can result in a negative value
in kvm_mmu_change_mmu_pages (say, with cpu hotplug).
Signed-off-by: Marcelo Tosatti <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/x86/kvm/mmu.c | 2 ++
1 file changed, 2 insertions(+)
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -2713,12 +2713,14 @@ static int alloc_mmu_pages(struct kvm_vc
ASSERT(vcpu);
+ spin_lock(&vcpu->kvm->mmu_lock);
if (vcpu->kvm->arch.n_requested_mmu_pages)
vcpu->kvm->arch.n_free_mmu_pages =
vcpu->kvm->arch.n_requested_mmu_pages;
else
vcpu->kvm->arch.n_free_mmu_pages =
vcpu->kvm->arch.n_alloc_mmu_pages;
+ spin_unlock(&vcpu->kvm->mmu_lock);
/*
* When emulating 32-bit mode, cr3 is only 32 bits even on x86_64.
* Therefore we need to allocate shadow page tables in the first
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Marcelo Tosatti <[email protected]>
(cherry picked from commit b90c062c65cc8839edfac39778a37a55ca9bda36)
Remove the bogus n_free_mmu_pages assignment from alloc_mmu_pages.
It breaks accounting of mmu pages, since n_free_mmu_pages is modified
but the real number of pages remains the same.
Signed-off-by: Marcelo Tosatti <[email protected]>
Signed-off-by: Avi Kivity <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/x86/kvm/mmu.c | 8 --------
1 file changed, 8 deletions(-)
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -2713,14 +2713,6 @@ static int alloc_mmu_pages(struct kvm_vc
ASSERT(vcpu);
- spin_lock(&vcpu->kvm->mmu_lock);
- if (vcpu->kvm->arch.n_requested_mmu_pages)
- vcpu->kvm->arch.n_free_mmu_pages =
- vcpu->kvm->arch.n_requested_mmu_pages;
- else
- vcpu->kvm->arch.n_free_mmu_pages =
- vcpu->kvm->arch.n_alloc_mmu_pages;
- spin_unlock(&vcpu->kvm->mmu_lock);
/*
* When emulating 32-bit mode, cr3 is only 32 bits even on x86_64.
* Therefore we need to allocate shadow page tables in the first
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Avi Kivity <[email protected]>
(cherry picked from commit 88c808fd42b53a7e01a2ac3253ef31fef74cb5af)
update_cr8_intercept() can be triggered from userspace while there
is no apic present.
Signed-off-by: Avi Kivity <[email protected]>
Cc: Marcelo Tosatti <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/x86/kvm/x86.c | 3 +++
1 file changed, 3 insertions(+)
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3202,6 +3202,9 @@ static void update_cr8_intercept(struct
if (!kvm_x86_ops->update_cr8_intercept)
return;
+ if (!vcpu->arch.apic)
+ return;
+
if (!vcpu->arch.apic->vapic_addr)
max_irr = kvm_lapic_find_highest_irr(vcpu);
else
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Marcelo Tosatti <[email protected]>
(cherry picked from commit dc7e795e3dd2a763e5ceaa1615f307e808cf3932)
This reverts commit 6c20e1442bb1c62914bb85b7f4a38973d2a423ba.
To my understanding, it became obsolete with the advent of the more
robust check in mmu_alloc_roots (89da4ff17f). Moreover, it prevents
the conceptually safe pattern
1. set sregs
2. register mem-slots
3. run vcpu
by setting a sticky triple fault during step 1.
Signed-off-by: Jan Kiszka <[email protected]>
Signed-off-by: Avi Kivity <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/x86/kvm/x86.c | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4125,13 +4125,7 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct
vcpu->arch.cr2 = sregs->cr2;
mmu_reset_needed |= vcpu->arch.cr3 != sregs->cr3;
-
- down_read(&vcpu->kvm->slots_lock);
- if (gfn_to_memslot(vcpu->kvm, sregs->cr3 >> PAGE_SHIFT))
- vcpu->arch.cr3 = sregs->cr3;
- else
- set_bit(KVM_REQ_TRIPLE_FAULT, &vcpu->requests);
- up_read(&vcpu->kvm->slots_lock);
+ vcpu->arch.cr3 = sregs->cr3;
kvm_set_cr8(vcpu, sregs->cr8);
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Kurt Roeckx <[email protected]>
commit f0adb134d8dc9993a9998dc50845ec4f6ff4fadc upstream.
Fixes bugzilla #13780
From: Kurt Roeckx <[email protected]>
Signed-off-by: Dave Jones <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/x86/kernel/cpu/cpufreq/powernow-k8.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
@@ -605,9 +605,10 @@ static int check_pst_table(struct powern
return 0;
}
-static void invalidate_entry(struct powernow_k8_data *data, unsigned int entry)
+static void invalidate_entry(struct cpufreq_frequency_table *powernow_table,
+ unsigned int entry)
{
- data->powernow_table[entry].frequency = CPUFREQ_ENTRY_INVALID;
+ powernow_table[entry].frequency = CPUFREQ_ENTRY_INVALID;
}
static void print_basics(struct powernow_k8_data *data)
@@ -914,13 +915,13 @@ static int fill_powernow_table_pstate(st
"bad value %d.\n", i, index);
printk(KERN_ERR PFX "Please report to BIOS "
"manufacturer\n");
- invalidate_entry(data, i);
+ invalidate_entry(powernow_table, i);
continue;
}
rdmsr(MSR_PSTATE_DEF_BASE + index, lo, hi);
if (!(hi & HW_PSTATE_VALID_MASK)) {
dprintk("invalid pstate %d, ignoring\n", index);
- invalidate_entry(data, i);
+ invalidate_entry(powernow_table, i);
continue;
}
@@ -970,7 +971,7 @@ static int fill_powernow_table_fidvid(st
/* verify frequency is OK */
if ((freq > (MAX_FREQ * 1000)) || (freq < (MIN_FREQ * 1000))) {
dprintk("invalid freq %u kHz, ignoring\n", freq);
- invalidate_entry(data, i);
+ invalidate_entry(powernow_table, i);
continue;
}
@@ -978,7 +979,7 @@ static int fill_powernow_table_fidvid(st
* BIOSs are using "off" to indicate invalid */
if (vid == VID_OFF) {
dprintk("invalid vid %u, ignoring\n", vid);
- invalidate_entry(data, i);
+ invalidate_entry(powernow_table, i);
continue;
}
@@ -1009,7 +1010,7 @@ static int fill_powernow_table_fidvid(st
(unsigned int)
(data->acpi_data.states[i].core_frequency
* 1000));
- invalidate_entry(data, i);
+ invalidate_entry(powernow_table, i);
continue;
}
}
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Pierre Habouzit <[email protected]>
commit 119e7a22bb70d84849384e5113792cd45afa4f85 upstream.
This improves patch fa6963b24 so that perf.data stuff that has
been dumped as root can be read (annotate/report) by a user
without the use of the --force.
Rationale is that root has plenty of ways to screw us (usually)
that do not require twisted schemes involving specially
crafting a perf.data.
Signed-off-by: Pierre Habouzit <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
tools/perf/builtin-annotate.c | 4 ++--
tools/perf/builtin-report.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -1335,8 +1335,8 @@ static int __cmd_annotate(void)
exit(-1);
}
- if (!force && (stat.st_uid != geteuid())) {
- fprintf(stderr, "file: %s not owned by current user\n", input_name);
+ if (!force && stat.st_uid && (stat.st_uid != geteuid())) {
+ fprintf(stderr, "file: %s not owned by current user or root\n", input_name);
exit(-1);
}
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -1857,8 +1857,8 @@ static int __cmd_report(void)
exit(-1);
}
- if (!force && (stat.st_uid != geteuid())) {
- fprintf(stderr, "file: %s not owned by current user\n", input_name);
+ if (!force && stat.st_uid && (stat.st_uid != geteuid())) {
+ fprintf(stderr, "file: %s not owned by current user or root\n", input_name);
exit(-1);
}
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Patrick McHardy <[email protected]>
netfilter: nf_nat: fix inverted logic for persistent NAT mappings
Upstream commit cce5a5c3:
Kernel 2.6.30 introduced a patch [1] for the persistent option in the
netfilter SNAT target. This is exactly what we need here so I had a quick look
at the code and noticed that the patch is wrong. The logic is simply inverted.
The patch below fixes this.
Also note that because of this the default behavior of the SNAT target has
changed since kernel 2.6.30 as it now ignores the destination IP in choosing
the source IP for nating (which should only be the case if the persistent
option is set).
[1] http://git.eu.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=98d500d66cb7940747b424b245fc6a51ecfbf005
Signed-off-by: Maximilian Engelhardt <[email protected]>
Signed-off-by: Patrick McHardy <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ipv4/netfilter/nf_nat_core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/net/ipv4/netfilter/nf_nat_core.c
+++ b/net/ipv4/netfilter/nf_nat_core.c
@@ -212,7 +212,7 @@ find_best_ips_proto(struct nf_conntrack_
maxip = ntohl(range->max_ip);
j = jhash_2words((__force u32)tuple->src.u3.ip,
range->flags & IP_NAT_RANGE_PERSISTENT ?
- (__force u32)tuple->dst.u3.ip : 0, 0);
+ 0 : (__force u32)tuple->dst.u3.ip, 0);
j = ((u64)j * (maxip - minip + 1)) >> 32;
*var_ipp = htonl(minip + j);
}
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Patrick McHardy <[email protected]>
netfilter: nf_conntrack: netns fix re reliable conntrack event delivery
Upstream commit ee254fa4:
Conntracks in netns other than init_net dying list were never killed.
Signed-off-by: Alexey Dobriyan <[email protected]>
Acked-by: Pablo Neira Ayuso <[email protected]>
Signed-off-by: Patrick McHardy <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/netfilter/nf_conntrack_core.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1089,14 +1089,14 @@ void nf_conntrack_flush_report(struct ne
}
EXPORT_SYMBOL_GPL(nf_conntrack_flush_report);
-static void nf_ct_release_dying_list(void)
+static void nf_ct_release_dying_list(struct net *net)
{
struct nf_conntrack_tuple_hash *h;
struct nf_conn *ct;
struct hlist_nulls_node *n;
spin_lock_bh(&nf_conntrack_lock);
- hlist_nulls_for_each_entry(h, n, &init_net.ct.dying, hnnode) {
+ hlist_nulls_for_each_entry(h, n, &net->ct.dying, hnnode) {
ct = nf_ct_tuplehash_to_ctrack(h);
/* never fails to remove them, no listeners at this point */
nf_ct_kill(ct);
@@ -1115,7 +1115,7 @@ static void nf_conntrack_cleanup_net(str
{
i_see_dead_people:
nf_ct_iterate_cleanup(net, kill_all, NULL);
- nf_ct_release_dying_list();
+ nf_ct_release_dying_list(net);
if (atomic_read(&net->ct.count) != 0) {
schedule();
goto i_see_dead_people;
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Patrick McHardy <[email protected]>
netfilter: bridge: refcount fix
Upstream commit f3abc9b9:
commit f216f082b2b37c4943f1e7c393e2786648d48f6f
([NETFILTER]: bridge netfilter: deal with martians correctly)
added a refcount leak on in_dev.
Instead of using in_dev_get(), we can use __in_dev_get_rcu(),
as netfilter hooks are running under rcu_read_lock(), as pointed
by Patrick.
Signed-off-by: Eric Dumazet <[email protected]>
Signed-off-by: Patrick McHardy <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/bridge/br_netfilter.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -359,7 +359,7 @@ static int br_nf_pre_routing_finish(stru
},
.proto = 0,
};
- struct in_device *in_dev = in_dev_get(dev);
+ struct in_device *in_dev = __in_dev_get_rcu(dev);
/* If err equals -EHOSTUNREACH the error is due to a
* martian destination or due to the fact that
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Patrick McHardy <[email protected]>
netfilter: ebt_ulog: fix checkentry return value
Upstream commit 8a56df0a:
Commit 19eda87 (netfilter: change return types of check functions for
Ebtables extensions) broke the ebtables ulog module by missing a return
value conversion.
Signed-off-by: Patrick McHardy <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/bridge/netfilter/ebt_ulog.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -266,7 +266,7 @@ static bool ebt_ulog_tg_check(const stru
if (uloginfo->qthreshold > EBT_ULOG_MAX_QLEN)
uloginfo->qthreshold = EBT_ULOG_MAX_QLEN;
- return 0;
+ return true;
}
static struct xt_target ebt_ulog_tg_reg __read_mostly = {
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Nick Kossifidis <[email protected]>
commit edd7fc7003f31da48d06e215a93ea966a22c2a03 upstream.
* Don't put chip to full sleep because there are problems during
wakeup. Instead hold MAC/Baseband on warm reset state via a new
function ath5k_hw_on_hold.
* Minor cleanups
Signed-off-by: Nick Kossifidis <[email protected]>
Tested-by: Ben Greear <[email protected]>
Tested-by: Johannes Stezenbach <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/net/wireless/ath/ath5k/ath5k.h | 1
drivers/net/wireless/ath/ath5k/attach.c | 2
drivers/net/wireless/ath/ath5k/base.c | 44 ++++-----
drivers/net/wireless/ath/ath5k/reset.c | 155 +++++++++++++++++++++++---------
4 files changed, 140 insertions(+), 62 deletions(-)
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -1164,6 +1164,7 @@ extern void ath5k_unregister_leds(struct
/* Reset Functions */
extern int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial);
+extern int ath5k_hw_on_hold(struct ath5k_hw *ah);
extern int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool change_channel);
/* Power management functions */
extern int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration);
--- a/drivers/net/wireless/ath/ath5k/attach.c
+++ b/drivers/net/wireless/ath/ath5k/attach.c
@@ -145,7 +145,7 @@ struct ath5k_hw *ath5k_hw_attach(struct
goto err_free;
/* Bring device out of sleep and reset it's units */
- ret = ath5k_hw_nic_wakeup(ah, CHANNEL_B, true);
+ ret = ath5k_hw_nic_wakeup(ah, 0, true);
if (ret)
goto err_free;
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -2445,27 +2445,29 @@ ath5k_stop_hw(struct ath5k_softc *sc)
ret = ath5k_stop_locked(sc);
if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) {
/*
- * Set the chip in full sleep mode. Note that we are
- * careful to do this only when bringing the interface
- * completely to a stop. When the chip is in this state
- * it must be carefully woken up or references to
- * registers in the PCI clock domain may freeze the bus
- * (and system). This varies by chip and is mostly an
- * issue with newer parts that go to sleep more quickly.
- */
- if (sc->ah->ah_mac_srev >= 0x78) {
- /*
- * XXX
- * don't put newer MAC revisions > 7.8 to sleep because
- * of the above mentioned problems
- */
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mac version > 7.8, "
- "not putting device to sleep\n");
- } else {
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
- "putting device to full sleep\n");
- ath5k_hw_set_power(sc->ah, AR5K_PM_FULL_SLEEP, true, 0);
- }
+ * Don't set the card in full sleep mode!
+ *
+ * a) When the device is in this state it must be carefully
+ * woken up or references to registers in the PCI clock
+ * domain may freeze the bus (and system). This varies
+ * by chip and is mostly an issue with newer parts
+ * (madwifi sources mentioned srev >= 0x78) that go to
+ * sleep more quickly.
+ *
+ * b) On older chips full sleep results a weird behaviour
+ * during wakeup. I tested various cards with srev < 0x78
+ * and they don't wake up after module reload, a second
+ * module reload is needed to bring the card up again.
+ *
+ * Until we figure out what's going on don't enable
+ * full chip reset on any chip (this is what Legacy HAL
+ * and Sam's HAL do anyway). Instead Perform a full reset
+ * on the device (same as initial state after attach) and
+ * leave it idle (keep MAC/BB on warm reset) */
+ ret = ath5k_hw_on_hold(sc->ah);
+
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
+ "putting device to sleep\n");
}
ath5k_txbuf_free(sc, sc->bbuf);
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -258,29 +258,35 @@ int ath5k_hw_set_power(struct ath5k_hw *
if (!set_chip)
goto commit;
- /* Preserve sleep duration */
data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL);
+
+ /* If card is down we 'll get 0xffff... so we
+ * need to clean this up before we write the register
+ */
if (data & 0xffc00000)
data = 0;
else
- data = data & 0xfffcffff;
+ /* Preserve sleep duration etc */
+ data = data & ~AR5K_SLEEP_CTL_SLE;
- ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL);
+ ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE,
+ AR5K_SLEEP_CTL);
udelay(15);
- for (i = 50; i > 0; i--) {
+ for (i = 200; i > 0; i--) {
/* Check if the chip did wake up */
if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) &
AR5K_PCICFG_SPWR_DN) == 0)
break;
/* Wait a bit and retry */
- udelay(200);
- ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL);
+ udelay(50);
+ ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE,
+ AR5K_SLEEP_CTL);
}
/* Fail if the chip didn't wake up */
- if (i <= 0)
+ if (i == 0)
return -EIO;
break;
@@ -297,6 +303,64 @@ commit:
}
/*
+ * Put device on hold
+ *
+ * Put MAC and Baseband on warm reset and
+ * keep that state (don't clean sleep control
+ * register). After this MAC and Baseband are
+ * disabled and a full reset is needed to come
+ * back. This way we save as much power as possible
+ * without puting the card on full sleep.
+ */
+int ath5k_hw_on_hold(struct ath5k_hw *ah)
+{
+ struct pci_dev *pdev = ah->ah_sc->pdev;
+ u32 bus_flags;
+ int ret;
+
+ /* Make sure device is awake */
+ ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n");
+ return ret;
+ }
+
+ /*
+ * Put chipset on warm reset...
+ *
+ * Note: puting PCI core on warm reset on PCI-E cards
+ * results card to hang and always return 0xffff... so
+ * we ingore that flag for PCI-E cards. On PCI cards
+ * this flag gets cleared after 64 PCI clocks.
+ */
+ bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
+
+ if (ah->ah_version == AR5K_AR5210) {
+ ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
+ AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
+ AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
+ mdelay(2);
+ } else {
+ ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
+ AR5K_RESET_CTL_BASEBAND | bus_flags);
+ }
+
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc, "failed to put device on warm reset\n");
+ return -EIO;
+ }
+
+ /* ...wakeup again!*/
+ ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc, "failed to put device on hold\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+/*
* Bring up MAC + PHY Chips and program PLL
* TODO: Half/Quarter rate support
*/
@@ -319,6 +383,50 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw
return ret;
}
+ /*
+ * Put chipset on warm reset...
+ *
+ * Note: puting PCI core on warm reset on PCI-E cards
+ * results card to hang and always return 0xffff... so
+ * we ingore that flag for PCI-E cards. On PCI cards
+ * this flag gets cleared after 64 PCI clocks.
+ */
+ bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
+
+ if (ah->ah_version == AR5K_AR5210) {
+ ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
+ AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
+ AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
+ mdelay(2);
+ } else {
+ ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
+ AR5K_RESET_CTL_BASEBAND | bus_flags);
+ }
+
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n");
+ return -EIO;
+ }
+
+ /* ...wakeup again!...*/
+ ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n");
+ return ret;
+ }
+
+ /* ...clear reset control register and pull device out of
+ * warm reset */
+ if (ath5k_hw_nic_reset(ah, 0)) {
+ ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n");
+ return -EIO;
+ }
+
+ /* On initialization skip PLL programming since we don't have
+ * a channel / mode set yet */
+ if (initial)
+ return 0;
+
if (ah->ah_version != AR5K_AR5210) {
/*
* Get channel mode flags
@@ -384,39 +492,6 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw
AR5K_PHY_TURBO);
}
- /* reseting PCI on PCI-E cards results card to hang
- * and always return 0xffff... so we ingore that flag
- * for PCI-E cards */
- bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
-
- /* Reset chipset */
- if (ah->ah_version == AR5K_AR5210) {
- ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
- AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
- AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
- mdelay(2);
- } else {
- ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
- AR5K_RESET_CTL_BASEBAND | bus_flags);
- }
- if (ret) {
- ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n");
- return -EIO;
- }
-
- /* ...wakeup again!*/
- ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
- if (ret) {
- ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n");
- return ret;
- }
-
- /* ...final warm reset */
- if (ath5k_hw_nic_reset(ah, 0)) {
- ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n");
- return -EIO;
- }
-
if (ah->ah_version != AR5K_AR5210) {
/* ...update PLL if needed */
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Bob Copeland <[email protected]>
commit 0d0cd72fa1e6bfd419c99478ec70b4877ed0ef86 upstream.
Paraphrasing Rafael J. Wysocki: "drivers should not release PCI IRQs
in suspend." Doing so causes a warning during suspend/resume on some
platforms.
Cc: Rafael J. Wysocki <[email protected]>
Reported-by: Alan Jenkins <[email protected]>
Signed-off-by: Bob Copeland <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/net/wireless/ath/ath5k/base.c | 11 -----------
1 file changed, 11 deletions(-)
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -666,7 +666,6 @@ ath5k_pci_suspend(struct pci_dev *pdev,
ath5k_led_off(sc);
- free_irq(pdev->irq, sc);
pci_save_state(pdev);
pci_disable_device(pdev);
pci_set_power_state(pdev, PCI_D3hot);
@@ -694,18 +693,8 @@ ath5k_pci_resume(struct pci_dev *pdev)
*/
pci_write_config_byte(pdev, 0x41, 0);
- err = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
- if (err) {
- ATH5K_ERR(sc, "request_irq failed\n");
- goto err_no_irq;
- }
-
ath5k_led_enable(sc);
return 0;
-
-err_no_irq:
- pci_disable_device(pdev);
- return err;
}
#endif /* CONFIG_PM */
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Alan Stern <[email protected]>
commit 2023c610dc54a4f4130b0494309a9bd668ca3df8 upstream.
This patch (as1271) affects when new devices get linked into their
bus's list of devices. Currently this happens after probing, and it
doesn't happen at all if probing fails. Clearly this is wrong,
because at that point quite a few symbolic links have already been
created in sysfs. We are committed to adding the device, so it should
be linked into the bus's list regardless.
In addition, this needs to happen before the uevent announcing the new
device gets issued. Otherwise user programs might try to access the
device before it has been added to the bus.
To fix both these problems, the patch moves the call to
klist_add_tail() forward from bus_attach_device() to bus_add_device().
Since bus_attach_device() now does nothing but probe for drivers, it
has been renamed to bus_probe_device(). And lastly, the kerneldoc is
updated.
Signed-off-by: Alan Stern <[email protected]>
CC: Kay Sievers <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/base/base.h | 2 +-
drivers/base/bus.c | 23 ++++++++++-------------
drivers/base/core.c | 2 +-
3 files changed, 12 insertions(+), 15 deletions(-)
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -104,7 +104,7 @@ extern int system_bus_init(void);
extern int cpu_dev_init(void);
extern int bus_add_device(struct device *dev);
-extern void bus_attach_device(struct device *dev);
+extern void bus_probe_device(struct device *dev);
extern void bus_remove_device(struct device *dev);
extern int bus_add_driver(struct device_driver *drv);
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -459,8 +459,9 @@ static inline void remove_deprecated_bus
* bus_add_device - add device to bus
* @dev: device being added
*
+ * - Add device's bus attributes.
+ * - Create links to device's bus.
* - Add the device to its bus's list of devices.
- * - Create link to device's bus.
*/
int bus_add_device(struct device *dev)
{
@@ -483,6 +484,7 @@ int bus_add_device(struct device *dev)
error = make_deprecated_bus_links(dev);
if (error)
goto out_deprecated;
+ klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices);
}
return 0;
@@ -498,24 +500,19 @@ out_put:
}
/**
- * bus_attach_device - add device to bus
- * @dev: device tried to attach to a driver
+ * bus_probe_device - probe drivers for a new device
+ * @dev: device to probe
*
- * - Add device to bus's list of devices.
- * - Try to attach to driver.
+ * - Automatically probe for a driver if the bus allows it.
*/
-void bus_attach_device(struct device *dev)
+void bus_probe_device(struct device *dev)
{
struct bus_type *bus = dev->bus;
- int ret = 0;
+ int ret;
- if (bus) {
- if (bus->p->drivers_autoprobe)
- ret = device_attach(dev);
+ if (bus && bus->p->drivers_autoprobe) {
+ ret = device_attach(dev);
WARN_ON(ret < 0);
- if (ret >= 0)
- klist_add_tail(&dev->p->knode_bus,
- &bus->p->klist_devices);
}
}
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -945,7 +945,7 @@ int device_add(struct device *dev)
BUS_NOTIFY_ADD_DEVICE, dev);
kobject_uevent(&dev->kobj, KOBJ_ADD);
- bus_attach_device(dev);
+ bus_probe_device(dev);
if (parent)
klist_add_tail(&dev->p->knode_parent,
&parent->p->klist_children);
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Alan Cox <[email protected]>
commit 7ca0ff9ab3218ec443a7a9ad247e4650373ed41e upstream.
Now we are extracting out methods for shutdown and the like we can add a
proper tty_port_close method that knows all the innards of the tty closing
process and hides the lot from the caller.
At some point in the future this will be paired with a similar open()
helper and the drivers can stick to hardware management.
Signed-off-by: Alan Cox <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/char/tty_port.c | 29 +++++++++++++++++++++++++++--
include/linux/tty.h | 8 +++++++-
2 files changed, 34 insertions(+), 3 deletions(-)
--- a/drivers/char/tty_port.c
+++ b/drivers/char/tty_port.c
@@ -96,6 +96,14 @@ void tty_port_tty_set(struct tty_port *p
}
EXPORT_SYMBOL(tty_port_tty_set);
+static void tty_port_shutdown(struct tty_port *port)
+{
+ if (port->ops->shutdown &&
+ test_and_clear_bit(ASYNC_INITIALIZED, &port->flags))
+ port->ops->shutdown(port);
+
+}
+
/**
* tty_port_hangup - hangup helper
* @port: tty port
@@ -116,6 +124,7 @@ void tty_port_hangup(struct tty_port *po
port->tty = NULL;
spin_unlock_irqrestore(&port->lock, flags);
wake_up_interruptible(&port->open_wait);
+ tty_port_shutdown(port);
}
EXPORT_SYMBOL(tty_port_hangup);
@@ -296,15 +305,17 @@ int tty_port_close_start(struct tty_port
if (port->count) {
spin_unlock_irqrestore(&port->lock, flags);
+ if (port->ops->drop)
+ port->ops->drop(port);
return 0;
}
- port->flags |= ASYNC_CLOSING;
+ set_bit(ASYNC_CLOSING, &port->flags);
tty->closing = 1;
spin_unlock_irqrestore(&port->lock, flags);
/* Don't block on a stalled port, just pull the chain */
if (tty->flow_stopped)
tty_driver_flush_buffer(tty);
- if (port->flags & ASYNC_INITIALIZED &&
+ if (test_bit(ASYNCB_INITIALIZED, &port->flags) &&
port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
tty_wait_until_sent(tty, port->closing_wait);
if (port->drain_delay) {
@@ -318,6 +329,9 @@ int tty_port_close_start(struct tty_port
timeout = 2 * HZ;
schedule_timeout_interruptible(timeout);
}
+ /* Don't call port->drop for the last reference. Callers will want
+ to drop the last active reference in ->shutdown() or the tty
+ shutdown path */
return 1;
}
EXPORT_SYMBOL(tty_port_close_start);
@@ -348,3 +362,14 @@ void tty_port_close_end(struct tty_port
spin_unlock_irqrestore(&port->lock, flags);
}
EXPORT_SYMBOL(tty_port_close_end);
+
+void tty_port_close(struct tty_port *port, struct tty_struct *tty,
+ struct file *filp)
+{
+ if (tty_port_close_start(port, tty, filp) == 0)
+ return;
+ tty_port_shutdown(port);
+ tty_port_close_end(port, tty);
+ tty_port_tty_set(port, NULL);
+}
+EXPORT_SYMBOL(tty_port_close);
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -185,7 +185,12 @@ struct tty_port;
struct tty_port_operations {
/* Return 1 if the carrier is raised */
int (*carrier_raised)(struct tty_port *port);
+ /* Control the DTR line */
void (*dtr_rts)(struct tty_port *port, int raise);
+ /* Called when the last close completes or a hangup finishes
+ IFF the port was initialized. Do not use to free resources */
+ void (*shutdown)(struct tty_port *port);
+ void (*drop)(struct tty_port *port);
};
struct tty_port {
@@ -457,7 +462,8 @@ extern int tty_port_block_til_ready(stru
extern int tty_port_close_start(struct tty_port *port,
struct tty_struct *tty, struct file *filp);
extern void tty_port_close_end(struct tty_port *port, struct tty_struct *tty);
-
+extern void tty_port_close(struct tty_port *port,
+ struct tty_struct *tty, struct file *filp);
extern int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc);
extern int tty_unregister_ldisc(int disc);
extern int tty_set_ldisc(struct tty_struct *tty, int ldisc);
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Alan Cox <[email protected]>
commit d2b391822a11302add9e46476f3da4e18e6de84c upstream.
The USB layer uses tty_hangup to deal with unplugs of the physical hardware
(analogous to loss of carrier) and then frees the resources. However the
tty_hangup is asynchronous. As the hangup can sleep we can use tty_vhangup
which is the non async version to avoid freeing resources too early.
Signed-off-by: Alan Cox <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/serial/usb-serial.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -1161,10 +1161,7 @@ void usb_serial_disconnect(struct usb_in
if (port) {
struct tty_struct *tty = tty_port_tty_get(&port->port);
if (tty) {
- /* The hangup will occur asynchronously but
- the object refcounts will sort out all the
- cleanup */
- tty_hangup(tty);
+ tty_vhangup(tty);
tty_kref_put(tty);
}
kill_traffic(port);
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Alan Cox <[email protected]>
commit 4455e344959a217ffc28de2ab1af87541322b343 upstream.
Signed-off-by: Alan Cox <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/serial/usb-serial.c | 28 +++++++---------------------
1 file changed, 7 insertions(+), 21 deletions(-)
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -316,16 +316,19 @@ static void serial_do_down(struct usb_se
*
* Do the resource freeing and refcount dropping for the port. We must
* be careful about ordering and we must avoid freeing up the console.
+ *
+ * Called when the last tty kref is dropped.
*/
-static void serial_do_free(struct usb_serial_port *port)
+static void serial_do_free(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial;
struct module *owner;
/* The console is magical, do not hang up the console hardware
or there will be tears */
- if (port->console)
+ if (port == NULL || port->console)
return;
serial = port->serial;
@@ -350,30 +353,12 @@ static void serial_close(struct tty_stru
dbg("%s - port %d", __func__, port->number);
- /* FIXME:
- This leaves a very narrow race. Really we should do the
- serial_do_free() on tty->shutdown(), but tty->shutdown can
- be called from IRQ context and serial_do_free can sleep.
-
- The right fix is probably to make the tty free (which is rare)
- and thus tty->shutdown() occur via a work queue and simplify all
- the drivers that use it.
- */
- if (tty_hung_up_p(filp)) {
- /* serial_hangup already called serial_down at this point.
- Another user may have already reopened the port but
- serial_do_free is refcounted */
- serial_do_free(port);
- return;
- }
-
if (tty_port_close_start(&port->port, tty, filp) == 0)
return;
-
serial_do_down(port);
tty_port_close_end(&port->port, tty);
tty_port_tty_set(&port->port, NULL);
- serial_do_free(port);
+
}
static void serial_hangup(struct tty_struct *tty)
@@ -1243,6 +1228,7 @@ static const struct tty_operations seria
.chars_in_buffer = serial_chars_in_buffer,
.tiocmget = serial_tiocmget,
.tiocmset = serial_tiocmset,
+ .shutdown = serial_do_free,
.proc_fops = &serial_proc_fops,
};
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Luca Tettamanti <[email protected]>
commit 2c2a6172afab7421f6af7e228cd3121f423ea932 upstream.
Add myself as asus_atk0110 maintainer.
Signed-off-by: Luca Tettamanti <[email protected]>
Signed-off-by: Jean Delvare <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
MAINTAINERS | 6 ++++++
1 file changed, 6 insertions(+)
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -897,6 +897,12 @@ W: http://wireless.kernel.org/en/users/D
S: Maintained
F: drivers/net/wireless/ath/ar9170/
+ATK0110 HWMON DRIVER
+M: Luca Tettamanti <[email protected]>
+L: [email protected]
+S: Maintained
+F: drivers/hwmon/asus_atk0110.c
+
ATI_REMOTE2 DRIVER
M: Ville Syrjala <[email protected]>
S: Maintained
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Alan Cox <[email protected]>
commit fe1ae7fdd2ee603f2d95f04e09a68f7f79045127 upstream.
Various drivers have hacks to mangle termios structures. This stems from
the fact there is no nice setup hook for configuring the termios settings
when the port is created
Signed-off-by: Alan Cox <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/char/tty_io.c | 1
drivers/usb/serial/ark3116.c | 46 +++++++++------------------------------
drivers/usb/serial/cypress_m8.c | 12 ++--------
drivers/usb/serial/empeg.c | 12 ++--------
drivers/usb/serial/iuu_phoenix.c | 31 +++++++++++---------------
drivers/usb/serial/kobil_sct.c | 22 +++++++++---------
drivers/usb/serial/oti6858.c | 21 ++++++++---------
drivers/usb/serial/spcp8x5.c | 21 ++++++++---------
drivers/usb/serial/usb-serial.c | 38 +++++++++++++++++++++++++++++++-
drivers/usb/serial/whiteheat.c | 6 ++---
include/linux/usb/serial.h | 3 ++
11 files changed, 106 insertions(+), 107 deletions(-)
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -1184,6 +1184,7 @@ int tty_init_termios(struct tty_struct *
tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios);
return 0;
}
+EXPORT_SYMBOL_GPL(tty_init_termios);
/**
* tty_driver_install_tty() - install a tty entry in the driver
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -35,11 +35,6 @@ static struct usb_device_id id_table []
};
MODULE_DEVICE_TABLE(usb, id_table);
-struct ark3116_private {
- spinlock_t lock;
- u8 termios_initialized;
-};
-
static inline void ARK3116_SND(struct usb_serial *serial, int seq,
__u8 request, __u8 requesttype,
__u16 value, __u16 index)
@@ -82,22 +77,11 @@ static inline void ARK3116_RCV_QUIET(str
static int ark3116_attach(struct usb_serial *serial)
{
char *buf;
- struct ark3116_private *priv;
- int i;
-
- for (i = 0; i < serial->num_ports; ++i) {
- priv = kzalloc(sizeof(struct ark3116_private), GFP_KERNEL);
- if (!priv)
- goto cleanup;
- spin_lock_init(&priv->lock);
-
- usb_set_serial_port_data(serial->port[i], priv);
- }
buf = kmalloc(1, GFP_KERNEL);
if (!buf) {
dbg("error kmalloc -> out of mem?");
- goto cleanup;
+ return -ENOMEM;
}
/* 3 */
@@ -149,13 +133,16 @@ static int ark3116_attach(struct usb_ser
kfree(buf);
return 0;
+}
-cleanup:
- for (--i; i >= 0; --i) {
- kfree(usb_get_serial_port_data(serial->port[i]));
- usb_set_serial_port_data(serial->port[i], NULL);
- }
- return -ENOMEM;
+static void ark3116_init_termios(struct tty_struct *tty)
+{
+ struct ktermios *termios = tty->termios;
+ *termios = tty_std_termios;
+ termios->c_cflag = B9600 | CS8
+ | CREAD | HUPCL | CLOCAL;
+ termios->c_ispeed = 9600;
+ termios->c_ospeed = 9600;
}
static void ark3116_set_termios(struct tty_struct *tty,
@@ -163,10 +150,8 @@ static void ark3116_set_termios(struct t
struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
- struct ark3116_private *priv = usb_get_serial_port_data(port);
struct ktermios *termios = tty->termios;
unsigned int cflag = termios->c_cflag;
- unsigned long flags;
int baud;
int ark3116_baud;
char *buf;
@@ -176,16 +161,6 @@ static void ark3116_set_termios(struct t
dbg("%s - port %d", __func__, port->number);
- spin_lock_irqsave(&priv->lock, flags);
- if (!priv->termios_initialized) {
- *termios = tty_std_termios;
- termios->c_cflag = B9600 | CS8
- | CREAD | HUPCL | CLOCAL;
- termios->c_ispeed = 9600;
- termios->c_ospeed = 9600;
- priv->termios_initialized = 1;
- }
- spin_unlock_irqrestore(&priv->lock, flags);
cflag = termios->c_cflag;
termios->c_cflag &= ~(CMSPAR|CRTSCTS);
@@ -455,6 +430,7 @@ static struct usb_serial_driver ark3116_
.num_ports = 1,
.attach = ark3116_attach,
.set_termios = ark3116_set_termios,
+ .init_termios = ark3116_init_termios,
.ioctl = ark3116_ioctl,
.tiocmget = ark3116_tiocmget,
.open = ark3116_open,
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -659,15 +659,7 @@ static int cypress_open(struct tty_struc
spin_unlock_irqrestore(&priv->lock, flags);
/* Set termios */
- result = cypress_write(tty, port, NULL, 0);
-
- if (result) {
- dev_err(&port->dev,
- "%s - failed setting the control lines - error %d\n",
- __func__, result);
- return result;
- } else
- dbg("%s - success setting the control lines", __func__);
+ cypress_send(port);
if (tty)
cypress_set_termios(tty, port, &priv->tmp_termios);
@@ -1005,6 +997,8 @@ static void cypress_set_termios(struct t
dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&priv->lock, flags);
+ /* We can't clean this one up as we don't know the device type
+ early enough */
if (!priv->termios_initialized) {
if (priv->chiptype == CT_EARTHMATE) {
*(tty->termios) = tty_std_termios;
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -90,8 +90,7 @@ static int empeg_chars_in_buffer(struct
static void empeg_throttle(struct tty_struct *tty);
static void empeg_unthrottle(struct tty_struct *tty);
static int empeg_startup(struct usb_serial *serial);
-static void empeg_set_termios(struct tty_struct *tty,
- struct usb_serial_port *port, struct ktermios *old_termios);
+static void empeg_init_termios(struct tty_struct *tty);
static void empeg_write_bulk_callback(struct urb *urb);
static void empeg_read_bulk_callback(struct urb *urb);
@@ -123,7 +122,7 @@ static struct usb_serial_driver empeg_de
.throttle = empeg_throttle,
.unthrottle = empeg_unthrottle,
.attach = empeg_startup,
- .set_termios = empeg_set_termios,
+ .init_termios = empeg_init_termios,
.write = empeg_write,
.write_room = empeg_write_room,
.chars_in_buffer = empeg_chars_in_buffer,
@@ -150,9 +149,6 @@ static int empeg_open(struct tty_struct
dbg("%s - port %d", __func__, port->number);
- /* Force default termio settings */
- empeg_set_termios(tty, port, NULL) ;
-
bytes_in = 0;
bytes_out = 0;
@@ -425,11 +421,9 @@ static int empeg_startup(struct usb_ser
}
-static void empeg_set_termios(struct tty_struct *tty,
- struct usb_serial_port *port, struct ktermios *old_termios)
+static void empeg_init_termios(struct tty_struct *tty)
{
struct ktermios *termios = tty->termios;
- dbg("%s - port %d", __func__, port->number);
/*
* The empeg-car player wants these particular tty settings.
--- a/drivers/usb/serial/iuu_phoenix.c
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -71,7 +71,6 @@ struct iuu_private {
spinlock_t lock; /* store irq state */
wait_queue_head_t delta_msr_wait;
u8 line_status;
- u8 termios_initialized;
int tiostatus; /* store IUART SIGNAL for tiocmget call */
u8 reset; /* if 1 reset is needed */
int poll; /* number of poll */
@@ -1018,6 +1017,18 @@ static void iuu_close(struct usb_serial_
}
}
+static void iuu_init_termios(struct tty_struct *tty)
+{
+ *(tty->termios) = tty_std_termios;
+ tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600
+ | TIOCM_CTS | CSTOPB | PARENB;
+ tty->termios->c_ispeed = 9600;
+ tty->termios->c_ospeed = 9600;
+ tty->termios->c_lflag = 0;
+ tty->termios->c_oflag = 0;
+ tty->termios->c_iflag = 0;
+}
+
static int iuu_open(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp)
{
@@ -1025,7 +1036,6 @@ static int iuu_open(struct tty_struct *t
u8 *buf;
int result;
u32 actual;
- unsigned long flags;
struct iuu_private *priv = usb_get_serial_port_data(port);
dbg("%s - port %d", __func__, port->number);
@@ -1064,21 +1074,7 @@ static int iuu_open(struct tty_struct *t
port->bulk_in_buffer, 512,
NULL, NULL);
- /* set the termios structure */
- spin_lock_irqsave(&priv->lock, flags);
- if (tty && !priv->termios_initialized) {
- *(tty->termios) = tty_std_termios;
- tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600
- | TIOCM_CTS | CSTOPB | PARENB;
- tty->termios->c_ispeed = 9600;
- tty->termios->c_ospeed = 9600;
- tty->termios->c_lflag = 0;
- tty->termios->c_oflag = 0;
- tty->termios->c_iflag = 0;
- priv->termios_initialized = 1;
- priv->poll = 0;
- }
- spin_unlock_irqrestore(&priv->lock, flags);
+ priv->poll = 0;
/* initialize writebuf */
#define FISH(a, b, c, d) do { \
@@ -1201,6 +1197,7 @@ static struct usb_serial_driver iuu_devi
.tiocmget = iuu_tiocmget,
.tiocmset = iuu_tiocmset,
.set_termios = iuu_set_termios,
+ .init_termios = iuu_init_termios,
.attach = iuu_startup,
.release = iuu_release,
};
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -85,7 +85,7 @@ static void kobil_read_int_callback(stru
static void kobil_write_callback(struct urb *purb);
static void kobil_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old);
-
+static void kobil_init_termios(struct tty_struct *tty);
static struct usb_device_id id_table [] = {
{ USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_ADAPTER_B_PRODUCT_ID) },
@@ -120,6 +120,7 @@ static struct usb_serial_driver kobil_de
.release = kobil_release,
.ioctl = kobil_ioctl,
.set_termios = kobil_set_termios,
+ .init_termios = kobil_init_termios,
.tiocmget = kobil_tiocmget,
.tiocmset = kobil_tiocmset,
.open = kobil_open,
@@ -210,6 +211,15 @@ static void kobil_release(struct usb_ser
kfree(usb_get_serial_port_data(serial->port[i]));
}
+static void kobil_init_termios(struct tty_struct *tty)
+{
+ /* Default to echo off and other sane device settings */
+ tty->termios->c_lflag = 0;
+ tty->termios->c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN | XCASE);
+ tty->termios->c_iflag = IGNBRK | IGNPAR | IXOFF;
+ /* do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D) */
+ tty->termios->c_oflag &= ~ONLCR;
+}
static int kobil_open(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp)
@@ -226,16 +236,6 @@ static int kobil_open(struct tty_struct
/* someone sets the dev to 0 if the close method has been called */
port->interrupt_in_urb->dev = port->serial->dev;
- if (tty) {
-
- /* Default to echo off and other sane device settings */
- tty->termios->c_lflag = 0;
- tty->termios->c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN |
- XCASE);
- tty->termios->c_iflag = IGNBRK | IGNPAR | IXOFF;
- /* do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D) */
- tty->termios->c_oflag &= ~ONLCR;
- }
/* allocate memory for transfer buffer */
transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL);
if (!transfer_buffer)
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -146,6 +146,7 @@ static int oti6858_open(struct tty_struc
static void oti6858_close(struct usb_serial_port *port);
static void oti6858_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old);
+static void oti6858_init_termios(struct tty_struct *tty);
static int oti6858_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg);
static void oti6858_read_int_callback(struct urb *urb);
@@ -186,6 +187,7 @@ static struct usb_serial_driver oti6858_
.write = oti6858_write,
.ioctl = oti6858_ioctl,
.set_termios = oti6858_set_termios,
+ .init_termios = oti6858_init_termios,
.tiocmget = oti6858_tiocmget,
.tiocmset = oti6858_tiocmset,
.read_bulk_callback = oti6858_read_bulk_callback,
@@ -206,7 +208,6 @@ struct oti6858_private {
struct {
u8 read_urb_in_use;
u8 write_urb_in_use;
- u8 termios_initialized;
} flags;
struct delayed_work delayed_write_work;
@@ -447,6 +448,14 @@ static int oti6858_chars_in_buffer(struc
return chars;
}
+static void oti6858_init_termios(struct tty_struct *tty)
+{
+ *(tty->termios) = tty_std_termios;
+ tty->termios->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
+ tty->termios->c_ispeed = 38400;
+ tty->termios->c_ospeed = 38400;
+}
+
static void oti6858_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
@@ -464,16 +473,6 @@ static void oti6858_set_termios(struct t
return;
}
- spin_lock_irqsave(&priv->lock, flags);
- if (!priv->flags.termios_initialized) {
- *(tty->termios) = tty_std_termios;
- tty->termios->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
- tty->termios->c_ispeed = 38400;
- tty->termios->c_ospeed = 38400;
- priv->flags.termios_initialized = 1;
- }
- spin_unlock_irqrestore(&priv->lock, flags);
-
cflag = tty->termios->c_cflag;
spin_lock_irqsave(&priv->lock, flags);
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -299,7 +299,6 @@ struct spcp8x5_private {
wait_queue_head_t delta_msr_wait;
u8 line_control;
u8 line_status;
- u8 termios_initialized;
};
/* desc : when device plug in,this function would be called.
@@ -498,6 +497,15 @@ static void spcp8x5_close(struct usb_ser
dev_dbg(&port->dev, "usb_unlink_urb(read_urb) = %d\n", result);
}
+static void spcp8x5_init_termios(struct tty_struct *tty)
+{
+ /* for the 1st time call this function */
+ *(tty->termios) = tty_std_termios;
+ tty->termios->c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
+ tty->termios->c_ispeed = 115200;
+ tty->termios->c_ospeed = 115200;
+}
+
/* set the serial param for transfer. we should check if we really need to
* transfer. if we set flow control we should do this too. */
static void spcp8x5_set_termios(struct tty_struct *tty,
@@ -514,16 +522,6 @@ static void spcp8x5_set_termios(struct t
int i;
u8 control;
- /* for the 1st time call this function */
- spin_lock_irqsave(&priv->lock, flags);
- if (!priv->termios_initialized) {
- *(tty->termios) = tty_std_termios;
- tty->termios->c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
- tty->termios->c_ispeed = 115200;
- tty->termios->c_ospeed = 115200;
- priv->termios_initialized = 1;
- }
- spin_unlock_irqrestore(&priv->lock, flags);
/* check that they really want us to change something */
if (!tty_termios_hw_change(tty->termios, old_termios))
@@ -1011,6 +1009,7 @@ static struct usb_serial_driver spcp8x5_
.carrier_raised = spcp8x5_carrier_raised,
.write = spcp8x5_write,
.set_termios = spcp8x5_set_termios,
+ .init_termios = spcp8x5_init_termios,
.ioctl = spcp8x5_ioctl,
.tiocmget = spcp8x5_tiocmget,
.tiocmset = spcp8x5_tiocmset,
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -721,6 +721,41 @@ static const struct tty_port_operations
.dtr_rts = serial_dtr_rts,
};
+/**
+ * serial_install - install tty
+ * @driver: the driver (USB in our case)
+ * @tty: the tty being created
+ *
+ * Create the termios objects for this tty. We use the default USB
+ * serial ones but permit them to be overriddenby serial->type->termios.
+ * This lets us remove all the ugly hackery
+ */
+
+static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+ int idx = tty->index;
+ struct usb_serial *serial;
+ int retval;
+
+ /* If the termios setup has yet to be done */
+ if (tty->driver->termios[idx] == NULL) {
+ /* perform the standard setup */
+ retval = tty_init_termios(tty);
+ if (retval)
+ return retval;
+ /* allow the driver to update it */
+ serial = usb_serial_get_by_index(tty->index);
+ if (serial->type->init_termios)
+ serial->type->init_termios(tty);
+ usb_serial_put(serial);
+ }
+ /* Final install (we use the default method) */
+ tty_driver_kref_get(driver);
+ tty->count++;
+ driver->ttys[idx] = tty;
+ return 0;
+}
+
int usb_serial_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
@@ -1228,7 +1263,8 @@ static const struct tty_operations seria
.chars_in_buffer = serial_chars_in_buffer,
.tiocmget = serial_tiocmget,
.tiocmset = serial_tiocmset,
- .shutdown = serial_do_free,
+ .shutdown = serial_do_free,
+ .install = serial_install,
.proc_fops = &serial_proc_fops,
};
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -259,7 +259,7 @@ static int firm_send_command(struct usb_
__u8 *data, __u8 datasize);
static int firm_open(struct usb_serial_port *port);
static int firm_close(struct usb_serial_port *port);
-static int firm_setup_port(struct tty_struct *tty);
+static void firm_setup_port(struct tty_struct *tty);
static int firm_set_rts(struct usb_serial_port *port, __u8 onoff);
static int firm_set_dtr(struct usb_serial_port *port, __u8 onoff);
static int firm_set_break(struct usb_serial_port *port, __u8 onoff);
@@ -1211,7 +1211,7 @@ static int firm_close(struct usb_serial_
}
-static int firm_setup_port(struct tty_struct *tty)
+static void firm_setup_port(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct whiteheat_port_settings port_settings;
@@ -1286,7 +1286,7 @@ static int firm_setup_port(struct tty_st
port_settings.lloop = 0;
/* now send the message to the device */
- return firm_send_command(port, WHITEHEAT_SETUP_PORT,
+ firm_send_command(port, WHITEHEAT_SETUP_PORT,
(__u8 *)&port_settings, sizeof(port_settings));
}
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -261,6 +261,9 @@ struct usb_serial_driver {
be an attached tty at this point */
void (*dtr_rts)(struct usb_serial_port *port, int on);
int (*carrier_raised)(struct usb_serial_port *port);
+ /* Called by the usb serial hooks to allow the user to rework the
+ termios state */
+ void (*init_termios)(struct tty_struct *tty);
/* USB events */
void (*read_int_callback)(struct urb *urb);
void (*write_int_callback)(struct urb *urb);
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Alan Stern <[email protected]>
commit 41bd34ddd7aa46dbc03b5bb33896e0fa8100fe7b upstream.
This patch (as1284) changes the referencing of the usb_serial and
usb_serial_port structures in usb-serial.c. It's not feasible to make
the port structures keep a reference to the serial structure, because
the ports need to remain in existence when serial is released -- quite
a few of the drivers expect this. Consequently taking a reference
to the port when the device file is open is insufficient; such a
reference would not pin serial.
To fix this, we now take a reference to serial when the device file is
opened. The final put_device() for the ports occurs in
destroy_serial(), so that the ports will last as long as they are
needed.
The patch initializes all the port devices, including those in the
unused "fake" ports. This makes the code more uniform because they
can all be released in the same way. The error handling code in
usb_serial_probe() is much simplified by this approach; instead of
freeing everything by hand we can use a single usb_serial_put() call.
Also simplified is the port-release mechanism. Instead of being two
separate routines, port_release() and port_free() can be combined into
one.
Signed-off-by: Alan Stern <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/serial/usb-serial.c | 95 ++++++++--------------------------------
1 file changed, 20 insertions(+), 75 deletions(-)
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -43,8 +43,6 @@
#define DRIVER_AUTHOR "Greg Kroah-Hartman, [email protected], http://www.kroah.com/linux/"
#define DRIVER_DESC "USB Serial Driver core"
-static void port_free(struct usb_serial_port *port);
-
/* Driver structure we register with the USB core */
static struct usb_driver usb_serial_driver = {
.name = "usbserial",
@@ -145,27 +143,16 @@ static void destroy_serial(struct kref *
serial->type->release(serial);
- for (i = 0; i < serial->num_ports; ++i) {
+ /* Now that nothing is using the ports, they can be freed */
+ for (i = 0; i < serial->num_port_pointers; ++i) {
port = serial->port[i];
- if (port)
+ if (port) {
+ port->serial = NULL;
put_device(&port->dev);
- }
-
- /* If this is a "fake" port, we have to clean it up here, as it will
- * not get cleaned up in port_release() as it was never registered with
- * the driver core */
- if (serial->num_ports < serial->num_port_pointers) {
- for (i = serial->num_ports;
- i < serial->num_port_pointers; ++i) {
- port = serial->port[i];
- if (port)
- port_free(port);
}
}
usb_put_dev(serial->dev);
-
- /* free up any memory that we allocated */
kfree(serial);
}
@@ -201,8 +188,6 @@ static int serial_open (struct tty_struc
port = serial->port[portNumber];
if (!port || serial->disconnected)
retval = -ENODEV;
- else
- get_device(&port->dev);
/*
* Note: Our locking order requirement does not allow port->mutex
* to be acquired while serial->disc_mutex is held.
@@ -213,7 +198,7 @@ static int serial_open (struct tty_struc
if (mutex_lock_interruptible(&port->mutex)) {
retval = -ERESTARTSYS;
- goto bailout_port_put;
+ goto bailout_serial_put;
}
++port->port.count;
@@ -273,8 +258,6 @@ bailout_mutex_unlock:
tty->driver_data = NULL;
tty_port_tty_set(&port->port, NULL);
mutex_unlock(&port->mutex);
-bailout_port_put:
- put_device(&port->dev);
bailout_serial_put:
usb_serial_put(serial);
return retval;
@@ -333,14 +316,13 @@ static void serial_do_free(struct tty_st
serial = port->serial;
owner = serial->type->driver.owner;
- put_device(&port->dev);
- /* Mustn't dereference port any more */
+
mutex_lock(&serial->disc_mutex);
if (!serial->disconnected)
usb_autopm_put_interface(serial->interface);
mutex_unlock(&serial->disc_mutex);
+
usb_serial_put(serial);
- /* Mustn't dereference serial any more */
module_put(owner);
}
@@ -581,14 +563,6 @@ static void usb_serial_port_work(struct
tty_kref_put(tty);
}
-static void port_release(struct device *dev)
-{
- struct usb_serial_port *port = to_usb_serial_port(dev);
-
- dbg ("%s - %s", __func__, dev_name(dev));
- port_free(port);
-}
-
static void kill_traffic(struct usb_serial_port *port)
{
usb_kill_urb(port->read_urb);
@@ -608,8 +582,12 @@ static void kill_traffic(struct usb_seri
usb_kill_urb(port->interrupt_out_urb);
}
-static void port_free(struct usb_serial_port *port)
+static void port_release(struct device *dev)
{
+ struct usb_serial_port *port = to_usb_serial_port(dev);
+
+ dbg ("%s - %s", __func__, dev_name(dev));
+
/*
* Stop all the traffic before cancelling the work, so that
* nobody will restart it by calling usb_serial_port_softint.
@@ -955,6 +933,11 @@ int usb_serial_probe(struct usb_interfac
mutex_init(&port->mutex);
INIT_WORK(&port->work, usb_serial_port_work);
serial->port[i] = port;
+ port->dev.parent = &interface->dev;
+ port->dev.driver = NULL;
+ port->dev.bus = &usb_serial_bus_type;
+ port->dev.release = &port_release;
+ device_initialize(&port->dev);
}
/* set up the endpoint information */
@@ -1097,15 +1080,10 @@ int usb_serial_probe(struct usb_interfac
/* register all of the individual ports with the driver core */
for (i = 0; i < num_ports; ++i) {
port = serial->port[i];
- port->dev.parent = &interface->dev;
- port->dev.driver = NULL;
- port->dev.bus = &usb_serial_bus_type;
- port->dev.release = &port_release;
-
dev_set_name(&port->dev, "ttyUSB%d", port->number);
dbg ("%s - registering %s", __func__, dev_name(&port->dev));
port->dev_state = PORT_REGISTERING;
- retval = device_register(&port->dev);
+ retval = device_add(&port->dev);
if (retval) {
dev_err(&port->dev, "Error registering port device, "
"continuing\n");
@@ -1123,39 +1101,7 @@ exit:
return 0;
probe_error:
- for (i = 0; i < num_bulk_in; ++i) {
- port = serial->port[i];
- if (!port)
- continue;
- usb_free_urb(port->read_urb);
- kfree(port->bulk_in_buffer);
- }
- for (i = 0; i < num_bulk_out; ++i) {
- port = serial->port[i];
- if (!port)
- continue;
- usb_free_urb(port->write_urb);
- kfree(port->bulk_out_buffer);
- }
- for (i = 0; i < num_interrupt_in; ++i) {
- port = serial->port[i];
- if (!port)
- continue;
- usb_free_urb(port->interrupt_in_urb);
- kfree(port->interrupt_in_buffer);
- }
- for (i = 0; i < num_interrupt_out; ++i) {
- port = serial->port[i];
- if (!port)
- continue;
- usb_free_urb(port->interrupt_out_urb);
- kfree(port->interrupt_out_buffer);
- }
-
- /* free up any memory that we allocated */
- for (i = 0; i < serial->num_port_pointers; ++i)
- kfree(serial->port[i]);
- kfree(serial);
+ usb_serial_put(serial);
return -EIO;
}
EXPORT_SYMBOL_GPL(usb_serial_probe);
@@ -1206,8 +1152,7 @@ void usb_serial_disconnect(struct usb_in
}
serial->type->disconnect(serial);
- /* let the last holder of this object
- * cause it to be cleaned up */
+ /* let the last holder of this object cause it to be cleaned up */
usb_serial_put(serial);
dev_info(dev, "device disconnected\n");
}
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Alan Stern <[email protected]>
commit f5b0953a89fa3407fb293cc54ead7d8feec489e4 upstream.
This patch (as1285) rearranges the subroutines in usb-serial.c
concerned with tty lifetimes into a more logical order: install, open,
hangup, close, release. It also updates the formatting of the
kerneldoc comments.
Signed-off-by: Alan Stern <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/serial/usb-serial.c | 154 ++++++++++++++++++++--------------------
1 file changed, 77 insertions(+), 77 deletions(-)
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -166,6 +166,41 @@ void usb_serial_put(struct usb_serial *s
/*****************************************************************************
* Driver tty interface functions
*****************************************************************************/
+
+/**
+ * serial_install - install tty
+ * @driver: the driver (USB in our case)
+ * @tty: the tty being created
+ *
+ * Create the termios objects for this tty. We use the default
+ * USB serial settings but permit them to be overridden by
+ * serial->type->init_termios.
+ */
+static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+ int idx = tty->index;
+ struct usb_serial *serial;
+ int retval;
+
+ /* If the termios setup has yet to be done */
+ if (tty->driver->termios[idx] == NULL) {
+ /* perform the standard setup */
+ retval = tty_init_termios(tty);
+ if (retval)
+ return retval;
+ /* allow the driver to update it */
+ serial = usb_serial_get_by_index(tty->index);
+ if (serial->type->init_termios)
+ serial->type->init_termios(tty);
+ usb_serial_put(serial);
+ }
+ /* Final install (we use the default method) */
+ tty_driver_kref_get(driver);
+ tty->count++;
+ driver->ttys[idx] = tty;
+ return 0;
+}
+
static int serial_open (struct tty_struct *tty, struct file *filp)
{
struct usb_serial *serial;
@@ -264,13 +299,11 @@ bailout_serial_put:
}
/**
- * serial_do_down - shut down hardware
- * @port: port to shut down
+ * serial_do_down - shut down hardware
+ * @port: port to shut down
*
- * Shut down a USB port unless it is the console. We never shut down the
- * console hardware as it will always be in use.
- *
- * Don't free any resources at this point
+ * Shut down a USB serial port unless it is the console. We never
+ * shut down the console hardware as it will always be in use.
*/
static void serial_do_down(struct usb_serial_port *port)
{
@@ -278,8 +311,10 @@ static void serial_do_down(struct usb_se
struct usb_serial *serial;
struct module *owner;
- /* The console is magical, do not hang up the console hardware
- or there will be tears */
+ /*
+ * The console is magical. Do not hang up the console hardware
+ * or there will be tears.
+ */
if (port->console)
return;
@@ -293,24 +328,50 @@ static void serial_do_down(struct usb_se
mutex_unlock(&port->mutex);
}
+static void serial_hangup(struct tty_struct *tty)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ serial_do_down(port);
+ tty_port_hangup(&port->port);
+ /* We must not free port yet - the USB serial layer depends on it's
+ continued existence */
+}
+
+static void serial_close(struct tty_struct *tty, struct file *filp)
+{
+ struct usb_serial_port *port = tty->driver_data;
+
+ if (!port)
+ return;
+
+ dbg("%s - port %d", __func__, port->number);
+
+ if (tty_port_close_start(&port->port, tty, filp) == 0)
+ return;
+ serial_do_down(port);
+ tty_port_close_end(&port->port, tty);
+ tty_port_tty_set(&port->port, NULL);
+
+}
+
/**
- * serial_do_free - free resources post close/hangup
- * @port: port to free up
+ * serial_do_free - free resources post close/hangup
+ * @port: port to free up
*
- * Do the resource freeing and refcount dropping for the port. We must
- * be careful about ordering and we must avoid freeing up the console.
+ * Do the resource freeing and refcount dropping for the port.
+ * Avoid freeing the console.
*
- * Called when the last tty kref is dropped.
+ * Called when the last tty kref is dropped.
*/
-
static void serial_do_free(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial;
struct module *owner;
- /* The console is magical, do not hang up the console hardware
- or there will be tears */
+ /* The console is magical. Do not hang up the console hardware
+ * or there will be tears.
+ */
if (port == NULL || port->console)
return;
@@ -326,32 +387,6 @@ static void serial_do_free(struct tty_st
module_put(owner);
}
-static void serial_close(struct tty_struct *tty, struct file *filp)
-{
- struct usb_serial_port *port = tty->driver_data;
-
- if (!port)
- return;
-
- dbg("%s - port %d", __func__, port->number);
-
- if (tty_port_close_start(&port->port, tty, filp) == 0)
- return;
- serial_do_down(port);
- tty_port_close_end(&port->port, tty);
- tty_port_tty_set(&port->port, NULL);
-
-}
-
-static void serial_hangup(struct tty_struct *tty)
-{
- struct usb_serial_port *port = tty->driver_data;
- serial_do_down(port);
- tty_port_hangup(&port->port);
- /* We must not free port yet - the USB serial layer depends on it's
- continued existence */
-}
-
static int serial_write(struct tty_struct *tty, const unsigned char *buf,
int count)
{
@@ -699,41 +734,6 @@ static const struct tty_port_operations
.dtr_rts = serial_dtr_rts,
};
-/**
- * serial_install - install tty
- * @driver: the driver (USB in our case)
- * @tty: the tty being created
- *
- * Create the termios objects for this tty. We use the default USB
- * serial ones but permit them to be overriddenby serial->type->termios.
- * This lets us remove all the ugly hackery
- */
-
-static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
-{
- int idx = tty->index;
- struct usb_serial *serial;
- int retval;
-
- /* If the termios setup has yet to be done */
- if (tty->driver->termios[idx] == NULL) {
- /* perform the standard setup */
- retval = tty_init_termios(tty);
- if (retval)
- return retval;
- /* allow the driver to update it */
- serial = usb_serial_get_by_index(tty->index);
- if (serial->type->init_termios)
- serial->type->init_termios(tty);
- usb_serial_put(serial);
- }
- /* Final install (we use the default method) */
- tty_driver_kref_get(driver);
- tty->count++;
- driver->ttys[idx] = tty;
- return 0;
-}
-
int usb_serial_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Alan Stern <[email protected]>
commit 8bc2c1b2daf95029658868cb1427baea2da87139 upstream.
This patch (as1286) changes usb_serial_get_by_index(). Now the
routine will check whether the serial device has been disconnected; if
it has then the return value will be NULL. If the device hasn't been
disconnected then the routine will return with serial->disc_mutex
held, so that the caller can use the structure without fear of racing
against driver unloads.
This permits the scope of table_mutex in destroy_serial() to be
reduced. Instead of protecting the entire function, it suffices to
protect the part that actually uses serial_table[], i.e., the call to
return_serial(). There's no longer any danger of the refcount being
incremented after it reaches 0 (which was the reason for having the
large scope previously), because it can't reach 0 until the serial
device has been disconnected.
Also, the patch makes serial_install() check that serial is non-NULL
before attempting to use it.
Signed-off-by: Alan Stern <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/serial/usb-serial.c | 31 +++++++++++++++++++++++--------
1 file changed, 23 insertions(+), 8 deletions(-)
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -66,6 +66,11 @@ static struct usb_serial *serial_table[S
static DEFINE_MUTEX(table_lock);
static LIST_HEAD(usb_serial_driver_list);
+/*
+ * Look up the serial structure. If it is found and it hasn't been
+ * disconnected, return with its disc_mutex held and its refcount
+ * incremented. Otherwise return NULL.
+ */
struct usb_serial *usb_serial_get_by_index(unsigned index)
{
struct usb_serial *serial;
@@ -73,8 +78,15 @@ struct usb_serial *usb_serial_get_by_ind
mutex_lock(&table_lock);
serial = serial_table[index];
- if (serial)
- kref_get(&serial->kref);
+ if (serial) {
+ mutex_lock(&serial->disc_mutex);
+ if (serial->disconnected) {
+ mutex_unlock(&serial->disc_mutex);
+ serial = NULL;
+ } else {
+ kref_get(&serial->kref);
+ }
+ }
mutex_unlock(&table_lock);
return serial;
}
@@ -123,8 +135,10 @@ static void return_serial(struct usb_ser
dbg("%s", __func__);
+ mutex_lock(&table_lock);
for (i = 0; i < serial->num_ports; ++i)
serial_table[serial->minor + i] = NULL;
+ mutex_unlock(&table_lock);
}
static void destroy_serial(struct kref *kref)
@@ -158,9 +172,7 @@ static void destroy_serial(struct kref *
void usb_serial_put(struct usb_serial *serial)
{
- mutex_lock(&table_lock);
kref_put(&serial->kref, destroy_serial);
- mutex_unlock(&table_lock);
}
/*****************************************************************************
@@ -190,9 +202,12 @@ static int serial_install(struct tty_dri
return retval;
/* allow the driver to update it */
serial = usb_serial_get_by_index(tty->index);
- if (serial->type->init_termios)
- serial->type->init_termios(tty);
- usb_serial_put(serial);
+ if (serial) {
+ if (serial->type->init_termios)
+ serial->type->init_termios(tty);
+ usb_serial_put(serial);
+ mutex_unlock(&serial->disc_mutex);
+ }
}
/* Final install (we use the default method) */
tty_driver_kref_get(driver);
@@ -218,7 +233,6 @@ static int serial_open (struct tty_struc
return -ENODEV;
}
- mutex_lock(&serial->disc_mutex);
portNumber = tty->index - serial->minor;
port = serial->port[portNumber];
if (!port || serial->disconnected)
@@ -529,6 +543,7 @@ static int serial_proc_show(struct seq_f
seq_putc(m, '\n');
usb_serial_put(serial);
+ mutex_unlock(&serial->disc_mutex);
}
return 0;
}
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Alan Stern <[email protected]>
commit cc56cd0157753c04a987888a2f793803df661a40 upstream.
This patch (as1287) makes serial_install() be reponsible for acquiring
references to the usb_serial structure and the driver module when a
tty is first used. This is more sensible than having serial_open() do
it, because a tty can be opened many times whereas it is installed
only once, when it is created. (Not to mention that these actions are
reversed when the tty is released, not when it is closed.) Finally,
it is at install time that the TTY core takes its own reference to the
usb_serial module, so it is only fitting that we should act the same
way in regard to the lower-level serial driver.
Signed-off-by: Alan Stern <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/serial/usb-serial.c | 111 ++++++++++++++++------------------------
1 file changed, 47 insertions(+), 64 deletions(-)
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -187,100 +187,92 @@ void usb_serial_put(struct usb_serial *s
* Create the termios objects for this tty. We use the default
* USB serial settings but permit them to be overridden by
* serial->type->init_termios.
+ *
+ * This is the first place a new tty gets used. Hence this is where we
+ * acquire references to the usb_serial structure and the driver module,
+ * where we store a pointer to the port, and where we do an autoresume.
+ * All these actions are reversed in serial_do_free().
*/
static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
{
int idx = tty->index;
struct usb_serial *serial;
- int retval;
+ struct usb_serial_port *port;
+ int retval = -ENODEV;
+
+ serial = usb_serial_get_by_index(idx);
+ if (!serial)
+ return retval;
+
+ port = serial->port[idx - serial->minor];
+ if (!port)
+ goto error_no_port;
+ if (!try_module_get(serial->type->driver.owner))
+ goto error_module_get;
+
+ retval = usb_autopm_get_interface(serial->interface);
+ if (retval)
+ goto error_get_interface;
/* If the termios setup has yet to be done */
if (tty->driver->termios[idx] == NULL) {
/* perform the standard setup */
retval = tty_init_termios(tty);
if (retval)
- return retval;
+ goto error_init_termios;
/* allow the driver to update it */
- serial = usb_serial_get_by_index(tty->index);
- if (serial) {
- if (serial->type->init_termios)
- serial->type->init_termios(tty);
- usb_serial_put(serial);
- mutex_unlock(&serial->disc_mutex);
- }
+ if (serial->type->init_termios)
+ serial->type->init_termios(tty);
}
+ mutex_unlock(&serial->disc_mutex);
+
+ tty->driver_data = port;
+
/* Final install (we use the default method) */
tty_driver_kref_get(driver);
tty->count++;
driver->ttys[idx] = tty;
- return 0;
+ return retval;
+
+ error_init_termios:
+ usb_autopm_put_interface(serial->interface);
+ error_get_interface:
+ module_put(serial->type->driver.owner);
+ error_module_get:
+ error_no_port:
+ usb_serial_put(serial);
+ mutex_unlock(&serial->disc_mutex);
+ return retval;
}
static int serial_open (struct tty_struct *tty, struct file *filp)
{
struct usb_serial *serial;
struct usb_serial_port *port;
- unsigned int portNumber;
int retval = 0;
int first = 0;
dbg("%s", __func__);
- /* get the serial object associated with this tty pointer */
- serial = usb_serial_get_by_index(tty->index);
- if (!serial) {
- tty->driver_data = NULL;
- return -ENODEV;
- }
-
- portNumber = tty->index - serial->minor;
- port = serial->port[portNumber];
- if (!port || serial->disconnected)
- retval = -ENODEV;
- /*
- * Note: Our locking order requirement does not allow port->mutex
- * to be acquired while serial->disc_mutex is held.
- */
- mutex_unlock(&serial->disc_mutex);
- if (retval)
- goto bailout_serial_put;
+ port = tty->driver_data;
+ serial = port->serial;
- if (mutex_lock_interruptible(&port->mutex)) {
- retval = -ERESTARTSYS;
- goto bailout_serial_put;
- }
+ if (mutex_lock_interruptible(&port->mutex))
+ return -ERESTARTSYS;
++port->port.count;
-
- /* set up our port structure making the tty driver
- * remember our port object, and us it */
- tty->driver_data = port;
tty_port_tty_set(&port->port, tty);
/* If the console is attached, the device is already open */
if (port->port.count == 1 && !port->console) {
first = 1;
- /* lock this module before we call it
- * this may fail, which means we must bail out,
- * safe because we are called with BKL held */
- if (!try_module_get(serial->type->driver.owner)) {
- retval = -ENODEV;
- goto bailout_mutex_unlock;
- }
-
mutex_lock(&serial->disc_mutex);
- if (serial->disconnected)
- retval = -ENODEV;
- else
- retval = usb_autopm_get_interface(serial->interface);
- if (retval)
- goto bailout_module_put;
/* only call the device specific open if this
* is the first time the port is opened */
retval = serial->type->open(tty, port, filp);
if (retval)
- goto bailout_interface_put;
+ goto bailout_module_put;
mutex_unlock(&serial->disc_mutex);
set_bit(ASYNCB_INITIALIZED, &port->port.flags);
}
@@ -297,18 +289,11 @@ static int serial_open (struct tty_struc
goto bailout_mutex_unlock;
/* Undo the initial port actions */
mutex_lock(&serial->disc_mutex);
-bailout_interface_put:
- usb_autopm_put_interface(serial->interface);
bailout_module_put:
mutex_unlock(&serial->disc_mutex);
- module_put(serial->type->driver.owner);
bailout_mutex_unlock:
port->port.count = 0;
- tty->driver_data = NULL;
- tty_port_tty_set(&port->port, NULL);
mutex_unlock(&port->mutex);
-bailout_serial_put:
- usb_serial_put(serial);
return retval;
}
@@ -355,9 +340,6 @@ static void serial_close(struct tty_stru
{
struct usb_serial_port *port = tty->driver_data;
- if (!port)
- return;
-
dbg("%s - port %d", __func__, port->number);
if (tty_port_close_start(&port->port, tty, filp) == 0)
@@ -365,7 +347,6 @@ static void serial_close(struct tty_stru
serial_do_down(port);
tty_port_close_end(&port->port, tty);
tty_port_tty_set(&port->port, NULL);
-
}
/**
@@ -386,9 +367,11 @@ static void serial_do_free(struct tty_st
/* The console is magical. Do not hang up the console hardware
* or there will be tears.
*/
- if (port == NULL || port->console)
+ if (port->console)
return;
+ tty->driver_data = NULL;
+
serial = port->serial;
owner = serial->type->driver.owner;
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Alan Stern <[email protected]>
commit 7e29bb4b779f4f35385e6f21994758845bf14d23 upstream.
This patch (as1288) fixes the initialization logic in
serial_install(). A new tty always needs to have a termios
initialized no matter what, not just in the case where the lower
driver will override the termios settings.
Signed-off-by: Alan Stern <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/serial/usb-serial.c | 22 ++++++++++------------
1 file changed, 10 insertions(+), 12 deletions(-)
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -210,22 +210,21 @@ static int serial_install(struct tty_dri
if (!try_module_get(serial->type->driver.owner))
goto error_module_get;
+ /* perform the standard setup */
+ retval = tty_init_termios(tty);
+ if (retval)
+ goto error_init_termios;
+
retval = usb_autopm_get_interface(serial->interface);
if (retval)
goto error_get_interface;
- /* If the termios setup has yet to be done */
- if (tty->driver->termios[idx] == NULL) {
- /* perform the standard setup */
- retval = tty_init_termios(tty);
- if (retval)
- goto error_init_termios;
- /* allow the driver to update it */
- if (serial->type->init_termios)
- serial->type->init_termios(tty);
- }
mutex_unlock(&serial->disc_mutex);
+ /* allow the driver to update the settings */
+ if (serial->type->init_termios)
+ serial->type->init_termios(tty);
+
tty->driver_data = port;
/* Final install (we use the default method) */
@@ -234,9 +233,8 @@ static int serial_install(struct tty_dri
driver->ttys[idx] = tty;
return retval;
- error_init_termios:
- usb_autopm_put_interface(serial->interface);
error_get_interface:
+ error_init_termios:
module_put(serial->type->driver.owner);
error_module_get:
error_no_port:
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Alan Stern <[email protected]>
commit 74556123e034c8337b69a3ebac2f3a5fc0a97032 upstream.
This patch (as1289) renames serial_do_down() to serial_down() and
serial_do_free() to serial_release(). It also adds a missing call to
tty_shutdown() in serial_release().
Signed-off-by: Alan Stern <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/serial/usb-serial.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -191,7 +191,7 @@ void usb_serial_put(struct usb_serial *s
* This is the first place a new tty gets used. Hence this is where we
* acquire references to the usb_serial structure and the driver module,
* where we store a pointer to the port, and where we do an autoresume.
- * All these actions are reversed in serial_do_free().
+ * All these actions are reversed in serial_release().
*/
static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
{
@@ -296,13 +296,13 @@ bailout_mutex_unlock:
}
/**
- * serial_do_down - shut down hardware
+ * serial_down - shut down hardware
* @port: port to shut down
*
* Shut down a USB serial port unless it is the console. We never
* shut down the console hardware as it will always be in use.
*/
-static void serial_do_down(struct usb_serial_port *port)
+static void serial_down(struct usb_serial_port *port)
{
struct usb_serial_driver *drv = port->serial->type;
struct usb_serial *serial;
@@ -328,7 +328,7 @@ static void serial_do_down(struct usb_se
static void serial_hangup(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
- serial_do_down(port);
+ serial_down(port);
tty_port_hangup(&port->port);
/* We must not free port yet - the USB serial layer depends on it's
continued existence */
@@ -342,13 +342,13 @@ static void serial_close(struct tty_stru
if (tty_port_close_start(&port->port, tty, filp) == 0)
return;
- serial_do_down(port);
+ serial_down(port);
tty_port_close_end(&port->port, tty);
tty_port_tty_set(&port->port, NULL);
}
/**
- * serial_do_free - free resources post close/hangup
+ * serial_release - free resources post close/hangup
* @port: port to free up
*
* Do the resource freeing and refcount dropping for the port.
@@ -356,7 +356,7 @@ static void serial_close(struct tty_stru
*
* Called when the last tty kref is dropped.
*/
-static void serial_do_free(struct tty_struct *tty)
+static void serial_release(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial;
@@ -368,6 +368,9 @@ static void serial_do_free(struct tty_st
if (port->console)
return;
+ /* Standard shutdown processing */
+ tty_shutdown(tty);
+
tty->driver_data = NULL;
serial = port->serial;
@@ -1204,7 +1207,7 @@ static const struct tty_operations seria
.chars_in_buffer = serial_chars_in_buffer,
.tiocmget = serial_tiocmget,
.tiocmset = serial_tiocmset,
- .shutdown = serial_do_free,
+ .shutdown = serial_release,
.install = serial_install,
.proc_fops = &serial_proc_fops,
};
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Alan Stern <[email protected]>
commit ff8324df1187b7280e507c976777df76c73a1ef1 upstream.
This patch (as1290) adds some missing tests. serial_down() isn't
supposed to do anything if the hardware hasn't been initialized, and
serial_close() isn't supposed to do anything if the tty has gotten a
hangup (because serial_hangup() takes care of shutting down the
hardware).
The patch also updates and adds a few debugging lines.
Signed-off-by: Alan Stern <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/serial/usb-serial.c | 21 +++++++++++++++++----
1 file changed, 17 insertions(+), 4 deletions(-)
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -200,6 +200,8 @@ static int serial_install(struct tty_dri
struct usb_serial_port *port;
int retval = -ENODEV;
+ dbg("%s", __func__);
+
serial = usb_serial_get_by_index(idx);
if (!serial)
return retval;
@@ -250,11 +252,11 @@ static int serial_open (struct tty_struc
int retval = 0;
int first = 0;
- dbg("%s", __func__);
-
port = tty->driver_data;
serial = port->serial;
+ dbg("%s - port %d", __func__, port->number);
+
if (mutex_lock_interruptible(&port->mutex))
return -ERESTARTSYS;
@@ -315,6 +317,12 @@ static void serial_down(struct usb_seria
if (port->console)
return;
+ /* Don't call the close method if the hardware hasn't been
+ * initialized.
+ */
+ if (!test_and_clear_bit(ASYNCB_INITIALIZED, &port->port.flags))
+ return;
+
mutex_lock(&port->mutex);
serial = port->serial;
owner = serial->type->driver.owner;
@@ -328,10 +336,11 @@ static void serial_down(struct usb_seria
static void serial_hangup(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
+
+ dbg("%s - port %d", __func__, port->number);
+
serial_down(port);
tty_port_hangup(&port->port);
- /* We must not free port yet - the USB serial layer depends on it's
- continued existence */
}
static void serial_close(struct tty_struct *tty, struct file *filp)
@@ -340,6 +349,8 @@ static void serial_close(struct tty_stru
dbg("%s - port %d", __func__, port->number);
+ if (tty_hung_up_p(filp))
+ return;
if (tty_port_close_start(&port->port, tty, filp) == 0)
return;
serial_down(port);
@@ -368,6 +379,8 @@ static void serial_release(struct tty_st
if (port->console)
return;
+ dbg("%s - port %d", __func__, port->number);
+
/* Standard shutdown processing */
tty_shutdown(tty);
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Alan Stern <[email protected]>
commit 320348c8d5c9b591282633ddb8959b42f7fc7a1c upstream.
This patch (as1291) removes a bunch of code from serial_open(), things
that were rendered unnecessary by earlier patches. A missing spinlock
is added to protect port->port.count, which needs to be incremented
even if the open fails but not if the tty has gotten a hangup. The
test for whether the hardware has been initialized, based on the use
count, is replaced by a more transparent test of the
ASYNCB_INITIALIZED bit in the port flags.
Signed-off-by: Alan Stern <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/serial/usb-serial.c | 59 ++++++++++++++--------------------------
1 file changed, 22 insertions(+), 37 deletions(-)
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -245,55 +245,40 @@ static int serial_install(struct tty_dri
return retval;
}
-static int serial_open (struct tty_struct *tty, struct file *filp)
+static int serial_open(struct tty_struct *tty, struct file *filp)
{
- struct usb_serial *serial;
- struct usb_serial_port *port;
- int retval = 0;
- int first = 0;
-
- port = tty->driver_data;
- serial = port->serial;
+ struct usb_serial_port *port = tty->driver_data;
+ struct usb_serial *serial = port->serial;
+ int retval;
dbg("%s - port %d", __func__, port->number);
- if (mutex_lock_interruptible(&port->mutex))
- return -ERESTARTSYS;
-
- ++port->port.count;
+ spin_lock_irq(&port->port.lock);
+ if (!tty_hung_up_p(filp))
+ ++port->port.count;
+ spin_unlock_irq(&port->port.lock);
tty_port_tty_set(&port->port, tty);
- /* If the console is attached, the device is already open */
- if (port->port.count == 1 && !port->console) {
- first = 1;
+ /* Do the device-specific open only if the hardware isn't
+ * already initialized.
+ */
+ if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) {
+ if (mutex_lock_interruptible(&port->mutex))
+ return -ERESTARTSYS;
mutex_lock(&serial->disc_mutex);
-
- /* only call the device specific open if this
- * is the first time the port is opened */
- retval = serial->type->open(tty, port, filp);
- if (retval)
- goto bailout_module_put;
+ if (serial->disconnected)
+ retval = -ENODEV;
+ else
+ retval = port->serial->type->open(tty, port, flip);
mutex_unlock(&serial->disc_mutex);
+ mutex_unlock(&port->mutex);
+ if (retval)
+ return retval;
set_bit(ASYNCB_INITIALIZED, &port->port.flags);
}
- mutex_unlock(&port->mutex);
+
/* Now do the correct tty layer semantics */
retval = tty_port_block_til_ready(&port->port, tty, filp);
- if (retval == 0) {
- if (!first)
- usb_serial_put(serial);
- return 0;
- }
- mutex_lock(&port->mutex);
- if (first == 0)
- goto bailout_mutex_unlock;
- /* Undo the initial port actions */
- mutex_lock(&serial->disc_mutex);
-bailout_module_put:
- mutex_unlock(&serial->disc_mutex);
-bailout_mutex_unlock:
- port->port.count = 0;
- mutex_unlock(&port->mutex);
return retval;
}
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Alan Stern <[email protected]>
commit 7bd032dc2793afcbaf4a350056768da84cdbd89b upstream.
This patch (as1292) modifies the USB serial console driver, to make it
compatible with the recent changes to the USB serial core. The most
important change is that serial->disc_mutex now has to be unlocked
following a successful call to usb_serial_get_by_index().
Other less notable changes include:
Use the requested port number instead of port 0 always.
Prevent the serial device from being autosuspended.
Use the ASYNCB_INITIALIZED flag bit to indicate when the
port hardware has been initialized.
In spite of these changes, there's no question that the USB serial
console code is still a big hack.
Signed-off-by: Alan Stern <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/serial/console.c | 28 +++++++++++++++++++---------
1 file changed, 19 insertions(+), 9 deletions(-)
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/console.h>
+#include <linux/serial.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
@@ -63,7 +64,7 @@ static int usb_console_setup(struct cons
char *s;
struct usb_serial *serial;
struct usb_serial_port *port;
- int retval = 0;
+ int retval;
struct tty_struct *tty = NULL;
struct ktermios *termios = NULL, dummy;
@@ -116,13 +117,17 @@ static int usb_console_setup(struct cons
return -ENODEV;
}
- port = serial->port[0];
+ retval = usb_autopm_get_interface(serial->interface);
+ if (retval)
+ goto error_get_interface;
+
+ port = serial->port[co->index - serial->minor];
tty_port_tty_set(&port->port, NULL);
info->port = port;
++port->port.count;
- if (port->port.count == 1) {
+ if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) {
if (serial->type->set_termios) {
/*
* allocate a fake tty so the driver can initialize
@@ -168,6 +173,7 @@ static int usb_console_setup(struct cons
kfree(termios);
kfree(tty);
}
+ set_bit(ASYNCB_INITIALIZED, &port->port.flags);
}
/* Now that any required fake tty operations are completed restore
* the tty port count */
@@ -175,18 +181,22 @@ static int usb_console_setup(struct cons
/* The console is special in terms of closing the device so
* indicate this port is now acting as a system console. */
port->console = 1;
- retval = 0;
-out:
+ mutex_unlock(&serial->disc_mutex);
return retval;
-free_termios:
+
+ free_termios:
kfree(termios);
tty_port_tty_set(&port->port, NULL);
-free_tty:
+ free_tty:
kfree(tty);
-reset_open_count:
+ reset_open_count:
port->port.count = 0;
- goto out;
+ usb_autopm_put_interface(serial->interface);
+ error_get_interface:
+ usb_serial_put(serial);
+ mutex_unlock(&serial->disc_mutex);
+ return retval;
}
static void usb_console_write(struct console *co,
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Sarah Sharp <[email protected]>
commit b0567b3f635db72c881a0d561cebb544ec085073 upstream.
Different sections of the xHCI 0.95 specification had opposing
requirements for the chain bit in a link transaction request buffer (TRB).
The chain bit is used to designate that adjacent TRBs are all part of the
same scatter gather list that should be sent to the device. Link TRBs can
be in the middle, or at the beginning or end of these chained TRBs.
Sections 4.11.5.1 and 6.4.4.1 both stated the link TRB "shall have the
chain bit set to 1", meaning it is always chained to the next TRB.
However, section 4.6.9 on the stop endpoint command has specific cases for
what the hardware must do for a link TRB with the chain bit set to 0. The
0.96 specification errata later cleared up this issue by fixing the
4.11.5.1 and 6.4.4.1 sections to state that a link TRB can have the chain
bit set to 1 or 0.
The problem is that the xHCI cancellation code depends on the chain bit of
the link TRB being cleared when it's at the end of a TD, and some 0.95
xHCI hardware simply stops processing the ring when it encounters a link
TRB with the chain bit cleared.
Allow users who are testing 0.95 xHCI prototypes to set a module parameter
(link_quirk) to turn on this link TRB work around. Cancellation may not
work if the ring is stopped exactly on a link TRB with chain bit set, but
cancellation should be a relatively uncommon case.
Signed-off-by: Sarah Sharp <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/host/xhci-hcd.c | 12 ++++++++++++
drivers/usb/host/xhci-mem.c | 3 +++
drivers/usb/host/xhci-ring.c | 15 +++++++++++----
drivers/usb/host/xhci.h | 9 +++++++++
4 files changed, 35 insertions(+), 4 deletions(-)
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1058,6 +1058,8 @@ struct xhci_hcd {
int noops_submitted;
int noops_handled;
int error_bitmask;
+ unsigned int quirks;
+#define XHCI_LINK_TRB_QUIRK (1 << 0)
};
/* For testing purposes */
@@ -1136,6 +1138,13 @@ static inline void xhci_write_64(struct
writel(val_hi, ptr + 1);
}
+static inline int xhci_link_trb_quirk(struct xhci_hcd *xhci)
+{
+ u32 temp = xhci_readl(xhci, &xhci->cap_regs->hc_capbase);
+ return ((HC_VERSION(temp) == 0x95) &&
+ (xhci->quirks & XHCI_LINK_TRB_QUIRK));
+}
+
/* xHCI debugging */
void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int set_num);
void xhci_print_registers(struct xhci_hcd *xhci);
--- a/drivers/usb/host/xhci-hcd.c
+++ b/drivers/usb/host/xhci-hcd.c
@@ -22,12 +22,18 @@
#include <linux/irq.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include "xhci.h"
#define DRIVER_AUTHOR "Sarah Sharp"
#define DRIVER_DESC "'eXtensible' Host Controller (xHC) Driver"
+/* Some 0.95 hardware can't handle the chain bit on a Link TRB being cleared */
+static int link_quirk;
+module_param(link_quirk, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB");
+
/* TODO: copied from ehci-hcd.c - can this be refactored? */
/*
* handshake - spin reading hc until handshake completes or fails
@@ -214,6 +220,12 @@ int xhci_init(struct usb_hcd *hcd)
xhci_dbg(xhci, "xhci_init\n");
spin_lock_init(&xhci->lock);
+ if (link_quirk) {
+ xhci_dbg(xhci, "QUIRK: Not clearing Link TRB chain bits.\n");
+ xhci->quirks |= XHCI_LINK_TRB_QUIRK;
+ } else {
+ xhci_dbg(xhci, "xHCI has no QUIRKS\n");
+ }
retval = xhci_mem_init(xhci, GFP_KERNEL);
xhci_dbg(xhci, "Finished xhci_init\n");
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -94,6 +94,9 @@ static void xhci_link_segments(struct xh
val = prev->trbs[TRBS_PER_SEGMENT-1].link.control;
val &= ~TRB_TYPE_BITMASK;
val |= TRB_TYPE(TRB_LINK);
+ /* Always set the chain bit with 0.95 hardware */
+ if (xhci_link_trb_quirk(xhci))
+ val |= TRB_CHAIN;
prev->trbs[TRBS_PER_SEGMENT-1].link.control = val;
}
xhci_dbg(xhci, "Linking segment 0x%llx to segment 0x%llx (DMA)\n",
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -172,8 +172,9 @@ static void inc_deq(struct xhci_hcd *xhc
* have their chain bit cleared (so that each Link TRB is a separate TD).
*
* Section 6.4.4.1 of the 0.95 spec says link TRBs cannot have the chain bit
- * set, but other sections talk about dealing with the chain bit set.
- * Assume section 6.4.4.1 is wrong, and the chain bit can be set in a Link TRB.
+ * set, but other sections talk about dealing with the chain bit set. This was
+ * fixed in the 0.96 specification errata, but we have to assume that all 0.95
+ * xHCI hardware can't handle the chain bit being cleared on a link TRB.
*/
static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer)
{
@@ -191,8 +192,14 @@ static void inc_enq(struct xhci_hcd *xhc
while (last_trb(xhci, ring, ring->enq_seg, next)) {
if (!consumer) {
if (ring != xhci->event_ring) {
- next->link.control &= ~TRB_CHAIN;
- next->link.control |= chain;
+ /* If we're not dealing with 0.95 hardware,
+ * carry over the chain bit of the previous TRB
+ * (which may mean the chain bit is cleared).
+ */
+ if (!xhci_link_trb_quirk(xhci)) {
+ next->link.control &= ~TRB_CHAIN;
+ next->link.control |= chain;
+ }
/* Give this link TRB to the hardware */
wmb();
if (next->link.control & TRB_CYCLE)
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Sarah Sharp <[email protected]>
commit 018218d1d9eb06116d24a02dd5e7a390f0353d0f upstream.
Use the virtual address of the memory hardware uses, not the address for
the container of that memory.
Signed-off-by: Sarah Sharp <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/host/xhci-dbg.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
--- a/drivers/usb/host/xhci-dbg.c
+++ b/drivers/usb/host/xhci-dbg.c
@@ -413,7 +413,8 @@ void xhci_dbg_slot_ctx(struct xhci_hcd *
int i;
struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx);
- dma_addr_t dma = ctx->dma + ((unsigned long)slot_ctx - (unsigned long)ctx);
+ dma_addr_t dma = ctx->dma +
+ ((unsigned long)slot_ctx - (unsigned long)ctx->bytes);
int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params);
xhci_dbg(xhci, "Slot Context:\n");
@@ -459,7 +460,7 @@ void xhci_dbg_ep_ctx(struct xhci_hcd *xh
for (i = 0; i < last_ep_ctx; ++i) {
struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, ctx, i);
dma_addr_t dma = ctx->dma +
- ((unsigned long)ep_ctx - (unsigned long)ctx);
+ ((unsigned long)ep_ctx - (unsigned long)ctx->bytes);
xhci_dbg(xhci, "Endpoint %02d Context:\n", i);
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info\n",
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Sarah Sharp <[email protected]>
commit f2217e8edd95b0428d8123d426e0097a5e955f9f upstream.
Refactor out the code issue, wait for, and parse the event completion code
for a configure endpoint command. Modify it to support the evaluate
context command, which has a very similar submission process. Add
functions to copy parts of the output context into the input context
(which will be used in the evaluate context command).
Signed-off-by: Sarah Sharp <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/host/xhci-hcd.c | 169 +++++++++++++++++++++++++++++--------------
drivers/usb/host/xhci-mem.c | 38 +++++++++
drivers/usb/host/xhci-ring.c | 9 ++
drivers/usb/host/xhci.h | 5 +
4 files changed, 169 insertions(+), 52 deletions(-)
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1168,6 +1168,9 @@ int xhci_setup_addressable_virt_dev(stru
unsigned int xhci_get_endpoint_index(struct usb_endpoint_descriptor *desc);
unsigned int xhci_get_endpoint_flag(struct usb_endpoint_descriptor *desc);
void xhci_endpoint_zero(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, struct usb_host_endpoint *ep);
+void xhci_endpoint_copy(struct xhci_hcd *xhci,
+ struct xhci_virt_device *vdev, unsigned int ep_index);
+void xhci_slot_copy(struct xhci_hcd *xhci, struct xhci_virt_device *vdev);
int xhci_endpoint_init(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev,
struct usb_device *udev, struct usb_host_endpoint *ep,
gfp_t mem_flags);
@@ -1216,6 +1219,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
int slot_id, unsigned int ep_index);
int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
u32 slot_id);
+int xhci_queue_evaluate_context(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
+ u32 slot_id);
int xhci_queue_reset_ep(struct xhci_hcd *xhci, int slot_id,
unsigned int ep_index);
void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
--- a/drivers/usb/host/xhci-hcd.c
+++ b/drivers/usb/host/xhci-hcd.c
@@ -942,6 +942,122 @@ static void xhci_zero_in_ctx(struct xhci
}
}
+static int xhci_configure_endpoint_result(struct xhci_hcd *xhci,
+ struct usb_device *udev, struct xhci_virt_device *virt_dev)
+{
+ int ret;
+
+ switch (virt_dev->cmd_status) {
+ case COMP_ENOMEM:
+ dev_warn(&udev->dev, "Not enough host controller resources "
+ "for new device state.\n");
+ ret = -ENOMEM;
+ /* FIXME: can we allocate more resources for the HC? */
+ break;
+ case COMP_BW_ERR:
+ dev_warn(&udev->dev, "Not enough bandwidth "
+ "for new device state.\n");
+ ret = -ENOSPC;
+ /* FIXME: can we go back to the old state? */
+ break;
+ case COMP_TRB_ERR:
+ /* the HCD set up something wrong */
+ dev_warn(&udev->dev, "ERROR: Endpoint drop flag = 0, "
+ "add flag = 1, "
+ "and endpoint is not disabled.\n");
+ ret = -EINVAL;
+ break;
+ case COMP_SUCCESS:
+ dev_dbg(&udev->dev, "Successful Endpoint Configure command\n");
+ ret = 0;
+ break;
+ default:
+ xhci_err(xhci, "ERROR: unexpected command completion "
+ "code 0x%x.\n", virt_dev->cmd_status);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int xhci_evaluate_context_result(struct xhci_hcd *xhci,
+ struct usb_device *udev, struct xhci_virt_device *virt_dev)
+{
+ int ret;
+
+ switch (virt_dev->cmd_status) {
+ case COMP_EINVAL:
+ dev_warn(&udev->dev, "WARN: xHCI driver setup invalid evaluate "
+ "context command.\n");
+ ret = -EINVAL;
+ break;
+ case COMP_EBADSLT:
+ dev_warn(&udev->dev, "WARN: slot not enabled for"
+ "evaluate context command.\n");
+ case COMP_CTX_STATE:
+ dev_warn(&udev->dev, "WARN: invalid context state for "
+ "evaluate context command.\n");
+ xhci_dbg_ctx(xhci, virt_dev->out_ctx, 1);
+ ret = -EINVAL;
+ break;
+ case COMP_SUCCESS:
+ dev_dbg(&udev->dev, "Successful evaluate context command\n");
+ ret = 0;
+ break;
+ default:
+ xhci_err(xhci, "ERROR: unexpected command completion "
+ "code 0x%x.\n", virt_dev->cmd_status);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+/* Issue a configure endpoint command or evaluate context command
+ * and wait for it to finish.
+ */
+static int xhci_configure_endpoint(struct xhci_hcd *xhci,
+ struct usb_device *udev, struct xhci_virt_device *virt_dev,
+ bool ctx_change)
+{
+ int ret;
+ int timeleft;
+ unsigned long flags;
+
+ spin_lock_irqsave(&xhci->lock, flags);
+ if (!ctx_change)
+ ret = xhci_queue_configure_endpoint(xhci, virt_dev->in_ctx->dma,
+ udev->slot_id);
+ else
+ ret = xhci_queue_evaluate_context(xhci, virt_dev->in_ctx->dma,
+ udev->slot_id);
+ if (ret < 0) {
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ xhci_dbg(xhci, "FIXME allocate a new ring segment\n");
+ return -ENOMEM;
+ }
+ xhci_ring_cmd_db(xhci);
+ spin_unlock_irqrestore(&xhci->lock, flags);
+
+ /* Wait for the configure endpoint command to complete */
+ timeleft = wait_for_completion_interruptible_timeout(
+ &virt_dev->cmd_completion,
+ USB_CTRL_SET_TIMEOUT);
+ if (timeleft <= 0) {
+ xhci_warn(xhci, "%s while waiting for %s command\n",
+ timeleft == 0 ? "Timeout" : "Signal",
+ ctx_change == 0 ?
+ "configure endpoint" :
+ "evaluate context");
+ /* FIXME cancel the configure endpoint command */
+ return -ETIME;
+ }
+
+ if (!ctx_change)
+ return xhci_configure_endpoint_result(xhci, udev, virt_dev);
+ return xhci_evaluate_context_result(xhci, udev, virt_dev);
+}
+
/* Called after one or more calls to xhci_add_endpoint() or
* xhci_drop_endpoint(). If this call fails, the USB core is expected
* to call xhci_reset_bandwidth().
@@ -956,8 +1072,6 @@ int xhci_check_bandwidth(struct usb_hcd
{
int i;
int ret = 0;
- int timeleft;
- unsigned long flags;
struct xhci_hcd *xhci;
struct xhci_virt_device *virt_dev;
struct xhci_input_control_ctx *ctrl_ctx;
@@ -987,56 +1101,7 @@ int xhci_check_bandwidth(struct usb_hcd
xhci_dbg_ctx(xhci, virt_dev->in_ctx,
LAST_CTX_TO_EP_NUM(slot_ctx->dev_info));
- spin_lock_irqsave(&xhci->lock, flags);
- ret = xhci_queue_configure_endpoint(xhci, virt_dev->in_ctx->dma,
- udev->slot_id);
- if (ret < 0) {
- spin_unlock_irqrestore(&xhci->lock, flags);
- xhci_dbg(xhci, "FIXME allocate a new ring segment\n");
- return -ENOMEM;
- }
- xhci_ring_cmd_db(xhci);
- spin_unlock_irqrestore(&xhci->lock, flags);
-
- /* Wait for the configure endpoint command to complete */
- timeleft = wait_for_completion_interruptible_timeout(
- &virt_dev->cmd_completion,
- USB_CTRL_SET_TIMEOUT);
- if (timeleft <= 0) {
- xhci_warn(xhci, "%s while waiting for configure endpoint command\n",
- timeleft == 0 ? "Timeout" : "Signal");
- /* FIXME cancel the configure endpoint command */
- return -ETIME;
- }
-
- switch (virt_dev->cmd_status) {
- case COMP_ENOMEM:
- dev_warn(&udev->dev, "Not enough host controller resources "
- "for new device state.\n");
- ret = -ENOMEM;
- /* FIXME: can we allocate more resources for the HC? */
- break;
- case COMP_BW_ERR:
- dev_warn(&udev->dev, "Not enough bandwidth "
- "for new device state.\n");
- ret = -ENOSPC;
- /* FIXME: can we go back to the old state? */
- break;
- case COMP_TRB_ERR:
- /* the HCD set up something wrong */
- dev_warn(&udev->dev, "ERROR: Endpoint drop flag = 0, add flag = 1, "
- "and endpoint is not disabled.\n");
- ret = -EINVAL;
- break;
- case COMP_SUCCESS:
- dev_dbg(&udev->dev, "Successful Endpoint Configure command\n");
- break;
- default:
- xhci_err(xhci, "ERROR: unexpected command completion "
- "code 0x%x.\n", virt_dev->cmd_status);
- ret = -EINVAL;
- break;
- }
+ ret = xhci_configure_endpoint(xhci, udev, virt_dev, false);
if (ret) {
/* Callee should call reset_bandwidth() */
return ret;
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -601,6 +601,44 @@ void xhci_endpoint_zero(struct xhci_hcd
*/
}
+/* Copy output xhci_ep_ctx to the input xhci_ep_ctx copy.
+ * Useful when you want to change one particular aspect of the endpoint and then
+ * issue a configure endpoint command.
+ */
+void xhci_endpoint_copy(struct xhci_hcd *xhci,
+ struct xhci_virt_device *vdev, unsigned int ep_index)
+{
+ struct xhci_ep_ctx *out_ep_ctx;
+ struct xhci_ep_ctx *in_ep_ctx;
+
+ out_ep_ctx = xhci_get_ep_ctx(xhci, vdev->out_ctx, ep_index);
+ in_ep_ctx = xhci_get_ep_ctx(xhci, vdev->in_ctx, ep_index);
+
+ in_ep_ctx->ep_info = out_ep_ctx->ep_info;
+ in_ep_ctx->ep_info2 = out_ep_ctx->ep_info2;
+ in_ep_ctx->deq = out_ep_ctx->deq;
+ in_ep_ctx->tx_info = out_ep_ctx->tx_info;
+}
+
+/* Copy output xhci_slot_ctx to the input xhci_slot_ctx.
+ * Useful when you want to change one particular aspect of the endpoint and then
+ * issue a configure endpoint command. Only the context entries field matters,
+ * but we'll copy the whole thing anyway.
+ */
+void xhci_slot_copy(struct xhci_hcd *xhci, struct xhci_virt_device *vdev)
+{
+ struct xhci_slot_ctx *in_slot_ctx;
+ struct xhci_slot_ctx *out_slot_ctx;
+
+ in_slot_ctx = xhci_get_slot_ctx(xhci, vdev->in_ctx);
+ out_slot_ctx = xhci_get_slot_ctx(xhci, vdev->out_ctx);
+
+ in_slot_ctx->dev_info = out_slot_ctx->dev_info;
+ in_slot_ctx->dev_info2 = out_slot_ctx->dev_info2;
+ in_slot_ctx->tt_info = out_slot_ctx->tt_info;
+ in_slot_ctx->dev_state = out_slot_ctx->dev_state;
+}
+
/* Set up the scratchpad buffer array and scratchpad buffers, if needed. */
static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags)
{
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1740,6 +1740,15 @@ int xhci_queue_configure_endpoint(struct
TRB_TYPE(TRB_CONFIG_EP) | SLOT_ID_FOR_TRB(slot_id));
}
+/* Queue an evaluate context command TRB */
+int xhci_queue_evaluate_context(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
+ u32 slot_id)
+{
+ return queue_command(xhci, lower_32_bits(in_ctx_ptr),
+ upper_32_bits(in_ctx_ptr), 0,
+ TRB_TYPE(TRB_EVAL_CONTEXT) | SLOT_ID_FOR_TRB(slot_id));
+}
+
int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id,
unsigned int ep_index)
{
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Sarah Sharp <[email protected]>
commit 47aded8ade9fee6779b121b2b156235f261239d7 upstream.
Set the max packet size for the default control endpoint on high speed
devices to be 64 bytes. High speed devices always have a max packet size
of 64 bytes. There's no use setting it to eight for the initial 8 byte
descriptor fetch and then issuing (and waiting for) an evaluate context
command to update it to 64 bytes for the subsequent control transfers.
The USB core guesses that the max packet size on a full speed control
endpoint is 64 bytes, and then updates it after the first 8-byte
descriptor fetch. Change the initial setup for the xHCI internal
representation of the full speed device to have a 64 byte max packet size.
Signed-off-by: Sarah Sharp <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/host/xhci-mem.c | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -401,15 +401,28 @@ int xhci_setup_addressable_virt_dev(stru
/* Step 5 */
ep0_ctx->ep_info2 = EP_TYPE(CTRL_EP);
/*
- * See section 4.3 bullet 6:
- * The default Max Packet size for ep0 is "8 bytes for a USB2
- * LS/FS/HS device or 512 bytes for a USB3 SS device"
* XXX: Not sure about wireless USB devices.
*/
- if (udev->speed == USB_SPEED_SUPER)
+ switch (udev->speed) {
+ case USB_SPEED_SUPER:
ep0_ctx->ep_info2 |= MAX_PACKET(512);
- else
+ break;
+ case USB_SPEED_HIGH:
+ /* USB core guesses at a 64-byte max packet first for FS devices */
+ case USB_SPEED_FULL:
+ ep0_ctx->ep_info2 |= MAX_PACKET(64);
+ break;
+ case USB_SPEED_LOW:
ep0_ctx->ep_info2 |= MAX_PACKET(8);
+ break;
+ case USB_SPEED_VARIABLE:
+ xhci_dbg(xhci, "FIXME xHCI doesn't support wireless speeds\n");
+ return -EINVAL;
+ break;
+ default:
+ /* New speed? */
+ BUG();
+ }
/* EP 0 can handle "burst" sizes of 1, so Max Burst Size field is 0 */
ep0_ctx->ep_info2 |= MAX_BURST(0);
ep0_ctx->ep_info2 |= ERROR_COUNT(3);
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Sarah Sharp <[email protected]>
commit 2d3f1fac7ee8bb4c6fad40f838488edbeabb0c50 upstream.
Full speed devices have varying max packet sizes (8, 16, 32, or 64) for
endpoint 0. The xHCI hardware needs to know the real max packet size
that the USB core discovers after it fetches the first 8 bytes of the
device descriptor.
In order to fix this without adding a new hook to host controller drivers,
the xHCI driver looks for an updated max packet size for control
endpoints. If it finds an updated size, it issues an evaluate context
command and waits for that command to finish. This should only happen in
the initialization and device descriptor fetching steps in the khubd
thread, so blocking should be fine.
Signed-off-by: Sarah Sharp <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/host/xhci-hcd.c | 88 ++++++++++++++++++++++++++++++++++++++++---
drivers/usb/host/xhci-ring.c | 4 +
drivers/usb/host/xhci.h | 2
3 files changed, 89 insertions(+), 5 deletions(-)
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -601,6 +601,8 @@ struct xhci_ep_ctx {
/* bit 7 is Host Initiate Disable - for disabling stream selection */
#define MAX_BURST(p) (((p)&0xff) << 8)
#define MAX_PACKET(p) (((p)&0xffff) << 16)
+#define MAX_PACKET_MASK (0xffff << 16)
+#define MAX_PACKET_DECODED(p) (((p) >> 16) & 0xffff)
/**
--- a/drivers/usb/host/xhci-hcd.c
+++ b/drivers/usb/host/xhci-hcd.c
@@ -601,6 +601,70 @@ int xhci_check_args(struct usb_hcd *hcd,
return 1;
}
+static int xhci_configure_endpoint(struct xhci_hcd *xhci,
+ struct usb_device *udev, struct xhci_virt_device *virt_dev,
+ bool ctx_change);
+
+/*
+ * Full speed devices may have a max packet size greater than 8 bytes, but the
+ * USB core doesn't know that until it reads the first 8 bytes of the
+ * descriptor. If the usb_device's max packet size changes after that point,
+ * we need to issue an evaluate context command and wait on it.
+ */
+static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
+ unsigned int ep_index, struct urb *urb)
+{
+ struct xhci_container_ctx *in_ctx;
+ struct xhci_container_ctx *out_ctx;
+ struct xhci_input_control_ctx *ctrl_ctx;
+ struct xhci_ep_ctx *ep_ctx;
+ int max_packet_size;
+ int hw_max_packet_size;
+ int ret = 0;
+
+ out_ctx = xhci->devs[slot_id]->out_ctx;
+ ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);
+ hw_max_packet_size = MAX_PACKET_DECODED(ep_ctx->ep_info2);
+ max_packet_size = urb->dev->ep0.desc.wMaxPacketSize;
+ if (hw_max_packet_size != max_packet_size) {
+ xhci_dbg(xhci, "Max Packet Size for ep 0 changed.\n");
+ xhci_dbg(xhci, "Max packet size in usb_device = %d\n",
+ max_packet_size);
+ xhci_dbg(xhci, "Max packet size in xHCI HW = %d\n",
+ hw_max_packet_size);
+ xhci_dbg(xhci, "Issuing evaluate context command.\n");
+
+ /* Set up the modified control endpoint 0 */
+ xhci_endpoint_copy(xhci, xhci->devs[slot_id], ep_index);
+ in_ctx = xhci->devs[slot_id]->in_ctx;
+ ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index);
+ ep_ctx->ep_info2 &= ~MAX_PACKET_MASK;
+ ep_ctx->ep_info2 |= MAX_PACKET(max_packet_size);
+
+ /* Set up the input context flags for the command */
+ /* FIXME: This won't work if a non-default control endpoint
+ * changes max packet sizes.
+ */
+ ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
+ ctrl_ctx->add_flags = EP0_FLAG;
+ ctrl_ctx->drop_flags = 0;
+
+ xhci_dbg(xhci, "Slot %d input context\n", slot_id);
+ xhci_dbg_ctx(xhci, in_ctx, ep_index);
+ xhci_dbg(xhci, "Slot %d output context\n", slot_id);
+ xhci_dbg_ctx(xhci, out_ctx, ep_index);
+
+ ret = xhci_configure_endpoint(xhci, urb->dev,
+ xhci->devs[slot_id], true);
+
+ /* Clean up the input context for later use by bandwidth
+ * functions.
+ */
+ ctrl_ctx->add_flags = SLOT_FLAG;
+ }
+ return ret;
+}
+
/*
* non-error returns are a promise to giveback() the urb later
* we drop ownership so next owner (or urb unlink) can get it
@@ -612,13 +676,13 @@ int xhci_urb_enqueue(struct usb_hcd *hcd
int ret = 0;
unsigned int slot_id, ep_index;
+
if (!urb || xhci_check_args(hcd, urb->dev, urb->ep, true, __func__) <= 0)
return -EINVAL;
slot_id = urb->dev->slot_id;
ep_index = xhci_get_endpoint_index(&urb->ep->desc);
- spin_lock_irqsave(&xhci->lock, flags);
if (!xhci->devs || !xhci->devs[slot_id]) {
if (!in_interrupt())
dev_warn(&urb->dev->dev, "WARN: urb submitted for dev with no Slot ID\n");
@@ -631,19 +695,33 @@ int xhci_urb_enqueue(struct usb_hcd *hcd
ret = -ESHUTDOWN;
goto exit;
}
- if (usb_endpoint_xfer_control(&urb->ep->desc))
+ if (usb_endpoint_xfer_control(&urb->ep->desc)) {
+ /* Check to see if the max packet size for the default control
+ * endpoint changed during FS device enumeration
+ */
+ if (urb->dev->speed == USB_SPEED_FULL) {
+ ret = xhci_check_maxpacket(xhci, slot_id,
+ ep_index, urb);
+ if (ret < 0)
+ return ret;
+ }
+
/* We have a spinlock and interrupts disabled, so we must pass
* atomic context to this function, which may allocate memory.
*/
+ spin_lock_irqsave(&xhci->lock, flags);
ret = xhci_queue_ctrl_tx(xhci, GFP_ATOMIC, urb,
slot_id, ep_index);
- else if (usb_endpoint_xfer_bulk(&urb->ep->desc))
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ } else if (usb_endpoint_xfer_bulk(&urb->ep->desc)) {
+ spin_lock_irqsave(&xhci->lock, flags);
ret = xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb,
slot_id, ep_index);
- else
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ } else {
ret = -EINVAL;
+ }
exit:
- spin_unlock_irqrestore(&xhci->lock, flags);
return ret;
}
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -701,6 +701,10 @@ static void handle_cmd_completion(struct
xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status);
complete(&xhci->devs[slot_id]->cmd_completion);
break;
+ case TRB_TYPE(TRB_EVAL_CONTEXT):
+ xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status);
+ complete(&xhci->devs[slot_id]->cmd_completion);
+ break;
case TRB_TYPE(TRB_ADDR_DEV):
xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status);
complete(&xhci->addr_dev);
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Sarah Sharp <[email protected]>
commit 82d1009f537c2a43be0a410abd33521f76ee3a5a upstream.
When a control endpoint stalls, the next control transfer will clear the
stall. The USB core doesn't call down to the host controller driver's
endpoint_reset() method when control endpoints stall, so the xHCI driver
has to do all its stall handling for internal state in its interrupt handler.
When the host stalls on a control endpoint, it may stop on the data phase
or status phase of the control transfer. Like other stalled endpoints,
the xHCI driver needs to queue a Reset Endpoint command and move the
hardware's control endpoint ring dequeue pointer past the failed control
transfer (with a Set TR Dequeue Pointer or a Configure Endpoint command).
Since the USB core doesn't call usb_hcd_reset_endpoint() for control
endpoints, we need to do this in interrupt context when we get notified of
the stalled transfer. URBs may be queued to the hardware before these two
commands complete. The endpoint queue will be restarted once both
commands complete.
Signed-off-by: Sarah Sharp <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/host/xhci-hcd.c | 35 ++++++++++++++++++++++++-----------
drivers/usb/host/xhci-ring.c | 33 ++++++++++++++++++++++++++++++---
drivers/usb/host/xhci.h | 4 ++++
3 files changed, 58 insertions(+), 14 deletions(-)
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -589,6 +589,7 @@ struct xhci_ep_ctx {
*/
#define FORCE_EVENT (0x1)
#define ERROR_COUNT(p) (((p) & 0x3) << 1)
+#define CTX_TO_EP_TYPE(p) (((p) >> 3) & 0x7)
#define EP_TYPE(p) ((p) << 3)
#define ISOC_OUT_EP 1
#define BULK_OUT_EP 2
@@ -1231,6 +1232,9 @@ void xhci_find_new_dequeue_state(struct
void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
struct xhci_ring *ep_ring, unsigned int slot_id,
unsigned int ep_index, struct xhci_dequeue_state *deq_state);
+void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
+ struct usb_device *udev, struct usb_host_endpoint *ep,
+ unsigned int ep_index, struct xhci_ring *ep_ring);
/* xHCI roothub code */
int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,
--- a/drivers/usb/host/xhci-hcd.c
+++ b/drivers/usb/host/xhci-hcd.c
@@ -1230,6 +1230,25 @@ void xhci_reset_bandwidth(struct usb_hcd
xhci_zero_in_ctx(xhci, virt_dev);
}
+void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
+ struct usb_device *udev, struct usb_host_endpoint *ep,
+ unsigned int ep_index, struct xhci_ring *ep_ring)
+{
+ struct xhci_dequeue_state deq_state;
+
+ xhci_dbg(xhci, "Cleaning up stalled endpoint ring\n");
+ /* We need to move the HW's dequeue pointer past this TD,
+ * or it will attempt to resend it on the next doorbell ring.
+ */
+ xhci_find_new_dequeue_state(xhci, udev->slot_id,
+ ep_index, ep_ring->stopped_td, &deq_state);
+
+ xhci_dbg(xhci, "Queueing new dequeue state\n");
+ xhci_queue_new_dequeue_state(xhci, ep_ring,
+ udev->slot_id,
+ ep_index, &deq_state);
+}
+
/* Deal with stalled endpoints. The core should have sent the control message
* to clear the halt condition. However, we need to make the xHCI hardware
* reset its sequence number, since a device will expect a sequence number of
@@ -1244,7 +1263,6 @@ void xhci_endpoint_reset(struct usb_hcd
unsigned int ep_index;
unsigned long flags;
int ret;
- struct xhci_dequeue_state deq_state;
struct xhci_ring *ep_ring;
xhci = hcd_to_xhci(hcd);
@@ -1261,6 +1279,10 @@ void xhci_endpoint_reset(struct usb_hcd
ep->desc.bEndpointAddress);
return;
}
+ if (usb_endpoint_xfer_control(&ep->desc)) {
+ xhci_dbg(xhci, "Control endpoint stall already handled.\n");
+ return;
+ }
xhci_dbg(xhci, "Queueing reset endpoint command\n");
spin_lock_irqsave(&xhci->lock, flags);
@@ -1271,16 +1293,7 @@ void xhci_endpoint_reset(struct usb_hcd
* command. Better hope that last command worked!
*/
if (!ret) {
- xhci_dbg(xhci, "Cleaning up stalled endpoint ring\n");
- /* We need to move the HW's dequeue pointer past this TD,
- * or it will attempt to resend it on the next doorbell ring.
- */
- xhci_find_new_dequeue_state(xhci, udev->slot_id,
- ep_index, ep_ring->stopped_td, &deq_state);
- xhci_dbg(xhci, "Queueing new dequeue state\n");
- xhci_queue_new_dequeue_state(xhci, ep_ring,
- udev->slot_id,
- ep_index, &deq_state);
+ xhci_cleanup_stalled_ring(xhci, udev, ep, ep_index, ep_ring);
kfree(ep_ring->stopped_td);
xhci_ring_cmd_db(xhci);
}
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -817,6 +817,7 @@ static int handle_tx_event(struct xhci_h
{
struct xhci_virt_device *xdev;
struct xhci_ring *ep_ring;
+ unsigned int slot_id;
int ep_index;
struct xhci_td *td = 0;
dma_addr_t event_dma;
@@ -827,7 +828,8 @@ static int handle_tx_event(struct xhci_h
struct xhci_ep_ctx *ep_ctx;
xhci_dbg(xhci, "In %s\n", __func__);
- xdev = xhci->devs[TRB_TO_SLOT_ID(event->flags)];
+ slot_id = TRB_TO_SLOT_ID(event->flags);
+ xdev = xhci->devs[slot_id];
if (!xdev) {
xhci_err(xhci, "ERROR Transfer event pointed to bad slot\n");
return -ENODEV;
@@ -941,6 +943,25 @@ static int handle_tx_event(struct xhci_h
xhci_warn(xhci, "WARN: short transfer on control ep\n");
status = -EREMOTEIO;
break;
+ case COMP_STALL:
+ /* Did we transfer part of the data (middle) phase? */
+ if (event_trb != ep_ring->dequeue &&
+ event_trb != td->last_trb)
+ td->urb->actual_length =
+ td->urb->transfer_buffer_length
+ - TRB_LEN(event->transfer_len);
+ else
+ td->urb->actual_length = 0;
+
+ ep_ring->stopped_td = td;
+ ep_ring->stopped_trb = event_trb;
+ xhci_queue_reset_ep(xhci, slot_id, ep_index);
+ xhci_cleanup_stalled_ring(xhci,
+ td->urb->dev,
+ td->urb->ep,
+ ep_index, ep_ring);
+ xhci_ring_cmd_db(xhci);
+ goto td_cleanup;
default:
/* Others already handled above */
break;
@@ -1083,6 +1104,7 @@ static int handle_tx_event(struct xhci_h
inc_deq(xhci, ep_ring, false);
}
+td_cleanup:
/* Clean up the endpoint's TD list */
urb = td->urb;
list_del(&td->td_list);
@@ -1091,8 +1113,13 @@ static int handle_tx_event(struct xhci_h
list_del(&td->cancelled_td_list);
ep_ring->cancels_pending--;
}
- /* Leave the TD around for the reset endpoint function to use */
- if (GET_COMP_CODE(event->transfer_len) != COMP_STALL) {
+ /* Leave the TD around for the reset endpoint function to use
+ * (but only if it's not a control endpoint, since we already
+ * queued the Set TR dequeue pointer command for stalled
+ * control endpoints).
+ */
+ if (usb_endpoint_xfer_control(&urb->ep->desc) ||
+ GET_COMP_CODE(event->transfer_len) != COMP_STALL) {
kfree(td);
}
urb->hcpriv = NULL;
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Sarah Sharp <[email protected]>
commit ac9d8fe7c6a8041cca5a0738915d2c4e21381421 upstream.
This Fresco Logic xHCI host controller chip revision puts bad data into
the output endpoint context after a Reset Endpoint command. It needs a
Configure Endpoint command (instead of a Set TR Dequeue Pointer command)
after the reset endpoint command.
Set up the input context before issuing the Reset Endpoint command so we
don't copy bad data from the output endpoint context. The HW also can't
handle two commands queued at once, so submit the TRB for the Configure
Endpoint command in the event handler for the Reset Endpoint command.
Devices that stall on control endpoints before a configuration is selected
will not work under this Fresco Logic xHCI host controller revision.
This patch is for prototype hardware that will be given to other companies
for evaluation purposes only, and should not reach consumer hands. Fresco
Logic's next chip rev should have this bug fixed.
Signed-off-by: Sarah Sharp <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/host/xhci-hcd.c | 77 +++++++++++++++++++++++++++++++++++++------
drivers/usb/host/xhci-pci.c | 13 +++++++
drivers/usb/host/xhci-ring.c | 61 ++++++++++++++++++++++++++++++----
drivers/usb/host/xhci.h | 20 +++++++----
4 files changed, 148 insertions(+), 23 deletions(-)
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -929,6 +929,12 @@ struct xhci_td {
union xhci_trb *last_trb;
};
+struct xhci_dequeue_state {
+ struct xhci_segment *new_deq_seg;
+ union xhci_trb *new_deq_ptr;
+ int new_cycle_state;
+};
+
struct xhci_ring {
struct xhci_segment *first_seg;
union xhci_trb *enqueue;
@@ -955,12 +961,6 @@ struct xhci_ring {
u32 cycle_state;
};
-struct xhci_dequeue_state {
- struct xhci_segment *new_deq_seg;
- union xhci_trb *new_deq_ptr;
- int new_cycle_state;
-};
-
struct xhci_erst_entry {
/* 64-bit event ring segment address */
u64 seg_addr;
@@ -1063,6 +1063,7 @@ struct xhci_hcd {
int error_bitmask;
unsigned int quirks;
#define XHCI_LINK_TRB_QUIRK (1 << 0)
+#define XHCI_RESET_EP_QUIRK (1 << 1)
};
/* For testing purposes */
@@ -1170,6 +1171,8 @@ int xhci_alloc_virt_device(struct xhci_h
int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *udev);
unsigned int xhci_get_endpoint_index(struct usb_endpoint_descriptor *desc);
unsigned int xhci_get_endpoint_flag(struct usb_endpoint_descriptor *desc);
+unsigned int xhci_get_endpoint_flag_from_index(unsigned int ep_index);
+unsigned int xhci_last_valid_endpoint(u32 added_ctxs);
void xhci_endpoint_zero(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, struct usb_host_endpoint *ep);
void xhci_endpoint_copy(struct xhci_hcd *xhci,
struct xhci_virt_device *vdev, unsigned int ep_index);
@@ -1233,8 +1236,11 @@ void xhci_queue_new_dequeue_state(struct
struct xhci_ring *ep_ring, unsigned int slot_id,
unsigned int ep_index, struct xhci_dequeue_state *deq_state);
void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
- struct usb_device *udev, struct usb_host_endpoint *ep,
+ struct usb_device *udev,
unsigned int ep_index, struct xhci_ring *ep_ring);
+void xhci_queue_config_ep_quirk(struct xhci_hcd *xhci,
+ unsigned int slot_id, unsigned int ep_index,
+ struct xhci_dequeue_state *deq_state);
/* xHCI roothub code */
int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,
--- a/drivers/usb/host/xhci-hcd.c
+++ b/drivers/usb/host/xhci-hcd.c
@@ -224,7 +224,7 @@ int xhci_init(struct usb_hcd *hcd)
xhci_dbg(xhci, "QUIRK: Not clearing Link TRB chain bits.\n");
xhci->quirks |= XHCI_LINK_TRB_QUIRK;
} else {
- xhci_dbg(xhci, "xHCI has no QUIRKS\n");
+ xhci_dbg(xhci, "xHCI doesn't need link TRB QUIRK\n");
}
retval = xhci_mem_init(xhci, GFP_KERNEL);
xhci_dbg(xhci, "Finished xhci_init\n");
@@ -567,13 +567,22 @@ unsigned int xhci_get_endpoint_flag(stru
return 1 << (xhci_get_endpoint_index(desc) + 1);
}
+/* Find the flag for this endpoint (for use in the control context). Use the
+ * endpoint index to create a bitmask. The slot context is bit 0, endpoint 0 is
+ * bit 1, etc.
+ */
+unsigned int xhci_get_endpoint_flag_from_index(unsigned int ep_index)
+{
+ return 1 << (ep_index + 1);
+}
+
/* Compute the last valid endpoint context index. Basically, this is the
* endpoint index plus one. For slot contexts with more than valid endpoint,
* we find the most significant bit set in the added contexts flags.
* e.g. ep 1 IN (with epnum 0x81) => added_ctxs = 0b1000
* fls(0b1000) = 4, but the endpoint context index is 3, so subtract one.
*/
-static inline unsigned int xhci_last_valid_endpoint(u32 added_ctxs)
+unsigned int xhci_last_valid_endpoint(u32 added_ctxs)
{
return fls(added_ctxs) - 1;
}
@@ -1230,8 +1239,44 @@ void xhci_reset_bandwidth(struct usb_hcd
xhci_zero_in_ctx(xhci, virt_dev);
}
+void xhci_setup_input_ctx_for_quirk(struct xhci_hcd *xhci,
+ unsigned int slot_id, unsigned int ep_index,
+ struct xhci_dequeue_state *deq_state)
+{
+ struct xhci_container_ctx *in_ctx;
+ struct xhci_input_control_ctx *ctrl_ctx;
+ struct xhci_ep_ctx *ep_ctx;
+ u32 added_ctxs;
+ dma_addr_t addr;
+
+ xhci_endpoint_copy(xhci, xhci->devs[slot_id], ep_index);
+ in_ctx = xhci->devs[slot_id]->in_ctx;
+ ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index);
+ addr = xhci_trb_virt_to_dma(deq_state->new_deq_seg,
+ deq_state->new_deq_ptr);
+ if (addr == 0) {
+ xhci_warn(xhci, "WARN Cannot submit config ep after "
+ "reset ep command\n");
+ xhci_warn(xhci, "WARN deq seg = %p, deq ptr = %p\n",
+ deq_state->new_deq_seg,
+ deq_state->new_deq_ptr);
+ return;
+ }
+ ep_ctx->deq = addr | deq_state->new_cycle_state;
+
+ xhci_slot_copy(xhci, xhci->devs[slot_id]);
+
+ ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
+ added_ctxs = xhci_get_endpoint_flag_from_index(ep_index);
+ ctrl_ctx->add_flags = added_ctxs | SLOT_FLAG;
+ ctrl_ctx->drop_flags = added_ctxs;
+
+ xhci_dbg(xhci, "Slot ID %d Input Context:\n", slot_id);
+ xhci_dbg_ctx(xhci, in_ctx, ep_index);
+}
+
void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
- struct usb_device *udev, struct usb_host_endpoint *ep,
+ struct usb_device *udev,
unsigned int ep_index, struct xhci_ring *ep_ring)
{
struct xhci_dequeue_state deq_state;
@@ -1241,12 +1286,26 @@ void xhci_cleanup_stalled_ring(struct xh
* or it will attempt to resend it on the next doorbell ring.
*/
xhci_find_new_dequeue_state(xhci, udev->slot_id,
- ep_index, ep_ring->stopped_td, &deq_state);
+ ep_index, ep_ring->stopped_td,
+ &deq_state);
- xhci_dbg(xhci, "Queueing new dequeue state\n");
- xhci_queue_new_dequeue_state(xhci, ep_ring,
- udev->slot_id,
- ep_index, &deq_state);
+ /* HW with the reset endpoint quirk will use the saved dequeue state to
+ * issue a configure endpoint command later.
+ */
+ if (!(xhci->quirks & XHCI_RESET_EP_QUIRK)) {
+ xhci_dbg(xhci, "Queueing new dequeue state\n");
+ xhci_queue_new_dequeue_state(xhci, ep_ring,
+ udev->slot_id,
+ ep_index, &deq_state);
+ } else {
+ /* Better hope no one uses the input context between now and the
+ * reset endpoint completion!
+ */
+ xhci_dbg(xhci, "Setting up input context for "
+ "configure endpoint command\n");
+ xhci_setup_input_ctx_for_quirk(xhci, udev->slot_id,
+ ep_index, &deq_state);
+ }
}
/* Deal with stalled endpoints. The core should have sent the control message
@@ -1293,7 +1352,7 @@ void xhci_endpoint_reset(struct usb_hcd
* command. Better hope that last command worked!
*/
if (!ret) {
- xhci_cleanup_stalled_ring(xhci, udev, ep, ep_index, ep_ring);
+ xhci_cleanup_stalled_ring(xhci, udev, ep_index, ep_ring);
kfree(ep_ring->stopped_td);
xhci_ring_cmd_db(xhci);
}
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -24,6 +24,10 @@
#include "xhci.h"
+/* Device for a quirk */
+#define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73
+#define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000
+
static const char hcd_name[] = "xhci_hcd";
/* called after powerup, by probe or system-pm "wakeup" */
@@ -62,6 +66,15 @@ static int xhci_pci_setup(struct usb_hcd
xhci->hcc_params = xhci_readl(xhci, &xhci->cap_regs->hcc_params);
xhci_print_registers(xhci);
+ /* Look for vendor-specific quirks */
+ if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC &&
+ pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK &&
+ pdev->revision == 0x0) {
+ xhci->quirks |= XHCI_RESET_EP_QUIRK;
+ xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure"
+ " endpoint cmd after reset endpoint\n");
+ }
+
/* Make sure the HC is halted. */
retval = xhci_halt(xhci);
if (retval)
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -469,7 +469,6 @@ void xhci_queue_new_dequeue_state(struct
* ring running.
*/
ep_ring->state |= SET_DEQ_PENDING;
- xhci_ring_cmd_db(xhci);
}
/*
@@ -538,6 +537,7 @@ static void handle_stopped_endpoint(stru
if (deq_state.new_deq_ptr && deq_state.new_deq_seg) {
xhci_queue_new_dequeue_state(xhci, ep_ring,
slot_id, ep_index, &deq_state);
+ xhci_ring_cmd_db(xhci);
} else {
/* Otherwise just ring the doorbell to restart the ring */
ring_ep_doorbell(xhci, slot_id, ep_index);
@@ -651,18 +651,31 @@ static void handle_reset_ep_completion(s
{
int slot_id;
unsigned int ep_index;
+ struct xhci_ring *ep_ring;
slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]);
ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]);
+ ep_ring = xhci->devs[slot_id]->ep_rings[ep_index];
/* This command will only fail if the endpoint wasn't halted,
* but we don't care.
*/
xhci_dbg(xhci, "Ignoring reset ep completion code of %u\n",
(unsigned int) GET_COMP_CODE(event->status));
- /* Clear our internal halted state and restart the ring */
- xhci->devs[slot_id]->ep_rings[ep_index]->state &= ~EP_HALTED;
- ring_ep_doorbell(xhci, slot_id, ep_index);
+ /* HW with the reset endpoint quirk needs to have a configure endpoint
+ * command complete before the endpoint can be used. Queue that here
+ * because the HW can't handle two commands being queued in a row.
+ */
+ if (xhci->quirks & XHCI_RESET_EP_QUIRK) {
+ xhci_dbg(xhci, "Queueing configure endpoint command\n");
+ xhci_queue_configure_endpoint(xhci,
+ xhci->devs[slot_id]->in_ctx->dma, slot_id);
+ xhci_ring_cmd_db(xhci);
+ } else {
+ /* Clear our internal halted state and restart the ring */
+ ep_ring->state &= ~EP_HALTED;
+ ring_ep_doorbell(xhci, slot_id, ep_index);
+ }
}
static void handle_cmd_completion(struct xhci_hcd *xhci,
@@ -671,6 +684,10 @@ static void handle_cmd_completion(struct
int slot_id = TRB_TO_SLOT_ID(event->flags);
u64 cmd_dma;
dma_addr_t cmd_dequeue_dma;
+ struct xhci_input_control_ctx *ctrl_ctx;
+ unsigned int ep_index;
+ struct xhci_ring *ep_ring;
+ unsigned int ep_state;
cmd_dma = event->cmd_trb;
cmd_dequeue_dma = xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
@@ -698,8 +715,39 @@ static void handle_cmd_completion(struct
xhci_free_virt_device(xhci, slot_id);
break;
case TRB_TYPE(TRB_CONFIG_EP):
- xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status);
- complete(&xhci->devs[slot_id]->cmd_completion);
+ /*
+ * Configure endpoint commands can come from the USB core
+ * configuration or alt setting changes, or because the HW
+ * needed an extra configure endpoint command after a reset
+ * endpoint command. In the latter case, the xHCI driver is
+ * not waiting on the configure endpoint command.
+ */
+ ctrl_ctx = xhci_get_input_control_ctx(xhci,
+ xhci->devs[slot_id]->in_ctx);
+ /* Input ctx add_flags are the endpoint index plus one */
+ ep_index = xhci_last_valid_endpoint(ctrl_ctx->add_flags) - 1;
+ ep_ring = xhci->devs[slot_id]->ep_rings[ep_index];
+ if (!ep_ring) {
+ /* This must have been an initial configure endpoint */
+ xhci->devs[slot_id]->cmd_status =
+ GET_COMP_CODE(event->status);
+ complete(&xhci->devs[slot_id]->cmd_completion);
+ break;
+ }
+ ep_state = ep_ring->state;
+ xhci_dbg(xhci, "Completed config ep cmd - last ep index = %d, "
+ "state = %d\n", ep_index, ep_state);
+ if (xhci->quirks & XHCI_RESET_EP_QUIRK &&
+ ep_state & EP_HALTED) {
+ /* Clear our internal halted state and restart ring */
+ xhci->devs[slot_id]->ep_rings[ep_index]->state &=
+ ~EP_HALTED;
+ ring_ep_doorbell(xhci, slot_id, ep_index);
+ } else {
+ xhci->devs[slot_id]->cmd_status =
+ GET_COMP_CODE(event->status);
+ complete(&xhci->devs[slot_id]->cmd_completion);
+ }
break;
case TRB_TYPE(TRB_EVAL_CONTEXT):
xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status);
@@ -958,7 +1006,6 @@ static int handle_tx_event(struct xhci_h
xhci_queue_reset_ep(xhci, slot_id, ep_index);
xhci_cleanup_stalled_ring(xhci,
td->urb->dev,
- td->urb->ep,
ep_index, ep_ring);
xhci_ring_cmd_db(xhci);
goto td_cleanup;
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Sarah Sharp <[email protected]>
commit 66d1eebce5cca916e0b08d961690bb01c64751ef upstream.
Use trb_comp_code instead of getting the completion code from the transfer
event every time.
Signed-off-by: Sarah Sharp <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/host/xhci-ring.c | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -874,6 +874,7 @@ static int handle_tx_event(struct xhci_h
struct urb *urb = 0;
int status = -EINPROGRESS;
struct xhci_ep_ctx *ep_ctx;
+ u32 trb_comp_code;
xhci_dbg(xhci, "In %s\n", __func__);
slot_id = TRB_TO_SLOT_ID(event->flags);
@@ -931,7 +932,8 @@ static int handle_tx_event(struct xhci_h
(unsigned int) event->flags);
/* Look for common error cases */
- switch (GET_COMP_CODE(event->transfer_len)) {
+ trb_comp_code = GET_COMP_CODE(event->transfer_len);
+ switch (trb_comp_code) {
/* Skip codes that require special handling depending on
* transfer type
*/
@@ -974,7 +976,7 @@ static int handle_tx_event(struct xhci_h
/* Was this a control transfer? */
if (usb_endpoint_xfer_control(&td->urb->ep->desc)) {
xhci_debug_trb(xhci, xhci->event_ring->dequeue);
- switch (GET_COMP_CODE(event->transfer_len)) {
+ switch (trb_comp_code) {
case COMP_SUCCESS:
if (event_trb == ep_ring->dequeue) {
xhci_warn(xhci, "WARN: Success on ctrl setup TRB without IOC set??\n");
@@ -1031,7 +1033,7 @@ static int handle_tx_event(struct xhci_h
}
} else {
/* Maybe the event was for the data stage? */
- if (GET_COMP_CODE(event->transfer_len) != COMP_STOP_INVAL) {
+ if (trb_comp_code != COMP_STOP_INVAL) {
/* We didn't stop on a link TRB in the middle */
td->urb->actual_length =
td->urb->transfer_buffer_length -
@@ -1043,7 +1045,7 @@ static int handle_tx_event(struct xhci_h
}
}
} else {
- switch (GET_COMP_CODE(event->transfer_len)) {
+ switch (trb_comp_code) {
case COMP_SUCCESS:
/* Double check that the HW transferred everything. */
if (event_trb != td->last_trb) {
@@ -1120,14 +1122,14 @@ static int handle_tx_event(struct xhci_h
/* If the ring didn't stop on a Link or No-op TRB, add
* in the actual bytes transferred from the Normal TRB
*/
- if (GET_COMP_CODE(event->transfer_len) != COMP_STOP_INVAL)
+ if (trb_comp_code != COMP_STOP_INVAL)
td->urb->actual_length +=
TRB_LEN(cur_trb->generic.field[2]) -
TRB_LEN(event->transfer_len);
}
}
- if (GET_COMP_CODE(event->transfer_len) == COMP_STOP_INVAL ||
- GET_COMP_CODE(event->transfer_len) == COMP_STOP) {
+ if (trb_comp_code == COMP_STOP_INVAL ||
+ trb_comp_code == COMP_STOP) {
/* The Endpoint Stop Command completion will take care of any
* stopped TDs. A stopped TD may be restarted, so don't update
* the ring dequeue pointer or take this TD off any lists yet.
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Sarah Sharp <[email protected]>
commit 83fbcdcca03013bb5af130d6d91eba11e3d3269e upstream.
The 0.95 xHCI spec says that non-control endpoints will be halted if a
babble is detected on a transfer. The 0.96 xHCI spec says all types of
endpoints will be halted when a babble is detected. Some hardware that
claims to be 0.95 compliant halts the control endpoint anyway.
When a babble is detected on a control endpoint, check the hardware's
output endpoint context to see if the endpoint is marked as halted. If
the control endpoint is halted, a reset endpoint command must be issued
and the transfer ring dequeue pointer needs to be moved past the stopped
transfer. Basically, we treat it as if the control endpoint had stalled.
Handle bulk babbling endpoints as if we got a completion event with a
stall completion code.
Signed-off-by: Sarah Sharp <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/host/xhci-ring.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -993,6 +993,16 @@ static int handle_tx_event(struct xhci_h
xhci_warn(xhci, "WARN: short transfer on control ep\n");
status = -EREMOTEIO;
break;
+ case COMP_BABBLE:
+ /* The 0.96 spec says a babbling control endpoint
+ * is not halted. The 0.96 spec says it is. Some HW
+ * claims to be 0.95 compliant, but it halts the control
+ * endpoint anyway. Check if a babble halted the
+ * endpoint.
+ */
+ if (ep_ctx->ep_info != EP_STATE_HALTED)
+ break;
+ /* else fall through */
case COMP_STALL:
/* Did we transfer part of the data (middle) phase? */
if (event_trb != ep_ring->dequeue &&
@@ -1137,7 +1147,8 @@ static int handle_tx_event(struct xhci_h
ep_ring->stopped_td = td;
ep_ring->stopped_trb = event_trb;
} else {
- if (GET_COMP_CODE(event->transfer_len) == COMP_STALL) {
+ if (trb_comp_code == COMP_STALL ||
+ trb_comp_code == COMP_BABBLE) {
/* The transfer is completed from the driver's
* perspective, but we need to issue a set dequeue
* command for this stalled endpoint to move the dequeue
@@ -1168,7 +1179,8 @@ td_cleanup:
* control endpoints).
*/
if (usb_endpoint_xfer_control(&urb->ep->desc) ||
- GET_COMP_CODE(event->transfer_len) != COMP_STALL) {
+ (trb_comp_code != COMP_STALL &&
+ trb_comp_code != COMP_BABBLE)) {
kfree(td);
}
urb->hcpriv = NULL;
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Sarah Sharp <[email protected]>
commit 9191eee7b8a0e18c07c06d6da502706805cab6d2 upstream.
On a successful transfer, urb->td is freed before the URB is ready to be
given back to the driver. Don't touch urb->td after it's freed. This bug
would have only shown up when xHCI debugging was turned on, and the freed
memory was quickly reused for something else.
Signed-off-by: Sarah Sharp <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/host/xhci-ring.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1193,7 +1193,7 @@ cleanup:
if (urb) {
usb_hcd_unlink_urb_from_ep(xhci_to_hcd(xhci), urb);
xhci_dbg(xhci, "Giveback URB %p, len = %d, status = %d\n",
- urb, td->urb->actual_length, status);
+ urb, urb->actual_length, status);
spin_unlock(&xhci->lock);
usb_hcd_giveback_urb(xhci_to_hcd(xhci), urb, status);
spin_lock(&xhci->lock);
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Sarah Sharp <[email protected]>
commit 99eb32db45061443ab7552b8fdceae68b90fde55 upstream.
Make sure that the amount of data the xHC says was transmitted is less
than or equal to the size of the requested transfer buffer. Before, if
the host controller erroneously reported that the number of bytes
untransferred was bigger than the buffer in the URB, urb->actual_length
could be set to a very large size.
Make sure urb->actual_length <= urb->transfer_buffer_length.
Signed-off-by: Sarah Sharp <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/host/xhci-ring.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1092,7 +1092,8 @@ static int handle_tx_event(struct xhci_h
td->urb->actual_length =
td->urb->transfer_buffer_length -
TRB_LEN(event->transfer_len);
- if (td->urb->actual_length < 0) {
+ if (td->urb->transfer_buffer_length <
+ td->urb->actual_length) {
xhci_warn(xhci, "HC gave bad length "
"of %d bytes left\n",
TRB_LEN(event->transfer_len));
@@ -1167,6 +1168,20 @@ static int handle_tx_event(struct xhci_h
td_cleanup:
/* Clean up the endpoint's TD list */
urb = td->urb;
+ /* Do one last check of the actual transfer length.
+ * If the host controller said we transferred more data than
+ * the buffer length, urb->actual_length will be a very big
+ * number (since it's unsigned). Play it safe and say we didn't
+ * transfer anything.
+ */
+ if (urb->actual_length > urb->transfer_buffer_length) {
+ xhci_warn(xhci, "URB transfer length is wrong, "
+ "xHC issue? req. len = %u, "
+ "act. len = %u\n",
+ urb->transfer_buffer_length,
+ urb->actual_length);
+ urb->actual_length = 0;
+ }
list_del(&td->td_list);
/* Was this TD slated to be cancelled but completed anyway? */
if (!list_empty(&td->cancelled_td_list)) {
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Sarah Sharp <[email protected]>
commit 204970a4bb2f584afc430ae330cd44aee329cea4 upstream.
Make sure that the driver that submitted the URB considers a short packet
an error before setting -EREMOTEIO during a short control transfer.
Signed-off-by: Sarah Sharp <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/host/xhci-ring.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -991,7 +991,10 @@ static int handle_tx_event(struct xhci_h
break;
case COMP_SHORT_TX:
xhci_warn(xhci, "WARN: short transfer on control ep\n");
- status = -EREMOTEIO;
+ if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
+ status = -EREMOTEIO;
+ else
+ status = 0;
break;
case COMP_BABBLE:
/* The 0.96 spec says a babbling control endpoint
@@ -1034,7 +1037,10 @@ static int handle_tx_event(struct xhci_h
if (event_trb == td->last_trb) {
if (td->urb->actual_length != 0) {
/* Don't overwrite a previously set error code */
- if (status == -EINPROGRESS || status == 0)
+ if ((status == -EINPROGRESS ||
+ status == 0) &&
+ (td->urb->transfer_flags
+ & URB_SHORT_NOT_OK))
/* Did we already see a short data stage? */
status = -EREMOTEIO;
} else {
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Sarah Sharp <[email protected]>
commit 2f697f6cbff155b3ce4053a50cdf00b5be4dda11 upstream.
The xHCI hardware reports the number of bytes untransferred for a given
transfer buffer. If the hardware reports a bytes untransferred value
greater than the submitted buffer size, we want to play it safe and say no
data was transferred. If the driver considers a short packet to be an
error, remember to set -EREMOTEIO.
Signed-off-by: Sarah Sharp <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/host/xhci-ring.c | 9 +++++++++
1 file changed, 9 insertions(+)
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1104,6 +1104,11 @@ static int handle_tx_event(struct xhci_h
"of %d bytes left\n",
TRB_LEN(event->transfer_len));
td->urb->actual_length = 0;
+ if (td->urb->transfer_flags &
+ URB_SHORT_NOT_OK)
+ status = -EREMOTEIO;
+ else
+ status = 0;
}
/* Don't overwrite a previously set error code */
if (status == -EINPROGRESS) {
@@ -1187,6 +1192,10 @@ td_cleanup:
urb->transfer_buffer_length,
urb->actual_length);
urb->actual_length = 0;
+ if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
+ status = -EREMOTEIO;
+ else
+ status = 0;
}
list_del(&td->td_list);
/* Was this TD slated to be cancelled but completed anyway? */
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Sarah Sharp <[email protected]>
commit 624defa12f304b4d11eda309bc207fa5a1900d0f upstream.
Interrupt transfers are submitted to the xHCI hardware using the same TRB
type as bulk transfers. Re-use the bulk transfer enqueueing code to
enqueue interrupt transfers.
Interrupt transfers are a bit different than bulk transfers. When the
interrupt endpoint is to be serviced, the xHC will consume (at most) one
TD. A TD (comprised of sg list entries) can take several service
intervals to transmit. The important thing for device drivers to note is
that if they use the scatter gather interface to submit interrupt
requests, they will not get data sent from two different scatter gather
lists in the same service interval.
For now, the xHCI driver will use the service interval from the endpoint's
descriptor (bInterval). Drivers will need a hook to poll at a more
frequent interval. Set urb->interval to the interval that the xHCI
hardware will use.
Signed-off-by: Sarah Sharp <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/host/xhci-hcd.c | 5 ++++
drivers/usb/host/xhci-ring.c | 48 ++++++++++++++++++++++++++++++++++++++++++-
drivers/usb/host/xhci.h | 3 ++
3 files changed, 55 insertions(+), 1 deletion(-)
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -581,6 +581,7 @@ struct xhci_ep_ctx {
/* bit 15 is Linear Stream Array */
/* Interval - period between requests to an endpoint - 125u increments. */
#define EP_INTERVAL(p) ((p & 0xff) << 16)
+#define EP_INTERVAL_TO_UFRAMES(p) (1 << (((p) >> 16) & 0xff))
/* ep_info2 bitmasks */
/*
@@ -1223,6 +1224,8 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *
int slot_id, unsigned int ep_index);
int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
int slot_id, unsigned int ep_index);
+int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
+ int slot_id, unsigned int ep_index);
int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
u32 slot_id);
int xhci_queue_evaluate_context(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
--- a/drivers/usb/host/xhci-hcd.c
+++ b/drivers/usb/host/xhci-hcd.c
@@ -727,6 +727,11 @@ int xhci_urb_enqueue(struct usb_hcd *hcd
ret = xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb,
slot_id, ep_index);
spin_unlock_irqrestore(&xhci->lock, flags);
+ } else if (usb_endpoint_xfer_int(&urb->ep->desc)) {
+ spin_lock_irqsave(&xhci->lock, flags);
+ ret = xhci_queue_intr_tx(xhci, GFP_ATOMIC, urb,
+ slot_id, ep_index);
+ spin_unlock_irqrestore(&xhci->lock, flags);
} else {
ret = -EINVAL;
}
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1072,7 +1072,12 @@ static int handle_tx_event(struct xhci_h
else
status = 0;
} else {
- xhci_dbg(xhci, "Successful bulk transfer!\n");
+ if (usb_endpoint_xfer_bulk(&td->urb->ep->desc))
+ xhci_dbg(xhci, "Successful bulk "
+ "transfer!\n");
+ else
+ xhci_dbg(xhci, "Successful interrupt "
+ "transfer!\n");
status = 0;
}
break;
@@ -1464,6 +1469,47 @@ static void giveback_first_trb(struct xh
ring_ep_doorbell(xhci, slot_id, ep_index);
}
+/*
+ * xHCI uses normal TRBs for both bulk and interrupt. When the interrupt
+ * endpoint is to be serviced, the xHC will consume (at most) one TD. A TD
+ * (comprised of sg list entries) can take several service intervals to
+ * transmit.
+ */
+int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
+ struct urb *urb, int slot_id, unsigned int ep_index)
+{
+ struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci,
+ xhci->devs[slot_id]->out_ctx, ep_index);
+ int xhci_interval;
+ int ep_interval;
+
+ xhci_interval = EP_INTERVAL_TO_UFRAMES(ep_ctx->ep_info);
+ ep_interval = urb->interval;
+ /* Convert to microframes */
+ if (urb->dev->speed == USB_SPEED_LOW ||
+ urb->dev->speed == USB_SPEED_FULL)
+ ep_interval *= 8;
+ /* FIXME change this to a warning and a suggestion to use the new API
+ * to set the polling interval (once the API is added).
+ */
+ if (xhci_interval != ep_interval) {
+ if (!printk_ratelimit())
+ dev_dbg(&urb->dev->dev, "Driver uses different interval"
+ " (%d microframe%s) than xHCI "
+ "(%d microframe%s)\n",
+ ep_interval,
+ ep_interval == 1 ? "" : "s",
+ xhci_interval,
+ xhci_interval == 1 ? "" : "s");
+ urb->interval = xhci_interval;
+ /* Convert back to frames for LS/FS devices */
+ if (urb->dev->speed == USB_SPEED_LOW ||
+ urb->dev->speed == USB_SPEED_FULL)
+ urb->interval /= 8;
+ }
+ return xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index);
+}
+
static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
struct urb *urb, int slot_id, unsigned int ep_index)
{
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Sarah Sharp <[email protected]>
commit 6682bb39e111b34290e25c4d275c5bcf8bbccbe1 upstream.
When there's a descriptor after the SuperSpeed endpoint companion
descriptor, the previous code would have skipped over twice the length it
was supposed to. This code fixes crashes seen with UASP devices (which
have a UASP descriptor after the SS endpoint companion descriptor).
Signed-off-by: Sarah Sharp <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/core/config.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -105,7 +105,7 @@ static int usb_parse_ss_endpoint_compani
ep->ss_ep_comp->extralen = i;
buffer += i;
size -= i;
- retval = buffer - buffer_start + i;
+ retval = buffer - buffer_start;
if (num_skipped > 0)
dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
num_skipped, plural(num_skipped),
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: KAMEZAWA Hiroyuki <[email protected]>
Not upstream due to other fixes in .32
Works around a BUG() which is triggered when the kernel accesses holes in
vmalloc regions.
BUG: unable to handle kernel paging request at fa54c000
IP: [<c04f687a>] read_kcore+0x260/0x31a
*pde = 3540b067 *pte = 00000000
Oops: 0000 [#1] SMP
last sysfs file: /sys/devices/pci0000:00/0000:00:1c.2/0000:03:00.0/ieee80211/phy0/rfkill0/state
Modules linked in: fuse sco bridge stp llc bnep l2cap bluetooth sunrpc nf_conntrack_ftp ip6t_REJECT nf_conntrack_ipv6 ip6table_filter ip6_tables ipv6 cpufreq_ondemand acpi_cpufreq dm_multipath uinput usb_storage arc4 ecb snd_hda_codec_realtek snd_hda_intel ath5k snd_hda_codec snd_hwdep iTCO_wdt snd_pcm iTCO_vendor_support pcspkr i2c_i801 mac80211 joydev snd_timer serio_raw r8169 snd soundcore mii snd_page_alloc ath cfg80211 ata_generic i915 drm i2c_algo_bit i2c_core video output [last unloaded: scsi_wait_scan]
Sep 4 12:45:16 tuxedu kernel: Pid: 2266, comm: cat Not tainted (2.6.31-rc8 #2) Joybook Lite U101
EIP: 0060:[<c04f687a>] EFLAGS: 00010286 CPU: 0
EIP is at read_kcore+0x260/0x31a
EAX: f5e5ea00 EBX: fa54d000 ECX: 00000400 EDX: 00001000
ESI: fa54c000 EDI: f44ad000 EBP: e4533f4c ESP: e4533f24
DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
Process cat (pid: 2266, ti=e4532000 task=f09d19a0 task.ti=e4532000)
Stack:
00005000 00000000 f44ad000 09d9c000 00003000 fa54c000 00001000 f6d16f60
e4520b80 fffffffb e4533f70 c04ef8eb e4533f98 00008000 09d97000 c04f661a
e4520b80 09d97000 c04ef88c e4533f8c c04ba531 e4533f98 c04c0930 e4520b80
Call Trace:
[<c04ef8eb>] ? proc_reg_read+0x5f/0x73
[<c04f661a>] ? read_kcore+0x0/0x31a
[<c04ef88c>] ? proc_reg_read+0x0/0x73
[<c04ba531>] ? vfs_read+0x82/0xe1
[<c04c0930>] ? path_put+0x1a/0x1d
[<c04ba62e>] ? sys_read+0x40/0x62
[<c0403298>] ? sysenter_do_call+0x12/0x2d
Code: 39 f3 89 ca 0f 43 f3 89 fb 29 f2 29 f3 39 cf 0f 46 d3 29 55 dc 8d 1c 32 f6 40 0c 01 75 18 89 d1 89 f7 c1 e9 02 2b 7d ec 03 7d e0 <f3> a5 89 d1 83 e1 03 74 02 f3 a4 8b 00 83 7d dc 00 74 04 85 c0
EIP: [<c04f687a>] read_kcore+0x260/0x31a SS:ESP 0068:e4533f24
CR2: 00000000fa54c000
To access vmalloc area which may have memory holes, copy_from_user is
useful. So this:
# cat /proc/kcore > /dev/null
will not panic.
This is a minimal fix, suitable for 2.6.30.x and 2.6.31. More extensive
/proc/kcore changes are planned for 2.6.32.
Signed-off-by: KAMEZAWA Hiroyuki <[email protected]>
Tested-by: Nick Craig-Wood <[email protected]>
Cc: Pekka Enberg <[email protected]>
Reported-by: <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/proc/kcore.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -361,7 +361,13 @@ read_kcore(struct file *file, char __use
/* don't dump ioremap'd stuff! (TA) */
if (m->flags & VM_IOREMAP)
continue;
- memcpy(elf_buf + (vmstart - start),
+ /*
+ * we may access memory holes, then use
+ * ex_table. checking return value just for
+ * avoid warnings.
+ */
+ vmsize = __copy_from_user_inatomic(
+ elf_buf + (vmstart - start),
(char *)vmstart, vmsize);
}
read_unlock(&vmlist_lock);
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Lee Schermerhorn <[email protected]>
Not upstream as it is fixed differently in .32
I noticed that alloc_bootmem_huge_page() will only advance to the next
node on failure to allocate a huge page. I asked about this on linux-mm
and linux-numa, cc'ing the usual huge page suspects. Mel Gorman
responded:
I strongly suspect that the same node being used until allocation
failure instead of round-robin is an oversight and not deliberate
at all. It appears to be a side-effect of a fix made way back in
commit 63b4613c3f0d4b724ba259dc6c201bb68b884e1a ["hugetlb: fix
hugepage allocation with memoryless nodes"]. Prior to that patch
it looked like allocations would always round-robin even when
allocation was successful.
Andy Whitcroft countered that the existing behavior looked like Andi
Kleen's original implementation and suggested that we ask him. We did and
Andy replied that his intention was to interleave the allocations. So,
...
This patch moves the advance of the hstate next node from which to
allocate up before the test for success of the attempted allocation. This
will unconditionally advance the next node from which to alloc,
interleaving successful allocations over the nodes with sufficient
contiguous memory, and skipping over nodes that fail the huge page
allocation attempt.
Note that alloc_bootmem_huge_page() will only be called for huge pages of
order > MAX_ORDER.
Signed-off-by: Lee Schermerhorn <[email protected]>
Reviewed-by: Andi Kleen <[email protected]>
Cc: Mel Gorman <[email protected]>
Cc: David Rientjes <[email protected]>
Cc: Adam Litke <[email protected]>
Cc: Andy Whitcroft <[email protected]>
Cc: Eric Whitney <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
mm/hugetlb.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1010,6 +1010,7 @@ int __weak alloc_bootmem_huge_page(struc
NODE_DATA(h->hugetlb_next_nid),
huge_page_size(h), huge_page_size(h), 0);
+ hstate_next_node(h);
if (addr) {
/*
* Use the beginning of the huge page to store the
@@ -1019,7 +1020,6 @@ int __weak alloc_bootmem_huge_page(struc
m = addr;
goto found;
}
- hstate_next_node(h);
nr_nodes--;
}
return 0;
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Mel Gorman <[email protected]>
commit 78986a678f6ec3759a01976749f4437d8bf2d6c3 upstream.
After anti-fragmentation was merged, a bug was reported whereby devices
that depended on high-order atomic allocations were failing. The solution
was to preserve a property in the buddy allocator which tended to keep the
minimum number of free pages in the zone at the lower physical addresses
and contiguous. To preserve this property, MIGRATE_RESERVE was introduced
and a number of pageblocks at the start of a zone would be marked
"reserve", the number of which depended on min_free_kbytes.
Anti-fragmentation works by avoiding the mixing of page migratetypes
within the same pageblock. One way of helping this is to increase
min_free_kbytes because it becomes less like that it will be necessary to
place pages of of MIGRATE_RESERVE is unbounded, the free memory is kept
there in large contiguous blocks instead of helping anti-fragmentation as
much as it should. With the page-allocator tracepoint patches applied, it
was found during anti-fragmentation tests that the number of
fragmentation-related events were far higher than expected even with
min_free_kbytes at higher values.
This patch limits the number of MIGRATE_RESERVE blocks that exist per zone
to two. For example, with a sufficient min_free_kbytes, 4MB of memory
will be kept aside on an x86-64 and remain more or less free and
contiguous for the systems uptime. This should be sufficient for devices
depending on high-order atomic allocations while helping fragmentation
control when min_free_kbytes is tuned appropriately. As side-effect of
this patch is that the reserve variable is converted to int as unsigned
long was the wrong type to use when ensuring that only the required number
of reserve blocks are created.
With the patches applied, fragmentation-related events as measured by the
page allocator tracepoints were significantly reduced when running some
fragmentation stress-tests on systems with min_free_kbytes tuned to a
value appropriate for hugepage allocations at runtime. On x86, the events
recorded were reduced by 99.8%, on x86-64 by 99.72% and on ppc64 by
99.83%.
Signed-off-by: Mel Gorman <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
mm/page_alloc.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -2783,7 +2783,8 @@ static void setup_zone_migrate_reserve(s
{
unsigned long start_pfn, pfn, end_pfn;
struct page *page;
- unsigned long reserve, block_migratetype;
+ unsigned long block_migratetype;
+ int reserve;
/* Get the start pfn, end pfn and the number of blocks to reserve */
start_pfn = zone->zone_start_pfn;
@@ -2791,6 +2792,15 @@ static void setup_zone_migrate_reserve(s
reserve = roundup(min_wmark_pages(zone), pageblock_nr_pages) >>
pageblock_order;
+ /*
+ * Reserve blocks are generally in place to help high-order atomic
+ * allocations that are short-lived. A min_free_kbytes value that
+ * would result in more than 2 reserve blocks for atomic allocations
+ * is assumed to be in place to help anti-fragmentation for the
+ * future allocation of hugepages at runtime.
+ */
+ reserve = min(2, reserve);
+
for (pfn = start_pfn; pfn < end_pfn; pfn += pageblock_nr_pages) {
if (!pfn_valid(pfn))
continue;
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Hugh Dickins <[email protected]>
commit 408e82b78bcc9f1b47c76e833c3df97f675947de upstream.
Hiroaki Wakabayashi points out that when mlock() has been interrupted
by SIGKILL, the subsequent munlock() takes unnecessarily long because
its use of __get_user_pages() insists on faulting in all the pages
which mlock() never reached.
It's worse than slowness if mlock() is terminated by Out Of Memory kill:
the munlock_vma_pages_all() in exit_mmap() insists on faulting in all the
pages which mlock() could not find memory for; so innocent bystanders are
killed too, and perhaps the system hangs.
__get_user_pages() does a lot that's silly for munlock(): so remove the
munlock option from __mlock_vma_pages_range(), and use a simple loop of
follow_page()s in munlock_vma_pages_range() instead; ignoring absent
pages, and not marking present pages as accessed or dirty.
(Change munlock() to only go so far as mlock() reached? That does not
work out, given the convention that mlock() claims complete success even
when it has to give up early - in part so that an underlying file can be
extended later, and those pages locked which earlier would give SIGBUS.)
Signed-off-by: Hugh Dickins <[email protected]>
Acked-by: Rik van Riel <[email protected]>
Reviewed-by: Minchan Kim <[email protected]>
Cc: KAMEZAWA Hiroyuki <[email protected]>
Cc: KOSAKI Motohiro <[email protected]>
Cc: Nick Piggin <[email protected]>
Cc: Mel Gorman <[email protected]>
Reviewed-by: Hiroaki Wakabayashi <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
mm/mlock.c | 99 ++++++++++++++++++++++++-------------------------------------
1 file changed, 40 insertions(+), 59 deletions(-)
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -139,49 +139,36 @@ static void munlock_vma_page(struct page
}
/**
- * __mlock_vma_pages_range() - mlock/munlock a range of pages in the vma.
+ * __mlock_vma_pages_range() - mlock a range of pages in the vma.
* @vma: target vma
* @start: start address
* @end: end address
- * @mlock: 0 indicate munlock, otherwise mlock.
*
- * If @mlock == 0, unlock an mlocked range;
- * else mlock the range of pages. This takes care of making the pages present ,
- * too.
+ * This takes care of making the pages present too.
*
* return 0 on success, negative error code on error.
*
* vma->vm_mm->mmap_sem must be held for at least read.
*/
static long __mlock_vma_pages_range(struct vm_area_struct *vma,
- unsigned long start, unsigned long end,
- int mlock)
+ unsigned long start, unsigned long end)
{
struct mm_struct *mm = vma->vm_mm;
unsigned long addr = start;
struct page *pages[16]; /* 16 gives a reasonable batch */
int nr_pages = (end - start) / PAGE_SIZE;
int ret = 0;
- int gup_flags = 0;
+ int gup_flags;
VM_BUG_ON(start & ~PAGE_MASK);
VM_BUG_ON(end & ~PAGE_MASK);
VM_BUG_ON(start < vma->vm_start);
VM_BUG_ON(end > vma->vm_end);
- VM_BUG_ON((!rwsem_is_locked(&mm->mmap_sem)) &&
- (atomic_read(&mm->mm_users) != 0));
-
- /*
- * mlock: don't page populate if vma has PROT_NONE permission.
- * munlock: always do munlock although the vma has PROT_NONE
- * permission, or SIGKILL is pending.
- */
- if (!mlock)
- gup_flags |= GUP_FLAGS_IGNORE_VMA_PERMISSIONS |
- GUP_FLAGS_IGNORE_SIGKILL;
+ VM_BUG_ON(!rwsem_is_locked(&mm->mmap_sem));
+ gup_flags = 0;
if (vma->vm_flags & VM_WRITE)
- gup_flags |= GUP_FLAGS_WRITE;
+ gup_flags = GUP_FLAGS_WRITE;
while (nr_pages > 0) {
int i;
@@ -201,19 +188,10 @@ static long __mlock_vma_pages_range(stru
* This can happen for, e.g., VM_NONLINEAR regions before
* a page has been allocated and mapped at a given offset,
* or for addresses that map beyond end of a file.
- * We'll mlock the the pages if/when they get faulted in.
+ * We'll mlock the pages if/when they get faulted in.
*/
if (ret < 0)
break;
- if (ret == 0) {
- /*
- * We know the vma is there, so the only time
- * we cannot get a single page should be an
- * error (ret < 0) case.
- */
- WARN_ON(1);
- break;
- }
lru_add_drain(); /* push cached pages to LRU */
@@ -224,28 +202,22 @@ static long __mlock_vma_pages_range(stru
/*
* Because we lock page here and migration is blocked
* by the elevated reference, we need only check for
- * page truncation (file-cache only).
+ * file-cache page truncation. This page->mapping
+ * check also neatly skips over the ZERO_PAGE(),
+ * though if that's common we'd prefer not to lock it.
*/
- if (page->mapping) {
- if (mlock)
- mlock_vma_page(page);
- else
- munlock_vma_page(page);
- }
+ if (page->mapping)
+ mlock_vma_page(page);
unlock_page(page);
- put_page(page); /* ref from get_user_pages() */
-
- /*
- * here we assume that get_user_pages() has given us
- * a list of virtually contiguous pages.
- */
- addr += PAGE_SIZE; /* for next get_user_pages() */
- nr_pages--;
+ put_page(page); /* ref from get_user_pages() */
}
+
+ addr += ret * PAGE_SIZE;
+ nr_pages -= ret;
ret = 0;
}
- return ret; /* count entire vma as locked_vm */
+ return ret; /* 0 or negative error code */
}
/*
@@ -289,7 +261,7 @@ long mlock_vma_pages_range(struct vm_are
is_vm_hugetlb_page(vma) ||
vma == get_gate_vma(current))) {
- __mlock_vma_pages_range(vma, start, end, 1);
+ __mlock_vma_pages_range(vma, start, end);
/* Hide errors from mmap() and other callers */
return 0;
@@ -310,7 +282,6 @@ no_mlock:
return nr_pages; /* error or pages NOT mlocked */
}
-
/*
* munlock_vma_pages_range() - munlock all pages in the vma range.'
* @vma - vma containing range to be munlock()ed.
@@ -330,10 +301,24 @@ no_mlock:
* free them. This will result in freeing mlocked pages.
*/
void munlock_vma_pages_range(struct vm_area_struct *vma,
- unsigned long start, unsigned long end)
+ unsigned long start, unsigned long end)
{
+ unsigned long addr;
+
+ lru_add_drain();
vma->vm_flags &= ~VM_LOCKED;
- __mlock_vma_pages_range(vma, start, end, 0);
+
+ for (addr = start; addr < end; addr += PAGE_SIZE) {
+ struct page *page = follow_page(vma, addr, FOLL_GET);
+ if (page) {
+ lock_page(page);
+ if (page->mapping)
+ munlock_vma_page(page);
+ unlock_page(page);
+ put_page(page);
+ }
+ cond_resched();
+ }
}
/*
@@ -400,18 +385,14 @@ success:
* It's okay if try_to_unmap_one unmaps a page just after we
* set VM_LOCKED, __mlock_vma_pages_range will bring it back.
*/
- vma->vm_flags = newflags;
if (lock) {
- ret = __mlock_vma_pages_range(vma, start, end, 1);
-
- if (ret > 0) {
- mm->locked_vm -= ret;
- ret = 0;
- } else
- ret = __mlock_posix_error_return(ret); /* translate if needed */
+ vma->vm_flags = newflags;
+ ret = __mlock_vma_pages_range(vma, start, end);
+ if (ret < 0)
+ ret = __mlock_posix_error_return(ret);
} else {
- __mlock_vma_pages_range(vma, start, end, 0);
+ munlock_vma_pages_range(vma, start, end);
}
out:
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Hugh Dickins <[email protected]>
commit 1ac0cb5d0e22d5e483f56b2bc12172dec1cf7536 upstream.
do_anonymous_page() has been wrong to dirty the pte regardless.
If it's not going to mark the pte writable, then it won't help
to mark it dirty here, and clogs up memory with pages which will
need swap instead of being thrown away. Especially wrong if no
overcommit is chosen, and this vma is not yet VM_ACCOUNTed -
we could exceed the limit and OOM despite no overcommit.
Signed-off-by: Hugh Dickins <[email protected]>
Acked-by: Rik van Riel <[email protected]>
Cc: KAMEZAWA Hiroyuki <[email protected]>
Cc: KOSAKI Motohiro <[email protected]>
Cc: Nick Piggin <[email protected]>
Cc: Mel Gorman <[email protected]>
Cc: Minchan Kim <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
mm/memory.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2638,7 +2638,8 @@ static int do_anonymous_page(struct mm_s
goto oom_free_page;
entry = mk_pte(page, vma->vm_page_prot);
- entry = maybe_mkwrite(pte_mkdirty(entry), vma);
+ if (vma->vm_flags & VM_WRITE)
+ entry = pte_mkwrite(pte_mkdirty(entry));
page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
if (!pte_none(*page_table))
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Lee Schermerhorn <[email protected]>
commit 252c5f94d944487e9f50ece7942b0fbf659c5c31 upstream.
We noticed very erratic behavior [throughput] with the AIM7 shared
workload running on recent distro [SLES11] and mainline kernels on an
8-socket, 32-core, 256GB x86_64 platform. On the SLES11 kernel
[2.6.27.19+] with Barcelona processors, as we increased the load [10s of
thousands of tasks], the throughput would vary between two "plateaus"--one
at ~65K jobs per minute and one at ~130K jpm. The simple patch below
causes the results to smooth out at the ~130k plateau.
But wait, there's more:
We do not see this behavior on smaller platforms--e.g., 4 socket/8 core.
This could be the result of the larger number of cpus on the larger
platform--a scalability issue--or it could be the result of the larger
number of interconnect "hops" between some nodes in this platform and how
the tasks for a given load end up distributed over the nodes' cpus and
memories--a stochastic NUMA effect.
The variability in the results are less pronounced [on the same platform]
with Shanghai processors and with mainline kernels. With 31-rc6 on
Shanghai processors and 288 file systems on 288 fibre attached storage
volumes, the curves [jpm vs load] are both quite flat with the patched
kernel consistently producing ~3.9% better throughput [~80K jpm vs ~77K
jpm] than the unpatched kernel.
Profiling indicated that the "slow" runs were incurring high[er]
contention on an anon_vma lock in vma_adjust(), apparently called from the
sbrk() system call.
The patch:
A comment in mm/mmap.c:vma_adjust() suggests that we don't really need the
anon_vma lock when we're only adjusting the end of a vma, as is the case
for brk(). The comment questions whether it's worth while to optimize for
this case. Apparently, on the newer, larger x86_64 platforms, with
interesting NUMA topologies, it is worth while--especially considering
that the patch [if correct!] is quite simple.
We can detect this condition--no overlap with next vma--by noting a NULL
"importer". The anon_vma pointer will also be NULL in this case, so
simply avoid loading vma->anon_vma to avoid the lock.
However, we DO need to take the anon_vma lock when we're inserting a vma
['insert' non-NULL] even when we have no overlap [NULL "importer"], so we
need to check for 'insert', as well. And Hugh points out that we should
also take it when adjusting vm_start (so that rmap.c can rely upon
vma_address() while it holds the anon_vma lock).
akpm: Zhang Yanmin reprts a 150% throughput improvement with aim7, so it
might be -stable material even though thiss isn't a regression: "this
issue is not clear on dual socket Nehalem machine (2*4*2 cpu), but is
severe on large machine (4*8*2 cpu)"
[[email protected]: test vma start too]
Signed-off-by: Lee Schermerhorn <[email protected]>
Signed-off-by: Hugh Dickins <[email protected]>
Cc: Nick Piggin <[email protected]>
Cc: Eric Whitney <[email protected]>
Tested-by: "Zhang, Yanmin" <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
mm/mmap.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -570,9 +570,9 @@ again: remove_next = 1 + (end > next->
/*
* When changing only vma->vm_end, we don't really need
- * anon_vma lock: but is that case worth optimizing out?
+ * anon_vma lock.
*/
- if (vma->anon_vma)
+ if (vma->anon_vma && (insert || importer || start != vma->vm_start))
anon_vma = vma->anon_vma;
if (anon_vma) {
spin_lock(&anon_vma->lock);
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Michael Abbott <[email protected]>
commit 96830a57de1197519b62af6a4c9ceea556c18c3d upstream.
Git commit 79741dd changes idle cputime accounting, but unfortunately
the /proc/uptime file hasn't caught up. Here the idle time calculation
from /proc/stat is copied over.
Signed-off-by: Michael Abbott <[email protected]>
Signed-off-by: Martin Schwidefsky <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/proc/uptime.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
--- a/fs/proc/uptime.c
+++ b/fs/proc/uptime.c
@@ -4,13 +4,18 @@
#include <linux/sched.h>
#include <linux/seq_file.h>
#include <linux/time.h>
+#include <linux/kernel_stat.h>
#include <asm/cputime.h>
static int uptime_proc_show(struct seq_file *m, void *v)
{
struct timespec uptime;
struct timespec idle;
- cputime_t idletime = cputime_add(init_task.utime, init_task.stime);
+ int i;
+ cputime_t idletime = cputime_zero;
+
+ for_each_possible_cpu(i)
+ idletime = cputime64_add(idletime, kstat_cpu(i).cpustat.idle);
do_posix_clock_monotonic_gettime(&uptime);
monotonic_to_bootbased(&uptime);
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Chris Wilson <[email protected]>
commit c715089f49844260f1eeae8e3b55af9468ba1325 upstream.
During a page fault and rebinding the buffer there exists a window for a
signal to arrive during the i915_wait_request() and trigger a
ERESTARTSYS. This used to be handled by returning SIGBUS and thereby
killing the application. Try 'cairo-perf-trace & cairo-test-suite' and
watch X go boom!
The solution as suggested by H. Peter Anvin is to simply return NOPAGE and
leave the higher layers to spot we did not fill the page and resubmit
the page fault.
Signed-off-by: Chris Wilson <[email protected]>
[anholt: Mostly squash it with another commit]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/gpu/drm/i915/i915_gem.c | 29 ++++++++++++-----------------
1 file changed, 12 insertions(+), 17 deletions(-)
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1151,26 +1151,21 @@ int i915_gem_fault(struct vm_area_struct
mutex_lock(&dev->struct_mutex);
if (!obj_priv->gtt_space) {
ret = i915_gem_object_bind_to_gtt(obj, obj_priv->gtt_alignment);
- if (ret) {
- mutex_unlock(&dev->struct_mutex);
- return VM_FAULT_SIGBUS;
- }
+ if (ret)
+ goto unlock;
+
list_add_tail(&obj_priv->list, &dev_priv->mm.inactive_list);
ret = i915_gem_object_set_to_gtt_domain(obj, write);
- if (ret) {
- mutex_unlock(&dev->struct_mutex);
- return VM_FAULT_SIGBUS;
- }
+ if (ret)
+ goto unlock;
}
/* Need a new fence register? */
if (obj_priv->tiling_mode != I915_TILING_NONE) {
ret = i915_gem_object_get_fence_reg(obj);
- if (ret) {
- mutex_unlock(&dev->struct_mutex);
- return VM_FAULT_SIGBUS;
- }
+ if (ret)
+ goto unlock;
}
pfn = ((dev->agp->base + obj_priv->gtt_offset) >> PAGE_SHIFT) +
@@ -1178,18 +1173,18 @@ int i915_gem_fault(struct vm_area_struct
/* Finally, remap it using the new GTT offset */
ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
-
+unlock:
mutex_unlock(&dev->struct_mutex);
switch (ret) {
+ case 0:
+ case -ERESTARTSYS:
+ return VM_FAULT_NOPAGE;
case -ENOMEM:
case -EAGAIN:
return VM_FAULT_OOM;
- case -EFAULT:
- case -EINVAL:
- return VM_FAULT_SIGBUS;
default:
- return VM_FAULT_NOPAGE;
+ return VM_FAULT_SIGBUS;
}
}
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Brian Rogers <[email protected]>
commit d2ebd0f806fdb6104903365e355675934eec22b2 upstream.
Original commit message:
ir-kbd-i2c's ir_probe() function can be called much later (i.e. at
ir-kbd-i2c module load), than the lifetime of a struct IR_i2c_init_data
allocated off of the stack in cx18_i2c_new_ir() at registration time.
Make sure we pass a pointer to a persistent IR_i2c_init_data object at
i2c registration time.
Thanks to Brian Rogers, Dustin Mitchell, Andy Walls and Jean Delvare to
rise this question.
Before this patch, if ir-kbd-i2c were probed after em28xx, trash data
were used. After the patch, no matter what order, it is properly
reported as tested by me:
input: i2c IR (i2c IR (EM2840 Hauppaug as /class/input/input10
ir-kbd-i2c: i2c IR (i2c IR (EM2840 Hauppaug detected at i2c-4/4-0030/ir0 [em28xx #0]
Original-patch-by: Mauro Carvalho Chehab <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
[[email protected]: backported for 2.6.31]
Signed-off-by: Brian Rogers <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/media/video/em28xx/em28xx-cards.c | 32 ++++++++++++++----------------
drivers/media/video/em28xx/em28xx.h | 4 +++
2 files changed, 19 insertions(+), 17 deletions(-)
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -2170,8 +2170,6 @@ static int em28xx_hint_board(struct em28
/* ----------------------------------------------------------------------- */
void em28xx_register_i2c_ir(struct em28xx *dev)
{
- struct i2c_board_info info;
- struct IR_i2c_init_data init_data;
const unsigned short addr_list[] = {
0x30, 0x47, I2C_CLIENT_END
};
@@ -2179,9 +2177,9 @@ void em28xx_register_i2c_ir(struct em28x
if (disable_ir)
return;
- memset(&info, 0, sizeof(struct i2c_board_info));
- memset(&init_data, 0, sizeof(struct IR_i2c_init_data));
- strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+ memset(&dev->info, 0, sizeof(&dev->info));
+ memset(&dev->init_data, 0, sizeof(dev->init_data));
+ strlcpy(dev->info.type, "ir_video", I2C_NAME_SIZE);
/* detect & configure */
switch (dev->model) {
@@ -2191,19 +2189,19 @@ void em28xx_register_i2c_ir(struct em28x
break;
case (EM2800_BOARD_TERRATEC_CINERGY_200):
case (EM2820_BOARD_TERRATEC_CINERGY_250):
- init_data.ir_codes = ir_codes_em_terratec;
- init_data.get_key = em28xx_get_key_terratec;
- init_data.name = "i2c IR (EM28XX Terratec)";
+ dev->init_data.ir_codes = ir_codes_em_terratec;
+ dev->init_data.get_key = em28xx_get_key_terratec;
+ dev->init_data.name = "i2c IR (EM28XX Terratec)";
break;
case (EM2820_BOARD_PINNACLE_USB_2):
- init_data.ir_codes = ir_codes_pinnacle_grey;
- init_data.get_key = em28xx_get_key_pinnacle_usb_grey;
- init_data.name = "i2c IR (EM28XX Pinnacle PCTV)";
+ dev->init_data.ir_codes = ir_codes_pinnacle_grey;
+ dev->init_data.get_key = em28xx_get_key_pinnacle_usb_grey;
+ dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)";
break;
case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2):
- init_data.ir_codes = ir_codes_hauppauge_new;
- init_data.get_key = em28xx_get_key_em_haup;
- init_data.name = "i2c IR (EM2840 Hauppauge)";
+ dev->init_data.ir_codes = ir_codes_hauppauge_new;
+ dev->init_data.get_key = em28xx_get_key_em_haup;
+ dev->init_data.name = "i2c IR (EM2840 Hauppauge)";
break;
case (EM2820_BOARD_MSI_VOX_USB_2):
break;
@@ -2215,9 +2213,9 @@ void em28xx_register_i2c_ir(struct em28x
break;
}
- if (init_data.name)
- info.platform_data = &init_data;
- i2c_new_probed_device(&dev->i2c_adap, &info, addr_list);
+ if (dev->init_data.name)
+ dev->info.platform_data = &dev->init_data;
+ i2c_new_probed_device(&dev->i2c_adap, &dev->info, addr_list);
}
void em28xx_card_setup(struct em28xx *dev)
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -595,6 +595,10 @@ struct em28xx {
struct delayed_work sbutton_query_work;
struct em28xx_dvb *dvb;
+
+ /* I2C keyboard data */
+ struct i2c_board_info info;
+ struct IR_i2c_init_data init_data;
};
struct em28xx_ops {
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Brian Rogers <[email protected]>
commit 7aedd5ec87686c557d48584d69ad880c11a0984d upstream.
Tested on MSI TV@nywhere Plus.
Original commit message:
ir-kbd-i2c's ir_probe() function can be called much later (i.e. at
ir-kbd-i2c module load), than the lifetime of a struct IR_i2c_init_data
allocated off of the stack in cx18_i2c_new_ir() at registration time.
Make sure we pass a pointer to a persistent IR_i2c_init_data object at
i2c registration time.
Thanks to Brian Rogers, Dustin Mitchell, Andy Walls and Jean Delvare to
rise this question.
Before this patch, if ir-kbd-i2c were probed after SAA7134, trash data
were used.
Compile tested only, but the patch is identical to em28xx one. So, it
should work properly.
Original-patch-by: Mauro Carvalho Chehab <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
[[email protected]: backported for 2.6.31]
Signed-off-by: Brian Rogers <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/media/video/saa7134/saa7134-input.c | 56 +++++++++++++---------------
drivers/media/video/saa7134/saa7134.h | 4 ++
2 files changed, 31 insertions(+), 29 deletions(-)
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -584,6 +584,10 @@ struct saa7134_dev {
int nosignal;
unsigned int insuspend;
+ /* I2C keyboard data */
+ struct i2c_board_info info;
+ struct IR_i2c_init_data init_data;
+
/* SAA7134_MPEG_* */
struct saa7134_ts ts;
struct saa7134_dmaqueue ts_q;
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -684,8 +684,6 @@ void saa7134_input_fini(struct saa7134_d
void saa7134_probe_i2c_ir(struct saa7134_dev *dev)
{
- struct i2c_board_info info;
- struct IR_i2c_init_data init_data;
const unsigned short addr_list[] = {
0x7a, 0x47, 0x71, 0x2d,
I2C_CLIENT_END
@@ -705,32 +703,32 @@ void saa7134_probe_i2c_ir(struct saa7134
return;
}
- memset(&info, 0, sizeof(struct i2c_board_info));
- memset(&init_data, 0, sizeof(struct IR_i2c_init_data));
- strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+ memset(&dev->info, 0, sizeof(dev->info));
+ memset(&dev->init_data, 0, sizeof(dev->init_data));
+ strlcpy(dev->info.type, "ir_video", I2C_NAME_SIZE);
switch (dev->board) {
case SAA7134_BOARD_PINNACLE_PCTV_110i:
case SAA7134_BOARD_PINNACLE_PCTV_310i:
- init_data.name = "Pinnacle PCTV";
+ dev->init_data.name = "Pinnacle PCTV";
if (pinnacle_remote == 0) {
- init_data.get_key = get_key_pinnacle_color;
- init_data.ir_codes = ir_codes_pinnacle_color;
+ dev->init_data.get_key = get_key_pinnacle_color;
+ dev->init_data.ir_codes = ir_codes_pinnacle_color;
} else {
- init_data.get_key = get_key_pinnacle_grey;
- init_data.ir_codes = ir_codes_pinnacle_grey;
+ dev->init_data.get_key = get_key_pinnacle_grey;
+ dev->init_data.ir_codes = ir_codes_pinnacle_grey;
}
break;
case SAA7134_BOARD_UPMOST_PURPLE_TV:
- init_data.name = "Purple TV";
- init_data.get_key = get_key_purpletv;
- init_data.ir_codes = ir_codes_purpletv;
+ dev->init_data.name = "Purple TV";
+ dev->init_data.get_key = get_key_purpletv;
+ dev->init_data.ir_codes = ir_codes_purpletv;
break;
case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS:
- init_data.name = "MSI TV@nywhere Plus";
- init_data.get_key = get_key_msi_tvanywhere_plus;
- init_data.ir_codes = ir_codes_msi_tvanywhere_plus;
- info.addr = 0x30;
+ dev->init_data.name = "MSI TV@nywhere Plus";
+ dev->init_data.get_key = get_key_msi_tvanywhere_plus;
+ dev->init_data.ir_codes = ir_codes_msi_tvanywhere_plus;
+ dev->info.addr = 0x30;
/* MSI TV@nywhere Plus controller doesn't seem to
respond to probes unless we read something from
an existing device. Weird...
@@ -741,9 +739,9 @@ void saa7134_probe_i2c_ir(struct saa7134
(1 == rc) ? "yes" : "no");
break;
case SAA7134_BOARD_HAUPPAUGE_HVR1110:
- init_data.name = "HVR 1110";
- init_data.get_key = get_key_hvr1110;
- init_data.ir_codes = ir_codes_hauppauge_new;
+ dev->init_data.name = "HVR 1110";
+ dev->init_data.get_key = get_key_hvr1110;
+ dev->init_data.ir_codes = ir_codes_hauppauge_new;
break;
case SAA7134_BOARD_BEHOLD_607FM_MK3:
case SAA7134_BOARD_BEHOLD_607FM_MK5:
@@ -757,26 +755,26 @@ void saa7134_probe_i2c_ir(struct saa7134
case SAA7134_BOARD_BEHOLD_M63:
case SAA7134_BOARD_BEHOLD_M6_EXTRA:
case SAA7134_BOARD_BEHOLD_H6:
- init_data.name = "BeholdTV";
- init_data.get_key = get_key_beholdm6xx;
- init_data.ir_codes = ir_codes_behold;
+ dev->init_data.name = "BeholdTV";
+ dev->init_data.get_key = get_key_beholdm6xx;
+ dev->init_data.ir_codes = ir_codes_behold;
break;
case SAA7134_BOARD_AVERMEDIA_CARDBUS_501:
case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
- info.addr = 0x40;
+ dev->info.addr = 0x40;
break;
}
- if (init_data.name)
- info.platform_data = &init_data;
+ if (dev->init_data.name)
+ dev->info.platform_data = &dev->init_data;
/* No need to probe if address is known */
- if (info.addr) {
- i2c_new_device(&dev->i2c_adap, &info);
+ if (dev->info.addr) {
+ i2c_new_device(&dev->i2c_adap, &dev->info);
return;
}
/* Address not known, fallback to probing */
- i2c_new_probed_device(&dev->i2c_adap, &info, addr_list);
+ i2c_new_probed_device(&dev->i2c_adap, &dev->info, addr_list);
}
static int saa7134_rc5_irq(struct saa7134_dev *dev)
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Rex Feany <[email protected]>
commit e0908085fc2391c85b85fb814ae1df377c8e0dcb upstream.
After upgrading to the latest kernel on my mpc875 userspace started
running incredibly slow (hours to get to a shell, even!).
I tracked it down to commit 8d30c14cab30d405a05f2aaceda1e9ad57800f36,
that patch removed a work-around for the 8xx. Adding it
back makes my problem go away.
Signed-off-by: Rex Feany <[email protected]>
Signed-off-by: Benjamin Herrenschmidt <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/powerpc/mm/pgtable.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
--- a/arch/powerpc/mm/pgtable.c
+++ b/arch/powerpc/mm/pgtable.c
@@ -30,6 +30,8 @@
#include <asm/tlbflush.h>
#include <asm/tlb.h>
+#include "mmu_decl.h"
+
static DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur);
static unsigned long pte_freelist_forced_free;
@@ -119,7 +121,7 @@ void pte_free_finish(void)
/*
* Handle i/d cache flushing, called from set_pte_at() or ptep_set_access_flags()
*/
-static pte_t do_dcache_icache_coherency(pte_t pte)
+static pte_t do_dcache_icache_coherency(pte_t pte, unsigned long addr)
{
unsigned long pfn = pte_pfn(pte);
struct page *page;
@@ -128,6 +130,17 @@ static pte_t do_dcache_icache_coherency(
return pte;
page = pfn_to_page(pfn);
+#ifdef CONFIG_8xx
+ /* On 8xx, cache control instructions (particularly
+ * "dcbst" from flush_dcache_icache) fault as write
+ * operation if there is an unpopulated TLB entry
+ * for the address in question. To workaround that,
+ * we invalidate the TLB here, thus avoiding dcbst
+ * misbehaviour.
+ */
+ _tlbil_va(addr, 0 /* 8xx doesn't care about PID */);
+#endif
+
if (!PageReserved(page) && !test_bit(PG_arch_1, &page->flags)) {
pr_devel("do_dcache_icache_coherency... flushing\n");
flush_dcache_icache_page(page);
@@ -198,7 +211,7 @@ void set_pte_at(struct mm_struct *mm, un
*/
pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
if (pte_need_exec_flush(pte, 1))
- pte = do_dcache_icache_coherency(pte);
+ pte = do_dcache_icache_coherency(pte, addr);
/* Perform the setting of the PTE */
__set_pte_at(mm, addr, ptep, pte, 0);
@@ -216,7 +229,7 @@ int ptep_set_access_flags(struct vm_area
{
int changed;
if (!dirty && pte_need_exec_flush(entry, 0))
- entry = do_dcache_icache_coherency(entry);
+ entry = do_dcache_icache_coherency(entry, address);
changed = !pte_same(*(ptep), entry);
if (changed) {
if (!(vma->vm_flags & VM_HUGETLB))
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Weirich, Bernhard <[email protected]>
[I'm going to fix upstream differently, by having all CPU types
actually support _PAGE_SPECIAL, but I prefer the simple and obvious
fix for -stable. -- Ben]
The test that decides whether to define __HAVE_ARCH_PTE_SPECIAL on
powerpc is bogus and will end up always defining it, even when
_PAGE_SPECIAL is not supported (in which case it's 0) such as on
8xx or 40x processors.
Signed-off-by: Bernhard Weirich <[email protected]>
Signed-off-by: Benjamin Herrenschmidt <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/powerpc/include/asm/pte-common.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/powerpc/include/asm/pte-common.h
+++ b/arch/powerpc/include/asm/pte-common.h
@@ -176,7 +176,7 @@ extern unsigned long bad_call_to_PMD_PAG
#define HAVE_PAGE_AGP
/* Advertise support for _PAGE_SPECIAL */
-#ifdef _PAGE_SPECIAL
+#if _PAGE_SPECIAL != 0
#define __HAVE_ARCH_PTE_SPECIAL
#endif
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Jan Scholz <[email protected]>
commit 42960a13001aa6df52ca9952ce996f94a744ea65 upstream.
Commit fa047e4f6fa63a6e9d0ae4d7749538830d14a343 "HID: fix inverted
wheel for bluetooth version of apple mighty mouse" is incomplete. If
we remove Apple MightyMouse (bluetooth version) from the list of
apple_devices in drivers/hid/hid-apple.c we have to remove it from
hid_blacklist in drivers/hid/hid-core.c as well.
Signed-off-by: Jan Scholz <[email protected]>
Signed-off-by: Jiri Kosina <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/hid/hid-core.c | 1 -
1 file changed, 1 deletion(-)
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1319,7 +1319,6 @@ static const struct hid_device_id hid_bl
{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) },
{ }
};
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Kashyap, Desai <[email protected]>
commit c55b89fba9872ebcd5ac15cdfdad29ffb89329f0 upstream.
This patch is solving problem for PAE kernel DMA operation.
On PAE system dma_addr and unsigned long will have different
values.
Now dma_addr is not type casted using unsigned long.
Signed-off-by: Kashyap Desai <[email protected]>
Signed-off-by: James Bottomley <[email protected]>
Cc: Jan Beulich <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/message/fusion/mptbase.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -1015,9 +1015,9 @@ mpt_add_sge_64bit(void *pAddr, u32 flags
{
SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
pSge->Address.Low = cpu_to_le32
- (lower_32_bits((unsigned long)(dma_addr)));
+ (lower_32_bits(dma_addr));
pSge->Address.High = cpu_to_le32
- (upper_32_bits((unsigned long)dma_addr));
+ (upper_32_bits(dma_addr));
pSge->FlagsLength = cpu_to_le32
((flagslength | MPT_SGE_FLAGS_64_BIT_ADDRESSING));
}
@@ -1038,8 +1038,8 @@ mpt_add_sge_64bit_1078(void *pAddr, u32
u32 tmp;
pSge->Address.Low = cpu_to_le32
- (lower_32_bits((unsigned long)(dma_addr)));
- tmp = (u32)(upper_32_bits((unsigned long)dma_addr));
+ (lower_32_bits(dma_addr));
+ tmp = (u32)(upper_32_bits(dma_addr));
/*
* 1078 errata workaround for the 36GB limitation
@@ -1101,7 +1101,7 @@ mpt_add_chain_64bit(void *pAddr, u8 next
pChain->NextChainOffset = next;
pChain->Address.Low = cpu_to_le32(tmp);
- tmp = (u32)(upper_32_bits((unsigned long)dma_addr));
+ tmp = (u32)(upper_32_bits(dma_addr));
pChain->Address.High = cpu_to_le32(tmp);
}
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: David Howells <[email protected]>
commit 645d83c5db970a1c57225e155113b4aa2451e920 upstream.
Fix MAP_PRIVATE mmap() of files and devices where the data in the backing store
might be mapped directly. Use the BDI_CAP_MAP_DIRECT capability flag to govern
whether or not we should be trying to map a file directly. This can be used to
determine whether or not a region has been filled in at the point where we call
do_mmap_shared() or do_mmap_private().
The BDI_CAP_MAP_DIRECT capability flag is cleared by validate_mmap_request() if
there's any reason we can't use it. It's also cleared in do_mmap_pgoff() if
f_op->get_unmapped_area() fails.
Without this fix, attempting to run a program from a RomFS image on a
non-mappable MTD partition results in a BUG as the kernel attempts XIP, and
this can be caught in gdb:
Program received signal SIGABRT, Aborted.
0xc005dce8 in add_nommu_region (region=<value optimized out>) at mm/nommu.c:547
(gdb) bt
#0 0xc005dce8 in add_nommu_region (region=<value optimized out>) at mm/nommu.c:547
#1 0xc005f168 in do_mmap_pgoff (file=0xc31a6620, addr=<value optimized out>, len=3808, prot=3, flags=6146, pgoff=0) at mm/nommu.c:1373
#2 0xc00a96b8 in elf_fdpic_map_file (params=0xc33fbbec, file=0xc31a6620, mm=0xc31bef60, what=0xc0213144 "executable") at mm.h:1145
#3 0xc00aa8b4 in load_elf_fdpic_binary (bprm=0xc316cb00, regs=<value optimized out>) at fs/binfmt_elf_fdpic.c:343
#4 0xc006b588 in search_binary_handler (bprm=0x6, regs=0xc33fbce0) at fs/exec.c:1234
#5 0xc006c648 in do_execve (filename=<value optimized out>, argv=0xc3ad14cc, envp=0xc3ad1460, regs=0xc33fbce0) at fs/exec.c:1356
#6 0xc0008cf0 in sys_execve (name=<value optimized out>, argv=0xc3ad14cc, envp=0xc3ad1460) at arch/frv/kernel/process.c:263
#7 0xc00075dc in __syscall_call () at arch/frv/kernel/entry.S:897
Note that this fix does the following commit differently:
commit a190887b58c32d19c2eee007c5eb8faa970a69ba
Author: David Howells <[email protected]>
Date: Sat Sep 5 11:17:07 2009 -0700
nommu: fix error handling in do_mmap_pgoff()
Reported-by: Graff Yang <[email protected]>
Signed-off-by: David Howells <[email protected]>
Acked-by: Pekka Enberg <[email protected]>
Cc: Paul Mundt <[email protected]>
Cc: Mel Gorman <[email protected]>
Cc: Greg Ungerer <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
mm/nommu.c | 34 ++++++++++++----------------------
1 file changed, 12 insertions(+), 22 deletions(-)
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -1056,7 +1056,7 @@ static int do_mmap_shared_file(struct vm
ret = vma->vm_file->f_op->mmap(vma->vm_file, vma);
if (ret == 0) {
vma->vm_region->vm_top = vma->vm_region->vm_end;
- return ret;
+ return 0;
}
if (ret != -ENOSYS)
return ret;
@@ -1073,7 +1073,8 @@ static int do_mmap_shared_file(struct vm
*/
static int do_mmap_private(struct vm_area_struct *vma,
struct vm_region *region,
- unsigned long len)
+ unsigned long len,
+ unsigned long capabilities)
{
struct page *pages;
unsigned long total, point, n, rlen;
@@ -1084,13 +1085,13 @@ static int do_mmap_private(struct vm_are
* shared mappings on devices or memory
* - VM_MAYSHARE will be set if it may attempt to share
*/
- if (vma->vm_file) {
+ if (capabilities & BDI_CAP_MAP_DIRECT) {
ret = vma->vm_file->f_op->mmap(vma->vm_file, vma);
if (ret == 0) {
/* shouldn't return success if we're not sharing */
BUG_ON(!(vma->vm_flags & VM_MAYSHARE));
vma->vm_region->vm_top = vma->vm_region->vm_end;
- return ret;
+ return 0;
}
if (ret != -ENOSYS)
return ret;
@@ -1328,7 +1329,7 @@ unsigned long do_mmap_pgoff(struct file
* - this is the hook for quasi-memory character devices to
* tell us the location of a shared mapping
*/
- if (file && file->f_op->get_unmapped_area) {
+ if (capabilities & BDI_CAP_MAP_DIRECT) {
addr = file->f_op->get_unmapped_area(file, addr, len,
pgoff, flags);
if (IS_ERR((void *) addr)) {
@@ -1352,15 +1353,17 @@ unsigned long do_mmap_pgoff(struct file
}
vma->vm_region = region;
- add_nommu_region(region);
- /* set up the mapping */
+ /* set up the mapping
+ * - the region is filled in if BDI_CAP_MAP_DIRECT is still set
+ */
if (file && vma->vm_flags & VM_SHARED)
ret = do_mmap_shared_file(vma);
else
- ret = do_mmap_private(vma, region, len);
+ ret = do_mmap_private(vma, region, len, capabilities);
if (ret < 0)
- goto error_put_region;
+ goto error_just_free;
+ add_nommu_region(region);
/* okay... we have a mapping; now we have to register it */
result = vma->vm_start;
@@ -1378,19 +1381,6 @@ share:
kleave(" = %lx", result);
return result;
-error_put_region:
- __put_nommu_region(region);
- if (vma) {
- if (vma->vm_file) {
- fput(vma->vm_file);
- if (vma->vm_flags & VM_EXECUTABLE)
- removed_exe_file_vma(vma->vm_mm);
- }
- kmem_cache_free(vm_area_cachep, vma);
- }
- kleave(" = %d [pr]", ret);
- return ret;
-
error_just_free:
up_write(&nommu_region_sem);
error:
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Jay Sternberg <[email protected]>
commit cc0f555d511a5fe9d4519334c8f674a1dbab9e3a upstream.
Adding new API version to account for change to ucode file format. New
header includes the build number of the ucode. This build number is the
SVN revision thus allowing for exact correlation to the code that
generated it.
The header adds the build number so that older ucode images can also be
enhanced to include the build in the future.
some cleanup in iwl_read_ucode needed to ensure old header not used and
reduce unnecessary references through pointer with the data is already
in heap variable.
Signed-off-by: Jay Sternberg <[email protected]>
Signed-off-by: Reinette Chatre <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-3945.c | 40 ++++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl-4965.c | 39 +++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl-5000.c | 51 +++++++++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl-6000.c | 5 +-
drivers/net/wireless/iwlwifi/iwl-agn.c | 55 ++++++++++++++++------------
drivers/net/wireless/iwlwifi/iwl-core.h | 12 ++++++
drivers/net/wireless/iwlwifi/iwl-dev.h | 31 +++++++++++----
drivers/net/wireless/iwlwifi/iwl3945-base.c | 45 ++++++++++++----------
8 files changed, 224 insertions(+), 54 deletions(-)
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -2111,7 +2111,7 @@ static void iwl3945_nic_start(struct iwl
*/
static int iwl3945_read_ucode(struct iwl_priv *priv)
{
- struct iwl_ucode *ucode;
+ const struct iwl_ucode_header *ucode;
int ret = -EINVAL, index;
const struct firmware *ucode_raw;
/* firmware file name contains uCode/driver compatibility version */
@@ -2152,22 +2152,24 @@ static int iwl3945_read_ucode(struct iwl
goto error;
/* Make sure that we got at least our header! */
- if (ucode_raw->size < sizeof(*ucode)) {
+ if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) {
IWL_ERR(priv, "File size way too small!\n");
ret = -EINVAL;
goto err_release;
}
/* Data from ucode file: header followed by uCode images */
- ucode = (void *)ucode_raw->data;
+ ucode = (struct iwl_ucode_header *)ucode_raw->data;
priv->ucode_ver = le32_to_cpu(ucode->ver);
api_ver = IWL_UCODE_API(priv->ucode_ver);
- inst_size = le32_to_cpu(ucode->inst_size);
- data_size = le32_to_cpu(ucode->data_size);
- init_size = le32_to_cpu(ucode->init_size);
- init_data_size = le32_to_cpu(ucode->init_data_size);
- boot_size = le32_to_cpu(ucode->boot_size);
+ inst_size = priv->cfg->ops->ucode->get_inst_size(ucode, api_ver);
+ data_size = priv->cfg->ops->ucode->get_data_size(ucode, api_ver);
+ init_size = priv->cfg->ops->ucode->get_init_size(ucode, api_ver);
+ init_data_size =
+ priv->cfg->ops->ucode->get_init_data_size(ucode, api_ver);
+ boot_size = priv->cfg->ops->ucode->get_boot_size(ucode, api_ver);
+ src = priv->cfg->ops->ucode->get_data(ucode, api_ver);
/* api_ver should match the api version forming part of the
* firmware filename ... but we don't check for that and only rely
@@ -2208,12 +2210,13 @@ static int iwl3945_read_ucode(struct iwl
/* Verify size of file vs. image size info in file's header */
- if (ucode_raw->size < sizeof(*ucode) +
+ if (ucode_raw->size != priv->cfg->ops->ucode->get_header_size(api_ver) +
inst_size + data_size + init_size +
init_data_size + boot_size) {
- IWL_DEBUG_INFO(priv, "uCode file size %zd too small\n",
- ucode_raw->size);
+ IWL_DEBUG_INFO(priv,
+ "uCode file size %zd does not match expected size\n",
+ ucode_raw->size);
ret = -EINVAL;
goto err_release;
}
@@ -2296,44 +2299,44 @@ static int iwl3945_read_ucode(struct iwl
/* Copy images into buffers for card's bus-master reads ... */
/* Runtime instructions (first block of data in file) */
- src = &ucode->data[0];
- len = priv->ucode_code.len;
+ len = inst_size;
IWL_DEBUG_INFO(priv,
"Copying (but not loading) uCode instr len %zd\n", len);
memcpy(priv->ucode_code.v_addr, src, len);
+ src += len;
+
IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
/* Runtime data (2nd block)
* NOTE: Copy into backup buffer will be done in iwl3945_up() */
- src = &ucode->data[inst_size];
- len = priv->ucode_data.len;
+ len = data_size;
IWL_DEBUG_INFO(priv,
"Copying (but not loading) uCode data len %zd\n", len);
memcpy(priv->ucode_data.v_addr, src, len);
memcpy(priv->ucode_data_backup.v_addr, src, len);
+ src += len;
/* Initialization instructions (3rd block) */
if (init_size) {
- src = &ucode->data[inst_size + data_size];
- len = priv->ucode_init.len;
+ len = init_size;
IWL_DEBUG_INFO(priv,
"Copying (but not loading) init instr len %zd\n", len);
memcpy(priv->ucode_init.v_addr, src, len);
+ src += len;
}
/* Initialization data (4th block) */
if (init_data_size) {
- src = &ucode->data[inst_size + data_size + init_size];
- len = priv->ucode_init_data.len;
+ len = init_data_size;
IWL_DEBUG_INFO(priv,
"Copying (but not loading) init data len %zd\n", len);
memcpy(priv->ucode_init_data.v_addr, src, len);
+ src += len;
}
/* Bootstrap instructions (5th block) */
- src = &ucode->data[inst_size + data_size + init_size + init_data_size];
- len = priv->ucode_boot.len;
+ len = boot_size;
IWL_DEBUG_INFO(priv,
"Copying (but not loading) boot instr len %zd\n", len);
memcpy(priv->ucode_boot.v_addr, src, len);
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -2784,11 +2784,50 @@ static int iwl3945_load_bsm(struct iwl_p
return 0;
}
+#define IWL3945_UCODE_GET(item) \
+static u32 iwl3945_ucode_get_##item(const struct iwl_ucode_header *ucode,\
+ u32 api_ver) \
+{ \
+ return le32_to_cpu(ucode->u.v1.item); \
+}
+
+static u32 iwl3945_ucode_get_header_size(u32 api_ver)
+{
+ return UCODE_HEADER_SIZE(1);
+}
+static u32 iwl3945_ucode_get_build(const struct iwl_ucode_header *ucode,
+ u32 api_ver)
+{
+ return 0;
+}
+static u8 *iwl3945_ucode_get_data(const struct iwl_ucode_header *ucode,
+ u32 api_ver)
+{
+ return (u8 *) ucode->u.v1.data;
+}
+
+IWL3945_UCODE_GET(inst_size);
+IWL3945_UCODE_GET(data_size);
+IWL3945_UCODE_GET(init_size);
+IWL3945_UCODE_GET(init_data_size);
+IWL3945_UCODE_GET(boot_size);
+
static struct iwl_hcmd_ops iwl3945_hcmd = {
.rxon_assoc = iwl3945_send_rxon_assoc,
.commit_rxon = iwl3945_commit_rxon,
};
+static struct iwl_ucode_ops iwl3945_ucode = {
+ .get_header_size = iwl3945_ucode_get_header_size,
+ .get_build = iwl3945_ucode_get_build,
+ .get_inst_size = iwl3945_ucode_get_inst_size,
+ .get_data_size = iwl3945_ucode_get_data_size,
+ .get_init_size = iwl3945_ucode_get_init_size,
+ .get_init_data_size = iwl3945_ucode_get_init_data_size,
+ .get_boot_size = iwl3945_ucode_get_boot_size,
+ .get_data = iwl3945_ucode_get_data,
+};
+
static struct iwl_lib_ops iwl3945_lib = {
.txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd,
.txq_free_tfd = iwl3945_hw_txq_free_tfd,
@@ -2829,6 +2868,7 @@ static struct iwl_hcmd_utils_ops iwl3945
};
static struct iwl_ops iwl3945_ops = {
+ .ucode = &iwl3945_ucode,
.lib = &iwl3945_lib,
.hcmd = &iwl3945_hcmd,
.utils = &iwl3945_hcmd_utils,
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -2221,12 +2221,50 @@ static void iwl4965_cancel_deferred_work
cancel_work_sync(&priv->txpower_work);
}
+#define IWL4965_UCODE_GET(item) \
+static u32 iwl4965_ucode_get_##item(const struct iwl_ucode_header *ucode,\
+ u32 api_ver) \
+{ \
+ return le32_to_cpu(ucode->u.v1.item); \
+}
+
+static u32 iwl4965_ucode_get_header_size(u32 api_ver)
+{
+ return UCODE_HEADER_SIZE(1);
+}
+static u32 iwl4965_ucode_get_build(const struct iwl_ucode_header *ucode,
+ u32 api_ver)
+{
+ return 0;
+}
+static u8 *iwl4965_ucode_get_data(const struct iwl_ucode_header *ucode,
+ u32 api_ver)
+{
+ return (u8 *) ucode->u.v1.data;
+}
+
+IWL4965_UCODE_GET(inst_size);
+IWL4965_UCODE_GET(data_size);
+IWL4965_UCODE_GET(init_size);
+IWL4965_UCODE_GET(init_data_size);
+IWL4965_UCODE_GET(boot_size);
+
static struct iwl_hcmd_ops iwl4965_hcmd = {
.rxon_assoc = iwl4965_send_rxon_assoc,
.commit_rxon = iwl_commit_rxon,
.set_rxon_chain = iwl_set_rxon_chain,
};
+static struct iwl_ucode_ops iwl4965_ucode = {
+ .get_header_size = iwl4965_ucode_get_header_size,
+ .get_build = iwl4965_ucode_get_build,
+ .get_inst_size = iwl4965_ucode_get_inst_size,
+ .get_data_size = iwl4965_ucode_get_data_size,
+ .get_init_size = iwl4965_ucode_get_init_size,
+ .get_init_data_size = iwl4965_ucode_get_init_data_size,
+ .get_boot_size = iwl4965_ucode_get_boot_size,
+ .get_data = iwl4965_ucode_get_data,
+};
static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
.get_hcmd_size = iwl4965_get_hcmd_size,
.build_addsta_hcmd = iwl4965_build_addsta_hcmd,
@@ -2287,6 +2325,7 @@ static struct iwl_lib_ops iwl4965_lib =
};
static struct iwl_ops iwl4965_ops = {
+ .ucode = &iwl4965_ucode,
.lib = &iwl4965_lib,
.hcmd = &iwl4965_hcmd,
.utils = &iwl4965_hcmd_utils,
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -1426,6 +1426,44 @@ int iwl5000_calc_rssi(struct iwl_priv *p
return max_rssi - agc - IWL49_RSSI_OFFSET;
}
+#define IWL5000_UCODE_GET(item) \
+static u32 iwl5000_ucode_get_##item(const struct iwl_ucode_header *ucode,\
+ u32 api_ver) \
+{ \
+ if (api_ver <= 2) \
+ return le32_to_cpu(ucode->u.v1.item); \
+ return le32_to_cpu(ucode->u.v2.item); \
+}
+
+static u32 iwl5000_ucode_get_header_size(u32 api_ver)
+{
+ if (api_ver <= 2)
+ return UCODE_HEADER_SIZE(1);
+ return UCODE_HEADER_SIZE(2);
+}
+
+static u32 iwl5000_ucode_get_build(const struct iwl_ucode_header *ucode,
+ u32 api_ver)
+{
+ if (api_ver <= 2)
+ return 0;
+ return le32_to_cpu(ucode->u.v2.build);
+}
+
+static u8 *iwl5000_ucode_get_data(const struct iwl_ucode_header *ucode,
+ u32 api_ver)
+{
+ if (api_ver <= 2)
+ return (u8 *) ucode->u.v1.data;
+ return (u8 *) ucode->u.v2.data;
+}
+
+IWL5000_UCODE_GET(inst_size);
+IWL5000_UCODE_GET(data_size);
+IWL5000_UCODE_GET(init_size);
+IWL5000_UCODE_GET(init_data_size);
+IWL5000_UCODE_GET(boot_size);
+
struct iwl_hcmd_ops iwl5000_hcmd = {
.rxon_assoc = iwl5000_send_rxon_assoc,
.commit_rxon = iwl_commit_rxon,
@@ -1441,6 +1479,17 @@ struct iwl_hcmd_utils_ops iwl5000_hcmd_u
.calc_rssi = iwl5000_calc_rssi,
};
+struct iwl_ucode_ops iwl5000_ucode = {
+ .get_header_size = iwl5000_ucode_get_header_size,
+ .get_build = iwl5000_ucode_get_build,
+ .get_inst_size = iwl5000_ucode_get_inst_size,
+ .get_data_size = iwl5000_ucode_get_data_size,
+ .get_init_size = iwl5000_ucode_get_init_size,
+ .get_init_data_size = iwl5000_ucode_get_init_data_size,
+ .get_boot_size = iwl5000_ucode_get_boot_size,
+ .get_data = iwl5000_ucode_get_data,
+};
+
struct iwl_lib_ops iwl5000_lib = {
.set_hw_params = iwl5000_hw_set_hw_params,
.txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
@@ -1542,12 +1591,14 @@ static struct iwl_lib_ops iwl5150_lib =
};
struct iwl_ops iwl5000_ops = {
+ .ucode = &iwl5000_ucode,
.lib = &iwl5000_lib,
.hcmd = &iwl5000_hcmd,
.utils = &iwl5000_hcmd_utils,
};
static struct iwl_ops iwl5150_ops = {
+ .ucode = &iwl5000_ucode,
.lib = &iwl5150_lib,
.hcmd = &iwl5000_hcmd,
.utils = &iwl5000_hcmd_utils,
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -46,8 +46,8 @@
#include "iwl-5000-hw.h"
/* Highest firmware API version supported */
-#define IWL6000_UCODE_API_MAX 2
-#define IWL6050_UCODE_API_MAX 2
+#define IWL6000_UCODE_API_MAX 3
+#define IWL6050_UCODE_API_MAX 3
/* Lowest firmware API version supported */
#define IWL6000_UCODE_API_MIN 1
@@ -69,6 +69,7 @@ static struct iwl_hcmd_utils_ops iwl6000
};
static struct iwl_ops iwl6000_ops = {
+ .ucode = &iwl5000_ucode,
.lib = &iwl5000_lib,
.hcmd = &iwl5000_hcmd,
.utils = &iwl6000_hcmd_utils,
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1348,7 +1348,7 @@ static void iwl_nic_start(struct iwl_pri
*/
static int iwl_read_ucode(struct iwl_priv *priv)
{
- struct iwl_ucode *ucode;
+ struct iwl_ucode_header *ucode;
int ret = -EINVAL, index;
const struct firmware *ucode_raw;
const char *name_pre = priv->cfg->fw_name_pre;
@@ -1357,7 +1357,8 @@ static int iwl_read_ucode(struct iwl_pri
char buf[25];
u8 *src;
size_t len;
- u32 api_ver, inst_size, data_size, init_size, init_data_size, boot_size;
+ u32 api_ver, build;
+ u32 inst_size, data_size, init_size, init_data_size, boot_size;
/* Ask kernel firmware_class module to get the boot firmware off disk.
* request_firmware() is synchronous, file is in memory on return. */
@@ -1387,23 +1388,26 @@ static int iwl_read_ucode(struct iwl_pri
if (ret < 0)
goto error;
- /* Make sure that we got at least our header! */
- if (ucode_raw->size < sizeof(*ucode)) {
+ /* Make sure that we got at least the v1 header! */
+ if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) {
IWL_ERR(priv, "File size way too small!\n");
ret = -EINVAL;
goto err_release;
}
/* Data from ucode file: header followed by uCode images */
- ucode = (void *)ucode_raw->data;
+ ucode = (struct iwl_ucode_header *)ucode_raw->data;
priv->ucode_ver = le32_to_cpu(ucode->ver);
api_ver = IWL_UCODE_API(priv->ucode_ver);
- inst_size = le32_to_cpu(ucode->inst_size);
- data_size = le32_to_cpu(ucode->data_size);
- init_size = le32_to_cpu(ucode->init_size);
- init_data_size = le32_to_cpu(ucode->init_data_size);
- boot_size = le32_to_cpu(ucode->boot_size);
+ build = priv->cfg->ops->ucode->get_build(ucode, api_ver);
+ inst_size = priv->cfg->ops->ucode->get_inst_size(ucode, api_ver);
+ data_size = priv->cfg->ops->ucode->get_data_size(ucode, api_ver);
+ init_size = priv->cfg->ops->ucode->get_init_size(ucode, api_ver);
+ init_data_size =
+ priv->cfg->ops->ucode->get_init_data_size(ucode, api_ver);
+ boot_size = priv->cfg->ops->ucode->get_boot_size(ucode, api_ver);
+ src = priv->cfg->ops->ucode->get_data(ucode, api_ver);
/* api_ver should match the api version forming part of the
* firmware filename ... but we don't check for that and only rely
@@ -1429,6 +1433,9 @@ static int iwl_read_ucode(struct iwl_pri
IWL_UCODE_API(priv->ucode_ver),
IWL_UCODE_SERIAL(priv->ucode_ver));
+ if (build)
+ IWL_DEBUG_INFO(priv, "Build %u\n", build);
+
IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n",
priv->ucode_ver);
IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n",
@@ -1443,12 +1450,14 @@ static int iwl_read_ucode(struct iwl_pri
boot_size);
/* Verify size of file vs. image size info in file's header */
- if (ucode_raw->size < sizeof(*ucode) +
+ if (ucode_raw->size !=
+ priv->cfg->ops->ucode->get_header_size(api_ver) +
inst_size + data_size + init_size +
init_data_size + boot_size) {
- IWL_DEBUG_INFO(priv, "uCode file size %d too small\n",
- (int)ucode_raw->size);
+ IWL_DEBUG_INFO(priv,
+ "uCode file size %d does not match expected size\n",
+ (int)ucode_raw->size);
ret = -EINVAL;
goto err_release;
}
@@ -1528,42 +1537,42 @@ static int iwl_read_ucode(struct iwl_pri
/* Copy images into buffers for card's bus-master reads ... */
/* Runtime instructions (first block of data in file) */
- src = &ucode->data[0];
- len = priv->ucode_code.len;
+ len = inst_size;
IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n", len);
memcpy(priv->ucode_code.v_addr, src, len);
+ src += len;
+
IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
/* Runtime data (2nd block)
* NOTE: Copy into backup buffer will be done in iwl_up() */
- src = &ucode->data[inst_size];
- len = priv->ucode_data.len;
+ len = data_size;
IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n", len);
memcpy(priv->ucode_data.v_addr, src, len);
memcpy(priv->ucode_data_backup.v_addr, src, len);
+ src += len;
/* Initialization instructions (3rd block) */
if (init_size) {
- src = &ucode->data[inst_size + data_size];
- len = priv->ucode_init.len;
+ len = init_size;
IWL_DEBUG_INFO(priv, "Copying (but not loading) init instr len %Zd\n",
len);
memcpy(priv->ucode_init.v_addr, src, len);
+ src += len;
}
/* Initialization data (4th block) */
if (init_data_size) {
- src = &ucode->data[inst_size + data_size + init_size];
- len = priv->ucode_init_data.len;
+ len = init_data_size;
IWL_DEBUG_INFO(priv, "Copying (but not loading) init data len %Zd\n",
len);
memcpy(priv->ucode_init_data.v_addr, src, len);
+ src += len;
}
/* Bootstrap instructions (5th block) */
- src = &ucode->data[inst_size + data_size + init_size + init_data_size];
- len = priv->ucode_boot.len;
+ len = boot_size;
IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n", len);
memcpy(priv->ucode_boot.v_addr, src, len);
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -116,6 +116,17 @@ struct iwl_temp_ops {
void (*set_ct_kill)(struct iwl_priv *priv);
};
+struct iwl_ucode_ops {
+ u32 (*get_header_size)(u32);
+ u32 (*get_build)(const struct iwl_ucode_header *, u32);
+ u32 (*get_inst_size)(const struct iwl_ucode_header *, u32);
+ u32 (*get_data_size)(const struct iwl_ucode_header *, u32);
+ u32 (*get_init_size)(const struct iwl_ucode_header *, u32);
+ u32 (*get_init_data_size)(const struct iwl_ucode_header *, u32);
+ u32 (*get_boot_size)(const struct iwl_ucode_header *, u32);
+ u8 * (*get_data)(const struct iwl_ucode_header *, u32);
+};
+
struct iwl_lib_ops {
/* set hw dependent parameters */
int (*set_hw_params)(struct iwl_priv *priv);
@@ -171,6 +182,7 @@ struct iwl_lib_ops {
};
struct iwl_ops {
+ const struct iwl_ucode_ops *ucode;
const struct iwl_lib_ops *lib;
const struct iwl_hcmd_ops *hcmd;
const struct iwl_hcmd_utils_ops *utils;
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -66,6 +66,7 @@ extern struct iwl_cfg iwl1000_bgn_cfg;
/* shared structures from iwl-5000.c */
extern struct iwl_mod_params iwl50_mod_params;
extern struct iwl_ops iwl5000_ops;
+extern struct iwl_ucode_ops iwl5000_ucode;
extern struct iwl_lib_ops iwl5000_lib;
extern struct iwl_hcmd_ops iwl5000_hcmd;
extern struct iwl_hcmd_utils_ops iwl5000_hcmd_utils;
@@ -525,15 +526,29 @@ struct fw_desc {
};
/* uCode file layout */
-struct iwl_ucode {
- __le32 ver; /* major/minor/API/serial */
- __le32 inst_size; /* bytes of runtime instructions */
- __le32 data_size; /* bytes of runtime data */
- __le32 init_size; /* bytes of initialization instructions */
- __le32 init_data_size; /* bytes of initialization data */
- __le32 boot_size; /* bytes of bootstrap instructions */
- u8 data[0]; /* data in same order as "size" elements */
+struct iwl_ucode_header {
+ __le32 ver; /* major/minor/API/serial */
+ union {
+ struct {
+ __le32 inst_size; /* bytes of runtime code */
+ __le32 data_size; /* bytes of runtime data */
+ __le32 init_size; /* bytes of init code */
+ __le32 init_data_size; /* bytes of init data */
+ __le32 boot_size; /* bytes of bootstrap code */
+ u8 data[0]; /* in same order as sizes */
+ } v1;
+ struct {
+ __le32 build; /* build number */
+ __le32 inst_size; /* bytes of runtime code */
+ __le32 data_size; /* bytes of runtime data */
+ __le32 init_size; /* bytes of init code */
+ __le32 init_data_size; /* bytes of init data */
+ __le32 boot_size; /* bytes of bootstrap code */
+ u8 data[0]; /* in same order as sizes */
+ } v2;
+ } u;
};
+#define UCODE_HEADER_SIZE(ver) ((ver) == 1 ? 24 : 28)
struct iwl4965_ibss_seq {
u8 mac[ETH_ALEN];
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Jay Sternberg <[email protected]>
commit cce53aa347c1e023d967b1cb1aa393c725aedba5 upstream.
firmware file now contains build number so API needs to be updated.
Signed-off-by: Jay Sternberg <[email protected]>
Signed-off-by: Reinette Chatre <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-1000.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -46,7 +46,7 @@
#include "iwl-5000-hw.h"
/* Highest firmware API version supported */
-#define IWL1000_UCODE_API_MAX 2
+#define IWL1000_UCODE_API_MAX 3
/* Lowest firmware API version supported */
#define IWL1000_UCODE_API_MIN 1
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Wey-Yi Guy <[email protected]>
commit 02c06e4abc0680afd31bf481a803541556757fb6 upstream.
On 1000, there are two Switching Voltage Regulators (SVR). The first one
apply digital voltage level (1.32V) for PCIe block and core. We need to
use this regulator to solve a stability issue related to noisy DC2DC
line in the silicon.
Signed-off-by: Wey-Yi Guy <[email protected]>
Signed-off-by: Reinette Chatre <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-5000.c | 7 +++++++
drivers/net/wireless/iwlwifi/iwl-prph.h | 5 ++++-
2 files changed, 11 insertions(+), 1 deletion(-)
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -239,6 +239,13 @@ static void iwl5000_nic_config(struct iw
APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
+ if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_1000) {
+ /* Setting digital SVR for 1000 card to 1.32V */
+ iwl_set_bits_mask_prph(priv, APMG_DIGITAL_SVR_REG,
+ APMG_SVR_DIGITAL_VOLTAGE_1_32,
+ ~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK);
+ }
+
spin_unlock_irqrestore(&priv->lock, flags);
}
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -80,6 +80,8 @@
#define APMG_RFKILL_REG (APMG_BASE + 0x0014)
#define APMG_RTC_INT_STT_REG (APMG_BASE + 0x001c)
#define APMG_RTC_INT_MSK_REG (APMG_BASE + 0x0020)
+#define APMG_DIGITAL_SVR_REG (APMG_BASE + 0x0058)
+#define APMG_ANALOG_SVR_REG (APMG_BASE + 0x006C)
#define APMG_CLK_VAL_DMA_CLK_RQT (0x00000200)
#define APMG_CLK_VAL_BSM_CLK_RQT (0x00000800)
@@ -91,7 +93,8 @@
#define APMG_PS_CTRL_VAL_PWR_SRC_VMAIN (0x00000000)
#define APMG_PS_CTRL_VAL_PWR_SRC_MAX (0x01000000) /* 3945 only */
#define APMG_PS_CTRL_VAL_PWR_SRC_VAUX (0x02000000)
-
+#define APMG_SVR_VOLTAGE_CONFIG_BIT_MSK (0x000001E0) /* bit 8:5 */
+#define APMG_SVR_DIGITAL_VOLTAGE_1_32 (0x00000060)
#define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800)
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Wey-Yi Guy <[email protected]>
commit 415e49936b4b29b34c2fb561eeab867d41fc43a6 upstream.
For devices using OTP memory, EEPROM image can start from
any one of the OTP blocks. If shadow RAM is disabled, we need to
traverse link list to find the last valid block, then start the EEPROM
image reading.
If OTP is not full, the valid block is the block _before_ the last block
on the link list; the last block on the link list is the empty block
ready for next OTP refresh/update.
If OTP is full, then the last block is the valid block to be used for
configure the device.
Signed-off-by: Wey-Yi Guy <[email protected]>
Signed-off-by: Reinette Chatre <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-1000.c | 4
drivers/net/wireless/iwlwifi/iwl-6000.c | 20 ++-
drivers/net/wireless/iwlwifi/iwl-core.h | 4
drivers/net/wireless/iwlwifi/iwl-dev.h | 12 +
drivers/net/wireless/iwlwifi/iwl-eeprom.c | 185 ++++++++++++++++++++++++------
drivers/net/wireless/iwlwifi/iwl-eeprom.h | 10 +
6 files changed, 192 insertions(+), 43 deletions(-)
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -62,12 +62,14 @@ struct iwl_cfg iwl1000_bgn_cfg = {
.ucode_api_min = IWL1000_UCODE_API_MIN,
.sku = IWL_SKU_G|IWL_SKU_N,
.ops = &iwl5000_ops,
- .eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+ .eeprom_size = OTP_LOW_IMAGE_SIZE,
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.mod_params = &iwl50_mod_params,
.valid_tx_ant = ANT_A,
.valid_rx_ant = ANT_AB,
.need_pll_cfg = true,
+ .max_ll_items = OTP_MAX_LL_ITEMS_1000,
+ .shadow_ram_support = false,
};
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -82,13 +82,15 @@ struct iwl_cfg iwl6000_2ag_cfg = {
.ucode_api_min = IWL6000_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G,
.ops = &iwl6000_ops,
- .eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+ .eeprom_size = OTP_LOW_IMAGE_SIZE,
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.mod_params = &iwl50_mod_params,
.valid_tx_ant = ANT_BC,
.valid_rx_ant = ANT_BC,
.need_pll_cfg = false,
+ .max_ll_items = OTP_MAX_LL_ITEMS_6x00,
+ .shadow_ram_support = true,
};
struct iwl_cfg iwl6000_2agn_cfg = {
@@ -98,13 +100,15 @@ struct iwl_cfg iwl6000_2agn_cfg = {
.ucode_api_min = IWL6000_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
.ops = &iwl6000_ops,
- .eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+ .eeprom_size = OTP_LOW_IMAGE_SIZE,
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.mod_params = &iwl50_mod_params,
.valid_tx_ant = ANT_AB,
.valid_rx_ant = ANT_AB,
.need_pll_cfg = false,
+ .max_ll_items = OTP_MAX_LL_ITEMS_6x00,
+ .shadow_ram_support = true,
};
struct iwl_cfg iwl6050_2agn_cfg = {
@@ -114,13 +118,15 @@ struct iwl_cfg iwl6050_2agn_cfg = {
.ucode_api_min = IWL6050_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
.ops = &iwl6000_ops,
- .eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+ .eeprom_size = OTP_LOW_IMAGE_SIZE,
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.mod_params = &iwl50_mod_params,
.valid_tx_ant = ANT_AB,
.valid_rx_ant = ANT_AB,
.need_pll_cfg = false,
+ .max_ll_items = OTP_MAX_LL_ITEMS_6x00,
+ .shadow_ram_support = true,
};
struct iwl_cfg iwl6000_3agn_cfg = {
@@ -130,13 +136,15 @@ struct iwl_cfg iwl6000_3agn_cfg = {
.ucode_api_min = IWL6000_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
.ops = &iwl6000_ops,
- .eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+ .eeprom_size = OTP_LOW_IMAGE_SIZE,
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.mod_params = &iwl50_mod_params,
.valid_tx_ant = ANT_ABC,
.valid_rx_ant = ANT_ABC,
.need_pll_cfg = false,
+ .max_ll_items = OTP_MAX_LL_ITEMS_6x00,
+ .shadow_ram_support = true,
};
struct iwl_cfg iwl6050_3agn_cfg = {
@@ -146,13 +154,15 @@ struct iwl_cfg iwl6050_3agn_cfg = {
.ucode_api_min = IWL6050_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
.ops = &iwl6000_ops,
- .eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+ .eeprom_size = OTP_LOW_IMAGE_SIZE,
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.mod_params = &iwl50_mod_params,
.valid_tx_ant = ANT_ABC,
.valid_rx_ant = ANT_ABC,
.need_pll_cfg = false,
+ .max_ll_items = OTP_MAX_LL_ITEMS_6x00,
+ .shadow_ram_support = true,
};
MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -207,6 +207,8 @@ struct iwl_mod_params {
* filename is constructed as fw_name_pre<api>.ucode.
* @ucode_api_max: Highest version of uCode API supported by driver.
* @ucode_api_min: Lowest version of uCode API supported by driver.
+ * @max_ll_items: max number of OTP blocks
+ * @shadow_ram_support: shadow support for OTP memory
*
* We enable the driver to be backward compatible wrt API version. The
* driver specifies which APIs it supports (with @ucode_api_max being the
@@ -243,6 +245,8 @@ struct iwl_cfg {
u8 valid_rx_ant;
bool need_pll_cfg;
bool use_isr_legacy;
+ const u16 max_ll_items;
+ const bool shadow_ram_support;
};
/***************************
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -835,6 +835,18 @@ enum iwl_nvm_type {
NVM_DEVICE_TYPE_OTP,
};
+/*
+ * Two types of OTP memory access modes
+ * IWL_OTP_ACCESS_ABSOLUTE - absolute address mode,
+ * based on physical memory addressing
+ * IWL_OTP_ACCESS_RELATIVE - relative address mode,
+ * based on logical memory addressing
+ */
+enum iwl_access_mode {
+ IWL_OTP_ACCESS_ABSOLUTE,
+ IWL_OTP_ACCESS_RELATIVE,
+};
+
/* interrupt statistics */
struct isr_statistics {
u32 hw;
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -152,6 +152,19 @@ int iwlcore_eeprom_verify_signature(stru
}
EXPORT_SYMBOL(iwlcore_eeprom_verify_signature);
+static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode)
+{
+ u32 otpgp;
+
+ otpgp = iwl_read32(priv, CSR_OTP_GP_REG);
+ if (mode == IWL_OTP_ACCESS_ABSOLUTE)
+ iwl_clear_bit(priv, CSR_OTP_GP_REG,
+ CSR_OTP_GP_REG_OTP_ACCESS_MODE);
+ else
+ iwl_set_bit(priv, CSR_OTP_GP_REG,
+ CSR_OTP_GP_REG_OTP_ACCESS_MODE);
+}
+
static int iwlcore_get_nvm_type(struct iwl_priv *priv)
{
u32 otpgp;
@@ -249,6 +262,124 @@ static int iwl_init_otp_access(struct iw
return ret;
}
+static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data)
+{
+ int ret = 0;
+ u32 r;
+ u32 otpgp;
+
+ _iwl_write32(priv, CSR_EEPROM_REG,
+ CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
+ ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG,
+ CSR_EEPROM_REG_READ_VALID_MSK,
+ IWL_EEPROM_ACCESS_TIMEOUT);
+ if (ret < 0) {
+ IWL_ERR(priv, "Time out reading OTP[%d]\n", addr);
+ return ret;
+ }
+ r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
+ /* check for ECC errors: */
+ otpgp = iwl_read32(priv, CSR_OTP_GP_REG);
+ if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) {
+ /* stop in this case */
+ /* set the uncorrectable OTP ECC bit for acknowledgement */
+ iwl_set_bit(priv, CSR_OTP_GP_REG,
+ CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
+ IWL_ERR(priv, "Uncorrectable OTP ECC error, abort OTP read\n");
+ return -EINVAL;
+ }
+ if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) {
+ /* continue in this case */
+ /* set the correctable OTP ECC bit for acknowledgement */
+ iwl_set_bit(priv, CSR_OTP_GP_REG,
+ CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK);
+ IWL_ERR(priv, "Correctable OTP ECC error, continue read\n");
+ }
+ *eeprom_data = le16_to_cpu((__force __le16)(r >> 16));
+ return 0;
+}
+
+/*
+ * iwl_is_otp_empty: check for empty OTP
+ */
+static bool iwl_is_otp_empty(struct iwl_priv *priv)
+{
+ u16 next_link_addr = 0, link_value;
+ bool is_empty = false;
+
+ /* locate the beginning of OTP link list */
+ if (!iwl_read_otp_word(priv, next_link_addr, &link_value)) {
+ if (!link_value) {
+ IWL_ERR(priv, "OTP is empty\n");
+ is_empty = true;
+ }
+ } else {
+ IWL_ERR(priv, "Unable to read first block of OTP list.\n");
+ is_empty = true;
+ }
+
+ return is_empty;
+}
+
+
+/*
+ * iwl_find_otp_image: find EEPROM image in OTP
+ * finding the OTP block that contains the EEPROM image.
+ * the last valid block on the link list (the block _before_ the last block)
+ * is the block we should read and used to configure the device.
+ * If all the available OTP blocks are full, the last block will be the block
+ * we should read and used to configure the device.
+ * only perform this operation if shadow RAM is disabled
+ */
+static int iwl_find_otp_image(struct iwl_priv *priv,
+ u16 *validblockaddr)
+{
+ u16 next_link_addr = 0, link_value = 0, valid_addr;
+ int ret = 0;
+ int usedblocks = 0;
+
+ /* set addressing mode to absolute to traverse the link list */
+ iwl_set_otp_access(priv, IWL_OTP_ACCESS_ABSOLUTE);
+
+ /* checking for empty OTP or error */
+ if (iwl_is_otp_empty(priv))
+ return -EINVAL;
+
+ /*
+ * start traverse link list
+ * until reach the max number of OTP blocks
+ * different devices have different number of OTP blocks
+ */
+ do {
+ /* save current valid block address
+ * check for more block on the link list
+ */
+ valid_addr = next_link_addr;
+ next_link_addr = link_value;
+ IWL_DEBUG_INFO(priv, "OTP blocks %d addr 0x%x\n",
+ usedblocks, next_link_addr);
+ if (iwl_read_otp_word(priv, next_link_addr, &link_value))
+ return -EINVAL;
+ if (!link_value) {
+ /*
+ * reach the end of link list,
+ * set address point to the starting address
+ * of the image
+ */
+ goto done;
+ }
+ /* more in the link list, continue */
+ usedblocks++;
+ } while (usedblocks < priv->cfg->max_ll_items);
+ /* OTP full, use last block */
+ IWL_DEBUG_INFO(priv, "OTP is full, use last block\n");
+done:
+ *validblockaddr = valid_addr;
+ /* skip first 2 bytes (link list pointer) */
+ *validblockaddr += 2;
+ return ret;
+}
+
/**
* iwl_eeprom_init - read EEPROM contents
*
@@ -263,14 +394,13 @@ int iwl_eeprom_init(struct iwl_priv *pri
int sz;
int ret;
u16 addr;
- u32 otpgp;
+ u16 validblockaddr = 0;
+ u16 cache_addr = 0;
priv->nvm_device_type = iwlcore_get_nvm_type(priv);
/* allocate eeprom */
- if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
- priv->cfg->eeprom_size =
- OTP_BLOCK_SIZE * OTP_LOWER_BLOCKS_TOTAL;
+ IWL_DEBUG_INFO(priv, "NVM size = %d\n", priv->cfg->eeprom_size);
sz = priv->cfg->eeprom_size;
priv->eeprom = kzalloc(sz, GFP_KERNEL);
if (!priv->eeprom) {
@@ -298,46 +428,31 @@ int iwl_eeprom_init(struct iwl_priv *pri
if (ret) {
IWL_ERR(priv, "Failed to initialize OTP access.\n");
ret = -ENOENT;
- goto err;
+ goto done;
}
_iwl_write32(priv, CSR_EEPROM_GP,
iwl_read32(priv, CSR_EEPROM_GP) &
~CSR_EEPROM_GP_IF_OWNER_MSK);
- /* clear */
- _iwl_write32(priv, CSR_OTP_GP_REG,
- iwl_read32(priv, CSR_OTP_GP_REG) |
+
+ iwl_set_bit(priv, CSR_OTP_GP_REG,
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK |
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
-
- for (addr = 0; addr < sz; addr += sizeof(u16)) {
- u32 r;
-
- _iwl_write32(priv, CSR_EEPROM_REG,
- CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
-
- ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG,
- CSR_EEPROM_REG_READ_VALID_MSK,
- IWL_EEPROM_ACCESS_TIMEOUT);
- if (ret < 0) {
- IWL_ERR(priv, "Time out reading OTP[%d]\n", addr);
+ /* traversing the linked list if no shadow ram supported */
+ if (!priv->cfg->shadow_ram_support) {
+ if (iwl_find_otp_image(priv, &validblockaddr)) {
+ ret = -ENOENT;
goto done;
}
- r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
- /* check for ECC errors: */
- otpgp = iwl_read32(priv, CSR_OTP_GP_REG);
- if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) {
- /* stop in this case */
- IWL_ERR(priv, "Uncorrectable OTP ECC error, Abort OTP read\n");
+ }
+ for (addr = validblockaddr; addr < validblockaddr + sz;
+ addr += sizeof(u16)) {
+ u16 eeprom_data;
+
+ ret = iwl_read_otp_word(priv, addr, &eeprom_data);
+ if (ret)
goto done;
- }
- if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) {
- /* continue in this case */
- _iwl_write32(priv, CSR_OTP_GP_REG,
- iwl_read32(priv, CSR_OTP_GP_REG) |
- CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK);
- IWL_ERR(priv, "Correctable OTP ECC error, continue read\n");
- }
- e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
+ e[cache_addr / 2] = eeprom_data;
+ cache_addr += sizeof(u16);
}
} else {
/* eeprom is an array of 16bit values */
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -180,8 +180,14 @@ struct iwl_eeprom_channel {
#define EEPROM_5050_EEPROM_VERSION (0x21E)
/* OTP */
-#define OTP_LOWER_BLOCKS_TOTAL (3)
-#define OTP_BLOCK_SIZE (0x400)
+/* lower blocks contain EEPROM image and calibration data */
+#define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */
+/* high blocks contain PAPD data */
+#define OTP_HIGH_IMAGE_SIZE_6x00 (6 * 512 * sizeof(u16)) /* 6 KB */
+#define OTP_HIGH_IMAGE_SIZE_1000 (0x200 * sizeof(u16)) /* 1024 bytes */
+#define OTP_MAX_LL_ITEMS_1000 (3) /* OTP blocks for 1000 */
+#define OTP_MAX_LL_ITEMS_6x00 (4) /* OTP blocks for 6x00 */
+#define OTP_MAX_LL_ITEMS_6x50 (7) /* OTP blocks for 6x50 */
/* 2.4 GHz */
extern const u8 iwl_eeprom_band_1[14];
2.6.31-stable review patch. If anyone has any objections, please let us know.
------------------
From: Wey-Yi Guy <[email protected]>
This is commit 5bddf54962bf68002816df710348ba197d6391bb in linux-2.6.
If NetworkManager is busy scanning when user
tries to unload the module, the driver can not be unloaded
because HW still scanning.
Make sure driver sends abort scan host command to uCode if it
is in the middle of scanning during driver unload.
Signed-off-by: Wey-Yi Guy <[email protected]>
Signed-off-by: Reinette Chatre <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +-
drivers/net/wireless/iwlwifi/iwl-scan.c | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -2215,7 +2215,7 @@ static void iwl_mac_stop(struct ieee8021
priv->is_open = 0;
- if (iwl_is_ready_rf(priv)) {
+ if (iwl_is_ready_rf(priv) || test_bit(STATUS_SCAN_HW, &priv->status)) {
/* stop mac, cancel any scan request and clear
* RXON_FILTER_ASSOC_MSK BIT
*/
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -799,7 +799,8 @@ void iwl_bg_abort_scan(struct work_struc
{
struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan);
- if (!iwl_is_ready(priv))
+ if (!test_bit(STATUS_READY, &priv->status) ||
+ !test_bit(STATUS_GEO_CONFIGURED, &priv->status))
return;
mutex_lock(&priv->mutex);
Greg KH <[email protected]> writes:
> Note from the -stable maintainer on this release:
>
> This release is big. Yeah, really big. There are a number of
> areas that needed some rework in order to get things back to
> working order. Like the tty layer. Hopefully everyone can now
> use their usb to serial devices again without oopsing the
> kernel
The ftdi_sio driver still crashes and burns.
CPU 0:
Modules linked in: nfsd lockd nfs_acl auth_rpcgss exportfs sco bridge stp bnep l2cap bluetooth sunrpc ipv6 cpufreq_ondemand powernow_k8 freq_table dm_mirror dm_region_hash dm_log dm_multipath dm_mod uinput kvm_amd kvm fuse xt_multiport iptable_nat ip_tables nf_nat x_tables nf_conntrack_ipv4 nf_conntrack nf_defrag_ipv4 tun 8021q snd_hda_codec_realtek k8temp amd64_edac_mod snd_hda_intel snd_hda_codec snd_hwdep ftdi_sio firewire_ohci edac_core hwmon e1000e sata_sil24 snd_pcm snd_timer firewire_core usbserial forcedeth pata_amd crc_itu_t snd soundcore pcspkr snd_page_alloc i2c_nforce2 i2c_core sg ata_generic pata_acpi sata_nv libata sd_mod scsi_mod ext3 jbd mbcache uhci_hcd ohci_hcd ehci_hcd [last unloaded: scsi_wait_scan]
Pid: 0, comm: swapper Not tainted 2.6.31.2-rc1 #7
RIP: 0010:[<ffffffff8102c840>] [<ffffffff8102c840>] native_safe_halt+0x6/0x8
RSP: 0018:ffffffff81545e48 EFLAGS: 00000246
RAX: 0000000000000000 RBX: ffffffff81545e48 RCX: 0000000003000000
RDX: 0000000000000000 RSI: 0000000000000001 RDI: ffffffff81545e58
RBP: ffffffff8100c7ce R08: 0000000000000000 R09: 0000000000080e80
R10: 0000000000000000 R11: 000000000000000e R12: ffffffff810737df
R13: ffffffff81545dd8 R14: ffffffff8105c697 R15: ffffffff81545e38
FS: 00007fe3e0df5910(0000) GS:ffff8800017bd000(0000) knlGS:0000000000000000
CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b
CR2: 0000000001d9c000 CR3: 000000003b8e6000 CR4: 00000000000006f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Call Trace:
[<ffffffff81014126>] ? default_idle+0x51/0x8b
[<ffffffff81014265>] ? c1e_idle+0x105/0x120
[<ffffffff8100ae15>] ? cpu_idle+0xb0/0xf3
[<ffffffff81392185>] ? rest_init+0x79/0x8f
[<ffffffff815ccfae>] ? start_kernel+0x3dc/0x3fd
[<ffffffff815cc2d4>] ? x86_64_start_reservations+0xbb/0xd6
[<ffffffff815cc3f4>] ? x86_64_start_kernel+0x105/0x128
bad: scheduling from the idle thread!
Pid: 0, comm: swapper Not tainted 2.6.31.2-rc1 #7
Call Trace:
<IRQ> [<ffffffff81041021>] dequeue_task_idle+0x37/0x5a
[<ffffffff810407e3>] dequeue_task+0xce/0xf0
[<ffffffff8104083c>] deactivate_task+0x37/0x56
[<ffffffff813a4fc7>] schedule+0x13d/0x6f3
[<ffffffff81042942>] ? enqueue_task_fair+0xdf/0x13c
[<ffffffff810700a2>] ? sched_clock_cpu+0x162/0x17f
[<ffffffff813a5e97>] __mutex_lock_common+0x12f/0x1aa
[<ffffffff813a5f39>] __mutex_lock_slowpath+0x27/0x3d
[<ffffffff813a5c4d>] mutex_lock+0x25/0x53
[<ffffffff81253f55>] tty_unthrottle+0x29/0x6d
[<ffffffff812528e6>] reset_buffer_flags+0xe8/0x105
[<ffffffff81252927>] n_tty_flush_buffer+0x24/0x97
[<ffffffff812535d7>] n_tty_receive_buf+0xc3d/0xe72
[<ffffffff8129b8b1>] ? usb_submit_urb+0x30d/0x33f
[<ffffffff8129b151>] ? usb_hcd_submit_urb+0x888/0x943
[<ffffffff81254ddf>] ? tty_ldisc_try+0x53/0x71
[<ffffffff81255ee1>] flush_to_ldisc+0x116/0x1bd
[<ffffffff81255fe6>] tty_flip_buffer_push+0x5e/0x85
[<ffffffffa01ff0ab>] ftdi_process_read+0x481/0x627 [ftdi_sio]
[<ffffffffa0000fa3>] ? ehci_qtd_free+0x27/0x3d [ehci_hcd]
[<ffffffffa01ff480>] ftdi_read_bulk_callback+0x22f/0x25a [ftdi_sio]
[<ffffffff81040c49>] ? complete+0x54/0x73
[<ffffffffa00db214>] ? nv_host_intr+0x2f/0x87 [sata_nv]
[<ffffffff81299a86>] usb_hcd_giveback_urb+0x9b/0xe5
[<ffffffffa00010f9>] ehci_urb_done+0x91/0xbc [ehci_hcd]
[<ffffffffa00027f3>] qh_completions+0x42a/0x4ca [ehci_hcd]
[<ffffffffa0002938>] ehci_work+0xa5/0x7ab [ehci_hcd]
[<ffffffffa00db90f>] ? nv_swncq_interrupt+0x6a3/0x6d1 [sata_nv]
[<ffffffff81073401>] ? clocksource_read+0x1d/0x33
[<ffffffffa000597f>] ehci_irq+0x351/0x391 [ehci_hcd]
[<ffffffff81056273>] ? irq_exit+0x5f/0xa3
[<ffffffff81073401>] ? clocksource_read+0x1d/0x33
[<ffffffff810737df>] ? getnstimeofday+0x69/0xd3
[<ffffffff81299390>] usb_hcd_irq+0x4d/0xa1
[<ffffffff810a2313>] handle_IRQ_event+0x6a/0x13f
[<ffffffff810a43d3>] handle_fasteoi_irq+0x90/0xe1
[<ffffffff8100eb5a>] handle_irq+0x95/0xb7
[<ffffffff8100df49>] do_IRQ+0x6a/0xe0
[<ffffffff8100c7d3>] ret_from_intr+0x0/0x11
<EOI> [<ffffffff8102c840>] ? native_safe_halt+0x6/0x8
[<ffffffff81014126>] ? default_idle+0x51/0x8b
[<ffffffff81014265>] ? c1e_idle+0x105/0x120
[<ffffffff8100ae15>] ? cpu_idle+0xb0/0xf3
[<ffffffff81392185>] ? rest_init+0x79/0x8f
[<ffffffff815ccfae>] ? start_kernel+0x3dc/0x3fd
[<ffffffff815cc2d4>] ? x86_64_start_reservations+0xbb/0xd6
[<ffffffff815cc3f4>] ? x86_64_start_kernel+0x105/0x128
BUG: scheduling while atomic: swapper/0/0x00010000
Eric
On Thu, Oct 01, 2009 at 10:01:34PM -0700, Eric W. Biederman wrote:
> Greg KH <[email protected]> writes:
>
> > Note from the -stable maintainer on this release:
> >
> > This release is big. Yeah, really big. There are a number of
> > areas that needed some rework in order to get things back to
> > working order. Like the tty layer. Hopefully everyone can now
> > use their usb to serial devices again without oopsing the
> > kernel
>
> The ftdi_sio driver still crashes and burns.
What were you doing when it crashed? I tested the pl2303 device and it
worked fine for me here, I don't have a ftdi_sio one :(
thanks,
greg k-h
Greg KH <[email protected]> writes:
> On Thu, Oct 01, 2009 at 10:01:34PM -0700, Eric W. Biederman wrote:
>> Greg KH <[email protected]> writes:
>>
>> > Note from the -stable maintainer on this release:
>> >
>> > This release is big. Yeah, really big. There are a number of
>> > areas that needed some rework in order to get things back to
>> > working order. Like the tty layer. Hopefully everyone can now
>> > use their usb to serial devices again without oopsing the
>> > kernel
>>
>> The ftdi_sio driver still crashes and burns.
>
> What were you doing when it crashed? I tested the pl2303 device and it
> worked fine for me here, I don't have a ftdi_sio one :(
sending a line every 1/10 a second in both directions. Plus I threw
in baud rate change every 20 seconds. I can kill an ftdi_sio no time that way.
I think the change to disable low latency in ftdi_sio fixes that I am build
a kernel to check that now.
Eric
Greg KH <[email protected]> writes:
> On Thu, Oct 01, 2009 at 10:01:34PM -0700, Eric W. Biederman wrote:
>> Greg KH <[email protected]> writes:
>>
>> > Note from the -stable maintainer on this release:
>> >
>> > This release is big. Yeah, really big. There are a number of
>> > areas that needed some rework in order to get things back to
>> > working order. Like the tty layer. Hopefully everyone can now
>> > use their usb to serial devices again without oopsing the
>> > kernel
>>
>> The ftdi_sio driver still crashes and burns.
>
> What were you doing when it crashed? I tested the pl2303 device and it
> worked fine for me here, I don't have a ftdi_sio one :(
The patch that floated on the list earlier does fix the worst of the
symptoms.
Eric
From: Johan Hovold <[email protected]>
Subject: [PATCH] USB: ftdi_sio: Remove tty->low_latency.
Fixes tty_flip_buffer_push being called from hard interrupt context with
low_latency set.
Signed-off-by: Johan Hovold <[email protected]>
---
drivers/usb/serial/ftdi_sio.c | 4 ----
1 files changed, 0 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 8fec5d4..22b72e8 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -1228,7 +1228,6 @@ static int set_serial_info(struct tty_struct *tty,
(new_serial.flags & ASYNC_FLAGS));
priv->custom_divisor = new_serial.custom_divisor;
- tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
write_latency_timer(port);
check_and_exit:
@@ -1699,9 +1698,6 @@ static int ftdi_open(struct tty_struct *tty,
priv->rx_bytes = 0;
spin_unlock_irqrestore(&priv->rx_lock, flags);
- if (tty)
- tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-
write_latency_timer(port);
/* No error checking for this (will get errors later anyway) */
--
1.6.2.5
On Thu, 1 Oct 2009, Greg KH wrote:
> 2.6.31-stable review patch. If anyone has any objections, please let us know.
>
> ------------------
> From: Hugh Dickins <[email protected]>
>
> commit 1ac0cb5d0e22d5e483f56b2bc12172dec1cf7536 upstream.
>
> do_anonymous_page() has been wrong to dirty the pte regardless.
> If it's not going to mark the pte writable, then it won't help
> to mark it dirty here, and clogs up memory with pages which will
> need swap instead of being thrown away. Especially wrong if no
> overcommit is chosen, and this vma is not yet VM_ACCOUNTed -
> we could exceed the limit and OOM despite no overcommit.
Thanks a lot for including this little fix in 2.6.31.2.
It is equally relevant to both 2.6.27.36 and 2.6.30.9,
so if not too late, please consider adding it into those too.
Thanks,
Hugh
>
> Signed-off-by: Hugh Dickins <[email protected]>
> Acked-by: Rik van Riel <[email protected]>
> Cc: KAMEZAWA Hiroyuki <[email protected]>
> Cc: KOSAKI Motohiro <[email protected]>
> Cc: Nick Piggin <[email protected]>
> Cc: Mel Gorman <[email protected]>
> Cc: Minchan Kim <[email protected]>
> Signed-off-by: Andrew Morton <[email protected]>
> Signed-off-by: Linus Torvalds <[email protected]>
> Signed-off-by: Greg Kroah-Hartman <[email protected]>
>
> ---
> mm/memory.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> --- a/mm/memory.c
> +++ b/mm/memory.c
> @@ -2638,7 +2638,8 @@ static int do_anonymous_page(struct mm_s
> goto oom_free_page;
>
> entry = mk_pte(page, vma->vm_page_prot);
> - entry = maybe_mkwrite(pte_mkdirty(entry), vma);
> + if (vma->vm_flags & VM_WRITE)
> + entry = pte_mkwrite(pte_mkdirty(entry));
>
> page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
> if (!pte_none(*page_table))
On Thu, 1 Oct 2009, Greg KH wrote:
> 2.6.31-stable review patch. If anyone has any objections, please let us know.
>
> ------------------
> From: Lee Schermerhorn <[email protected]>
>
> commit 252c5f94d944487e9f50ece7942b0fbf659c5c31 upstream.
>
> We noticed very erratic behavior [throughput] with the AIM7 shared
> workload running on recent distro [SLES11] and mainline kernels on an
> 8-socket, 32-core, 256GB x86_64 platform. On the SLES11 kernel
> [2.6.27.19+] with Barcelona processors, as we increased the load [10s of
> thousands of tasks], the throughput would vary between two "plateaus"--one
> at ~65K jobs per minute and one at ~130K jpm. The simple patch below
> causes the results to smooth out at the ~130k plateau.
>
> But wait, there's more:
>
> We do not see this behavior on smaller platforms--e.g., 4 socket/8 core.
> This could be the result of the larger number of cpus on the larger
> platform--a scalability issue--or it could be the result of the larger
> number of interconnect "hops" between some nodes in this platform and how
> the tasks for a given load end up distributed over the nodes' cpus and
> memories--a stochastic NUMA effect.
>
> The variability in the results are less pronounced [on the same platform]
> with Shanghai processors and with mainline kernels. With 31-rc6 on
> Shanghai processors and 288 file systems on 288 fibre attached storage
> volumes, the curves [jpm vs load] are both quite flat with the patched
> kernel consistently producing ~3.9% better throughput [~80K jpm vs ~77K
> jpm] than the unpatched kernel.
>
> Profiling indicated that the "slow" runs were incurring high[er]
> contention on an anon_vma lock in vma_adjust(), apparently called from the
> sbrk() system call.
>
> The patch:
>
> A comment in mm/mmap.c:vma_adjust() suggests that we don't really need the
> anon_vma lock when we're only adjusting the end of a vma, as is the case
> for brk(). The comment questions whether it's worth while to optimize for
> this case. Apparently, on the newer, larger x86_64 platforms, with
> interesting NUMA topologies, it is worth while--especially considering
> that the patch [if correct!] is quite simple.
>
> We can detect this condition--no overlap with next vma--by noting a NULL
> "importer". The anon_vma pointer will also be NULL in this case, so
> simply avoid loading vma->anon_vma to avoid the lock.
>
> However, we DO need to take the anon_vma lock when we're inserting a vma
> ['insert' non-NULL] even when we have no overlap [NULL "importer"], so we
> need to check for 'insert', as well. And Hugh points out that we should
> also take it when adjusting vm_start (so that rmap.c can rely upon
> vma_address() while it holds the anon_vma lock).
>
> akpm: Zhang Yanmin reprts a 150% throughput improvement with aim7, so it
> might be -stable material even though thiss isn't a regression: "this
> issue is not clear on dual socket Nehalem machine (2*4*2 cpu), but is
> severe on large machine (4*8*2 cpu)"
Thanks a lot for including this little fix in 2.6.31.2.
It is equally relevant to both 2.6.27.36 and 2.6.30.9,
so if not too late, please consider adding it into those too.
It feels weird to be arguing this way, when I argued against its
relevance to -stable in the first place: but it deserves to be
in the older stables as much as it deserves to be in the latest.
Thanks,
Hugh
>
> [[email protected]: test vma start too]
> Signed-off-by: Lee Schermerhorn <[email protected]>
> Signed-off-by: Hugh Dickins <[email protected]>
> Cc: Nick Piggin <[email protected]>
> Cc: Eric Whitney <[email protected]>
> Tested-by: "Zhang, Yanmin" <[email protected]>
> Signed-off-by: Andrew Morton <[email protected]>
> Signed-off-by: Linus Torvalds <[email protected]>
> Signed-off-by: Greg Kroah-Hartman <[email protected]>
>
> ---
> mm/mmap.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> --- a/mm/mmap.c
> +++ b/mm/mmap.c
> @@ -570,9 +570,9 @@ again: remove_next = 1 + (end > next->
>
> /*
> * When changing only vma->vm_end, we don't really need
> - * anon_vma lock: but is that case worth optimizing out?
> + * anon_vma lock.
> */
> - if (vma->anon_vma)
> + if (vma->anon_vma && (insert || importer || start != vma->vm_start))
> anon_vma = vma->anon_vma;
> if (anon_vma) {
> spin_lock(&anon_vma->lock);
Greg KH wrote:
> 2.6.31-stable review patch. If anyone has any objections, please let us know.
>
> ------------------
> From: Sarah Sharp <[email protected]>
>
> commit 66d1eebce5cca916e0b08d961690bb01c64751ef upstream.
>
> Use trb_comp_code instead of getting the completion code from the transfer
> event every time.
Are all these xhci patches really candidates for the stable tree? XHCI
support is marked as EXPERIMENTAL, the xhci standard is still at the
draft stage, and I don't believe there are any xhci products available
on the market yet.
David
--
David Vrabel, Senior Software Engineer, Drivers
CSR, Churchill House, Cambridge Business Park, Tel: +44 (0)1223 692562
Cowley Road, Cambridge, CB4 0WZ http://www.csr.com/
Member of the CSR plc group of companies. CSR plc registered in England and Wales, registered number 4187346, registered office Churchill House, Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, United Kingdom
On Thu, 1 Oct 2009, Greg KH wrote:
> 2.6.31-stable review patch. If anyone has any objections, please let us know.
>
> ------------------
> From: Hugh Dickins <[email protected]>
>
> commit 408e82b78bcc9f1b47c76e833c3df97f675947de upstream.
>
> Hiroaki Wakabayashi points out that when mlock() has been interrupted
> by SIGKILL, the subsequent munlock() takes unnecessarily long because
> its use of __get_user_pages() insists on faulting in all the pages
> which mlock() never reached.
>
> It's worse than slowness if mlock() is terminated by Out Of Memory kill:
> the munlock_vma_pages_all() in exit_mmap() insists on faulting in all the
> pages which mlock() could not find memory for; so innocent bystanders are
> killed too, and perhaps the system hangs.
>
> __get_user_pages() does a lot that's silly for munlock(): so remove the
> munlock option from __mlock_vma_pages_range(), and use a simple loop of
> follow_page()s in munlock_vma_pages_range() instead; ignoring absent
> pages, and not marking present pages as accessed or dirty.
>
> (Change munlock() to only go so far as mlock() reached? That does not
> work out, given the convention that mlock() claims complete success even
> when it has to give up early - in part so that an underlying file can be
> extended later, and those pages locked which earlier would give SIGBUS.)
Thanks a lot for including this fix in 2.6.31.2.
If I'd done my homework, I'd be asking you to include the equivalent
in 2.6.30.9 (it's irrelevant to 2.6.27.36); but because of intervening
changes, although it would appear to apply there, it would be wrong.
And it's more than a one-liner, so I'd need to retest properly.
If there's ever a call for a 2.6.30.10, I ought to supply you with
the proper patch; but for now, unless others disagree, let's not
rush it for 2.6.30.9.
Hugh
On Fri, Oct 02, 2009 at 05:38:36PM +0100, David Vrabel wrote:
> Greg KH wrote:
> > 2.6.31-stable review patch. If anyone has any objections, please let us know.
> >
> > ------------------
> > From: Sarah Sharp <[email protected]>
> >
> > commit 66d1eebce5cca916e0b08d961690bb01c64751ef upstream.
> >
> > Use trb_comp_code instead of getting the completion code from the transfer
> > event every time.
>
> Are all these xhci patches really candidates for the stable tree? XHCI
> support is marked as EXPERIMENTAL, the xhci standard is still at the
> draft stage, and I don't believe there are any xhci products available
> on the market yet.
Did you read the 000/136 message where I explained why I was accepting
all of these xhci patches into the -stable tree?
thanks,
greg k-h
On Fri, Oct 02, 2009 at 05:46:40PM +0100, Hugh Dickins wrote:
> On Thu, 1 Oct 2009, Greg KH wrote:
> > 2.6.31-stable review patch. If anyone has any objections, please let us know.
> >
> > ------------------
> > From: Hugh Dickins <[email protected]>
> >
> > commit 408e82b78bcc9f1b47c76e833c3df97f675947de upstream.
> >
> > Hiroaki Wakabayashi points out that when mlock() has been interrupted
> > by SIGKILL, the subsequent munlock() takes unnecessarily long because
> > its use of __get_user_pages() insists on faulting in all the pages
> > which mlock() never reached.
> >
> > It's worse than slowness if mlock() is terminated by Out Of Memory kill:
> > the munlock_vma_pages_all() in exit_mmap() insists on faulting in all the
> > pages which mlock() could not find memory for; so innocent bystanders are
> > killed too, and perhaps the system hangs.
> >
> > __get_user_pages() does a lot that's silly for munlock(): so remove the
> > munlock option from __mlock_vma_pages_range(), and use a simple loop of
> > follow_page()s in munlock_vma_pages_range() instead; ignoring absent
> > pages, and not marking present pages as accessed or dirty.
> >
> > (Change munlock() to only go so far as mlock() reached? That does not
> > work out, given the convention that mlock() claims complete success even
> > when it has to give up early - in part so that an underlying file can be
> > extended later, and those pages locked which earlier would give SIGBUS.)
>
> Thanks a lot for including this fix in 2.6.31.2.
>
> If I'd done my homework, I'd be asking you to include the equivalent
> in 2.6.30.9 (it's irrelevant to 2.6.27.36); but because of intervening
> changes, although it would appear to apply there, it would be wrong.
>
> And it's more than a one-liner, so I'd need to retest properly.
> If there's ever a call for a 2.6.30.10, I ought to supply you with
> the proper patch; but for now, unless others disagree, let's not
> rush it for 2.6.30.9.
Thanks, but I really don't want to create a 2.6.30.10. So if no one
needs it, I'd not want to make you do any extra work for this.
greg k-h
On Fri, Oct 02, 2009 at 05:36:44PM +0100, Hugh Dickins wrote:
> On Thu, 1 Oct 2009, Greg KH wrote:
> > 2.6.31-stable review patch. If anyone has any objections, please let us know.
> >
> > ------------------
> > From: Lee Schermerhorn <[email protected]>
> >
> > commit 252c5f94d944487e9f50ece7942b0fbf659c5c31 upstream.
> >
> > We noticed very erratic behavior [throughput] with the AIM7 shared
> > workload running on recent distro [SLES11] and mainline kernels on an
> > 8-socket, 32-core, 256GB x86_64 platform. On the SLES11 kernel
> > [2.6.27.19+] with Barcelona processors, as we increased the load [10s of
> > thousands of tasks], the throughput would vary between two "plateaus"--one
> > at ~65K jobs per minute and one at ~130K jpm. The simple patch below
> > causes the results to smooth out at the ~130k plateau.
> >
> > But wait, there's more:
> >
> > We do not see this behavior on smaller platforms--e.g., 4 socket/8 core.
> > This could be the result of the larger number of cpus on the larger
> > platform--a scalability issue--or it could be the result of the larger
> > number of interconnect "hops" between some nodes in this platform and how
> > the tasks for a given load end up distributed over the nodes' cpus and
> > memories--a stochastic NUMA effect.
> >
> > The variability in the results are less pronounced [on the same platform]
> > with Shanghai processors and with mainline kernels. With 31-rc6 on
> > Shanghai processors and 288 file systems on 288 fibre attached storage
> > volumes, the curves [jpm vs load] are both quite flat with the patched
> > kernel consistently producing ~3.9% better throughput [~80K jpm vs ~77K
> > jpm] than the unpatched kernel.
> >
> > Profiling indicated that the "slow" runs were incurring high[er]
> > contention on an anon_vma lock in vma_adjust(), apparently called from the
> > sbrk() system call.
> >
> > The patch:
> >
> > A comment in mm/mmap.c:vma_adjust() suggests that we don't really need the
> > anon_vma lock when we're only adjusting the end of a vma, as is the case
> > for brk(). The comment questions whether it's worth while to optimize for
> > this case. Apparently, on the newer, larger x86_64 platforms, with
> > interesting NUMA topologies, it is worth while--especially considering
> > that the patch [if correct!] is quite simple.
> >
> > We can detect this condition--no overlap with next vma--by noting a NULL
> > "importer". The anon_vma pointer will also be NULL in this case, so
> > simply avoid loading vma->anon_vma to avoid the lock.
> >
> > However, we DO need to take the anon_vma lock when we're inserting a vma
> > ['insert' non-NULL] even when we have no overlap [NULL "importer"], so we
> > need to check for 'insert', as well. And Hugh points out that we should
> > also take it when adjusting vm_start (so that rmap.c can rely upon
> > vma_address() while it holds the anon_vma lock).
> >
> > akpm: Zhang Yanmin reprts a 150% throughput improvement with aim7, so it
> > might be -stable material even though thiss isn't a regression: "this
> > issue is not clear on dual socket Nehalem machine (2*4*2 cpu), but is
> > severe on large machine (4*8*2 cpu)"
>
> Thanks a lot for including this little fix in 2.6.31.2.
> It is equally relevant to both 2.6.27.36 and 2.6.30.9,
> so if not too late, please consider adding it into those too.
>
> It feels weird to be arguing this way, when I argued against its
> relevance to -stable in the first place: but it deserves to be
> in the older stables as much as it deserves to be in the latest.
Ok, I'll go queue it up for these .30 and .27 releases.
thanks for letting me know.
greg k-h
On Fri, Oct 02, 2009 at 05:34:03PM +0100, Hugh Dickins wrote:
> On Thu, 1 Oct 2009, Greg KH wrote:
> > 2.6.31-stable review patch. If anyone has any objections, please let us know.
> >
> > ------------------
> > From: Hugh Dickins <[email protected]>
> >
> > commit 1ac0cb5d0e22d5e483f56b2bc12172dec1cf7536 upstream.
> >
> > do_anonymous_page() has been wrong to dirty the pte regardless.
> > If it's not going to mark the pte writable, then it won't help
> > to mark it dirty here, and clogs up memory with pages which will
> > need swap instead of being thrown away. Especially wrong if no
> > overcommit is chosen, and this vma is not yet VM_ACCOUNTed -
> > we could exceed the limit and OOM despite no overcommit.
>
> Thanks a lot for including this little fix in 2.6.31.2.
> It is equally relevant to both 2.6.27.36 and 2.6.30.9,
> so if not too late, please consider adding it into those too.
Ok, will do.
thanks,
greg k-h
Greg KH wrote:
> On Fri, Oct 02, 2009 at 05:38:36PM +0100, David Vrabel wrote:
>> Greg KH wrote:
>>> 2.6.31-stable review patch. If anyone has any objections, please let us know.
>>>
>>> ------------------
>>> From: Sarah Sharp <[email protected]>
>>>
>>> commit 66d1eebce5cca916e0b08d961690bb01c64751ef upstream.
>>>
>>> Use trb_comp_code instead of getting the completion code from the transfer
>>> event every time.
>> Are all these xhci patches really candidates for the stable tree? XHCI
>> support is marked as EXPERIMENTAL, the xhci standard is still at the
>> draft stage, and I don't believe there are any xhci products available
>> on the market yet.
>
> Did you read the 000/136 message where I explained why I was accepting
> all of these xhci patches into the -stable tree?
I have now, sorry. It just seemed odd that XHCI patches where added to
stable releases whilst essential WHCI patches don't even make it into
the current rc tree.
David
--
David Vrabel, Senior Software Engineer, Drivers
CSR, Churchill House, Cambridge Business Park, Tel: +44 (0)1223 692562
Cowley Road, Cambridge, CB4 0WZ http://www.csr.com/
Member of the CSR plc group of companies. CSR plc registered in England and Wales, registered number 4187346, registered office Churchill House, Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, United Kingdom
On Fri, Oct 02, 2009 at 06:23:03PM +0100, David Vrabel wrote:
> Greg KH wrote:
> > On Fri, Oct 02, 2009 at 05:38:36PM +0100, David Vrabel wrote:
> >> Greg KH wrote:
> >>> 2.6.31-stable review patch. If anyone has any objections, please let us know.
> >>>
> >>> ------------------
> >>> From: Sarah Sharp <[email protected]>
> >>>
> >>> commit 66d1eebce5cca916e0b08d961690bb01c64751ef upstream.
> >>>
> >>> Use trb_comp_code instead of getting the completion code from the transfer
> >>> event every time.
> >> Are all these xhci patches really candidates for the stable tree? XHCI
> >> support is marked as EXPERIMENTAL, the xhci standard is still at the
> >> draft stage, and I don't believe there are any xhci products available
> >> on the market yet.
> >
> > Did you read the 000/136 message where I explained why I was accepting
> > all of these xhci patches into the -stable tree?
>
> I have now, sorry. It just seemed odd that XHCI patches where added to
> stable releases whilst essential WHCI patches don't even make it into
> the current rc tree.
The WHCI patches were submitted much after the XHCI patches. The XHCI
patches were in my tree, and the -next and -mm patches for weeks, it was
my fault that they didn't make it to Linus earlier. This is quite
different from the WHCI patches.
thanks,
greg k-h
Em Qui 01 Out 2009, ?s 22:17:07, Greg KH escreveu:
> 2.6.31-stable review patch. If anyone has any objections, please let us know.
>
> ------------------
> From: Kurt Roeckx <[email protected]>
>
> commit f0adb134d8dc9993a9998dc50845ec4f6ff4fadc upstream.
>
> Fixes bugzilla #13780
>
> From: Kurt Roeckx <[email protected]>
> Signed-off-by: Dave Jones <[email protected]>
> Signed-off-by: Greg Kroah-Hartman <[email protected]>
>
> ---
> arch/x86/kernel/cpu/cpufreq/powernow-k8.c | 15 ++++++++-------
> 1 file changed, 8 insertions(+), 7 deletions(-)
>
> --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
> +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
> @@ -605,9 +605,10 @@ static int check_pst_table(struct powern
> return 0;
> }
>
> -static void invalidate_entry(struct powernow_k8_data *data, unsigned int entry)
> +static void invalidate_entry(struct cpufreq_frequency_table *powernow_table,
> + unsigned int entry)
> {
> - data->powernow_table[entry].frequency = CPUFREQ_ENTRY_INVALID;
> + powernow_table[entry].frequency = CPUFREQ_ENTRY_INVALID;
> }
>
> static void print_basics(struct powernow_k8_data *data)
> @@ -914,13 +915,13 @@ static int fill_powernow_table_pstate(st
> "bad value %d.\n", i, index);
> printk(KERN_ERR PFX "Please report to BIOS "
> "manufacturer\n");
> - invalidate_entry(data, i);
> + invalidate_entry(powernow_table, i);
> continue;
> }
> rdmsr(MSR_PSTATE_DEF_BASE + index, lo, hi);
> if (!(hi & HW_PSTATE_VALID_MASK)) {
> dprintk("invalid pstate %d, ignoring\n", index);
> - invalidate_entry(data, i);
> + invalidate_entry(powernow_table, i);
> continue;
> }
>
> @@ -970,7 +971,7 @@ static int fill_powernow_table_fidvid(st
> /* verify frequency is OK */
> if ((freq > (MAX_FREQ * 1000)) || (freq < (MIN_FREQ * 1000))) {
> dprintk("invalid freq %u kHz, ignoring\n", freq);
> - invalidate_entry(data, i);
> + invalidate_entry(powernow_table, i);
> continue;
> }
>
> @@ -978,7 +979,7 @@ static int fill_powernow_table_fidvid(st
> * BIOSs are using "off" to indicate invalid */
> if (vid == VID_OFF) {
> dprintk("invalid vid %u, ignoring\n", vid);
> - invalidate_entry(data, i);
> + invalidate_entry(powernow_table, i);
> continue;
> }
>
> @@ -1009,7 +1010,7 @@ static int fill_powernow_table_fidvid(st
> (unsigned int)
> (data->acpi_data.states[i].core_frequency
> * 1000));
> - invalidate_entry(data, i);
> + invalidate_entry(powernow_table, i);
> continue;
> }
> }
>
With this applied I get following warning:
arch/x86/kernel/cpu/cpufreq/powernow-k8.c:1001: warning: passing argument 1 of 'invalidate_entry' from incompatible pointer type
There is a missing data->powernow_table change, following diff on top fixes it:
diff -p -up linux-2.6.31/arch/x86/kernel/cpu/cpufreq/powernow-k8.c.orig linux-2.6.31/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
--- linux-2.6.31/arch/x86/kernel/cpu/cpufreq/powernow-k8.c.orig 2009-10-03 12:06:38.000000000 -0300
+++ linux-2.6.31/arch/x86/kernel/cpu/cpufreq/powernow-k8.c 2009-10-03 12:08:34.000000000 -0300
@@ -998,7 +998,7 @@ static int fill_powernow_table_fidvid(st
dprintk("double low frequency table entry, "
"ignoring it.\n");
- invalidate_entry(data, i);
+ invalidate_entry(powernow_table, i);
continue;
} else
cntlofreq = i;
--
[]'s
Herton
On Sat, Oct 03, 2009 at 12:19:08PM -0300, Herton Ronaldo Krzesinski wrote:
> Em Qui 01 Out 2009, ?s 22:17:07, Greg KH escreveu:
> > 2.6.31-stable review patch. If anyone has any objections, please let us know.
> >
> > ------------------
> > From: Kurt Roeckx <[email protected]>
> >
> > commit f0adb134d8dc9993a9998dc50845ec4f6ff4fadc upstream.
> >
> > Fixes bugzilla #13780
> >
> > From: Kurt Roeckx <[email protected]>
> > Signed-off-by: Dave Jones <[email protected]>
> > Signed-off-by: Greg Kroah-Hartman <[email protected]>
> >
> > ---
> > arch/x86/kernel/cpu/cpufreq/powernow-k8.c | 15 ++++++++-------
> > 1 file changed, 8 insertions(+), 7 deletions(-)
> >
> > --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
> > +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
> > @@ -605,9 +605,10 @@ static int check_pst_table(struct powern
> > return 0;
> > }
> >
> > -static void invalidate_entry(struct powernow_k8_data *data, unsigned int entry)
> > +static void invalidate_entry(struct cpufreq_frequency_table *powernow_table,
> > + unsigned int entry)
> > {
> > - data->powernow_table[entry].frequency = CPUFREQ_ENTRY_INVALID;
> > + powernow_table[entry].frequency = CPUFREQ_ENTRY_INVALID;
> > }
> >
> > static void print_basics(struct powernow_k8_data *data)
> > @@ -914,13 +915,13 @@ static int fill_powernow_table_pstate(st
> > "bad value %d.\n", i, index);
> > printk(KERN_ERR PFX "Please report to BIOS "
> > "manufacturer\n");
> > - invalidate_entry(data, i);
> > + invalidate_entry(powernow_table, i);
> > continue;
> > }
> > rdmsr(MSR_PSTATE_DEF_BASE + index, lo, hi);
> > if (!(hi & HW_PSTATE_VALID_MASK)) {
> > dprintk("invalid pstate %d, ignoring\n", index);
> > - invalidate_entry(data, i);
> > + invalidate_entry(powernow_table, i);
> > continue;
> > }
> >
> > @@ -970,7 +971,7 @@ static int fill_powernow_table_fidvid(st
> > /* verify frequency is OK */
> > if ((freq > (MAX_FREQ * 1000)) || (freq < (MIN_FREQ * 1000))) {
> > dprintk("invalid freq %u kHz, ignoring\n", freq);
> > - invalidate_entry(data, i);
> > + invalidate_entry(powernow_table, i);
> > continue;
> > }
> >
> > @@ -978,7 +979,7 @@ static int fill_powernow_table_fidvid(st
> > * BIOSs are using "off" to indicate invalid */
> > if (vid == VID_OFF) {
> > dprintk("invalid vid %u, ignoring\n", vid);
> > - invalidate_entry(data, i);
> > + invalidate_entry(powernow_table, i);
> > continue;
> > }
> >
> > @@ -1009,7 +1010,7 @@ static int fill_powernow_table_fidvid(st
> > (unsigned int)
> > (data->acpi_data.states[i].core_frequency
> > * 1000));
> > - invalidate_entry(data, i);
> > + invalidate_entry(powernow_table, i);
> > continue;
> > }
> > }
> >
>
> With this applied I get following warning:
> arch/x86/kernel/cpu/cpufreq/powernow-k8.c:1001: warning: passing argument 1 of 'invalidate_entry' from incompatible pointer type
>
> There is a missing data->powernow_table change, following diff on top fixes it:
>
> diff -p -up linux-2.6.31/arch/x86/kernel/cpu/cpufreq/powernow-k8.c.orig linux-2.6.31/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
> --- linux-2.6.31/arch/x86/kernel/cpu/cpufreq/powernow-k8.c.orig 2009-10-03 12:06:38.000000000 -0300
> +++ linux-2.6.31/arch/x86/kernel/cpu/cpufreq/powernow-k8.c 2009-10-03 12:08:34.000000000 -0300
> @@ -998,7 +998,7 @@ static int fill_powernow_table_fidvid(st
>
> dprintk("double low frequency table entry, "
> "ignoring it.\n");
> - invalidate_entry(data, i);
> + invalidate_entry(powernow_table, i);
> continue;
> } else
> cntlofreq = i;
>
Thanks, I've merged this into the original patch. For some reason my
build isn't letting me build this file so I didn't see the warning.
thanks again,
greg k-h
Hi, Greg.
Could you consider adding the following commit in linus-tree to 2.6.31-stable ?
I've verified the commit can be applied onto v2.6.31.2.
commit 31a5639623a487d6db996c8138c9e53fef2e2d91
Author: Daisuke Nishimura <[email protected]>
Date: Mon Sep 21 17:02:50 2009 -0700
mm: add_to_swap_cache() must not sleep
After commit 355cfa73 ("mm: modify swap_map and add SWAP_HAS_CACHE flag"),
read_swap_cache_async() will busy-wait while a entry doesn't exist in swap
cache but it has SWAP_HAS_CACHE flag.
Such entries can exist on add/delete path of swap cache. On add path,
add_to_swap_cache() is called soon after SWAP_HAS_CACHE flag is set, and
on delete path, swapcache_free() will be called (SWAP_HAS_CACHE flag is
cleared) soon after __delete_from_swap_cache() is called. So, the
busy-wait works well in most cases.
But this mechanism can cause soft lockup if add_to_swap_cache() sleeps and
read_swap_cache_async() tries to swap-in the same entry on the same cpu.
This patch calls radix_tree_preload() before swapcache_prepare() and
divides add_to_swap_cache() into two part: radix_tree_preload() part and
radix_tree_insert() part(define it as __add_to_swap_cache()).
Signed-off-by: Daisuke Nishimura <[email protected]>
Cc: KAMEZAWA Hiroyuki <[email protected]>
Cc: Balbir Singh <[email protected]>
Cc: Hugh Dickins <[email protected]>
Cc: Johannes Weiner <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
This is a fix for a soft lockup bug introduced at 2.6.31-rc1.
It was rare, but I saw the bug several times, and Alok-san reported me the bug
also happens on Ubuntu 9.10(alpha).
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/433646
Thanks,
Daisuke Nishimura.
On Tue, Oct 06, 2009 at 09:12:54AM +0900, Daisuke Nishimura wrote:
> Hi, Greg.
>
> Could you consider adding the following commit in linus-tree to 2.6.31-stable ?
> I've verified the commit can be applied onto v2.6.31.2.
Now queued up.
thanks,
greg k-h