diff options
Diffstat (limited to 'arch/ppc64/kernel')
| -rw-r--r-- | arch/ppc64/kernel/entry.S | 9 | ||||
| -rw-r--r-- | arch/ppc64/kernel/head.S | 10 | ||||
| -rw-r--r-- | arch/ppc64/kernel/iSeries_setup.c | 22 | ||||
| -rw-r--r-- | arch/ppc64/kernel/idle.c | 8 | ||||
| -rw-r--r-- | arch/ppc64/kernel/mf.c | 85 | ||||
| -rw-r--r-- | arch/ppc64/kernel/pSeries_reconfig.c | 8 | ||||
| -rw-r--r-- | arch/ppc64/kernel/pmac_smp.c | 28 | ||||
| -rw-r--r-- | arch/ppc64/kernel/process.c | 3 | ||||
| -rw-r--r-- | arch/ppc64/kernel/prom_init.c | 154 | ||||
| -rw-r--r-- | arch/ppc64/kernel/rtc.c | 39 | ||||
| -rw-r--r-- | arch/ppc64/kernel/setup.c | 56 | ||||
| -rw-r--r-- | arch/ppc64/kernel/smp.c | 3 | ||||
| -rw-r--r-- | arch/ppc64/kernel/sysfs.c | 8 | ||||
| -rw-r--r-- | arch/ppc64/kernel/time.c | 3 |
14 files changed, 237 insertions, 199 deletions
diff --git a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S index d3604056e1a9..b61572eb2a71 100644 --- a/arch/ppc64/kernel/entry.S +++ b/arch/ppc64/kernel/entry.S | |||
| @@ -436,15 +436,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | |||
| 436 | REST_8GPRS(14, r1) | 436 | REST_8GPRS(14, r1) |
| 437 | REST_10GPRS(22, r1) | 437 | REST_10GPRS(22, r1) |
| 438 | 438 | ||
| 439 | #ifdef CONFIG_PPC_ISERIES | ||
| 440 | clrrdi r7,r1,THREAD_SHIFT /* get current_thread_info() */ | ||
| 441 | ld r7,TI_FLAGS(r7) /* Get run light flag */ | ||
| 442 | mfspr r9,CTRLF | ||
| 443 | srdi r7,r7,TIF_RUN_LIGHT | ||
| 444 | insrdi r9,r7,1,63 /* Insert run light into CTRL */ | ||
| 445 | mtspr CTRLT,r9 | ||
| 446 | #endif | ||
| 447 | |||
| 448 | /* convert old thread to its task_struct for return value */ | 439 | /* convert old thread to its task_struct for return value */ |
| 449 | addi r3,r3,-THREAD | 440 | addi r3,r3,-THREAD |
| 450 | ld r7,_NIP(r1) /* Return to _switch caller in new task */ | 441 | ld r7,_NIP(r1) /* Return to _switch caller in new task */ |
diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S index 92a744c31ab1..346dbf606b5d 100644 --- a/arch/ppc64/kernel/head.S +++ b/arch/ppc64/kernel/head.S | |||
| @@ -626,10 +626,10 @@ system_reset_iSeries: | |||
| 626 | lhz r24,PACAPACAINDEX(r13) /* Get processor # */ | 626 | lhz r24,PACAPACAINDEX(r13) /* Get processor # */ |
| 627 | cmpwi 0,r24,0 /* Are we processor 0? */ | 627 | cmpwi 0,r24,0 /* Are we processor 0? */ |
| 628 | beq .__start_initialization_iSeries /* Start up the first processor */ | 628 | beq .__start_initialization_iSeries /* Start up the first processor */ |
| 629 | mfspr r4,CTRLF | 629 | mfspr r4,SPRN_CTRLF |
| 630 | li r5,RUNLATCH /* Turn off the run light */ | 630 | li r5,CTRL_RUNLATCH /* Turn off the run light */ |
| 631 | andc r4,r4,r5 | 631 | andc r4,r4,r5 |
| 632 | mtspr CTRLT,r4 | 632 | mtspr SPRN_CTRLT,r4 |
| 633 | 633 | ||
| 634 | 1: | 634 | 1: |
| 635 | HMT_LOW | 635 | HMT_LOW |
| @@ -2082,9 +2082,9 @@ _GLOBAL(hmt_start_secondary) | |||
| 2082 | mfspr r4, HID0 | 2082 | mfspr r4, HID0 |
| 2083 | ori r4, r4, 0x1 | 2083 | ori r4, r4, 0x1 |
| 2084 | mtspr HID0, r4 | 2084 | mtspr HID0, r4 |
| 2085 | mfspr r4, CTRLF | 2085 | mfspr r4, SPRN_CTRLF |
| 2086 | oris r4, r4, 0x40 | 2086 | oris r4, r4, 0x40 |
| 2087 | mtspr CTRLT, r4 | 2087 | mtspr SPRN_CTRLT, r4 |
| 2088 | blr | 2088 | blr |
| 2089 | #endif | 2089 | #endif |
| 2090 | 2090 | ||
diff --git a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c index da20120f2261..6d06eb550a3f 100644 --- a/arch/ppc64/kernel/iSeries_setup.c +++ b/arch/ppc64/kernel/iSeries_setup.c | |||
| @@ -852,6 +852,28 @@ static int __init iSeries_src_init(void) | |||
| 852 | 852 | ||
| 853 | late_initcall(iSeries_src_init); | 853 | late_initcall(iSeries_src_init); |
| 854 | 854 | ||
| 855 | static int set_spread_lpevents(char *str) | ||
| 856 | { | ||
| 857 | unsigned long i; | ||
| 858 | unsigned long val = simple_strtoul(str, NULL, 0); | ||
| 859 | |||
| 860 | /* | ||
| 861 | * The parameter is the number of processors to share in processing | ||
| 862 | * lp events. | ||
| 863 | */ | ||
| 864 | if (( val > 0) && (val <= NR_CPUS)) { | ||
| 865 | for (i = 1; i < val; ++i) | ||
| 866 | paca[i].lpqueue_ptr = paca[0].lpqueue_ptr; | ||
| 867 | |||
| 868 | printk("lpevent processing spread over %ld processors\n", val); | ||
| 869 | } else { | ||
| 870 | printk("invalid spread_lpevents %ld\n", val); | ||
| 871 | } | ||
| 872 | |||
| 873 | return 1; | ||
| 874 | } | ||
| 875 | __setup("spread_lpevents=", set_spread_lpevents); | ||
| 876 | |||
| 855 | void __init iSeries_early_setup(void) | 877 | void __init iSeries_early_setup(void) |
| 856 | { | 878 | { |
| 857 | iSeries_fixup_klimit(); | 879 | iSeries_fixup_klimit(); |
diff --git a/arch/ppc64/kernel/idle.c b/arch/ppc64/kernel/idle.c index 6abc621d3ba0..f24ce2b87200 100644 --- a/arch/ppc64/kernel/idle.c +++ b/arch/ppc64/kernel/idle.c | |||
| @@ -75,13 +75,9 @@ static int iSeries_idle(void) | |||
| 75 | { | 75 | { |
| 76 | struct paca_struct *lpaca; | 76 | struct paca_struct *lpaca; |
| 77 | long oldval; | 77 | long oldval; |
| 78 | unsigned long CTRL; | ||
| 79 | 78 | ||
| 80 | /* ensure iSeries run light will be out when idle */ | 79 | /* ensure iSeries run light will be out when idle */ |
| 81 | clear_thread_flag(TIF_RUN_LIGHT); | 80 | ppc64_runlatch_off(); |
| 82 | CTRL = mfspr(CTRLF); | ||
| 83 | CTRL &= ~RUNLATCH; | ||
| 84 | mtspr(CTRLT, CTRL); | ||
| 85 | 81 | ||
| 86 | lpaca = get_paca(); | 82 | lpaca = get_paca(); |
| 87 | 83 | ||
| @@ -111,7 +107,9 @@ static int iSeries_idle(void) | |||
| 111 | } | 107 | } |
| 112 | } | 108 | } |
| 113 | 109 | ||
| 110 | ppc64_runlatch_on(); | ||
| 114 | schedule(); | 111 | schedule(); |
| 112 | ppc64_runlatch_off(); | ||
| 115 | } | 113 | } |
| 116 | 114 | ||
| 117 | return 0; | 115 | return 0; |
diff --git a/arch/ppc64/kernel/mf.c b/arch/ppc64/kernel/mf.c index 1bd52ece497c..5aca7e8005a8 100644 --- a/arch/ppc64/kernel/mf.c +++ b/arch/ppc64/kernel/mf.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * mf.c | 2 | * mf.c |
| 3 | * Copyright (C) 2001 Troy D. Armstrong IBM Corporation | 3 | * Copyright (C) 2001 Troy D. Armstrong IBM Corporation |
| 4 | * Copyright (C) 2004 Stephen Rothwell IBM Corporation | 4 | * Copyright (C) 2004-2005 Stephen Rothwell IBM Corporation |
| 5 | * | 5 | * |
| 6 | * This modules exists as an interface between a Linux secondary partition | 6 | * This modules exists as an interface between a Linux secondary partition |
| 7 | * running on an iSeries and the primary partition's Virtual Service | 7 | * running on an iSeries and the primary partition's Virtual Service |
| @@ -36,10 +36,12 @@ | |||
| 36 | 36 | ||
| 37 | #include <asm/time.h> | 37 | #include <asm/time.h> |
| 38 | #include <asm/uaccess.h> | 38 | #include <asm/uaccess.h> |
| 39 | #include <asm/paca.h> | ||
| 39 | #include <asm/iSeries/vio.h> | 40 | #include <asm/iSeries/vio.h> |
| 40 | #include <asm/iSeries/mf.h> | 41 | #include <asm/iSeries/mf.h> |
| 41 | #include <asm/iSeries/HvLpConfig.h> | 42 | #include <asm/iSeries/HvLpConfig.h> |
| 42 | #include <asm/iSeries/ItSpCommArea.h> | 43 | #include <asm/iSeries/ItSpCommArea.h> |
| 44 | #include <asm/iSeries/ItLpQueue.h> | ||
| 43 | 45 | ||
| 44 | /* | 46 | /* |
| 45 | * This is the structure layout for the Machine Facilites LPAR event | 47 | * This is the structure layout for the Machine Facilites LPAR event |
| @@ -696,36 +698,23 @@ static void get_rtc_time_complete(void *token, struct ce_msg_data *ce_msg) | |||
| 696 | complete(&rtc->com); | 698 | complete(&rtc->com); |
| 697 | } | 699 | } |
| 698 | 700 | ||
| 699 | int mf_get_rtc(struct rtc_time *tm) | 701 | static int rtc_set_tm(int rc, u8 *ce_msg, struct rtc_time *tm) |
| 700 | { | 702 | { |
| 701 | struct ce_msg_comp_data ce_complete; | ||
| 702 | struct rtc_time_data rtc_data; | ||
| 703 | int rc; | ||
| 704 | |||
| 705 | memset(&ce_complete, 0, sizeof(ce_complete)); | ||
| 706 | memset(&rtc_data, 0, sizeof(rtc_data)); | ||
| 707 | init_completion(&rtc_data.com); | ||
| 708 | ce_complete.handler = &get_rtc_time_complete; | ||
| 709 | ce_complete.token = &rtc_data; | ||
| 710 | rc = signal_ce_msg_simple(0x40, &ce_complete); | ||
| 711 | if (rc) | ||
| 712 | return rc; | ||
| 713 | wait_for_completion(&rtc_data.com); | ||
| 714 | tm->tm_wday = 0; | 703 | tm->tm_wday = 0; |
| 715 | tm->tm_yday = 0; | 704 | tm->tm_yday = 0; |
| 716 | tm->tm_isdst = 0; | 705 | tm->tm_isdst = 0; |
| 717 | if (rtc_data.rc) { | 706 | if (rc) { |
| 718 | tm->tm_sec = 0; | 707 | tm->tm_sec = 0; |
| 719 | tm->tm_min = 0; | 708 | tm->tm_min = 0; |
| 720 | tm->tm_hour = 0; | 709 | tm->tm_hour = 0; |
| 721 | tm->tm_mday = 15; | 710 | tm->tm_mday = 15; |
| 722 | tm->tm_mon = 5; | 711 | tm->tm_mon = 5; |
| 723 | tm->tm_year = 52; | 712 | tm->tm_year = 52; |
| 724 | return rtc_data.rc; | 713 | return rc; |
| 725 | } | 714 | } |
| 726 | 715 | ||
| 727 | if ((rtc_data.ce_msg.ce_msg[2] == 0xa9) || | 716 | if ((ce_msg[2] == 0xa9) || |
| 728 | (rtc_data.ce_msg.ce_msg[2] == 0xaf)) { | 717 | (ce_msg[2] == 0xaf)) { |
| 729 | /* TOD clock is not set */ | 718 | /* TOD clock is not set */ |
| 730 | tm->tm_sec = 1; | 719 | tm->tm_sec = 1; |
| 731 | tm->tm_min = 1; | 720 | tm->tm_min = 1; |
| @@ -736,7 +725,6 @@ int mf_get_rtc(struct rtc_time *tm) | |||
| 736 | mf_set_rtc(tm); | 725 | mf_set_rtc(tm); |
| 737 | } | 726 | } |
| 738 | { | 727 | { |
| 739 | u8 *ce_msg = rtc_data.ce_msg.ce_msg; | ||
| 740 | u8 year = ce_msg[5]; | 728 | u8 year = ce_msg[5]; |
| 741 | u8 sec = ce_msg[6]; | 729 | u8 sec = ce_msg[6]; |
| 742 | u8 min = ce_msg[7]; | 730 | u8 min = ce_msg[7]; |
| @@ -765,6 +753,63 @@ int mf_get_rtc(struct rtc_time *tm) | |||
| 765 | return 0; | 753 | return 0; |
| 766 | } | 754 | } |
| 767 | 755 | ||
| 756 | int mf_get_rtc(struct rtc_time *tm) | ||
| 757 | { | ||
| 758 | struct ce_msg_comp_data ce_complete; | ||
| 759 | struct rtc_time_data rtc_data; | ||
| 760 | int rc; | ||
| 761 | |||
| 762 | memset(&ce_complete, 0, sizeof(ce_complete)); | ||
| 763 | memset(&rtc_data, 0, sizeof(rtc_data)); | ||
| 764 | init_completion(&rtc_data.com); | ||
| 765 | ce_complete.handler = &get_rtc_time_complete; | ||
| 766 | ce_complete.token = &rtc_data; | ||
| 767 | rc = signal_ce_msg_simple(0x40, &ce_complete); | ||
| 768 | if (rc) | ||
| 769 | return rc; | ||
| 770 | wait_for_completion(&rtc_data.com); | ||
| 771 | return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm); | ||
| 772 | } | ||
| 773 | |||
| 774 | struct boot_rtc_time_data { | ||
| 775 | int busy; | ||
| 776 | struct ce_msg_data ce_msg; | ||
| 777 | int rc; | ||
| 778 | }; | ||
| 779 | |||
| 780 | static void get_boot_rtc_time_complete(void *token, struct ce_msg_data *ce_msg) | ||
| 781 | { | ||
| 782 | struct boot_rtc_time_data *rtc = token; | ||
| 783 | |||
| 784 | memcpy(&rtc->ce_msg, ce_msg, sizeof(rtc->ce_msg)); | ||
| 785 | rtc->rc = 0; | ||
| 786 | rtc->busy = 0; | ||
| 787 | } | ||
| 788 | |||
| 789 | int mf_get_boot_rtc(struct rtc_time *tm) | ||
| 790 | { | ||
| 791 | struct ce_msg_comp_data ce_complete; | ||
| 792 | struct boot_rtc_time_data rtc_data; | ||
| 793 | int rc; | ||
| 794 | |||
| 795 | memset(&ce_complete, 0, sizeof(ce_complete)); | ||
| 796 | memset(&rtc_data, 0, sizeof(rtc_data)); | ||
| 797 | rtc_data.busy = 1; | ||
| 798 | ce_complete.handler = &get_boot_rtc_time_complete; | ||
| 799 | ce_complete.token = &rtc_data; | ||
| 800 | rc = signal_ce_msg_simple(0x40, &ce_complete); | ||
| 801 | if (rc) | ||
| 802 | return rc; | ||
| 803 | /* We need to poll here as we are not yet taking interrupts */ | ||
| 804 | while (rtc_data.busy) { | ||
| 805 | extern unsigned long lpevent_count; | ||
| 806 | struct ItLpQueue *lpq = get_paca()->lpqueue_ptr; | ||
| 807 | if (lpq && ItLpQueue_isLpIntPending(lpq)) | ||
| 808 | lpevent_count += ItLpQueue_process(lpq, NULL); | ||
| 809 | } | ||
| 810 | return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm); | ||
| 811 | } | ||
| 812 | |||
| 768 | int mf_set_rtc(struct rtc_time *tm) | 813 | int mf_set_rtc(struct rtc_time *tm) |
| 769 | { | 814 | { |
| 770 | char ce_time[12]; | 815 | char ce_time[12]; |
diff --git a/arch/ppc64/kernel/pSeries_reconfig.c b/arch/ppc64/kernel/pSeries_reconfig.c index cb5443f2e49b..dc2a69d412a2 100644 --- a/arch/ppc64/kernel/pSeries_reconfig.c +++ b/arch/ppc64/kernel/pSeries_reconfig.c | |||
| @@ -47,14 +47,6 @@ static void remove_node_proc_entries(struct device_node *np) | |||
| 47 | remove_proc_entry(pp->name, np->pde); | 47 | remove_proc_entry(pp->name, np->pde); |
| 48 | pp = pp->next; | 48 | pp = pp->next; |
| 49 | } | 49 | } |
| 50 | |||
| 51 | /* Assuming that symlinks have the same parent directory as | ||
| 52 | * np->pde. | ||
| 53 | */ | ||
| 54 | if (np->name_link) | ||
| 55 | remove_proc_entry(np->name_link->name, parent->pde); | ||
| 56 | if (np->addr_link) | ||
| 57 | remove_proc_entry(np->addr_link->name, parent->pde); | ||
| 58 | if (np->pde) | 50 | if (np->pde) |
| 59 | remove_proc_entry(np->pde->name, parent->pde); | 51 | remove_proc_entry(np->pde->name, parent->pde); |
| 60 | } | 52 | } |
diff --git a/arch/ppc64/kernel/pmac_smp.c b/arch/ppc64/kernel/pmac_smp.c index c27588ede2fe..a23de37227bf 100644 --- a/arch/ppc64/kernel/pmac_smp.c +++ b/arch/ppc64/kernel/pmac_smp.c | |||
| @@ -68,6 +68,7 @@ extern struct smp_ops_t *smp_ops; | |||
| 68 | 68 | ||
| 69 | static void (*pmac_tb_freeze)(int freeze); | 69 | static void (*pmac_tb_freeze)(int freeze); |
| 70 | static struct device_node *pmac_tb_clock_chip_host; | 70 | static struct device_node *pmac_tb_clock_chip_host; |
| 71 | static u8 pmac_tb_pulsar_addr; | ||
| 71 | static DEFINE_SPINLOCK(timebase_lock); | 72 | static DEFINE_SPINLOCK(timebase_lock); |
| 72 | static unsigned long timebase; | 73 | static unsigned long timebase; |
| 73 | 74 | ||
| @@ -106,12 +107,9 @@ static void smp_core99_pulsar_tb_freeze(int freeze) | |||
| 106 | u8 data; | 107 | u8 data; |
| 107 | int rc; | 108 | int rc; |
| 108 | 109 | ||
| 109 | /* Strangely, the device-tree says address is 0xd2, but darwin | ||
| 110 | * accesses 0xd0 ... | ||
| 111 | */ | ||
| 112 | pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_combined); | 110 | pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_combined); |
| 113 | rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host, | 111 | rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host, |
| 114 | 0xd4 | pmac_low_i2c_read, | 112 | pmac_tb_pulsar_addr | pmac_low_i2c_read, |
| 115 | 0x2e, &data, 1); | 113 | 0x2e, &data, 1); |
| 116 | if (rc != 0) | 114 | if (rc != 0) |
| 117 | goto bail; | 115 | goto bail; |
| @@ -120,7 +118,7 @@ static void smp_core99_pulsar_tb_freeze(int freeze) | |||
| 120 | 118 | ||
| 121 | pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_stdsub); | 119 | pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_stdsub); |
| 122 | rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host, | 120 | rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host, |
| 123 | 0xd4 | pmac_low_i2c_write, | 121 | pmac_tb_pulsar_addr | pmac_low_i2c_write, |
| 124 | 0x2e, &data, 1); | 122 | 0x2e, &data, 1); |
| 125 | bail: | 123 | bail: |
| 126 | if (rc != 0) { | 124 | if (rc != 0) { |
| @@ -185,6 +183,12 @@ static int __init smp_core99_probe(void) | |||
| 185 | if (ncpus <= 1) | 183 | if (ncpus <= 1) |
| 186 | return 1; | 184 | return 1; |
| 187 | 185 | ||
| 186 | /* HW sync only on these platforms */ | ||
| 187 | if (!machine_is_compatible("PowerMac7,2") && | ||
| 188 | !machine_is_compatible("PowerMac7,3") && | ||
| 189 | !machine_is_compatible("RackMac3,1")) | ||
| 190 | goto nohwsync; | ||
| 191 | |||
| 188 | /* Look for the clock chip */ | 192 | /* Look for the clock chip */ |
| 189 | for (cc = NULL; (cc = of_find_node_by_name(cc, "i2c-hwclock")) != NULL;) { | 193 | for (cc = NULL; (cc = of_find_node_by_name(cc, "i2c-hwclock")) != NULL;) { |
| 190 | struct device_node *p = of_get_parent(cc); | 194 | struct device_node *p = of_get_parent(cc); |
| @@ -198,11 +202,18 @@ static int __init smp_core99_probe(void) | |||
| 198 | goto next; | 202 | goto next; |
| 199 | switch (*reg) { | 203 | switch (*reg) { |
| 200 | case 0xd2: | 204 | case 0xd2: |
| 201 | pmac_tb_freeze = smp_core99_cypress_tb_freeze; | 205 | if (device_is_compatible(cc, "pulsar-legacy-slewing")) { |
| 202 | printk(KERN_INFO "Timebase clock is Cypress chip\n"); | 206 | pmac_tb_freeze = smp_core99_pulsar_tb_freeze; |
| 207 | pmac_tb_pulsar_addr = 0xd2; | ||
| 208 | printk(KERN_INFO "Timebase clock is Pulsar chip\n"); | ||
| 209 | } else if (device_is_compatible(cc, "cy28508")) { | ||
| 210 | pmac_tb_freeze = smp_core99_cypress_tb_freeze; | ||
| 211 | printk(KERN_INFO "Timebase clock is Cypress chip\n"); | ||
| 212 | } | ||
| 203 | break; | 213 | break; |
| 204 | case 0xd4: | 214 | case 0xd4: |
| 205 | pmac_tb_freeze = smp_core99_pulsar_tb_freeze; | 215 | pmac_tb_freeze = smp_core99_pulsar_tb_freeze; |
| 216 | pmac_tb_pulsar_addr = 0xd4; | ||
| 206 | printk(KERN_INFO "Timebase clock is Pulsar chip\n"); | 217 | printk(KERN_INFO "Timebase clock is Pulsar chip\n"); |
| 207 | break; | 218 | break; |
| 208 | } | 219 | } |
| @@ -210,12 +221,15 @@ static int __init smp_core99_probe(void) | |||
| 210 | pmac_tb_clock_chip_host = p; | 221 | pmac_tb_clock_chip_host = p; |
| 211 | smp_ops->give_timebase = smp_core99_give_timebase; | 222 | smp_ops->give_timebase = smp_core99_give_timebase; |
| 212 | smp_ops->take_timebase = smp_core99_take_timebase; | 223 | smp_ops->take_timebase = smp_core99_take_timebase; |
| 224 | of_node_put(cc); | ||
| 225 | of_node_put(p); | ||
| 213 | break; | 226 | break; |
| 214 | } | 227 | } |
| 215 | next: | 228 | next: |
| 216 | of_node_put(p); | 229 | of_node_put(p); |
| 217 | } | 230 | } |
| 218 | 231 | ||
| 232 | nohwsync: | ||
| 219 | mpic_request_ipis(); | 233 | mpic_request_ipis(); |
| 220 | 234 | ||
| 221 | return ncpus; | 235 | return ncpus; |
diff --git a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c index 8b0686122738..cdfecbeb331f 100644 --- a/arch/ppc64/kernel/process.c +++ b/arch/ppc64/kernel/process.c | |||
| @@ -378,9 +378,6 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, | |||
| 378 | childregs->gpr[1] = sp + sizeof(struct pt_regs); | 378 | childregs->gpr[1] = sp + sizeof(struct pt_regs); |
| 379 | p->thread.regs = NULL; /* no user register state */ | 379 | p->thread.regs = NULL; /* no user register state */ |
| 380 | clear_ti_thread_flag(p->thread_info, TIF_32BIT); | 380 | clear_ti_thread_flag(p->thread_info, TIF_32BIT); |
| 381 | #ifdef CONFIG_PPC_ISERIES | ||
| 382 | set_ti_thread_flag(p->thread_info, TIF_RUN_LIGHT); | ||
| 383 | #endif | ||
| 384 | } else { | 381 | } else { |
| 385 | childregs->gpr[1] = usp; | 382 | childregs->gpr[1] = usp; |
| 386 | p->thread.regs = childregs; | 383 | p->thread.regs = childregs; |
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c index 35ec42de962e..b7683abfbe6a 100644 --- a/arch/ppc64/kernel/prom_init.c +++ b/arch/ppc64/kernel/prom_init.c | |||
| @@ -211,13 +211,23 @@ struct { | |||
| 211 | */ | 211 | */ |
| 212 | #define ADDR(x) (u32) ((unsigned long)(x) - offset) | 212 | #define ADDR(x) (u32) ((unsigned long)(x) - offset) |
| 213 | 213 | ||
| 214 | /* | ||
| 215 | * Error results ... some OF calls will return "-1" on error, some | ||
| 216 | * will return 0, some will return either. To simplify, here are | ||
| 217 | * macros to use with any ihandle or phandle return value to check if | ||
| 218 | * it is valid | ||
| 219 | */ | ||
| 220 | |||
| 221 | #define PROM_ERROR (-1u) | ||
| 222 | #define PHANDLE_VALID(p) ((p) != 0 && (p) != PROM_ERROR) | ||
| 223 | #define IHANDLE_VALID(i) ((i) != 0 && (i) != PROM_ERROR) | ||
| 224 | |||
| 225 | |||
| 214 | /* This is the one and *ONLY* place where we actually call open | 226 | /* This is the one and *ONLY* place where we actually call open |
| 215 | * firmware from, since we need to make sure we're running in 32b | 227 | * firmware from, since we need to make sure we're running in 32b |
| 216 | * mode when we do. We switch back to 64b mode upon return. | 228 | * mode when we do. We switch back to 64b mode upon return. |
| 217 | */ | 229 | */ |
| 218 | 230 | ||
| 219 | #define PROM_ERROR (-1) | ||
| 220 | |||
| 221 | static int __init call_prom(const char *service, int nargs, int nret, ...) | 231 | static int __init call_prom(const char *service, int nargs, int nret, ...) |
| 222 | { | 232 | { |
| 223 | int i; | 233 | int i; |
| @@ -587,14 +597,13 @@ static void __init prom_send_capabilities(void) | |||
| 587 | { | 597 | { |
| 588 | unsigned long offset = reloc_offset(); | 598 | unsigned long offset = reloc_offset(); |
| 589 | ihandle elfloader; | 599 | ihandle elfloader; |
| 590 | int ret; | ||
| 591 | 600 | ||
| 592 | elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader")); | 601 | elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader")); |
| 593 | if (elfloader == 0) { | 602 | if (elfloader == 0) { |
| 594 | prom_printf("couldn't open /packages/elf-loader\n"); | 603 | prom_printf("couldn't open /packages/elf-loader\n"); |
| 595 | return; | 604 | return; |
| 596 | } | 605 | } |
| 597 | ret = call_prom("call-method", 3, 1, ADDR("process-elf-header"), | 606 | call_prom("call-method", 3, 1, ADDR("process-elf-header"), |
| 598 | elfloader, ADDR(&fake_elf)); | 607 | elfloader, ADDR(&fake_elf)); |
| 599 | call_prom("close", 1, 0, elfloader); | 608 | call_prom("close", 1, 0, elfloader); |
| 600 | } | 609 | } |
| @@ -646,7 +655,7 @@ static unsigned long __init alloc_up(unsigned long size, unsigned long align) | |||
| 646 | base = _ALIGN_UP(base + 0x100000, align)) { | 655 | base = _ALIGN_UP(base + 0x100000, align)) { |
| 647 | prom_debug(" trying: 0x%x\n\r", base); | 656 | prom_debug(" trying: 0x%x\n\r", base); |
| 648 | addr = (unsigned long)prom_claim(base, size, 0); | 657 | addr = (unsigned long)prom_claim(base, size, 0); |
| 649 | if ((int)addr != PROM_ERROR) | 658 | if (addr != PROM_ERROR) |
| 650 | break; | 659 | break; |
| 651 | addr = 0; | 660 | addr = 0; |
| 652 | if (align == 0) | 661 | if (align == 0) |
| @@ -708,7 +717,7 @@ static unsigned long __init alloc_down(unsigned long size, unsigned long align, | |||
| 708 | for(; base > RELOC(alloc_bottom); base = _ALIGN_DOWN(base - 0x100000, align)) { | 717 | for(; base > RELOC(alloc_bottom); base = _ALIGN_DOWN(base - 0x100000, align)) { |
| 709 | prom_debug(" trying: 0x%x\n\r", base); | 718 | prom_debug(" trying: 0x%x\n\r", base); |
| 710 | addr = (unsigned long)prom_claim(base, size, 0); | 719 | addr = (unsigned long)prom_claim(base, size, 0); |
| 711 | if ((int)addr != PROM_ERROR) | 720 | if (addr != PROM_ERROR) |
| 712 | break; | 721 | break; |
| 713 | addr = 0; | 722 | addr = 0; |
| 714 | } | 723 | } |
| @@ -902,18 +911,19 @@ static void __init prom_instantiate_rtas(void) | |||
| 902 | { | 911 | { |
| 903 | unsigned long offset = reloc_offset(); | 912 | unsigned long offset = reloc_offset(); |
| 904 | struct prom_t *_prom = PTRRELOC(&prom); | 913 | struct prom_t *_prom = PTRRELOC(&prom); |
| 905 | phandle prom_rtas, rtas_node; | 914 | phandle rtas_node; |
| 915 | ihandle rtas_inst; | ||
| 906 | u32 base, entry = 0; | 916 | u32 base, entry = 0; |
| 907 | u32 size = 0; | 917 | u32 size = 0; |
| 908 | 918 | ||
| 909 | prom_debug("prom_instantiate_rtas: start...\n"); | 919 | prom_debug("prom_instantiate_rtas: start...\n"); |
| 910 | 920 | ||
| 911 | prom_rtas = call_prom("finddevice", 1, 1, ADDR("/rtas")); | 921 | rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas")); |
| 912 | prom_debug("prom_rtas: %x\n", prom_rtas); | 922 | prom_debug("rtas_node: %x\n", rtas_node); |
| 913 | if (prom_rtas == (phandle) -1) | 923 | if (!PHANDLE_VALID(rtas_node)) |
| 914 | return; | 924 | return; |
| 915 | 925 | ||
| 916 | prom_getprop(prom_rtas, "rtas-size", &size, sizeof(size)); | 926 | prom_getprop(rtas_node, "rtas-size", &size, sizeof(size)); |
| 917 | if (size == 0) | 927 | if (size == 0) |
| 918 | return; | 928 | return; |
| 919 | 929 | ||
| @@ -922,14 +932,18 @@ static void __init prom_instantiate_rtas(void) | |||
| 922 | prom_printf("RTAS allocation failed !\n"); | 932 | prom_printf("RTAS allocation failed !\n"); |
| 923 | return; | 933 | return; |
| 924 | } | 934 | } |
| 925 | prom_printf("instantiating rtas at 0x%x", base); | ||
| 926 | 935 | ||
| 927 | rtas_node = call_prom("open", 1, 1, ADDR("/rtas")); | 936 | rtas_inst = call_prom("open", 1, 1, ADDR("/rtas")); |
| 928 | prom_printf("..."); | 937 | if (!IHANDLE_VALID(rtas_inst)) { |
| 938 | prom_printf("opening rtas package failed"); | ||
| 939 | return; | ||
| 940 | } | ||
| 941 | |||
| 942 | prom_printf("instantiating rtas at 0x%x ...", base); | ||
| 929 | 943 | ||
| 930 | if (call_prom("call-method", 3, 2, | 944 | if (call_prom("call-method", 3, 2, |
| 931 | ADDR("instantiate-rtas"), | 945 | ADDR("instantiate-rtas"), |
| 932 | rtas_node, base) != PROM_ERROR) { | 946 | rtas_inst, base) != PROM_ERROR) { |
| 933 | entry = (long)_prom->args.rets[1]; | 947 | entry = (long)_prom->args.rets[1]; |
| 934 | } | 948 | } |
| 935 | if (entry == 0) { | 949 | if (entry == 0) { |
| @@ -940,8 +954,8 @@ static void __init prom_instantiate_rtas(void) | |||
| 940 | 954 | ||
| 941 | reserve_mem(base, size); | 955 | reserve_mem(base, size); |
| 942 | 956 | ||
| 943 | prom_setprop(prom_rtas, "linux,rtas-base", &base, sizeof(base)); | 957 | prom_setprop(rtas_node, "linux,rtas-base", &base, sizeof(base)); |
| 944 | prom_setprop(prom_rtas, "linux,rtas-entry", &entry, sizeof(entry)); | 958 | prom_setprop(rtas_node, "linux,rtas-entry", &entry, sizeof(entry)); |
| 945 | 959 | ||
| 946 | prom_debug("rtas base = 0x%x\n", base); | 960 | prom_debug("rtas base = 0x%x\n", base); |
| 947 | prom_debug("rtas entry = 0x%x\n", entry); | 961 | prom_debug("rtas entry = 0x%x\n", entry); |
| @@ -1062,7 +1076,7 @@ static void __init prom_initialize_tce_table(void) | |||
| 1062 | 1076 | ||
| 1063 | prom_printf("opening PHB %s", path); | 1077 | prom_printf("opening PHB %s", path); |
| 1064 | phb_node = call_prom("open", 1, 1, path); | 1078 | phb_node = call_prom("open", 1, 1, path); |
| 1065 | if ( (long)phb_node <= 0) | 1079 | if (phb_node == 0) |
| 1066 | prom_printf("... failed\n"); | 1080 | prom_printf("... failed\n"); |
| 1067 | else | 1081 | else |
| 1068 | prom_printf("... done\n"); | 1082 | prom_printf("... done\n"); |
| @@ -1279,12 +1293,12 @@ static void __init prom_init_client_services(unsigned long pp) | |||
| 1279 | 1293 | ||
| 1280 | /* get a handle for the stdout device */ | 1294 | /* get a handle for the stdout device */ |
| 1281 | _prom->chosen = call_prom("finddevice", 1, 1, ADDR("/chosen")); | 1295 | _prom->chosen = call_prom("finddevice", 1, 1, ADDR("/chosen")); |
| 1282 | if ((long)_prom->chosen <= 0) | 1296 | if (!PHANDLE_VALID(_prom->chosen)) |
| 1283 | prom_panic("cannot find chosen"); /* msg won't be printed :( */ | 1297 | prom_panic("cannot find chosen"); /* msg won't be printed :( */ |
| 1284 | 1298 | ||
| 1285 | /* get device tree root */ | 1299 | /* get device tree root */ |
| 1286 | _prom->root = call_prom("finddevice", 1, 1, ADDR("/")); | 1300 | _prom->root = call_prom("finddevice", 1, 1, ADDR("/")); |
| 1287 | if ((long)_prom->root <= 0) | 1301 | if (!PHANDLE_VALID(_prom->root)) |
| 1288 | prom_panic("cannot find device tree root"); /* msg won't be printed :( */ | 1302 | prom_panic("cannot find device tree root"); /* msg won't be printed :( */ |
| 1289 | } | 1303 | } |
| 1290 | 1304 | ||
| @@ -1356,9 +1370,8 @@ static int __init prom_find_machine_type(void) | |||
| 1356 | } | 1370 | } |
| 1357 | /* Default to pSeries. We need to know if we are running LPAR */ | 1371 | /* Default to pSeries. We need to know if we are running LPAR */ |
| 1358 | rtas = call_prom("finddevice", 1, 1, ADDR("/rtas")); | 1372 | rtas = call_prom("finddevice", 1, 1, ADDR("/rtas")); |
| 1359 | if (rtas != (phandle) -1) { | 1373 | if (PHANDLE_VALID(rtas)) { |
| 1360 | unsigned long x; | 1374 | int x = prom_getproplen(rtas, "ibm,hypertas-functions"); |
| 1361 | x = prom_getproplen(rtas, "ibm,hypertas-functions"); | ||
| 1362 | if (x != PROM_ERROR) { | 1375 | if (x != PROM_ERROR) { |
| 1363 | prom_printf("Hypertas detected, assuming LPAR !\n"); | 1376 | prom_printf("Hypertas detected, assuming LPAR !\n"); |
| 1364 | return PLATFORM_PSERIES_LPAR; | 1377 | return PLATFORM_PSERIES_LPAR; |
| @@ -1426,12 +1439,13 @@ static void __init prom_check_displays(void) | |||
| 1426 | * leave some room at the end of the path for appending extra | 1439 | * leave some room at the end of the path for appending extra |
| 1427 | * arguments | 1440 | * arguments |
| 1428 | */ | 1441 | */ |
| 1429 | if (call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-10) < 0) | 1442 | if (call_prom("package-to-path", 3, 1, node, path, |
| 1443 | PROM_SCRATCH_SIZE-10) == PROM_ERROR) | ||
| 1430 | continue; | 1444 | continue; |
| 1431 | prom_printf("found display : %s, opening ... ", path); | 1445 | prom_printf("found display : %s, opening ... ", path); |
| 1432 | 1446 | ||
| 1433 | ih = call_prom("open", 1, 1, path); | 1447 | ih = call_prom("open", 1, 1, path); |
| 1434 | if (ih == (ihandle)0 || ih == (ihandle)-1) { | 1448 | if (ih == 0) { |
| 1435 | prom_printf("failed\n"); | 1449 | prom_printf("failed\n"); |
| 1436 | continue; | 1450 | continue; |
| 1437 | } | 1451 | } |
| @@ -1514,6 +1528,12 @@ static unsigned long __init dt_find_string(char *str) | |||
| 1514 | return 0; | 1528 | return 0; |
| 1515 | } | 1529 | } |
| 1516 | 1530 | ||
| 1531 | /* | ||
| 1532 | * The Open Firmware 1275 specification states properties must be 31 bytes or | ||
| 1533 | * less, however not all firmwares obey this. Make it 64 bytes to be safe. | ||
| 1534 | */ | ||
| 1535 | #define MAX_PROPERTY_NAME 64 | ||
| 1536 | |||
| 1517 | static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, | 1537 | static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, |
| 1518 | unsigned long *mem_end) | 1538 | unsigned long *mem_end) |
| 1519 | { | 1539 | { |
| @@ -1527,10 +1547,12 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, | |||
| 1527 | /* get and store all property names */ | 1547 | /* get and store all property names */ |
| 1528 | prev_name = RELOC(""); | 1548 | prev_name = RELOC(""); |
| 1529 | for (;;) { | 1549 | for (;;) { |
| 1530 | 1550 | int rc; | |
| 1531 | /* 32 is max len of name including nul. */ | 1551 | |
| 1532 | namep = make_room(mem_start, mem_end, 32, 1); | 1552 | /* 64 is max len of name including nul. */ |
| 1533 | if (call_prom("nextprop", 3, 1, node, prev_name, namep) <= 0) { | 1553 | namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1); |
| 1554 | rc = call_prom("nextprop", 3, 1, node, prev_name, namep); | ||
| 1555 | if (rc != 1) { | ||
| 1534 | /* No more nodes: unwind alloc */ | 1556 | /* No more nodes: unwind alloc */ |
| 1535 | *mem_start = (unsigned long)namep; | 1557 | *mem_start = (unsigned long)namep; |
| 1536 | break; | 1558 | break; |
| @@ -1555,18 +1577,12 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, | |||
| 1555 | } | 1577 | } |
| 1556 | } | 1578 | } |
| 1557 | 1579 | ||
| 1558 | /* | ||
| 1559 | * The Open Firmware 1275 specification states properties must be 31 bytes or | ||
| 1560 | * less, however not all firmwares obey this. Make it 64 bytes to be safe. | ||
| 1561 | */ | ||
| 1562 | #define MAX_PROPERTY_NAME 64 | ||
| 1563 | |||
| 1564 | static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, | 1580 | static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, |
| 1565 | unsigned long *mem_end) | 1581 | unsigned long *mem_end) |
| 1566 | { | 1582 | { |
| 1567 | int l, align; | 1583 | int l, align; |
| 1568 | phandle child; | 1584 | phandle child; |
| 1569 | char *namep, *prev_name, *sstart; | 1585 | char *namep, *prev_name, *sstart, *p, *ep; |
| 1570 | unsigned long soff; | 1586 | unsigned long soff; |
| 1571 | unsigned char *valp; | 1587 | unsigned char *valp; |
| 1572 | unsigned long offset = reloc_offset(); | 1588 | unsigned long offset = reloc_offset(); |
| @@ -1588,6 +1604,14 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, | |||
| 1588 | call_prom("package-to-path", 3, 1, node, namep, l); | 1604 | call_prom("package-to-path", 3, 1, node, namep, l); |
| 1589 | } | 1605 | } |
| 1590 | namep[l] = '\0'; | 1606 | namep[l] = '\0'; |
| 1607 | /* Fixup an Apple bug where they have bogus \0 chars in the | ||
| 1608 | * middle of the path in some properties | ||
| 1609 | */ | ||
| 1610 | for (p = namep, ep = namep + l; p < ep; p++) | ||
| 1611 | if (*p == '\0') { | ||
| 1612 | memmove(p, p+1, ep - p); | ||
| 1613 | ep--; l--; | ||
| 1614 | } | ||
| 1591 | *mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 1, 4); | 1615 | *mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 1, 4); |
| 1592 | } | 1616 | } |
| 1593 | 1617 | ||
| @@ -1599,7 +1623,10 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, | |||
| 1599 | prev_name = RELOC(""); | 1623 | prev_name = RELOC(""); |
| 1600 | sstart = (char *)RELOC(dt_string_start); | 1624 | sstart = (char *)RELOC(dt_string_start); |
| 1601 | for (;;) { | 1625 | for (;;) { |
| 1602 | if (call_prom("nextprop", 3, 1, node, prev_name, pname) <= 0) | 1626 | int rc; |
| 1627 | |||
| 1628 | rc = call_prom("nextprop", 3, 1, node, prev_name, pname); | ||
| 1629 | if (rc != 1) | ||
| 1603 | break; | 1630 | break; |
| 1604 | 1631 | ||
| 1605 | /* find string offset */ | 1632 | /* find string offset */ |
| @@ -1615,7 +1642,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, | |||
| 1615 | l = call_prom("getproplen", 2, 1, node, pname); | 1642 | l = call_prom("getproplen", 2, 1, node, pname); |
| 1616 | 1643 | ||
| 1617 | /* sanity checks */ | 1644 | /* sanity checks */ |
| 1618 | if (l < 0) | 1645 | if (l == PROM_ERROR) |
| 1619 | continue; | 1646 | continue; |
| 1620 | if (l > MAX_PROPERTY_LENGTH) { | 1647 | if (l > MAX_PROPERTY_LENGTH) { |
| 1621 | prom_printf("WARNING: ignoring large property "); | 1648 | prom_printf("WARNING: ignoring large property "); |
| @@ -1750,7 +1777,45 @@ static void __init flatten_device_tree(void) | |||
| 1750 | prom_printf("Device tree struct 0x%x -> 0x%x\n", | 1777 | prom_printf("Device tree struct 0x%x -> 0x%x\n", |
| 1751 | RELOC(dt_struct_start), RELOC(dt_struct_end)); | 1778 | RELOC(dt_struct_start), RELOC(dt_struct_end)); |
| 1752 | 1779 | ||
| 1753 | } | 1780 | } |
| 1781 | |||
| 1782 | |||
| 1783 | static void __init fixup_device_tree(void) | ||
| 1784 | { | ||
| 1785 | unsigned long offset = reloc_offset(); | ||
| 1786 | phandle u3, i2c, mpic; | ||
| 1787 | u32 u3_rev; | ||
| 1788 | u32 interrupts[2]; | ||
| 1789 | u32 parent; | ||
| 1790 | |||
| 1791 | /* Some G5s have a missing interrupt definition, fix it up here */ | ||
| 1792 | u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000")); | ||
| 1793 | if (!PHANDLE_VALID(u3)) | ||
| 1794 | return; | ||
| 1795 | i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000")); | ||
| 1796 | if (!PHANDLE_VALID(i2c)) | ||
| 1797 | return; | ||
| 1798 | mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000")); | ||
| 1799 | if (!PHANDLE_VALID(mpic)) | ||
| 1800 | return; | ||
| 1801 | |||
| 1802 | /* check if proper rev of u3 */ | ||
| 1803 | if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) | ||
| 1804 | == PROM_ERROR) | ||
| 1805 | return; | ||
| 1806 | if (u3_rev != 0x35) | ||
| 1807 | return; | ||
| 1808 | /* does it need fixup ? */ | ||
| 1809 | if (prom_getproplen(i2c, "interrupts") > 0) | ||
| 1810 | return; | ||
| 1811 | /* interrupt on this revision of u3 is number 0 and level */ | ||
| 1812 | interrupts[0] = 0; | ||
| 1813 | interrupts[1] = 1; | ||
| 1814 | prom_setprop(i2c, "interrupts", &interrupts, sizeof(interrupts)); | ||
| 1815 | parent = (u32)mpic; | ||
| 1816 | prom_setprop(i2c, "interrupt-parent", &parent, sizeof(parent)); | ||
| 1817 | } | ||
| 1818 | |||
| 1754 | 1819 | ||
| 1755 | static void __init prom_find_boot_cpu(void) | 1820 | static void __init prom_find_boot_cpu(void) |
| 1756 | { | 1821 | { |
| @@ -1844,6 +1909,12 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long | |||
| 1844 | &getprop_rval, sizeof(getprop_rval)); | 1909 | &getprop_rval, sizeof(getprop_rval)); |
| 1845 | 1910 | ||
| 1846 | /* | 1911 | /* |
| 1912 | * On pSeries, inform the firmware about our capabilities | ||
| 1913 | */ | ||
| 1914 | if (RELOC(of_platform) & PLATFORM_PSERIES) | ||
| 1915 | prom_send_capabilities(); | ||
| 1916 | |||
| 1917 | /* | ||
| 1847 | * On pSeries, copy the CPU hold code | 1918 | * On pSeries, copy the CPU hold code |
| 1848 | */ | 1919 | */ |
| 1849 | if (RELOC(of_platform) & PLATFORM_PSERIES) | 1920 | if (RELOC(of_platform) & PLATFORM_PSERIES) |
| @@ -1920,6 +1991,11 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long | |||
| 1920 | } | 1991 | } |
| 1921 | 1992 | ||
| 1922 | /* | 1993 | /* |
| 1994 | * Fixup any known bugs in the device-tree | ||
| 1995 | */ | ||
| 1996 | fixup_device_tree(); | ||
| 1997 | |||
| 1998 | /* | ||
| 1923 | * Now finally create the flattened device-tree | 1999 | * Now finally create the flattened device-tree |
| 1924 | */ | 2000 | */ |
| 1925 | prom_printf("copying OF device tree ...\n"); | 2001 | prom_printf("copying OF device tree ...\n"); |
diff --git a/arch/ppc64/kernel/rtc.c b/arch/ppc64/kernel/rtc.c index 3e70b91375fc..67989055a9fe 100644 --- a/arch/ppc64/kernel/rtc.c +++ b/arch/ppc64/kernel/rtc.c | |||
| @@ -292,47 +292,10 @@ int iSeries_set_rtc_time(struct rtc_time *tm) | |||
| 292 | 292 | ||
| 293 | void iSeries_get_boot_time(struct rtc_time *tm) | 293 | void iSeries_get_boot_time(struct rtc_time *tm) |
| 294 | { | 294 | { |
| 295 | unsigned long time; | ||
| 296 | static unsigned long lastsec = 1; | ||
| 297 | |||
| 298 | u32 dataWord1 = *((u32 *)(&xSpCommArea.xBcdTimeAtIplStart)); | ||
| 299 | u32 dataWord2 = *(((u32 *)&(xSpCommArea.xBcdTimeAtIplStart)) + 1); | ||
| 300 | int year = 1970; | ||
| 301 | int year1 = ( dataWord1 >> 24 ) & 0x000000FF; | ||
| 302 | int year2 = ( dataWord1 >> 16 ) & 0x000000FF; | ||
| 303 | int sec = ( dataWord1 >> 8 ) & 0x000000FF; | ||
| 304 | int min = dataWord1 & 0x000000FF; | ||
| 305 | int hour = ( dataWord2 >> 24 ) & 0x000000FF; | ||
| 306 | int day = ( dataWord2 >> 8 ) & 0x000000FF; | ||
| 307 | int mon = dataWord2 & 0x000000FF; | ||
| 308 | |||
| 309 | if ( piranha_simulator ) | 295 | if ( piranha_simulator ) |
| 310 | return; | 296 | return; |
| 311 | 297 | ||
| 312 | BCD_TO_BIN(sec); | 298 | mf_get_boot_rtc(tm); |
| 313 | BCD_TO_BIN(min); | ||
| 314 | BCD_TO_BIN(hour); | ||
| 315 | BCD_TO_BIN(day); | ||
| 316 | BCD_TO_BIN(mon); | ||
| 317 | BCD_TO_BIN(year1); | ||
| 318 | BCD_TO_BIN(year2); | ||
| 319 | year = year1 * 100 + year2; | ||
| 320 | |||
| 321 | time = mktime(year, mon, day, hour, min, sec); | ||
| 322 | time += ( jiffies / HZ ); | ||
| 323 | |||
| 324 | /* Now THIS is a nasty hack! | ||
| 325 | * It ensures that the first two calls get different answers. | ||
| 326 | * That way the loop in init_time (time.c) will not think | ||
| 327 | * the clock is stuck. | ||
| 328 | */ | ||
| 329 | if ( lastsec ) { | ||
| 330 | time -= lastsec; | ||
| 331 | --lastsec; | ||
| 332 | } | ||
| 333 | |||
| 334 | to_tm(time, tm); | ||
| 335 | tm->tm_year -= 1900; | ||
| 336 | tm->tm_mon -= 1; | 299 | tm->tm_mon -= 1; |
| 337 | } | 300 | } |
| 338 | #endif | 301 | #endif |
diff --git a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c index 21c57f539c29..dce198d39328 100644 --- a/arch/ppc64/kernel/setup.c +++ b/arch/ppc64/kernel/setup.c | |||
| @@ -103,11 +103,6 @@ extern void unflatten_device_tree(void); | |||
| 103 | 103 | ||
| 104 | extern void smp_release_cpus(void); | 104 | extern void smp_release_cpus(void); |
| 105 | 105 | ||
| 106 | unsigned long decr_overclock = 1; | ||
| 107 | unsigned long decr_overclock_proc0 = 1; | ||
| 108 | unsigned long decr_overclock_set = 0; | ||
| 109 | unsigned long decr_overclock_proc0_set = 0; | ||
| 110 | |||
| 111 | int have_of = 1; | 106 | int have_of = 1; |
| 112 | int boot_cpuid = 0; | 107 | int boot_cpuid = 0; |
| 113 | int boot_cpuid_phys = 0; | 108 | int boot_cpuid_phys = 0; |
| @@ -1120,64 +1115,15 @@ void ppc64_dump_msg(unsigned int src, const char *msg) | |||
| 1120 | printk("[dump]%04x %s\n", src, msg); | 1115 | printk("[dump]%04x %s\n", src, msg); |
| 1121 | } | 1116 | } |
| 1122 | 1117 | ||
| 1123 | int set_spread_lpevents( char * str ) | ||
| 1124 | { | ||
| 1125 | /* The parameter is the number of processors to share in processing lp events */ | ||
| 1126 | unsigned long i; | ||
| 1127 | unsigned long val = simple_strtoul( str, NULL, 0 ); | ||
| 1128 | if ( ( val > 0 ) && ( val <= NR_CPUS ) ) { | ||
| 1129 | for ( i=1; i<val; ++i ) | ||
| 1130 | paca[i].lpqueue_ptr = paca[0].lpqueue_ptr; | ||
| 1131 | printk("lpevent processing spread over %ld processors\n", val); | ||
| 1132 | } | ||
| 1133 | else | ||
| 1134 | printk("invalid spreaqd_lpevents %ld\n", val); | ||
| 1135 | return 1; | ||
| 1136 | } | ||
| 1137 | |||
| 1138 | /* This should only be called on processor 0 during calibrate decr */ | 1118 | /* This should only be called on processor 0 during calibrate decr */ |
| 1139 | void setup_default_decr(void) | 1119 | void setup_default_decr(void) |
| 1140 | { | 1120 | { |
| 1141 | struct paca_struct *lpaca = get_paca(); | 1121 | struct paca_struct *lpaca = get_paca(); |
| 1142 | 1122 | ||
| 1143 | if ( decr_overclock_set && !decr_overclock_proc0_set ) | 1123 | lpaca->default_decr = tb_ticks_per_jiffy; |
| 1144 | decr_overclock_proc0 = decr_overclock; | ||
| 1145 | |||
| 1146 | lpaca->default_decr = tb_ticks_per_jiffy / decr_overclock_proc0; | ||
| 1147 | lpaca->next_jiffy_update_tb = get_tb() + tb_ticks_per_jiffy; | 1124 | lpaca->next_jiffy_update_tb = get_tb() + tb_ticks_per_jiffy; |
| 1148 | } | 1125 | } |
| 1149 | 1126 | ||
| 1150 | int set_decr_overclock_proc0( char * str ) | ||
| 1151 | { | ||
| 1152 | unsigned long val = simple_strtoul( str, NULL, 0 ); | ||
| 1153 | if ( ( val >= 1 ) && ( val <= 48 ) ) { | ||
| 1154 | decr_overclock_proc0_set = 1; | ||
| 1155 | decr_overclock_proc0 = val; | ||
| 1156 | printk("proc 0 decrementer overclock factor of %ld\n", val); | ||
| 1157 | } | ||
| 1158 | else | ||
| 1159 | printk("invalid proc 0 decrementer overclock factor of %ld\n", val); | ||
| 1160 | return 1; | ||
| 1161 | } | ||
| 1162 | |||
| 1163 | int set_decr_overclock( char * str ) | ||
| 1164 | { | ||
| 1165 | unsigned long val = simple_strtoul( str, NULL, 0 ); | ||
| 1166 | if ( ( val >= 1 ) && ( val <= 48 ) ) { | ||
| 1167 | decr_overclock_set = 1; | ||
| 1168 | decr_overclock = val; | ||
| 1169 | printk("decrementer overclock factor of %ld\n", val); | ||
| 1170 | } | ||
| 1171 | else | ||
| 1172 | printk("invalid decrementer overclock factor of %ld\n", val); | ||
| 1173 | return 1; | ||
| 1174 | |||
| 1175 | } | ||
| 1176 | |||
| 1177 | __setup("spread_lpevents=", set_spread_lpevents ); | ||
| 1178 | __setup("decr_overclock_proc0=", set_decr_overclock_proc0 ); | ||
| 1179 | __setup("decr_overclock=", set_decr_overclock ); | ||
| 1180 | |||
| 1181 | #ifndef CONFIG_PPC_ISERIES | 1127 | #ifndef CONFIG_PPC_ISERIES |
| 1182 | /* | 1128 | /* |
| 1183 | * This function can be used by platforms to "find" legacy serial ports. | 1129 | * This function can be used by platforms to "find" legacy serial ports. |
diff --git a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c index 3b906cd94037..9ef5d36d6b25 100644 --- a/arch/ppc64/kernel/smp.c +++ b/arch/ppc64/kernel/smp.c | |||
| @@ -334,7 +334,6 @@ void smp_call_function_interrupt(void) | |||
| 334 | } | 334 | } |
| 335 | } | 335 | } |
| 336 | 336 | ||
| 337 | extern unsigned long decr_overclock; | ||
| 338 | extern struct gettimeofday_struct do_gtod; | 337 | extern struct gettimeofday_struct do_gtod; |
| 339 | 338 | ||
| 340 | struct thread_info *current_set[NR_CPUS]; | 339 | struct thread_info *current_set[NR_CPUS]; |
| @@ -491,7 +490,7 @@ int __devinit __cpu_up(unsigned int cpu) | |||
| 491 | if (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu)) | 490 | if (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu)) |
| 492 | return -EINVAL; | 491 | return -EINVAL; |
| 493 | 492 | ||
| 494 | paca[cpu].default_decr = tb_ticks_per_jiffy / decr_overclock; | 493 | paca[cpu].default_decr = tb_ticks_per_jiffy; |
| 495 | 494 | ||
| 496 | if (!cpu_has_feature(CPU_FTR_SLB)) { | 495 | if (!cpu_has_feature(CPU_FTR_SLB)) { |
| 497 | void *tmp; | 496 | void *tmp; |
diff --git a/arch/ppc64/kernel/sysfs.c b/arch/ppc64/kernel/sysfs.c index 0925694c3ce5..c8fa6569b2fd 100644 --- a/arch/ppc64/kernel/sysfs.c +++ b/arch/ppc64/kernel/sysfs.c | |||
| @@ -113,7 +113,6 @@ void ppc64_enable_pmcs(void) | |||
| 113 | #ifdef CONFIG_PPC_PSERIES | 113 | #ifdef CONFIG_PPC_PSERIES |
| 114 | unsigned long set, reset; | 114 | unsigned long set, reset; |
| 115 | int ret; | 115 | int ret; |
| 116 | unsigned int ctrl; | ||
| 117 | #endif /* CONFIG_PPC_PSERIES */ | 116 | #endif /* CONFIG_PPC_PSERIES */ |
| 118 | 117 | ||
| 119 | /* Only need to enable them once */ | 118 | /* Only need to enable them once */ |
| @@ -167,11 +166,8 @@ void ppc64_enable_pmcs(void) | |||
| 167 | * On SMT machines we have to set the run latch in the ctrl register | 166 | * On SMT machines we have to set the run latch in the ctrl register |
| 168 | * in order to make PMC6 spin. | 167 | * in order to make PMC6 spin. |
| 169 | */ | 168 | */ |
| 170 | if (cpu_has_feature(CPU_FTR_SMT)) { | 169 | if (cpu_has_feature(CPU_FTR_SMT)) |
| 171 | ctrl = mfspr(CTRLF); | 170 | ppc64_runlatch_on(); |
| 172 | ctrl |= RUNLATCH; | ||
| 173 | mtspr(CTRLT, ctrl); | ||
| 174 | } | ||
| 175 | #endif /* CONFIG_PPC_PSERIES */ | 171 | #endif /* CONFIG_PPC_PSERIES */ |
| 176 | } | 172 | } |
| 177 | 173 | ||
diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c index 772a465b49f9..33364a7d2cd2 100644 --- a/arch/ppc64/kernel/time.c +++ b/arch/ppc64/kernel/time.c | |||
| @@ -325,9 +325,7 @@ int timer_interrupt(struct pt_regs * regs) | |||
| 325 | 325 | ||
| 326 | irq_enter(); | 326 | irq_enter(); |
| 327 | 327 | ||
| 328 | #ifndef CONFIG_PPC_ISERIES | ||
| 329 | profile_tick(CPU_PROFILING, regs); | 328 | profile_tick(CPU_PROFILING, regs); |
| 330 | #endif | ||
| 331 | 329 | ||
| 332 | lpaca->lppaca.int_dword.fields.decr_int = 0; | 330 | lpaca->lppaca.int_dword.fields.decr_int = 0; |
| 333 | 331 | ||
| @@ -515,6 +513,7 @@ void __init time_init(void) | |||
| 515 | do_gtod.varp = &do_gtod.vars[0]; | 513 | do_gtod.varp = &do_gtod.vars[0]; |
| 516 | do_gtod.var_idx = 0; | 514 | do_gtod.var_idx = 0; |
| 517 | do_gtod.varp->tb_orig_stamp = tb_last_stamp; | 515 | do_gtod.varp->tb_orig_stamp = tb_last_stamp; |
| 516 | get_paca()->next_jiffy_update_tb = tb_last_stamp + tb_ticks_per_jiffy; | ||
| 518 | do_gtod.varp->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC; | 517 | do_gtod.varp->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC; |
| 519 | do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; | 518 | do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; |
| 520 | do_gtod.varp->tb_to_xs = tb_to_xs; | 519 | do_gtod.varp->tb_to_xs = tb_to_xs; |
