From: Greg Kroah-Hartman Date: Fri, 18 Jan 2013 22:01:35 +0000 (-0800) Subject: 3.0-stable patches X-Git-Tag: v3.0.60~8 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e60d23ec7da6746ea35b203cebdf11c1498f5d19;p=thirdparty%2Fkernel%2Fstable-queue.git 3.0-stable patches added patches: drbd-add-missing-part_round_stats-to-_drbd_start_io_acct.patch ext4-init-pagevec-in-ext4_da_block_invalidatepages.patch intel-iommu-prevent-devices-with-rmrrs-from-being-placed.patch powerpc-fix-wii_memory_fixups-compile-error-on-3.0.y-tree.patch s390-time-fix-sched_clock-overflow.patch usb-fix-endpoint-disabling-for-failed-config-changes.patch x86-sandy-bridge-reserve-pages-when-integrated-graphics-is-present.patch xhci-fix-null-pointer-dereference-when-destroying-half-built.patch --- diff --git a/queue-3.0/drbd-add-missing-part_round_stats-to-_drbd_start_io_acct.patch b/queue-3.0/drbd-add-missing-part_round_stats-to-_drbd_start_io_acct.patch new file mode 100644 index 00000000000..dce9bd68a86 --- /dev/null +++ b/queue-3.0/drbd-add-missing-part_round_stats-to-_drbd_start_io_acct.patch @@ -0,0 +1,30 @@ +From 72585d2428fa3a0daab02ebad1f41e5ef517dbaa Mon Sep 17 00:00:00 2001 +From: Philipp Reisner +Date: Thu, 23 Feb 2012 12:56:26 +0100 +Subject: drbd: add missing part_round_stats to _drbd_start_io_acct + +From: Philipp Reisner + +commit 72585d2428fa3a0daab02ebad1f41e5ef517dbaa upstream. + +Without this, iostat frequently sees bogus svctime and >= 100% "utilization". + +Signed-off-by: Philipp Reisner +Signed-off-by: Lars Ellenberg +Cc: Raoul Bhatia +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/drbd/drbd_req.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/block/drbd/drbd_req.c ++++ b/drivers/block/drbd/drbd_req.c +@@ -37,6 +37,7 @@ static void _drbd_start_io_acct(struct d + const int rw = bio_data_dir(bio); + int cpu; + cpu = part_stat_lock(); ++ part_round_stats(cpu, &mdev->vdisk->part0); + part_stat_inc(cpu, &mdev->vdisk->part0, ios[rw]); + part_stat_add(cpu, &mdev->vdisk->part0, sectors[rw], bio_sectors(bio)); + part_inc_in_flight(&mdev->vdisk->part0, rw); diff --git a/queue-3.0/ext4-init-pagevec-in-ext4_da_block_invalidatepages.patch b/queue-3.0/ext4-init-pagevec-in-ext4_da_block_invalidatepages.patch new file mode 100644 index 00000000000..ff0e76025ec --- /dev/null +++ b/queue-3.0/ext4-init-pagevec-in-ext4_da_block_invalidatepages.patch @@ -0,0 +1,38 @@ +From 66bea92c69477a75a5d37b9bfed5773c92a3c4b4 Mon Sep 17 00:00:00 2001 +From: Eric Sandeen +Date: Wed, 14 Nov 2012 22:22:05 -0500 +Subject: ext4: init pagevec in ext4_da_block_invalidatepages + +From: Eric Sandeen + +commit 66bea92c69477a75a5d37b9bfed5773c92a3c4b4 upstream. + +ext4_da_block_invalidatepages is missing a pagevec_init(), +which means that pvec->cold contains random garbage. + +This affects whether the page goes to the front or +back of the LRU when ->cold makes it to +free_hot_cold_page() + +Reviewed-by: Lukas Czerner +Reviewed-by: Carlos Maiolino +Signed-off-by: Eric Sandeen +Signed-off-by: "Theodore Ts'o" +Signed-off-by: CAI Qian +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/inode.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -2199,6 +2199,8 @@ static void ext4_da_block_invalidatepage + + index = mpd->first_page; + end = mpd->next_page - 1; ++ ++ pagevec_init(&pvec, 0); + while (index <= end) { + nr_pages = pagevec_lookup(&pvec, mapping, index, PAGEVEC_SIZE); + if (nr_pages == 0) diff --git a/queue-3.0/intel-iommu-prevent-devices-with-rmrrs-from-being-placed.patch b/queue-3.0/intel-iommu-prevent-devices-with-rmrrs-from-being-placed.patch new file mode 100644 index 00000000000..e60f21c1880 --- /dev/null +++ b/queue-3.0/intel-iommu-prevent-devices-with-rmrrs-from-being-placed.patch @@ -0,0 +1,68 @@ +From ea2447f700cab264019b52e2b417d689e052dcfd Mon Sep 17 00:00:00 2001 +From: Tom Mingarelli +Date: Tue, 20 Nov 2012 19:43:17 +0000 +Subject: intel-iommu: Prevent devices with RMRRs from being placed + into SI Domain + +From: Tom Mingarelli + +commit ea2447f700cab264019b52e2b417d689e052dcfd upstream. + +This patch is to prevent non-USB devices that have RMRRs associated with them from +being placed into the SI Domain during init. This fixes the issue where the RMRR info +for devices being placed in and out of the SI Domain gets lost. + +Signed-off-by: Thomas Mingarelli +Tested-by: Shuah Khan +Reviewed-by: Donald Dutile +Reviewed-by: Alex Williamson +Signed-off-by: Joerg Roedel +Signed-off-by: CAI Qian +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/intel-iommu.c | 31 +++++++++++++++++++++++++++++++ + 1 file changed, 31 insertions(+) + +--- a/drivers/pci/intel-iommu.c ++++ b/drivers/pci/intel-iommu.c +@@ -2289,8 +2289,39 @@ static int domain_add_dev_info(struct dm + return 0; + } + ++static bool device_has_rmrr(struct pci_dev *dev) ++{ ++ struct dmar_rmrr_unit *rmrr; ++ int i; ++ ++ for_each_rmrr_units(rmrr) { ++ for (i = 0; i < rmrr->devices_cnt; i++) { ++ /* ++ * Return TRUE if this RMRR contains the device that ++ * is passed in. ++ */ ++ if (rmrr->devices[i] == dev) ++ return true; ++ } ++ } ++ return false; ++} ++ + static int iommu_should_identity_map(struct pci_dev *pdev, int startup) + { ++ ++ /* ++ * We want to prevent any device associated with an RMRR from ++ * getting placed into the SI Domain. This is done because ++ * problems exist when devices are moved in and out of domains ++ * and their respective RMRR info is lost. We exempt USB devices ++ * from this process due to their usage of RMRRs that are known ++ * to not be needed after BIOS hand-off to OS. ++ */ ++ if (device_has_rmrr(pdev) && ++ (pdev->class >> 8) != PCI_CLASS_SERIAL_USB) ++ return 0; ++ + if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev)) + return 1; + diff --git a/queue-3.0/powerpc-fix-wii_memory_fixups-compile-error-on-3.0.y-tree.patch b/queue-3.0/powerpc-fix-wii_memory_fixups-compile-error-on-3.0.y-tree.patch new file mode 100644 index 00000000000..a582adf0588 --- /dev/null +++ b/queue-3.0/powerpc-fix-wii_memory_fixups-compile-error-on-3.0.y-tree.patch @@ -0,0 +1,46 @@ +From shuah.khan@hp.com Fri Jan 18 13:21:04 2013 +From: Shuah Khan +Date: Wed, 12 Dec 2012 16:27:51 -0700 +Subject: powerpc: fix wii_memory_fixups() compile error on 3.0.y tree +Message-ID: <1355354871.2722.38.camel@lorien2> + +From: Shuah Khan + +[not upstream as the code involved was removed in the 3.3.0 release] + +Fix wii_memory_fixups() the following compile error on 3.0.y tree with +wii_defconfig on 3.0.y tree. + + CC arch/powerpc/platforms/embedded6xx/wii.o +arch/powerpc/platforms/embedded6xx/wii.c: In function ‘wii_memory_fixups’: +arch/powerpc/platforms/embedded6xx/wii.c:88:2: error: format ‘%llx’ expects argument of type ‘long long unsigned int’, but argument 2 has type ‘phys_addr_t’ [-Werror=format] +arch/powerpc/platforms/embedded6xx/wii.c:88:2: error: format ‘%llx’ expects argument of type ‘long long unsigned int’, but argument 3 has type ‘phys_addr_t’ [-Werror=format] +arch/powerpc/platforms/embedded6xx/wii.c:90:2: error: format ‘%llx’ expects argument of type ‘long long unsigned int’, but argument 2 has type ‘phys_addr_t’ [-Werror=format] +arch/powerpc/platforms/embedded6xx/wii.c:90:2: error: format ‘%llx’ expects argument of type ‘long long unsigned int’, but argument 3 has type ‘phys_addr_t’ [-Werror=format] +cc1: all warnings being treated as errors +make[2]: *** [arch/powerpc/platforms/embedded6xx/wii.o] Error 1 +make[1]: *** [arch/powerpc/platforms/embedded6xx] Error 2 +make: *** [arch/powerpc/platforms] Error 2 + +Signed-off-by: Shuah Khan +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/platforms/embedded6xx/wii.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/arch/powerpc/platforms/embedded6xx/wii.c ++++ b/arch/powerpc/platforms/embedded6xx/wii.c +@@ -85,9 +85,11 @@ void __init wii_memory_fixups(void) + wii_hole_start = p[0].base + p[0].size; + wii_hole_size = p[1].base - wii_hole_start; + +- pr_info("MEM1: <%08llx %08llx>\n", p[0].base, p[0].size); ++ pr_info("MEM1: <%08llx %08llx>\n", ++ (unsigned long long) p[0].base, (unsigned long long) p[0].size); + pr_info("HOLE: <%08lx %08lx>\n", wii_hole_start, wii_hole_size); +- pr_info("MEM2: <%08llx %08llx>\n", p[1].base, p[1].size); ++ pr_info("MEM2: <%08llx %08llx>\n", ++ (unsigned long long) p[1].base, (unsigned long long) p[1].size); + + p[0].size += wii_hole_size + p[1].size; + diff --git a/queue-3.0/s390-time-fix-sched_clock-overflow.patch b/queue-3.0/s390-time-fix-sched_clock-overflow.patch new file mode 100644 index 00000000000..6256083fedd --- /dev/null +++ b/queue-3.0/s390-time-fix-sched_clock-overflow.patch @@ -0,0 +1,89 @@ +From ed4f20943cd4c7b55105c04daedf8d63ab6d499c Mon Sep 17 00:00:00 2001 +From: Heiko Carstens +Date: Mon, 14 Jan 2013 16:55:55 +0100 +Subject: s390/time: fix sched_clock() overflow + +From: Heiko Carstens + +commit ed4f20943cd4c7b55105c04daedf8d63ab6d499c upstream. + +Converting a 64 Bit TOD format value to nanoseconds means that the value +must be divided by 4.096. In order to achieve that we multiply with 125 +and divide by 512. +When used within sched_clock() this triggers an overflow after appr. +417 days. Resulting in a sched_clock() return value that is much smaller +than previously and therefore may cause all sort of weird things in +subsystems that rely on a monotonic sched_clock() behaviour. + +To fix this implement a tod_to_ns() helper function which converts TOD +values without overflow and call this function from both places that +open coded the conversion: sched_clock() and kvm_s390_handle_wait(). + +Reviewed-by: Martin Schwidefsky +Signed-off-by: Heiko Carstens +Signed-off-by: Martin Schwidefsky +Signed-off-by: Greg Kroah-Hartman + +--- + arch/s390/include/asm/timex.h | 28 ++++++++++++++++++++++++++++ + arch/s390/kernel/time.c | 2 +- + arch/s390/kvm/interrupt.c | 2 +- + 3 files changed, 30 insertions(+), 2 deletions(-) + +--- a/arch/s390/include/asm/timex.h ++++ b/arch/s390/include/asm/timex.h +@@ -126,4 +126,32 @@ static inline unsigned long long get_clo + return get_clock_xt() - sched_clock_base_cc; + } + ++/** ++ * tod_to_ns - convert a TOD format value to nanoseconds ++ * @todval: to be converted TOD format value ++ * Returns: number of nanoseconds that correspond to the TOD format value ++ * ++ * Converting a 64 Bit TOD format value to nanoseconds means that the value ++ * must be divided by 4.096. In order to achieve that we multiply with 125 ++ * and divide by 512: ++ * ++ * ns = (todval * 125) >> 9; ++ * ++ * In order to avoid an overflow with the multiplication we can rewrite this. ++ * With a split todval == 2^32 * th + tl (th upper 32 bits, tl lower 32 bits) ++ * we end up with ++ * ++ * ns = ((2^32 * th + tl) * 125 ) >> 9; ++ * -> ns = (2^23 * th * 125) + ((tl * 125) >> 9); ++ * ++ */ ++static inline unsigned long long tod_to_ns(unsigned long long todval) ++{ ++ unsigned long long ns; ++ ++ ns = ((todval >> 32) << 23) * 125; ++ ns += ((todval & 0xffffffff) * 125) >> 9; ++ return ns; ++} ++ + #endif +--- a/arch/s390/kernel/time.c ++++ b/arch/s390/kernel/time.c +@@ -63,7 +63,7 @@ static DEFINE_PER_CPU(struct clock_event + */ + unsigned long long notrace __kprobes sched_clock(void) + { +- return (get_clock_monotonic() * 125) >> 9; ++ return tod_to_ns(get_clock_monotonic()); + } + + /* +--- a/arch/s390/kvm/interrupt.c ++++ b/arch/s390/kvm/interrupt.c +@@ -358,7 +358,7 @@ int kvm_s390_handle_wait(struct kvm_vcpu + return 0; + } + +- sltime = ((vcpu->arch.sie_block->ckc - now)*125)>>9; ++ sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now); + + hrtimer_start(&vcpu->arch.ckc_timer, ktime_set (0, sltime) , HRTIMER_MODE_REL); + VCPU_EVENT(vcpu, 5, "enabled wait via clock comparator: %llx ns", sltime); diff --git a/queue-3.0/series b/queue-3.0/series index bdfcb3e4a3d..4339f6df84b 100644 --- a/queue-3.0/series +++ b/queue-3.0/series @@ -1,3 +1,11 @@ sh-fix-fdpic-binary-loader.patch tcm_fc-do-not-indicate-retry-capability-to-initiators.patch tcm_fc-do-not-report-target-role-when-target-is-not-defined.patch +s390-time-fix-sched_clock-overflow.patch +x86-sandy-bridge-reserve-pages-when-integrated-graphics-is-present.patch +ext4-init-pagevec-in-ext4_da_block_invalidatepages.patch +powerpc-fix-wii_memory_fixups-compile-error-on-3.0.y-tree.patch +usb-fix-endpoint-disabling-for-failed-config-changes.patch +intel-iommu-prevent-devices-with-rmrrs-from-being-placed.patch +drbd-add-missing-part_round_stats-to-_drbd_start_io_acct.patch +xhci-fix-null-pointer-dereference-when-destroying-half-built.patch diff --git a/queue-3.0/usb-fix-endpoint-disabling-for-failed-config-changes.patch b/queue-3.0/usb-fix-endpoint-disabling-for-failed-config-changes.patch new file mode 100644 index 00000000000..3afd97f44c2 --- /dev/null +++ b/queue-3.0/usb-fix-endpoint-disabling-for-failed-config-changes.patch @@ -0,0 +1,104 @@ +From 36caff5d795429c572443894e8789c2150dd796b Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Wed, 7 Nov 2012 10:31:30 -0500 +Subject: USB: fix endpoint-disabling for failed config changes + +From: Alan Stern + +commit 36caff5d795429c572443894e8789c2150dd796b upstream. + +This patch (as1631) fixes a bug that shows up when a config change +fails for a device under an xHCI controller. The controller needs to +be told to disable the endpoints that have been enabled for the new +config. The existing code does this, but before storing the +information about which endpoints were enabled! As a result, any +second attempt to install the new config is doomed to fail because +xhci-hcd will refuse to enable an endpoint that is already enabled. + +The patch optimistically initializes the new endpoints' device +structures before asking the device to switch to the new config. If +the request fails then the endpoint information is already stored, so +we can use usb_hcd_alloc_bandwidth() to disable the endpoints with no +trouble. The rest of the error path is slightly more complex now; we +have to disable the new interfaces and call put_device() rather than +simply deallocating them. + +Signed-off-by: Alan Stern +Reported-and-tested-by: Matthias Schniedermeyer +CC: Sarah Sharp +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: CAI Qian + +--- + drivers/usb/core/message.c | 53 ++++++++++++++++++++++++++------------------- + 1 file changed, 31 insertions(+), 22 deletions(-) + +--- a/drivers/usb/core/message.c ++++ b/drivers/usb/core/message.c +@@ -1770,28 +1770,8 @@ free_interfaces: + goto free_interfaces; + } + +- ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), +- USB_REQ_SET_CONFIGURATION, 0, configuration, 0, +- NULL, 0, USB_CTRL_SET_TIMEOUT); +- if (ret < 0) { +- /* All the old state is gone, so what else can we do? +- * The device is probably useless now anyway. +- */ +- cp = NULL; +- } +- +- dev->actconfig = cp; +- if (!cp) { +- usb_set_device_state(dev, USB_STATE_ADDRESS); +- usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL); +- mutex_unlock(hcd->bandwidth_mutex); +- usb_autosuspend_device(dev); +- goto free_interfaces; +- } +- mutex_unlock(hcd->bandwidth_mutex); +- usb_set_device_state(dev, USB_STATE_CONFIGURED); +- +- /* Initialize the new interface structures and the ++ /* ++ * Initialize the new interface structures and the + * hc/hcd/usbcore interface/endpoint state. + */ + for (i = 0; i < nintf; ++i) { +@@ -1835,6 +1815,35 @@ free_interfaces: + } + kfree(new_interfaces); + ++ ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ++ USB_REQ_SET_CONFIGURATION, 0, configuration, 0, ++ NULL, 0, USB_CTRL_SET_TIMEOUT); ++ if (ret < 0 && cp) { ++ /* ++ * All the old state is gone, so what else can we do? ++ * The device is probably useless now anyway. ++ */ ++ usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL); ++ for (i = 0; i < nintf; ++i) { ++ usb_disable_interface(dev, cp->interface[i], true); ++ put_device(&cp->interface[i]->dev); ++ cp->interface[i] = NULL; ++ } ++ cp = NULL; ++ } ++ ++ dev->actconfig = cp; ++ mutex_unlock(hcd->bandwidth_mutex); ++ ++ if (!cp) { ++ usb_set_device_state(dev, USB_STATE_ADDRESS); ++ ++ /* Leave LPM disabled while the device is unconfigured. */ ++ usb_autosuspend_device(dev); ++ return ret; ++ } ++ usb_set_device_state(dev, USB_STATE_CONFIGURED); ++ + if (cp->string == NULL && + !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS)) + cp->string = usb_cache_string(dev, cp->desc.iConfiguration); diff --git a/queue-3.0/x86-sandy-bridge-reserve-pages-when-integrated-graphics-is-present.patch b/queue-3.0/x86-sandy-bridge-reserve-pages-when-integrated-graphics-is-present.patch new file mode 100644 index 00000000000..81f41502d72 --- /dev/null +++ b/queue-3.0/x86-sandy-bridge-reserve-pages-when-integrated-graphics-is-present.patch @@ -0,0 +1,132 @@ +From a9acc5365dbda29f7be2884efb63771dc24bd815 Mon Sep 17 00:00:00 2001 +From: Jesse Barnes +Date: Wed, 14 Nov 2012 20:43:31 +0000 +Subject: x86/Sandy Bridge: reserve pages when integrated graphics is present + +From: Jesse Barnes + +commit a9acc5365dbda29f7be2884efb63771dc24bd815 upstream. + +SNB graphics devices have a bug that prevent them from accessing certain +memory ranges, namely anything below 1M and in the pages listed in the +table. So reserve those at boot if set detect a SNB gfx device on the +CPU to avoid GPU hangs. + +Stephane Marchesin had a similar patch to the page allocator awhile +back, but rather than reserving pages up front, it leaked them at +allocation time. + +[ hpa: made a number of stylistic changes, marked arrays as static + const, and made less verbose; use "memblock=debug" for full + verbosity. ] + +Signed-off-by: Jesse Barnes +Signed-off-by: H. Peter Anvin +Cc: CAI Qian +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kernel/setup.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 78 insertions(+) + +--- a/arch/x86/kernel/setup.c ++++ b/arch/x86/kernel/setup.c +@@ -631,6 +631,81 @@ static __init void reserve_ibft_region(v + + static unsigned reserve_low = CONFIG_X86_RESERVE_LOW << 10; + ++static bool __init snb_gfx_workaround_needed(void) ++{ ++ int i; ++ u16 vendor, devid; ++ static const u16 snb_ids[] = { ++ 0x0102, ++ 0x0112, ++ 0x0122, ++ 0x0106, ++ 0x0116, ++ 0x0126, ++ 0x010a, ++ }; ++ ++ /* Assume no if something weird is going on with PCI */ ++ if (!early_pci_allowed()) ++ return false; ++ ++ vendor = read_pci_config_16(0, 2, 0, PCI_VENDOR_ID); ++ if (vendor != 0x8086) ++ return false; ++ ++ devid = read_pci_config_16(0, 2, 0, PCI_DEVICE_ID); ++ for (i = 0; i < ARRAY_SIZE(snb_ids); i++) ++ if (devid == snb_ids[i]) ++ return true; ++ ++ return false; ++} ++ ++/* ++ * Sandy Bridge graphics has trouble with certain ranges, exclude ++ * them from allocation. ++ */ ++static void __init trim_snb_memory(void) ++{ ++ static const unsigned long bad_pages[] = { ++ 0x20050000, ++ 0x20110000, ++ 0x20130000, ++ 0x20138000, ++ 0x40004000, ++ }; ++ int i; ++ ++ if (!snb_gfx_workaround_needed()) ++ return; ++ ++ printk(KERN_DEBUG "reserving inaccessible SNB gfx pages\n"); ++ ++ /* ++ * Reserve all memory below the 1 MB mark that has not ++ * already been reserved. ++ */ ++ memblock_reserve(0, 1<<20); ++ ++ for (i = 0; i < ARRAY_SIZE(bad_pages); i++) { ++ if (memblock_reserve(bad_pages[i], PAGE_SIZE)) ++ printk(KERN_WARNING "failed to reserve 0x%08lx\n", ++ bad_pages[i]); ++ } ++} ++ ++/* ++ * Here we put platform-specific memory range workarounds, i.e. ++ * memory known to be corrupt or otherwise in need to be reserved on ++ * specific platforms. ++ * ++ * If this gets used more widely it could use a real dispatch mechanism. ++ */ ++static void __init trim_platform_memory_ranges(void) ++{ ++ trim_snb_memory(); ++} ++ + static void __init trim_bios_range(void) + { + /* +@@ -651,6 +726,7 @@ static void __init trim_bios_range(void) + * take them out. + */ + e820_remove_range(BIOS_BEGIN, BIOS_END - BIOS_BEGIN, E820_RAM, 1); ++ + sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); + } + +@@ -929,6 +1005,8 @@ void __init setup_arch(char **cmdline_p) + + setup_trampolines(); + ++ trim_platform_memory_ranges(); ++ + init_gbpages(); + + /* max_pfn_mapped is updated here */ diff --git a/queue-3.0/xhci-fix-null-pointer-dereference-when-destroying-half-built.patch b/queue-3.0/xhci-fix-null-pointer-dereference-when-destroying-half-built.patch new file mode 100644 index 00000000000..117a2035e9c --- /dev/null +++ b/queue-3.0/xhci-fix-null-pointer-dereference-when-destroying-half-built.patch @@ -0,0 +1,77 @@ +From 68e5254adb88bede68285f11fb442a4d34fb550c Mon Sep 17 00:00:00 2001 +From: Julius Werner +Date: Thu, 1 Nov 2012 12:47:59 -0700 +Subject: xhci: fix null-pointer dereference when destroying half-built + segment rings + +From: Julius Werner + +commit 68e5254adb88bede68285f11fb442a4d34fb550c upstream. + +xhci_alloc_segments_for_ring() builds a list of xhci_segments and links +the tail to head at the end (forming a ring). When it bails out for OOM +reasons half-way through, it tries to destroy its half-built list with +xhci_free_segments_for_ring(), even though it is not a ring yet. This +causes a null-pointer dereference upon hitting the last element. + +Furthermore, one of its callers (xhci_ring_alloc()) mistakenly believes +the output parameters to be valid upon this kind of OOM failure, and +calls xhci_ring_free() on them. Since the (incomplete) list/ring should +already be destroyed in that case, this would lead to a use after free. + +This patch fixes those issues by having xhci_alloc_segments_for_ring() +destroy its half-built, non-circular list manually and destroying the +invalid struct xhci_ring in xhci_ring_alloc() with a plain kfree(). + +This patch should be backported to kernels as old as 2.6.31, that +contains the commit 0ebbab37422315a5d0cb29792271085bafdf38c0 "USB: xhci: +Ring allocation and initialization." + +A separate patch will need to be developed for kernels older than 3.4, +since the ring allocation code was refactored in that kernel. + +Signed-off-by: Julius Werner +Signed-off-by: Sarah Sharp +Signed-off-by: Julius Werner +Signed-off-by: Sarah Sharp +[bwh: Backported to 3.2: + - Adjust context + - Since segment allocation is done directly in xhci_ring_alloc(), walk + the list starting from ring->first_seg when freeing] +Signed-off-by: Ben Hutchings +Signed-off-by: CAI Qian +Signed-off-by: Greg Kroah-Hartman + + +--- + drivers/usb/host/xhci-mem.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -180,8 +180,15 @@ static struct xhci_ring *xhci_ring_alloc + struct xhci_segment *next; + + next = xhci_segment_alloc(xhci, flags); +- if (!next) ++ if (!next) { ++ prev = ring->first_seg; ++ while (prev) { ++ next = prev->next; ++ xhci_segment_free(xhci, prev); ++ prev = next; ++ } + goto fail; ++ } + xhci_link_segments(xhci, prev, next, link_trbs, isoc); + + prev = next; +@@ -201,7 +208,7 @@ static struct xhci_ring *xhci_ring_alloc + return ring; + + fail: +- xhci_ring_free(xhci, ring); ++ kfree(ring); + return NULL; + } +