aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-02-19 11:33:12 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-02-19 11:33:12 -0500
commitff5f16820f632079d5095884adc5d71ee3249fa4 (patch)
tree5f474546110a3c7c3194264978304d268a716840
parent409ee136f28f71cbec518cfc85a379a508ccbaa0 (diff)
parent12d319b920fa673a4d5e7c1785c5dc82dcd15257 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 fixes from Martin Schwidefsky: "Several bug fixes: - There are four different stack tracers, and three of them have bugs. For 4.5 the bugs are fixed and we prepare a cleanup patch for the next merge window. - Three bug fixes for the dasd driver in regard to parallel access volumes and the new max_dev_sectors block device queue limit - The irq restore optimization needs a fixup for memcpy_real - The diagnose trace code has a conflict with lockdep" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: s390/dasd: fix performance drop s390/maccess: reduce stnsm instructions s390/diag: avoid lockdep recursion s390/dasd: fix refcount for PAV reassignment s390/dasd: prevent incorrect length error under z/VM after PAV changes s390: fix DAT off memory access, e.g. on kdump s390/oprofile: fix address range for asynchronous stack s390/perf_event: fix address range for asynchronous stack s390/stacktrace: add save_stack_trace_regs() s390/stacktrace: save full stack traces s390/stacktrace: add missing end marker s390/stacktrace: fix address ranges for asynchronous and panic stack s390/stacktrace: fix save_stack_trace_tsk() for current task
-rw-r--r--arch/s390/kernel/perf_event.c8
-rw-r--r--arch/s390/kernel/stacktrace.c47
-rw-r--r--arch/s390/kernel/trace.c3
-rw-r--r--arch/s390/mm/maccess.c12
-rw-r--r--arch/s390/oprofile/backtrace.c8
-rw-r--r--drivers/s390/block/dasd.c1
-rw-r--r--drivers/s390/block/dasd_alias.c23
7 files changed, 73 insertions, 29 deletions
diff --git a/arch/s390/kernel/perf_event.c b/arch/s390/kernel/perf_event.c
index cfcba2dd9bb5..0943b11a2f6e 100644
--- a/arch/s390/kernel/perf_event.c
+++ b/arch/s390/kernel/perf_event.c
@@ -260,12 +260,13 @@ static unsigned long __store_trace(struct perf_callchain_entry *entry,
260void perf_callchain_kernel(struct perf_callchain_entry *entry, 260void perf_callchain_kernel(struct perf_callchain_entry *entry,
261 struct pt_regs *regs) 261 struct pt_regs *regs)
262{ 262{
263 unsigned long head; 263 unsigned long head, frame_size;
264 struct stack_frame *head_sf; 264 struct stack_frame *head_sf;
265 265
266 if (user_mode(regs)) 266 if (user_mode(regs))
267 return; 267 return;
268 268
269 frame_size = STACK_FRAME_OVERHEAD + sizeof(struct pt_regs);
269 head = regs->gprs[15]; 270 head = regs->gprs[15];
270 head_sf = (struct stack_frame *) head; 271 head_sf = (struct stack_frame *) head;
271 272
@@ -273,8 +274,9 @@ void perf_callchain_kernel(struct perf_callchain_entry *entry,
273 return; 274 return;
274 275
275 head = head_sf->back_chain; 276 head = head_sf->back_chain;
276 head = __store_trace(entry, head, S390_lowcore.async_stack - ASYNC_SIZE, 277 head = __store_trace(entry, head,
277 S390_lowcore.async_stack); 278 S390_lowcore.async_stack + frame_size - ASYNC_SIZE,
279 S390_lowcore.async_stack + frame_size);
278 280
279 __store_trace(entry, head, S390_lowcore.thread_info, 281 __store_trace(entry, head, S390_lowcore.thread_info,
280 S390_lowcore.thread_info + THREAD_SIZE); 282 S390_lowcore.thread_info + THREAD_SIZE);
diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c
index 5acba3cb7220..8f64ebd63767 100644
--- a/arch/s390/kernel/stacktrace.c
+++ b/arch/s390/kernel/stacktrace.c
@@ -59,26 +59,32 @@ static unsigned long save_context_stack(struct stack_trace *trace,
59 } 59 }
60} 60}
61 61
62void save_stack_trace(struct stack_trace *trace) 62static void __save_stack_trace(struct stack_trace *trace, unsigned long sp)
63{ 63{
64 register unsigned long sp asm ("15"); 64 unsigned long new_sp, frame_size;
65 unsigned long orig_sp, new_sp;
66 65
67 orig_sp = sp; 66 frame_size = STACK_FRAME_OVERHEAD + sizeof(struct pt_regs);
68 new_sp = save_context_stack(trace, orig_sp, 67 new_sp = save_context_stack(trace, sp,
69 S390_lowcore.panic_stack - PAGE_SIZE, 68 S390_lowcore.panic_stack + frame_size - PAGE_SIZE,
70 S390_lowcore.panic_stack, 1); 69 S390_lowcore.panic_stack + frame_size, 1);
71 if (new_sp != orig_sp)
72 return;
73 new_sp = save_context_stack(trace, new_sp, 70 new_sp = save_context_stack(trace, new_sp,
74 S390_lowcore.async_stack - ASYNC_SIZE, 71 S390_lowcore.async_stack + frame_size - ASYNC_SIZE,
75 S390_lowcore.async_stack, 1); 72 S390_lowcore.async_stack + frame_size, 1);
76 if (new_sp != orig_sp)
77 return;
78 save_context_stack(trace, new_sp, 73 save_context_stack(trace, new_sp,
79 S390_lowcore.thread_info, 74 S390_lowcore.thread_info,
80 S390_lowcore.thread_info + THREAD_SIZE, 1); 75 S390_lowcore.thread_info + THREAD_SIZE, 1);
81} 76}
77
78void save_stack_trace(struct stack_trace *trace)
79{
80 register unsigned long r15 asm ("15");
81 unsigned long sp;
82
83 sp = r15;
84 __save_stack_trace(trace, sp);
85 if (trace->nr_entries < trace->max_entries)
86 trace->entries[trace->nr_entries++] = ULONG_MAX;
87}
82EXPORT_SYMBOL_GPL(save_stack_trace); 88EXPORT_SYMBOL_GPL(save_stack_trace);
83 89
84void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) 90void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
@@ -86,6 +92,10 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
86 unsigned long sp, low, high; 92 unsigned long sp, low, high;
87 93
88 sp = tsk->thread.ksp; 94 sp = tsk->thread.ksp;
95 if (tsk == current) {
96 /* Get current stack pointer. */
97 asm volatile("la %0,0(15)" : "=a" (sp));
98 }
89 low = (unsigned long) task_stack_page(tsk); 99 low = (unsigned long) task_stack_page(tsk);
90 high = (unsigned long) task_pt_regs(tsk); 100 high = (unsigned long) task_pt_regs(tsk);
91 save_context_stack(trace, sp, low, high, 0); 101 save_context_stack(trace, sp, low, high, 0);
@@ -93,3 +103,14 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
93 trace->entries[trace->nr_entries++] = ULONG_MAX; 103 trace->entries[trace->nr_entries++] = ULONG_MAX;
94} 104}
95EXPORT_SYMBOL_GPL(save_stack_trace_tsk); 105EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
106
107void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
108{
109 unsigned long sp;
110
111 sp = kernel_stack_pointer(regs);
112 __save_stack_trace(trace, sp);
113 if (trace->nr_entries < trace->max_entries)
114 trace->entries[trace->nr_entries++] = ULONG_MAX;
115}
116EXPORT_SYMBOL_GPL(save_stack_trace_regs);
diff --git a/arch/s390/kernel/trace.c b/arch/s390/kernel/trace.c
index 21a5df99552b..dde7654f5c68 100644
--- a/arch/s390/kernel/trace.c
+++ b/arch/s390/kernel/trace.c
@@ -18,6 +18,9 @@ void trace_s390_diagnose_norecursion(int diag_nr)
18 unsigned long flags; 18 unsigned long flags;
19 unsigned int *depth; 19 unsigned int *depth;
20 20
21 /* Avoid lockdep recursion. */
22 if (IS_ENABLED(CONFIG_LOCKDEP))
23 return;
21 local_irq_save(flags); 24 local_irq_save(flags);
22 depth = this_cpu_ptr(&diagnose_trace_depth); 25 depth = this_cpu_ptr(&diagnose_trace_depth);
23 if (*depth == 0) { 26 if (*depth == 0) {
diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c
index fec59c067d0d..792f9c63fbca 100644
--- a/arch/s390/mm/maccess.c
+++ b/arch/s390/mm/maccess.c
@@ -93,15 +93,19 @@ static int __memcpy_real(void *dest, void *src, size_t count)
93 */ 93 */
94int memcpy_real(void *dest, void *src, size_t count) 94int memcpy_real(void *dest, void *src, size_t count)
95{ 95{
96 int irqs_disabled, rc;
96 unsigned long flags; 97 unsigned long flags;
97 int rc;
98 98
99 if (!count) 99 if (!count)
100 return 0; 100 return 0;
101 local_irq_save(flags); 101 flags = __arch_local_irq_stnsm(0xf8UL);
102 __arch_local_irq_stnsm(0xfbUL); 102 irqs_disabled = arch_irqs_disabled_flags(flags);
103 if (!irqs_disabled)
104 trace_hardirqs_off();
103 rc = __memcpy_real(dest, src, count); 105 rc = __memcpy_real(dest, src, count);
104 local_irq_restore(flags); 106 if (!irqs_disabled)
107 trace_hardirqs_on();
108 __arch_local_irq_ssm(flags);
105 return rc; 109 return rc;
106} 110}
107 111
diff --git a/arch/s390/oprofile/backtrace.c b/arch/s390/oprofile/backtrace.c
index fe0bfe370c45..1884e1759529 100644
--- a/arch/s390/oprofile/backtrace.c
+++ b/arch/s390/oprofile/backtrace.c
@@ -54,12 +54,13 @@ __show_trace(unsigned int *depth, unsigned long sp,
54 54
55void s390_backtrace(struct pt_regs * const regs, unsigned int depth) 55void s390_backtrace(struct pt_regs * const regs, unsigned int depth)
56{ 56{
57 unsigned long head; 57 unsigned long head, frame_size;
58 struct stack_frame* head_sf; 58 struct stack_frame* head_sf;
59 59
60 if (user_mode(regs)) 60 if (user_mode(regs))
61 return; 61 return;
62 62
63 frame_size = STACK_FRAME_OVERHEAD + sizeof(struct pt_regs);
63 head = regs->gprs[15]; 64 head = regs->gprs[15];
64 head_sf = (struct stack_frame*)head; 65 head_sf = (struct stack_frame*)head;
65 66
@@ -68,8 +69,9 @@ void s390_backtrace(struct pt_regs * const regs, unsigned int depth)
68 69
69 head = head_sf->back_chain; 70 head = head_sf->back_chain;
70 71
71 head = __show_trace(&depth, head, S390_lowcore.async_stack - ASYNC_SIZE, 72 head = __show_trace(&depth, head,
72 S390_lowcore.async_stack); 73 S390_lowcore.async_stack + frame_size - ASYNC_SIZE,
74 S390_lowcore.async_stack + frame_size);
73 75
74 __show_trace(&depth, head, S390_lowcore.thread_info, 76 __show_trace(&depth, head, S390_lowcore.thread_info,
75 S390_lowcore.thread_info + THREAD_SIZE); 77 S390_lowcore.thread_info + THREAD_SIZE);
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 41605dac8309..c78db05e75b1 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -3035,6 +3035,7 @@ static void dasd_setup_queue(struct dasd_block *block)
3035 max = block->base->discipline->max_blocks << block->s2b_shift; 3035 max = block->base->discipline->max_blocks << block->s2b_shift;
3036 } 3036 }
3037 queue_flag_set_unlocked(QUEUE_FLAG_NONROT, block->request_queue); 3037 queue_flag_set_unlocked(QUEUE_FLAG_NONROT, block->request_queue);
3038 block->request_queue->limits.max_dev_sectors = max;
3038 blk_queue_logical_block_size(block->request_queue, 3039 blk_queue_logical_block_size(block->request_queue,
3039 block->bp_block); 3040 block->bp_block);
3040 blk_queue_max_hw_sectors(block->request_queue, max); 3041 blk_queue_max_hw_sectors(block->request_queue, max);
diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c
index 184b1dbeb554..286782c60da4 100644
--- a/drivers/s390/block/dasd_alias.c
+++ b/drivers/s390/block/dasd_alias.c
@@ -264,8 +264,10 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device)
264 spin_unlock_irqrestore(&lcu->lock, flags); 264 spin_unlock_irqrestore(&lcu->lock, flags);
265 cancel_work_sync(&lcu->suc_data.worker); 265 cancel_work_sync(&lcu->suc_data.worker);
266 spin_lock_irqsave(&lcu->lock, flags); 266 spin_lock_irqsave(&lcu->lock, flags);
267 if (device == lcu->suc_data.device) 267 if (device == lcu->suc_data.device) {
268 dasd_put_device(device);
268 lcu->suc_data.device = NULL; 269 lcu->suc_data.device = NULL;
270 }
269 } 271 }
270 was_pending = 0; 272 was_pending = 0;
271 if (device == lcu->ruac_data.device) { 273 if (device == lcu->ruac_data.device) {
@@ -273,8 +275,10 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device)
273 was_pending = 1; 275 was_pending = 1;
274 cancel_delayed_work_sync(&lcu->ruac_data.dwork); 276 cancel_delayed_work_sync(&lcu->ruac_data.dwork);
275 spin_lock_irqsave(&lcu->lock, flags); 277 spin_lock_irqsave(&lcu->lock, flags);
276 if (device == lcu->ruac_data.device) 278 if (device == lcu->ruac_data.device) {
279 dasd_put_device(device);
277 lcu->ruac_data.device = NULL; 280 lcu->ruac_data.device = NULL;
281 }
278 } 282 }
279 private->lcu = NULL; 283 private->lcu = NULL;
280 spin_unlock_irqrestore(&lcu->lock, flags); 284 spin_unlock_irqrestore(&lcu->lock, flags);
@@ -549,8 +553,10 @@ static void lcu_update_work(struct work_struct *work)
549 if ((rc && (rc != -EOPNOTSUPP)) || (lcu->flags & NEED_UAC_UPDATE)) { 553 if ((rc && (rc != -EOPNOTSUPP)) || (lcu->flags & NEED_UAC_UPDATE)) {
550 DBF_DEV_EVENT(DBF_WARNING, device, "could not update" 554 DBF_DEV_EVENT(DBF_WARNING, device, "could not update"
551 " alias data in lcu (rc = %d), retry later", rc); 555 " alias data in lcu (rc = %d), retry later", rc);
552 schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ); 556 if (!schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ))
557 dasd_put_device(device);
553 } else { 558 } else {
559 dasd_put_device(device);
554 lcu->ruac_data.device = NULL; 560 lcu->ruac_data.device = NULL;
555 lcu->flags &= ~UPDATE_PENDING; 561 lcu->flags &= ~UPDATE_PENDING;
556 } 562 }
@@ -593,8 +599,10 @@ static int _schedule_lcu_update(struct alias_lcu *lcu,
593 */ 599 */
594 if (!usedev) 600 if (!usedev)
595 return -EINVAL; 601 return -EINVAL;
602 dasd_get_device(usedev);
596 lcu->ruac_data.device = usedev; 603 lcu->ruac_data.device = usedev;
597 schedule_delayed_work(&lcu->ruac_data.dwork, 0); 604 if (!schedule_delayed_work(&lcu->ruac_data.dwork, 0))
605 dasd_put_device(usedev);
598 return 0; 606 return 0;
599} 607}
600 608
@@ -723,7 +731,7 @@ static int reset_summary_unit_check(struct alias_lcu *lcu,
723 ASCEBC((char *) &cqr->magic, 4); 731 ASCEBC((char *) &cqr->magic, 4);
724 ccw = cqr->cpaddr; 732 ccw = cqr->cpaddr;
725 ccw->cmd_code = DASD_ECKD_CCW_RSCK; 733 ccw->cmd_code = DASD_ECKD_CCW_RSCK;
726 ccw->flags = 0 ; 734 ccw->flags = CCW_FLAG_SLI;
727 ccw->count = 16; 735 ccw->count = 16;
728 ccw->cda = (__u32)(addr_t) cqr->data; 736 ccw->cda = (__u32)(addr_t) cqr->data;
729 ((char *)cqr->data)[0] = reason; 737 ((char *)cqr->data)[0] = reason;
@@ -930,6 +938,7 @@ static void summary_unit_check_handling_work(struct work_struct *work)
930 /* 3. read new alias configuration */ 938 /* 3. read new alias configuration */
931 _schedule_lcu_update(lcu, device); 939 _schedule_lcu_update(lcu, device);
932 lcu->suc_data.device = NULL; 940 lcu->suc_data.device = NULL;
941 dasd_put_device(device);
933 spin_unlock_irqrestore(&lcu->lock, flags); 942 spin_unlock_irqrestore(&lcu->lock, flags);
934} 943}
935 944
@@ -989,6 +998,8 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device,
989 } 998 }
990 lcu->suc_data.reason = reason; 999 lcu->suc_data.reason = reason;
991 lcu->suc_data.device = device; 1000 lcu->suc_data.device = device;
1001 dasd_get_device(device);
992 spin_unlock(&lcu->lock); 1002 spin_unlock(&lcu->lock);
993 schedule_work(&lcu->suc_data.worker); 1003 if (!schedule_work(&lcu->suc_data.worker))
1004 dasd_put_device(device);
994}; 1005};