aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/bios32.c37
-rw-r--r--arch/arm/kernel/irq.c6
-rw-r--r--arch/arm/kernel/ptrace.c24
-rw-r--r--arch/arm/kernel/signal.c55
-rw-r--r--arch/arm/kernel/smp.c32
-rw-r--r--arch/arm/kernel/sys_arm.c2
6 files changed, 62 insertions, 94 deletions
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index ede5f7741c42..25552508c3fd 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -374,16 +374,29 @@ EXPORT_SYMBOL(pcibios_fixup_bus);
374#endif 374#endif
375 375
376/* 376/*
377 * Swizzle the device pin each time we cross a bridge. 377 * Swizzle the device pin each time we cross a bridge. If a platform does
378 * This might update pin and returns the slot number. 378 * not provide a swizzle function, we perform the standard PCI swizzling.
379 *
380 * The default swizzling walks up the bus tree one level at a time, applying
381 * the standard swizzle function at each step, stopping when it finds the PCI
382 * root bus. This will return the slot number of the bridge device on the
383 * root bus and the interrupt pin on that device which should correspond
384 * with the downstream device interrupt.
385 *
386 * Platforms may override this, in which case the slot and pin returned
387 * depend entirely on the platform code. However, please note that the
388 * PCI standard swizzle is implemented on plug-in cards and Cardbus based
389 * PCI extenders, so it can not be ignored.
379 */ 390 */
380static u8 __devinit pcibios_swizzle(struct pci_dev *dev, u8 *pin) 391static u8 __devinit pcibios_swizzle(struct pci_dev *dev, u8 *pin)
381{ 392{
382 struct pci_sys_data *sys = dev->sysdata; 393 struct pci_sys_data *sys = dev->sysdata;
383 int slot = 0, oldpin = *pin; 394 int slot, oldpin = *pin;
384 395
385 if (sys->swizzle) 396 if (sys->swizzle)
386 slot = sys->swizzle(dev, pin); 397 slot = sys->swizzle(dev, pin);
398 else
399 slot = pci_common_swizzle(dev, pin);
387 400
388 if (debug_pci) 401 if (debug_pci)
389 printk("PCI: %s swizzling pin %d => pin %d slot %d\n", 402 printk("PCI: %s swizzling pin %d => pin %d slot %d\n",
@@ -410,7 +423,7 @@ static int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
410 return irq; 423 return irq;
411} 424}
412 425
413static void __init pcibios_init_hw(struct hw_pci *hw) 426static void __init pcibios_init_hw(struct hw_pci *hw, struct list_head *head)
414{ 427{
415 struct pci_sys_data *sys = NULL; 428 struct pci_sys_data *sys = NULL;
416 int ret; 429 int ret;
@@ -424,7 +437,6 @@ static void __init pcibios_init_hw(struct hw_pci *hw)
424#ifdef CONFIG_PCI_DOMAINS 437#ifdef CONFIG_PCI_DOMAINS
425 sys->domain = hw->domain; 438 sys->domain = hw->domain;
426#endif 439#endif
427 sys->hw = hw;
428 sys->busnr = busnr; 440 sys->busnr = busnr;
429 sys->swizzle = hw->swizzle; 441 sys->swizzle = hw->swizzle;
430 sys->map_irq = hw->map_irq; 442 sys->map_irq = hw->map_irq;
@@ -440,14 +452,18 @@ static void __init pcibios_init_hw(struct hw_pci *hw)
440 &iomem_resource, sys->mem_offset); 452 &iomem_resource, sys->mem_offset);
441 } 453 }
442 454
443 sys->bus = hw->scan(nr, sys); 455 if (hw->scan)
456 sys->bus = hw->scan(nr, sys);
457 else
458 sys->bus = pci_scan_root_bus(NULL, sys->busnr,
459 hw->ops, sys, &sys->resources);
444 460
445 if (!sys->bus) 461 if (!sys->bus)
446 panic("PCI: unable to scan bus!"); 462 panic("PCI: unable to scan bus!");
447 463
448 busnr = sys->bus->subordinate + 1; 464 busnr = sys->bus->subordinate + 1;
449 465
450 list_add(&sys->node, &hw->buses); 466 list_add(&sys->node, head);
451 } else { 467 } else {
452 kfree(sys); 468 kfree(sys);
453 if (ret < 0) 469 if (ret < 0)
@@ -459,19 +475,18 @@ static void __init pcibios_init_hw(struct hw_pci *hw)
459void __init pci_common_init(struct hw_pci *hw) 475void __init pci_common_init(struct hw_pci *hw)
460{ 476{
461 struct pci_sys_data *sys; 477 struct pci_sys_data *sys;
462 478 LIST_HEAD(head);
463 INIT_LIST_HEAD(&hw->buses);
464 479
465 pci_add_flags(PCI_REASSIGN_ALL_RSRC); 480 pci_add_flags(PCI_REASSIGN_ALL_RSRC);
466 if (hw->preinit) 481 if (hw->preinit)
467 hw->preinit(); 482 hw->preinit();
468 pcibios_init_hw(hw); 483 pcibios_init_hw(hw, &head);
469 if (hw->postinit) 484 if (hw->postinit)
470 hw->postinit(); 485 hw->postinit();
471 486
472 pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq); 487 pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq);
473 488
474 list_for_each_entry(sys, &hw->buses, node) { 489 list_for_each_entry(sys, &head, node) {
475 struct pci_bus *bus = sys->bus; 490 struct pci_bus *bus = sys->bus;
476 491
477 if (!pci_has_flag(PCI_PROBE_ONLY)) { 492 if (!pci_has_flag(PCI_PROBE_ONLY)) {
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 71ccdbfed662..8349d4e97e2b 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -155,10 +155,10 @@ static bool migrate_one_irq(struct irq_desc *desc)
155 } 155 }
156 156
157 c = irq_data_get_irq_chip(d); 157 c = irq_data_get_irq_chip(d);
158 if (c->irq_set_affinity) 158 if (!c->irq_set_affinity)
159 c->irq_set_affinity(d, affinity, true);
160 else
161 pr_debug("IRQ%u: unable to set affinity\n", d->irq); 159 pr_debug("IRQ%u: unable to set affinity\n", d->irq);
160 else if (c->irq_set_affinity(d, affinity, true) == IRQ_SET_MASK_OK && ret)
161 cpumask_copy(d->affinity, affinity);
162 162
163 return ret; 163 return ret;
164} 164}
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 80abafb9bf33..9650c143afc1 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -906,27 +906,14 @@ long arch_ptrace(struct task_struct *child, long request,
906 return ret; 906 return ret;
907} 907}
908 908
909#ifdef __ARMEB__
910#define AUDIT_ARCH_NR AUDIT_ARCH_ARMEB
911#else
912#define AUDIT_ARCH_NR AUDIT_ARCH_ARM
913#endif
914
915asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno) 909asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
916{ 910{
917 unsigned long ip; 911 unsigned long ip;
918 912
919 /* 913 if (why)
920 * Save IP. IP is used to denote syscall entry/exit:
921 * IP = 0 -> entry, = 1 -> exit
922 */
923 ip = regs->ARM_ip;
924 regs->ARM_ip = why;
925
926 if (!ip)
927 audit_syscall_exit(regs); 914 audit_syscall_exit(regs);
928 else 915 else
929 audit_syscall_entry(AUDIT_ARCH_NR, scno, regs->ARM_r0, 916 audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0,
930 regs->ARM_r1, regs->ARM_r2, regs->ARM_r3); 917 regs->ARM_r1, regs->ARM_r2, regs->ARM_r3);
931 918
932 if (!test_thread_flag(TIF_SYSCALL_TRACE)) 919 if (!test_thread_flag(TIF_SYSCALL_TRACE))
@@ -936,6 +923,13 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
936 923
937 current_thread_info()->syscall = scno; 924 current_thread_info()->syscall = scno;
938 925
926 /*
927 * IP is used to denote syscall entry/exit:
928 * IP = 0 -> entry, =1 -> exit
929 */
930 ip = regs->ARM_ip;
931 regs->ARM_ip = why;
932
939 /* the 0x80 provides a way for the tracing parent to distinguish 933 /* the 0x80 provides a way for the tracing parent to distinguish
940 between a syscall stop and SIGTRAP delivery */ 934 between a syscall stop and SIGTRAP delivery */
941 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) 935 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 7cb532fc8aa4..d68d1b694680 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -180,44 +180,23 @@ static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame)
180 180
181static int preserve_vfp_context(struct vfp_sigframe __user *frame) 181static int preserve_vfp_context(struct vfp_sigframe __user *frame)
182{ 182{
183 struct thread_info *thread = current_thread_info();
184 struct vfp_hard_struct *h = &thread->vfpstate.hard;
185 const unsigned long magic = VFP_MAGIC; 183 const unsigned long magic = VFP_MAGIC;
186 const unsigned long size = VFP_STORAGE_SIZE; 184 const unsigned long size = VFP_STORAGE_SIZE;
187 int err = 0; 185 int err = 0;
188 186
189 vfp_sync_hwstate(thread);
190 __put_user_error(magic, &frame->magic, err); 187 __put_user_error(magic, &frame->magic, err);
191 __put_user_error(size, &frame->size, err); 188 __put_user_error(size, &frame->size, err);
192 189
193 /* 190 if (err)
194 * Copy the floating point registers. There can be unused 191 return -EFAULT;
195 * registers see asm/hwcap.h for details.
196 */
197 err |= __copy_to_user(&frame->ufp.fpregs, &h->fpregs,
198 sizeof(h->fpregs));
199 /*
200 * Copy the status and control register.
201 */
202 __put_user_error(h->fpscr, &frame->ufp.fpscr, err);
203
204 /*
205 * Copy the exception registers.
206 */
207 __put_user_error(h->fpexc, &frame->ufp_exc.fpexc, err);
208 __put_user_error(h->fpinst, &frame->ufp_exc.fpinst, err);
209 __put_user_error(h->fpinst2, &frame->ufp_exc.fpinst2, err);
210 192
211 return err ? -EFAULT : 0; 193 return vfp_preserve_user_clear_hwstate(&frame->ufp, &frame->ufp_exc);
212} 194}
213 195
214static int restore_vfp_context(struct vfp_sigframe __user *frame) 196static int restore_vfp_context(struct vfp_sigframe __user *frame)
215{ 197{
216 struct thread_info *thread = current_thread_info();
217 struct vfp_hard_struct *h = &thread->vfpstate.hard;
218 unsigned long magic; 198 unsigned long magic;
219 unsigned long size; 199 unsigned long size;
220 unsigned long fpexc;
221 int err = 0; 200 int err = 0;
222 201
223 __get_user_error(magic, &frame->magic, err); 202 __get_user_error(magic, &frame->magic, err);
@@ -228,33 +207,7 @@ static int restore_vfp_context(struct vfp_sigframe __user *frame)
228 if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE) 207 if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE)
229 return -EINVAL; 208 return -EINVAL;
230 209
231 vfp_flush_hwstate(thread); 210 return vfp_restore_user_hwstate(&frame->ufp, &frame->ufp_exc);
232
233 /*
234 * Copy the floating point registers. There can be unused
235 * registers see asm/hwcap.h for details.
236 */
237 err |= __copy_from_user(&h->fpregs, &frame->ufp.fpregs,
238 sizeof(h->fpregs));
239 /*
240 * Copy the status and control register.
241 */
242 __get_user_error(h->fpscr, &frame->ufp.fpscr, err);
243
244 /*
245 * Sanitise and restore the exception registers.
246 */
247 __get_user_error(fpexc, &frame->ufp_exc.fpexc, err);
248 /* Ensure the VFP is enabled. */
249 fpexc |= FPEXC_EN;
250 /* Ensure FPINST2 is invalid and the exception flag is cleared. */
251 fpexc &= ~(FPEXC_EX | FPEXC_FP2V);
252 h->fpexc = fpexc;
253
254 __get_user_error(h->fpinst, &frame->ufp_exc.fpinst, err);
255 __get_user_error(h->fpinst2, &frame->ufp_exc.fpinst2, err);
256
257 return err ? -EFAULT : 0;
258} 211}
259 212
260#endif 213#endif
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 11c4148b8abb..cf58558ef4b9 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -251,8 +251,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
251 struct mm_struct *mm = &init_mm; 251 struct mm_struct *mm = &init_mm;
252 unsigned int cpu = smp_processor_id(); 252 unsigned int cpu = smp_processor_id();
253 253
254 printk("CPU%u: Booted secondary processor\n", cpu);
255
256 /* 254 /*
257 * All kernel threads share the same mm context; grab a 255 * All kernel threads share the same mm context; grab a
258 * reference and switch to it. 256 * reference and switch to it.
@@ -264,6 +262,8 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
264 enter_lazy_tlb(mm, current); 262 enter_lazy_tlb(mm, current);
265 local_flush_tlb_all(); 263 local_flush_tlb_all();
266 264
265 printk("CPU%u: Booted secondary processor\n", cpu);
266
267 cpu_init(); 267 cpu_init();
268 preempt_disable(); 268 preempt_disable();
269 trace_hardirqs_off(); 269 trace_hardirqs_off();
@@ -513,10 +513,6 @@ static void ipi_cpu_stop(unsigned int cpu)
513 local_fiq_disable(); 513 local_fiq_disable();
514 local_irq_disable(); 514 local_irq_disable();
515 515
516#ifdef CONFIG_HOTPLUG_CPU
517 platform_cpu_kill(cpu);
518#endif
519
520 while (1) 516 while (1)
521 cpu_relax(); 517 cpu_relax();
522} 518}
@@ -579,17 +575,25 @@ void smp_send_reschedule(int cpu)
579 smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE); 575 smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE);
580} 576}
581 577
578#ifdef CONFIG_HOTPLUG_CPU
579static void smp_kill_cpus(cpumask_t *mask)
580{
581 unsigned int cpu;
582 for_each_cpu(cpu, mask)
583 platform_cpu_kill(cpu);
584}
585#else
586static void smp_kill_cpus(cpumask_t *mask) { }
587#endif
588
582void smp_send_stop(void) 589void smp_send_stop(void)
583{ 590{
584 unsigned long timeout; 591 unsigned long timeout;
592 struct cpumask mask;
585 593
586 if (num_online_cpus() > 1) { 594 cpumask_copy(&mask, cpu_online_mask);
587 struct cpumask mask; 595 cpumask_clear_cpu(smp_processor_id(), &mask);
588 cpumask_copy(&mask, cpu_online_mask); 596 smp_cross_call(&mask, IPI_CPU_STOP);
589 cpumask_clear_cpu(smp_processor_id(), &mask);
590
591 smp_cross_call(&mask, IPI_CPU_STOP);
592 }
593 597
594 /* Wait up to one second for other CPUs to stop */ 598 /* Wait up to one second for other CPUs to stop */
595 timeout = USEC_PER_SEC; 599 timeout = USEC_PER_SEC;
@@ -598,6 +602,8 @@ void smp_send_stop(void)
598 602
599 if (num_online_cpus() > 1) 603 if (num_online_cpus() > 1)
600 pr_warning("SMP: failed to stop secondary CPUs\n"); 604 pr_warning("SMP: failed to stop secondary CPUs\n");
605
606 smp_kill_cpus(&mask);
601} 607}
602 608
603/* 609/*
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
index d2b177905cdb..76cbb055dd05 100644
--- a/arch/arm/kernel/sys_arm.c
+++ b/arch/arm/kernel/sys_arm.c
@@ -115,7 +115,7 @@ int kernel_execve(const char *filename,
115 "Ir" (THREAD_START_SP - sizeof(regs)), 115 "Ir" (THREAD_START_SP - sizeof(regs)),
116 "r" (&regs), 116 "r" (&regs),
117 "Ir" (sizeof(regs)) 117 "Ir" (sizeof(regs))
118 : "r0", "r1", "r2", "r3", "ip", "lr", "memory"); 118 : "r0", "r1", "r2", "r3", "r8", "r9", "ip", "lr", "memory");
119 119
120 out: 120 out:
121 return ret; 121 return ret;