diff options
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/bios32.c | 37 | ||||
-rw-r--r-- | arch/arm/kernel/irq.c | 6 | ||||
-rw-r--r-- | arch/arm/kernel/ptrace.c | 24 | ||||
-rw-r--r-- | arch/arm/kernel/signal.c | 55 | ||||
-rw-r--r-- | arch/arm/kernel/smp.c | 32 | ||||
-rw-r--r-- | arch/arm/kernel/sys_arm.c | 2 |
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 | */ |
380 | static u8 __devinit pcibios_swizzle(struct pci_dev *dev, u8 *pin) | 391 | static 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 | ||
413 | static void __init pcibios_init_hw(struct hw_pci *hw) | 426 | static 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) | |||
459 | void __init pci_common_init(struct hw_pci *hw) | 475 | void __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 | |||
915 | asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno) | 909 | asmlinkage 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 | ||
181 | static int preserve_vfp_context(struct vfp_sigframe __user *frame) | 181 | static 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 | ||
214 | static int restore_vfp_context(struct vfp_sigframe __user *frame) | 196 | static 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 | ||
579 | static 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 | ||
586 | static void smp_kill_cpus(cpumask_t *mask) { } | ||
587 | #endif | ||
588 | |||
582 | void smp_send_stop(void) | 589 | void 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" (®s), | 116 | "r" (®s), |
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; |