--- /dev/null
+From 85a00d9bbfb4704fbf368944b1cb9fed8f1598c5 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Wed, 22 Sep 2010 13:05:04 -0700
+Subject: efifb: check that the base address is plausible on pci systems
+
+From: Peter Jones <pjones@redhat.com>
+
+commit 85a00d9bbfb4704fbf368944b1cb9fed8f1598c5 upstream.
+
+Some Apple machines have identical DMI data but different memory
+configurations for the video. Given that, check that the address in our
+table is actually within the range of a PCI BAR on a VGA device in the
+machine.
+
+This also fixes up the return value from set_system(), which has always
+been wrong, but never resulted in bad behavior since there's only ever
+been one matching entry in the dmi table.
+
+The patch
+
+1) stops people's machines from crashing when we get their display wrong,
+ which seems to be unfortunately inevitable,
+
+2) allows us to support identical dmi data with differing video memory
+ configurations
+
+This also adds me as the efifb maintainer, since I've effectively been
+acting as such for quite some time.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: maximilian attems <max@stro.at>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ MAINTAINERS | 6 ++++
+ drivers/video/efifb.c | 61 ++++++++++++++++++++++++++++++++++++++++----------
+ 2 files changed, 55 insertions(+), 12 deletions(-)
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -1974,6 +1974,12 @@ W: http://acpi4asus.sf.net
+ S: Maintained
+ F: drivers/platform/x86/eeepc-laptop.c
+
++EFIFB FRAMEBUFFER DRIVER
++L: linux-fbdev@vger.kernel.org
++M: Peter Jones <pjones@redhat.com>
++S: Maintained
++F: drivers/video/efifb.c
++
+ EFS FILESYSTEM
+ W: http://aeschi.ch.eu.org/efs/
+ S: Orphan
+--- a/drivers/video/efifb.c
++++ b/drivers/video/efifb.c
+@@ -13,7 +13,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/screen_info.h>
+ #include <linux/dmi.h>
+-
++#include <linux/pci.h>
+ #include <video/vga.h>
+
+ static struct fb_var_screeninfo efifb_defined __initdata = {
+@@ -113,7 +113,7 @@ static int set_system(const struct dmi_s
+ {
+ struct efifb_dmi_info *info = id->driver_data;
+ if (info->base == 0)
+- return -ENODEV;
++ return 0;
+
+ printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p "
+ "(%dx%d, stride %d)\n", id->ident,
+@@ -121,18 +121,55 @@ static int set_system(const struct dmi_s
+ info->stride);
+
+ /* Trust the bootloader over the DMI tables */
+- if (screen_info.lfb_base == 0)
++ if (screen_info.lfb_base == 0) {
++#if defined(CONFIG_PCI)
++ struct pci_dev *dev = NULL;
++ int found_bar = 0;
++#endif
+ screen_info.lfb_base = info->base;
+- if (screen_info.lfb_linelength == 0)
+- screen_info.lfb_linelength = info->stride;
+- if (screen_info.lfb_width == 0)
+- screen_info.lfb_width = info->width;
+- if (screen_info.lfb_height == 0)
+- screen_info.lfb_height = info->height;
+- if (screen_info.orig_video_isVGA == 0)
+- screen_info.orig_video_isVGA = VIDEO_TYPE_EFI;
+
+- return 0;
++#if defined(CONFIG_PCI)
++ /* make sure that the address in the table is actually on a
++ * VGA device's PCI BAR */
++
++ for_each_pci_dev(dev) {
++ int i;
++ if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
++ continue;
++ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
++ resource_size_t start, end;
++
++ start = pci_resource_start(dev, i);
++ if (start == 0)
++ break;
++ end = pci_resource_end(dev, i);
++ if (screen_info.lfb_base >= start &&
++ screen_info.lfb_base < end) {
++ found_bar = 1;
++ }
++ }
++ }
++ if (!found_bar)
++ screen_info.lfb_base = 0;
++#endif
++ }
++ if (screen_info.lfb_base) {
++ if (screen_info.lfb_linelength == 0)
++ screen_info.lfb_linelength = info->stride;
++ if (screen_info.lfb_width == 0)
++ screen_info.lfb_width = info->width;
++ if (screen_info.lfb_height == 0)
++ screen_info.lfb_height = info->height;
++ if (screen_info.orig_video_isVGA == 0)
++ screen_info.orig_video_isVGA = VIDEO_TYPE_EFI;
++ } else {
++ screen_info.lfb_linelength = 0;
++ screen_info.lfb_width = 0;
++ screen_info.lfb_height = 0;
++ screen_info.orig_video_isVGA = 0;
++ return 0;
++ }
++ return 1;
+ }
+
+ static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green,
--- /dev/null
+From 2a5f07b5ec098edc69e05fdd2f35d3fbb1235723 Mon Sep 17 00:00:00 2001
+From: Tejun Heo <tj@kernel.org>
+Date: Mon, 1 Nov 2010 11:39:19 +0100
+Subject: libata: fix NULL sdev dereference race in atapi_qc_complete()
+
+From: Tejun Heo <tj@kernel.org>
+
+commit 2a5f07b5ec098edc69e05fdd2f35d3fbb1235723 upstream.
+
+SCSI commands may be issued between __scsi_add_device() and dev->sdev
+assignment, so it's unsafe for ata_qc_complete() to dereference
+dev->sdev->locked without checking whether it's NULL or not. Fix it.
+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/ata/libata-scsi.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/ata/libata-scsi.c
++++ b/drivers/ata/libata-scsi.c
+@@ -2497,8 +2497,11 @@ static void atapi_qc_complete(struct ata
+ *
+ * If door lock fails, always clear sdev->locked to
+ * avoid this infinite loop.
++ *
++ * This may happen before SCSI scan is complete. Make
++ * sure qc->dev->sdev isn't NULL before dereferencing.
+ */
+- if (qc->cdb[0] == ALLOW_MEDIUM_REMOVAL)
++ if (qc->cdb[0] == ALLOW_MEDIUM_REMOVAL && qc->dev->sdev)
+ qc->dev->sdev->locked = 0;
+
+ qc->scsicmd->result = SAM_STAT_CHECK_CONDITION;
--- /dev/null
+From bc496ed00ab1411d3efaf295b72e0c9eb343e1a3 Mon Sep 17 00:00:00 2001
+From: Douglas Gilbert <dgilbert@interlog.com>
+Date: Mon, 1 Feb 2010 13:11:38 -0500
+Subject: libata-scsi passthru: fix bug which truncated LBA48 return values
+
+From: Douglas Gilbert <dgilbert@interlog.com>
+
+commit bc496ed00ab1411d3efaf295b72e0c9eb343e1a3 upstream.
+
+Fix assignment which overwrote SAT ATA PASS-THROUGH command EXTEND
+bit setting (ATA_TFLAG_LBA48)
+
+Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
+Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
+Cc: Kerin Millar <kerframil@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/ata/libata-scsi.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/ata/libata-scsi.c
++++ b/drivers/ata/libata-scsi.c
+@@ -2825,7 +2825,7 @@ static unsigned int ata_scsi_pass_thru(s
+ * write indication (used for PIO/DMA setup), result TF is
+ * copied back and we don't whine too much about its failure.
+ */
+- tf->flags = ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
++ tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+ if (scmd->sc_data_direction == DMA_TO_DEVICE)
+ tf->flags |= ATA_TFLAG_WRITE;
+
--- /dev/null
+From 8c05cd08a7504b855c265263e84af61aabafa329 Mon Sep 17 00:00:00 2001
+From: Darrick J. Wong <djwong@us.ibm.com>
+Date: Tue, 16 Nov 2010 09:13:41 -0800
+Subject: PCI: fix offset check for sysfs mmapped files
+
+From: Darrick J. Wong <djwong@us.ibm.com>
+
+commit 8c05cd08a7504b855c265263e84af61aabafa329 upstream.
+
+I just loaded 2.6.37-rc2 on my machines, and I noticed that X no longer starts.
+Running an strace of the X server shows that it's doing this:
+
+open("/sys/bus/pci/devices/0000:07:00.0/resource0", O_RDWR) = 10
+mmap(NULL, 16777216, PROT_READ|PROT_WRITE, MAP_SHARED, 10, 0) = -1 EINVAL (Invalid argument)
+
+This code seems to be asking for a shared read/write mapping of 16MB worth of
+BAR0 starting at file offset 0, and letting the kernel assign a starting
+address. Unfortunately, this -EINVAL causes X not to start. Looking into
+dmesg, there's a complaint like so:
+
+process "Xorg" tried to map 0x01000000 bytes at page 0x00000000 on 0000:07:00.0 BAR 0 (start 0x 96000000, size 0x 1000000)
+
+...with the following code in pci_mmap_fits:
+
+ pci_start = (mmap_api == PCI_MMAP_SYSFS) ?
+ pci_resource_start(pdev, resno) >> PAGE_SHIFT : 0;
+ if (start >= pci_start && start < pci_start + size &&
+ start + nr <= pci_start + size)
+
+It looks like the logic here is set up such that when the mmap call comes via
+sysfs, the check in pci_mmap_fits wants vma->vm_pgoff to be between the
+resource's start and end address, and the end of the vma to be no farther than
+the end. However, the sysfs PCI resource files always start at offset zero,
+which means that this test always fails for programs that mmap the sysfs files.
+Given the comment in the original commit
+3b519e4ea618b6943a82931630872907f9ac2c2b, I _think_ the old procfs files
+require that the file offset be equal to the resource's base address when
+mmapping.
+
+I think what we want here is for pci_start to be 0 when mmap_api ==
+PCI_MMAP_PROCFS. The following patch makes that change, after which the Matrox
+and Mach64 X drivers work again.
+
+Acked-by: Martin Wilck <martin.wilck@ts.fujitsu.com>
+Signed-off-by: Darrick J. Wong <djwong@us.ibm.com>
+Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/pci/pci-sysfs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/pci/pci-sysfs.c
++++ b/drivers/pci/pci-sysfs.c
+@@ -672,7 +672,7 @@ int pci_mmap_fits(struct pci_dev *pdev,
+ nr = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+ start = vma->vm_pgoff;
+ size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1;
+- pci_start = (mmap_api == PCI_MMAP_SYSFS) ?
++ pci_start = (mmap_api == PCI_MMAP_PROCFS) ?
+ pci_resource_start(pdev, resno) >> PAGE_SHIFT : 0;
+ if (start >= pci_start && start < pci_start + size &&
+ start + nr <= pci_start + size)
--- /dev/null
+From 3b519e4ea618b6943a82931630872907f9ac2c2b Mon Sep 17 00:00:00 2001
+From: Martin Wilck <martin.wilck@ts.fujitsu.com>
+Date: Wed, 10 Nov 2010 11:03:21 +0100
+Subject: PCI: fix size checks for mmap() on /proc/bus/pci files
+
+From: Martin Wilck <martin.wilck@ts.fujitsu.com>
+
+commit 3b519e4ea618b6943a82931630872907f9ac2c2b upstream.
+
+The checks for valid mmaps of PCI resources made through /proc/bus/pci files
+that were introduced in 9eff02e2042f96fb2aedd02e032eca1c5333d767 have several
+problems:
+
+1. mmap() calls on /proc/bus/pci files are made with real file offsets > 0,
+whereas under /sys/bus/pci/devices, the start of the resource corresponds
+to offset 0. This may lead to false negatives in pci_mmap_fits(), which
+implicitly assumes the /sys/bus/pci/devices layout.
+
+2. The loop in proc_bus_pci_mmap doesn't skip empty resouces. This leads
+to false positives, because pci_mmap_fits() doesn't treat empty resources
+correctly (the calculated size is 1 << (8*sizeof(resource_size_t)-PAGE_SHIFT)
+in this case!).
+
+3. If a user maps resources with BAR > 0, pci_mmap_fits will emit bogus
+WARNINGS for the first resources that don't fit until the correct one is found.
+
+On many controllers the first 2-4 BARs are used, and the others are empty.
+In this case, an mmap attempt will first fail on the non-empty BARs
+(including the "right" BAR because of 1.) and emit bogus WARNINGS because
+of 3., and finally succeed on the first empty BAR because of 2.
+This is certainly not the intended behaviour.
+
+This patch addresses all 3 issues.
+Updated with an enum type for the additional parameter for pci_mmap_fits().
+
+Signed-off-by: Martin Wilck <martin.wilck@ts.fujitsu.com>
+Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/pci/pci-sysfs.c | 22 ++++++++++++++++------
+ drivers/pci/pci.h | 7 ++++++-
+ drivers/pci/proc.c | 2 +-
+ 3 files changed, 23 insertions(+), 8 deletions(-)
+
+--- a/drivers/pci/pci-sysfs.c
++++ b/drivers/pci/pci-sysfs.c
+@@ -662,17 +662,21 @@ void pci_remove_legacy_files(struct pci_
+
+ #ifdef HAVE_PCI_MMAP
+
+-int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma)
++int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma,
++ enum pci_mmap_api mmap_api)
+ {
+- unsigned long nr, start, size;
++ unsigned long nr, start, size, pci_start;
+
++ if (pci_resource_len(pdev, resno) == 0)
++ return 0;
+ nr = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+ start = vma->vm_pgoff;
+ size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1;
+- if (start < size && size - start >= nr)
++ pci_start = (mmap_api == PCI_MMAP_SYSFS) ?
++ pci_resource_start(pdev, resno) >> PAGE_SHIFT : 0;
++ if (start >= pci_start && start < pci_start + size &&
++ start + nr <= pci_start + size)
+ return 1;
+- WARN(1, "process \"%s\" tried to map 0x%08lx-0x%08lx on %s BAR %d (size 0x%08lx)\n",
+- current->comm, start, start+nr, pci_name(pdev), resno, size);
+ return 0;
+ }
+
+@@ -702,8 +706,14 @@ pci_mmap_resource(struct kobject *kobj,
+ if (i >= PCI_ROM_RESOURCE)
+ return -ENODEV;
+
+- if (!pci_mmap_fits(pdev, i, vma))
++ if (!pci_mmap_fits(pdev, i, vma, PCI_MMAP_SYSFS)) {
++ WARN(1, "process \"%s\" tried to map 0x%08lx bytes "
++ "at page 0x%08lx on %s BAR %d (start 0x%16Lx, size 0x%16Lx)\n",
++ current->comm, vma->vm_end-vma->vm_start, vma->vm_pgoff,
++ pci_name(pdev), i,
++ pci_resource_start(pdev, i), pci_resource_len(pdev, i));
+ return -EINVAL;
++ }
+
+ /* pci_mmap_page_range() expects the same kind of entry as coming
+ * from /proc/bus/pci/ which is a "user visible" value. If this is
+--- a/drivers/pci/pci.h
++++ b/drivers/pci/pci.h
+@@ -13,8 +13,13 @@ extern int pci_create_sysfs_dev_files(st
+ extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
+ extern void pci_cleanup_rom(struct pci_dev *dev);
+ #ifdef HAVE_PCI_MMAP
++enum pci_mmap_api {
++ PCI_MMAP_SYSFS, /* mmap on /sys/bus/pci/devices/<BDF>/resource<N> */
++ PCI_MMAP_PROCFS /* mmap on /proc/bus/pci/<BDF> */
++};
+ extern int pci_mmap_fits(struct pci_dev *pdev, int resno,
+- struct vm_area_struct *vma);
++ struct vm_area_struct *vmai,
++ enum pci_mmap_api mmap_api);
+ #endif
+ int pci_probe_reset_function(struct pci_dev *dev);
+
+--- a/drivers/pci/proc.c
++++ b/drivers/pci/proc.c
+@@ -259,7 +259,7 @@ static int proc_bus_pci_mmap(struct file
+
+ /* Make sure the caller is mapping a real resource for this device */
+ for (i = 0; i < PCI_ROM_RESOURCE; i++) {
+- if (pci_mmap_fits(dev, i, vma))
++ if (pci_mmap_fits(dev, i, vma, PCI_MMAP_PROCFS))
+ break;
+ }
+
mm-vfs-revalidate-page-mapping-in-do_generic_file_read.patch
bio-take-care-not-overflow-page-count-when-mapping-copying-user-data.patch
drm-ttm-clear-the-ghost-cpu_writers-flag-on-ttm_buffer_object_transfer.patch
+libata-scsi-passthru-fix-bug-which-truncated-lba48-return-values.patch
+libata-fix-null-sdev-dereference-race-in-atapi_qc_complete.patch
+pci-fix-size-checks-for-mmap-on-proc-bus-pci-files.patch
+pci-fix-offset-check-for-sysfs-mmapped-files.patch
+efifb-check-that-the-base-address-is-plausible-on-pci-systems.patch