Created
April 25, 2012 20:50
-
-
Save pfactum/2493253 to your computer and use it in GitHub Desktop.
diff
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/Makefile b/Makefile | |
index ea38990..fafc8d5 100644 | |
--- a/Makefile | |
+++ b/Makefile | |
@@ -1,6 +1,6 @@ | |
VERSION = 3 | |
PATCHLEVEL = 3 | |
-SUBLEVEL = 2 | |
+SUBLEVEL = 3 | |
EXTRAVERSION = -pf | |
NAME = Saber-toothed Squirrel | |
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S | |
index c5d6025..15bc187 100644 | |
--- a/arch/arm/boot/compressed/head.S | |
+++ b/arch/arm/boot/compressed/head.S | |
@@ -273,7 +273,7 @@ restart: adr r0, LC0 | |
add r0, r0, #0x100 | |
mov r1, r6 | |
sub r2, sp, r6 | |
- blne atags_to_fdt | |
+ bleq atags_to_fdt | |
ldmfd sp!, {r0-r3, ip, lr} | |
sub sp, sp, #0x10000 | |
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S | |
index f1c8486..c2e2b66 100644 | |
--- a/arch/arm/mm/proc-v7.S | |
+++ b/arch/arm/mm/proc-v7.S | |
@@ -255,6 +255,18 @@ __v7_setup: | |
mcr p15, 0, r5, c10, c2, 0 @ write PRRR | |
mcr p15, 0, r6, c10, c2, 1 @ write NMRR | |
#endif | |
+#ifndef CONFIG_ARM_THUMBEE | |
+ mrc p15, 0, r0, c0, c1, 0 @ read ID_PFR0 for ThumbEE | |
+ and r0, r0, #(0xf << 12) @ ThumbEE enabled field | |
+ teq r0, #(1 << 12) @ check if ThumbEE is present | |
+ bne 1f | |
+ mov r5, #0 | |
+ mcr p14, 6, r5, c1, c0, 0 @ Initialize TEEHBR to 0 | |
+ mrc p14, 6, r0, c0, c0, 0 @ load TEECR | |
+ orr r0, r0, #1 @ set the 1st bit in order to | |
+ mcr p14, 6, r0, c0, c0, 0 @ stop userspace TEEHBR access | |
+1: | |
+#endif | |
adr r5, v7_crval | |
ldmia r5, {r5, r6} | |
#ifdef CONFIG_CPU_ENDIAN_BE8 | |
diff --git a/arch/ia64/include/asm/futex.h b/arch/ia64/include/asm/futex.h | |
index 8428525..21ab376 100644 | |
--- a/arch/ia64/include/asm/futex.h | |
+++ b/arch/ia64/include/asm/futex.h | |
@@ -107,15 +107,16 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, | |
return -EFAULT; | |
{ | |
- register unsigned long r8 __asm ("r8") = 0; | |
+ register unsigned long r8 __asm ("r8"); | |
unsigned long prev; | |
__asm__ __volatile__( | |
" mf;; \n" | |
- " mov ar.ccv=%3;; \n" | |
- "[1:] cmpxchg4.acq %0=[%1],%2,ar.ccv \n" | |
+ " mov %0=r0 \n" | |
+ " mov ar.ccv=%4;; \n" | |
+ "[1:] cmpxchg4.acq %1=[%2],%3,ar.ccv \n" | |
" .xdata4 \"__ex_table\", 1b-., 2f-. \n" | |
"[2:]" | |
- : "=r" (prev) | |
+ : "=r" (r8), "=r" (prev) | |
: "r" (uaddr), "r" (newval), | |
"rO" ((long) (unsigned) oldval) | |
: "memory"); | |
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig | |
index 6d99a5f..d4f4d2e 100644 | |
--- a/arch/s390/Kconfig | |
+++ b/arch/s390/Kconfig | |
@@ -89,7 +89,6 @@ config S390 | |
select HAVE_KERNEL_XZ | |
select HAVE_ARCH_MUTEX_CPU_RELAX | |
select HAVE_ARCH_JUMP_LABEL if !MARCH_G5 | |
- select HAVE_RCU_TABLE_FREE if SMP | |
select ARCH_SAVE_PAGE_KEYS if HIBERNATION | |
select HAVE_MEMBLOCK | |
select HAVE_MEMBLOCK_NODE_MAP | |
diff --git a/arch/s390/include/asm/pgalloc.h b/arch/s390/include/asm/pgalloc.h | |
index 8eef9b5..78e3041 100644 | |
--- a/arch/s390/include/asm/pgalloc.h | |
+++ b/arch/s390/include/asm/pgalloc.h | |
@@ -22,10 +22,7 @@ void crst_table_free(struct mm_struct *, unsigned long *); | |
unsigned long *page_table_alloc(struct mm_struct *, unsigned long); | |
void page_table_free(struct mm_struct *, unsigned long *); | |
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE | |
void page_table_free_rcu(struct mmu_gather *, unsigned long *); | |
-void __tlb_remove_table(void *_table); | |
-#endif | |
static inline void clear_table(unsigned long *s, unsigned long val, size_t n) | |
{ | |
diff --git a/arch/s390/include/asm/tlb.h b/arch/s390/include/asm/tlb.h | |
index c687a2c..775a5ee 100644 | |
--- a/arch/s390/include/asm/tlb.h | |
+++ b/arch/s390/include/asm/tlb.h | |
@@ -30,14 +30,10 @@ | |
struct mmu_gather { | |
struct mm_struct *mm; | |
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE | |
struct mmu_table_batch *batch; | |
-#endif | |
unsigned int fullmm; | |
- unsigned int need_flush; | |
}; | |
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE | |
struct mmu_table_batch { | |
struct rcu_head rcu; | |
unsigned int nr; | |
@@ -49,7 +45,6 @@ struct mmu_table_batch { | |
extern void tlb_table_flush(struct mmu_gather *tlb); | |
extern void tlb_remove_table(struct mmu_gather *tlb, void *table); | |
-#endif | |
static inline void tlb_gather_mmu(struct mmu_gather *tlb, | |
struct mm_struct *mm, | |
@@ -57,29 +52,20 @@ static inline void tlb_gather_mmu(struct mmu_gather *tlb, | |
{ | |
tlb->mm = mm; | |
tlb->fullmm = full_mm_flush; | |
- tlb->need_flush = 0; | |
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE | |
tlb->batch = NULL; | |
-#endif | |
if (tlb->fullmm) | |
__tlb_flush_mm(mm); | |
} | |
static inline void tlb_flush_mmu(struct mmu_gather *tlb) | |
{ | |
- if (!tlb->need_flush) | |
- return; | |
- tlb->need_flush = 0; | |
- __tlb_flush_mm(tlb->mm); | |
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE | |
tlb_table_flush(tlb); | |
-#endif | |
} | |
static inline void tlb_finish_mmu(struct mmu_gather *tlb, | |
unsigned long start, unsigned long end) | |
{ | |
- tlb_flush_mmu(tlb); | |
+ tlb_table_flush(tlb); | |
} | |
/* | |
@@ -105,10 +91,8 @@ static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) | |
static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, | |
unsigned long address) | |
{ | |
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE | |
if (!tlb->fullmm) | |
return page_table_free_rcu(tlb, (unsigned long *) pte); | |
-#endif | |
page_table_free(tlb->mm, (unsigned long *) pte); | |
} | |
@@ -125,10 +109,8 @@ static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd, | |
#ifdef __s390x__ | |
if (tlb->mm->context.asce_limit <= (1UL << 31)) | |
return; | |
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE | |
if (!tlb->fullmm) | |
return tlb_remove_table(tlb, pmd); | |
-#endif | |
crst_table_free(tlb->mm, (unsigned long *) pmd); | |
#endif | |
} | |
@@ -146,10 +128,8 @@ static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud, | |
#ifdef __s390x__ | |
if (tlb->mm->context.asce_limit <= (1UL << 42)) | |
return; | |
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE | |
if (!tlb->fullmm) | |
return tlb_remove_table(tlb, pud); | |
-#endif | |
crst_table_free(tlb->mm, (unsigned long *) pud); | |
#endif | |
} | |
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c | |
index 51b0738..6dc115b 100644 | |
--- a/arch/s390/mm/pgtable.c | |
+++ b/arch/s390/mm/pgtable.c | |
@@ -679,8 +679,6 @@ void page_table_free(struct mm_struct *mm, unsigned long *table) | |
} | |
} | |
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE | |
- | |
static void __page_table_free_rcu(void *table, unsigned bit) | |
{ | |
struct page *page; | |
@@ -734,7 +732,66 @@ void __tlb_remove_table(void *_table) | |
free_pages((unsigned long) table, ALLOC_ORDER); | |
} | |
-#endif | |
+static void tlb_remove_table_smp_sync(void *arg) | |
+{ | |
+ /* Simply deliver the interrupt */ | |
+} | |
+ | |
+static void tlb_remove_table_one(void *table) | |
+{ | |
+ /* | |
+ * This isn't an RCU grace period and hence the page-tables cannot be | |
+ * assumed to be actually RCU-freed. | |
+ * | |
+ * It is however sufficient for software page-table walkers that rely | |
+ * on IRQ disabling. See the comment near struct mmu_table_batch. | |
+ */ | |
+ smp_call_function(tlb_remove_table_smp_sync, NULL, 1); | |
+ __tlb_remove_table(table); | |
+} | |
+ | |
+static void tlb_remove_table_rcu(struct rcu_head *head) | |
+{ | |
+ struct mmu_table_batch *batch; | |
+ int i; | |
+ | |
+ batch = container_of(head, struct mmu_table_batch, rcu); | |
+ | |
+ for (i = 0; i < batch->nr; i++) | |
+ __tlb_remove_table(batch->tables[i]); | |
+ | |
+ free_page((unsigned long)batch); | |
+} | |
+ | |
+void tlb_table_flush(struct mmu_gather *tlb) | |
+{ | |
+ struct mmu_table_batch **batch = &tlb->batch; | |
+ | |
+ if (*batch) { | |
+ __tlb_flush_mm(tlb->mm); | |
+ call_rcu_sched(&(*batch)->rcu, tlb_remove_table_rcu); | |
+ *batch = NULL; | |
+ } | |
+} | |
+ | |
+void tlb_remove_table(struct mmu_gather *tlb, void *table) | |
+{ | |
+ struct mmu_table_batch **batch = &tlb->batch; | |
+ | |
+ if (*batch == NULL) { | |
+ *batch = (struct mmu_table_batch *) | |
+ __get_free_page(GFP_NOWAIT | __GFP_NOWARN); | |
+ if (*batch == NULL) { | |
+ __tlb_flush_mm(tlb->mm); | |
+ tlb_remove_table_one(table); | |
+ return; | |
+ } | |
+ (*batch)->nr = 0; | |
+ } | |
+ (*batch)->tables[(*batch)->nr++] = table; | |
+ if ((*batch)->nr == MAX_TABLE_BATCH) | |
+ tlb_table_flush(tlb); | |
+} | |
/* | |
* switch on pgstes for its userspace process (for kvm) | |
diff --git a/arch/sparc/kernel/ds.c b/arch/sparc/kernel/ds.c | |
index 381edcd..27728e1 100644 | |
--- a/arch/sparc/kernel/ds.c | |
+++ b/arch/sparc/kernel/ds.c | |
@@ -1267,4 +1267,4 @@ static int __init ds_init(void) | |
return vio_register_driver(&ds_driver); | |
} | |
-subsys_initcall(ds_init); | |
+fs_initcall(ds_init); | |
diff --git a/arch/sparc/kernel/rtrap_64.S b/arch/sparc/kernel/rtrap_64.S | |
index 77f1b95..9171fc2 100644 | |
--- a/arch/sparc/kernel/rtrap_64.S | |
+++ b/arch/sparc/kernel/rtrap_64.S | |
@@ -20,11 +20,6 @@ | |
.text | |
.align 32 | |
-__handle_softirq: | |
- call do_softirq | |
- nop | |
- ba,a,pt %xcc, __handle_softirq_continue | |
- nop | |
__handle_preemption: | |
call schedule | |
wrpr %g0, RTRAP_PSTATE, %pstate | |
@@ -89,9 +84,7 @@ rtrap: | |
cmp %l1, 0 | |
/* mm/ultra.S:xcall_report_regs KNOWS about this load. */ | |
- bne,pn %icc, __handle_softirq | |
ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 | |
-__handle_softirq_continue: | |
rtrap_xcall: | |
sethi %hi(0xf << 20), %l4 | |
and %l1, %l4, %l4 | |
diff --git a/arch/x86/include/asm/cmpxchg.h b/arch/x86/include/asm/cmpxchg.h | |
index b3b7332..99480e5 100644 | |
--- a/arch/x86/include/asm/cmpxchg.h | |
+++ b/arch/x86/include/asm/cmpxchg.h | |
@@ -43,7 +43,7 @@ extern void __add_wrong_size(void) | |
switch (sizeof(*(ptr))) { \ | |
case __X86_CASE_B: \ | |
asm volatile (lock #op "b %b0, %1\n" \ | |
- : "+r" (__ret), "+m" (*(ptr)) \ | |
+ : "+q" (__ret), "+m" (*(ptr)) \ | |
: : "memory", "cc"); \ | |
break; \ | |
case __X86_CASE_W: \ | |
@@ -173,7 +173,7 @@ extern void __add_wrong_size(void) | |
switch (sizeof(*(ptr))) { \ | |
case __X86_CASE_B: \ | |
asm volatile (lock "addb %b1, %0\n" \ | |
- : "+m" (*(ptr)) : "ri" (inc) \ | |
+ : "+m" (*(ptr)) : "qi" (inc) \ | |
: "memory", "cc"); \ | |
break; \ | |
case __X86_CASE_W: \ | |
diff --git a/configs/dell-inspiron-1525.config b/configs/dell-inspiron-1525.config | |
index 6808399..94789e3 100644 | |
--- a/configs/dell-inspiron-1525.config | |
+++ b/configs/dell-inspiron-1525.config | |
@@ -1,6 +1,6 @@ | |
# | |
# Automatically generated file; DO NOT EDIT. | |
-# Linux/i386 3.3.1-pf Kernel Configuration | |
+# Linux/i386 3.3.3-pf Kernel Configuration | |
# | |
# CONFIG_64BIT is not set | |
CONFIG_X86_32=y | |
diff --git a/distro/archlinux/PKGBUILD b/distro/archlinux/PKGBUILD | |
index 5d2d287..d2a38d9 100644 | |
--- a/distro/archlinux/PKGBUILD | |
+++ b/distro/archlinux/PKGBUILD | |
@@ -1,6 +1,6 @@ | |
pkgname=kernel33-pf | |
-basekernel=3.3.2 | |
-pkgver=3.3.2 | |
+basekernel=3.3.3 | |
+pkgver=3.3.3 | |
pkgrel=pf | |
pkgdesc="The Linux Kernel and modules" | |
arch=('i686' 'x86_64') | |
diff --git a/distro/archlinux/kernel33.install b/distro/archlinux/kernel33.install | |
index 23f42bf..3b22c73 100644 | |
--- a/distro/archlinux/kernel33.install | |
+++ b/distro/archlinux/kernel33.install | |
@@ -1,4 +1,4 @@ | |
-KERNEL_VERSION="3.3.2" | |
+KERNEL_VERSION="3.3.3" | |
LOCAL_VERSION="-pf" | |
post_install () { | |
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c | |
index e820b68..acda773 100644 | |
--- a/drivers/block/cciss_scsi.c | |
+++ b/drivers/block/cciss_scsi.c | |
@@ -866,6 +866,7 @@ cciss_scsi_detect(ctlr_info_t *h) | |
sh->can_queue = cciss_tape_cmds; | |
sh->sg_tablesize = h->maxsgentries; | |
sh->max_cmd_len = MAX_COMMAND_SIZE; | |
+ sh->max_sectors = h->cciss_max_sectors; | |
((struct cciss_scsi_adapter_data_t *) | |
h->scsi_ctlr)->scsi_host = sh; | |
@@ -1410,7 +1411,7 @@ static void cciss_scatter_gather(ctlr_info_t *h, CommandList_struct *c, | |
/* track how many SG entries we are using */ | |
if (request_nsgs > h->maxSG) | |
h->maxSG = request_nsgs; | |
- c->Header.SGTotal = (__u8) request_nsgs + chained; | |
+ c->Header.SGTotal = (u16) request_nsgs + chained; | |
if (request_nsgs > h->max_cmd_sgentries) | |
c->Header.SGList = h->max_cmd_sgentries; | |
else | |
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c | |
index 4eca6e5..fa65913 100644 | |
--- a/drivers/bluetooth/ath3k.c | |
+++ b/drivers/bluetooth/ath3k.c | |
@@ -72,6 +72,8 @@ static struct usb_device_id ath3k_table[] = { | |
/* Atheros AR3012 with sflash firmware*/ | |
{ USB_DEVICE(0x0CF3, 0x3004) }, | |
+ { USB_DEVICE(0x0CF3, 0x311D) }, | |
+ { USB_DEVICE(0x13d3, 0x3375) }, | |
/* Atheros AR5BBU12 with sflash firmware */ | |
{ USB_DEVICE(0x0489, 0xE02C) }, | |
@@ -88,6 +90,8 @@ static struct usb_device_id ath3k_blist_tbl[] = { | |
/* Atheros AR3012 with sflash firmware*/ | |
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, | |
+ { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, | |
+ { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, | |
{ } /* Terminating entry */ | |
}; | |
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c | |
index 1f91da3..f8f83fe 100644 | |
--- a/drivers/bluetooth/btusb.c | |
+++ b/drivers/bluetooth/btusb.c | |
@@ -128,6 +128,8 @@ static struct usb_device_id blacklist_table[] = { | |
/* Atheros 3012 with sflash firmware */ | |
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, | |
+ { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, | |
+ { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, | |
/* Atheros AR5BBU12 with sflash firmware */ | |
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, | |
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c | |
index 0711448..5119c4b 100644 | |
--- a/drivers/bluetooth/hci_ldisc.c | |
+++ b/drivers/bluetooth/hci_ldisc.c | |
@@ -237,7 +237,6 @@ static void hci_uart_destruct(struct hci_dev *hdev) | |
return; | |
BT_DBG("%s", hdev->name); | |
- kfree(hdev->driver_data); | |
} | |
/* ------ LDISC part ------ */ | |
@@ -310,12 +309,13 @@ static void hci_uart_tty_close(struct tty_struct *tty) | |
hci_uart_close(hdev); | |
if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) { | |
- hu->proto->close(hu); | |
if (hdev) { | |
hci_unregister_dev(hdev); | |
hci_free_dev(hdev); | |
} | |
+ hu->proto->close(hu); | |
} | |
+ kfree(hu); | |
} | |
} | |
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c | |
index 5ee318c..84ecbb9 100644 | |
--- a/drivers/gpu/drm/i915/i915_drv.c | |
+++ b/drivers/gpu/drm/i915/i915_drv.c | |
@@ -64,7 +64,7 @@ MODULE_PARM_DESC(semaphores, | |
"Use semaphores for inter-ring sync (default: -1 (use per-chip defaults))"); | |
int i915_enable_rc6 __read_mostly = -1; | |
-module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600); | |
+module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0400); | |
MODULE_PARM_DESC(i915_enable_rc6, | |
"Enable power-saving render C-state 6 (default: -1 (use per-chip default)"); | |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c | |
index 94f860c..12eb789 100644 | |
--- a/drivers/gpu/drm/i915/intel_dp.c | |
+++ b/drivers/gpu/drm/i915/intel_dp.c | |
@@ -219,14 +219,38 @@ intel_dp_max_data_rate(int max_link_clock, int max_lanes) | |
return (max_link_clock * max_lanes * 8) / 10; | |
} | |
+static bool | |
+intel_dp_adjust_dithering(struct intel_dp *intel_dp, | |
+ struct drm_display_mode *mode, | |
+ struct drm_display_mode *adjusted_mode) | |
+{ | |
+ int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp)); | |
+ int max_lanes = intel_dp_max_lane_count(intel_dp); | |
+ int max_rate, mode_rate; | |
+ | |
+ mode_rate = intel_dp_link_required(mode->clock, 24); | |
+ max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes); | |
+ | |
+ if (mode_rate > max_rate) { | |
+ mode_rate = intel_dp_link_required(mode->clock, 18); | |
+ if (mode_rate > max_rate) | |
+ return false; | |
+ | |
+ if (adjusted_mode) | |
+ adjusted_mode->private_flags | |
+ |= INTEL_MODE_DP_FORCE_6BPC; | |
+ | |
+ return true; | |
+ } | |
+ | |
+ return true; | |
+} | |
+ | |
static int | |
intel_dp_mode_valid(struct drm_connector *connector, | |
struct drm_display_mode *mode) | |
{ | |
struct intel_dp *intel_dp = intel_attached_dp(connector); | |
- int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp)); | |
- int max_lanes = intel_dp_max_lane_count(intel_dp); | |
- int max_rate, mode_rate; | |
if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) { | |
if (mode->hdisplay > intel_dp->panel_fixed_mode->hdisplay) | |
@@ -236,16 +260,8 @@ intel_dp_mode_valid(struct drm_connector *connector, | |
return MODE_PANEL; | |
} | |
- mode_rate = intel_dp_link_required(mode->clock, 24); | |
- max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes); | |
- | |
- if (mode_rate > max_rate) { | |
- mode_rate = intel_dp_link_required(mode->clock, 18); | |
- if (mode_rate > max_rate) | |
- return MODE_CLOCK_HIGH; | |
- else | |
- mode->private_flags |= INTEL_MODE_DP_FORCE_6BPC; | |
- } | |
+ if (!intel_dp_adjust_dithering(intel_dp, mode, NULL)) | |
+ return MODE_CLOCK_HIGH; | |
if (mode->clock < 10000) | |
return MODE_CLOCK_LOW; | |
@@ -673,7 +689,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | |
int lane_count, clock; | |
int max_lane_count = intel_dp_max_lane_count(intel_dp); | |
int max_clock = intel_dp_max_link_bw(intel_dp) == DP_LINK_BW_2_7 ? 1 : 0; | |
- int bpp = mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24; | |
+ int bpp; | |
static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 }; | |
if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) { | |
@@ -687,6 +703,11 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | |
mode->clock = intel_dp->panel_fixed_mode->clock; | |
} | |
+ if (!intel_dp_adjust_dithering(intel_dp, mode, adjusted_mode)) | |
+ return false; | |
+ | |
+ bpp = adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24; | |
+ | |
for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { | |
for (clock = 0; clock <= max_clock; clock++) { | |
int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); | |
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c | |
index 12a04b9..2dea5aa 100644 | |
--- a/drivers/gpu/drm/i915/intel_fb.c | |
+++ b/drivers/gpu/drm/i915/intel_fb.c | |
@@ -283,6 +283,8 @@ void intel_fb_restore_mode(struct drm_device *dev) | |
struct drm_mode_config *config = &dev->mode_config; | |
struct drm_plane *plane; | |
+ mutex_lock(&dev->mode_config.mutex); | |
+ | |
ret = drm_fb_helper_restore_fbdev_mode(&dev_priv->fbdev->helper); | |
if (ret) | |
DRM_DEBUG("failed to restore crtc mode\n"); | |
@@ -290,4 +292,6 @@ void intel_fb_restore_mode(struct drm_device *dev) | |
/* Be sure to shut off any planes that may be active */ | |
list_for_each_entry(plane, &config->plane_list, head) | |
plane->funcs->disable_plane(plane); | |
+ | |
+ mutex_unlock(&dev->mode_config.mutex); | |
} | |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c | |
index 5361915..cbc3c04 100644 | |
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c | |
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |
@@ -1057,7 +1057,7 @@ int intel_init_ring_buffer(struct drm_device *dev, | |
* of the buffer. | |
*/ | |
ring->effective_size = ring->size; | |
- if (IS_I830(ring->dev)) | |
+ if (IS_I830(ring->dev) || IS_845G(ring->dev)) | |
ring->effective_size -= 128; | |
return 0; | |
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c | |
index a82b097..24a9231 100644 | |
--- a/drivers/gpu/drm/i915/intel_sprite.c | |
+++ b/drivers/gpu/drm/i915/intel_sprite.c | |
@@ -95,7 +95,6 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, | |
/* must disable */ | |
sprctl |= SPRITE_TRICKLE_FEED_DISABLE; | |
sprctl |= SPRITE_ENABLE; | |
- sprctl |= SPRITE_DEST_KEY; | |
/* Sizes are 0 based */ | |
src_w--; | |
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c | |
index 8ed806a..1dae0ea 100644 | |
--- a/drivers/gpu/drm/radeon/atombios_encoders.c | |
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c | |
@@ -230,6 +230,10 @@ atombios_dvo_setup(struct drm_encoder *encoder, int action) | |
if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) | |
return; | |
+ /* some R4xx chips have the wrong frev */ | |
+ if (rdev->family <= CHIP_RV410) | |
+ frev = 1; | |
+ | |
switch (frev) { | |
case 1: | |
switch (crev) { | |
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c | |
index d2e6144..afc40f4 100644 | |
--- a/drivers/gpu/drm/radeon/radeon_connectors.c | |
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |
@@ -946,7 +946,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) | |
encoder = obj_to_encoder(obj); | |
- if (encoder->encoder_type != DRM_MODE_ENCODER_DAC || | |
+ if (encoder->encoder_type != DRM_MODE_ENCODER_DAC && | |
encoder->encoder_type != DRM_MODE_ENCODER_TVDAC) | |
continue; | |
@@ -976,6 +976,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) | |
* cases the DVI port is actually a virtual KVM port connected to the service | |
* processor. | |
*/ | |
+out: | |
if ((!rdev->is_atom_bios) && | |
(ret == connector_status_disconnected) && | |
rdev->mode_info.bios_hardcoded_edid_size) { | |
@@ -983,7 +984,6 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) | |
ret = connector_status_connected; | |
} | |
-out: | |
/* updated in get modes as well since we need to know if it's analog or digital */ | |
radeon_connector_update_scratch_regs(connector, ret); | |
return ret; | |
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c | |
index 98a8ad6..43e4443 100644 | |
--- a/drivers/gpu/drm/radeon/radeon_i2c.c | |
+++ b/drivers/gpu/drm/radeon/radeon_i2c.c | |
@@ -890,6 +890,10 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, | |
struct radeon_i2c_chan *i2c; | |
int ret; | |
+ /* don't add the mm_i2c bus unless hw_i2c is enabled */ | |
+ if (rec->mm_i2c && (radeon_hw_i2c == 0)) | |
+ return NULL; | |
+ | |
i2c = kzalloc(sizeof(struct radeon_i2c_chan), GFP_KERNEL); | |
if (i2c == NULL) | |
return NULL; | |
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c | |
index 66d5fe1..65060b7 100644 | |
--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c | |
+++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c | |
@@ -147,6 +147,12 @@ static bool radeon_msi_ok(struct radeon_device *rdev) | |
(rdev->pdev->subsystem_device == 0x01fd)) | |
return true; | |
+ /* RV515 seems to have MSI issues where it loses | |
+ * MSI rearms occasionally. This leads to lockups and freezes. | |
+ * disable it by default. | |
+ */ | |
+ if (rdev->family == CHIP_RV515) | |
+ return false; | |
if (rdev->flags & RADEON_IS_IGP) { | |
/* APUs work fine with MSIs */ | |
if (rdev->family >= CHIP_PALM) | |
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c | |
index 3c5c550..cbae5d9 100644 | |
--- a/drivers/infiniband/ulp/srpt/ib_srpt.c | |
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.c | |
@@ -3225,6 +3225,7 @@ static void srpt_add_one(struct ib_device *device) | |
srq_attr.attr.max_wr = sdev->srq_size; | |
srq_attr.attr.max_sge = 1; | |
srq_attr.attr.srq_limit = 0; | |
+ srq_attr.srq_type = IB_SRQT_BASIC; | |
sdev->srq = ib_create_srq(sdev->pd, &srq_attr); | |
if (IS_ERR(sdev->srq)) | |
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c | |
index 239af9a..22cb5cf 100644 | |
--- a/drivers/md/bitmap.c | |
+++ b/drivers/md/bitmap.c | |
@@ -1819,7 +1819,9 @@ int bitmap_load(struct mddev *mddev) | |
* re-add of a missing device */ | |
start = mddev->recovery_cp; | |
+ mutex_lock(&mddev->bitmap_info.mutex); | |
err = bitmap_init_from_disk(bitmap, start); | |
+ mutex_unlock(&mddev->bitmap_info.mutex); | |
if (err) | |
goto out; | |
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c | |
index 118e0f6..edc735a 100644 | |
--- a/drivers/md/raid1.c | |
+++ b/drivers/md/raid1.c | |
@@ -1669,6 +1669,7 @@ static int process_checks(struct r1bio *r1_bio) | |
struct r1conf *conf = mddev->private; | |
int primary; | |
int i; | |
+ int vcnt; | |
for (primary = 0; primary < conf->raid_disks * 2; primary++) | |
if (r1_bio->bios[primary]->bi_end_io == end_sync_read && | |
@@ -1678,9 +1679,9 @@ static int process_checks(struct r1bio *r1_bio) | |
break; | |
} | |
r1_bio->read_disk = primary; | |
+ vcnt = (r1_bio->sectors + PAGE_SIZE / 512 - 1) >> (PAGE_SHIFT - 9); | |
for (i = 0; i < conf->raid_disks * 2; i++) { | |
int j; | |
- int vcnt = r1_bio->sectors >> (PAGE_SHIFT- 9); | |
struct bio *pbio = r1_bio->bios[primary]; | |
struct bio *sbio = r1_bio->bios[i]; | |
int size; | |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c | |
index be7101d..1898389 100644 | |
--- a/drivers/md/raid10.c | |
+++ b/drivers/md/raid10.c | |
@@ -1742,6 +1742,7 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio) | |
struct r10conf *conf = mddev->private; | |
int i, first; | |
struct bio *tbio, *fbio; | |
+ int vcnt; | |
atomic_set(&r10_bio->remaining, 1); | |
@@ -1756,10 +1757,10 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio) | |
first = i; | |
fbio = r10_bio->devs[i].bio; | |
+ vcnt = (r10_bio->sectors + (PAGE_SIZE >> 9) - 1) >> (PAGE_SHIFT - 9); | |
/* now find blocks with errors */ | |
for (i=0 ; i < conf->copies ; i++) { | |
int j, d; | |
- int vcnt = r10_bio->sectors >> (PAGE_SHIFT-9); | |
tbio = r10_bio->devs[i].bio; | |
@@ -1825,7 +1826,6 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio) | |
*/ | |
for (i = 0; i < conf->copies; i++) { | |
int j, d; | |
- int vcnt = r10_bio->sectors >> (PAGE_SHIFT-9); | |
tbio = r10_bio->devs[i].repl_bio; | |
if (!tbio || !tbio->bi_end_io) | |
diff --git a/drivers/net/Makefile b/drivers/net/Makefile | |
index 43ea94e..0569b7a 100644 | |
--- a/drivers/net/Makefile | |
+++ b/drivers/net/Makefile | |
@@ -7,9 +7,9 @@ | |
# | |
obj-$(CONFIG_BONDING) += bonding/ | |
obj-$(CONFIG_DUMMY) += dummy.o | |
-obj-$(CONFIG_IMQ) += imq.o | |
obj-$(CONFIG_EQUALIZER) += eql.o | |
obj-$(CONFIG_IFB) += ifb.o | |
+obj-$(CONFIG_IMQ) += imq.o | |
obj-$(CONFIG_MACVLAN) += macvlan.o | |
obj-$(CONFIG_MACVTAP) += macvtap.o | |
obj-$(CONFIG_MII) += mii.o | |
diff --git a/drivers/net/imq.c b/drivers/net/imq.c | |
index af72583..2aaf95a 100644 | |
--- a/drivers/net/imq.c | |
+++ b/drivers/net/imq.c | |
@@ -121,6 +121,12 @@ | |
* - Clean-up, move 'get imq device pointer by imqX name' to | |
* separate function from imq_nf_queue(). | |
* | |
+ * 2012/01/05 - Jussi Kivilinna <jussi.kivilinna@mbnet.fi> | |
+ * - Port to 3.2 | |
+ * | |
+ * 2012/03/19 - Jussi Kivilinna <jussi.kivilinna@mbnet.fi> | |
+ * - Port to 3.3 | |
+ * | |
* Also, many thanks to pablo Sebastian Greco for making the initial | |
* patch and to those who helped the testing. | |
* | |
@@ -283,13 +289,14 @@ recheck: | |
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | |
case htons(ETH_P_IPV6): { | |
const struct ipv6hdr *iph = ipv6_hdr(skb); | |
- __be16 frag_off; | |
+ __be16 fo = 0; | |
+ | |
if (unlikely(!pskb_may_pull(skb, sizeof(struct ipv6hdr)))) | |
goto other; | |
addr1 = iph->daddr.s6_addr32[3]; | |
addr2 = iph->saddr.s6_addr32[3]; | |
- ihl = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &ip_proto, &frag_off); | |
+ ihl = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &ip_proto, &fo); | |
if (unlikely(ihl < 0)) | |
goto other; | |
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c | |
index 34a7c45..c694cae 100644 | |
--- a/drivers/net/wireless/rtlwifi/pci.c | |
+++ b/drivers/net/wireless/rtlwifi/pci.c | |
@@ -921,8 +921,13 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) | |
memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); | |
ring = &rtlpci->tx_ring[BEACON_QUEUE]; | |
pskb = __skb_dequeue(&ring->queue); | |
- if (pskb) | |
+ if (pskb) { | |
+ struct rtl_tx_desc *entry = &ring->desc[ring->idx]; | |
+ pci_unmap_single(rtlpci->pdev, rtlpriv->cfg->ops->get_desc( | |
+ (u8 *) entry, true, HW_DESC_TXBUFF_ADDR), | |
+ pskb->len, PCI_DMA_TODEVICE); | |
kfree_skb(pskb); | |
+ } | |
/*NB: the beacon data buffer must be 32-bit aligned. */ | |
pskb = ieee80211_beacon_get(hw, mac->vif); | |
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c | |
index fbbfaba..049e207 100644 | |
--- a/drivers/net/wireless/rtlwifi/usb.c | |
+++ b/drivers/net/wireless/rtlwifi/usb.c | |
@@ -127,46 +127,38 @@ static int _usbctrl_vendorreq_sync_read(struct usb_device *udev, u8 request, | |
return status; | |
} | |
-static u32 _usb_read_sync(struct usb_device *udev, u32 addr, u16 len) | |
+static u32 _usb_read_sync(struct rtl_priv *rtlpriv, u32 addr, u16 len) | |
{ | |
+ struct device *dev = rtlpriv->io.dev; | |
+ struct usb_device *udev = to_usb_device(dev); | |
u8 request; | |
u16 wvalue; | |
u16 index; | |
- u32 *data; | |
- u32 ret; | |
+ __le32 *data = &rtlpriv->usb_data[rtlpriv->usb_data_index]; | |
- data = kmalloc(sizeof(u32), GFP_KERNEL); | |
- if (!data) | |
- return -ENOMEM; | |
request = REALTEK_USB_VENQT_CMD_REQ; | |
index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */ | |
wvalue = (u16)addr; | |
_usbctrl_vendorreq_sync_read(udev, request, wvalue, index, data, len); | |
- ret = le32_to_cpu(*data); | |
- kfree(data); | |
- return ret; | |
+ if (++rtlpriv->usb_data_index >= RTL_USB_MAX_RX_COUNT) | |
+ rtlpriv->usb_data_index = 0; | |
+ return le32_to_cpu(*data); | |
} | |
static u8 _usb_read8_sync(struct rtl_priv *rtlpriv, u32 addr) | |
{ | |
- struct device *dev = rtlpriv->io.dev; | |
- | |
- return (u8)_usb_read_sync(to_usb_device(dev), addr, 1); | |
+ return (u8)_usb_read_sync(rtlpriv, addr, 1); | |
} | |
static u16 _usb_read16_sync(struct rtl_priv *rtlpriv, u32 addr) | |
{ | |
- struct device *dev = rtlpriv->io.dev; | |
- | |
- return (u16)_usb_read_sync(to_usb_device(dev), addr, 2); | |
+ return (u16)_usb_read_sync(rtlpriv, addr, 2); | |
} | |
static u32 _usb_read32_sync(struct rtl_priv *rtlpriv, u32 addr) | |
{ | |
- struct device *dev = rtlpriv->io.dev; | |
- | |
- return _usb_read_sync(to_usb_device(dev), addr, 4); | |
+ return _usb_read_sync(rtlpriv, addr, 4); | |
} | |
static void _usb_write_async(struct usb_device *udev, u32 addr, u32 val, | |
@@ -954,6 +946,11 @@ int __devinit rtl_usb_probe(struct usb_interface *intf, | |
return -ENOMEM; | |
} | |
rtlpriv = hw->priv; | |
+ rtlpriv->usb_data = kzalloc(RTL_USB_MAX_RX_COUNT * sizeof(u32), | |
+ GFP_KERNEL); | |
+ if (!rtlpriv->usb_data) | |
+ return -ENOMEM; | |
+ rtlpriv->usb_data_index = 0; | |
init_completion(&rtlpriv->firmware_loading_complete); | |
SET_IEEE80211_DEV(hw, &intf->dev); | |
udev = interface_to_usbdev(intf); | |
@@ -1023,6 +1020,7 @@ void rtl_usb_disconnect(struct usb_interface *intf) | |
/* rtl_deinit_rfkill(hw); */ | |
rtl_usb_deinit(hw); | |
rtl_deinit_core(hw); | |
+ kfree(rtlpriv->usb_data); | |
rtlpriv->cfg->ops->deinit_sw_leds(hw); | |
rtlpriv->cfg->ops->deinit_sw_vars(hw); | |
_rtl_usb_io_handler_release(hw); | |
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h | |
index cfd8d1c..37d2329 100644 | |
--- a/drivers/net/wireless/rtlwifi/wifi.h | |
+++ b/drivers/net/wireless/rtlwifi/wifi.h | |
@@ -65,7 +65,7 @@ | |
#define QOS_QUEUE_NUM 4 | |
#define RTL_MAC80211_NUM_QUEUE 5 | |
#define REALTEK_USB_VENQT_MAX_BUF_SIZE 254 | |
- | |
+#define RTL_USB_MAX_RX_COUNT 100 | |
#define QBSS_LOAD_SIZE 5 | |
#define MAX_WMMELE_LENGTH 64 | |
@@ -1627,6 +1627,10 @@ struct rtl_priv { | |
interface or hardware */ | |
unsigned long status; | |
+ /* data buffer pointer for USB reads */ | |
+ __le32 *usb_data; | |
+ int usb_data_index; | |
+ | |
/*This must be the last item so | |
that it points to the data allocated | |
beyond this structure like: | |
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c | |
index a952c8d..ee5a561 100644 | |
--- a/drivers/rtc/rtc-pl031.c | |
+++ b/drivers/rtc/rtc-pl031.c | |
@@ -339,8 +339,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) | |
dev_dbg(&adev->dev, "revision = 0x%01x\n", ldata->hw_revision); | |
/* Enable the clockwatch on ST Variants */ | |
- if ((ldata->hw_designer == AMBA_VENDOR_ST) && | |
- (ldata->hw_revision > 1)) | |
+ if (ldata->hw_designer == AMBA_VENDOR_ST) | |
writel(readl(ldata->base + RTC_CR) | RTC_CR_CWEN, | |
ldata->base + RTC_CR); | |
diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c | |
index 10182eb..0ddfe77 100644 | |
--- a/drivers/spi/spi-topcliff-pch.c | |
+++ b/drivers/spi/spi-topcliff-pch.c | |
@@ -318,22 +318,23 @@ static void pch_spi_handler_sub(struct pch_spi_data *data, u32 reg_spsr_val, | |
data->tx_index = tx_index; | |
data->rx_index = rx_index; | |
- } | |
- | |
- /* if transfer complete interrupt */ | |
- if (reg_spsr_val & SPSR_FI_BIT) { | |
- if ((tx_index == bpw_len) && (rx_index == tx_index)) { | |
- /* disable interrupts */ | |
- pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL); | |
- | |
- /* transfer is completed; | |
- inform pch_spi_process_messages */ | |
- data->transfer_complete = true; | |
- data->transfer_active = false; | |
- wake_up(&data->wait); | |
- } else { | |
- dev_err(&data->master->dev, | |
- "%s : Transfer is not completed", __func__); | |
+ /* if transfer complete interrupt */ | |
+ if (reg_spsr_val & SPSR_FI_BIT) { | |
+ if ((tx_index == bpw_len) && (rx_index == tx_index)) { | |
+ /* disable interrupts */ | |
+ pch_spi_setclr_reg(data->master, PCH_SPCR, 0, | |
+ PCH_ALL); | |
+ | |
+ /* transfer is completed; | |
+ inform pch_spi_process_messages */ | |
+ data->transfer_complete = true; | |
+ data->transfer_active = false; | |
+ wake_up(&data->wait); | |
+ } else { | |
+ dev_err(&data->master->dev, | |
+ "%s : Transfer is not completed", | |
+ __func__); | |
+ } | |
} | |
} | |
} | |
diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c | |
index f2e85a9..95db3ba 100644 | |
--- a/drivers/staging/iio/magnetometer/hmc5843.c | |
+++ b/drivers/staging/iio/magnetometer/hmc5843.c | |
@@ -521,7 +521,9 @@ static int hmc5843_detect(struct i2c_client *client, | |
/* Called when we have found a new HMC5843. */ | |
static void hmc5843_init_client(struct i2c_client *client) | |
{ | |
- struct hmc5843_data *data = i2c_get_clientdata(client); | |
+ struct iio_dev *indio_dev = i2c_get_clientdata(client); | |
+ struct hmc5843_data *data = iio_priv(indio_dev); | |
+ | |
hmc5843_set_meas_conf(client, data->meas_conf); | |
hmc5843_set_rate(client, data->rate); | |
hmc5843_configure(client, data->operating_mode); | |
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c | |
index 9b7336f..0e2c703 100644 | |
--- a/drivers/tty/serial/8250/8250.c | |
+++ b/drivers/tty/serial/8250/8250.c | |
@@ -1592,13 +1592,11 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id) | |
do { | |
struct uart_8250_port *up; | |
struct uart_port *port; | |
- bool skip; | |
up = list_entry(l, struct uart_8250_port, list); | |
port = &up->port; | |
- skip = pass_counter && up->port.flags & UPF_IIR_ONCE; | |
- if (!skip && port->handle_irq(port)) { | |
+ if (port->handle_irq(port)) { | |
handled = 1; | |
end = NULL; | |
} else if (end == NULL) | |
@@ -2057,10 +2055,12 @@ static int serial8250_startup(struct uart_port *port) | |
spin_unlock_irqrestore(&up->port.lock, flags); | |
/* | |
- * If the interrupt is not reasserted, setup a timer to | |
- * kick the UART on a regular basis. | |
+ * If the interrupt is not reasserted, or we otherwise | |
+ * don't trust the iir, setup a timer to kick the UART | |
+ * on a regular basis. | |
*/ | |
- if (!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) { | |
+ if ((!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) || | |
+ up->port.flags & UPF_BUG_THRE) { | |
up->bugs |= UART_BUG_THRE; | |
pr_debug("ttyS%d - using backup timer\n", | |
serial_index(port)); | |
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c | |
index da2b0b0..858dca8 100644 | |
--- a/drivers/tty/serial/8250/8250_pci.c | |
+++ b/drivers/tty/serial/8250/8250_pci.c | |
@@ -1096,7 +1096,7 @@ static int kt_serial_setup(struct serial_private *priv, | |
const struct pciserial_board *board, | |
struct uart_port *port, int idx) | |
{ | |
- port->flags |= UPF_IIR_ONCE; | |
+ port->flags |= UPF_BUG_THRE; | |
return skip_tx_en_setup(priv, board, port, idx); | |
} | |
@@ -1118,18 +1118,6 @@ pci_xr17c154_setup(struct serial_private *priv, | |
return pci_default_setup(priv, board, port, idx); | |
} | |
-static int try_enable_msi(struct pci_dev *dev) | |
-{ | |
- /* use msi if available, but fallback to legacy otherwise */ | |
- pci_enable_msi(dev); | |
- return 0; | |
-} | |
- | |
-static void disable_msi(struct pci_dev *dev) | |
-{ | |
- pci_disable_msi(dev); | |
-} | |
- | |
#define PCI_VENDOR_ID_SBSMODULARIO 0x124B | |
#define PCI_SUBVENDOR_ID_SBSMODULARIO 0x124B | |
#define PCI_DEVICE_ID_OCTPRO 0x0001 | |
@@ -1249,9 +1237,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { | |
.device = PCI_DEVICE_ID_INTEL_PATSBURG_KT, | |
.subvendor = PCI_ANY_ID, | |
.subdevice = PCI_ANY_ID, | |
- .init = try_enable_msi, | |
.setup = kt_serial_setup, | |
- .exit = disable_msi, | |
}, | |
/* | |
* ITE | |
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c | |
index 1d04c50..5ba0898 100644 | |
--- a/drivers/tty/serial/altera_uart.c | |
+++ b/drivers/tty/serial/altera_uart.c | |
@@ -555,7 +555,7 @@ static int __devinit altera_uart_probe(struct platform_device *pdev) | |
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
if (res_mem) | |
port->mapbase = res_mem->start; | |
- else if (platp->mapbase) | |
+ else if (platp) | |
port->mapbase = platp->mapbase; | |
else | |
return -EINVAL; | |
@@ -563,7 +563,7 @@ static int __devinit altera_uart_probe(struct platform_device *pdev) | |
res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | |
if (res_irq) | |
port->irq = res_irq->start; | |
- else if (platp->irq) | |
+ else if (platp) | |
port->irq = platp->irq; | |
/* Check platform data first so we can override device node data */ | |
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c | |
index 6800f5f..4ed35c5 100644 | |
--- a/drivers/tty/serial/amba-pl011.c | |
+++ b/drivers/tty/serial/amba-pl011.c | |
@@ -1381,6 +1381,10 @@ static int pl011_startup(struct uart_port *port) | |
uap->port.uartclk = clk_get_rate(uap->clk); | |
+ /* Clear pending error and receive interrupts */ | |
+ writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS | | |
+ UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR); | |
+ | |
/* | |
* Allocate the IRQ | |
*/ | |
@@ -1417,10 +1421,6 @@ static int pl011_startup(struct uart_port *port) | |
cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE; | |
writew(cr, uap->port.membase + UART011_CR); | |
- /* Clear pending error interrupts */ | |
- writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS, | |
- uap->port.membase + UART011_ICR); | |
- | |
/* | |
* initialise the old status of the modem signals | |
*/ | |
@@ -1435,6 +1435,9 @@ static int pl011_startup(struct uart_port *port) | |
* as well. | |
*/ | |
spin_lock_irq(&uap->port.lock); | |
+ /* Clear out any spuriously appearing RX interrupts */ | |
+ writew(UART011_RTIS | UART011_RXIS, | |
+ uap->port.membase + UART011_ICR); | |
uap->im = UART011_RTIM; | |
if (!pl011_dma_rx_running(uap)) | |
uap->im |= UART011_RXIM; | |
@@ -1944,6 +1947,10 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) | |
uap->port.line = i; | |
pl011_dma_probe(uap); | |
+ /* Ensure interrupts from this UART are masked and cleared */ | |
+ writew(0, uap->port.membase + UART011_IMSC); | |
+ writew(0xffff, uap->port.membase + UART011_ICR); | |
+ | |
snprintf(uap->type, sizeof(uap->type), "PL011 rev%u", amba_rev(dev)); | |
amba_ports[i] = uap; | |
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c | |
index 17ae657..525951f 100644 | |
--- a/drivers/tty/serial/pch_uart.c | |
+++ b/drivers/tty/serial/pch_uart.c | |
@@ -1586,6 +1586,7 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, | |
} | |
pci_enable_msi(pdev); | |
+ pci_set_master(pdev); | |
iobase = pci_resource_start(pdev, 0); | |
mapbase = pci_resource_start(pdev, 1); | |
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c | |
index c55e5fb..38a829a 100644 | |
--- a/drivers/tty/serial/samsung.c | |
+++ b/drivers/tty/serial/samsung.c | |
@@ -982,6 +982,7 @@ static void s3c24xx_serial_resetport(struct uart_port *port, | |
ucon &= ucon_mask; | |
wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); | |
+ wr_regl(port, S3C2410_ULCON, cfg->ulcon); | |
/* reset both fifos */ | |
wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); | |
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c | |
index d40ff95..52aa620 100644 | |
--- a/drivers/usb/core/driver.c | |
+++ b/drivers/usb/core/driver.c | |
@@ -1190,8 +1190,13 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) | |
if (status == 0) { | |
status = usb_suspend_device(udev, msg); | |
- /* Again, ignore errors during system sleep transitions */ | |
- if (!PMSG_IS_AUTO(msg)) | |
+ /* | |
+ * Ignore errors from non-root-hub devices during | |
+ * system sleep transitions. For the most part, | |
+ * these devices should go to low power anyway when | |
+ * the entire bus is suspended. | |
+ */ | |
+ if (udev->parent && !PMSG_IS_AUTO(msg)) | |
status = 0; | |
} | |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c | |
index 265c2f6..7e619f4 100644 | |
--- a/drivers/usb/core/hub.c | |
+++ b/drivers/usb/core/hub.c | |
@@ -3071,6 +3071,22 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, | |
if (retval) | |
goto fail; | |
+ /* | |
+ * Some superspeed devices have finished the link training process | |
+ * and attached to a superspeed hub port, but the device descriptor | |
+ * got from those devices show they aren't superspeed devices. Warm | |
+ * reset the port attached by the devices can fix them. | |
+ */ | |
+ if ((udev->speed == USB_SPEED_SUPER) && | |
+ (le16_to_cpu(udev->descriptor.bcdUSB) < 0x0300)) { | |
+ dev_err(&udev->dev, "got a wrong device descriptor, " | |
+ "warm reset device\n"); | |
+ hub_port_reset(hub, port1, udev, | |
+ HUB_BH_RESET_TIME, true); | |
+ retval = -EINVAL; | |
+ goto fail; | |
+ } | |
+ | |
if (udev->descriptor.bMaxPacketSize0 == 0xff || | |
udev->speed == USB_SPEED_SUPER) | |
i = 512; | |
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c | |
index b3bdfed..aed3e07 100644 | |
--- a/drivers/usb/core/message.c | |
+++ b/drivers/usb/core/message.c | |
@@ -308,7 +308,8 @@ static void sg_complete(struct urb *urb) | |
retval = usb_unlink_urb(io->urbs [i]); | |
if (retval != -EINPROGRESS && | |
retval != -ENODEV && | |
- retval != -EBUSY) | |
+ retval != -EBUSY && | |
+ retval != -EIDRM) | |
dev_err(&io->dev->dev, | |
"%s, unlink --> %d\n", | |
__func__, retval); | |
@@ -317,7 +318,6 @@ static void sg_complete(struct urb *urb) | |
} | |
spin_lock(&io->lock); | |
} | |
- urb->dev = NULL; | |
/* on the last completion, signal usb_sg_wait() */ | |
io->bytes += urb->actual_length; | |
@@ -524,7 +524,6 @@ void usb_sg_wait(struct usb_sg_request *io) | |
case -ENXIO: /* hc didn't queue this one */ | |
case -EAGAIN: | |
case -ENOMEM: | |
- io->urbs[i]->dev = NULL; | |
retval = 0; | |
yield(); | |
break; | |
@@ -542,7 +541,6 @@ void usb_sg_wait(struct usb_sg_request *io) | |
/* fail any uncompleted urbs */ | |
default: | |
- io->urbs[i]->dev = NULL; | |
io->urbs[i]->status = retval; | |
dev_dbg(&io->dev->dev, "%s, submit --> %d\n", | |
__func__, retval); | |
@@ -593,7 +591,10 @@ void usb_sg_cancel(struct usb_sg_request *io) | |
if (!io->urbs [i]->dev) | |
continue; | |
retval = usb_unlink_urb(io->urbs [i]); | |
- if (retval != -EINPROGRESS && retval != -EBUSY) | |
+ if (retval != -EINPROGRESS | |
+ && retval != -ENODEV | |
+ && retval != -EBUSY | |
+ && retval != -EIDRM) | |
dev_warn(&io->dev->dev, "%s, unlink --> %d\n", | |
__func__, retval); | |
} | |
diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c | |
index 2d567ba..9c0d2d5 100644 | |
--- a/drivers/usb/gadget/pch_udc.c | |
+++ b/drivers/usb/gadget/pch_udc.c | |
@@ -311,6 +311,7 @@ struct pch_udc_ep { | |
* @registered: driver regsitered with system | |
* @suspended: driver in suspended state | |
* @connected: gadget driver associated | |
+ * @vbus_session: required vbus_session state | |
* @set_cfg_not_acked: pending acknowledgement 4 setup | |
* @waiting_zlp_ack: pending acknowledgement 4 ZLP | |
* @data_requests: DMA pool for data requests | |
@@ -337,6 +338,7 @@ struct pch_udc_dev { | |
registered:1, | |
suspended:1, | |
connected:1, | |
+ vbus_session:1, | |
set_cfg_not_acked:1, | |
waiting_zlp_ack:1; | |
struct pci_pool *data_requests; | |
@@ -554,6 +556,29 @@ static void pch_udc_clear_disconnect(struct pch_udc_dev *dev) | |
} | |
/** | |
+ * pch_udc_reconnect() - This API initializes usb device controller, | |
+ * and clear the disconnect status. | |
+ * @dev: Reference to pch_udc_regs structure | |
+ */ | |
+static void pch_udc_init(struct pch_udc_dev *dev); | |
+static void pch_udc_reconnect(struct pch_udc_dev *dev) | |
+{ | |
+ pch_udc_init(dev); | |
+ | |
+ /* enable device interrupts */ | |
+ /* pch_udc_enable_interrupts() */ | |
+ pch_udc_bit_clr(dev, UDC_DEVIRQMSK_ADDR, | |
+ UDC_DEVINT_UR | UDC_DEVINT_ENUM); | |
+ | |
+ /* Clear the disconnect */ | |
+ pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES); | |
+ pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_SD); | |
+ mdelay(1); | |
+ /* Resume USB signalling */ | |
+ pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES); | |
+} | |
+ | |
+/** | |
* pch_udc_vbus_session() - set or clearr the disconnect status. | |
* @dev: Reference to pch_udc_regs structure | |
* @is_active: Parameter specifying the action | |
@@ -563,10 +588,18 @@ static void pch_udc_clear_disconnect(struct pch_udc_dev *dev) | |
static inline void pch_udc_vbus_session(struct pch_udc_dev *dev, | |
int is_active) | |
{ | |
- if (is_active) | |
- pch_udc_clear_disconnect(dev); | |
- else | |
+ if (is_active) { | |
+ pch_udc_reconnect(dev); | |
+ dev->vbus_session = 1; | |
+ } else { | |
+ if (dev->driver && dev->driver->disconnect) { | |
+ spin_unlock(&dev->lock); | |
+ dev->driver->disconnect(&dev->gadget); | |
+ spin_lock(&dev->lock); | |
+ } | |
pch_udc_set_disconnect(dev); | |
+ dev->vbus_session = 0; | |
+ } | |
} | |
/** | |
@@ -1126,7 +1159,17 @@ static int pch_udc_pcd_pullup(struct usb_gadget *gadget, int is_on) | |
if (!gadget) | |
return -EINVAL; | |
dev = container_of(gadget, struct pch_udc_dev, gadget); | |
- pch_udc_vbus_session(dev, is_on); | |
+ if (is_on) { | |
+ pch_udc_reconnect(dev); | |
+ } else { | |
+ if (dev->driver && dev->driver->disconnect) { | |
+ spin_unlock(&dev->lock); | |
+ dev->driver->disconnect(&dev->gadget); | |
+ spin_lock(&dev->lock); | |
+ } | |
+ pch_udc_set_disconnect(dev); | |
+ } | |
+ | |
return 0; | |
} | |
@@ -2336,8 +2379,11 @@ static void pch_udc_svc_ur_interrupt(struct pch_udc_dev *dev) | |
/* Complete request queue */ | |
empty_req_queue(ep); | |
} | |
- if (dev->driver && dev->driver->disconnect) | |
+ if (dev->driver && dev->driver->disconnect) { | |
+ spin_unlock(&dev->lock); | |
dev->driver->disconnect(&dev->gadget); | |
+ spin_lock(&dev->lock); | |
+ } | |
} | |
/** | |
@@ -2372,6 +2418,11 @@ static void pch_udc_svc_enum_interrupt(struct pch_udc_dev *dev) | |
pch_udc_set_dma(dev, DMA_DIR_TX); | |
pch_udc_set_dma(dev, DMA_DIR_RX); | |
pch_udc_ep_set_rrdy(&(dev->ep[UDC_EP0OUT_IDX])); | |
+ | |
+ /* enable device interrupts */ | |
+ pch_udc_enable_interrupts(dev, UDC_DEVINT_UR | UDC_DEVINT_US | | |
+ UDC_DEVINT_ES | UDC_DEVINT_ENUM | | |
+ UDC_DEVINT_SI | UDC_DEVINT_SC); | |
} | |
/** | |
@@ -2473,8 +2524,24 @@ static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr) | |
if (dev_intr & UDC_DEVINT_SC) | |
pch_udc_svc_cfg_interrupt(dev); | |
/* USB Suspend interrupt */ | |
- if (dev_intr & UDC_DEVINT_US) | |
+ if (dev_intr & UDC_DEVINT_US) { | |
+ if (dev->driver | |
+ && dev->driver->suspend) { | |
+ spin_unlock(&dev->lock); | |
+ dev->driver->suspend(&dev->gadget); | |
+ spin_lock(&dev->lock); | |
+ } | |
+ | |
+ if (dev->vbus_session == 0) { | |
+ if (dev->driver && dev->driver->disconnect) { | |
+ spin_unlock(&dev->lock); | |
+ dev->driver->disconnect(&dev->gadget); | |
+ spin_lock(&dev->lock); | |
+ } | |
+ pch_udc_reconnect(dev); | |
+ } | |
dev_dbg(&dev->pdev->dev, "USB_SUSPEND\n"); | |
+ } | |
/* Clear the SOF interrupt, if enabled */ | |
if (dev_intr & UDC_DEVINT_SOF) | |
dev_dbg(&dev->pdev->dev, "SOF\n"); | |
@@ -2500,6 +2567,14 @@ static irqreturn_t pch_udc_isr(int irq, void *pdev) | |
dev_intr = pch_udc_read_device_interrupts(dev); | |
ep_intr = pch_udc_read_ep_interrupts(dev); | |
+ /* For a hot plug, this find that the controller is hung up. */ | |
+ if (dev_intr == ep_intr) | |
+ if (dev_intr == pch_udc_readl(dev, UDC_DEVCFG_ADDR)) { | |
+ dev_dbg(&dev->pdev->dev, "UDC: Hung up\n"); | |
+ /* The controller is reset */ | |
+ pch_udc_writel(dev, UDC_SRST, UDC_SRST_ADDR); | |
+ return IRQ_HANDLED; | |
+ } | |
if (dev_intr) | |
/* Clear device interrupts */ | |
pch_udc_write_device_interrupts(dev, dev_intr); | |
@@ -2913,8 +2988,10 @@ static int pch_udc_probe(struct pci_dev *pdev, | |
} | |
pch_udc = dev; | |
/* initialize the hardware */ | |
- if (pch_udc_pcd_init(dev)) | |
+ if (pch_udc_pcd_init(dev)) { | |
+ retval = -ENODEV; | |
goto finished; | |
+ } | |
if (request_irq(pdev->irq, pch_udc_isr, IRQF_SHARED, KBUILD_MODNAME, | |
dev)) { | |
dev_err(&pdev->dev, "%s: request_irq(%d) fail\n", __func__, | |
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c | |
index 7732d69..2afff88 100644 | |
--- a/drivers/usb/host/pci-quirks.c | |
+++ b/drivers/usb/host/pci-quirks.c | |
@@ -825,9 +825,13 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev) | |
} | |
} | |
- /* Disable any BIOS SMIs */ | |
- writel(XHCI_LEGACY_DISABLE_SMI, | |
- base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET); | |
+ val = readl(base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET); | |
+ /* Mask off (turn off) any enabled SMIs */ | |
+ val &= XHCI_LEGACY_DISABLE_SMI; | |
+ /* Mask all SMI events bits, RW1C */ | |
+ val |= XHCI_LEGACY_SMI_EVENTS; | |
+ /* Disable any BIOS SMIs and clear all SMI events*/ | |
+ writel(val, base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET); | |
if (usb_is_intel_switchable_xhci(pdev)) | |
usb_enable_xhci_ports(pdev); | |
diff --git a/drivers/usb/host/xhci-ext-caps.h b/drivers/usb/host/xhci-ext-caps.h | |
index c7f3312..377f424 100644 | |
--- a/drivers/usb/host/xhci-ext-caps.h | |
+++ b/drivers/usb/host/xhci-ext-caps.h | |
@@ -62,8 +62,9 @@ | |
/* USB Legacy Support Control and Status Register - section 7.1.2 */ | |
/* Add this offset, plus the value of xECP in HCCPARAMS to the base address */ | |
#define XHCI_LEGACY_CONTROL_OFFSET (0x04) | |
-/* bits 1:2, 5:12, and 17:19 need to be preserved; bits 21:28 should be zero */ | |
-#define XHCI_LEGACY_DISABLE_SMI ((0x3 << 1) + (0xff << 5) + (0x7 << 17)) | |
+/* bits 1:3, 5:12, and 17:19 need to be preserved; bits 21:28 should be zero */ | |
+#define XHCI_LEGACY_DISABLE_SMI ((0x7 << 1) + (0xff << 5) + (0x7 << 17)) | |
+#define XHCI_LEGACY_SMI_EVENTS (0x7 << 29) | |
/* USB 2.0 xHCI 0.96 L1C capability - section 7.2.2.1.3.2 */ | |
#define XHCI_L1C (1 << 16) | |
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c | |
index 383fc85..4c1e721 100644 | |
--- a/drivers/usb/host/xhci-mem.c | |
+++ b/drivers/usb/host/xhci-mem.c | |
@@ -1690,11 +1690,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) | |
int i; | |
/* Free the Event Ring Segment Table and the actual Event Ring */ | |
- if (xhci->ir_set) { | |
- xhci_writel(xhci, 0, &xhci->ir_set->erst_size); | |
- xhci_write_64(xhci, 0, &xhci->ir_set->erst_base); | |
- xhci_write_64(xhci, 0, &xhci->ir_set->erst_dequeue); | |
- } | |
size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries); | |
if (xhci->erst.entries) | |
dma_free_coherent(&pdev->dev, size, | |
@@ -1706,7 +1701,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) | |
xhci->event_ring = NULL; | |
xhci_dbg(xhci, "Freed event ring\n"); | |
- xhci_write_64(xhci, 0, &xhci->op_regs->cmd_ring); | |
if (xhci->cmd_ring) | |
xhci_ring_free(xhci, xhci->cmd_ring); | |
xhci->cmd_ring = NULL; | |
@@ -1735,7 +1729,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) | |
xhci->medium_streams_pool = NULL; | |
xhci_dbg(xhci, "Freed medium stream array pool\n"); | |
- xhci_write_64(xhci, 0, &xhci->op_regs->dcbaa_ptr); | |
if (xhci->dcbaa) | |
dma_free_coherent(&pdev->dev, sizeof(*xhci->dcbaa), | |
xhci->dcbaa, xhci->dcbaa->dma); | |
@@ -2344,6 +2337,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) | |
fail: | |
xhci_warn(xhci, "Couldn't initialize memory\n"); | |
+ xhci_halt(xhci); | |
+ xhci_reset(xhci); | |
xhci_mem_cleanup(xhci); | |
return -ENOMEM; | |
} | |
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c | |
index ef98b38..211296a 100644 | |
--- a/drivers/usb/host/xhci-pci.c | |
+++ b/drivers/usb/host/xhci-pci.c | |
@@ -95,6 +95,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) | |
xhci->quirks |= XHCI_RESET_ON_RESUME; | |
xhci_dbg(xhci, "QUIRK: Resetting on resume\n"); | |
} | |
+ if (pdev->vendor == PCI_VENDOR_ID_VIA) | |
+ xhci->quirks |= XHCI_RESET_ON_RESUME; | |
} | |
/* called during probe() after chip reset completes */ | |
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c | |
index b62037b..6851bc2 100644 | |
--- a/drivers/usb/host/xhci-ring.c | |
+++ b/drivers/usb/host/xhci-ring.c | |
@@ -2350,7 +2350,7 @@ hw_died: | |
u32 irq_pending; | |
/* Acknowledge the PCI interrupt */ | |
irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending); | |
- irq_pending |= 0x3; | |
+ irq_pending |= IMAN_IP; | |
xhci_writel(xhci, irq_pending, &xhci->ir_set->irq_pending); | |
} | |
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c | |
index c939f5f..f9ea3c8 100644 | |
--- a/drivers/usb/host/xhci.c | |
+++ b/drivers/usb/host/xhci.c | |
@@ -664,11 +664,11 @@ static void xhci_save_registers(struct xhci_hcd *xhci) | |
xhci->s3.dev_nt = xhci_readl(xhci, &xhci->op_regs->dev_notification); | |
xhci->s3.dcbaa_ptr = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr); | |
xhci->s3.config_reg = xhci_readl(xhci, &xhci->op_regs->config_reg); | |
- xhci->s3.irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending); | |
- xhci->s3.irq_control = xhci_readl(xhci, &xhci->ir_set->irq_control); | |
xhci->s3.erst_size = xhci_readl(xhci, &xhci->ir_set->erst_size); | |
xhci->s3.erst_base = xhci_read_64(xhci, &xhci->ir_set->erst_base); | |
xhci->s3.erst_dequeue = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); | |
+ xhci->s3.irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending); | |
+ xhci->s3.irq_control = xhci_readl(xhci, &xhci->ir_set->irq_control); | |
} | |
static void xhci_restore_registers(struct xhci_hcd *xhci) | |
@@ -677,10 +677,11 @@ static void xhci_restore_registers(struct xhci_hcd *xhci) | |
xhci_writel(xhci, xhci->s3.dev_nt, &xhci->op_regs->dev_notification); | |
xhci_write_64(xhci, xhci->s3.dcbaa_ptr, &xhci->op_regs->dcbaa_ptr); | |
xhci_writel(xhci, xhci->s3.config_reg, &xhci->op_regs->config_reg); | |
- xhci_writel(xhci, xhci->s3.irq_pending, &xhci->ir_set->irq_pending); | |
- xhci_writel(xhci, xhci->s3.irq_control, &xhci->ir_set->irq_control); | |
xhci_writel(xhci, xhci->s3.erst_size, &xhci->ir_set->erst_size); | |
xhci_write_64(xhci, xhci->s3.erst_base, &xhci->ir_set->erst_base); | |
+ xhci_write_64(xhci, xhci->s3.erst_dequeue, &xhci->ir_set->erst_dequeue); | |
+ xhci_writel(xhci, xhci->s3.irq_pending, &xhci->ir_set->irq_pending); | |
+ xhci_writel(xhci, xhci->s3.irq_control, &xhci->ir_set->irq_control); | |
} | |
static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci) | |
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h | |
index fb99c83..a947d70 100644 | |
--- a/drivers/usb/host/xhci.h | |
+++ b/drivers/usb/host/xhci.h | |
@@ -205,6 +205,10 @@ struct xhci_op_regs { | |
#define CMD_PM_INDEX (1 << 11) | |
/* bits 12:31 are reserved (and should be preserved on writes). */ | |
+/* IMAN - Interrupt Management Register */ | |
+#define IMAN_IP (1 << 1) | |
+#define IMAN_IE (1 << 0) | |
+ | |
/* USBSTS - USB status - status bitmasks */ | |
/* HC not running - set to 1 when run/stop bit is cleared. */ | |
#define STS_HALT XHCI_STS_HALT | |
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c | |
index 8aa51d9..0ca65e4 100644 | |
--- a/drivers/usb/serial/ftdi_sio.c | |
+++ b/drivers/usb/serial/ftdi_sio.c | |
@@ -75,7 +75,8 @@ struct ftdi_private { | |
unsigned long last_dtr_rts; /* saved modem control outputs */ | |
struct async_icount icount; | |
wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ | |
- char prev_status, diff_status; /* Used for TIOCMIWAIT */ | |
+ char prev_status; /* Used for TIOCMIWAIT */ | |
+ bool dev_gone; /* Used to abort TIOCMIWAIT */ | |
char transmit_empty; /* If transmitter is empty or not */ | |
struct usb_serial_port *port; | |
__u16 interface; /* FT2232C, FT2232H or FT4232H port interface | |
@@ -1679,6 +1680,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) | |
init_waitqueue_head(&priv->delta_msr_wait); | |
priv->flags = ASYNC_LOW_LATENCY; | |
+ priv->dev_gone = false; | |
if (quirk && quirk->port_probe) | |
quirk->port_probe(priv); | |
@@ -1836,6 +1838,9 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port) | |
dbg("%s", __func__); | |
+ priv->dev_gone = true; | |
+ wake_up_interruptible_all(&priv->delta_msr_wait); | |
+ | |
remove_sysfs_attrs(port); | |
kref_put(&priv->kref, ftdi_sio_priv_release); | |
@@ -1979,17 +1984,19 @@ static int ftdi_process_packet(struct tty_struct *tty, | |
N.B. packet may be processed more than once, but differences | |
are only processed once. */ | |
status = packet[0] & FTDI_STATUS_B0_MASK; | |
- if (status & FTDI_RS0_CTS) | |
- priv->icount.cts++; | |
- if (status & FTDI_RS0_DSR) | |
- priv->icount.dsr++; | |
- if (status & FTDI_RS0_RI) | |
- priv->icount.rng++; | |
- if (status & FTDI_RS0_RLSD) | |
- priv->icount.dcd++; | |
if (status != priv->prev_status) { | |
- priv->diff_status |= status ^ priv->prev_status; | |
- wake_up_interruptible(&priv->delta_msr_wait); | |
+ char diff_status = status ^ priv->prev_status; | |
+ | |
+ if (diff_status & FTDI_RS0_CTS) | |
+ priv->icount.cts++; | |
+ if (diff_status & FTDI_RS0_DSR) | |
+ priv->icount.dsr++; | |
+ if (diff_status & FTDI_RS0_RI) | |
+ priv->icount.rng++; | |
+ if (diff_status & FTDI_RS0_RLSD) | |
+ priv->icount.dcd++; | |
+ | |
+ wake_up_interruptible_all(&priv->delta_msr_wait); | |
priv->prev_status = status; | |
} | |
@@ -2392,15 +2399,12 @@ static int ftdi_ioctl(struct tty_struct *tty, | |
*/ | |
case TIOCMIWAIT: | |
cprev = priv->icount; | |
- while (1) { | |
+ while (!priv->dev_gone) { | |
interruptible_sleep_on(&priv->delta_msr_wait); | |
/* see if a signal did it */ | |
if (signal_pending(current)) | |
return -ERESTARTSYS; | |
cnow = priv->icount; | |
- if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && | |
- cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) | |
- return -EIO; /* no change => error */ | |
if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || | |
((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || | |
((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || | |
@@ -2409,7 +2413,7 @@ static int ftdi_ioctl(struct tty_struct *tty, | |
} | |
cprev = cnow; | |
} | |
- /* not reached */ | |
+ return -EIO; | |
break; | |
case TIOCSERGETLSR: | |
return get_lsr_info(port, (struct serial_struct __user *)arg); | |
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c | |
index 2a54121..6e5bce0 100644 | |
--- a/drivers/usb/serial/option.c | |
+++ b/drivers/usb/serial/option.c | |
@@ -708,6 +708,7 @@ static const struct usb_device_id option_ids[] = { | |
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) }, | |
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED) }, | |
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED) }, | |
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED) }, | |
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED3) }, | |
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED4) }, | |
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED5) }, | |
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c | |
index 3d8cda5..d6c2f8c 100644 | |
--- a/drivers/usb/serial/pl2303.c | |
+++ b/drivers/usb/serial/pl2303.c | |
@@ -421,7 +421,7 @@ static void pl2303_set_termios(struct tty_struct *tty, | |
control = priv->line_control; | |
if ((cflag & CBAUD) == B0) | |
priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); | |
- else | |
+ else if ((old_termios->c_cflag & CBAUD) == B0) | |
priv->line_control |= (CONTROL_DTR | CONTROL_RTS); | |
if (control != priv->line_control) { | |
control = priv->line_control; | |
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c | |
index fdae0a4..2bea36f 100644 | |
--- a/drivers/usb/serial/sierra.c | |
+++ b/drivers/usb/serial/sierra.c | |
@@ -289,6 +289,7 @@ static const struct usb_device_id id_table[] = { | |
{ USB_DEVICE(0x1199, 0x6856) }, /* Sierra Wireless AirCard 881 U */ | |
{ USB_DEVICE(0x1199, 0x6859) }, /* Sierra Wireless AirCard 885 E */ | |
{ USB_DEVICE(0x1199, 0x685A) }, /* Sierra Wireless AirCard 885 E */ | |
+ { USB_DEVICE(0x1199, 0x68A2) }, /* Sierra Wireless MC7710 */ | |
/* Sierra Wireless C885 */ | |
{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6880, 0xFF, 0xFF, 0xFF)}, | |
/* Sierra Wireless C888, Air Card 501, USB 303, USB 304 */ | |
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c | |
index 611b206..584f23c 100644 | |
--- a/drivers/usb/serial/usb-serial.c | |
+++ b/drivers/usb/serial/usb-serial.c | |
@@ -1063,6 +1063,12 @@ int usb_serial_probe(struct usb_interface *interface, | |
serial->attached = 1; | |
} | |
+ /* Avoid race with tty_open and serial_install by setting the | |
+ * disconnected flag and not clearing it until all ports have been | |
+ * registered. | |
+ */ | |
+ serial->disconnected = 1; | |
+ | |
if (get_free_serial(serial, num_ports, &minor) == NULL) { | |
dev_err(&interface->dev, "No more free serial devices\n"); | |
goto probe_error; | |
@@ -1087,6 +1093,8 @@ int usb_serial_probe(struct usb_interface *interface, | |
} | |
} | |
+ serial->disconnected = 0; | |
+ | |
usb_serial_console_init(debug, minor); | |
exit: | |
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c | |
index e7f69ef..8408543 100644 | |
--- a/drivers/video/uvesafb.c | |
+++ b/drivers/video/uvesafb.c | |
@@ -815,8 +815,15 @@ static int __devinit uvesafb_vbe_init(struct fb_info *info) | |
par->pmi_setpal = pmi_setpal; | |
par->ypan = ypan; | |
- if (par->pmi_setpal || par->ypan) | |
- uvesafb_vbe_getpmi(task, par); | |
+ if (par->pmi_setpal || par->ypan) { | |
+ if (__supported_pte_mask & _PAGE_NX) { | |
+ par->pmi_setpal = par->ypan = 0; | |
+ printk(KERN_WARNING "uvesafb: NX protection is actively." | |
+ "We have better not to use the PMI.\n"); | |
+ } else { | |
+ uvesafb_vbe_getpmi(task, par); | |
+ } | |
+ } | |
#else | |
/* The protected mode interface is not available on non-x86. */ | |
par->pmi_setpal = par->ypan = 0; | |
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c | |
index 0436c12..56136d90 100644 | |
--- a/fs/btrfs/backref.c | |
+++ b/fs/btrfs/backref.c | |
@@ -116,6 +116,7 @@ add_parent: | |
* to a logical address | |
*/ | |
static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, | |
+ int search_commit_root, | |
struct __prelim_ref *ref, | |
struct ulist *parents) | |
{ | |
@@ -131,6 +132,7 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, | |
path = btrfs_alloc_path(); | |
if (!path) | |
return -ENOMEM; | |
+ path->search_commit_root = !!search_commit_root; | |
root_key.objectid = ref->root_id; | |
root_key.type = BTRFS_ROOT_ITEM_KEY; | |
@@ -188,6 +190,7 @@ out: | |
* resolve all indirect backrefs from the list | |
*/ | |
static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info, | |
+ int search_commit_root, | |
struct list_head *head) | |
{ | |
int err; | |
@@ -212,7 +215,8 @@ static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info, | |
continue; | |
if (ref->count == 0) | |
continue; | |
- err = __resolve_indirect_ref(fs_info, ref, parents); | |
+ err = __resolve_indirect_ref(fs_info, search_commit_root, | |
+ ref, parents); | |
if (err) { | |
if (ret == 0) | |
ret = err; | |
@@ -586,6 +590,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans, | |
struct btrfs_delayed_ref_head *head; | |
int info_level = 0; | |
int ret; | |
+ int search_commit_root = (trans == BTRFS_BACKREF_SEARCH_COMMIT_ROOT); | |
struct list_head prefs_delayed; | |
struct list_head prefs; | |
struct __prelim_ref *ref; | |
@@ -600,6 +605,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans, | |
path = btrfs_alloc_path(); | |
if (!path) | |
return -ENOMEM; | |
+ path->search_commit_root = !!search_commit_root; | |
/* | |
* grab both a lock on the path and a lock on the delayed ref head. | |
@@ -614,35 +620,39 @@ again: | |
goto out; | |
BUG_ON(ret == 0); | |
- /* | |
- * look if there are updates for this ref queued and lock the head | |
- */ | |
- delayed_refs = &trans->transaction->delayed_refs; | |
- spin_lock(&delayed_refs->lock); | |
- head = btrfs_find_delayed_ref_head(trans, bytenr); | |
- if (head) { | |
- if (!mutex_trylock(&head->mutex)) { | |
- atomic_inc(&head->node.refs); | |
- spin_unlock(&delayed_refs->lock); | |
- | |
- btrfs_release_path(path); | |
- | |
- /* | |
- * Mutex was contended, block until it's | |
- * released and try again | |
- */ | |
- mutex_lock(&head->mutex); | |
- mutex_unlock(&head->mutex); | |
- btrfs_put_delayed_ref(&head->node); | |
- goto again; | |
- } | |
- ret = __add_delayed_refs(head, seq, &info_key, &prefs_delayed); | |
- if (ret) { | |
- spin_unlock(&delayed_refs->lock); | |
- goto out; | |
+ if (trans != BTRFS_BACKREF_SEARCH_COMMIT_ROOT) { | |
+ /* | |
+ * look if there are updates for this ref queued and lock the | |
+ * head | |
+ */ | |
+ delayed_refs = &trans->transaction->delayed_refs; | |
+ spin_lock(&delayed_refs->lock); | |
+ head = btrfs_find_delayed_ref_head(trans, bytenr); | |
+ if (head) { | |
+ if (!mutex_trylock(&head->mutex)) { | |
+ atomic_inc(&head->node.refs); | |
+ spin_unlock(&delayed_refs->lock); | |
+ | |
+ btrfs_release_path(path); | |
+ | |
+ /* | |
+ * Mutex was contended, block until it's | |
+ * released and try again | |
+ */ | |
+ mutex_lock(&head->mutex); | |
+ mutex_unlock(&head->mutex); | |
+ btrfs_put_delayed_ref(&head->node); | |
+ goto again; | |
+ } | |
+ ret = __add_delayed_refs(head, seq, &info_key, | |
+ &prefs_delayed); | |
+ if (ret) { | |
+ spin_unlock(&delayed_refs->lock); | |
+ goto out; | |
+ } | |
} | |
+ spin_unlock(&delayed_refs->lock); | |
} | |
- spin_unlock(&delayed_refs->lock); | |
if (path->slots[0]) { | |
struct extent_buffer *leaf; | |
@@ -679,7 +689,7 @@ again: | |
if (ret) | |
goto out; | |
- ret = __resolve_indirect_refs(fs_info, &prefs); | |
+ ret = __resolve_indirect_refs(fs_info, search_commit_root, &prefs); | |
if (ret) | |
goto out; | |
@@ -1074,8 +1084,7 @@ int tree_backref_for_extent(unsigned long *ptr, struct extent_buffer *eb, | |
return 0; | |
} | |
-static int iterate_leaf_refs(struct btrfs_fs_info *fs_info, | |
- struct btrfs_path *path, u64 logical, | |
+static int iterate_leaf_refs(struct btrfs_fs_info *fs_info, u64 logical, | |
u64 orig_extent_item_objectid, | |
u64 extent_item_pos, u64 root, | |
iterate_extent_inodes_t *iterate, void *ctx) | |
@@ -1143,35 +1152,38 @@ static int iterate_leaf_refs(struct btrfs_fs_info *fs_info, | |
* calls iterate() for every inode that references the extent identified by | |
* the given parameters. | |
* when the iterator function returns a non-zero value, iteration stops. | |
- * path is guaranteed to be in released state when iterate() is called. | |
*/ | |
int iterate_extent_inodes(struct btrfs_fs_info *fs_info, | |
- struct btrfs_path *path, | |
u64 extent_item_objectid, u64 extent_item_pos, | |
+ int search_commit_root, | |
iterate_extent_inodes_t *iterate, void *ctx) | |
{ | |
int ret; | |
struct list_head data_refs = LIST_HEAD_INIT(data_refs); | |
struct list_head shared_refs = LIST_HEAD_INIT(shared_refs); | |
struct btrfs_trans_handle *trans; | |
- struct ulist *refs; | |
- struct ulist *roots; | |
+ struct ulist *refs = NULL; | |
+ struct ulist *roots = NULL; | |
struct ulist_node *ref_node = NULL; | |
struct ulist_node *root_node = NULL; | |
struct seq_list seq_elem; | |
- struct btrfs_delayed_ref_root *delayed_refs; | |
- | |
- trans = btrfs_join_transaction(fs_info->extent_root); | |
- if (IS_ERR(trans)) | |
- return PTR_ERR(trans); | |
+ struct btrfs_delayed_ref_root *delayed_refs = NULL; | |
pr_debug("resolving all inodes for extent %llu\n", | |
extent_item_objectid); | |
- delayed_refs = &trans->transaction->delayed_refs; | |
- spin_lock(&delayed_refs->lock); | |
- btrfs_get_delayed_seq(delayed_refs, &seq_elem); | |
- spin_unlock(&delayed_refs->lock); | |
+ if (search_commit_root) { | |
+ trans = BTRFS_BACKREF_SEARCH_COMMIT_ROOT; | |
+ } else { | |
+ trans = btrfs_join_transaction(fs_info->extent_root); | |
+ if (IS_ERR(trans)) | |
+ return PTR_ERR(trans); | |
+ | |
+ delayed_refs = &trans->transaction->delayed_refs; | |
+ spin_lock(&delayed_refs->lock); | |
+ btrfs_get_delayed_seq(delayed_refs, &seq_elem); | |
+ spin_unlock(&delayed_refs->lock); | |
+ } | |
ret = btrfs_find_all_leafs(trans, fs_info, extent_item_objectid, | |
extent_item_pos, seq_elem.seq, | |
@@ -1188,7 +1200,7 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info, | |
while (!ret && (root_node = ulist_next(roots, root_node))) { | |
pr_debug("root %llu references leaf %llu\n", | |
root_node->val, ref_node->val); | |
- ret = iterate_leaf_refs(fs_info, path, ref_node->val, | |
+ ret = iterate_leaf_refs(fs_info, ref_node->val, | |
extent_item_objectid, | |
extent_item_pos, root_node->val, | |
iterate, ctx); | |
@@ -1198,8 +1210,11 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info, | |
ulist_free(refs); | |
ulist_free(roots); | |
out: | |
- btrfs_put_delayed_seq(delayed_refs, &seq_elem); | |
- btrfs_end_transaction(trans, fs_info->extent_root); | |
+ if (!search_commit_root) { | |
+ btrfs_put_delayed_seq(delayed_refs, &seq_elem); | |
+ btrfs_end_transaction(trans, fs_info->extent_root); | |
+ } | |
+ | |
return ret; | |
} | |
@@ -1210,6 +1225,7 @@ int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info, | |
int ret; | |
u64 extent_item_pos; | |
struct btrfs_key found_key; | |
+ int search_commit_root = path->search_commit_root; | |
ret = extent_from_logical(fs_info, logical, path, | |
&found_key); | |
@@ -1220,8 +1236,9 @@ int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info, | |
return ret; | |
extent_item_pos = logical - found_key.objectid; | |
- ret = iterate_extent_inodes(fs_info, path, found_key.objectid, | |
- extent_item_pos, iterate, ctx); | |
+ ret = iterate_extent_inodes(fs_info, found_key.objectid, | |
+ extent_item_pos, search_commit_root, | |
+ iterate, ctx); | |
return ret; | |
} | |
diff --git a/fs/btrfs/backref.h b/fs/btrfs/backref.h | |
index d00dfa9..57ea2e9 100644 | |
--- a/fs/btrfs/backref.h | |
+++ b/fs/btrfs/backref.h | |
@@ -22,6 +22,8 @@ | |
#include "ioctl.h" | |
#include "ulist.h" | |
+#define BTRFS_BACKREF_SEARCH_COMMIT_ROOT ((struct btrfs_trans_handle *)0) | |
+ | |
struct inode_fs_paths { | |
struct btrfs_path *btrfs_path; | |
struct btrfs_root *fs_root; | |
@@ -44,9 +46,8 @@ int tree_backref_for_extent(unsigned long *ptr, struct extent_buffer *eb, | |
u64 *out_root, u8 *out_level); | |
int iterate_extent_inodes(struct btrfs_fs_info *fs_info, | |
- struct btrfs_path *path, | |
u64 extent_item_objectid, | |
- u64 extent_offset, | |
+ u64 extent_offset, int search_commit_root, | |
iterate_extent_inodes_t *iterate, void *ctx); | |
int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info, | |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c | |
index 37e0a80..f6f584f 100644 | |
--- a/fs/btrfs/extent-tree.c | |
+++ b/fs/btrfs/extent-tree.c | |
@@ -4110,7 +4110,7 @@ static u64 calc_global_metadata_size(struct btrfs_fs_info *fs_info) | |
num_bytes += div64_u64(data_used + meta_used, 50); | |
if (num_bytes * 3 > meta_used) | |
- num_bytes = div64_u64(meta_used, 3) * 2; | |
+ num_bytes = div64_u64(meta_used, 3); | |
return ALIGN(num_bytes, fs_info->extent_root->leafsize << 10); | |
} | |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c | |
index d8b5471..1b36f19 100644 | |
--- a/fs/btrfs/ioctl.c | |
+++ b/fs/btrfs/ioctl.c | |
@@ -3066,8 +3066,8 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root, | |
goto out; | |
extent_item_pos = loi->logical - key.objectid; | |
- ret = iterate_extent_inodes(root->fs_info, path, key.objectid, | |
- extent_item_pos, build_ino_list, | |
+ ret = iterate_extent_inodes(root->fs_info, key.objectid, | |
+ extent_item_pos, 0, build_ino_list, | |
inodes); | |
if (ret < 0) | |
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c | |
index abc0fbf..b9b84cd 100644 | |
--- a/fs/btrfs/scrub.c | |
+++ b/fs/btrfs/scrub.c | |
@@ -352,8 +352,8 @@ static void scrub_print_warning(const char *errstr, struct scrub_bio *sbio, | |
} while (ret != 1); | |
} else { | |
swarn.path = path; | |
- iterate_extent_inodes(fs_info, path, found_key.objectid, | |
- extent_item_pos, | |
+ iterate_extent_inodes(fs_info, found_key.objectid, | |
+ extent_item_pos, 1, | |
scrub_print_warning_inode, &swarn); | |
} | |
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h | |
index 3ce6a0c..9983ba8 100644 | |
--- a/fs/ext4/ext4.h | |
+++ b/fs/ext4/ext4.h | |
@@ -1195,9 +1195,6 @@ struct ext4_sb_info { | |
unsigned long s_ext_blocks; | |
unsigned long s_ext_extents; | |
#endif | |
- /* ext4 extent cache stats */ | |
- unsigned long extent_cache_hits; | |
- unsigned long extent_cache_misses; | |
/* for buddy allocator */ | |
struct ext4_group_info ***s_group_info; | |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c | |
index 4394a757..8a63efb 100644 | |
--- a/fs/ext4/extents.c | |
+++ b/fs/ext4/extents.c | |
@@ -2051,10 +2051,6 @@ static int ext4_ext_check_cache(struct inode *inode, ext4_lblk_t block, | |
ret = 1; | |
} | |
errout: | |
- if (!ret) | |
- sbi->extent_cache_misses++; | |
- else | |
- sbi->extent_cache_hits++; | |
trace_ext4_ext_in_cache(inode, block, ret); | |
spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); | |
return ret; | |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c | |
index a089366..211e085 100644 | |
--- a/fs/ext4/super.c | |
+++ b/fs/ext4/super.c | |
@@ -2503,18 +2503,6 @@ static ssize_t lifetime_write_kbytes_show(struct ext4_attr *a, | |
EXT4_SB(sb)->s_sectors_written_start) >> 1))); | |
} | |
-static ssize_t extent_cache_hits_show(struct ext4_attr *a, | |
- struct ext4_sb_info *sbi, char *buf) | |
-{ | |
- return snprintf(buf, PAGE_SIZE, "%lu\n", sbi->extent_cache_hits); | |
-} | |
- | |
-static ssize_t extent_cache_misses_show(struct ext4_attr *a, | |
- struct ext4_sb_info *sbi, char *buf) | |
-{ | |
- return snprintf(buf, PAGE_SIZE, "%lu\n", sbi->extent_cache_misses); | |
-} | |
- | |
static ssize_t inode_readahead_blks_store(struct ext4_attr *a, | |
struct ext4_sb_info *sbi, | |
const char *buf, size_t count) | |
@@ -2572,8 +2560,6 @@ static struct ext4_attr ext4_attr_##name = __ATTR(name, mode, show, store) | |
EXT4_RO_ATTR(delayed_allocation_blocks); | |
EXT4_RO_ATTR(session_write_kbytes); | |
EXT4_RO_ATTR(lifetime_write_kbytes); | |
-EXT4_RO_ATTR(extent_cache_hits); | |
-EXT4_RO_ATTR(extent_cache_misses); | |
EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, sbi_ui_show, | |
inode_readahead_blks_store, s_inode_readahead_blks); | |
EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal); | |
@@ -2589,8 +2575,6 @@ static struct attribute *ext4_attrs[] = { | |
ATTR_LIST(delayed_allocation_blocks), | |
ATTR_LIST(session_write_kbytes), | |
ATTR_LIST(lifetime_write_kbytes), | |
- ATTR_LIST(extent_cache_hits), | |
- ATTR_LIST(extent_cache_misses), | |
ATTR_LIST(inode_readahead_blks), | |
ATTR_LIST(inode_goal), | |
ATTR_LIST(mb_stats), | |
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h | |
index c91ace7..cbb3d12 100644 | |
--- a/include/linux/serial_core.h | |
+++ b/include/linux/serial_core.h | |
@@ -355,7 +355,7 @@ struct uart_port { | |
#define UPF_CONS_FLOW ((__force upf_t) (1 << 23)) | |
#define UPF_SHARE_IRQ ((__force upf_t) (1 << 24)) | |
#define UPF_EXAR_EFR ((__force upf_t) (1 << 25)) | |
-#define UPF_IIR_ONCE ((__force upf_t) (1 << 26)) | |
+#define UPF_BUG_THRE ((__force upf_t) (1 << 26)) | |
/* The exact UART type is known and should not be probed. */ | |
#define UPF_FIXED_TYPE ((__force upf_t) (1 << 27)) | |
#define UPF_BOOT_AUTOCONF ((__force upf_t) (1 << 28)) | |
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h | |
index 00596e8..8a0222b 100644 | |
--- a/include/net/bluetooth/hci.h | |
+++ b/include/net/bluetooth/hci.h | |
@@ -84,6 +84,7 @@ enum { | |
HCI_SERVICE_CACHE, | |
HCI_LINK_KEYS, | |
HCI_DEBUG_KEYS, | |
+ HCI_UNREGISTER, | |
HCI_RESET, | |
}; | |
diff --git a/kernel/futex.c b/kernel/futex.c | |
index 0677023..866c9d5 100644 | |
--- a/kernel/futex.c | |
+++ b/kernel/futex.c | |
@@ -59,6 +59,7 @@ | |
#include <linux/magic.h> | |
#include <linux/pid.h> | |
#include <linux/nsproxy.h> | |
+#include <linux/ptrace.h> | |
#include <asm/futex.h> | |
@@ -2443,40 +2444,29 @@ SYSCALL_DEFINE3(get_robust_list, int, pid, | |
{ | |
struct robust_list_head __user *head; | |
unsigned long ret; | |
- const struct cred *cred = current_cred(), *pcred; | |
+ struct task_struct *p; | |
if (!futex_cmpxchg_enabled) | |
return -ENOSYS; | |
+ rcu_read_lock(); | |
+ | |
+ ret = -ESRCH; | |
if (!pid) | |
- head = current->robust_list; | |
+ p = current; | |
else { | |
- struct task_struct *p; | |
- | |
- ret = -ESRCH; | |
- rcu_read_lock(); | |
p = find_task_by_vpid(pid); | |
if (!p) | |
goto err_unlock; | |
- ret = -EPERM; | |
- pcred = __task_cred(p); | |
- /* If victim is in different user_ns, then uids are not | |
- comparable, so we must have CAP_SYS_PTRACE */ | |
- if (cred->user->user_ns != pcred->user->user_ns) { | |
- if (!ns_capable(pcred->user->user_ns, CAP_SYS_PTRACE)) | |
- goto err_unlock; | |
- goto ok; | |
- } | |
- /* If victim is in same user_ns, then uids are comparable */ | |
- if (cred->euid != pcred->euid && | |
- cred->euid != pcred->uid && | |
- !ns_capable(pcred->user->user_ns, CAP_SYS_PTRACE)) | |
- goto err_unlock; | |
-ok: | |
- head = p->robust_list; | |
- rcu_read_unlock(); | |
} | |
+ ret = -EPERM; | |
+ if (!ptrace_may_access(p, PTRACE_MODE_READ)) | |
+ goto err_unlock; | |
+ | |
+ head = p->robust_list; | |
+ rcu_read_unlock(); | |
+ | |
if (put_user(sizeof(*head), len_ptr)) | |
return -EFAULT; | |
return put_user(head, head_ptr); | |
diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c | |
index 5f9e689..a9642d5 100644 | |
--- a/kernel/futex_compat.c | |
+++ b/kernel/futex_compat.c | |
@@ -10,6 +10,7 @@ | |
#include <linux/compat.h> | |
#include <linux/nsproxy.h> | |
#include <linux/futex.h> | |
+#include <linux/ptrace.h> | |
#include <asm/uaccess.h> | |
@@ -136,40 +137,29 @@ compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr, | |
{ | |
struct compat_robust_list_head __user *head; | |
unsigned long ret; | |
- const struct cred *cred = current_cred(), *pcred; | |
+ struct task_struct *p; | |
if (!futex_cmpxchg_enabled) | |
return -ENOSYS; | |
+ rcu_read_lock(); | |
+ | |
+ ret = -ESRCH; | |
if (!pid) | |
- head = current->compat_robust_list; | |
+ p = current; | |
else { | |
- struct task_struct *p; | |
- | |
- ret = -ESRCH; | |
- rcu_read_lock(); | |
p = find_task_by_vpid(pid); | |
if (!p) | |
goto err_unlock; | |
- ret = -EPERM; | |
- pcred = __task_cred(p); | |
- /* If victim is in different user_ns, then uids are not | |
- comparable, so we must have CAP_SYS_PTRACE */ | |
- if (cred->user->user_ns != pcred->user->user_ns) { | |
- if (!ns_capable(pcred->user->user_ns, CAP_SYS_PTRACE)) | |
- goto err_unlock; | |
- goto ok; | |
- } | |
- /* If victim is in same user_ns, then uids are comparable */ | |
- if (cred->euid != pcred->euid && | |
- cred->euid != pcred->uid && | |
- !ns_capable(pcred->user->user_ns, CAP_SYS_PTRACE)) | |
- goto err_unlock; | |
-ok: | |
- head = p->compat_robust_list; | |
- rcu_read_unlock(); | |
} | |
+ ret = -EPERM; | |
+ if (!ptrace_may_access(p, PTRACE_MODE_READ)) | |
+ goto err_unlock; | |
+ | |
+ head = p->compat_robust_list; | |
+ rcu_read_unlock(); | |
+ | |
if (put_user(sizeof(*head), len_ptr)) | |
return -EFAULT; | |
return put_user(ptr_to_compat(head), head_ptr); | |
diff --git a/kernel/kmod.c b/kernel/kmod.c | |
index cb2eacb..53800a6 100644 | |
--- a/kernel/kmod.c | |
+++ b/kernel/kmod.c | |
@@ -379,6 +379,7 @@ void __usermodehelper_set_disable_depth(enum umh_disable_depth depth) | |
wake_up(&usermodehelper_disabled_waitq); | |
up_write(&umhelper_sem); | |
} | |
+EXPORT_SYMBOL_GPL(__usermodehelper_set_disable_depth); | |
/** | |
* __usermodehelper_disable - Prevent new helpers from being started. | |
@@ -412,7 +413,7 @@ int __usermodehelper_disable(enum umh_disable_depth depth) | |
__usermodehelper_set_disable_depth(UMH_ENABLED); | |
return -EAGAIN; | |
} | |
-EXPORT_SYMBOL_GPL(usermodehelper_disable); | |
+EXPORT_SYMBOL_GPL(__usermodehelper_disable); | |
static void helper_lock(void) | |
{ | |
diff --git a/kernel/panic.c b/kernel/panic.c | |
index 80aed44..8ed89a1 100644 | |
--- a/kernel/panic.c | |
+++ b/kernel/panic.c | |
@@ -97,7 +97,7 @@ void panic(const char *fmt, ...) | |
/* | |
* Avoid nested stack-dumping if a panic occurs during oops processing | |
*/ | |
- if (!oops_in_progress) | |
+ if (!test_taint(TAINT_DIE) && oops_in_progress <= 1) | |
dump_stack(); | |
#endif | |
diff --git a/kernel/power/user.c b/kernel/power/user.c | |
index 7ee517b..a79d572 100644 | |
--- a/kernel/power/user.c | |
+++ b/kernel/power/user.c | |
@@ -224,8 +224,14 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, | |
sys_sync(); | |
printk("done.\n"); | |
+ error = usermodehelper_disable(); | |
+ if (error) | |
+ break; | |
+ | |
error = freeze_processes(); | |
- if (!error) | |
+ if (error) | |
+ usermodehelper_enable(); | |
+ else | |
data->frozen = 1; | |
break; | |
@@ -234,6 +240,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, | |
break; | |
pm_restore_gfp_mask(); | |
thaw_processes(); | |
+ usermodehelper_enable(); | |
data->frozen = 0; | |
break; | |
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c | |
index 7656642..4aa1d7b 100644 | |
--- a/kernel/time/tick-sched.c | |
+++ b/kernel/time/tick-sched.c | |
@@ -538,9 +538,9 @@ static void tick_nohz_restart(struct tick_sched *ts, ktime_t now) | |
hrtimer_get_expires(&ts->sched_timer), 0)) | |
break; | |
} | |
- /* Update jiffies and reread time */ | |
- tick_do_update_jiffies64(now); | |
+ /* Reread time and update jiffies */ | |
now = ktime_get(); | |
+ tick_do_update_jiffies64(now); | |
} | |
} | |
diff --git a/mm/hugetlb.c b/mm/hugetlb.c | |
index a876871..a7cf829 100644 | |
--- a/mm/hugetlb.c | |
+++ b/mm/hugetlb.c | |
@@ -2700,6 +2700,7 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |
* so no worry about deadlock. | |
*/ | |
page = pte_page(entry); | |
+ get_page(page); | |
if (page != pagecache_page) | |
lock_page(page); | |
@@ -2731,6 +2732,7 @@ out_page_table_lock: | |
} | |
if (page != pagecache_page) | |
unlock_page(page); | |
+ put_page(page); | |
out_mutex: | |
mutex_unlock(&hugetlb_instantiation_mutex); | |
diff --git a/mm/memcontrol.c b/mm/memcontrol.c | |
index cd412fc..6fe7afe 100644 | |
--- a/mm/memcontrol.c | |
+++ b/mm/memcontrol.c | |
@@ -3350,6 +3350,7 @@ void mem_cgroup_replace_page_cache(struct page *oldpage, | |
* the newpage may be on LRU(or pagevec for LRU) already. We lock | |
* LRU while we overwrite pc->mem_cgroup. | |
*/ | |
+ pc = lookup_page_cgroup(newpage); | |
__mem_cgroup_commit_charge(memcg, newpage, 1, pc, type, true); | |
} | |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c | |
index 07bc69e..280953b 100644 | |
--- a/net/bluetooth/hci_conn.c | |
+++ b/net/bluetooth/hci_conn.c | |
@@ -279,7 +279,6 @@ static void hci_conn_timeout(struct work_struct *work) | |
{ | |
struct hci_conn *conn = container_of(work, struct hci_conn, | |
disc_work.work); | |
- struct hci_dev *hdev = conn->hdev; | |
__u8 reason; | |
BT_DBG("conn %p state %d", conn, conn->state); | |
@@ -287,8 +286,6 @@ static void hci_conn_timeout(struct work_struct *work) | |
if (atomic_read(&conn->refcnt)) | |
return; | |
- hci_dev_lock(hdev); | |
- | |
switch (conn->state) { | |
case BT_CONNECT: | |
case BT_CONNECT2: | |
@@ -308,8 +305,6 @@ static void hci_conn_timeout(struct work_struct *work) | |
conn->state = BT_CLOSED; | |
break; | |
} | |
- | |
- hci_dev_unlock(hdev); | |
} | |
/* Enter sniff mode */ | |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c | |
index 5aeb624..9a01451 100644 | |
--- a/net/bluetooth/hci_core.c | |
+++ b/net/bluetooth/hci_core.c | |
@@ -525,6 +525,11 @@ int hci_dev_open(__u16 dev) | |
hci_req_lock(hdev); | |
+ if (test_bit(HCI_UNREGISTER, &hdev->dev_flags)) { | |
+ ret = -ENODEV; | |
+ goto done; | |
+ } | |
+ | |
if (hdev->rfkill && rfkill_blocked(hdev->rfkill)) { | |
ret = -ERFKILL; | |
goto done; | |
@@ -1577,6 +1582,8 @@ void hci_unregister_dev(struct hci_dev *hdev) | |
BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); | |
+ set_bit(HCI_UNREGISTER, &hdev->dev_flags); | |
+ | |
write_lock(&hci_dev_list_lock); | |
list_del(&hdev->list); | |
write_unlock(&hci_dev_list_lock); | |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c | |
index 6ff1d81..d87e627 100644 | |
--- a/net/core/skbuff.c | |
+++ b/net/core/skbuff.c | |
@@ -532,8 +532,10 @@ static void skb_release_head_state(struct sk_buff *skb) | |
skb->destructor(skb); | |
} | |
#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) | |
- /* This should not happen. When it does, avoid memleak by restoring | |
- the chain of cb-backups. */ | |
+ /* | |
+ * This should not happen. When it does, avoid memleak by restoring | |
+ * the chain of cb-backups. | |
+ */ | |
while (skb->cb_next != NULL) { | |
if (net_ratelimit()) | |
printk(KERN_WARNING "IMQ: kfree_skb: skb->cb_next: " | |
@@ -541,7 +543,8 @@ static void skb_release_head_state(struct sk_buff *skb) | |
skb_restore_cb(skb); | |
} | |
- /* This should not happen either, nf_queue_entry is nullified in | |
+ /* | |
+ * This should not happen either, nf_queue_entry is nullified in | |
* imq_dev_xmit(). If we have non-NULL nf_queue_entry then we are | |
* leaking entry pointers, maybe memory. We don't know if this is | |
* pointer to already freed memory, or should this be freed. | |
@@ -549,7 +552,7 @@ static void skb_release_head_state(struct sk_buff *skb) | |
*/ | |
if (skb->nf_queue_entry && net_ratelimit()) | |
printk(KERN_WARNING | |
- "IMQ: kfree_skb: skb->nf_queue_entry != NULL"); | |
+ "IMQ: kfree_skb: skb->nf_queue_entry != NULL"); | |
#endif | |
#if IS_ENABLED(CONFIG_NF_CONNTRACK) | |
nf_conntrack_put(skb->nfct); | |
diff --git a/security/commoncap.c b/security/commoncap.c | |
index 7ce191e..b8d2bb9 100644 | |
--- a/security/commoncap.c | |
+++ b/security/commoncap.c | |
@@ -28,6 +28,7 @@ | |
#include <linux/prctl.h> | |
#include <linux/securebits.h> | |
#include <linux/user_namespace.h> | |
+#include <linux/personality.h> | |
/* | |
* If a non-root user executes a setuid-root binary in | |
@@ -504,6 +505,11 @@ int cap_bprm_set_creds(struct linux_binprm *bprm) | |
} | |
skip: | |
+ /* if we have fs caps, clear dangerous personality flags */ | |
+ if (!cap_issubset(new->cap_permitted, old->cap_permitted)) | |
+ bprm->per_clear |= PER_CLEAR_ON_SETID; | |
+ | |
+ | |
/* Don't let someone trace a set[ug]id/setpcap binary with the revised | |
* credentials unless they have the appropriate permit | |
*/ | |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c | |
index 602aae9..e5153ea 100644 | |
--- a/sound/pci/hda/patch_realtek.c | |
+++ b/sound/pci/hda/patch_realtek.c | |
@@ -4649,6 +4649,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { | |
ALC882_FIXUP_ACER_ASPIRE_4930G), | |
SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", ALC882_FIXUP_PB_M5210), | |
SND_PCI_QUIRK(0x1025, 0x0259, "Acer Aspire 5935", ALC889_FIXUP_DAC_ROUTE), | |
+ SND_PCI_QUIRK(0x1025, 0x026b, "Acer Aspire 8940G", ALC882_FIXUP_ACER_ASPIRE_8930G), | |
SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", ALC882_FIXUP_ACER_ASPIRE_7736), | |
SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_FIXUP_EAPD), | |
SND_PCI_QUIRK(0x1043, 0x1873, "ASUS W90V", ALC882_FIXUP_ASUS_W90V), | |
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c | |
index e11e482..a47a6f1 100644 | |
--- a/tools/perf/util/hist.c | |
+++ b/tools/perf/util/hist.c | |
@@ -230,6 +230,18 @@ struct hist_entry *__hists__add_entry(struct hists *hists, | |
if (!cmp) { | |
he->period += period; | |
++he->nr_events; | |
+ | |
+ /* If the map of an existing hist_entry has | |
+ * become out-of-date due to an exec() or | |
+ * similar, update it. Otherwise we will | |
+ * mis-adjust symbol addresses when computing | |
+ * the history counter to increment. | |
+ */ | |
+ if (he->ms.map != entry->ms.map) { | |
+ he->ms.map = entry->ms.map; | |
+ if (he->ms.map) | |
+ he->ms.map->referenced = true; | |
+ } | |
goto out; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment