--- /dev/null
+From 72585d2428fa3a0daab02ebad1f41e5ef517dbaa Mon Sep 17 00:00:00 2001
+From: Philipp Reisner <philipp.reisner@linbit.com>
+Date: Thu, 23 Feb 2012 12:56:26 +0100
+Subject: drbd: add missing part_round_stats to _drbd_start_io_acct
+
+From: Philipp Reisner <philipp.reisner@linbit.com>
+
+commit 72585d2428fa3a0daab02ebad1f41e5ef517dbaa upstream.
+
+Without this, iostat frequently sees bogus svctime and >= 100% "utilization".
+
+Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
+Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
+Cc: Raoul Bhatia <raoul@bhatia.at>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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);
--- /dev/null
+From 66bea92c69477a75a5d37b9bfed5773c92a3c4b4 Mon Sep 17 00:00:00 2001
+From: Eric Sandeen <sandeen@redhat.com>
+Date: Wed, 14 Nov 2012 22:22:05 -0500
+Subject: ext4: init pagevec in ext4_da_block_invalidatepages
+
+From: Eric Sandeen <sandeen@redhat.com>
+
+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 <lczerner@redhat.com>
+Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
+Signed-off-by: Eric Sandeen <sandeen@redhat.com>
+Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
+Signed-off-by: CAI Qian <caiqian@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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)
--- /dev/null
+From ea2447f700cab264019b52e2b417d689e052dcfd Mon Sep 17 00:00:00 2001
+From: Tom Mingarelli <thomas.mingarelli@hp.com>
+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 <thomas.mingarelli@hp.com>
+
+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 <thomas.mingarelli@hp.com>
+Tested-by: Shuah Khan <shuah.khan@hp.com>
+Reviewed-by: Donald Dutile <ddutile@redhat.com>
+Reviewed-by: Alex Williamson <alex.williamson@redhat.com>
+Signed-off-by: Joerg Roedel <joro@8bytes.org>
+Signed-off-by: CAI Qian <caiqian@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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;
+
--- /dev/null
+From shuah.khan@hp.com Fri Jan 18 13:21:04 2013
+From: Shuah Khan <shuah.khan@hp.com>
+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 <shuah.khan@hp.com>
+
+[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 <shuah.khan@hp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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;
+
--- /dev/null
+From ed4f20943cd4c7b55105c04daedf8d63ab6d499c Mon Sep 17 00:00:00 2001
+From: Heiko Carstens <heiko.carstens@de.ibm.com>
+Date: Mon, 14 Jan 2013 16:55:55 +0100
+Subject: s390/time: fix sched_clock() overflow
+
+From: Heiko Carstens <heiko.carstens@de.ibm.com>
+
+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 <schwidefsky@de.ibm.com>
+Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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);
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
--- /dev/null
+From 36caff5d795429c572443894e8789c2150dd796b Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Wed, 7 Nov 2012 10:31:30 -0500
+Subject: USB: fix endpoint-disabling for failed config changes
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+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 <stern@rowland.harvard.edu>
+Reported-and-tested-by: Matthias Schniedermeyer <ms@citd.de>
+CC: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: CAI Qian <caiqian@redhat.com>
+
+---
+ 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);
--- /dev/null
+From a9acc5365dbda29f7be2884efb63771dc24bd815 Mon Sep 17 00:00:00 2001
+From: Jesse Barnes <jbarnes@virtuousgeek.org>
+Date: Wed, 14 Nov 2012 20:43:31 +0000
+Subject: x86/Sandy Bridge: reserve pages when integrated graphics is present
+
+From: Jesse Barnes <jbarnes@virtuousgeek.org>
+
+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 <jbarnes@virtuousgeek.org>
+Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
+Cc: CAI Qian <caiqian@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 */
--- /dev/null
+From 68e5254adb88bede68285f11fb442a4d34fb550c Mon Sep 17 00:00:00 2001
+From: Julius Werner <jwerner@chromium.org>
+Date: Thu, 1 Nov 2012 12:47:59 -0700
+Subject: xhci: fix null-pointer dereference when destroying half-built
+ segment rings
+
+From: Julius Werner <jwerner@chromium.org>
+
+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 <jwerner@chromium.org>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Julius Werner <jwerner@chromium.org>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+[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 <ben@decadent.org.uk>
+Signed-off-by: CAI Qian <caiqian@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ 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;
+ }
+