rpms/kernel/devel linux-2.6-die-closed-source-bios-muppets-die.patch, NONE, 1.2.2.2 linux-2.6-intel-iommu-updates.patch, NONE, 1.1.2.2 config-sparc64-generic, 1.21.6.4, 1.21.6.5 config-sparc64-smp, 1.2.16.2, 1.2.16.3 config-x86-generic, 1.68.6.16, 1.68.6.17 config-x86_64-generic, 1.68.2.14, 1.68.2.15 kernel.spec, 1.1294.2.46, 1.1294.2.47 linux-2.6-bluetooth-autosuspend.diff, 1.1.6.2, 1.1.6.3 linux-2.6.31-lirc.patch, 1.2.2.3, 1.2.2.4 xen.pvops.post.patch, 1.1.2.19, 1.1.2.20 xen.pvops.pre.patch, 1.1.2.15, 1.1.2.16

myoung myoung at fedoraproject.org
Mon Aug 10 21:22:21 UTC 2009


Author: myoung

Update of /cvs/pkgs/rpms/kernel/devel
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv16116

Modified Files:
      Tag: private-myoung-dom0-branch
	config-sparc64-generic config-sparc64-smp config-x86-generic 
	config-x86_64-generic kernel.spec 
	linux-2.6-bluetooth-autosuspend.diff linux-2.6.31-lirc.patch 
	xen.pvops.post.patch xen.pvops.pre.patch 
Added Files:
      Tag: private-myoung-dom0-branch
	linux-2.6-die-closed-source-bios-muppets-die.patch 
	linux-2.6-intel-iommu-updates.patch 
Log Message:
for pvops temporarily disable CONFIG_CC_STACKPROTECTOR for x86_64 again
and also dracut


linux-2.6-die-closed-source-bios-muppets-die.patch:
 pci-quirks.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- NEW FILE linux-2.6-die-closed-source-bios-muppets-die.patch ---
Subject: [PATCH] Work around BIOS bugs by quiescing USB controllers earlier
From: David Woodhouse <dwmw2 at infradead.org>
To: "linux-usb at vger.kernel.org" <linux-usb at vger.kernel.org>
Date: Mon, 03 Aug 2009 12:40:27 +0100
Message-Id: <1249299627.14968.1.camel at macbook.infradead.org>
Cc: iommu at lists.linux-foundation.org

We are seeing a number of crashes in SMM, when VT-d is enabled while
'Legacy USB support' is enabled in various BIOSes.

The BIOS is supposed to indicate which addresses it uses for DMA in a
special ACPI table ("RMRR"), so that we can punch a hole for it when we
set up the IOMMU.

The problem is, as usual, that BIOS engineers are totally incompetent.
They write code which will crash if the DMA goes AWOL, and then they
either neglect to provide an RMRR table at all, or they put the wrong
addresses in it. And of course they don't do _any_ QA, since that would
take too much time away from their crack-smoking habit.

The real fix, of course, is for consumers to refuse to buy motherboards
which only have closed-source firmware available. If we had _open_
firmware, bugs like this would be easy to fix.

Since that's something I can only dream about, this patch implements an
alternative -- ensuring that the USB controllers are handed off from the
BIOS and quiesced _before_ the IOMMU is initialised. That would have
been a much better design than this RMRR nonsense in the first place, of
course. The bootloader has no business doing DMA after the OS has booted
anyway.

Signed-off-by: David Woodhouse <David.Woodhouse at intel.com>
---
Is this reasonable? At first glance, it looks like everything we do here
is perfectly OK to be done earlier.

diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 83b5f9c..23cf3bd 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -475,4 +475,4 @@ static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
 	else if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI)
 		quirk_usb_handoff_xhci(pdev);
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff);
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff);

linux-2.6-intel-iommu-updates.patch:
 arch/x86/kernel/pci-dma.c     |    4 
 arch/x86/kernel/pci-swiotlb.c |    5 
 drivers/pci/dmar.c            |   22 +++
 drivers/pci/intel-iommu.c     |  243 +++++++++++++++++++-----------------------
 drivers/pci/iova.c            |   16 --
 include/linux/iova.h          |    1 
 6 files changed, 135 insertions(+), 156 deletions(-)

--- NEW FILE linux-2.6-intel-iommu-updates.patch ---
commit 5fe60f4e5871b64e687229199fafd4ef13cd0886
Author: David Woodhouse <David.Woodhouse at intel.com>
Date:   Sun Aug 9 10:53:41 2009 +0100

    intel-iommu: make domain_add_dev_info() call domain_context_mapping()
    
    All callers of the former were also calling the latter, in one order or
    the other, and failing to correctly clean up if the second returned
    failure.
    
    Signed-off-by: David Woodhouse <David.Woodhouse at intel.com>

commit a131bc185528331451a93db6c50a7d2070376a61
Merge: 19943b0 ff1649f
Author: David Woodhouse <David.Woodhouse at intel.com>
Date:   Sat Aug 8 11:25:28 2009 +0100

    Merge branch 'master' of /pub/scm/linux/kernel/git/torvalds/linux-2.6
    
    Pull fixes in from 2.6.31 so that people testing the iommu-2.6.git tree
    no longer trip over bugs which were already fixed (sorry, Horms).

commit 19943b0e30b05d42e494ae6fef78156ebc8c637e
Author: David Woodhouse <David.Woodhouse at intel.com>
Date:   Tue Aug 4 16:19:20 2009 +0100

    intel-iommu: Unify hardware and software passthrough support
    
    This makes the hardware passthrough mode work a lot more like the
    software version, so that the behaviour of a kernel with 'iommu=pt'
    is the same whether the hardware supports passthrough or not.
    
    In particular:
     - We use a single si_domain for the pass-through devices.
     - 32-bit devices can be taken out of the pass-through domain so that
       they don't have to use swiotlb.
     - Devices will work again after being removed from a KVM guest.
     - A potential oops on OOM (in init_context_pass_through()) is fixed.
    
    Signed-off-by: David Woodhouse <David.Woodhouse at intel.com>

commit 0815565adfe3f4c369110c57d8ffe83caefeed68
Author: David Woodhouse <David.Woodhouse at intel.com>
Date:   Tue Aug 4 09:17:20 2009 +0100

    intel-iommu: Cope with broken HP DC7900 BIOS
    
    Yet another reason why trusting this stuff to the BIOS was a bad idea.
    The HP DC7900 BIOS reports an iommu at an address which just returns all
    ones, when VT-d is disabled in the BIOS.
    
    Fix up the missing iounmap in the error paths while we're at it.
    
    Signed-off-by: David Woodhouse <David.Woodhouse at intel.com>

commit cfc65dd57967f2e0c7b3a8b73e6d12470b1cf1c1
Author: Alex Williamson <alex.williamson at hp.com>
Date:   Thu Jul 30 16:15:18 2009 -0600

    iommu=pt is a valid early param
    
    This avoids a "Malformed early option 'iommu'" warning on boot when
    trying to use pass-through mode.
    
    Signed-off-by: Alex Williamson <alex.williamson at hp.com>
    Signed-off-by: David Woodhouse <David.Woodhouse at intel.com>

commit 86f4d0123b1fddb47d35b9a893f8c0b94bf89abe
Author: Dan Carpenter <error27 at gmail.com>
Date:   Sun Jul 19 14:47:45 2009 +0300

    intel-iommu: double kfree()
    
    g_iommus is freed after we "goto error;".
    
    Found by smatch (http://repo.or.cz/w/smatch.git).
    
    Signed-off-by: Dan Carpenter <error27 at gmail.com>
    Signed-off-by: David Woodhouse <David.Woodhouse at intel.com>

commit 0db9b7aebb6a1c2bba2d0636ae0b1f9ef729c827
Author: David Woodhouse <David.Woodhouse at intel.com>
Date:   Tue Jul 14 02:01:57 2009 +0100

    intel-iommu: Kill pointless intel_unmap_single() function
    
    Signed-off-by: David Woodhouse <David.Woodhouse at intel.com>

commit acea0018a24b794e32afea4f3be4230c58f2f8e3
Author: David Woodhouse <David.Woodhouse at intel.com>
Date:   Tue Jul 14 01:55:11 2009 +0100

    intel-iommu: Defer the iotlb flush and iova free for intel_unmap_sg() too.
    
    I see no reason why we did this _only_ in intel_unmap_page().
    
    Signed-off-by: David Woodhouse <David.Woodhouse at intel.com>

commit 3d39cecc4841e8d4c4abdb401d10180f5faaded0
Author: David Woodhouse <David.Woodhouse at intel.com>
Date:   Wed Jul 8 15:23:30 2009 +0100

    intel-iommu: Remove superfluous iova_alloc_lock from IOVA code
    
    We only ever obtain this lock immediately before the iova_rbtree_lock,
    and release it immediately after the iova_rbtree_lock. So ditch it and
    just use iova_rbtree_lock.
    
    [v2: Remove the lockdep bits this time too]
    Signed-off-by: David Woodhouse <David.Woodhouse at intel.com>

commit 147202aa772329a02c6e80bc2b7a6b8dd3deac0b
Author: David Woodhouse <David.Woodhouse at intel.com>
Date:   Tue Jul 7 19:43:20 2009 +0100

    intel-iommu: Speed up map routines by using cached domain ASAP
    
    We did before, in the end -- but it was at the bottom of a long stack of
    functions. Add an inline wrapper get_valid_domain_for_dev() which will
    use the cached one _first_ and only make the out-of-line call if it's
    not already set.
    
    This takes the average time taken for a 1-page intel_map_sg() from 5961
    cycles to 4812 cycles on my Lenovo x200s test box -- a modest 20%.
    
    Signed-off-by: David Woodhouse <David.Woodhouse at intel.com>
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index 1a041bc..ae13e34 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -212,10 +212,8 @@ static __init int iommu_setup(char *p)
 		if (!strncmp(p, "soft", 4))
 			swiotlb = 1;
 #endif
-		if (!strncmp(p, "pt", 2)) {
+		if (!strncmp(p, "pt", 2))
 			iommu_pass_through = 1;
-			return 1;
-		}
 
 		gart_parse_options(p);
 
diff --git a/arch/x86/kernel/pci-swiotlb.c b/arch/x86/kernel/pci-swiotlb.c
index 6af96ee..1e66b18 100644
--- a/arch/x86/kernel/pci-swiotlb.c
+++ b/arch/x86/kernel/pci-swiotlb.c
@@ -71,9 +71,8 @@ void __init pci_swiotlb_init(void)
 {
 	/* don't initialize swiotlb if iommu=off (no_iommu=1) */
 #ifdef CONFIG_X86_64
-	if ((!iommu_detected && !no_iommu && max_pfn > MAX_DMA32_PFN) ||
-		iommu_pass_through)
-	       swiotlb = 1;
+	if ((!iommu_detected && !no_iommu && max_pfn > MAX_DMA32_PFN))
+		swiotlb = 1;
 #endif
 	if (swiotlb_force)
 		swiotlb = 1;
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index 7b287cb..380b60e 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -632,20 +632,31 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
 	iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG);
 	iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG);
 
+	if (iommu->cap == (uint64_t)-1 && iommu->ecap == (uint64_t)-1) {
+		/* Promote an attitude of violence to a BIOS engineer today */
+		WARN(1, "Your BIOS is broken; DMAR reported at address %llx returns all ones!\n"
+		     "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
+		     drhd->reg_base_addr,
+		     dmi_get_system_info(DMI_BIOS_VENDOR),
+		     dmi_get_system_info(DMI_BIOS_VERSION),
+		     dmi_get_system_info(DMI_PRODUCT_VERSION));
+		goto err_unmap;
+	}
+
 #ifdef CONFIG_DMAR
 	agaw = iommu_calculate_agaw(iommu);
 	if (agaw < 0) {
 		printk(KERN_ERR
 		       "Cannot get a valid agaw for iommu (seq_id = %d)\n",
 		       iommu->seq_id);
-		goto error;
+		goto err_unmap;
 	}
 	msagaw = iommu_calculate_max_sagaw(iommu);
 	if (msagaw < 0) {
 		printk(KERN_ERR
 			"Cannot get a valid max agaw for iommu (seq_id = %d)\n",
 			iommu->seq_id);
-		goto error;
+		goto err_unmap;
 	}
 #endif
 	iommu->agaw = agaw;
@@ -665,7 +676,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
 	}
 
 	ver = readl(iommu->reg + DMAR_VER_REG);
-	pr_debug("IOMMU %llx: ver %d:%d cap %llx ecap %llx\n",
+	pr_info("IOMMU %llx: ver %d:%d cap %llx ecap %llx\n",
 		(unsigned long long)drhd->reg_base_addr,
 		DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver),
 		(unsigned long long)iommu->cap,
@@ -675,7 +686,10 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
 
 	drhd->iommu = iommu;
 	return 0;
-error:
+
+ err_unmap:
+	iounmap(iommu->reg);
+ error:
 	kfree(iommu);
 	return -1;
 }
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index 2314ad7..09606e9 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -251,7 +251,8 @@ static inline int first_pte_in_page(struct dma_pte *pte)
  * 	2. It maps to each iommu if successful.
  *	3. Each iommu mapps to this domain if successful.
  */
-struct dmar_domain *si_domain;
+static struct dmar_domain *si_domain;
+static int hw_pass_through = 1;
 
 /* devices under the same p2p bridge are owned in one domain */
 #define DOMAIN_FLAG_P2P_MULTIPLE_DEVICES (1 << 0)
@@ -1309,7 +1310,6 @@ static void iommu_detach_domain(struct dmar_domain *domain,
 }
 
 static struct iova_domain reserved_iova_list;
-static struct lock_class_key reserved_alloc_key;
 static struct lock_class_key reserved_rbtree_key;
 
 static void dmar_init_reserved_ranges(void)
@@ -1320,8 +1320,6 @@ static void dmar_init_reserved_ranges(void)
 
 	init_iova_domain(&reserved_iova_list, DMA_32BIT_PFN);
 
-	lockdep_set_class(&reserved_iova_list.iova_alloc_lock,
-		&reserved_alloc_key);
 	lockdep_set_class(&reserved_iova_list.iova_rbtree_lock,
 		&reserved_rbtree_key);
 
@@ -1958,14 +1956,24 @@ static int iommu_prepare_identity_map(struct pci_dev *pdev,
 	struct dmar_domain *domain;
 	int ret;
 
-	printk(KERN_INFO
-	       "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n",
-	       pci_name(pdev), start, end);
-
 	domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
 	if (!domain)
 		return -ENOMEM;
 
+	/* For _hardware_ passthrough, don't bother. But for software
+	   passthrough, we do it anyway -- it may indicate a memory
+	   range which is reserved in E820, so which didn't get set
+	   up to start with in si_domain */
+	if (domain == si_domain && hw_pass_through) {
+		printk("Ignoring identity map for HW passthrough device %s [0x%Lx - 0x%Lx]\n",
+		       pci_name(pdev), start, end);
+		return 0;
+	}
+
+	printk(KERN_INFO
+	       "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n",
+	       pci_name(pdev), start, end);
+
 	ret = iommu_domain_identity_map(domain, start, end);
 	if (ret)
 		goto error;
@@ -2016,23 +2024,6 @@ static inline void iommu_prepare_isa(void)
 }
 #endif /* !CONFIG_DMAR_FLPY_WA */
 
-/* Initialize each context entry as pass through.*/
-static int __init init_context_pass_through(void)
-{
-	struct pci_dev *pdev = NULL;
-	struct dmar_domain *domain;
-	int ret;
-
-	for_each_pci_dev(pdev) {
-		domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
-		ret = domain_context_mapping(domain, pdev,
-					     CONTEXT_TT_PASS_THROUGH);
-		if (ret)
-			return ret;
-	}
-	return 0;
-}
-
 static int md_domain_init(struct dmar_domain *domain, int guest_width);
 
 static int __init si_domain_work_fn(unsigned long start_pfn,
@@ -2047,7 +2038,7 @@ static int __init si_domain_work_fn(unsigned long start_pfn,
 
 }
 
-static int si_domain_init(void)
+static int si_domain_init(int hw)
 {
 	struct dmar_drhd_unit *drhd;
 	struct intel_iommu *iommu;
@@ -2074,6 +2065,9 @@ static int si_domain_init(void)
 
 	si_domain->flags = DOMAIN_FLAG_STATIC_IDENTITY;
 
+	if (hw)
+		return 0;
+
 	for_each_online_node(nid) {
 		work_with_active_regions(nid, si_domain_work_fn, &ret);
 		if (ret)
@@ -2100,15 +2094,23 @@ static int identity_mapping(struct pci_dev *pdev)
 }
 
 static int domain_add_dev_info(struct dmar_domain *domain,
-				  struct pci_dev *pdev)
+			       struct pci_dev *pdev,
+			       int translation)
 {
 	struct device_domain_info *info;
 	unsigned long flags;
+	int ret;
 
 	info = alloc_devinfo_mem();
 	if (!info)
 		return -ENOMEM;
 
+	ret = domain_context_mapping(domain, pdev, translation);
+	if (ret) {
+		free_devinfo_mem(info);
+		return ret;
+	}
+
 	info->segment = pci_domain_nr(pdev->bus);
 	info->bus = pdev->bus->number;
 	info->devfn = pdev->devfn;
@@ -2165,27 +2167,25 @@ static int iommu_should_identity_map(struct pci_dev *pdev, int startup)
 	return 1;
 }
 
-static int iommu_prepare_static_identity_mapping(void)
+static int iommu_prepare_static_identity_mapping(int hw)
 {
 	struct pci_dev *pdev = NULL;
 	int ret;
 
-	ret = si_domain_init();
+	ret = si_domain_init(hw);
 	if (ret)
 		return -EFAULT;
 
 	for_each_pci_dev(pdev) {
 		if (iommu_should_identity_map(pdev, 1)) {
-			printk(KERN_INFO "IOMMU: identity mapping for device %s\n",
-			       pci_name(pdev));
+			printk(KERN_INFO "IOMMU: %s identity mapping for device %s\n",
+			       hw ? "hardware" : "software", pci_name(pdev));
 
-			ret = domain_context_mapping(si_domain, pdev,
+			ret = domain_add_dev_info(si_domain, pdev,
+						     hw ? CONTEXT_TT_PASS_THROUGH :
 						     CONTEXT_TT_MULTI_LEVEL);
 			if (ret)
 				return ret;
-			ret = domain_add_dev_info(si_domain, pdev);
-			if (ret)
-				return ret;
 		}
 	}
 
@@ -2199,14 +2199,6 @@ int __init init_dmars(void)
 	struct pci_dev *pdev;
 	struct intel_iommu *iommu;
 	int i, ret;
-	int pass_through = 1;
-
-	/*
-	 * In case pass through can not be enabled, iommu tries to use identity
-	 * mapping.
-	 */
-	if (iommu_pass_through)
-		iommu_identity_mapping = 1;
 
 	/*
 	 * for each drhd
@@ -2234,7 +2226,6 @@ int __init init_dmars(void)
 	deferred_flush = kzalloc(g_num_of_iommus *
 		sizeof(struct deferred_flush_tables), GFP_KERNEL);
 	if (!deferred_flush) {
-		kfree(g_iommus);
 		ret = -ENOMEM;
 		goto error;
 	}
@@ -2261,14 +2252,8 @@ int __init init_dmars(void)
 			goto error;
 		}
 		if (!ecap_pass_through(iommu->ecap))
-			pass_through = 0;
+			hw_pass_through = 0;
 	}
-	if (iommu_pass_through)
-		if (!pass_through) {
-			printk(KERN_INFO
-			       "Pass Through is not supported by hardware.\n");
-			iommu_pass_through = 0;
-		}
 
 	/*
 	 * Start from the sane iommu hardware state.
@@ -2323,64 +2308,57 @@ int __init init_dmars(void)
 		}
 	}
 
+	if (iommu_pass_through)
+		iommu_identity_mapping = 1;
+#ifdef CONFIG_DMAR_BROKEN_GFX_WA
+	else
+		iommu_identity_mapping = 2;
+#endif
 	/*
-	 * If pass through is set and enabled, context entries of all pci
-	 * devices are intialized by pass through translation type.
+	 * If pass through is not set or not enabled, setup context entries for
+	 * identity mappings for rmrr, gfx, and isa and may fall back to static
+	 * identity mapping if iommu_identity_mapping is set.
 	 */
-	if (iommu_pass_through) {
-		ret = init_context_pass_through();
+	if (iommu_identity_mapping) {
+		ret = iommu_prepare_static_identity_mapping(hw_pass_through);
 		if (ret) {
-			printk(KERN_ERR "IOMMU: Pass through init failed.\n");
-			iommu_pass_through = 0;
+			printk(KERN_CRIT "Failed to setup IOMMU pass-through\n");
+			goto error;
 		}
 	}
-
 	/*
-	 * If pass through is not set or not enabled, setup context entries for
-	 * identity mappings for rmrr, gfx, and isa and may fall back to static
-	 * identity mapping if iommu_identity_mapping is set.
+	 * For each rmrr
+	 *   for each dev attached to rmrr
+	 *   do
+	 *     locate drhd for dev, alloc domain for dev
+	 *     allocate free domain
+	 *     allocate page table entries for rmrr
+	 *     if context not allocated for bus
+	 *           allocate and init context
+	 *           set present in root table for this bus
+	 *     init context with domain, translation etc
+	 *    endfor
+	 * endfor
 	 */
-	if (!iommu_pass_through) {
-#ifdef CONFIG_DMAR_BROKEN_GFX_WA
-		if (!iommu_identity_mapping)
-			iommu_identity_mapping = 2;
-#endif
-		if (iommu_identity_mapping)
-			iommu_prepare_static_identity_mapping();
-		/*
-		 * For each rmrr
-		 *   for each dev attached to rmrr
-		 *   do
-		 *     locate drhd for dev, alloc domain for dev
-		 *     allocate free domain
-		 *     allocate page table entries for rmrr
-		 *     if context not allocated for bus
-		 *           allocate and init context
-		 *           set present in root table for this bus
-		 *     init context with domain, translation etc
-		 *    endfor
-		 * endfor
-		 */
-		printk(KERN_INFO "IOMMU: Setting RMRR:\n");
-		for_each_rmrr_units(rmrr) {
-			for (i = 0; i < rmrr->devices_cnt; i++) {
-				pdev = rmrr->devices[i];
-				/*
-				 * some BIOS lists non-exist devices in DMAR
-				 * table.
-				 */
-				if (!pdev)
-					continue;
-				ret = iommu_prepare_rmrr_dev(rmrr, pdev);
-				if (ret)
-					printk(KERN_ERR
-				 "IOMMU: mapping reserved region failed\n");
-			}
+	printk(KERN_INFO "IOMMU: Setting RMRR:\n");
+	for_each_rmrr_units(rmrr) {
+		for (i = 0; i < rmrr->devices_cnt; i++) {
+			pdev = rmrr->devices[i];
+			/*
+			 * some BIOS lists non-exist devices in DMAR
+			 * table.
+			 */
+			if (!pdev)
+				continue;
+			ret = iommu_prepare_rmrr_dev(rmrr, pdev);
+			if (ret)
+				printk(KERN_ERR
+				       "IOMMU: mapping reserved region failed\n");
 		}
-
-		iommu_prepare_isa();
 	}
 
+	iommu_prepare_isa();
+
 	/*
 	 * for each drhd
 	 *   enable fault log
@@ -2454,8 +2432,7 @@ static struct iova *intel_alloc_iova(struct device *dev,
 	return iova;
 }
 
-static struct dmar_domain *
-get_valid_domain_for_dev(struct pci_dev *pdev)
+static struct dmar_domain *__get_valid_domain_for_dev(struct pci_dev *pdev)
 {
 	struct dmar_domain *domain;
 	int ret;
@@ -2483,6 +2460,18 @@ get_valid_domain_for_dev(struct pci_dev *pdev)
 	return domain;
 }
 
+static inline struct dmar_domain *get_valid_domain_for_dev(struct pci_dev *dev)
+{
+	struct device_domain_info *info;
+
+	/* No lock here, assumes no domain exit in normal case */
+	info = dev->dev.archdata.iommu;
+	if (likely(info))
+		return info->domain;
+
+	return __get_valid_domain_for_dev(dev);
+}
+
 static int iommu_dummy(struct pci_dev *pdev)
 {
 	return pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO;
@@ -2525,10 +2514,10 @@ static int iommu_no_mapping(struct device *dev)
 		 */
 		if (iommu_should_identity_map(pdev, 0)) {
 			int ret;
-			ret = domain_add_dev_info(si_domain, pdev);
-			if (ret)
-				return 0;
-			ret = domain_context_mapping(si_domain, pdev, CONTEXT_TT_MULTI_LEVEL);
+			ret = domain_add_dev_info(si_domain, pdev,
+						  hw_pass_through ?
+						  CONTEXT_TT_PASS_THROUGH :
+						  CONTEXT_TT_MULTI_LEVEL);
 			if (!ret) {
 				printk(KERN_INFO "64bit %s uses identity mapping\n",
 				       pci_name(pdev));
@@ -2733,12 +2722,6 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
 	}
 }
 
-static void intel_unmap_single(struct device *dev, dma_addr_t dev_addr, size_t size,
-			       int dir)
-{
-	intel_unmap_page(dev, dev_addr, size, dir, NULL);
-}
-
 static void *intel_alloc_coherent(struct device *hwdev, size_t size,
 				  dma_addr_t *dma_handle, gfp_t flags)
 {
@@ -2771,7 +2754,7 @@ static void intel_free_coherent(struct device *hwdev, size_t size, void *vaddr,
 	size = PAGE_ALIGN(size);
 	order = get_order(size);
 
-	intel_unmap_single(hwdev, dma_handle, size, DMA_BIDIRECTIONAL);
+	intel_unmap_page(hwdev, dma_handle, size, DMA_BIDIRECTIONAL, NULL);
 	free_pages((unsigned long)vaddr, order);
 }
 
@@ -2807,11 +2790,18 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
 	/* free page tables */
 	dma_pte_free_pagetable(domain, start_pfn, last_pfn);
 
-	iommu_flush_iotlb_psi(iommu, domain->id, start_pfn,
-			      (last_pfn - start_pfn + 1));
-
-	/* free iova */
-	__free_iova(&domain->iovad, iova);
+	if (intel_iommu_strict) {
+		iommu_flush_iotlb_psi(iommu, domain->id, start_pfn,
+				      last_pfn - start_pfn + 1);
+		/* free iova */
+		__free_iova(&domain->iovad, iova);
+	} else {
+		add_unmap(domain, iova);
+		/*
+		 * queue up the release of the unmap to save the 1/6th of the
+		 * cpu used up by the iotlb flush operation...
+		 */
+	}
 }
 
 static int intel_nontranslate_map_sg(struct device *hddev,
@@ -3194,7 +3184,7 @@ int __init intel_iommu_init(void)
 	 * Check the need for DMA-remapping initialization now.
 	 * Above initialization will also be used by Interrupt-remapping.
 	 */
-	if (no_iommu || (swiotlb && !iommu_pass_through) || dmar_disabled)
+	if (no_iommu || swiotlb || dmar_disabled)
 		return -ENODEV;
 
 	iommu_init_mempool();
@@ -3214,14 +3204,7 @@ int __init intel_iommu_init(void)
 
 	init_timer(&unmap_timer);
 	force_iommu = 1;
-
-	if (!iommu_pass_through) {
-		printk(KERN_INFO
-		       "Multi-level page-table translation for DMAR.\n");
-		dma_ops = &intel_dma_ops;
-	} else
-		printk(KERN_INFO
-		       "DMAR: Pass through translation for DMAR.\n");
+	dma_ops = &intel_dma_ops;
 
 	init_iommu_sysfs();
 
@@ -3504,7 +3487,6 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
 	struct intel_iommu *iommu;
 	int addr_width;
 	u64 end;
-	int ret;
 
 	/* normally pdev is not mapped */
 	if (unlikely(domain_context_mapped(pdev))) {
@@ -3536,12 +3518,7 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
 		return -EFAULT;
 	}
 
-	ret = domain_add_dev_info(dmar_domain, pdev);
-	if (ret)
-		return ret;
-
-	ret = domain_context_mapping(dmar_domain, pdev, CONTEXT_TT_MULTI_LEVEL);
-	return ret;
+	return domain_add_dev_info(dmar_domain, pdev, CONTEXT_TT_MULTI_LEVEL);
 }
 
 static void intel_iommu_detach_device(struct iommu_domain *domain,
diff --git a/drivers/pci/iova.c b/drivers/pci/iova.c
index 46dd440..7914951 100644
--- a/drivers/pci/iova.c
+++ b/drivers/pci/iova.c
@@ -22,7 +22,6 @@
 void
 init_iova_domain(struct iova_domain *iovad, unsigned long pfn_32bit)
 {
-	spin_lock_init(&iovad->iova_alloc_lock);
 	spin_lock_init(&iovad->iova_rbtree_lock);
 	iovad->rbroot = RB_ROOT;
 	iovad->cached32_node = NULL;
@@ -205,7 +204,6 @@ alloc_iova(struct iova_domain *iovad, unsigned long size,
 	unsigned long limit_pfn,
 	bool size_aligned)
 {
-	unsigned long flags;
 	struct iova *new_iova;
 	int ret;
 
@@ -219,11 +217,9 @@ alloc_iova(struct iova_domain *iovad, unsigned long size,
 	if (size_aligned)
 		size = __roundup_pow_of_two(size);
 
-	spin_lock_irqsave(&iovad->iova_alloc_lock, flags);
 	ret = __alloc_and_insert_iova_range(iovad, size, limit_pfn,
 			new_iova, size_aligned);
 
-	spin_unlock_irqrestore(&iovad->iova_alloc_lock, flags);
 	if (ret) {
 		free_iova_mem(new_iova);
 		return NULL;
@@ -381,8 +377,7 @@ reserve_iova(struct iova_domain *iovad,
 	struct iova *iova;
 	unsigned int overlap = 0;
 
-	spin_lock_irqsave(&iovad->iova_alloc_lock, flags);
-	spin_lock(&iovad->iova_rbtree_lock);
+	spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
 	for (node = rb_first(&iovad->rbroot); node; node = rb_next(node)) {
 		if (__is_range_overlap(node, pfn_lo, pfn_hi)) {
 			iova = container_of(node, struct iova, node);
@@ -402,8 +397,7 @@ reserve_iova(struct iova_domain *iovad,
 	iova = __insert_new_range(iovad, pfn_lo, pfn_hi);
 finish:
 
-	spin_unlock(&iovad->iova_rbtree_lock);
-	spin_unlock_irqrestore(&iovad->iova_alloc_lock, flags);
+	spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
 	return iova;
 }
 
@@ -420,8 +414,7 @@ copy_reserved_iova(struct iova_domain *from, struct iova_domain *to)
 	unsigned long flags;
 	struct rb_node *node;
 
-	spin_lock_irqsave(&from->iova_alloc_lock, flags);
-	spin_lock(&from->iova_rbtree_lock);
+	spin_lock_irqsave(&from->iova_rbtree_lock, flags);
 	for (node = rb_first(&from->rbroot); node; node = rb_next(node)) {
 		struct iova *iova = container_of(node, struct iova, node);
 		struct iova *new_iova;
@@ -430,6 +423,5 @@ copy_reserved_iova(struct iova_domain *from, struct iova_domain *to)
 			printk(KERN_ERR "Reserve iova range %lx@%lx failed\n",
 				iova->pfn_lo, iova->pfn_lo);
 	}
-	spin_unlock(&from->iova_rbtree_lock);
-	spin_unlock_irqrestore(&from->iova_alloc_lock, flags);
+	spin_unlock_irqrestore(&from->iova_rbtree_lock, flags);
 }
diff --git a/include/linux/iova.h b/include/linux/iova.h
index 228f6c9..76a0759 100644
--- a/include/linux/iova.h
+++ b/include/linux/iova.h
@@ -28,7 +28,6 @@ struct iova {
 
 /* holds all the iova translations for a domain */
 struct iova_domain {
-	spinlock_t	iova_alloc_lock;/* Lock to protect iova  allocation */
 	spinlock_t	iova_rbtree_lock; /* Lock to protect update of rbtree */
 	struct rb_root	rbroot;		/* iova domain rbtree root */
 	struct rb_node	*cached32_node; /* Save last alloced node */


Index: config-sparc64-generic
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/config-sparc64-generic,v
retrieving revision 1.21.6.4
retrieving revision 1.21.6.5
diff -u -p -r1.21.6.4 -r1.21.6.5
--- config-sparc64-generic	27 Jun 2009 11:05:10 -0000	1.21.6.4
+++ config-sparc64-generic	10 Aug 2009 21:22:18 -0000	1.21.6.5
@@ -31,7 +31,7 @@ CONFIG_64BIT=y
 CONFIG_HUGETLB_PAGE_SIZE_4MB=y
 # CONFIG_HUGETLB_PAGE_SIZE_512K is not set
 # CONFIG_HUGETLB_PAGE_SIZE_64K is not set
-CONFIG_NR_CPUS=64
+CONFIG_NR_CPUS=256
 CONFIG_US3_FREQ=m
 CONFIG_US2E_FREQ=m
 CONFIG_SUN_OPENPROMFS=m
@@ -151,7 +151,7 @@ CONFIG_ATM_FORE200E_USE_TASKLET=y
 CONFIG_ATM_FORE200E_DEBUG=0
 CONFIG_ATM_FORE200E_TX_RETRY=16
 # CONFIG_DRM_TDFX is not set
-# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_ATKBD=y
 CONFIG_KEYBOARD_SUNKBD=y
 # CONFIG_INPUT_PCSPKR is not set
 CONFIG_INPUT_SPARCSPKR=m
@@ -199,3 +199,5 @@ CONFIG_LEDS_SUNFIRE=m
 CONFIG_TADPOLE_TS102_UCTRL=m
 
 CONFIG_RCU_FANOUT=64
+
+# CONFIG_KGDB is not set


Index: config-sparc64-smp
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/config-sparc64-smp,v
retrieving revision 1.2.16.2
retrieving revision 1.2.16.3
diff -u -p -r1.2.16.2 -r1.2.16.3
--- config-sparc64-smp	24 Apr 2009 22:27:04 -0000	1.2.16.2
+++ config-sparc64-smp	10 Aug 2009 21:22:18 -0000	1.2.16.3
@@ -1 +1,2 @@
 CONFIG_SMP=y
+CONFIG_KGDB=y


Index: config-x86-generic
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/config-x86-generic,v
retrieving revision 1.68.6.16
retrieving revision 1.68.6.17
diff -u -p -r1.68.6.16 -r1.68.6.17
--- config-x86-generic	8 Aug 2009 18:06:03 -0000	1.68.6.16
+++ config-x86-generic	10 Aug 2009 21:22:18 -0000	1.68.6.17
@@ -96,7 +96,7 @@ CONFIG_FB_EFI=y
 CONFIG_DMAR=y
 CONFIG_DMAR_BROKEN_GFX_WA=y
 CONFIG_DMAR_FLOPPY_WA=y
-# CONFIG_DMAR_DEFAULT_ON is not set
+CONFIG_DMAR_DEFAULT_ON=y
 
 CONFIG_FB_GEODE=y
 CONFIG_FB_GEODE_LX=y


Index: config-x86_64-generic
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/config-x86_64-generic,v
retrieving revision 1.68.2.14
retrieving revision 1.68.2.15
diff -u -p -r1.68.2.14 -r1.68.2.15
--- config-x86_64-generic	5 Aug 2009 23:00:10 -0000	1.68.2.14
+++ config-x86_64-generic	10 Aug 2009 21:22:18 -0000	1.68.2.15
@@ -36,7 +36,7 @@ CONFIG_PCI_MMCONFIG=y
 CONFIG_DMAR=y
 CONFIG_DMAR_BROKEN_GFX_WA=y
 CONFIG_DMAR_FLOPPY_WA=y
-# CONFIG_DMAR_DEFAULT_ON is not set
+CONFIG_DMAR_DEFAULT_ON=y
 
 CONFIG_KEXEC_JUMP=y
 
@@ -243,7 +243,7 @@ CONFIG_SPARSEMEM_VMEMMAP=y
 # CONFIG_BLK_DEV_CS5530 is not set
 # CONFIG_BLK_DEV_CS5535 is not set
 
-CONFIG_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR is not set
 # CONFIG_CC_STACKPROTECTOR_ALL is not set
 
 CONFIG_SGI_IOC4=m


Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/kernel.spec,v
retrieving revision 1.1294.2.46
retrieving revision 1.1294.2.47
diff -u -p -r1.1294.2.46 -r1.1294.2.47
--- kernel.spec	9 Aug 2009 00:20:17 -0000	1.1294.2.46
+++ kernel.spec	10 Aug 2009 21:22:18 -0000	1.1294.2.47
@@ -103,6 +103,7 @@ Summary: The Linux kernel
 %define with_vdso_install %{?_without_vdso_install: 0} %{?!_without_vdso_install: 1}
 # dracut initrd-generic
 %define with_dracut       %{?_without_dracut:       0} %{?!_without_dracut:       1}
+%define with_dracut 0
 
 # Build the kernel-doc package, but don't fail the build if it botches.
 # Here "true" means "continue" and "false" means "fail the build".
@@ -608,6 +609,10 @@ Patch30: sched-introduce-SCHED_RESET_ON_
 
 Patch41: linux-2.6-sysrq-c.patch
 
+# Intel IOMMU fixes/workarounds
+Patch100: linux-2.6-die-closed-source-bios-muppets-die.patch
+Patch101: linux-2.6-intel-iommu-updates.patch
+
 Patch141: linux-2.6-ps3-storage-alias.patch
 Patch143: linux-2.6-g5-therm-shutdown.patch
 Patch144: linux-2.6-vio-modalias.patch
@@ -1143,6 +1148,16 @@ ApplyPatch via-hwmon-temp-sensor.patch
 ApplyPatch linux-2.6-dell-laptop-rfkill-fix.patch
 
 #
+# Intel IOMMU
+#
+# Quiesce USB host controllers before setting up the IOMMU
+ApplyPatch linux-2.6-die-closed-source-bios-muppets-die.patch
+# Some performance fixes, unify hardware/software passthrough support, and 
+# most importantly: notice when the BIOS points us to a region that returns
+# all 0xFF, and claims that there's an IOMMU there.
+ApplyPatch linux-2.6-intel-iommu-updates.patch
+
+#
 # PowerPC
 #
 ### NOT (YET) UPSTREAM:
@@ -1974,6 +1989,31 @@ fi
 # and build.
 
 %changelog
+* Mon Aug 10 2009 Michael Young <m.a.young at durham.ac.uk>
+- disable CONFIG_CC_STACKPROTECTOR for x86_64 again (the workaround
+  needs revising)
+- disable dracut until the issue with livecd is fixed
+
+* Mon Aug 10 2009 Jarod Wilson <jarod at redhat.com>
+- Add new device ID to lirc_mceusb (#512483)
+- Fix some lockdep false positives
+- Add support for setting and enabling iMON clock via sysfs
+- Add tunable pad threshold support to lirc_imon
+- Add new pseudo-IR protocl to lirc_imon for universals w/o a pad
+- Fix mouse device support on older iMON devices
+
+* Mon Aug 10 2009 David Woodhouse <David.Woodhouse at intel.com> 2.6.31-0.145.rc5.git3
+- Merge latest Intel IOMMU fixes and BIOS workarounds, re-enable by default.
+
+* Sun Aug 09 2009 Kyle McMartin <kyle at redhat.com>
+- btusb autosuspend: fix build on !CONFIG_PM by stubbing out
+  suspend/resume methods.
+
+* Sat Aug 08 2009 Dennis Gilmore <dennis at ausil.us> 2.6.31-0.141.rc5.git3
+- disable kgdb on sparc64 uni-processor kernel
+- set max cpus to 256 on sparc64
+- enable AT keyboard on sparc64
+
 * Sat Aug 08 2009 Michael Young <m.a.young at durham.ac.uk>
 - update pvops patch to latest rebase/master and current rawhide
 - tell kernel.spec not to build non-PAE kernel for i686

linux-2.6-bluetooth-autosuspend.diff:
 btusb.c |  189 +++++++++++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 147 insertions(+), 42 deletions(-)

Index: linux-2.6-bluetooth-autosuspend.diff
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/linux-2.6-bluetooth-autosuspend.diff,v
retrieving revision 1.1.6.2
retrieving revision 1.1.6.3
diff -u -p -r1.1.6.2 -r1.1.6.3
--- linux-2.6-bluetooth-autosuspend.diff	5 Aug 2009 23:00:16 -0000	1.1.6.2
+++ linux-2.6-bluetooth-autosuspend.diff	10 Aug 2009 21:22:19 -0000	1.1.6.3
@@ -1,11 +1,5 @@
-commit 7ed6456e2717d641a287bf6a83c1bf80395d312c
-Author: Matthew Garrett <mjg at redhat.com>
-Date:   Sat Jul 18 23:19:10 2009 +0100
-
-    Add support for bluetooth autosuspend
-
 diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
-index e70c57e..2f4b4c6 100644
+index e70c57e..ac94f91 100644
 --- a/drivers/bluetooth/btusb.c
 +++ b/drivers/bluetooth/btusb.c
 @@ -145,6 +145,7 @@ static struct usb_device_id blacklist_table[] = {
@@ -251,7 +245,12 @@ index e70c57e..2f4b4c6 100644
  
  	return 0;
  }
-@@ -947,60 +1007,100 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
+@@ -943,73 +1003,118 @@ static void btusb_disconnect(struct usb_interface *intf)
+ 	hci_free_dev(hdev);
+ }
+ 
++#ifdef CONFIG_PM
+ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
  {
  	struct btusb_data *data = usb_get_intfdata(intf);
  
@@ -378,12 +377,17 @@ index e70c57e..2f4b4c6 100644
 +	schedule_work(&data->work);
  	return 0;
  }
++#endif
  
-@@ -1011,6 +1111,7 @@ static struct usb_driver btusb_driver = {
+ static struct usb_driver btusb_driver = {
+ 	.name		= "btusb",
+ 	.probe		= btusb_probe,
+ 	.disconnect	= btusb_disconnect,
++#ifdef CONFIG_PM
  	.suspend	= btusb_suspend,
  	.resume		= btusb_resume,
- 	.id_table	= btusb_table,
 +	.supports_autosuspend = 1,
++#endif
+ 	.id_table	= btusb_table,
  };
  
- static int __init btusb_init(void)

linux-2.6.31-lirc.patch:
 MAINTAINERS                           |    9 
 drivers/input/Kconfig                 |    2 
 drivers/input/Makefile                |    2 
 drivers/input/lirc/Kconfig            |  112 +
 drivers/input/lirc/Makefile           |   20 
 drivers/input/lirc/lirc.h             |  100 +
 drivers/input/lirc/lirc_bt829.c       |  383 +++++
 drivers/input/lirc/lirc_dev.c         |  851 ++++++++++++
 drivers/input/lirc/lirc_dev.h         |  184 ++
 drivers/input/lirc/lirc_i2c.c         |  537 +++++++
 drivers/input/lirc/lirc_igorplugusb.c |  556 ++++++++
 drivers/input/lirc/lirc_imon.c        | 2298 ++++++++++++++++++++++++++++++++++
 drivers/input/lirc/lirc_it87.c        |  986 ++++++++++++++
 drivers/input/lirc/lirc_it87.h        |  116 +
 drivers/input/lirc/lirc_ite8709.c     |  539 +++++++
 drivers/input/lirc/lirc_mceusb.c      | 1225 ++++++++++++++++++
 drivers/input/lirc/lirc_parallel.c    |  709 ++++++++++
 drivers/input/lirc/lirc_parallel.h    |   26 
 drivers/input/lirc/lirc_sasem.c       |  931 +++++++++++++
 drivers/input/lirc/lirc_serial.c      | 1316 +++++++++++++++++++
 drivers/input/lirc/lirc_sir.c         | 1283 ++++++++++++++++++
 drivers/input/lirc/lirc_streamzap.c   |  777 +++++++++++
 drivers/input/lirc/lirc_ttusbir.c     |  397 +++++
 drivers/input/lirc/lirc_zilog.c       | 1374 ++++++++++++++++++++
 24 files changed, 14733 insertions(+)

Index: linux-2.6.31-lirc.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/linux-2.6.31-lirc.patch,v
retrieving revision 1.2.2.3
retrieving revision 1.2.2.4
diff -u -p -r1.2.2.3 -r1.2.2.4
--- linux-2.6.31-lirc.patch	5 Aug 2009 23:00:17 -0000	1.2.2.3
+++ linux-2.6.31-lirc.patch	10 Aug 2009 21:22:19 -0000	1.2.2.4
@@ -1,6 +1,6 @@
 Linux Infrared Remote Control drivers -- http://www.lirc.org
 
-Last updated: Tuesday, July 7, 2009
+Last updated: Monday, August 10, 2009
 
 From http://git.wilsonet.com/linux-2.6-lirc.git/
 
@@ -14,30 +14,30 @@ Signed-off-by: Jarod Wilson <jarod at redha
  drivers/input/lirc/Makefile           |   20 +
  drivers/input/lirc/lirc.h             |  100 ++
  drivers/input/lirc/lirc_bt829.c       |  383 ++++++
- drivers/input/lirc/lirc_dev.c         |  851 ++++++++++++++
+ drivers/input/lirc/lirc_dev.c         |  851 ++++++++++++
  drivers/input/lirc/lirc_dev.h         |  184 +++
- drivers/input/lirc/lirc_i2c.c         |  537 +++++++++
- drivers/input/lirc/lirc_igorplugusb.c |  556 +++++++++
- drivers/input/lirc/lirc_imon.c        | 2062 +++++++++++++++++++++++++++++++++
- drivers/input/lirc/lirc_it87.c        |  986 ++++++++++++++++
+ drivers/input/lirc/lirc_i2c.c         |  537 ++++++++
+ drivers/input/lirc/lirc_igorplugusb.c |  556 ++++++++
+ drivers/input/lirc/lirc_imon.c        | 2298 +++++++++++++++++++++++++++++++++
+ drivers/input/lirc/lirc_it87.c        |  986 ++++++++++++++
  drivers/input/lirc/lirc_it87.h        |  116 ++
- drivers/input/lirc/lirc_ite8709.c     |  539 +++++++++
- drivers/input/lirc/lirc_mceusb.c      | 1223 +++++++++++++++++++
- drivers/input/lirc/lirc_parallel.c    |  709 +++++++++++
+ drivers/input/lirc/lirc_ite8709.c     |  539 ++++++++
+ drivers/input/lirc/lirc_mceusb.c      | 1225 ++++++++++++++++++
+ drivers/input/lirc/lirc_parallel.c    |  709 ++++++++++
  drivers/input/lirc/lirc_parallel.h    |   26 +
- drivers/input/lirc/lirc_sasem.c       |  931 +++++++++++++++
- drivers/input/lirc/lirc_serial.c      | 1316 +++++++++++++++++++++
- drivers/input/lirc/lirc_sir.c         | 1294 +++++++++++++++++++++
- drivers/input/lirc/lirc_streamzap.c   |  777 +++++++++++++
- drivers/input/lirc/lirc_ttusbir.c     |  397 +++++++
- drivers/input/lirc/lirc_zilog.c       | 1374 ++++++++++++++++++++++
- 24 files changed, 14506 insertions(+), 0 deletions(-)
+ drivers/input/lirc/lirc_sasem.c       |  931 +++++++++++++
+ drivers/input/lirc/lirc_serial.c      | 1316 +++++++++++++++++++
+ drivers/input/lirc/lirc_sir.c         | 1283 ++++++++++++++++++
+ drivers/input/lirc/lirc_streamzap.c   |  777 +++++++++++
+ drivers/input/lirc/lirc_ttusbir.c     |  397 ++++++
+ drivers/input/lirc/lirc_zilog.c       | 1374 ++++++++++++++++++++
+ 24 files changed, 14733 insertions(+), 0 deletions(-)
 
 diff --git a/MAINTAINERS b/MAINTAINERS
-index 381190c..fc79bdf 100644
+index b1114cf..eb86f8e 100644
 --- a/MAINTAINERS
 +++ b/MAINTAINERS
-@@ -3632,6 +3632,15 @@ W:	http://www.pasemi.com/
+@@ -3122,6 +3122,15 @@ W:	http://www.pasemi.com/
  L:	linuxppc-dev at ozlabs.org
  S:	Supported
  
@@ -717,7 +717,7 @@ index 0000000..0485884
 +MODULE_PARM_DESC(debug, "Debug enabled or not");
 diff --git a/drivers/input/lirc/lirc_dev.c b/drivers/input/lirc/lirc_dev.c
 new file mode 100644
-index 0000000..a5d5c89
+index 0000000..0510b4e
 --- /dev/null
 +++ b/drivers/input/lirc/lirc_dev.c
 @@ -0,0 +1,851 @@
@@ -794,7 +794,7 @@ index 0000000..a5d5c89
 +	struct cdev cdev;
 +};
 +
-+static DEFINE_MUTEX(driver_lock);
++static DEFINE_MUTEX(lirc_dev_lock);
 +
 +static struct irctl *irctls[MAX_IRCTL_DEVICES];
 +
@@ -990,7 +990,7 @@ index 0000000..a5d5c89
 +		goto out;
 +	}
 +
-+	mutex_lock(&driver_lock);
++	mutex_lock(&lirc_dev_lock);
 +
 +	minor = d->minor;
 +
@@ -1079,7 +1079,7 @@ index 0000000..a5d5c89
 +		goto out_sysfs;
 +
 +	ir->attached = 1;
-+	mutex_unlock(&driver_lock);
++	mutex_unlock(&lirc_dev_lock);
 +
 +	dprintk("lirc_dev: driver %s registered at minor number = %d\n",
 +		ir->d.name, ir->d.minor);
@@ -1088,7 +1088,7 @@ index 0000000..a5d5c89
 +out_sysfs:
 +	device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor));
 +out_lock:
-+	mutex_unlock(&driver_lock);
++	mutex_unlock(&lirc_dev_lock);
 +out:
 +	return err;
 +}
@@ -1107,12 +1107,12 @@ index 0000000..a5d5c89
 +
 +	ir = irctls[minor];
 +
-+	mutex_lock(&driver_lock);
++	mutex_lock(&lirc_dev_lock);
 +
 +	if (ir->d.minor != minor) {
 +		printk(KERN_ERR "lirc_dev: lirc_unregister_driver: "
 +		       "minor (%d) device not registered!", minor);
-+		mutex_unlock(&driver_lock);
++		mutex_unlock(&lirc_dev_lock);
 +		return -ENOENT;
 +	}
 +
@@ -1140,7 +1140,7 @@ index 0000000..a5d5c89
 +		irctls[minor] = NULL;
 +	}
 +
-+	mutex_unlock(&driver_lock);
++	mutex_unlock(&lirc_dev_lock);
 +
 +	return 0;
 +}
@@ -1157,7 +1157,7 @@ index 0000000..a5d5c89
 +		return -ENODEV;
 +	}
 +
-+	if (mutex_lock_interruptible(&driver_lock))
++	if (mutex_lock_interruptible(&lirc_dev_lock))
 +		return -ERESTARTSYS;
 +
 +	ir = irctls[iminor(inode)];
@@ -1203,7 +1203,7 @@ index 0000000..a5d5c89
 +		dprintk(LOGHEAD "open result = %d\n", ir->d.name, ir->d.minor,
 +			retval);
 +
-+	mutex_unlock(&driver_lock);
++	mutex_unlock(&lirc_dev_lock);
 +
 +	return retval;
 +}
@@ -1215,7 +1215,7 @@ index 0000000..a5d5c89
 +
 +	dprintk(LOGHEAD "close called\n", ir->d.name, ir->d.minor);
 +
-+	WARN_ON(mutex_lock_killable(&driver_lock));
++	WARN_ON(mutex_lock_killable(&lirc_dev_lock));
 +
 +	--ir->open;
 +	if (ir->attached) {
@@ -1227,7 +1227,7 @@ index 0000000..a5d5c89
 +		kfree(ir);
 +	}
 +
-+	mutex_unlock(&driver_lock);
++	mutex_unlock(&lirc_dev_lock);
 +
 +	return 0;
 +}
@@ -1764,7 +1764,7 @@ index 0000000..8eeffa2
 +#endif
 diff --git a/drivers/input/lirc/lirc_i2c.c b/drivers/input/lirc/lirc_i2c.c
 new file mode 100644
-index 0000000..5a7f9d0
+index 0000000..e27d937
 --- /dev/null
 +++ b/drivers/input/lirc/lirc_i2c.c
 @@ -0,0 +1,537 @@
@@ -2122,8 +2122,8 @@ index 0000000..5a7f9d0
 +	.owner		= THIS_MODULE,
 +};
 +
-+static int ir_remove(struct i2c_client *client);
 +static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id);
++static int ir_remove(struct i2c_client *client);
 +static int ir_command(struct i2c_client *client, unsigned int cmd, void *arg);
 +
 +static const struct i2c_device_id ir_receiver_id[] = {
@@ -2140,8 +2140,8 @@ index 0000000..5a7f9d0
 +	},
 +	.probe		= ir_probe,
 +	.remove		= ir_remove,
-+	.command	= ir_command,
 +	.id_table	= ir_receiver_id,
++	.command	= ir_command,
 +};
 +
 +static void pcf_probe(struct i2c_client *client, struct IR *ir)
@@ -2869,10 +2869,10 @@ index 0000000..ff49bdd
 +
 diff --git a/drivers/input/lirc/lirc_imon.c b/drivers/input/lirc/lirc_imon.c
 new file mode 100644
-index 0000000..83e4101
+index 0000000..3c87d94
 --- /dev/null
 +++ b/drivers/input/lirc/lirc_imon.c
-@@ -0,0 +1,2062 @@
+@@ -0,0 +1,2298 @@
 +/*
 + *   lirc_imon.c:  LIRC/VFD/LCD driver for SoundGraph iMON IR/VFD/LCD
 + *		   including the iMON PAD model
@@ -2922,6 +2922,8 @@ index 0000000..83e4101
 +
 +#define BIT_DURATION	250	/* each bit received is 250us */
 +
++#define IMON_CLOCK_ENABLE_PACKETS	2
++
 +#define dprintk(fmt, args...)						\
 +	do {								\
 +		if (debug)						\
@@ -3008,7 +3010,7 @@ index 0000000..83e4101
 +	int ir_protocol;		/* iMON or MCE (RC6) IR protocol? */
 +	struct input_dev *mouse;	/* input device for iMON PAD remote */
 +	struct input_dev *touch;	/* input device for touchscreen */
-+	int has_touchscreen;		/* touchscreen present? */
++	int display_type;		/* store the display type */
 +	int pad_mouse;			/* toggle kbd(0)/mouse(1) mode */
 +	int touch_x;			/* x coordinate on touchscreen */
 +	int touch_y;			/* y coordinate on touchscreen */
@@ -3038,8 +3040,9 @@ index 0000000..83e4101
 +};
 +
 +enum {
-+	IMON_IR_PROTOCOL_IMON = 0,
-+	IMON_IR_PROTOCOL_MCE  = 1,
++	IMON_IR_PROTOCOL_IMON       = 0,
++	IMON_IR_PROTOCOL_MCE        = 1,
++	IMON_IR_PROTOCOL_IMON_NOPAD = 2,
 +};
 +/*
 + * USB Device ID for iMON USB Control Boards
@@ -3236,7 +3239,7 @@ index 0000000..83e4101
 +/* lcd, vfd, vga or none? should be auto-detected, but can be overridden... */
 +static int display_type;
 +
-+/* IR protocol: native iMON or Windows MCE (RC-6) */
++/* IR protocol: native iMON, Windows MCE (RC-6), or iMON w/o PAD stabilize */
 +static int ir_protocol;
 +
 +/*
@@ -3245,6 +3248,9 @@ index 0000000..83e4101
 + */
 +static int nomouse;
 +
++/* threshold at which a pad push registers as an arrow key in kbd mode */
++static int pad_thresh;
++
 +
 +/***  M O D U L E   C O D E ***/
 +
@@ -3260,10 +3266,15 @@ index 0000000..83e4101
 +		 "1=vfd, 2=lcd, 3=vga, 4=none (default: autodetect)");
 +module_param(ir_protocol, int, S_IRUGO | S_IWUSR);
 +MODULE_PARM_DESC(ir_protocol, "Which IR protocol to use. 0=native iMON, "
-+		 "1=Windows Media Center Ed. (RC-6) (default: native iMON)");
++		 "1=Windows Media Center Ed. (RC-6), 2=iMON w/o PAD stabilize "
++		 "(default: native iMON)");
 +module_param(nomouse, int, S_IRUGO | S_IWUSR);
 +MODULE_PARM_DESC(nomouse, "Disable mouse input device mode when IR device is "
 +		 "open. 0=don't disable, 1=disable. (default: don't disable)");
++module_param(pad_thresh, int, S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(pad_thresh, "Threshold at which a pad push registers as an "
++		 "arrow key in kbd mode (default 80 on newer devices, 15 on "
++		 "older devices)");
 +
 +static void free_imon_context(struct imon_context *context)
 +{
@@ -3481,21 +3492,105 @@ index 0000000..83e4101
 +		return -ENODEV;
 +	}
 +
-+	mutex_lock(&context->lock);
-+
 +	if (!context->dev_present_intf0) {
 +		err("%s: no iMON device present", __func__);
-+		retval = -ENODEV;
-+		goto exit;
++		return -ENODEV;
 +	}
 +
 +	memcpy(context->usb_tx_buf, packet, sizeof(packet));
 +	retval = send_packet(context);
 +
-+exit:
-+	mutex_unlock(&context->lock);
++	return retval;
++}
++
++/**
++ * Sends packets to setup and show clock on iMON display
++ *
++ * Arguments: year - last 2 digits of year, month - 1..12,
++ * day - 1..31, dow - day of the week (0-Sun...6-Sat),
++ * hour - 0..23, minute - 0..59, second - 0..59
++ */
++static int send_set_imon_clock(struct imon_context *context,
++			       unsigned int year, unsigned int month,
++			       unsigned int day, unsigned int dow,
++			       unsigned int hour, unsigned int minute,
++			       unsigned int second)
++{
++	unsigned char clock_enable_pkt[IMON_CLOCK_ENABLE_PACKETS][8];
++	int retval = 0;
++	int i;
++
++	if (!context) {
++		err("%s: no context for device", __func__);
++		return -ENODEV;
++	}
++
++	switch(context->display_type) {
++	case IMON_DISPLAY_TYPE_LCD:
++		clock_enable_pkt[0][0] = 0x80;
++		clock_enable_pkt[0][1] = year;
++		clock_enable_pkt[0][2] = month-1;
++		clock_enable_pkt[0][3] = day;
++		clock_enable_pkt[0][4] = hour;
++		clock_enable_pkt[0][5] = minute;
++		clock_enable_pkt[0][6] = second;
++
++		clock_enable_pkt[1][0] = 0x80;
++		clock_enable_pkt[1][1] = 0;
++		clock_enable_pkt[1][2] = 0;
++		clock_enable_pkt[1][3] = 0;
++		clock_enable_pkt[1][4] = 0;
++		clock_enable_pkt[1][5] = 0;
++		clock_enable_pkt[1][6] = 0;
++
++		if (context->ffdc_dev) {
++			clock_enable_pkt[0][7] = 0x50;
++			clock_enable_pkt[1][7] = 0x51;
++		} else {
++			clock_enable_pkt[0][7] = 0x88;
++			clock_enable_pkt[1][7] = 0x8a;
++		}
++
++		break;
++
++	case IMON_DISPLAY_TYPE_VFD:
++		clock_enable_pkt[0][0] = year;
++		clock_enable_pkt[0][1] = month-1;
++		clock_enable_pkt[0][2] = day;
++		clock_enable_pkt[0][3] = dow;
++		clock_enable_pkt[0][4] = hour;
++		clock_enable_pkt[0][5] = minute;
++		clock_enable_pkt[0][6] = second;
++		clock_enable_pkt[0][7] = 0x40;
++
++		clock_enable_pkt[1][0] = 0;
++		clock_enable_pkt[1][1] = 0;
++		clock_enable_pkt[1][2] = 1;
++		clock_enable_pkt[1][3] = 0;
++		clock_enable_pkt[1][4] = 0;
++		clock_enable_pkt[1][5] = 0;
++		clock_enable_pkt[1][6] = 0;
++		clock_enable_pkt[1][7] = 0x42;
++
++		break;
++
++	default:
++		return -ENODEV;
++	}
++
++
++	for (i = 0; i < IMON_CLOCK_ENABLE_PACKETS; i++) {
++		memcpy(context->usb_tx_buf, clock_enable_pkt[i], 8);
++		retval = send_packet(context);
++		if (retval) {
++			err("%s: send_packet failed for packet %d",
++			    __func__, i);
++			break;
++		}
++	}
 +
 +	return retval;
++
 +}
 +
 +/**
@@ -3551,16 +3646,104 @@ index 0000000..83e4101
 +	return count;
 +}
 +
++/**
++ * sysfs functions to control internal imon clock
++ */
++static ssize_t show_imon_clock(struct device *d,
++			       struct device_attribute *attr, char *buf)
++{
++	struct imon_context *context = dev_get_drvdata(d);
++	size_t len;
++
++	if (!context)
++		return -ENODEV;
++
++	mutex_lock(&context->lock);
++
++	if (!context->display_supported) {
++		len = snprintf(buf, PAGE_SIZE, "Not supported.");
++	} else {
++		len = snprintf(buf, PAGE_SIZE,
++			"To set the clock on your iMON display:\n"
++			"# date \"+%%y %%m %%d %%w %%H %%M %%S\" > imon_clock\n"
++			"%s", context->display_isopen ?
++			"\nNOTE: imon device must be closed\n" : "");
++	}
++
++	mutex_unlock(&context->lock);
++
++	return len;
++}
++
++static ssize_t store_imon_clock(struct device *d,
++				struct device_attribute *attr,
++				const char *buf, size_t count)
++{
++	struct imon_context *context = dev_get_drvdata(d);
++	ssize_t retval;
++	unsigned int year, month, day, dow, hour, minute, second;
++
++	if (!context)
++		return -ENODEV;
++
++	mutex_lock(&context->lock);
++
++	if (!context->display_supported) {
++		retval = -ENODEV;
++		goto exit;
++	} else if (context->display_isopen) {
++		retval = -EBUSY;
++		goto exit;
++	}
++
++	if (sscanf(buf, "%u %u %u %u %u %u %u",	&year, &month, &day, &dow,
++		   &hour, &minute, &second) != 7) {
++		retval = -EINVAL;
++		goto exit;
++	}
++
++	if ((month < 1 || month > 12) ||
++	    (day < 1 || day > 31) || (dow > 6) ||
++	    (hour > 23) || (minute > 59) || (second > 59)) {
++		retval = -EINVAL;
++		goto exit;
++	}
++
++	retval = send_set_imon_clock(context, year, month, day, dow,
++				     hour, minute, second);
++	if (retval)
++		goto exit;
++
++	retval = count;
++exit:
++	mutex_unlock(&context->lock);
++
++	return retval;
++}
++
++
++static DEVICE_ATTR(imon_clock, S_IWUSR | S_IRUGO, show_imon_clock,
++		   store_imon_clock);
++
 +static DEVICE_ATTR(associate_remote, S_IWUSR | S_IRUGO, show_associate_remote,
 +		   store_associate_remote);
 +
-+static struct attribute *imon_sysfs_entries[] = {
++static struct attribute *imon_display_sysfs_entries[] = {
++	&dev_attr_imon_clock.attr,
++	NULL
++};
++
++static struct attribute_group imon_display_attribute_group = {
++	.attrs = imon_display_sysfs_entries
++};
++
++static struct attribute *imon_rf_sysfs_entries[] = {
 +	&dev_attr_associate_remote.attr,
 +	NULL
 +};
 +
-+static struct attribute_group imon_attribute_group = {
-+	.attrs = imon_sysfs_entries
++static struct attribute_group imon_rf_attribute_group = {
++	.attrs = imon_rf_sysfs_entries
 +};
 +
 +/**
@@ -3743,12 +3926,15 @@ index 0000000..83e4101
 +	unsigned char ir_proto_packet[] =
 +		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 };
 +
-+	/* not supported on devices that don't do onboard decoding */
-+	if (!context->ir_onboard_decode)
-+		return;
-+
 +	switch (ir_protocol) {
 +	case IMON_IR_PROTOCOL_MCE:
++		/* MCE proto not supported on devices without tx control */
++		if (!context->tx_control) {
++			printk(KERN_INFO "%s: MCE IR protocol not supported on "
++			       "this device, using iMON protocol\n", __func__);
++			context->ir_protocol = IMON_IR_PROTOCOL_IMON;
++			return;
++		}
 +		dprintk("Configuring IR receiver for MCE protocol\n");
 +		ir_proto_packet[0] = 0x01;
 +		context->ir_protocol = IMON_IR_PROTOCOL_MCE;
@@ -3758,10 +3944,16 @@ index 0000000..83e4101
 +		/* ir_proto_packet[0] = 0x00; // already the default */
 +		context->ir_protocol = IMON_IR_PROTOCOL_IMON;
 +		break;
++	case IMON_IR_PROTOCOL_IMON_NOPAD:
++		dprintk("Configuring IR receiver for iMON protocol without "
++			"PAD stabilize function enabled\n");
++		/* ir_proto_packet[0] = 0x00; // already the default */
++		context->ir_protocol = IMON_IR_PROTOCOL_IMON_NOPAD;
++		break;
 +	default:
 +		printk(KERN_INFO "%s: unknown IR protocol specified, will "
 +		       "just default to iMON protocol\n", __func__);
-+		context->ir_protocol = IMON_IR_PROTOCOL_MCE;
++		context->ir_protocol = IMON_IR_PROTOCOL_IMON;
 +		break;
 +	}
 +	memcpy(context->usb_tx_buf, &ir_proto_packet,
@@ -3891,12 +4083,14 @@ index 0000000..83e4101
 +}
 +
 +/**
-+ * The directional pad is overly sensitive in keyboard mode, so we do some
-+ * interesting contortions to make it less touchy.
++ * The directional pad behaves a bit differently, depending on whether this is
++ * one of the older ffdc devices or a newer device. Newer devices appear to
++ * have a higher resolution matrix for more precise mouse movement, but it
++ * makes things overly sensitive in keyboard mode, so we do some interesting
++ * contortions to make it less touchy. Older devices run through the same
++ * routine with shorter timeout and a smaller threshold.
 + */
-+#define IMON_PAD_TIMEOUT	1000	/* in msecs */
-+#define IMON_PAD_THRESHOLD	80	/* 160x160 square */
-+static int stabilize(int a, int b)
++static int stabilize(int a, int b, u16 timeout, u16 threshold)
 +{
 +	struct timeval ct;
 +	static struct timeval prev_time = {0, 0};
@@ -3920,7 +4114,7 @@ index 0000000..83e4101
 +
 +	prev_time = ct;
 +
-+	if (abs(x) > IMON_PAD_THRESHOLD || abs(y) > IMON_PAD_THRESHOLD) {
++	if (abs(x) > threshold || abs(y) > threshold) {
 +		if (abs(y) > abs(x))
 +			result = (y > 0) ? 0x7F : 0x80;
 +		else
@@ -3935,21 +4129,21 @@ index 0000000..83e4101
 +			if (hits > 3) {
 +				switch (result) {
 +				case 0x7F:
-+					y = 17 * IMON_PAD_THRESHOLD / 30;
++					y = 17 * threshold / 30;
 +					break;
 +				case 0x80:
-+					y -= 17 * IMON_PAD_THRESHOLD / 30;
++					y -= 17 * threshold / 30;
 +					break;
 +				case 0x7F00:
-+					x = 17 * IMON_PAD_THRESHOLD / 30;
++					x = 17 * threshold / 30;
 +					break;
 +				case 0x8000:
-+					x -= 17 * IMON_PAD_THRESHOLD / 30;
++					x -= 17 * threshold / 30;
 +					break;
 +				}
 +			}
 +
-+			if (hits == 2 && msec_hit < IMON_PAD_TIMEOUT) {
++			if (hits == 2 && msec_hit < timeout) {
 +				result = 0;
 +				hits = 1;
 +			}
@@ -3974,20 +4168,21 @@ index 0000000..83e4101
 +	char rel_x = 0x00, rel_y = 0x00;
 +	int octet, bit;
 +	unsigned char mask;
-+	int i, chunk_num, dir;
++	int i, chunk_num;
 +	int ts_input = 0;
 +	int mouse_input;
++	int right_shift = 1;
++	int dir = 0;
++	u16 timeout, threshold;
 +	struct input_dev *mouse = NULL;
 +	struct input_dev *touch = NULL;
 +	const unsigned char toggle_button1[] = { 0x29, 0x91, 0x15, 0xb7 };
 +	const unsigned char toggle_button2[] = { 0x29, 0x91, 0x35, 0xb7 };
 +	const unsigned char ch_up[]   = { 0x28, 0x93, 0x95, 0xb7 };
 +	const unsigned char ch_down[] = { 0x28, 0x87, 0x95, 0xb7 };
-+	const unsigned char btn_left[]  = { 0x68, 0x83, 0x01, 0xb7 };
-+	const unsigned char btn_right[] = { 0x68, 0x84, 0x81, 0xb7 };
 +
 +	mouse = context->mouse;
-+	if (context->has_touchscreen)
++	if (context->display_type == IMON_DISPLAY_TYPE_VGA)
 +		touch = context->touch;
 +
 +	/* keyboard/mouse mode toggle button */
@@ -4005,8 +4200,8 @@ index 0000000..83e4101
 +	}
 +
 +	/* send touchscreen events through input subsystem if touchpad data */
-+	if (context->has_touchscreen && len == 8 &&
-+	    (buf[6] == 0x14 || buf[6] == 0x03) && buf[7] == 0x86) {
++	if (context->display_type == IMON_DISPLAY_TYPE_VGA && len == 8 &&
++	    buf[7] == 0x86) {
 +		if (touch == NULL) {
 +			printk(KERN_WARNING "%s: touchscreen input device is "
 +			       "NULL!\n", __func__);
@@ -4028,31 +4223,30 @@ index 0000000..83e4101
 +			mouse_input = 1;
 +			rel_x = buf[2];
 +			rel_y = buf[3];
-+		/* 0xffdc iMON PAD input */
++			right_shift = 1;
++		/* 0xffdc iMON PAD or mouse button input */
 +		} else if (context->ffdc_dev && (buf[0] & 0x40) &&
 +			   !((buf[1] & 0x01) || ((buf[1] >> 2) & 0x01))) {
 +			mouse_input = 1;
 +			rel_x = (buf[1] & 0x08) | (buf[1] & 0x10) >> 2 |
 +				(buf[1] & 0x20) >> 4 | (buf[1] & 0x40) >> 6;
 +			if (buf[0] & 0x02)
-+				rel_x |= ~0x11;
++				rel_x |= ~0x0f;
 +			rel_x = rel_x + rel_x / 2;
 +			rel_y = (buf[2] & 0x08) | (buf[2] & 0x10) >> 2 |
 +				(buf[2] & 0x20) >> 4 | (buf[2] & 0x40) >> 6;
 +			if (buf[0] & 0x01)
-+				rel_y |= ~0x11;
++				rel_y |= ~0x0f;
 +			rel_y = rel_y + rel_y / 2;
-+		/* 0xffdc mouse buttons */
-+		} else if (context->ffdc_dev && !memcmp(buf, btn_left, 4)) {
-+			mouse_input = 1;
-+			buf[1] = 0x01;
-+		} else if (context->ffdc_dev && !memcmp(buf, btn_right, 4)) {
-+			mouse_input = 1;
-+			buf[1] = 0x02;
++			right_shift = 2;
 +		/* ch+/- buttons, which we use for an emulated scroll wheel */
-+		} else if (!memcmp(buf, ch_up, 4) || !memcmp(buf, ch_down, 4))
++		} else if (!memcmp(buf, ch_up, 4)) {
 +			mouse_input = 1;
-+		else
++			dir = 1;
++		} else if (!memcmp(buf, ch_down, 4)) {
++			mouse_input = 1;
++			dir = -1;
++		} else
 +			mouse_input = 0;
 +
 +		if (mouse_input) {
@@ -4062,18 +4256,12 @@ index 0000000..83e4101
 +				return;
 +			}
 +			dprintk("sending mouse data via input subsystem\n");
-+			if (!memcmp(buf, ch_up, 4))
-+				dir = 1;
-+			else if (!memcmp(buf, ch_down, 4))
-+				dir = -1;
-+			else
-+				dir = 0;
 +
 +			if (dir == 0) {
 +				input_report_key(mouse, BTN_LEFT,
 +						 buf[1] & 0x01);
 +				input_report_key(mouse, BTN_RIGHT,
-+						 buf[1] >> 1 & 0x01);
++						 buf[1] >> right_shift & 0x01);
 +				input_report_rel(mouse, REL_X, rel_x);
 +				input_report_rel(mouse, REL_Y, rel_y);
 +			} else
@@ -4098,6 +4286,9 @@ index 0000000..83e4101
 +		/* first, pad to 8 bytes so it conforms with everything else */
 +		buf[5] = buf[6] = buf[7] = 0;
 +		len = 8;
++		timeout = 500;	/* in msecs */
++		/* (2*threshold) x (2*threshold) square */
++		threshold = pad_thresh ? pad_thresh : 80;
 +		rel_x = buf[2];
 +		rel_y = buf[3];
 +
@@ -4111,12 +4302,23 @@ index 0000000..83e4101
 +		 * diagonals, it has a tendancy to jump back and forth, so lets
 +		 * try to ignore when they get too close
 +		 */
-+		if ((buf[1] == 0) && ((rel_x != 0) || (rel_y != 0))) {
-+			dir = stabilize((int)rel_x, (int)rel_y);
-+			if (!dir)
-+				return;
-+			buf[2] = dir & 0xFF;
-+			buf[3] = (dir >> 8) & 0xFF;
++		if (context->ir_protocol == IMON_IR_PROTOCOL_IMON) {
++			if ((buf[1] == 0) && ((rel_x != 0) || (rel_y != 0))) {
++				dir = stabilize((int)rel_x, (int)rel_y,
++						timeout, threshold);
++				if (!dir)
++					return;
++				buf[2] = dir & 0xFF;
++				buf[3] = (dir >> 8) & 0xFF;
++			}
++		} else {
++			if (abs(rel_y) > abs(rel_x)) {
++				buf[2] = (rel_y > 0) ? 0x7F : 0x80;
++				buf[3] = 0;
++			} else {
++				buf[2] = 0;
++				buf[3] = (rel_x > 0) ? 0x7F : 0x80;
++			}
 +		}
 +
 +	} else if ((len == 8) && (buf[0] & 0x40) &&
@@ -4134,6 +4336,9 @@ index 0000000..83e4101
 +		 * 0x01007F00, ..., so one can use the normal imon-pad config
 +		 * from the remotes dir.
 +		 */
++		timeout = 10;	/* in msecs */
++		/* (2*threshold) x (2*threshold) square */
++		threshold = pad_thresh ? pad_thresh : 15;
 +
 +		/* buf[1] is x */
 +		rel_x = (buf[1] & 0x08) | (buf[1] & 0x10) >> 2 |
@@ -4149,11 +4354,22 @@ index 0000000..83e4101
 +		buf[0] = 0x01;
 +		buf[1] = buf[4] = buf[5] = buf[6] = buf[7] = 0;
 +
-+		dir = stabilize((int)rel_x, (int)rel_y);
-+		if (!dir)
-+			return;
-+		buf[2] = dir & 0xFF;
-+		buf[3] = (dir >> 8) & 0xFF;
++		if (context->ir_protocol == IMON_IR_PROTOCOL_IMON) {
++			dir = stabilize((int)rel_x, (int)rel_y,
++					timeout, threshold);
++			if (!dir)
++				return;
++			buf[2] = dir & 0xFF;
++			buf[3] = (dir >> 8) & 0xFF;
++		} else {
++			if (abs(rel_y) > abs(rel_x)) {
++				buf[2] = (rel_y > 0) ? 0x7F : 0x80;
++				buf[3] = 0;
++			} else {
++				buf[2] = 0;
++				buf[3] = (rel_x > 0) ? 0x7F : 0x80;
++			}
++		}
 +
 +	} else if (ts_input) {
 +		/*
@@ -4276,7 +4492,7 @@ index 0000000..83e4101
 +	struct imon_context *context = (struct imon_context *)data;
 +	struct input_dev *touch;
 +
-+	if (!context->has_touchscreen)
++	if (!context->display_type == IMON_DISPLAY_TYPE_VGA)
 +		return;
 +
 +	touch = context->touch;
@@ -4387,24 +4603,41 @@ index 0000000..83e4101
 +	int alloc_status = 0;
 +	int vfd_proto_6p = 0;
 +	int ir_onboard_decode = 0;
-+	int has_touchscreen = 0;
 +	int buf_chunk_size = BUF_CHUNK_SIZE;
 +	int code_length;
 +	int tx_control = 0;
 +	struct imon_context *context = NULL;
 +	struct imon_context *first_if_context = NULL;
-+	int i;
++	int i, sysfs_err;
++	int configured_display_type = IMON_DISPLAY_TYPE_VFD;
 +	u16 vendor, product;
 +	const unsigned char fp_packet[] = { 0x40, 0x00, 0x00, 0x00,
 +					    0x00, 0x00, 0x00, 0x88 };
 +
 +	/*
++	 * Try to auto-detect the type of display if the user hasn't set
++	 * it by hand via the display_type modparam. Default is VFD.
++	 */
++	if (display_type == IMON_DISPLAY_TYPE_AUTO) {
++		if (usb_match_id(interface, lcd_device_list))
++			configured_display_type = IMON_DISPLAY_TYPE_LCD;
++		else if (usb_match_id(interface, imon_touchscreen_list))
++			configured_display_type = IMON_DISPLAY_TYPE_VGA;
++		else if (usb_match_id(interface, ir_only_list))
++			configured_display_type = IMON_DISPLAY_TYPE_NONE;
++		else
++			configured_display_type = IMON_DISPLAY_TYPE_VFD;
++	} else {
++		configured_display_type = display_type;
++		dprintk("%s: overriding display type to %d via modparam\n",
++			__func__, display_type);
++	}
++
++	/*
 +	 * If it's the LCD, as opposed to the VFD, we just need to replace
 +	 * the "write" file op.
 +	 */
-+	if ((display_type == IMON_DISPLAY_TYPE_AUTO &&
-+	     usb_match_id(interface, lcd_device_list)) ||
-+	    display_type == IMON_DISPLAY_TYPE_LCD)
++	if (configured_display_type == IMON_DISPLAY_TYPE_LCD)
 +		display_fops.write = &lcd_write;
 +
 +	/*
@@ -4480,9 +4713,7 @@ index 0000000..83e4101
 +	 * that SoundGraph recycles device IDs between devices both with
 +	 * and without... :\
 +	 */
-+	if ((display_type == IMON_DISPLAY_TYPE_AUTO &&
-+	     usb_match_id(interface, ir_only_list)) ||
-+	    display_type == IMON_DISPLAY_TYPE_NONE) {
++	if (configured_display_type == IMON_DISPLAY_TYPE_NONE) {
 +		display_ep_found = 0;
 +		dprintk("%s: device has no display\n", __func__);
 +	}
@@ -4491,11 +4722,8 @@ index 0000000..83e4101
 +	 * iMON Touch devices have a VGA touchscreen, but no "display", as
 +	 * that refers to e.g. /dev/lcd0 (a character device LCD or VFD).
 +	 */
-+	if ((display_type == IMON_DISPLAY_TYPE_AUTO &&
-+	     usb_match_id(interface, imon_touchscreen_list)) ||
-+	    display_type == IMON_DISPLAY_TYPE_VGA) {
++	if (configured_display_type == IMON_DISPLAY_TYPE_VGA) {
 +		display_ep_found = 0;
-+		has_touchscreen = 1;
 +		dprintk("%s: iMON Touch device found\n", __func__);
 +	}
 +
@@ -4636,7 +4864,7 @@ index 0000000..83e4101
 +		if (product == 0xffdc)
 +			context->ffdc_dev = 1;
 +
-+		context->has_touchscreen = has_touchscreen;
++		context->display_type = configured_display_type;
 +
 +		context->mouse = input_allocate_device();
 +
@@ -4689,7 +4917,7 @@ index 0000000..83e4101
 +		context->rx_endpoint_intf1 = rx_endpoint;
 +		context->rx_urb_intf1 = rx_urb;
 +
-+		if (context->has_touchscreen) {
++		if (context->display_type == IMON_DISPLAY_TYPE_VGA) {
 +			context->touch = input_allocate_device();
 +
 +			snprintf(context->name_touch,
@@ -4745,17 +4973,23 @@ index 0000000..83e4101
 +
 +	/* RF products *also* use 0xffdc... sigh... */
 +	if (context->ffdc_dev) {
-+		int err;
-+
-+		err = sysfs_create_group(&interface->dev.kobj,
-+					 &imon_attribute_group);
-+		if (err)
-+			err("%s: Could not create sysfs entries(%d)",
-+			    __func__, err);
++		sysfs_err = sysfs_create_group(&interface->dev.kobj,
++					       &imon_rf_attribute_group);
++		if (sysfs_err)
++			err("%s: Could not create RF sysfs entries(%d)",
++			    __func__, sysfs_err);
 +	}
 +
 +	if (context->display_supported && ifnum == 0) {
 +		dprintk("%s: Registering iMON display with sysfs\n", __func__);
++
++		/* set up sysfs entry for built-in clock */
++		sysfs_err = sysfs_create_group(&interface->dev.kobj,
++					       &imon_display_attribute_group);
++		if (sysfs_err)
++			err("%s: Could not create display sysfs entries(%d)",
++			    __func__, sysfs_err);
++
 +		if (usb_register_dev(interface, &imon_class)) {
 +			/* Not a fatal error, so ignore */
 +			printk(KERN_INFO "%s: could not get a minor number for "
@@ -4830,7 +5064,9 @@ index 0000000..83e4101
 +	 * hasn't been called
 +	 */
 +	sysfs_remove_group(&interface->dev.kobj,
-+			   &imon_attribute_group);
++			   &imon_display_attribute_group);
++	sysfs_remove_group(&interface->dev.kobj,
++			   &imon_rf_attribute_group);
 +
 +	usb_set_intfdata(interface, NULL);
 +
@@ -4849,7 +5085,7 @@ index 0000000..83e4101
 +	} else {
 +		context->dev_present_intf1 = 0;
 +		usb_kill_urb(context->rx_urb_intf1);
-+		if (context->has_touchscreen)
++		if (context->display_type == IMON_DISPLAY_TYPE_VGA)
 +			input_unregister_device(context->touch);
 +	}
 +
@@ -6596,10 +6832,10 @@ index 0000000..3d53181
 +MODULE_PARM_DESC(debug, "Enable debugging messages");
 diff --git a/drivers/input/lirc/lirc_mceusb.c b/drivers/input/lirc/lirc_mceusb.c
 new file mode 100644
-index 0000000..840d0e1
+index 0000000..58dfdd5
 --- /dev/null
 +++ b/drivers/input/lirc/lirc_mceusb.c
-@@ -0,0 +1,1223 @@
+@@ -0,0 +1,1225 @@
 +/*
 + * LIRC driver for Windows Media Center Edition USB Infrared Transceivers
 + *
@@ -6783,6 +7019,8 @@ index 0000000..840d0e1
 +	{ USB_DEVICE(VENDOR_FORMOSA, 0xe017) },
 +	/* Formosa Industrial Computing / Beanbag Emulation Device */
 +	{ USB_DEVICE(VENDOR_FORMOSA, 0xe018) },
++	/* Formosa Industrial Computing AIM IR605/A */
++	{ USB_DEVICE(VENDOR_FORMOSA, 0xe03c) },
 +	/* Fintek eHome Infrared Transceiver */
 +	{ USB_DEVICE(VENDOR_FINTEK, 0x0602) },
 +	/* Fintek eHome Infrared Transceiver (in the AOpen MP45) */
@@ -10831,10 +11069,10 @@ index 0000000..d602e90
 +MODULE_PARM_DESC(debug, "Enable debugging messages");
 diff --git a/drivers/input/lirc/lirc_sir.c b/drivers/input/lirc/lirc_sir.c
 new file mode 100644
-index 0000000..6c64072
+index 0000000..b497642
 --- /dev/null
 +++ b/drivers/input/lirc/lirc_sir.c
-@@ -0,0 +1,1294 @@
+@@ -0,0 +1,1283 @@
 +/*
 + * LIRC SIR driver, (C) 2000 Milan Pikula <www at fornax.sk>
 + *
@@ -10979,8 +11217,16 @@ index 0000000..6c64072
 +#define LIRC_IRQ 4
 +#endif
 +#ifndef LIRC_PORT
++/* for external dongles, default to com1 */
++#if defined(LIRC_SIR_ACTISYS_ACT200L) || \
++    defined(LIRC_SIR_ACTISYS_ACT220L) || \
++    defined(LIRC_SIR_TEKRAM)
++#define LIRC_PORT 0x3f8
++#else
++/* onboard sir ports are typically com3 */
 +#define LIRC_PORT 0x3e8
 +#endif
++#endif
 +
 +static int io = LIRC_PORT;
 +static int irq = LIRC_IRQ;
@@ -10998,7 +11244,6 @@ index 0000000..6c64072
 +static DECLARE_WAIT_QUEUE_HEAD(lirc_read_queue);
 +
 +static DEFINE_SPINLOCK(hardware_lock);
-+static DEFINE_SPINLOCK(dev_lock);
 +
 +static int rx_buf[RBUF_LEN];
 +static unsigned int rx_tail, rx_head;
@@ -11015,8 +11260,6 @@ index 0000000..6c64072
 +/* SECTION: Prototypes */
 +
 +/* Communication with user-space */
-+static int lirc_open(struct inode *inode, struct file *file);
-+static int lirc_close(struct inode *inode, struct file *file);
 +static unsigned int lirc_poll(struct file *file, poll_table *wait);
 +static ssize_t lirc_read(struct file *file, char *buf, size_t count,
 +		loff_t *ppos);
@@ -11076,22 +11319,6 @@ index 0000000..6c64072
 +
 +/* SECTION: Communication with user-space */
 +
-+static int lirc_open(struct inode *inode, struct file *file)
-+{
-+	spin_lock(&dev_lock);
-+	if (module_refcount(THIS_MODULE)) {
-+		spin_unlock(&dev_lock);
-+		return -EBUSY;
-+	}
-+	spin_unlock(&dev_lock);
-+	return 0;
-+}
-+
-+static int lirc_close(struct inode *inode, struct file *file)
-+{
-+	return 0;
-+}
-+
 +static unsigned int lirc_poll(struct file *file, poll_table *wait)
 +{
 +	poll_wait(file, &lirc_read_queue, wait);
@@ -11306,8 +11533,8 @@ index 0000000..6c64072
 +	.write		= lirc_write,
 +	.poll		= lirc_poll,
 +	.ioctl		= lirc_ioctl,
-+	.open		= lirc_open,
-+	.release	= lirc_close,
++	.open		= lirc_dev_fop_open,
++	.release	= lirc_dev_fop_close,
 +};
 +
 +static int set_use_inc(void *data)
@@ -13317,7 +13544,7 @@ index 0000000..2955bad
 +module_exit(ttusbir_exit_module);
 diff --git a/drivers/input/lirc/lirc_zilog.c b/drivers/input/lirc/lirc_zilog.c
 new file mode 100644
-index 0000000..a06e6de
+index 0000000..c532399
 --- /dev/null
 +++ b/drivers/input/lirc/lirc_zilog.c
 @@ -0,0 +1,1374 @@

xen.pvops.post.patch:
 arch/x86/kernel/cpu/Makefile                 |    2 ++
 b/arch/x86/include/asm/paravirt_types.h      |    3 +++
 b/arch/x86/kernel/pci-swiotlb.c              |    5 ++---
 b/arch/x86/kernel/process_32.c               |    2 ++
 b/arch/x86/pci/common.c                      |   16 ++++++++++++++++
 drivers/pci/pci.h                            |    2 ++
 linux-2.6.29.x86_64/arch/x86/xen/Makefile    |    4 ++++
 linux-2.6.29.x86_64/arch/x86/xen/enlighten.c |    2 +-
 linux-2.6.29.x86_64/drivers/xen/Makefile     |    3 +++
 9 files changed, 35 insertions(+), 4 deletions(-)

Index: xen.pvops.post.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/Attic/xen.pvops.post.patch,v
retrieving revision 1.1.2.19
retrieving revision 1.1.2.20
diff -u -p -r1.1.2.19 -r1.1.2.20
--- xen.pvops.post.patch	8 Aug 2009 18:06:06 -0000	1.1.2.19
+++ xen.pvops.post.patch	10 Aug 2009 21:22:20 -0000	1.1.2.20
@@ -68,6 +68,22 @@ index 2202b62..f371fe8 100644
  }
  
  int __init pcibios_init(void)
+diff --git a/arch/x86/kernel/pci-swiotlb.c b/arch/x86/kernel/pci-swiotlb.c
+index 6af96ee..1e66b18 100644
+--- a/arch/x86/kernel/pci-swiotlb.c
++++ b/arch/x86/kernel/pci-swiotlb.c
+@@ -71,9 +71,8 @@ void __init pci_swiotlb_init(void)
+ {
+ 	/* don't initialize swiotlb if iommu=off (no_iommu=1) */
+ #ifdef CONFIG_X86_64
+-	if ((!iommu_detected && !no_iommu && max_pfn > MAX_DMA32_PFN) ||
+-		iommu_pass_through)
+-	       swiotlb = 1;
++	if ((!iommu_detected && !no_iommu && max_pfn > MAX_DMA32_PFN))
++		swiotlb = 1;
+ #endif
+ 	if (xen_wants_swiotlb())
+ 		swiotlb = 1;
 --- linux-2.6.29.x86_64/arch/x86/xen/Makefile.orig	2009-04-24 22:54:26.000000000 +0100
 +++ linux-2.6.29.x86_64/arch/x86/xen/Makefile	2009-04-26 16:46:57.000000000 +0100
 @@ -4,6 +4,10 @@

xen.pvops.pre.patch:
 b/arch/x86/include/asm/paravirt.h |    3 ---
 b/arch/x86/kernel/pci-swiotlb.c   |    5 +++--
 b/arch/x86/kernel/process_32.c    |    3 +--
 b/arch/x86/pci/common.c           |   16 ----------------
 drivers/pci/pci.h                 |    2 --
 5 files changed, 4 insertions(+), 25 deletions(-)

Index: xen.pvops.pre.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/Attic/xen.pvops.pre.patch,v
retrieving revision 1.1.2.15
retrieving revision 1.1.2.16
diff -u -p -r1.1.2.15 -r1.1.2.16
--- xen.pvops.pre.patch	8 Aug 2009 18:06:06 -0000	1.1.2.15
+++ xen.pvops.pre.patch	10 Aug 2009 21:22:20 -0000	1.1.2.16
@@ -2,6 +2,8 @@ temporarily revert various Fedora change
 Affected patches;
 linux-2.6-defaults-pci_no_msi.patch - drivers/pci/pci.h
 linux-2.6-execshield.patch - arch/x86/include/asm/paravirt.h arch/x86/kernel/process_32.c
+linux-2.6-intel-iommu-updates.patch - arch/x86/kernel/pci-swiotlb.c
+linux-2.6-pci-cacheline-sizing.patch - arch/x86/pci/common.c
 
 --- a/drivers/pci/pci.h	2009-04-24 20:46:50.000000000 +0100
 +++ b/drivers/pci/pci.h	2009-04-23 20:13:43.000000000 +0100
@@ -72,3 +74,19 @@ index 2202b62..f371fe8 100644
  	pcibios_resource_survey();
  
  	if (pci_bf_sort >= pci_force_bf)
+diff --git a/arch/x86/kernel/pci-swiotlb.c b/arch/x86/kernel/pci-swiotlb.c
+index 6af96ee..1e66b18 100644
+--- a/arch/x86/kernel/pci-swiotlb.c
++++ b/arch/x86/kernel/pci-swiotlb.c
+@@ -71,8 +71,9 @@ void __init pci_swiotlb_init(void)
+ {
+ 	/* don't initialize swiotlb if iommu=off (no_iommu=1) */
+ #ifdef CONFIG_X86_64
+-	if ((!iommu_detected && !no_iommu && max_pfn > MAX_DMA32_PFN))
+-		swiotlb = 1;
++	if ((!iommu_detected && !no_iommu && max_pfn > MAX_DMA32_PFN) ||
++		iommu_pass_through)
++	       swiotlb = 1;
+ #endif
+ 	if (swiotlb_force)
+ 		swiotlb = 1;




More information about the fedora-extras-commits mailing list