From: Greg Kroah-Hartman Date: Wed, 4 Jun 2014 05:58:58 +0000 (-0700) Subject: 3.10-stable patches X-Git-Tag: v3.14.6~47 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=285b712fca9a99a7e4f4781720d80d5e2a10d86b;p=thirdparty%2Fkernel%2Fstable-queue.git 3.10-stable patches added patches: asoc-wm8962-update-register-class_d_control_1-to-be-non-volatile.patch iwlwifi-pcie-disable-interrupts-upon-pcie-alloc.patch metag-fix-memory-barriers.patch metag-reduce-maximum-stack-size-to-256mb.patch x86-64-modify_ldt-make-support-for-16-bit-segments-a-runtime-option.patch xen-blkfront-restore-the-non-persistent-data-path.patch xen-blkfront-revoke-foreign-access-for-grants-not-mapped-by-the-backend.patch --- diff --git a/queue-3.10/asoc-wm8962-update-register-class_d_control_1-to-be-non-volatile.patch b/queue-3.10/asoc-wm8962-update-register-class_d_control_1-to-be-non-volatile.patch new file mode 100644 index 00000000000..21c223dc815 --- /dev/null +++ b/queue-3.10/asoc-wm8962-update-register-class_d_control_1-to-be-non-volatile.patch @@ -0,0 +1,86 @@ +From 44330ab516c15dda8a1e660eeaf0003f84e43e3f Mon Sep 17 00:00:00 2001 +From: Charles Keepax +Date: Tue, 13 May 2014 13:45:15 +0100 +Subject: ASoC: wm8962: Update register CLASS_D_CONTROL_1 to be non-volatile + +From: Charles Keepax + +commit 44330ab516c15dda8a1e660eeaf0003f84e43e3f upstream. + +The register CLASS_D_CONTROL_1 is marked as volatile because it contains +a bit, DAC_MUTE, which is also mirrored in the ADC_DAC_CONTROL_1 +register. This causes problems for the "Speaker Switch" control, which +will report an error if the CODEC is suspended because it relies on a +volatile register. + +To resolve this issue mark CLASS_D_CONTROL_1 as non-volatile and +manually keep the register cache in sync by updating both bits when +changing the mute status. + +Reported-by: Shawn Guo +Signed-off-by: Charles Keepax +Tested-by: Shawn Guo +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/codecs/wm8962.c | 15 ++++++++++++--- + sound/soc/codecs/wm8962.h | 4 ++++ + 2 files changed, 16 insertions(+), 3 deletions(-) + +--- a/sound/soc/codecs/wm8962.c ++++ b/sound/soc/codecs/wm8962.c +@@ -153,6 +153,7 @@ static struct reg_default wm8962_reg[] = + { 40, 0x0000 }, /* R40 - SPKOUTL volume */ + { 41, 0x0000 }, /* R41 - SPKOUTR volume */ + ++ { 49, 0x0010 }, /* R49 - Class D Control 1 */ + { 51, 0x0003 }, /* R51 - Class D Control 2 */ + + { 56, 0x0506 }, /* R56 - Clocking 4 */ +@@ -794,7 +795,6 @@ static bool wm8962_volatile_register(str + case WM8962_ALC2: + case WM8962_THERMAL_SHUTDOWN_STATUS: + case WM8962_ADDITIONAL_CONTROL_4: +- case WM8962_CLASS_D_CONTROL_1: + case WM8962_DC_SERVO_6: + case WM8962_INTERRUPT_STATUS_1: + case WM8962_INTERRUPT_STATUS_2: +@@ -2901,13 +2901,22 @@ static int wm8962_set_fll(struct snd_soc + static int wm8962_mute(struct snd_soc_dai *dai, int mute) + { + struct snd_soc_codec *codec = dai->codec; +- int val; ++ int val, ret; + + if (mute) +- val = WM8962_DAC_MUTE; ++ val = WM8962_DAC_MUTE | WM8962_DAC_MUTE_ALT; + else + val = 0; + ++ /** ++ * The DAC mute bit is mirrored in two registers, update both to keep ++ * the register cache consistent. ++ */ ++ ret = snd_soc_update_bits(codec, WM8962_CLASS_D_CONTROL_1, ++ WM8962_DAC_MUTE_ALT, val); ++ if (ret < 0) ++ return ret; ++ + return snd_soc_update_bits(codec, WM8962_ADC_DAC_CONTROL_1, + WM8962_DAC_MUTE, val); + } +--- a/sound/soc/codecs/wm8962.h ++++ b/sound/soc/codecs/wm8962.h +@@ -1954,6 +1954,10 @@ + #define WM8962_SPKOUTL_ENA_MASK 0x0040 /* SPKOUTL_ENA */ + #define WM8962_SPKOUTL_ENA_SHIFT 6 /* SPKOUTL_ENA */ + #define WM8962_SPKOUTL_ENA_WIDTH 1 /* SPKOUTL_ENA */ ++#define WM8962_DAC_MUTE_ALT 0x0010 /* DAC_MUTE */ ++#define WM8962_DAC_MUTE_ALT_MASK 0x0010 /* DAC_MUTE */ ++#define WM8962_DAC_MUTE_ALT_SHIFT 4 /* DAC_MUTE */ ++#define WM8962_DAC_MUTE_ALT_WIDTH 1 /* DAC_MUTE */ + #define WM8962_SPKOUTL_PGA_MUTE 0x0002 /* SPKOUTL_PGA_MUTE */ + #define WM8962_SPKOUTL_PGA_MUTE_MASK 0x0002 /* SPKOUTL_PGA_MUTE */ + #define WM8962_SPKOUTL_PGA_MUTE_SHIFT 1 /* SPKOUTL_PGA_MUTE */ diff --git a/queue-3.10/iwlwifi-pcie-disable-interrupts-upon-pcie-alloc.patch b/queue-3.10/iwlwifi-pcie-disable-interrupts-upon-pcie-alloc.patch new file mode 100644 index 00000000000..19ae46b2bfd --- /dev/null +++ b/queue-3.10/iwlwifi-pcie-disable-interrupts-upon-pcie-alloc.patch @@ -0,0 +1,68 @@ +From 83f7a85f1134c6e914453f5747435415a23d516b Mon Sep 17 00:00:00 2001 +From: Emmanuel Grumbach +Date: Sun, 13 Apr 2014 16:03:11 +0300 +Subject: iwlwifi: pcie: disable interrupts upon PCIe alloc + +From: Emmanuel Grumbach + +commit 83f7a85f1134c6e914453f5747435415a23d516b upstream. + +In case RFKILL is in KILL position, the NIC will issue an +interrupt straight away. This interrupt won't be sent +because it is masked in the hardware. +But if our interrupt service routine is called for another +reason (SHARED_IRQ), then we'll look at the interrupt cause +and service it. This can cause bad things if we are not +ready yet. +Explicitly clean the interrupt cause register to make sure +we won't service anything before we are ready to. + +Reported-and-tested-by: Alexander Monakov +Reviewed-by: Johannes Berg +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/iwlwifi/pcie/trans.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/iwlwifi/pcie/trans.c ++++ b/drivers/net/wireless/iwlwifi/pcie/trans.c +@@ -1538,6 +1538,10 @@ struct iwl_trans *iwl_trans_pcie_alloc(s + * PCI Tx retries from interfering with C3 CPU state */ + pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); + ++ trans->dev = &pdev->dev; ++ trans_pcie->pci_dev = pdev; ++ iwl_disable_interrupts(trans); ++ + err = pci_enable_msi(pdev); + if (err) { + dev_err(&pdev->dev, "pci_enable_msi failed(0X%x)\n", err); +@@ -1549,8 +1553,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(s + } + } + +- trans->dev = &pdev->dev; +- trans_pcie->pci_dev = pdev; + trans->hw_rev = iwl_read32(trans, CSR_HW_REV); + trans->hw_id = (pdev->device << 16) + pdev->subsystem_device; + snprintf(trans->hw_id_str, sizeof(trans->hw_id_str), +@@ -1574,8 +1576,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(s + if (!trans->dev_cmd_pool) + goto out_pci_disable_msi; + +- trans_pcie->inta_mask = CSR_INI_SET_MASK; +- + if (iwl_pcie_alloc_ict(trans)) + goto out_free_cmd_pool; + +@@ -1586,6 +1586,8 @@ struct iwl_trans *iwl_trans_pcie_alloc(s + goto out_free_ict; + } + ++ trans_pcie->inta_mask = CSR_INI_SET_MASK; ++ + return trans; + + out_free_ict: diff --git a/queue-3.10/metag-fix-memory-barriers.patch b/queue-3.10/metag-fix-memory-barriers.patch new file mode 100644 index 00000000000..ef6796f693f --- /dev/null +++ b/queue-3.10/metag-fix-memory-barriers.patch @@ -0,0 +1,62 @@ +From 2425ce84026c385b73ae72039f90d042d49e0394 Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Thu, 8 May 2014 15:51:37 -0400 +Subject: metag: fix memory barriers + +From: Mikulas Patocka + +commit 2425ce84026c385b73ae72039f90d042d49e0394 upstream. + +Volatile access doesn't really imply the compiler barrier. Volatile access +is only ordered with respect to other volatile accesses, it isn't ordered +with respect to general memory accesses. Gcc may reorder memory accesses +around volatile access, as we can see in this simple example (if we +compile it with optimization, both increments of *b will be collapsed to +just one): + +void fn(volatile int *a, long *b) +{ + (*b)++; + *a = 10; + (*b)++; +} + +Consequently, we need the compiler barrier after a write to the volatile +variable, to make sure that the compiler doesn't reorder the volatile +write with something else. + +Signed-off-by: Mikulas Patocka +Acked-by: Peter Zijlstra +Signed-off-by: James Hogan +Signed-off-by: Greg Kroah-Hartman + +--- + arch/metag/include/asm/barrier.h | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/arch/metag/include/asm/barrier.h ++++ b/arch/metag/include/asm/barrier.h +@@ -15,6 +15,7 @@ static inline void wr_fence(void) + volatile int *flushptr = (volatile int *) LINSYSEVENT_WR_FENCE; + barrier(); + *flushptr = 0; ++ barrier(); + } + + #else /* CONFIG_METAG_META21 */ +@@ -35,6 +36,7 @@ static inline void wr_fence(void) + *flushptr = 0; + *flushptr = 0; + *flushptr = 0; ++ barrier(); + } + + #endif /* !CONFIG_METAG_META21 */ +@@ -68,6 +70,7 @@ static inline void fence(void) + volatile int *flushptr = (volatile int *) LINSYSEVENT_WR_ATOMIC_UNLOCK; + barrier(); + *flushptr = 0; ++ barrier(); + } + #define smp_mb() fence() + #define smp_rmb() fence() diff --git a/queue-3.10/metag-reduce-maximum-stack-size-to-256mb.patch b/queue-3.10/metag-reduce-maximum-stack-size-to-256mb.patch new file mode 100644 index 00000000000..3db91c76bbe --- /dev/null +++ b/queue-3.10/metag-reduce-maximum-stack-size-to-256mb.patch @@ -0,0 +1,74 @@ +From d71f290b4e98a39f49f2595a13be3b4d5ce8e1f1 Mon Sep 17 00:00:00 2001 +From: James Hogan +Date: Tue, 13 May 2014 23:58:24 +0100 +Subject: metag: Reduce maximum stack size to 256MB + +From: James Hogan + +commit d71f290b4e98a39f49f2595a13be3b4d5ce8e1f1 upstream. + +Specify the maximum stack size for arches where the stack grows upward +(parisc and metag) in asm/processor.h rather than hard coding in +fs/exec.c so that metag can specify a smaller value of 256MB rather than +1GB. + +This fixes a BUG on metag if the RLIMIT_STACK hard limit is increased +beyond a safe value by root. E.g. when starting a process after running +"ulimit -H -s unlimited" it will then attempt to use a stack size of the +maximum 1GB which is far too big for metag's limited user virtual +address space (stack_top is usually 0x3ffff000): + +BUG: failure at fs/exec.c:589/shift_arg_pages()! + +Signed-off-by: James Hogan +Cc: Helge Deller +Cc: "James E.J. Bottomley" +Cc: linux-parisc@vger.kernel.org +Cc: linux-metag@vger.kernel.org +Cc: John David Anglin +Signed-off-by: Greg Kroah-Hartman + +--- + arch/metag/include/asm/processor.h | 2 ++ + arch/parisc/include/asm/processor.h | 2 ++ + fs/exec.c | 6 +++--- + 3 files changed, 7 insertions(+), 3 deletions(-) + +--- a/arch/metag/include/asm/processor.h ++++ b/arch/metag/include/asm/processor.h +@@ -22,6 +22,8 @@ + /* Add an extra page of padding at the top of the stack for the guard page. */ + #define STACK_TOP (TASK_SIZE - PAGE_SIZE) + #define STACK_TOP_MAX STACK_TOP ++/* Maximum virtual space for stack */ ++#define STACK_SIZE_MAX (1 << 28) /* 256 MB */ + + /* This decides where the kernel will search for a free chunk of vm + * space during mmap's. +--- a/arch/parisc/include/asm/processor.h ++++ b/arch/parisc/include/asm/processor.h +@@ -53,6 +53,8 @@ + #define STACK_TOP TASK_SIZE + #define STACK_TOP_MAX DEFAULT_TASK_SIZE + ++#define STACK_SIZE_MAX (1 << 30) /* 1 GB */ ++ + #endif + + #ifndef __ASSEMBLY__ +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -654,10 +654,10 @@ int setup_arg_pages(struct linux_binprm + unsigned long rlim_stack; + + #ifdef CONFIG_STACK_GROWSUP +- /* Limit stack size to 1GB */ ++ /* Limit stack size */ + stack_base = rlimit_max(RLIMIT_STACK); +- if (stack_base > (1 << 30)) +- stack_base = 1 << 30; ++ if (stack_base > STACK_SIZE_MAX) ++ stack_base = STACK_SIZE_MAX; + + /* Make sure we didn't let the argument array grow too large. */ + if (vma->vm_end - vma->vm_start > stack_base) diff --git a/queue-3.10/series b/queue-3.10/series index 32746d1fb50..75c4d719a3f 100644 --- a/queue-3.10/series +++ b/queue-3.10/series @@ -76,3 +76,10 @@ workqueue-fix-a-possible-race-condition-between-rescuer-and-pwq-release.patch workqueue-make-rescuer_thread-empty-wq-maydays-list-before-exiting.patch bus-mvebu-mbus-allow-several-windows-with-the-same-target-attribute.patch percpu-make-pcpu_alloc_chunk-use-pcpu_mem_free-instead-of-kfree.patch +xen-blkfront-revoke-foreign-access-for-grants-not-mapped-by-the-backend.patch +xen-blkfront-restore-the-non-persistent-data-path.patch +iwlwifi-pcie-disable-interrupts-upon-pcie-alloc.patch +asoc-wm8962-update-register-class_d_control_1-to-be-non-volatile.patch +metag-fix-memory-barriers.patch +metag-reduce-maximum-stack-size-to-256mb.patch +x86-64-modify_ldt-make-support-for-16-bit-segments-a-runtime-option.patch diff --git a/queue-3.10/x86-64-modify_ldt-make-support-for-16-bit-segments-a-runtime-option.patch b/queue-3.10/x86-64-modify_ldt-make-support-for-16-bit-segments-a-runtime-option.patch new file mode 100644 index 00000000000..6f87acaa807 --- /dev/null +++ b/queue-3.10/x86-64-modify_ldt-make-support-for-16-bit-segments-a-runtime-option.patch @@ -0,0 +1,86 @@ +From fa81511bb0bbb2b1aace3695ce869da9762624ff Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Wed, 14 May 2014 16:33:54 -0700 +Subject: x86-64, modify_ldt: Make support for 16-bit segments a runtime option + +From: Linus Torvalds + +commit fa81511bb0bbb2b1aace3695ce869da9762624ff upstream. + +Checkin: + +b3b42ac2cbae x86-64, modify_ldt: Ban 16-bit segments on 64-bit kernels + +disabled 16-bit segments on 64-bit kernels due to an information +leak. However, it does seem that people are genuinely using Wine to +run old 16-bit Windows programs on Linux. + +A proper fix for this ("espfix64") is coming in the upcoming merge +window, but as a temporary fix, create a sysctl to allow the +administrator to re-enable support for 16-bit segments. + +It adds a "/proc/sys/abi/ldt16" sysctl that defaults to zero (off). If +you hit this issue and care about your old Windows program more than +you care about a kernel stack address information leak, you can do + + echo 1 > /proc/sys/abi/ldt16 + +as root (add it to your startup scripts), and you should be ok. + +The sysctl table is only added if you have COMPAT support enabled on +x86-64, but I assume anybody who runs old windows binaries very much +does that ;) + +Signed-off-by: H. Peter Anvin +Link: http://lkml.kernel.org/r/CA%2B55aFw9BPoD10U1LfHbOMpHWZkvJTkMcfCs9s3urPr1YyWBxw@mail.gmail.com +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kernel/ldt.c | 4 +++- + arch/x86/vdso/vdso32-setup.c | 8 ++++++++ + 2 files changed, 11 insertions(+), 1 deletion(-) + +--- a/arch/x86/kernel/ldt.c ++++ b/arch/x86/kernel/ldt.c +@@ -20,6 +20,8 @@ + #include + #include + ++int sysctl_ldt16 = 0; ++ + #ifdef CONFIG_SMP + static void flush_ldt(void *current_mm) + { +@@ -234,7 +236,7 @@ static int write_ldt(void __user *ptr, u + * IRET leaking the high bits of the kernel stack address. + */ + #ifdef CONFIG_X86_64 +- if (!ldt_info.seg_32bit) { ++ if (!ldt_info.seg_32bit && !sysctl_ldt16) { + error = -EINVAL; + goto out_unlock; + } +--- a/arch/x86/vdso/vdso32-setup.c ++++ b/arch/x86/vdso/vdso32-setup.c +@@ -41,6 +41,7 @@ enum { + #ifdef CONFIG_X86_64 + #define vdso_enabled sysctl_vsyscall32 + #define arch_setup_additional_pages syscall32_setup_pages ++extern int sysctl_ldt16; + #endif + + /* +@@ -379,6 +380,13 @@ static ctl_table abi_table2[] = { + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec ++ }, ++ { ++ .procname = "ldt16", ++ .data = &sysctl_ldt16, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = proc_dointvec + }, + {} + }; diff --git a/queue-3.10/xen-blkfront-restore-the-non-persistent-data-path.patch b/queue-3.10/xen-blkfront-restore-the-non-persistent-data-path.patch new file mode 100644 index 00000000000..ce774792131 --- /dev/null +++ b/queue-3.10/xen-blkfront-restore-the-non-persistent-data-path.patch @@ -0,0 +1,279 @@ +From bfe11d6de1c416cea4f3f0f35f864162063ce3fa Mon Sep 17 00:00:00 2001 +From: Roger Pau Monne +Date: Tue, 29 Oct 2013 18:31:14 +0100 +Subject: xen-blkfront: restore the non-persistent data path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Roger Pau Monne + +commit bfe11d6de1c416cea4f3f0f35f864162063ce3fa upstream. + +When persistent grants were added they were always used, even if the +backend doesn't have this feature (there's no harm in always using the +same set of pages). This restores the old data path when the backend +doesn't have persistent grants, removing the burden of doing a memcpy +when it is not actually needed. + +Signed-off-by: Roger Pau Monné +Reported-by: Felipe Franciosi +Cc: Felipe Franciosi +Cc: Konrad Rzeszutek Wilk +Cc: David Vrabel +Signed-off-by: Konrad Rzeszutek Wilk +[v2: Fix up whitespace issues] +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/xen-blkfront.c | 105 ++++++++++++++++++++++++++++++------------- + 1 file changed, 74 insertions(+), 31 deletions(-) + +--- a/drivers/block/xen-blkfront.c ++++ b/drivers/block/xen-blkfront.c +@@ -104,7 +104,7 @@ struct blkfront_info + struct work_struct work; + struct gnttab_free_callback callback; + struct blk_shadow shadow[BLK_RING_SIZE]; +- struct list_head persistent_gnts; ++ struct list_head grants; + unsigned int persistent_gnts_c; + unsigned long shadow_free; + unsigned int feature_flush; +@@ -175,15 +175,17 @@ static int fill_grant_buffer(struct blkf + if (!gnt_list_entry) + goto out_of_memory; + +- granted_page = alloc_page(GFP_NOIO); +- if (!granted_page) { +- kfree(gnt_list_entry); +- goto out_of_memory; ++ if (info->feature_persistent) { ++ granted_page = alloc_page(GFP_NOIO); ++ if (!granted_page) { ++ kfree(gnt_list_entry); ++ goto out_of_memory; ++ } ++ gnt_list_entry->pfn = page_to_pfn(granted_page); + } + +- gnt_list_entry->pfn = page_to_pfn(granted_page); + gnt_list_entry->gref = GRANT_INVALID_REF; +- list_add(&gnt_list_entry->node, &info->persistent_gnts); ++ list_add(&gnt_list_entry->node, &info->grants); + i++; + } + +@@ -191,9 +193,10 @@ static int fill_grant_buffer(struct blkf + + out_of_memory: + list_for_each_entry_safe(gnt_list_entry, n, +- &info->persistent_gnts, node) { ++ &info->grants, node) { + list_del(&gnt_list_entry->node); +- __free_page(pfn_to_page(gnt_list_entry->pfn)); ++ if (info->feature_persistent) ++ __free_page(pfn_to_page(gnt_list_entry->pfn)); + kfree(gnt_list_entry); + i--; + } +@@ -202,14 +205,14 @@ out_of_memory: + } + + static struct grant *get_grant(grant_ref_t *gref_head, ++ unsigned long pfn, + struct blkfront_info *info) + { + struct grant *gnt_list_entry; + unsigned long buffer_mfn; + +- BUG_ON(list_empty(&info->persistent_gnts)); +- gnt_list_entry = list_first_entry(&info->persistent_gnts, struct grant, +- node); ++ BUG_ON(list_empty(&info->grants)); ++ gnt_list_entry = list_first_entry(&info->grants, struct grant, node); + list_del(&gnt_list_entry->node); + + if (gnt_list_entry->gref != GRANT_INVALID_REF) { +@@ -220,6 +223,10 @@ static struct grant *get_grant(grant_ref + /* Assign a gref to this page */ + gnt_list_entry->gref = gnttab_claim_grant_reference(gref_head); + BUG_ON(gnt_list_entry->gref == -ENOSPC); ++ if (!info->feature_persistent) { ++ BUG_ON(!pfn); ++ gnt_list_entry->pfn = pfn; ++ } + buffer_mfn = pfn_to_mfn(gnt_list_entry->pfn); + gnttab_grant_foreign_access_ref(gnt_list_entry->gref, + info->xbdev->otherend_id, +@@ -430,12 +437,12 @@ static int blkif_queue_request(struct re + fsect = sg->offset >> 9; + lsect = fsect + (sg->length >> 9) - 1; + +- gnt_list_entry = get_grant(&gref_head, info); ++ gnt_list_entry = get_grant(&gref_head, page_to_pfn(sg_page(sg)), info); + ref = gnt_list_entry->gref; + + info->shadow[id].grants_used[i] = gnt_list_entry; + +- if (rq_data_dir(req)) { ++ if (rq_data_dir(req) && info->feature_persistent) { + char *bvec_data; + void *shared_data; + +@@ -828,16 +835,17 @@ static void blkif_free(struct blkfront_i + blk_stop_queue(info->rq); + + /* Remove all persistent grants */ +- if (!list_empty(&info->persistent_gnts)) { ++ if (!list_empty(&info->grants)) { + list_for_each_entry_safe(persistent_gnt, n, +- &info->persistent_gnts, node) { ++ &info->grants, node) { + list_del(&persistent_gnt->node); + if (persistent_gnt->gref != GRANT_INVALID_REF) { + gnttab_end_foreign_access(persistent_gnt->gref, + 0, 0UL); + info->persistent_gnts_c--; + } +- __free_page(pfn_to_page(persistent_gnt->pfn)); ++ if (info->feature_persistent) ++ __free_page(pfn_to_page(persistent_gnt->pfn)); + kfree(persistent_gnt); + } + } +@@ -874,7 +882,7 @@ static void blkif_completion(struct blk_ + + nseg = s->req.u.rw.nr_segments; + +- if (bret->operation == BLKIF_OP_READ) { ++ if (bret->operation == BLKIF_OP_READ && info->feature_persistent) { + /* + * Copy the data received from the backend into the bvec. + * Since bv_offset can be different than 0, and bv_len different +@@ -902,7 +910,10 @@ static void blkif_completion(struct blk_ + * we add it at the head of the list, so it will be + * reused first. + */ +- list_add(&s->grants_used[i]->node, &info->persistent_gnts); ++ if (!info->feature_persistent) ++ pr_alert_ratelimited("backed has not unmapped grant: %u\n", ++ s->grants_used[i]->gref); ++ list_add(&s->grants_used[i]->node, &info->grants); + info->persistent_gnts_c++; + } else { + /* +@@ -913,7 +924,7 @@ static void blkif_completion(struct blk_ + */ + gnttab_end_foreign_access(s->grants_used[i]->gref, 0, 0UL); + s->grants_used[i]->gref = GRANT_INVALID_REF; +- list_add_tail(&s->grants_used[i]->node, &info->persistent_gnts); ++ list_add_tail(&s->grants_used[i]->node, &info->grants); + } + } + } +@@ -1052,12 +1063,6 @@ static int setup_blkring(struct xenbus_d + for (i = 0; i < BLK_RING_SIZE; i++) + sg_init_table(info->shadow[i].sg, BLKIF_MAX_SEGMENTS_PER_REQUEST); + +- /* Allocate memory for grants */ +- err = fill_grant_buffer(info, BLK_RING_SIZE * +- BLKIF_MAX_SEGMENTS_PER_REQUEST); +- if (err) +- goto fail; +- + err = xenbus_grant_ring(dev, virt_to_mfn(info->ring.sring)); + if (err < 0) { + free_page((unsigned long)sring); +@@ -1216,7 +1221,7 @@ static int blkfront_probe(struct xenbus_ + spin_lock_init(&info->io_lock); + info->xbdev = dev; + info->vdevice = vdevice; +- INIT_LIST_HEAD(&info->persistent_gnts); ++ INIT_LIST_HEAD(&info->grants); + info->persistent_gnts_c = 0; + info->connected = BLKIF_STATE_DISCONNECTED; + INIT_WORK(&info->work, blkif_restart_queue); +@@ -1245,7 +1250,8 @@ static int blkif_recover(struct blkfront + int i; + struct blkif_request *req; + struct blk_shadow *copy; +- int j; ++ unsigned int persistent; ++ int j, rc; + + /* Stage 1: Make a safe copy of the shadow state. */ + copy = kmemdup(info->shadow, sizeof(info->shadow), +@@ -1260,6 +1266,24 @@ static int blkif_recover(struct blkfront + info->shadow_free = info->ring.req_prod_pvt; + info->shadow[BLK_RING_SIZE-1].req.u.rw.id = 0x0fffffff; + ++ /* Check if the backend supports persistent grants */ ++ rc = xenbus_gather(XBT_NIL, info->xbdev->otherend, ++ "feature-persistent", "%u", &persistent, ++ NULL); ++ if (rc) ++ info->feature_persistent = 0; ++ else ++ info->feature_persistent = persistent; ++ ++ /* Allocate memory for grants */ ++ rc = fill_grant_buffer(info, BLK_RING_SIZE * ++ BLKIF_MAX_SEGMENTS_PER_REQUEST); ++ if (rc) { ++ xenbus_dev_fatal(info->xbdev, rc, "setting grant buffer failed"); ++ kfree(copy); ++ return rc; ++ } ++ + /* Stage 3: Find pending requests and requeue them. */ + for (i = 0; i < BLK_RING_SIZE; i++) { + /* Not in use? */ +@@ -1324,8 +1348,12 @@ static int blkfront_resume(struct xenbus + blkif_free(info, info->connected == BLKIF_STATE_CONNECTED); + + err = talk_to_blkback(dev, info); +- if (info->connected == BLKIF_STATE_SUSPENDED && !err) +- err = blkif_recover(info); ++ ++ /* ++ * We have to wait for the backend to switch to ++ * connected state, since we want to read which ++ * features it supports. ++ */ + + return err; + } +@@ -1429,9 +1457,16 @@ static void blkfront_connect(struct blkf + sectors); + set_capacity(info->gd, sectors); + revalidate_disk(info->gd); ++ return; + +- /* fall through */ + case BLKIF_STATE_SUSPENDED: ++ /* ++ * If we are recovering from suspension, we need to wait ++ * for the backend to announce it's features before ++ * reconnecting, we need to know if the backend supports ++ * persistent grants. ++ */ ++ blkif_recover(info); + return; + + default: +@@ -1499,6 +1534,14 @@ static void blkfront_connect(struct blkf + else + info->feature_persistent = persistent; + ++ /* Allocate memory for grants */ ++ err = fill_grant_buffer(info, BLK_RING_SIZE * ++ BLKIF_MAX_SEGMENTS_PER_REQUEST); ++ if (err) { ++ xenbus_dev_fatal(info->xbdev, err, "setting grant buffer failed"); ++ return; ++ } ++ + err = xlvbd_alloc_gendisk(sectors, info, binfo, sector_size); + if (err) { + xenbus_dev_fatal(info->xbdev, err, "xlvbd_add at %s", diff --git a/queue-3.10/xen-blkfront-revoke-foreign-access-for-grants-not-mapped-by-the-backend.patch b/queue-3.10/xen-blkfront-revoke-foreign-access-for-grants-not-mapped-by-the-backend.patch new file mode 100644 index 00000000000..9fb3cfd77dc --- /dev/null +++ b/queue-3.10/xen-blkfront-revoke-foreign-access-for-grants-not-mapped-by-the-backend.patch @@ -0,0 +1,70 @@ +From fbe363c476afe8ec992d3baf682670a4bd1b6ce6 Mon Sep 17 00:00:00 2001 +From: Roger Pau Monne +Date: Mon, 12 Aug 2013 12:53:44 +0200 +Subject: xen-blkfront: revoke foreign access for grants not mapped by the backend +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Roger Pau Monne + +commit fbe363c476afe8ec992d3baf682670a4bd1b6ce6 upstream. + +There's no need to keep the foreign access in a grant if it is not +persistently mapped by the backend. This allows us to free grants that +are not mapped by the backend, thus preventing blkfront from hoarding +all grants. + +The main effect of this is that blkfront will only persistently map +the same grants as the backend, and it will always try to use grants +that are already mapped by the backend. Also the number of persistent +grants in blkfront is the same as in blkback (and is controlled by the +value in blkback). + +Signed-off-by: Roger Pau Monné +Reviewed-by: David Vrabel +Acked-by: Matt Wilson +Cc: Konrad Rzeszutek Wilk +Cc: David Vrabel +Signed-off-by: Konrad Rzeszutek Wilk +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + + +--- + drivers/block/xen-blkfront.c | 24 +++++++++++++++++++++--- + 1 file changed, 21 insertions(+), 3 deletions(-) + +--- a/drivers/block/xen-blkfront.c ++++ b/drivers/block/xen-blkfront.c +@@ -894,9 +894,27 @@ static void blkif_completion(struct blk_ + } + } + /* Add the persistent grant into the list of free grants */ +- for (i = 0; i < s->req.u.rw.nr_segments; i++) { +- list_add(&s->grants_used[i]->node, &info->persistent_gnts); +- info->persistent_gnts_c++; ++ for (i = 0; i < nseg; i++) { ++ if (gnttab_query_foreign_access(s->grants_used[i]->gref)) { ++ /* ++ * If the grant is still mapped by the backend (the ++ * backend has chosen to make this grant persistent) ++ * we add it at the head of the list, so it will be ++ * reused first. ++ */ ++ list_add(&s->grants_used[i]->node, &info->persistent_gnts); ++ info->persistent_gnts_c++; ++ } else { ++ /* ++ * If the grant is not mapped by the backend we end the ++ * foreign access and add it to the tail of the list, ++ * so it will not be picked again unless we run out of ++ * persistent grants. ++ */ ++ gnttab_end_foreign_access(s->grants_used[i]->gref, 0, 0UL); ++ s->grants_used[i]->gref = GRANT_INVALID_REF; ++ list_add_tail(&s->grants_used[i]->node, &info->persistent_gnts); ++ } + } + } +