diff options
Diffstat (limited to 'arch/powerpc/platforms/pseries')
-rw-r--r-- | arch/powerpc/platforms/pseries/Makefile | 1 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh.c | 96 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh_cache.c | 17 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh_driver.c | 112 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh_event.c | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/firmware.c | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/hvCall.S | 273 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/hvCall_inst.c | 129 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/hvconsole.c | 5 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/iommu.c | 13 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/lpar.c | 46 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/nvram.c | 5 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/pci.c | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/plpar_wrappers.h | 107 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/ras.c | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/rtasd.c | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/setup.c | 42 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/smp.c | 12 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/xics.c | 44 |
19 files changed, 581 insertions, 337 deletions
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index e5e0ff466904..997243a91be8 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile | |||
@@ -12,3 +12,4 @@ obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o | |||
12 | 12 | ||
13 | obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o | 13 | obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o |
14 | obj-$(CONFIG_HVCS) += hvcserver.o | 14 | obj-$(CONFIG_HVCS) += hvcserver.o |
15 | obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o | ||
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 32eaddfa5470..84bc8f7e17ef 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c | |||
@@ -449,7 +449,11 @@ EXPORT_SYMBOL(eeh_check_failure); | |||
449 | /* ------------------------------------------------------------- */ | 449 | /* ------------------------------------------------------------- */ |
450 | /* The code below deals with error recovery */ | 450 | /* The code below deals with error recovery */ |
451 | 451 | ||
452 | /** Return negative value if a permanent error, else return | 452 | /** |
453 | * eeh_slot_availability - returns error status of slot | ||
454 | * @pdn pci device node | ||
455 | * | ||
456 | * Return negative value if a permanent error, else return | ||
453 | * a number of milliseconds to wait until the PCI slot is | 457 | * a number of milliseconds to wait until the PCI slot is |
454 | * ready to be used. | 458 | * ready to be used. |
455 | */ | 459 | */ |
@@ -474,11 +478,42 @@ eeh_slot_availability(struct pci_dn *pdn) | |||
474 | 478 | ||
475 | printk (KERN_ERR "EEH: Slot unavailable: rc=%d, rets=%d %d %d\n", | 479 | printk (KERN_ERR "EEH: Slot unavailable: rc=%d, rets=%d %d %d\n", |
476 | rc, rets[0], rets[1], rets[2]); | 480 | rc, rets[0], rets[1], rets[2]); |
477 | return -1; | 481 | return -2; |
482 | } | ||
483 | |||
484 | /** | ||
485 | * rtas_pci_enable - enable MMIO or DMA transfers for this slot | ||
486 | * @pdn pci device node | ||
487 | */ | ||
488 | |||
489 | int | ||
490 | rtas_pci_enable(struct pci_dn *pdn, int function) | ||
491 | { | ||
492 | int config_addr; | ||
493 | int rc; | ||
494 | |||
495 | /* Use PE configuration address, if present */ | ||
496 | config_addr = pdn->eeh_config_addr; | ||
497 | if (pdn->eeh_pe_config_addr) | ||
498 | config_addr = pdn->eeh_pe_config_addr; | ||
499 | |||
500 | rc = rtas_call(ibm_set_eeh_option, 4, 1, NULL, | ||
501 | config_addr, | ||
502 | BUID_HI(pdn->phb->buid), | ||
503 | BUID_LO(pdn->phb->buid), | ||
504 | function); | ||
505 | |||
506 | if (rc) | ||
507 | printk(KERN_WARNING "EEH: Cannot enable function %d, err=%d dn=%s\n", | ||
508 | function, rc, pdn->node->full_name); | ||
509 | |||
510 | return rc; | ||
478 | } | 511 | } |
479 | 512 | ||
480 | /** rtas_pci_slot_reset raises/lowers the pci #RST line | 513 | /** |
481 | * state: 1/0 to raise/lower the #RST | 514 | * rtas_pci_slot_reset - raises/lowers the pci #RST line |
515 | * @pdn pci device node | ||
516 | * @state: 1/0 to raise/lower the #RST | ||
482 | * | 517 | * |
483 | * Clear the EEH-frozen condition on a slot. This routine | 518 | * Clear the EEH-frozen condition on a slot. This routine |
484 | * asserts the PCI #RST line if the 'state' argument is '1', | 519 | * asserts the PCI #RST line if the 'state' argument is '1', |
@@ -511,24 +546,21 @@ rtas_pci_slot_reset(struct pci_dn *pdn, int state) | |||
511 | BUID_HI(pdn->phb->buid), | 546 | BUID_HI(pdn->phb->buid), |
512 | BUID_LO(pdn->phb->buid), | 547 | BUID_LO(pdn->phb->buid), |
513 | state); | 548 | state); |
514 | if (rc) { | 549 | if (rc) |
515 | printk (KERN_WARNING "EEH: Unable to reset the failed slot, (%d) #RST=%d dn=%s\n", | 550 | printk (KERN_WARNING "EEH: Unable to reset the failed slot," |
551 | " (%d) #RST=%d dn=%s\n", | ||
516 | rc, state, pdn->node->full_name); | 552 | rc, state, pdn->node->full_name); |
517 | return; | ||
518 | } | ||
519 | } | 553 | } |
520 | 554 | ||
521 | /** rtas_set_slot_reset -- assert the pci #RST line for 1/4 second | 555 | /** |
522 | * dn -- device node to be reset. | 556 | * rtas_set_slot_reset -- assert the pci #RST line for 1/4 second |
557 | * @pdn: pci device node to be reset. | ||
523 | * | 558 | * |
524 | * Return 0 if success, else a non-zero value. | 559 | * Return 0 if success, else a non-zero value. |
525 | */ | 560 | */ |
526 | 561 | ||
527 | int | 562 | static void __rtas_set_slot_reset(struct pci_dn *pdn) |
528 | rtas_set_slot_reset(struct pci_dn *pdn) | ||
529 | { | 563 | { |
530 | int i, rc; | ||
531 | |||
532 | rtas_pci_slot_reset (pdn, 1); | 564 | rtas_pci_slot_reset (pdn, 1); |
533 | 565 | ||
534 | /* The PCI bus requires that the reset be held high for at least | 566 | /* The PCI bus requires that the reset be held high for at least |
@@ -549,17 +581,33 @@ rtas_set_slot_reset(struct pci_dn *pdn) | |||
549 | * up traffic. */ | 581 | * up traffic. */ |
550 | #define PCI_BUS_SETTLE_TIME_MSEC 1800 | 582 | #define PCI_BUS_SETTLE_TIME_MSEC 1800 |
551 | msleep (PCI_BUS_SETTLE_TIME_MSEC); | 583 | msleep (PCI_BUS_SETTLE_TIME_MSEC); |
584 | } | ||
585 | |||
586 | int rtas_set_slot_reset(struct pci_dn *pdn) | ||
587 | { | ||
588 | int i, rc; | ||
589 | |||
590 | __rtas_set_slot_reset(pdn); | ||
552 | 591 | ||
553 | /* Now double check with the firmware to make sure the device is | 592 | /* Now double check with the firmware to make sure the device is |
554 | * ready to be used; if not, wait for recovery. */ | 593 | * ready to be used; if not, wait for recovery. */ |
555 | for (i=0; i<10; i++) { | 594 | for (i=0; i<10; i++) { |
556 | rc = eeh_slot_availability (pdn); | 595 | rc = eeh_slot_availability (pdn); |
557 | if (rc < 0) | ||
558 | printk (KERN_ERR "EEH: failed (%d) to reset slot %s\n", rc, pdn->node->full_name); | ||
559 | if (rc == 0) | 596 | if (rc == 0) |
560 | return 0; | 597 | return 0; |
561 | if (rc < 0) | 598 | |
599 | if (rc == -2) { | ||
600 | printk (KERN_ERR "EEH: failed (%d) to reset slot %s\n", | ||
601 | i, pdn->node->full_name); | ||
602 | __rtas_set_slot_reset(pdn); | ||
603 | continue; | ||
604 | } | ||
605 | |||
606 | if (rc < 0) { | ||
607 | printk (KERN_ERR "EEH: unrecoverable slot failure %s\n", | ||
608 | pdn->node->full_name); | ||
562 | return -1; | 609 | return -1; |
610 | } | ||
563 | 611 | ||
564 | msleep (rc+100); | 612 | msleep (rc+100); |
565 | } | 613 | } |
@@ -582,6 +630,8 @@ rtas_set_slot_reset(struct pci_dn *pdn) | |||
582 | 630 | ||
583 | /** | 631 | /** |
584 | * __restore_bars - Restore the Base Address Registers | 632 | * __restore_bars - Restore the Base Address Registers |
633 | * @pdn: pci device node | ||
634 | * | ||
585 | * Loads the PCI configuration space base address registers, | 635 | * Loads the PCI configuration space base address registers, |
586 | * the expansion ROM base address, the latency timer, and etc. | 636 | * the expansion ROM base address, the latency timer, and etc. |
587 | * from the saved values in the device node. | 637 | * from the saved values in the device node. |
@@ -691,11 +741,11 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
691 | { | 741 | { |
692 | struct eeh_early_enable_info *info = data; | 742 | struct eeh_early_enable_info *info = data; |
693 | int ret; | 743 | int ret; |
694 | char *status = get_property(dn, "status", NULL); | 744 | const char *status = get_property(dn, "status", NULL); |
695 | u32 *class_code = (u32 *)get_property(dn, "class-code", NULL); | 745 | const u32 *class_code = get_property(dn, "class-code", NULL); |
696 | u32 *vendor_id = (u32 *)get_property(dn, "vendor-id", NULL); | 746 | const u32 *vendor_id = get_property(dn, "vendor-id", NULL); |
697 | u32 *device_id = (u32 *)get_property(dn, "device-id", NULL); | 747 | const u32 *device_id = get_property(dn, "device-id", NULL); |
698 | u32 *regs; | 748 | const u32 *regs; |
699 | int enable; | 749 | int enable; |
700 | struct pci_dn *pdn = PCI_DN(dn); | 750 | struct pci_dn *pdn = PCI_DN(dn); |
701 | 751 | ||
@@ -737,7 +787,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
737 | 787 | ||
738 | /* Ok... see if this device supports EEH. Some do, some don't, | 788 | /* Ok... see if this device supports EEH. Some do, some don't, |
739 | * and the only way to find out is to check each and every one. */ | 789 | * and the only way to find out is to check each and every one. */ |
740 | regs = (u32 *)get_property(dn, "reg", NULL); | 790 | regs = get_property(dn, "reg", NULL); |
741 | if (regs) { | 791 | if (regs) { |
742 | /* First register entry is addr (00BBSS00) */ | 792 | /* First register entry is addr (00BBSS00) */ |
743 | /* Try to enable eeh */ | 793 | /* Try to enable eeh */ |
diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c index c37a8497c60f..b6b462d3c604 100644 --- a/arch/powerpc/platforms/pseries/eeh_cache.c +++ b/arch/powerpc/platforms/pseries/eeh_cache.c | |||
@@ -157,6 +157,7 @@ pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo, | |||
157 | if (!piar) | 157 | if (!piar) |
158 | return NULL; | 158 | return NULL; |
159 | 159 | ||
160 | pci_dev_get(dev); | ||
160 | piar->addr_lo = alo; | 161 | piar->addr_lo = alo; |
161 | piar->addr_hi = ahi; | 162 | piar->addr_hi = ahi; |
162 | piar->pcidev = dev; | 163 | piar->pcidev = dev; |
@@ -178,7 +179,6 @@ static void __pci_addr_cache_insert_device(struct pci_dev *dev) | |||
178 | struct device_node *dn; | 179 | struct device_node *dn; |
179 | struct pci_dn *pdn; | 180 | struct pci_dn *pdn; |
180 | int i; | 181 | int i; |
181 | int inserted = 0; | ||
182 | 182 | ||
183 | dn = pci_device_to_OF_node(dev); | 183 | dn = pci_device_to_OF_node(dev); |
184 | if (!dn) { | 184 | if (!dn) { |
@@ -197,9 +197,6 @@ static void __pci_addr_cache_insert_device(struct pci_dev *dev) | |||
197 | return; | 197 | return; |
198 | } | 198 | } |
199 | 199 | ||
200 | /* The cache holds a reference to the device... */ | ||
201 | pci_dev_get(dev); | ||
202 | |||
203 | /* Walk resources on this device, poke them into the tree */ | 200 | /* Walk resources on this device, poke them into the tree */ |
204 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { | 201 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { |
205 | unsigned long start = pci_resource_start(dev,i); | 202 | unsigned long start = pci_resource_start(dev,i); |
@@ -212,12 +209,7 @@ static void __pci_addr_cache_insert_device(struct pci_dev *dev) | |||
212 | if (start == 0 || ~start == 0 || end == 0 || ~end == 0) | 209 | if (start == 0 || ~start == 0 || end == 0 || ~end == 0) |
213 | continue; | 210 | continue; |
214 | pci_addr_cache_insert(dev, start, end, flags); | 211 | pci_addr_cache_insert(dev, start, end, flags); |
215 | inserted = 1; | ||
216 | } | 212 | } |
217 | |||
218 | /* If there was nothing to add, the cache has no reference... */ | ||
219 | if (!inserted) | ||
220 | pci_dev_put(dev); | ||
221 | } | 213 | } |
222 | 214 | ||
223 | /** | 215 | /** |
@@ -240,7 +232,6 @@ void pci_addr_cache_insert_device(struct pci_dev *dev) | |||
240 | static inline void __pci_addr_cache_remove_device(struct pci_dev *dev) | 232 | static inline void __pci_addr_cache_remove_device(struct pci_dev *dev) |
241 | { | 233 | { |
242 | struct rb_node *n; | 234 | struct rb_node *n; |
243 | int removed = 0; | ||
244 | 235 | ||
245 | restart: | 236 | restart: |
246 | n = rb_first(&pci_io_addr_cache_root.rb_root); | 237 | n = rb_first(&pci_io_addr_cache_root.rb_root); |
@@ -250,16 +241,12 @@ restart: | |||
250 | 241 | ||
251 | if (piar->pcidev == dev) { | 242 | if (piar->pcidev == dev) { |
252 | rb_erase(n, &pci_io_addr_cache_root.rb_root); | 243 | rb_erase(n, &pci_io_addr_cache_root.rb_root); |
253 | removed = 1; | 244 | pci_dev_put(piar->pcidev); |
254 | kfree(piar); | 245 | kfree(piar); |
255 | goto restart; | 246 | goto restart; |
256 | } | 247 | } |
257 | n = rb_next(n); | 248 | n = rb_next(n); |
258 | } | 249 | } |
259 | |||
260 | /* The cache no longer holds its reference to this device... */ | ||
261 | if (removed) | ||
262 | pci_dev_put(dev); | ||
263 | } | 250 | } |
264 | 251 | ||
265 | /** | 252 | /** |
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index aaad2c0afcbf..c2bc9904f1cb 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c | |||
@@ -77,8 +77,12 @@ static int irq_in_use(unsigned int irq) | |||
77 | } | 77 | } |
78 | 78 | ||
79 | /* ------------------------------------------------------- */ | 79 | /* ------------------------------------------------------- */ |
80 | /** eeh_report_error - report an EEH error to each device, | 80 | /** |
81 | * collect up and merge the device responses. | 81 | * eeh_report_error - report pci error to each device driver |
82 | * | ||
83 | * Report an EEH error to each device driver, collect up and | ||
84 | * merge the device driver responses. Cumulative response | ||
85 | * passed back in "userdata". | ||
82 | */ | 86 | */ |
83 | 87 | ||
84 | static void eeh_report_error(struct pci_dev *dev, void *userdata) | 88 | static void eeh_report_error(struct pci_dev *dev, void *userdata) |
@@ -96,24 +100,49 @@ static void eeh_report_error(struct pci_dev *dev, void *userdata) | |||
96 | PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED; | 100 | PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED; |
97 | disable_irq_nosync(dev->irq); | 101 | disable_irq_nosync(dev->irq); |
98 | } | 102 | } |
99 | if (!driver->err_handler) | 103 | if (!driver->err_handler || |
100 | return; | 104 | !driver->err_handler->error_detected) |
101 | if (!driver->err_handler->error_detected) | ||
102 | return; | 105 | return; |
103 | 106 | ||
104 | rc = driver->err_handler->error_detected (dev, pci_channel_io_frozen); | 107 | rc = driver->err_handler->error_detected (dev, pci_channel_io_frozen); |
105 | if (*res == PCI_ERS_RESULT_NONE) *res = rc; | 108 | if (*res == PCI_ERS_RESULT_NONE) *res = rc; |
106 | if (*res == PCI_ERS_RESULT_NEED_RESET) return; | ||
107 | if (*res == PCI_ERS_RESULT_DISCONNECT && | 109 | if (*res == PCI_ERS_RESULT_DISCONNECT && |
108 | rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; | 110 | rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; |
109 | } | 111 | } |
110 | 112 | ||
111 | /** eeh_report_reset -- tell this device that the pci slot | 113 | /** |
112 | * has been reset. | 114 | * eeh_report_mmio_enabled - tell drivers that MMIO has been enabled |
115 | * | ||
116 | * Report an EEH error to each device driver, collect up and | ||
117 | * merge the device driver responses. Cumulative response | ||
118 | * passed back in "userdata". | ||
119 | */ | ||
120 | |||
121 | static void eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata) | ||
122 | { | ||
123 | enum pci_ers_result rc, *res = userdata; | ||
124 | struct pci_driver *driver = dev->driver; | ||
125 | |||
126 | // dev->error_state = pci_channel_mmio_enabled; | ||
127 | |||
128 | if (!driver || | ||
129 | !driver->err_handler || | ||
130 | !driver->err_handler->mmio_enabled) | ||
131 | return; | ||
132 | |||
133 | rc = driver->err_handler->mmio_enabled (dev); | ||
134 | if (*res == PCI_ERS_RESULT_NONE) *res = rc; | ||
135 | if (*res == PCI_ERS_RESULT_DISCONNECT && | ||
136 | rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; | ||
137 | } | ||
138 | |||
139 | /** | ||
140 | * eeh_report_reset - tell device that slot has been reset | ||
113 | */ | 141 | */ |
114 | 142 | ||
115 | static void eeh_report_reset(struct pci_dev *dev, void *userdata) | 143 | static void eeh_report_reset(struct pci_dev *dev, void *userdata) |
116 | { | 144 | { |
145 | enum pci_ers_result rc, *res = userdata; | ||
117 | struct pci_driver *driver = dev->driver; | 146 | struct pci_driver *driver = dev->driver; |
118 | struct device_node *dn = pci_device_to_OF_node(dev); | 147 | struct device_node *dn = pci_device_to_OF_node(dev); |
119 | 148 | ||
@@ -124,14 +153,20 @@ static void eeh_report_reset(struct pci_dev *dev, void *userdata) | |||
124 | PCI_DN(dn)->eeh_mode &= ~EEH_MODE_IRQ_DISABLED; | 153 | PCI_DN(dn)->eeh_mode &= ~EEH_MODE_IRQ_DISABLED; |
125 | enable_irq(dev->irq); | 154 | enable_irq(dev->irq); |
126 | } | 155 | } |
127 | if (!driver->err_handler) | 156 | if (!driver->err_handler || |
128 | return; | 157 | !driver->err_handler->slot_reset) |
129 | if (!driver->err_handler->slot_reset) | ||
130 | return; | 158 | return; |
131 | 159 | ||
132 | driver->err_handler->slot_reset(dev); | 160 | rc = driver->err_handler->slot_reset(dev); |
161 | if (*res == PCI_ERS_RESULT_NONE) *res = rc; | ||
162 | if (*res == PCI_ERS_RESULT_DISCONNECT && | ||
163 | rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; | ||
133 | } | 164 | } |
134 | 165 | ||
166 | /** | ||
167 | * eeh_report_resume - tell device to resume normal operations | ||
168 | */ | ||
169 | |||
135 | static void eeh_report_resume(struct pci_dev *dev, void *userdata) | 170 | static void eeh_report_resume(struct pci_dev *dev, void *userdata) |
136 | { | 171 | { |
137 | struct pci_driver *driver = dev->driver; | 172 | struct pci_driver *driver = dev->driver; |
@@ -148,6 +183,13 @@ static void eeh_report_resume(struct pci_dev *dev, void *userdata) | |||
148 | driver->err_handler->resume(dev); | 183 | driver->err_handler->resume(dev); |
149 | } | 184 | } |
150 | 185 | ||
186 | /** | ||
187 | * eeh_report_failure - tell device driver that device is dead. | ||
188 | * | ||
189 | * This informs the device driver that the device is permanently | ||
190 | * dead, and that no further recovery attempts will be made on it. | ||
191 | */ | ||
192 | |||
151 | static void eeh_report_failure(struct pci_dev *dev, void *userdata) | 193 | static void eeh_report_failure(struct pci_dev *dev, void *userdata) |
152 | { | 194 | { |
153 | struct pci_driver *driver = dev->driver; | 195 | struct pci_driver *driver = dev->driver; |
@@ -190,11 +232,11 @@ static void eeh_report_failure(struct pci_dev *dev, void *userdata) | |||
190 | 232 | ||
191 | /** | 233 | /** |
192 | * eeh_reset_device() -- perform actual reset of a pci slot | 234 | * eeh_reset_device() -- perform actual reset of a pci slot |
193 | * Args: bus: pointer to the pci bus structure corresponding | 235 | * @bus: pointer to the pci bus structure corresponding |
194 | * to the isolated slot. A non-null value will | 236 | * to the isolated slot. A non-null value will |
195 | * cause all devices under the bus to be removed | 237 | * cause all devices under the bus to be removed |
196 | * and then re-added. | 238 | * and then re-added. |
197 | * pe_dn: pointer to a "Partionable Endpoint" device node. | 239 | * @pe_dn: pointer to a "Partionable Endpoint" device node. |
198 | * This is the top-level structure on which pci | 240 | * This is the top-level structure on which pci |
199 | * bus resets can be performed. | 241 | * bus resets can be performed. |
200 | */ | 242 | */ |
@@ -268,14 +310,14 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) | |||
268 | 310 | ||
269 | if (!frozen_dn) { | 311 | if (!frozen_dn) { |
270 | 312 | ||
271 | location = (char *) get_property(event->dn, "ibm,loc-code", NULL); | 313 | location = get_property(event->dn, "ibm,loc-code", NULL); |
272 | location = location ? location : "unknown"; | 314 | location = location ? location : "unknown"; |
273 | printk(KERN_ERR "EEH: Error: Cannot find partition endpoint " | 315 | printk(KERN_ERR "EEH: Error: Cannot find partition endpoint " |
274 | "for location=%s pci addr=%s\n", | 316 | "for location=%s pci addr=%s\n", |
275 | location, pci_name(event->dev)); | 317 | location, pci_name(event->dev)); |
276 | return NULL; | 318 | return NULL; |
277 | } | 319 | } |
278 | location = (char *) get_property(frozen_dn, "ibm,loc-code", NULL); | 320 | location = get_property(frozen_dn, "ibm,loc-code", NULL); |
279 | location = location ? location : "unknown"; | 321 | location = location ? location : "unknown"; |
280 | 322 | ||
281 | /* There are two different styles for coming up with the PE. | 323 | /* There are two different styles for coming up with the PE. |
@@ -347,23 +389,43 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) | |||
347 | goto hard_fail; | 389 | goto hard_fail; |
348 | } | 390 | } |
349 | 391 | ||
350 | /* If any device called out for a reset, then reset the slot */ | 392 | /* If all devices reported they can proceed, then re-enable MMIO */ |
351 | if (result == PCI_ERS_RESULT_NEED_RESET) { | 393 | if (result == PCI_ERS_RESULT_CAN_RECOVER) { |
352 | rc = eeh_reset_device(frozen_pdn, NULL); | 394 | rc = rtas_pci_enable(frozen_pdn, EEH_THAW_MMIO); |
353 | if (rc) | 395 | |
354 | goto hard_fail; | 396 | if (rc) { |
355 | pci_walk_bus(frozen_bus, eeh_report_reset, NULL); | 397 | result = PCI_ERS_RESULT_NEED_RESET; |
398 | } else { | ||
399 | result = PCI_ERS_RESULT_NONE; | ||
400 | pci_walk_bus(frozen_bus, eeh_report_mmio_enabled, &result); | ||
401 | } | ||
356 | } | 402 | } |
357 | 403 | ||
358 | /* If all devices reported they can proceed, the re-enable PIO */ | 404 | /* If all devices reported they can proceed, then re-enable DMA */ |
359 | if (result == PCI_ERS_RESULT_CAN_RECOVER) { | 405 | if (result == PCI_ERS_RESULT_CAN_RECOVER) { |
360 | /* XXX Not supported; we brute-force reset the device */ | 406 | rc = rtas_pci_enable(frozen_pdn, EEH_THAW_DMA); |
407 | |||
408 | if (rc) | ||
409 | result = PCI_ERS_RESULT_NEED_RESET; | ||
410 | } | ||
411 | |||
412 | /* If any device has a hard failure, then shut off everything. */ | ||
413 | if (result == PCI_ERS_RESULT_DISCONNECT) | ||
414 | goto hard_fail; | ||
415 | |||
416 | /* If any device called out for a reset, then reset the slot */ | ||
417 | if (result == PCI_ERS_RESULT_NEED_RESET) { | ||
361 | rc = eeh_reset_device(frozen_pdn, NULL); | 418 | rc = eeh_reset_device(frozen_pdn, NULL); |
362 | if (rc) | 419 | if (rc) |
363 | goto hard_fail; | 420 | goto hard_fail; |
364 | pci_walk_bus(frozen_bus, eeh_report_reset, NULL); | 421 | result = PCI_ERS_RESULT_NONE; |
422 | pci_walk_bus(frozen_bus, eeh_report_reset, &result); | ||
365 | } | 423 | } |
366 | 424 | ||
425 | /* All devices should claim they have recovered by now. */ | ||
426 | if (result != PCI_ERS_RESULT_RECOVERED) | ||
427 | goto hard_fail; | ||
428 | |||
367 | /* Tell all device drivers that they can resume operations */ | 429 | /* Tell all device drivers that they can resume operations */ |
368 | pci_walk_bus(frozen_bus, eeh_report_resume, NULL); | 430 | pci_walk_bus(frozen_bus, eeh_report_resume, NULL); |
369 | 431 | ||
diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c index 45ccc687e57c..137077451316 100644 --- a/arch/powerpc/platforms/pseries/eeh_event.c +++ b/arch/powerpc/platforms/pseries/eeh_event.c | |||
@@ -124,11 +124,11 @@ int eeh_send_failure_event (struct device_node *dn, | |||
124 | { | 124 | { |
125 | unsigned long flags; | 125 | unsigned long flags; |
126 | struct eeh_event *event; | 126 | struct eeh_event *event; |
127 | char *location; | 127 | const char *location; |
128 | 128 | ||
129 | if (!mem_init_done) { | 129 | if (!mem_init_done) { |
130 | printk(KERN_ERR "EEH: event during early boot not handled\n"); | 130 | printk(KERN_ERR "EEH: event during early boot not handled\n"); |
131 | location = (char *) get_property(dn, "ibm,loc-code", NULL); | 131 | location = get_property(dn, "ibm,loc-code", NULL); |
132 | printk(KERN_ERR "EEH: device node = %s\n", dn->full_name); | 132 | printk(KERN_ERR "EEH: device node = %s\n", dn->full_name); |
133 | printk(KERN_ERR "EEH: PCI location = %s\n", location); | 133 | printk(KERN_ERR "EEH: PCI location = %s\n", location); |
134 | return 1; | 134 | return 1; |
diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c index c01d8f0cbe6d..1c7b2baa5f73 100644 --- a/arch/powerpc/platforms/pseries/firmware.c +++ b/arch/powerpc/platforms/pseries/firmware.c | |||
@@ -68,7 +68,7 @@ firmware_features_table[FIRMWARE_MAX_FEATURES] = { | |||
68 | void __init fw_feature_init(void) | 68 | void __init fw_feature_init(void) |
69 | { | 69 | { |
70 | struct device_node *dn; | 70 | struct device_node *dn; |
71 | char *hypertas, *s; | 71 | const char *hypertas, *s; |
72 | int len, i; | 72 | int len, i; |
73 | 73 | ||
74 | DBG(" -> fw_feature_init()\n"); | 74 | DBG(" -> fw_feature_init()\n"); |
diff --git a/arch/powerpc/platforms/pseries/hvCall.S b/arch/powerpc/platforms/pseries/hvCall.S index c9ff547f9d25..c00cfed7af2c 100644 --- a/arch/powerpc/platforms/pseries/hvCall.S +++ b/arch/powerpc/platforms/pseries/hvCall.S | |||
@@ -1,7 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * This file contains the generic code to perform a call to the | 2 | * This file contains the generic code to perform a call to the |
3 | * pSeries LPAR hypervisor. | 3 | * pSeries LPAR hypervisor. |
4 | * NOTE: this file will go away when we move to inline this work. | ||
5 | * | 4 | * |
6 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public License | 6 | * modify it under the terms of the GNU General Public License |
@@ -11,217 +10,153 @@ | |||
11 | #include <asm/hvcall.h> | 10 | #include <asm/hvcall.h> |
12 | #include <asm/processor.h> | 11 | #include <asm/processor.h> |
13 | #include <asm/ppc_asm.h> | 12 | #include <asm/ppc_asm.h> |
13 | #include <asm/asm-offsets.h> | ||
14 | 14 | ||
15 | #define STK_PARM(i) (48 + ((i)-3)*8) | 15 | #define STK_PARM(i) (48 + ((i)-3)*8) |
16 | 16 | ||
17 | .text | 17 | #ifdef CONFIG_HCALL_STATS |
18 | 18 | /* | |
19 | /* long plpar_hcall(unsigned long opcode, R3 | 19 | * precall must preserve all registers. use unused STK_PARM() |
20 | unsigned long arg1, R4 | 20 | * areas to save snapshots and opcode. |
21 | unsigned long arg2, R5 | ||
22 | unsigned long arg3, R6 | ||
23 | unsigned long arg4, R7 | ||
24 | unsigned long *out1, R8 | ||
25 | unsigned long *out2, R9 | ||
26 | unsigned long *out3); R10 | ||
27 | */ | 21 | */ |
28 | _GLOBAL(plpar_hcall) | 22 | #define HCALL_INST_PRECALL \ |
29 | HMT_MEDIUM | 23 | std r3,STK_PARM(r3)(r1); /* save opcode */ \ |
30 | 24 | mftb r0; /* get timebase and */ \ | |
31 | mfcr r0 | 25 | std r0,STK_PARM(r5)(r1); /* save for later */ \ |
32 | 26 | BEGIN_FTR_SECTION; \ | |
33 | std r8,STK_PARM(r8)(r1) /* Save out ptrs */ | 27 | mfspr r0,SPRN_PURR; /* get PURR and */ \ |
34 | std r9,STK_PARM(r9)(r1) | 28 | std r0,STK_PARM(r6)(r1); /* save for later */ \ |
35 | std r10,STK_PARM(r10)(r1) | 29 | END_FTR_SECTION_IFCLR(CPU_FTR_PURR); |
36 | 30 | ||
37 | stw r0,8(r1) | 31 | /* |
38 | 32 | * postcall is performed immediately before function return which | |
39 | HVSC /* invoke the hypervisor */ | 33 | * allows liberal use of volatile registers. |
40 | 34 | */ | |
41 | lwz r0,8(r1) | 35 | #define HCALL_INST_POSTCALL \ |
42 | 36 | ld r4,STK_PARM(r3)(r1); /* validate opcode */ \ | |
43 | ld r8,STK_PARM(r8)(r1) /* Fetch r4-r6 ret args */ | 37 | cmpldi cr7,r4,MAX_HCALL_OPCODE; \ |
44 | ld r9,STK_PARM(r9)(r1) | 38 | bgt- cr7,1f; \ |
45 | ld r10,STK_PARM(r10)(r1) | 39 | \ |
46 | std r4,0(r8) | 40 | /* get time and PURR snapshots after hcall */ \ |
47 | std r5,0(r9) | 41 | mftb r7; /* timebase after */ \ |
48 | std r6,0(r10) | 42 | BEGIN_FTR_SECTION; \ |
49 | 43 | mfspr r8,SPRN_PURR; /* PURR after */ \ | |
50 | mtcrf 0xff,r0 | 44 | ld r6,STK_PARM(r6)(r1); /* PURR before */ \ |
51 | blr /* return r3 = status */ | 45 | subf r6,r6,r8; /* delta */ \ |
46 | END_FTR_SECTION_IFCLR(CPU_FTR_PURR); \ | ||
47 | ld r5,STK_PARM(r5)(r1); /* timebase before */ \ | ||
48 | subf r5,r5,r7; /* time delta */ \ | ||
49 | \ | ||
50 | /* calculate address of stat structure r4 = opcode */ \ | ||
51 | srdi r4,r4,2; /* index into array */ \ | ||
52 | mulli r4,r4,HCALL_STAT_SIZE; \ | ||
53 | LOAD_REG_ADDR(r7, per_cpu__hcall_stats); \ | ||
54 | add r4,r4,r7; \ | ||
55 | ld r7,PACA_DATA_OFFSET(r13); /* per cpu offset */ \ | ||
56 | add r4,r4,r7; \ | ||
57 | \ | ||
58 | /* update stats */ \ | ||
59 | ld r7,HCALL_STAT_CALLS(r4); /* count */ \ | ||
60 | addi r7,r7,1; \ | ||
61 | std r7,HCALL_STAT_CALLS(r4); \ | ||
62 | ld r7,HCALL_STAT_TB(r4); /* timebase */ \ | ||
63 | add r7,r7,r5; \ | ||
64 | std r7,HCALL_STAT_TB(r4); \ | ||
65 | BEGIN_FTR_SECTION; \ | ||
66 | ld r7,HCALL_STAT_PURR(r4); /* PURR */ \ | ||
67 | add r7,r7,r6; \ | ||
68 | std r7,HCALL_STAT_PURR(r4); \ | ||
69 | END_FTR_SECTION_IFCLR(CPU_FTR_PURR); \ | ||
70 | 1: | ||
71 | #else | ||
72 | #define HCALL_INST_PRECALL | ||
73 | #define HCALL_INST_POSTCALL | ||
74 | #endif | ||
52 | 75 | ||
76 | .text | ||
53 | 77 | ||
54 | /* Simple interface with no output values (other than status) */ | ||
55 | _GLOBAL(plpar_hcall_norets) | 78 | _GLOBAL(plpar_hcall_norets) |
56 | HMT_MEDIUM | 79 | HMT_MEDIUM |
57 | 80 | ||
58 | mfcr r0 | 81 | mfcr r0 |
59 | stw r0,8(r1) | 82 | stw r0,8(r1) |
60 | 83 | ||
61 | HVSC /* invoke the hypervisor */ | 84 | HCALL_INST_PRECALL |
62 | |||
63 | lwz r0,8(r1) | ||
64 | mtcrf 0xff,r0 | ||
65 | blr /* return r3 = status */ | ||
66 | |||
67 | |||
68 | /* long plpar_hcall_8arg_2ret(unsigned long opcode, R3 | ||
69 | unsigned long arg1, R4 | ||
70 | unsigned long arg2, R5 | ||
71 | unsigned long arg3, R6 | ||
72 | unsigned long arg4, R7 | ||
73 | unsigned long arg5, R8 | ||
74 | unsigned long arg6, R9 | ||
75 | unsigned long arg7, R10 | ||
76 | unsigned long arg8, 112(R1) | ||
77 | unsigned long *out1); 120(R1) | ||
78 | */ | ||
79 | _GLOBAL(plpar_hcall_8arg_2ret) | ||
80 | HMT_MEDIUM | ||
81 | |||
82 | mfcr r0 | ||
83 | ld r11,STK_PARM(r11)(r1) /* put arg8 in R11 */ | ||
84 | stw r0,8(r1) | ||
85 | 85 | ||
86 | HVSC /* invoke the hypervisor */ | 86 | HVSC /* invoke the hypervisor */ |
87 | 87 | ||
88 | HCALL_INST_POSTCALL | ||
89 | |||
88 | lwz r0,8(r1) | 90 | lwz r0,8(r1) |
89 | ld r10,STK_PARM(r12)(r1) /* Fetch r4 ret arg */ | ||
90 | std r4,0(r10) | ||
91 | mtcrf 0xff,r0 | 91 | mtcrf 0xff,r0 |
92 | blr /* return r3 = status */ | 92 | blr /* return r3 = status */ |
93 | 93 | ||
94 | 94 | _GLOBAL(plpar_hcall) | |
95 | /* long plpar_hcall_4out(unsigned long opcode, R3 | ||
96 | unsigned long arg1, R4 | ||
97 | unsigned long arg2, R5 | ||
98 | unsigned long arg3, R6 | ||
99 | unsigned long arg4, R7 | ||
100 | unsigned long *out1, R8 | ||
101 | unsigned long *out2, R9 | ||
102 | unsigned long *out3, R10 | ||
103 | unsigned long *out4); 112(R1) | ||
104 | */ | ||
105 | _GLOBAL(plpar_hcall_4out) | ||
106 | HMT_MEDIUM | 95 | HMT_MEDIUM |
107 | 96 | ||
108 | mfcr r0 | 97 | mfcr r0 |
109 | stw r0,8(r1) | 98 | stw r0,8(r1) |
110 | 99 | ||
111 | std r8,STK_PARM(r8)(r1) /* Save out ptrs */ | 100 | HCALL_INST_PRECALL |
112 | std r9,STK_PARM(r9)(r1) | ||
113 | std r10,STK_PARM(r10)(r1) | ||
114 | |||
115 | HVSC /* invoke the hypervisor */ | ||
116 | |||
117 | lwz r0,8(r1) | ||
118 | 101 | ||
119 | ld r8,STK_PARM(r8)(r1) /* Fetch r4-r7 ret args */ | 102 | std r4,STK_PARM(r4)(r1) /* Save ret buffer */ |
120 | ld r9,STK_PARM(r9)(r1) | ||
121 | ld r10,STK_PARM(r10)(r1) | ||
122 | ld r11,STK_PARM(r11)(r1) | ||
123 | std r4,0(r8) | ||
124 | std r5,0(r9) | ||
125 | std r6,0(r10) | ||
126 | std r7,0(r11) | ||
127 | 103 | ||
128 | mtcrf 0xff,r0 | 104 | mr r4,r5 |
129 | blr /* return r3 = status */ | 105 | mr r5,r6 |
130 | 106 | mr r6,r7 | |
131 | /* plpar_hcall_7arg_7ret(unsigned long opcode, R3 | 107 | mr r7,r8 |
132 | unsigned long arg1, R4 | 108 | mr r8,r9 |
133 | unsigned long arg2, R5 | 109 | mr r9,r10 |
134 | unsigned long arg3, R6 | ||
135 | unsigned long arg4, R7 | ||
136 | unsigned long arg5, R8 | ||
137 | unsigned long arg6, R9 | ||
138 | unsigned long arg7, R10 | ||
139 | unsigned long *out1, 112(R1) | ||
140 | unsigned long *out2, 110(R1) | ||
141 | unsigned long *out3, 108(R1) | ||
142 | unsigned long *out4, 106(R1) | ||
143 | unsigned long *out5, 104(R1) | ||
144 | unsigned long *out6, 102(R1) | ||
145 | unsigned long *out7); 100(R1) | ||
146 | */ | ||
147 | _GLOBAL(plpar_hcall_7arg_7ret) | ||
148 | HMT_MEDIUM | ||
149 | |||
150 | mfcr r0 | ||
151 | stw r0,8(r1) | ||
152 | 110 | ||
153 | HVSC /* invoke the hypervisor */ | 111 | HVSC /* invoke the hypervisor */ |
154 | 112 | ||
155 | lwz r0,8(r1) | 113 | ld r12,STK_PARM(r4)(r1) |
114 | std r4, 0(r12) | ||
115 | std r5, 8(r12) | ||
116 | std r6, 16(r12) | ||
117 | std r7, 24(r12) | ||
156 | 118 | ||
157 | ld r11,STK_PARM(r11)(r1) /* Fetch r4 ret arg */ | 119 | HCALL_INST_POSTCALL |
158 | std r4,0(r11) | ||
159 | ld r11,STK_PARM(r12)(r1) /* Fetch r5 ret arg */ | ||
160 | std r5,0(r11) | ||
161 | ld r11,STK_PARM(r13)(r1) /* Fetch r6 ret arg */ | ||
162 | std r6,0(r11) | ||
163 | ld r11,STK_PARM(r14)(r1) /* Fetch r7 ret arg */ | ||
164 | std r7,0(r11) | ||
165 | ld r11,STK_PARM(r15)(r1) /* Fetch r8 ret arg */ | ||
166 | std r8,0(r11) | ||
167 | ld r11,STK_PARM(r16)(r1) /* Fetch r9 ret arg */ | ||
168 | std r9,0(r11) | ||
169 | ld r11,STK_PARM(r17)(r1) /* Fetch r10 ret arg */ | ||
170 | std r10,0(r11) | ||
171 | 120 | ||
121 | lwz r0,8(r1) | ||
172 | mtcrf 0xff,r0 | 122 | mtcrf 0xff,r0 |
173 | 123 | ||
174 | blr /* return r3 = status */ | 124 | blr /* return r3 = status */ |
175 | 125 | ||
176 | /* plpar_hcall_9arg_9ret(unsigned long opcode, R3 | 126 | _GLOBAL(plpar_hcall9) |
177 | unsigned long arg1, R4 | ||
178 | unsigned long arg2, R5 | ||
179 | unsigned long arg3, R6 | ||
180 | unsigned long arg4, R7 | ||
181 | unsigned long arg5, R8 | ||
182 | unsigned long arg6, R9 | ||
183 | unsigned long arg7, R10 | ||
184 | unsigned long arg8, 112(R1) | ||
185 | unsigned long arg9, 110(R1) | ||
186 | unsigned long *out1, 108(R1) | ||
187 | unsigned long *out2, 106(R1) | ||
188 | unsigned long *out3, 104(R1) | ||
189 | unsigned long *out4, 102(R1) | ||
190 | unsigned long *out5, 100(R1) | ||
191 | unsigned long *out6, 98(R1) | ||
192 | unsigned long *out7); 96(R1) | ||
193 | unsigned long *out8, 94(R1) | ||
194 | unsigned long *out9, 92(R1) | ||
195 | */ | ||
196 | _GLOBAL(plpar_hcall_9arg_9ret) | ||
197 | HMT_MEDIUM | 127 | HMT_MEDIUM |
198 | 128 | ||
199 | mfcr r0 | 129 | mfcr r0 |
200 | stw r0,8(r1) | 130 | stw r0,8(r1) |
201 | 131 | ||
202 | ld r11,STK_PARM(r11)(r1) /* put arg8 in R11 */ | 132 | HCALL_INST_PRECALL |
203 | ld r12,STK_PARM(r12)(r1) /* put arg9 in R12 */ | 133 | |
134 | std r4,STK_PARM(r4)(r1) /* Save ret buffer */ | ||
135 | |||
136 | mr r4,r5 | ||
137 | mr r5,r6 | ||
138 | mr r6,r7 | ||
139 | mr r7,r8 | ||
140 | mr r8,r9 | ||
141 | mr r9,r10 | ||
142 | ld r10,STK_PARM(r11)(r1) /* put arg7 in R10 */ | ||
143 | ld r11,STK_PARM(r12)(r1) /* put arg8 in R11 */ | ||
144 | ld r12,STK_PARM(r13)(r1) /* put arg9 in R12 */ | ||
204 | 145 | ||
205 | HVSC /* invoke the hypervisor */ | 146 | HVSC /* invoke the hypervisor */ |
206 | 147 | ||
207 | ld r0,STK_PARM(r13)(r1) /* Fetch r4 ret arg */ | 148 | ld r12,STK_PARM(r4)(r1) |
208 | stdx r4,r0,r0 | 149 | std r4, 0(r12) |
209 | ld r0,STK_PARM(r14)(r1) /* Fetch r5 ret arg */ | 150 | std r5, 8(r12) |
210 | stdx r5,r0,r0 | 151 | std r6, 16(r12) |
211 | ld r0,STK_PARM(r15)(r1) /* Fetch r6 ret arg */ | 152 | std r7, 24(r12) |
212 | stdx r6,r0,r0 | 153 | std r8, 32(r12) |
213 | ld r0,STK_PARM(r16)(r1) /* Fetch r7 ret arg */ | 154 | std r9, 40(r12) |
214 | stdx r7,r0,r0 | 155 | std r10,48(r12) |
215 | ld r0,STK_PARM(r17)(r1) /* Fetch r8 ret arg */ | 156 | std r11,56(r12) |
216 | stdx r8,r0,r0 | 157 | std r12,64(r12) |
217 | ld r0,STK_PARM(r18)(r1) /* Fetch r9 ret arg */ | 158 | |
218 | stdx r9,r0,r0 | 159 | HCALL_INST_POSTCALL |
219 | ld r0,STK_PARM(r19)(r1) /* Fetch r10 ret arg */ | ||
220 | stdx r10,r0,r0 | ||
221 | ld r0,STK_PARM(r20)(r1) /* Fetch r11 ret arg */ | ||
222 | stdx r11,r0,r0 | ||
223 | ld r0,STK_PARM(r21)(r1) /* Fetch r12 ret arg */ | ||
224 | stdx r12,r0,r0 | ||
225 | 160 | ||
226 | lwz r0,8(r1) | 161 | lwz r0,8(r1) |
227 | mtcrf 0xff,r0 | 162 | mtcrf 0xff,r0 |
diff --git a/arch/powerpc/platforms/pseries/hvCall_inst.c b/arch/powerpc/platforms/pseries/hvCall_inst.c new file mode 100644 index 000000000000..641e6511cf06 --- /dev/null +++ b/arch/powerpc/platforms/pseries/hvCall_inst.c | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2006 Mike Kravetz IBM Corporation | ||
3 | * | ||
4 | * Hypervisor Call Instrumentation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/percpu.h> | ||
23 | #include <linux/debugfs.h> | ||
24 | #include <linux/seq_file.h> | ||
25 | #include <linux/cpumask.h> | ||
26 | #include <asm/hvcall.h> | ||
27 | #include <asm/firmware.h> | ||
28 | #include <asm/cputable.h> | ||
29 | |||
30 | DEFINE_PER_CPU(struct hcall_stats[HCALL_STAT_ARRAY_SIZE], hcall_stats); | ||
31 | |||
32 | /* | ||
33 | * Routines for displaying the statistics in debugfs | ||
34 | */ | ||
35 | static void *hc_start(struct seq_file *m, loff_t *pos) | ||
36 | { | ||
37 | if ((int)*pos < HCALL_STAT_ARRAY_SIZE) | ||
38 | return (void *)(unsigned long)(*pos + 1); | ||
39 | |||
40 | return NULL; | ||
41 | } | ||
42 | |||
43 | static void *hc_next(struct seq_file *m, void *p, loff_t * pos) | ||
44 | { | ||
45 | ++*pos; | ||
46 | |||
47 | return hc_start(m, pos); | ||
48 | } | ||
49 | |||
50 | static void hc_stop(struct seq_file *m, void *p) | ||
51 | { | ||
52 | } | ||
53 | |||
54 | static int hc_show(struct seq_file *m, void *p) | ||
55 | { | ||
56 | unsigned long h_num = (unsigned long)p; | ||
57 | struct hcall_stats *hs = (struct hcall_stats *)m->private; | ||
58 | |||
59 | if (hs[h_num].num_calls) { | ||
60 | if (!cpu_has_feature(CPU_FTR_PURR)) | ||
61 | seq_printf(m, "%lu %lu %lu %lu\n", h_num<<2, | ||
62 | hs[h_num].num_calls, | ||
63 | hs[h_num].tb_total, | ||
64 | hs[h_num].purr_total); | ||
65 | else | ||
66 | seq_printf(m, "%lu %lu %lu\n", h_num<<2, | ||
67 | hs[h_num].num_calls, | ||
68 | hs[h_num].tb_total); | ||
69 | } | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | static struct seq_operations hcall_inst_seq_ops = { | ||
75 | .start = hc_start, | ||
76 | .next = hc_next, | ||
77 | .stop = hc_stop, | ||
78 | .show = hc_show | ||
79 | }; | ||
80 | |||
81 | static int hcall_inst_seq_open(struct inode *inode, struct file *file) | ||
82 | { | ||
83 | int rc; | ||
84 | struct seq_file *seq; | ||
85 | |||
86 | rc = seq_open(file, &hcall_inst_seq_ops); | ||
87 | seq = file->private_data; | ||
88 | seq->private = file->f_dentry->d_inode->u.generic_ip; | ||
89 | |||
90 | return rc; | ||
91 | } | ||
92 | |||
93 | static struct file_operations hcall_inst_seq_fops = { | ||
94 | .open = hcall_inst_seq_open, | ||
95 | .read = seq_read, | ||
96 | .llseek = seq_lseek, | ||
97 | .release = seq_release, | ||
98 | }; | ||
99 | |||
100 | #define HCALL_ROOT_DIR "hcall_inst" | ||
101 | #define CPU_NAME_BUF_SIZE 32 | ||
102 | |||
103 | static int __init hcall_inst_init(void) | ||
104 | { | ||
105 | struct dentry *hcall_root; | ||
106 | struct dentry *hcall_file; | ||
107 | char cpu_name_buf[CPU_NAME_BUF_SIZE]; | ||
108 | int cpu; | ||
109 | |||
110 | if (!firmware_has_feature(FW_FEATURE_LPAR)) | ||
111 | return 0; | ||
112 | |||
113 | hcall_root = debugfs_create_dir(HCALL_ROOT_DIR, NULL); | ||
114 | if (!hcall_root) | ||
115 | return -ENOMEM; | ||
116 | |||
117 | for_each_possible_cpu(cpu) { | ||
118 | snprintf(cpu_name_buf, CPU_NAME_BUF_SIZE, "cpu%d", cpu); | ||
119 | hcall_file = debugfs_create_file(cpu_name_buf, S_IRUGO, | ||
120 | hcall_root, | ||
121 | per_cpu(hcall_stats, cpu), | ||
122 | &hcall_inst_seq_fops); | ||
123 | if (!hcall_file) | ||
124 | return -ENOMEM; | ||
125 | } | ||
126 | |||
127 | return 0; | ||
128 | } | ||
129 | __initcall(hcall_inst_init); | ||
diff --git a/arch/powerpc/platforms/pseries/hvconsole.c b/arch/powerpc/platforms/pseries/hvconsole.c index a72a987f1d4d..3f6a89b09816 100644 --- a/arch/powerpc/platforms/pseries/hvconsole.c +++ b/arch/powerpc/platforms/pseries/hvconsole.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <asm/hvcall.h> | 28 | #include <asm/hvcall.h> |
29 | #include <asm/hvconsole.h> | 29 | #include <asm/hvconsole.h> |
30 | #include "plpar_wrappers.h" | ||
30 | 31 | ||
31 | /** | 32 | /** |
32 | * hvc_get_chars - retrieve characters from firmware for denoted vterm adatper | 33 | * hvc_get_chars - retrieve characters from firmware for denoted vterm adatper |
@@ -40,9 +41,9 @@ int hvc_get_chars(uint32_t vtermno, char *buf, int count) | |||
40 | { | 41 | { |
41 | unsigned long got; | 42 | unsigned long got; |
42 | 43 | ||
43 | if (plpar_hcall(H_GET_TERM_CHAR, vtermno, 0, 0, 0, &got, | 44 | if (plpar_get_term_char(vtermno, &got, buf) == H_SUCCESS) |
44 | (unsigned long *)buf, (unsigned long *)buf+1) == H_SUCCESS) | ||
45 | return got; | 45 | return got; |
46 | |||
46 | return 0; | 47 | return 0; |
47 | } | 48 | } |
48 | 49 | ||
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index d67af2c65754..bbf2e34dc358 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c | |||
@@ -267,13 +267,12 @@ static void iommu_table_setparms(struct pci_controller *phb, | |||
267 | struct iommu_table *tbl) | 267 | struct iommu_table *tbl) |
268 | { | 268 | { |
269 | struct device_node *node; | 269 | struct device_node *node; |
270 | unsigned long *basep; | 270 | const unsigned long *basep, *sizep; |
271 | unsigned int *sizep; | ||
272 | 271 | ||
273 | node = (struct device_node *)phb->arch_data; | 272 | node = (struct device_node *)phb->arch_data; |
274 | 273 | ||
275 | basep = (unsigned long *)get_property(node, "linux,tce-base", NULL); | 274 | basep = get_property(node, "linux,tce-base", NULL); |
276 | sizep = (unsigned int *)get_property(node, "linux,tce-size", NULL); | 275 | sizep = get_property(node, "linux,tce-size", NULL); |
277 | if (basep == NULL || sizep == NULL) { | 276 | if (basep == NULL || sizep == NULL) { |
278 | printk(KERN_ERR "PCI_DMA: iommu_table_setparms: %s has " | 277 | printk(KERN_ERR "PCI_DMA: iommu_table_setparms: %s has " |
279 | "missing tce entries !\n", dn->full_name); | 278 | "missing tce entries !\n", dn->full_name); |
@@ -315,7 +314,7 @@ static void iommu_table_setparms(struct pci_controller *phb, | |||
315 | static void iommu_table_setparms_lpar(struct pci_controller *phb, | 314 | static void iommu_table_setparms_lpar(struct pci_controller *phb, |
316 | struct device_node *dn, | 315 | struct device_node *dn, |
317 | struct iommu_table *tbl, | 316 | struct iommu_table *tbl, |
318 | unsigned char *dma_window) | 317 | const void *dma_window) |
319 | { | 318 | { |
320 | unsigned long offset, size; | 319 | unsigned long offset, size; |
321 | 320 | ||
@@ -415,7 +414,7 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) | |||
415 | struct iommu_table *tbl; | 414 | struct iommu_table *tbl; |
416 | struct device_node *dn, *pdn; | 415 | struct device_node *dn, *pdn; |
417 | struct pci_dn *ppci; | 416 | struct pci_dn *ppci; |
418 | unsigned char *dma_window = NULL; | 417 | const void *dma_window = NULL; |
419 | 418 | ||
420 | DBG("iommu_bus_setup_pSeriesLP, bus %p, bus->self %p\n", bus, bus->self); | 419 | DBG("iommu_bus_setup_pSeriesLP, bus %p, bus->self %p\n", bus, bus->self); |
421 | 420 | ||
@@ -519,7 +518,7 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) | |||
519 | { | 518 | { |
520 | struct device_node *pdn, *dn; | 519 | struct device_node *pdn, *dn; |
521 | struct iommu_table *tbl; | 520 | struct iommu_table *tbl; |
522 | unsigned char *dma_window = NULL; | 521 | const void *dma_window = NULL; |
523 | struct pci_dn *pci; | 522 | struct pci_dn *pci; |
524 | 523 | ||
525 | DBG("iommu_dev_setup_pSeriesLP, dev %p (%s)\n", dev, pci_name(dev)); | 524 | DBG("iommu_dev_setup_pSeriesLP, dev %p (%s)\n", dev, pci_name(dev)); |
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 3aeb40699042..1820a0b0a8c6 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c | |||
@@ -48,13 +48,11 @@ | |||
48 | #define DBG_LOW(fmt...) do { } while(0) | 48 | #define DBG_LOW(fmt...) do { } while(0) |
49 | #endif | 49 | #endif |
50 | 50 | ||
51 | /* in pSeries_hvCall.S */ | 51 | /* in hvCall.S */ |
52 | EXPORT_SYMBOL(plpar_hcall); | 52 | EXPORT_SYMBOL(plpar_hcall); |
53 | EXPORT_SYMBOL(plpar_hcall_4out); | 53 | EXPORT_SYMBOL(plpar_hcall9); |
54 | EXPORT_SYMBOL(plpar_hcall_norets); | 54 | EXPORT_SYMBOL(plpar_hcall_norets); |
55 | EXPORT_SYMBOL(plpar_hcall_8arg_2ret); | 55 | |
56 | EXPORT_SYMBOL(plpar_hcall_7arg_7ret); | ||
57 | EXPORT_SYMBOL(plpar_hcall_9arg_9ret); | ||
58 | extern void pSeries_find_serial_port(void); | 56 | extern void pSeries_find_serial_port(void); |
59 | 57 | ||
60 | 58 | ||
@@ -204,20 +202,20 @@ void __init udbg_init_debug_lpar(void) | |||
204 | void __init find_udbg_vterm(void) | 202 | void __init find_udbg_vterm(void) |
205 | { | 203 | { |
206 | struct device_node *stdout_node; | 204 | struct device_node *stdout_node; |
207 | u32 *termno; | 205 | const u32 *termno; |
208 | char *name; | 206 | const char *name; |
209 | int add_console; | 207 | int add_console; |
210 | 208 | ||
211 | /* find the boot console from /chosen/stdout */ | 209 | /* find the boot console from /chosen/stdout */ |
212 | if (!of_chosen) | 210 | if (!of_chosen) |
213 | return; | 211 | return; |
214 | name = (char *)get_property(of_chosen, "linux,stdout-path", NULL); | 212 | name = get_property(of_chosen, "linux,stdout-path", NULL); |
215 | if (name == NULL) | 213 | if (name == NULL) |
216 | return; | 214 | return; |
217 | stdout_node = of_find_node_by_path(name); | 215 | stdout_node = of_find_node_by_path(name); |
218 | if (!stdout_node) | 216 | if (!stdout_node) |
219 | return; | 217 | return; |
220 | name = (char *)get_property(stdout_node, "name", NULL); | 218 | name = get_property(stdout_node, "name", NULL); |
221 | if (!name) { | 219 | if (!name) { |
222 | printk(KERN_WARNING "stdout node missing 'name' property!\n"); | 220 | printk(KERN_WARNING "stdout node missing 'name' property!\n"); |
223 | goto out; | 221 | goto out; |
@@ -228,7 +226,7 @@ void __init find_udbg_vterm(void) | |||
228 | /* Check if it's a virtual terminal */ | 226 | /* Check if it's a virtual terminal */ |
229 | if (strncmp(name, "vty", 3) != 0) | 227 | if (strncmp(name, "vty", 3) != 0) |
230 | goto out; | 228 | goto out; |
231 | termno = (u32 *)get_property(stdout_node, "reg", NULL); | 229 | termno = get_property(stdout_node, "reg", NULL); |
232 | if (termno == NULL) | 230 | if (termno == NULL) |
233 | goto out; | 231 | goto out; |
234 | vtermno = termno[0]; | 232 | vtermno = termno[0]; |
@@ -254,18 +252,34 @@ out: | |||
254 | void vpa_init(int cpu) | 252 | void vpa_init(int cpu) |
255 | { | 253 | { |
256 | int hwcpu = get_hard_smp_processor_id(cpu); | 254 | int hwcpu = get_hard_smp_processor_id(cpu); |
257 | unsigned long vpa = __pa(&lppaca[cpu]); | 255 | unsigned long addr; |
258 | long ret; | 256 | long ret; |
259 | 257 | ||
260 | if (cpu_has_feature(CPU_FTR_ALTIVEC)) | 258 | if (cpu_has_feature(CPU_FTR_ALTIVEC)) |
261 | lppaca[cpu].vmxregs_in_use = 1; | 259 | lppaca[cpu].vmxregs_in_use = 1; |
262 | 260 | ||
263 | ret = register_vpa(hwcpu, vpa); | 261 | addr = __pa(&lppaca[cpu]); |
262 | ret = register_vpa(hwcpu, addr); | ||
264 | 263 | ||
265 | if (ret) | 264 | if (ret) { |
266 | printk(KERN_ERR "WARNING: vpa_init: VPA registration for " | 265 | printk(KERN_ERR "WARNING: vpa_init: VPA registration for " |
267 | "cpu %d (hw %d) of area %lx returns %ld\n", | 266 | "cpu %d (hw %d) of area %lx returns %ld\n", |
268 | cpu, hwcpu, vpa, ret); | 267 | cpu, hwcpu, addr, ret); |
268 | return; | ||
269 | } | ||
270 | /* | ||
271 | * PAPR says this feature is SLB-Buffer but firmware never | ||
272 | * reports that. All SPLPAR support SLB shadow buffer. | ||
273 | */ | ||
274 | addr = __pa(&slb_shadow[cpu]); | ||
275 | if (firmware_has_feature(FW_FEATURE_SPLPAR)) { | ||
276 | ret = register_slb_shadow(hwcpu, addr); | ||
277 | if (ret) | ||
278 | printk(KERN_ERR | ||
279 | "WARNING: vpa_init: SLB shadow buffer " | ||
280 | "registration for cpu %d (hw %d) of area %lx " | ||
281 | "returns %ld\n", cpu, hwcpu, addr, ret); | ||
282 | } | ||
269 | } | 283 | } |
270 | 284 | ||
271 | long pSeries_lpar_hpte_insert(unsigned long hpte_group, | 285 | long pSeries_lpar_hpte_insert(unsigned long hpte_group, |
@@ -277,7 +291,6 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group, | |||
277 | unsigned long flags; | 291 | unsigned long flags; |
278 | unsigned long slot; | 292 | unsigned long slot; |
279 | unsigned long hpte_v, hpte_r; | 293 | unsigned long hpte_v, hpte_r; |
280 | unsigned long dummy0, dummy1; | ||
281 | 294 | ||
282 | if (!(vflags & HPTE_V_BOLTED)) | 295 | if (!(vflags & HPTE_V_BOLTED)) |
283 | DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, " | 296 | DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, " |
@@ -302,8 +315,7 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group, | |||
302 | if (rflags & (_PAGE_GUARDED|_PAGE_NO_CACHE)) | 315 | if (rflags & (_PAGE_GUARDED|_PAGE_NO_CACHE)) |
303 | hpte_r &= ~_PAGE_COHERENT; | 316 | hpte_r &= ~_PAGE_COHERENT; |
304 | 317 | ||
305 | lpar_rc = plpar_hcall(H_ENTER, flags, hpte_group, hpte_v, | 318 | lpar_rc = plpar_pte_enter(flags, hpte_group, hpte_v, hpte_r, &slot); |
306 | hpte_r, &slot, &dummy0, &dummy1); | ||
307 | if (unlikely(lpar_rc == H_PTEG_FULL)) { | 319 | if (unlikely(lpar_rc == H_PTEG_FULL)) { |
308 | if (!(vflags & HPTE_V_BOLTED)) | 320 | if (!(vflags & HPTE_V_BOLTED)) |
309 | DBG_LOW(" full\n"); | 321 | DBG_LOW(" full\n"); |
diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c index 18abfb1f4e24..64163cecdf93 100644 --- a/arch/powerpc/platforms/pseries/nvram.c +++ b/arch/powerpc/platforms/pseries/nvram.c | |||
@@ -123,13 +123,14 @@ static ssize_t pSeries_nvram_get_size(void) | |||
123 | int __init pSeries_nvram_init(void) | 123 | int __init pSeries_nvram_init(void) |
124 | { | 124 | { |
125 | struct device_node *nvram; | 125 | struct device_node *nvram; |
126 | unsigned int *nbytes_p, proplen; | 126 | const unsigned int *nbytes_p; |
127 | unsigned int proplen; | ||
127 | 128 | ||
128 | nvram = of_find_node_by_type(NULL, "nvram"); | 129 | nvram = of_find_node_by_type(NULL, "nvram"); |
129 | if (nvram == NULL) | 130 | if (nvram == NULL) |
130 | return -ENODEV; | 131 | return -ENODEV; |
131 | 132 | ||
132 | nbytes_p = (unsigned int *)get_property(nvram, "#bytes", &proplen); | 133 | nbytes_p = get_property(nvram, "#bytes", &proplen); |
133 | if (nbytes_p == NULL || proplen != sizeof(unsigned int)) | 134 | if (nbytes_p == NULL || proplen != sizeof(unsigned int)) |
134 | return -EIO; | 135 | return -EIO; |
135 | 136 | ||
diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c index e97e67f5e079..410a6bcc4ca0 100644 --- a/arch/powerpc/platforms/pseries/pci.c +++ b/arch/powerpc/platforms/pseries/pci.c | |||
@@ -60,7 +60,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device); | |||
60 | static void __devinit check_s7a(void) | 60 | static void __devinit check_s7a(void) |
61 | { | 61 | { |
62 | struct device_node *root; | 62 | struct device_node *root; |
63 | char *model; | 63 | const char *model; |
64 | 64 | ||
65 | s7a_workaround = 0; | 65 | s7a_workaround = 0; |
66 | root = of_find_node_by_path("/"); | 66 | root = of_find_node_by_path("/"); |
diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h index 3bd1b3e06003..3eb7b294d92f 100644 --- a/arch/powerpc/platforms/pseries/plpar_wrappers.h +++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h | |||
@@ -5,20 +5,17 @@ | |||
5 | 5 | ||
6 | static inline long poll_pending(void) | 6 | static inline long poll_pending(void) |
7 | { | 7 | { |
8 | unsigned long dummy; | 8 | return plpar_hcall_norets(H_POLL_PENDING); |
9 | return plpar_hcall(H_POLL_PENDING, 0, 0, 0, 0, &dummy, &dummy, &dummy); | ||
10 | } | 9 | } |
11 | 10 | ||
12 | static inline long prod_processor(void) | 11 | static inline long prod_processor(void) |
13 | { | 12 | { |
14 | plpar_hcall_norets(H_PROD); | 13 | return plpar_hcall_norets(H_PROD); |
15 | return 0; | ||
16 | } | 14 | } |
17 | 15 | ||
18 | static inline long cede_processor(void) | 16 | static inline long cede_processor(void) |
19 | { | 17 | { |
20 | plpar_hcall_norets(H_CEDE); | 18 | return plpar_hcall_norets(H_CEDE); |
21 | return 0; | ||
22 | } | 19 | } |
23 | 20 | ||
24 | static inline long vpa_call(unsigned long flags, unsigned long cpu, | 21 | static inline long vpa_call(unsigned long flags, unsigned long cpu, |
@@ -40,23 +37,59 @@ static inline long register_vpa(unsigned long cpu, unsigned long vpa) | |||
40 | return vpa_call(0x1, cpu, vpa); | 37 | return vpa_call(0x1, cpu, vpa); |
41 | } | 38 | } |
42 | 39 | ||
40 | static inline long unregister_slb_shadow(unsigned long cpu, unsigned long vpa) | ||
41 | { | ||
42 | return vpa_call(0x7, cpu, vpa); | ||
43 | } | ||
44 | |||
45 | static inline long register_slb_shadow(unsigned long cpu, unsigned long vpa) | ||
46 | { | ||
47 | return vpa_call(0x3, cpu, vpa); | ||
48 | } | ||
49 | |||
43 | extern void vpa_init(int cpu); | 50 | extern void vpa_init(int cpu); |
44 | 51 | ||
52 | static inline long plpar_pte_enter(unsigned long flags, | ||
53 | unsigned long hpte_group, unsigned long hpte_v, | ||
54 | unsigned long hpte_r, unsigned long *slot) | ||
55 | { | ||
56 | long rc; | ||
57 | unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; | ||
58 | |||
59 | rc = plpar_hcall(H_ENTER, retbuf, flags, hpte_group, hpte_v, hpte_r); | ||
60 | |||
61 | *slot = retbuf[0]; | ||
62 | |||
63 | return rc; | ||
64 | } | ||
65 | |||
45 | static inline long plpar_pte_remove(unsigned long flags, unsigned long ptex, | 66 | static inline long plpar_pte_remove(unsigned long flags, unsigned long ptex, |
46 | unsigned long avpn, unsigned long *old_pteh_ret, | 67 | unsigned long avpn, unsigned long *old_pteh_ret, |
47 | unsigned long *old_ptel_ret) | 68 | unsigned long *old_ptel_ret) |
48 | { | 69 | { |
49 | unsigned long dummy; | 70 | long rc; |
50 | return plpar_hcall(H_REMOVE, flags, ptex, avpn, 0, old_pteh_ret, | 71 | unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; |
51 | old_ptel_ret, &dummy); | 72 | |
73 | rc = plpar_hcall(H_REMOVE, retbuf, flags, ptex, avpn); | ||
74 | |||
75 | *old_pteh_ret = retbuf[0]; | ||
76 | *old_ptel_ret = retbuf[1]; | ||
77 | |||
78 | return rc; | ||
52 | } | 79 | } |
53 | 80 | ||
54 | static inline long plpar_pte_read(unsigned long flags, unsigned long ptex, | 81 | static inline long plpar_pte_read(unsigned long flags, unsigned long ptex, |
55 | unsigned long *old_pteh_ret, unsigned long *old_ptel_ret) | 82 | unsigned long *old_pteh_ret, unsigned long *old_ptel_ret) |
56 | { | 83 | { |
57 | unsigned long dummy; | 84 | long rc; |
58 | return plpar_hcall(H_READ, flags, ptex, 0, 0, old_pteh_ret, | 85 | unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; |
59 | old_ptel_ret, &dummy); | 86 | |
87 | rc = plpar_hcall(H_READ, retbuf, flags, ptex); | ||
88 | |||
89 | *old_pteh_ret = retbuf[0]; | ||
90 | *old_ptel_ret = retbuf[1]; | ||
91 | |||
92 | return rc; | ||
60 | } | 93 | } |
61 | 94 | ||
62 | static inline long plpar_pte_protect(unsigned long flags, unsigned long ptex, | 95 | static inline long plpar_pte_protect(unsigned long flags, unsigned long ptex, |
@@ -68,9 +101,14 @@ static inline long plpar_pte_protect(unsigned long flags, unsigned long ptex, | |||
68 | static inline long plpar_tce_get(unsigned long liobn, unsigned long ioba, | 101 | static inline long plpar_tce_get(unsigned long liobn, unsigned long ioba, |
69 | unsigned long *tce_ret) | 102 | unsigned long *tce_ret) |
70 | { | 103 | { |
71 | unsigned long dummy; | 104 | long rc; |
72 | return plpar_hcall(H_GET_TCE, liobn, ioba, 0, 0, tce_ret, &dummy, | 105 | unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; |
73 | &dummy); | 106 | |
107 | rc = plpar_hcall(H_GET_TCE, retbuf, liobn, ioba); | ||
108 | |||
109 | *tce_ret = retbuf[0]; | ||
110 | |||
111 | return rc; | ||
74 | } | 112 | } |
75 | 113 | ||
76 | static inline long plpar_tce_put(unsigned long liobn, unsigned long ioba, | 114 | static inline long plpar_tce_put(unsigned long liobn, unsigned long ioba, |
@@ -94,9 +132,17 @@ static inline long plpar_tce_stuff(unsigned long liobn, unsigned long ioba, | |||
94 | static inline long plpar_get_term_char(unsigned long termno, | 132 | static inline long plpar_get_term_char(unsigned long termno, |
95 | unsigned long *len_ret, char *buf_ret) | 133 | unsigned long *len_ret, char *buf_ret) |
96 | { | 134 | { |
135 | long rc; | ||
136 | unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; | ||
97 | unsigned long *lbuf = (unsigned long *)buf_ret; /* TODO: alignment? */ | 137 | unsigned long *lbuf = (unsigned long *)buf_ret; /* TODO: alignment? */ |
98 | return plpar_hcall(H_GET_TERM_CHAR, termno, 0, 0, 0, len_ret, | 138 | |
99 | lbuf + 0, lbuf + 1); | 139 | rc = plpar_hcall(H_GET_TERM_CHAR, retbuf, termno); |
140 | |||
141 | *len_ret = retbuf[0]; | ||
142 | lbuf[0] = retbuf[1]; | ||
143 | lbuf[1] = retbuf[2]; | ||
144 | |||
145 | return rc; | ||
100 | } | 146 | } |
101 | 147 | ||
102 | static inline long plpar_put_term_char(unsigned long termno, unsigned long len, | 148 | static inline long plpar_put_term_char(unsigned long termno, unsigned long len, |
@@ -107,4 +153,31 @@ static inline long plpar_put_term_char(unsigned long termno, unsigned long len, | |||
107 | lbuf[1]); | 153 | lbuf[1]); |
108 | } | 154 | } |
109 | 155 | ||
156 | static inline long plpar_eoi(unsigned long xirr) | ||
157 | { | ||
158 | return plpar_hcall_norets(H_EOI, xirr); | ||
159 | } | ||
160 | |||
161 | static inline long plpar_cppr(unsigned long cppr) | ||
162 | { | ||
163 | return plpar_hcall_norets(H_CPPR, cppr); | ||
164 | } | ||
165 | |||
166 | static inline long plpar_ipi(unsigned long servernum, unsigned long mfrr) | ||
167 | { | ||
168 | return plpar_hcall_norets(H_IPI, servernum, mfrr); | ||
169 | } | ||
170 | |||
171 | static inline long plpar_xirr(unsigned long *xirr_ret) | ||
172 | { | ||
173 | long rc; | ||
174 | unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; | ||
175 | |||
176 | rc = plpar_hcall(H_XIRR, retbuf); | ||
177 | |||
178 | *xirr_ret = retbuf[0]; | ||
179 | |||
180 | return rc; | ||
181 | } | ||
182 | |||
110 | #endif /* _PSERIES_PLPAR_WRAPPERS_H */ | 183 | #endif /* _PSERIES_PLPAR_WRAPPERS_H */ |
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c index c7ffde1a614e..903115d67fdc 100644 --- a/arch/powerpc/platforms/pseries/ras.c +++ b/arch/powerpc/platforms/pseries/ras.c | |||
@@ -79,7 +79,7 @@ static void request_ras_irqs(struct device_node *np, | |||
79 | { | 79 | { |
80 | int i, index, count = 0; | 80 | int i, index, count = 0; |
81 | struct of_irq oirq; | 81 | struct of_irq oirq; |
82 | u32 *opicprop; | 82 | const u32 *opicprop; |
83 | unsigned int opicplen; | 83 | unsigned int opicplen; |
84 | unsigned int virqs[16]; | 84 | unsigned int virqs[16]; |
85 | 85 | ||
@@ -87,7 +87,7 @@ static void request_ras_irqs(struct device_node *np, | |||
87 | * map those interrupts using the default interrupt host and default | 87 | * map those interrupts using the default interrupt host and default |
88 | * trigger | 88 | * trigger |
89 | */ | 89 | */ |
90 | opicprop = (u32 *)get_property(np, "open-pic-interrupt", &opicplen); | 90 | opicprop = get_property(np, "open-pic-interrupt", &opicplen); |
91 | if (opicprop) { | 91 | if (opicprop) { |
92 | opicplen /= sizeof(u32); | 92 | opicplen /= sizeof(u32); |
93 | for (i = 0; i < opicplen; i++) { | 93 | for (i = 0; i < opicplen; i++) { |
diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c index 2e4e04042d85..8ca2612221d6 100644 --- a/arch/powerpc/platforms/pseries/rtasd.c +++ b/arch/powerpc/platforms/pseries/rtasd.c | |||
@@ -359,11 +359,11 @@ static int enable_surveillance(int timeout) | |||
359 | static int get_eventscan_parms(void) | 359 | static int get_eventscan_parms(void) |
360 | { | 360 | { |
361 | struct device_node *node; | 361 | struct device_node *node; |
362 | int *ip; | 362 | const int *ip; |
363 | 363 | ||
364 | node = of_find_node_by_path("/rtas"); | 364 | node = of_find_node_by_path("/rtas"); |
365 | 365 | ||
366 | ip = (int *)get_property(node, "rtas-event-scan-rate", NULL); | 366 | ip = get_property(node, "rtas-event-scan-rate", NULL); |
367 | if (ip == NULL) { | 367 | if (ip == NULL) { |
368 | printk(KERN_ERR "rtasd: no rtas-event-scan-rate\n"); | 368 | printk(KERN_ERR "rtasd: no rtas-event-scan-rate\n"); |
369 | of_node_put(node); | 369 | of_node_put(node); |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 31867a701fcb..a6398fbe530d 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -133,9 +133,9 @@ void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc, | |||
133 | static void __init pseries_mpic_init_IRQ(void) | 133 | static void __init pseries_mpic_init_IRQ(void) |
134 | { | 134 | { |
135 | struct device_node *np, *old, *cascade = NULL; | 135 | struct device_node *np, *old, *cascade = NULL; |
136 | unsigned int *addrp; | 136 | const unsigned int *addrp; |
137 | unsigned long intack = 0; | 137 | unsigned long intack = 0; |
138 | unsigned int *opprop; | 138 | const unsigned int *opprop; |
139 | unsigned long openpic_addr = 0; | 139 | unsigned long openpic_addr = 0; |
140 | unsigned int cascade_irq; | 140 | unsigned int cascade_irq; |
141 | int naddr, n, i, opplen; | 141 | int naddr, n, i, opplen; |
@@ -143,7 +143,7 @@ static void __init pseries_mpic_init_IRQ(void) | |||
143 | 143 | ||
144 | np = of_find_node_by_path("/"); | 144 | np = of_find_node_by_path("/"); |
145 | naddr = prom_n_addr_cells(np); | 145 | naddr = prom_n_addr_cells(np); |
146 | opprop = (unsigned int *) get_property(np, "platform-open-pic", &opplen); | 146 | opprop = get_property(np, "platform-open-pic", &opplen); |
147 | if (opprop != 0) { | 147 | if (opprop != 0) { |
148 | openpic_addr = of_read_number(opprop, naddr); | 148 | openpic_addr = of_read_number(opprop, naddr); |
149 | printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr); | 149 | printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr); |
@@ -192,7 +192,7 @@ static void __init pseries_mpic_init_IRQ(void) | |||
192 | break; | 192 | break; |
193 | if (strcmp(np->name, "pci") != 0) | 193 | if (strcmp(np->name, "pci") != 0) |
194 | continue; | 194 | continue; |
195 | addrp = (u32 *)get_property(np, "8259-interrupt-acknowledge", | 195 | addrp = get_property(np, "8259-interrupt-acknowledge", |
196 | NULL); | 196 | NULL); |
197 | if (addrp == NULL) | 197 | if (addrp == NULL) |
198 | continue; | 198 | continue; |
@@ -223,23 +223,37 @@ static void pseries_lpar_enable_pmcs(void) | |||
223 | } | 223 | } |
224 | 224 | ||
225 | #ifdef CONFIG_KEXEC | 225 | #ifdef CONFIG_KEXEC |
226 | static void pseries_kexec_cpu_down_mpic(int crash_shutdown, int secondary) | 226 | static void pseries_kexec_cpu_down(int crash_shutdown, int secondary) |
227 | { | ||
228 | mpic_teardown_this_cpu(secondary); | ||
229 | } | ||
230 | |||
231 | static void pseries_kexec_cpu_down_xics(int crash_shutdown, int secondary) | ||
232 | { | 227 | { |
233 | /* Don't risk a hypervisor call if we're crashing */ | 228 | /* Don't risk a hypervisor call if we're crashing */ |
234 | if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) { | 229 | if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) { |
235 | unsigned long vpa = __pa(get_lppaca()); | 230 | unsigned long addr; |
236 | 231 | ||
237 | if (unregister_vpa(hard_smp_processor_id(), vpa)) { | 232 | addr = __pa(get_slb_shadow()); |
233 | if (unregister_slb_shadow(hard_smp_processor_id(), addr)) | ||
234 | printk("SLB shadow buffer deregistration of " | ||
235 | "cpu %u (hw_cpu_id %d) failed\n", | ||
236 | smp_processor_id(), | ||
237 | hard_smp_processor_id()); | ||
238 | |||
239 | addr = __pa(get_lppaca()); | ||
240 | if (unregister_vpa(hard_smp_processor_id(), addr)) { | ||
238 | printk("VPA deregistration of cpu %u (hw_cpu_id %d) " | 241 | printk("VPA deregistration of cpu %u (hw_cpu_id %d) " |
239 | "failed\n", smp_processor_id(), | 242 | "failed\n", smp_processor_id(), |
240 | hard_smp_processor_id()); | 243 | hard_smp_processor_id()); |
241 | } | 244 | } |
242 | } | 245 | } |
246 | } | ||
247 | |||
248 | static void pseries_kexec_cpu_down_mpic(int crash_shutdown, int secondary) | ||
249 | { | ||
250 | pseries_kexec_cpu_down(crash_shutdown, secondary); | ||
251 | mpic_teardown_this_cpu(secondary); | ||
252 | } | ||
253 | |||
254 | static void pseries_kexec_cpu_down_xics(int crash_shutdown, int secondary) | ||
255 | { | ||
256 | pseries_kexec_cpu_down(crash_shutdown, secondary); | ||
243 | xics_teardown_cpu(secondary); | 257 | xics_teardown_cpu(secondary); |
244 | } | 258 | } |
245 | #endif /* CONFIG_KEXEC */ | 259 | #endif /* CONFIG_KEXEC */ |
@@ -247,11 +261,11 @@ static void pseries_kexec_cpu_down_xics(int crash_shutdown, int secondary) | |||
247 | static void __init pseries_discover_pic(void) | 261 | static void __init pseries_discover_pic(void) |
248 | { | 262 | { |
249 | struct device_node *np; | 263 | struct device_node *np; |
250 | char *typep; | 264 | const char *typep; |
251 | 265 | ||
252 | for (np = NULL; (np = of_find_node_by_name(np, | 266 | for (np = NULL; (np = of_find_node_by_name(np, |
253 | "interrupt-controller"));) { | 267 | "interrupt-controller"));) { |
254 | typep = (char *)get_property(np, "compatible", NULL); | 268 | typep = get_property(np, "compatible", NULL); |
255 | if (strstr(typep, "open-pic")) { | 269 | if (strstr(typep, "open-pic")) { |
256 | pSeries_mpic_node = of_node_get(np); | 270 | pSeries_mpic_node = of_node_get(np); |
257 | ppc_md.init_IRQ = pseries_mpic_init_IRQ; | 271 | ppc_md.init_IRQ = pseries_mpic_init_IRQ; |
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index ac61098ff401..c6624b8a0e77 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c | |||
@@ -62,7 +62,7 @@ | |||
62 | */ | 62 | */ |
63 | static cpumask_t of_spin_map; | 63 | static cpumask_t of_spin_map; |
64 | 64 | ||
65 | extern void pSeries_secondary_smp_init(unsigned long); | 65 | extern void generic_secondary_smp_init(unsigned long); |
66 | 66 | ||
67 | #ifdef CONFIG_HOTPLUG_CPU | 67 | #ifdef CONFIG_HOTPLUG_CPU |
68 | 68 | ||
@@ -145,9 +145,9 @@ static int pSeries_add_processor(struct device_node *np) | |||
145 | unsigned int cpu; | 145 | unsigned int cpu; |
146 | cpumask_t candidate_map, tmp = CPU_MASK_NONE; | 146 | cpumask_t candidate_map, tmp = CPU_MASK_NONE; |
147 | int err = -ENOSPC, len, nthreads, i; | 147 | int err = -ENOSPC, len, nthreads, i; |
148 | u32 *intserv; | 148 | const u32 *intserv; |
149 | 149 | ||
150 | intserv = (u32 *)get_property(np, "ibm,ppc-interrupt-server#s", &len); | 150 | intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len); |
151 | if (!intserv) | 151 | if (!intserv) |
152 | return 0; | 152 | return 0; |
153 | 153 | ||
@@ -205,9 +205,9 @@ static void pSeries_remove_processor(struct device_node *np) | |||
205 | { | 205 | { |
206 | unsigned int cpu; | 206 | unsigned int cpu; |
207 | int len, nthreads, i; | 207 | int len, nthreads, i; |
208 | u32 *intserv; | 208 | const u32 *intserv; |
209 | 209 | ||
210 | intserv = (u32 *)get_property(np, "ibm,ppc-interrupt-server#s", &len); | 210 | intserv = get_property(np, "ibm,ppc-interrupt-server#s", &len); |
211 | if (!intserv) | 211 | if (!intserv) |
212 | return; | 212 | return; |
213 | 213 | ||
@@ -270,7 +270,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu) | |||
270 | { | 270 | { |
271 | int status; | 271 | int status; |
272 | unsigned long start_here = __pa((u32)*((unsigned long *) | 272 | unsigned long start_here = __pa((u32)*((unsigned long *) |
273 | pSeries_secondary_smp_init)); | 273 | generic_secondary_smp_init)); |
274 | unsigned int pcpu; | 274 | unsigned int pcpu; |
275 | int start_cpu; | 275 | int start_cpu; |
276 | 276 | ||
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index e98863025721..253972e5479f 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <asm/i8259.h> | 34 | #include <asm/i8259.h> |
35 | 35 | ||
36 | #include "xics.h" | 36 | #include "xics.h" |
37 | #include "plpar_wrappers.h" | ||
37 | 38 | ||
38 | #define XICS_IPI 2 | 39 | #define XICS_IPI 2 |
39 | #define XICS_IRQ_SPURIOUS 0 | 40 | #define XICS_IRQ_SPURIOUS 0 |
@@ -110,27 +111,6 @@ static inline void direct_qirr_info(int n_cpu, u8 value) | |||
110 | /* LPAR low level accessors */ | 111 | /* LPAR low level accessors */ |
111 | 112 | ||
112 | 113 | ||
113 | static inline long plpar_eoi(unsigned long xirr) | ||
114 | { | ||
115 | return plpar_hcall_norets(H_EOI, xirr); | ||
116 | } | ||
117 | |||
118 | static inline long plpar_cppr(unsigned long cppr) | ||
119 | { | ||
120 | return plpar_hcall_norets(H_CPPR, cppr); | ||
121 | } | ||
122 | |||
123 | static inline long plpar_ipi(unsigned long servernum, unsigned long mfrr) | ||
124 | { | ||
125 | return plpar_hcall_norets(H_IPI, servernum, mfrr); | ||
126 | } | ||
127 | |||
128 | static inline long plpar_xirr(unsigned long *xirr_ret) | ||
129 | { | ||
130 | unsigned long dummy; | ||
131 | return plpar_hcall(H_XIRR, 0, 0, 0, 0, xirr_ret, &dummy, &dummy); | ||
132 | } | ||
133 | |||
134 | static inline unsigned int lpar_xirr_info_get(int n_cpu) | 114 | static inline unsigned int lpar_xirr_info_get(int n_cpu) |
135 | { | 115 | { |
136 | unsigned long lpar_rc; | 116 | unsigned long lpar_rc; |
@@ -590,14 +570,14 @@ static void __init xics_init_one_node(struct device_node *np, | |||
590 | unsigned int *indx) | 570 | unsigned int *indx) |
591 | { | 571 | { |
592 | unsigned int ilen; | 572 | unsigned int ilen; |
593 | u32 *ireg; | 573 | const u32 *ireg; |
594 | 574 | ||
595 | /* This code does the theorically broken assumption that the interrupt | 575 | /* This code does the theorically broken assumption that the interrupt |
596 | * server numbers are the same as the hard CPU numbers. | 576 | * server numbers are the same as the hard CPU numbers. |
597 | * This happens to be the case so far but we are playing with fire... | 577 | * This happens to be the case so far but we are playing with fire... |
598 | * should be fixed one of these days. -BenH. | 578 | * should be fixed one of these days. -BenH. |
599 | */ | 579 | */ |
600 | ireg = (u32 *)get_property(np, "ibm,interrupt-server-ranges", NULL); | 580 | ireg = get_property(np, "ibm,interrupt-server-ranges", NULL); |
601 | 581 | ||
602 | /* Do that ever happen ? we'll know soon enough... but even good'old | 582 | /* Do that ever happen ? we'll know soon enough... but even good'old |
603 | * f80 does have that property .. | 583 | * f80 does have that property .. |
@@ -609,7 +589,7 @@ static void __init xics_init_one_node(struct device_node *np, | |||
609 | */ | 589 | */ |
610 | *indx = *ireg; | 590 | *indx = *ireg; |
611 | } | 591 | } |
612 | ireg = (u32 *)get_property(np, "reg", &ilen); | 592 | ireg = get_property(np, "reg", &ilen); |
613 | if (!ireg) | 593 | if (!ireg) |
614 | panic("xics_init_IRQ: can't find interrupt reg property"); | 594 | panic("xics_init_IRQ: can't find interrupt reg property"); |
615 | 595 | ||
@@ -635,7 +615,7 @@ static void __init xics_setup_8259_cascade(void) | |||
635 | { | 615 | { |
636 | struct device_node *np, *old, *found = NULL; | 616 | struct device_node *np, *old, *found = NULL; |
637 | int cascade, naddr; | 617 | int cascade, naddr; |
638 | u32 *addrp; | 618 | const u32 *addrp; |
639 | unsigned long intack = 0; | 619 | unsigned long intack = 0; |
640 | 620 | ||
641 | for_each_node_by_type(np, "interrupt-controller") | 621 | for_each_node_by_type(np, "interrupt-controller") |
@@ -661,7 +641,7 @@ static void __init xics_setup_8259_cascade(void) | |||
661 | break; | 641 | break; |
662 | if (strcmp(np->name, "pci") != 0) | 642 | if (strcmp(np->name, "pci") != 0) |
663 | continue; | 643 | continue; |
664 | addrp = (u32 *)get_property(np, "8259-interrupt-acknowledge", NULL); | 644 | addrp = get_property(np, "8259-interrupt-acknowledge", NULL); |
665 | if (addrp == NULL) | 645 | if (addrp == NULL) |
666 | continue; | 646 | continue; |
667 | naddr = prom_n_addr_cells(np); | 647 | naddr = prom_n_addr_cells(np); |
@@ -680,7 +660,8 @@ void __init xics_init_IRQ(void) | |||
680 | { | 660 | { |
681 | int i; | 661 | int i; |
682 | struct device_node *np; | 662 | struct device_node *np; |
683 | u32 *ireg, ilen, indx = 0; | 663 | u32 ilen, indx = 0; |
664 | const u32 *ireg; | ||
684 | int found = 0; | 665 | int found = 0; |
685 | 666 | ||
686 | ppc64_boot_msg(0x20, "XICS Init"); | 667 | ppc64_boot_msg(0x20, "XICS Init"); |
@@ -705,18 +686,17 @@ void __init xics_init_IRQ(void) | |||
705 | for (np = of_find_node_by_type(NULL, "cpu"); | 686 | for (np = of_find_node_by_type(NULL, "cpu"); |
706 | np; | 687 | np; |
707 | np = of_find_node_by_type(np, "cpu")) { | 688 | np = of_find_node_by_type(np, "cpu")) { |
708 | ireg = (u32 *)get_property(np, "reg", &ilen); | 689 | ireg = get_property(np, "reg", &ilen); |
709 | if (ireg && ireg[0] == get_hard_smp_processor_id(boot_cpuid)) { | 690 | if (ireg && ireg[0] == get_hard_smp_processor_id(boot_cpuid)) { |
710 | ireg = (u32 *)get_property(np, | 691 | ireg = get_property(np, |
711 | "ibm,ppc-interrupt-gserver#s", | 692 | "ibm,ppc-interrupt-gserver#s", &ilen); |
712 | &ilen); | ||
713 | i = ilen / sizeof(int); | 693 | i = ilen / sizeof(int); |
714 | if (ireg && i > 0) { | 694 | if (ireg && i > 0) { |
715 | default_server = ireg[0]; | 695 | default_server = ireg[0]; |
716 | /* take last element */ | 696 | /* take last element */ |
717 | default_distrib_server = ireg[i-1]; | 697 | default_distrib_server = ireg[i-1]; |
718 | } | 698 | } |
719 | ireg = (u32 *)get_property(np, | 699 | ireg = get_property(np, |
720 | "ibm,interrupt-server#-size", NULL); | 700 | "ibm,interrupt-server#-size", NULL); |
721 | if (ireg) | 701 | if (ireg) |
722 | interrupt_server_size = *ireg; | 702 | interrupt_server_size = *ireg; |