aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc64
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc64')
-rw-r--r--arch/ppc64/Kconfig2
-rw-r--r--arch/ppc64/Makefile6
-rw-r--r--arch/ppc64/kernel/HvLpEvent.c2
-rw-r--r--arch/ppc64/kernel/ItLpQueue.c1
-rw-r--r--arch/ppc64/kernel/Makefile7
-rw-r--r--arch/ppc64/kernel/XmPciLpEvent.c190
-rw-r--r--arch/ppc64/kernel/asm-offsets.c1
-rw-r--r--arch/ppc64/kernel/dma.c4
-rw-r--r--arch/ppc64/kernel/eeh.c2
-rw-r--r--arch/ppc64/kernel/head.S4
-rw-r--r--arch/ppc64/kernel/iSeries_VpdInfo.c220
-rw-r--r--arch/ppc64/kernel/iSeries_iommu.c3
-rw-r--r--arch/ppc64/kernel/iSeries_irq.c312
-rw-r--r--arch/ppc64/kernel/iSeries_pci.c45
-rw-r--r--arch/ppc64/kernel/iSeries_pci_reset.c104
-rw-r--r--arch/ppc64/kernel/iSeries_proc.c3
-rw-r--r--arch/ppc64/kernel/iSeries_setup.c14
-rw-r--r--arch/ppc64/kernel/iSeries_smp.c2
-rw-r--r--arch/ppc64/kernel/idle.c7
-rw-r--r--arch/ppc64/kernel/iommu.c3
-rw-r--r--arch/ppc64/kernel/irq.c2
-rw-r--r--arch/ppc64/kernel/lparcfg.c2
-rw-r--r--arch/ppc64/kernel/mf.c1
-rw-r--r--arch/ppc64/kernel/of_device.c2
-rw-r--r--arch/ppc64/kernel/pSeries_smp.c9
-rw-r--r--arch/ppc64/kernel/pci.c2
-rw-r--r--arch/ppc64/kernel/process.c8
-rw-r--r--arch/ppc64/kernel/prom.c12
-rw-r--r--arch/ppc64/kernel/ras.c1
-rw-r--r--arch/ppc64/kernel/rtasd.c4
-rw-r--r--arch/ppc64/kernel/rtc.c2
-rw-r--r--arch/ppc64/kernel/setup.c3
-rw-r--r--arch/ppc64/kernel/sys_ppc32.c3
-rw-r--r--arch/ppc64/kernel/vio.c41
-rw-r--r--arch/ppc64/kernel/viopath.c10
-rw-r--r--arch/ppc64/lib/Makefile2
-rw-r--r--arch/ppc64/mm/hash_utils.c6
-rw-r--r--arch/ppc64/mm/hugetlbpage.c214
-rw-r--r--arch/ppc64/mm/imalloc.c20
-rw-r--r--arch/ppc64/mm/init.c93
-rw-r--r--arch/ppc64/xmon/xmon.c9
41 files changed, 502 insertions, 876 deletions
diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
index 5cb343883e4d..0f1fa289744e 100644
--- a/arch/ppc64/Kconfig
+++ b/arch/ppc64/Kconfig
@@ -323,7 +323,7 @@ config EISA
323 bool 323 bool
324 324
325config PCI 325config PCI
326 bool 326 bool "support for PCI devices" if (EMBEDDED && PPC_ISERIES)
327 default y 327 default y
328 help 328 help
329 Find out whether your system includes a PCI bus. PCI is the name of 329 Find out whether your system includes a PCI bus. PCI is the name of
diff --git a/arch/ppc64/Makefile b/arch/ppc64/Makefile
index 691f3008e698..33c752ceca4b 100644
--- a/arch/ppc64/Makefile
+++ b/arch/ppc64/Makefile
@@ -35,9 +35,9 @@ CROSS32AS := $(AS) -a32
35CROSS32LD := $(LD) -m elf32ppc 35CROSS32LD := $(LD) -m elf32ppc
36CROSS32OBJCOPY := $(OBJCOPY) 36CROSS32OBJCOPY := $(OBJCOPY)
37endif 37endif
38AS := $(AS) -a64 38override AS += -a64
39LD := $(LD) -m elf64ppc 39override LD += -m elf64ppc
40CC := $(CC) -m64 40override CC += -m64
41endif 41endif
42 42
43export CROSS32CC CROSS32AS CROSS32LD CROSS32OBJCOPY 43export CROSS32CC CROSS32AS CROSS32LD CROSS32OBJCOPY
diff --git a/arch/ppc64/kernel/HvLpEvent.c b/arch/ppc64/kernel/HvLpEvent.c
index f8f19637f73f..90032b138902 100644
--- a/arch/ppc64/kernel/HvLpEvent.c
+++ b/arch/ppc64/kernel/HvLpEvent.c
@@ -12,7 +12,7 @@
12#include <asm/system.h> 12#include <asm/system.h>
13#include <asm/iSeries/HvLpEvent.h> 13#include <asm/iSeries/HvLpEvent.h>
14#include <asm/iSeries/HvCallEvent.h> 14#include <asm/iSeries/HvCallEvent.h>
15#include <asm/iSeries/LparData.h> 15#include <asm/iSeries/ItLpNaca.h>
16 16
17/* Array of LpEvent handler functions */ 17/* Array of LpEvent handler functions */
18LpEventHandler lpEventHandler[HvLpEvent_Type_NumTypes]; 18LpEventHandler lpEventHandler[HvLpEvent_Type_NumTypes];
diff --git a/arch/ppc64/kernel/ItLpQueue.c b/arch/ppc64/kernel/ItLpQueue.c
index c923a815760e..cdea00d7707f 100644
--- a/arch/ppc64/kernel/ItLpQueue.c
+++ b/arch/ppc64/kernel/ItLpQueue.c
@@ -16,7 +16,6 @@
16#include <asm/iSeries/ItLpQueue.h> 16#include <asm/iSeries/ItLpQueue.h>
17#include <asm/iSeries/HvLpEvent.h> 17#include <asm/iSeries/HvLpEvent.h>
18#include <asm/iSeries/HvCallEvent.h> 18#include <asm/iSeries/HvCallEvent.h>
19#include <asm/iSeries/LparData.h>
20 19
21static __inline__ int set_inUse( struct ItLpQueue * lpQueue ) 20static __inline__ int set_inUse( struct ItLpQueue * lpQueue )
22{ 21{
diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
index 96d90b0c5119..b5e167cf1a05 100644
--- a/arch/ppc64/kernel/Makefile
+++ b/arch/ppc64/kernel/Makefile
@@ -16,14 +16,13 @@ obj-y += vdso32/ vdso64/
16 16
17obj-$(CONFIG_PPC_OF) += of_device.o 17obj-$(CONFIG_PPC_OF) += of_device.o
18 18
19pci-obj-$(CONFIG_PPC_ISERIES) += iSeries_pci.o iSeries_pci_reset.o 19pci-obj-$(CONFIG_PPC_ISERIES) += iSeries_pci.o iSeries_irq.o \
20 iSeries_VpdInfo.o
20pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += pci_dn.o pci_direct_iommu.o 21pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += pci_dn.o pci_direct_iommu.o
21 22
22obj-$(CONFIG_PCI) += pci.o pci_iommu.o iomap.o $(pci-obj-y) 23obj-$(CONFIG_PCI) += pci.o pci_iommu.o iomap.o $(pci-obj-y)
23 24
24obj-$(CONFIG_PPC_ISERIES) += iSeries_irq.o \ 25obj-$(CONFIG_PPC_ISERIES) += HvCall.o HvLpConfig.o LparData.o \
25 iSeries_VpdInfo.o XmPciLpEvent.o \
26 HvCall.o HvLpConfig.o LparData.o \
27 iSeries_setup.o ItLpQueue.o hvCall.o \ 26 iSeries_setup.o ItLpQueue.o hvCall.o \
28 mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \ 27 mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \
29 iSeries_iommu.o 28 iSeries_iommu.o
diff --git a/arch/ppc64/kernel/XmPciLpEvent.c b/arch/ppc64/kernel/XmPciLpEvent.c
deleted file mode 100644
index 809c9bc6678b..000000000000
--- a/arch/ppc64/kernel/XmPciLpEvent.c
+++ /dev/null
@@ -1,190 +0,0 @@
1/*
2 * File XmPciLpEvent.h created by Wayne Holm on Mon Jan 15 2001.
3 *
4 * This module handles PCI interrupt events sent by the iSeries Hypervisor.
5*/
6
7#include <linux/config.h>
8#include <linux/pci.h>
9#include <linux/init.h>
10#include <linux/threads.h>
11#include <linux/smp.h>
12#include <linux/param.h>
13#include <linux/string.h>
14#include <linux/bootmem.h>
15#include <linux/ide.h>
16
17#include <asm/iSeries/HvTypes.h>
18#include <asm/iSeries/HvLpEvent.h>
19#include <asm/iSeries/HvCallPci.h>
20#include <asm/iSeries/XmPciLpEvent.h>
21#include <asm/ppcdebug.h>
22
23static long Pci_Interrupt_Count;
24static long Pci_Event_Count;
25
26enum XmPciLpEvent_Subtype {
27 XmPciLpEvent_BusCreated = 0, // PHB has been created
28 XmPciLpEvent_BusError = 1, // PHB has failed
29 XmPciLpEvent_BusFailed = 2, // Msg to Secondary, Primary failed bus
30 XmPciLpEvent_NodeFailed = 4, // Multi-adapter bridge has failed
31 XmPciLpEvent_NodeRecovered = 5, // Multi-adapter bridge has recovered
32 XmPciLpEvent_BusRecovered = 12, // PHB has been recovered
33 XmPciLpEvent_UnQuiesceBus = 18, // Secondary bus unqiescing
34 XmPciLpEvent_BridgeError = 21, // Bridge Error
35 XmPciLpEvent_SlotInterrupt = 22 // Slot interrupt
36};
37
38struct XmPciLpEvent_BusInterrupt {
39 HvBusNumber busNumber;
40 HvSubBusNumber subBusNumber;
41};
42
43struct XmPciLpEvent_NodeInterrupt {
44 HvBusNumber busNumber;
45 HvSubBusNumber subBusNumber;
46 HvAgentId deviceId;
47};
48
49struct XmPciLpEvent {
50 struct HvLpEvent hvLpEvent;
51
52 union {
53 u64 alignData; // Align on an 8-byte boundary
54
55 struct {
56 u32 fisr;
57 HvBusNumber busNumber;
58 HvSubBusNumber subBusNumber;
59 HvAgentId deviceId;
60 } slotInterrupt;
61
62 struct XmPciLpEvent_BusInterrupt busFailed;
63 struct XmPciLpEvent_BusInterrupt busRecovered;
64 struct XmPciLpEvent_BusInterrupt busCreated;
65
66 struct XmPciLpEvent_NodeInterrupt nodeFailed;
67 struct XmPciLpEvent_NodeInterrupt nodeRecovered;
68
69 } eventData;
70
71};
72
73static void intReceived(struct XmPciLpEvent *eventParm,
74 struct pt_regs *regsParm);
75
76static void XmPciLpEvent_handler(struct HvLpEvent *eventParm,
77 struct pt_regs *regsParm)
78{
79#ifdef CONFIG_PCI
80#if 0
81 PPCDBG(PPCDBG_BUSWALK, "XmPciLpEvent_handler, type 0x%x\n",
82 eventParm->xType);
83#endif
84 ++Pci_Event_Count;
85
86 if (eventParm && (eventParm->xType == HvLpEvent_Type_PciIo)) {
87 switch (eventParm->xFlags.xFunction) {
88 case HvLpEvent_Function_Int:
89 intReceived((struct XmPciLpEvent *)eventParm, regsParm);
90 break;
91 case HvLpEvent_Function_Ack:
92 printk(KERN_ERR
93 "XmPciLpEvent.c: unexpected ack received\n");
94 break;
95 default:
96 printk(KERN_ERR
97 "XmPciLpEvent.c: unexpected event function %d\n",
98 (int)eventParm->xFlags.xFunction);
99 break;
100 }
101 } else if (eventParm)
102 printk(KERN_ERR
103 "XmPciLpEvent.c: Unrecognized PCI event type 0x%x\n",
104 (int)eventParm->xType);
105 else
106 printk(KERN_ERR "XmPciLpEvent.c: NULL event received\n");
107#endif
108}
109
110static void intReceived(struct XmPciLpEvent *eventParm,
111 struct pt_regs *regsParm)
112{
113 int irq;
114
115 ++Pci_Interrupt_Count;
116#if 0
117 PPCDBG(PPCDBG_BUSWALK, "PCI: XmPciLpEvent.c: intReceived\n");
118#endif
119
120 switch (eventParm->hvLpEvent.xSubtype) {
121 case XmPciLpEvent_SlotInterrupt:
122 irq = eventParm->hvLpEvent.xCorrelationToken;
123 /* Dispatch the interrupt handlers for this irq */
124 ppc_irq_dispatch_handler(regsParm, irq);
125 HvCallPci_eoi(eventParm->eventData.slotInterrupt.busNumber,
126 eventParm->eventData.slotInterrupt.subBusNumber,
127 eventParm->eventData.slotInterrupt.deviceId);
128 break;
129 /* Ignore error recovery events for now */
130 case XmPciLpEvent_BusCreated:
131 printk(KERN_INFO "XmPciLpEvent.c: system bus %d created\n",
132 eventParm->eventData.busCreated.busNumber);
133 break;
134 case XmPciLpEvent_BusError:
135 case XmPciLpEvent_BusFailed:
136 printk(KERN_INFO "XmPciLpEvent.c: system bus %d failed\n",
137 eventParm->eventData.busFailed.busNumber);
138 break;
139 case XmPciLpEvent_BusRecovered:
140 case XmPciLpEvent_UnQuiesceBus:
141 printk(KERN_INFO "XmPciLpEvent.c: system bus %d recovered\n",
142 eventParm->eventData.busRecovered.busNumber);
143 break;
144 case XmPciLpEvent_NodeFailed:
145 case XmPciLpEvent_BridgeError:
146 printk(KERN_INFO
147 "XmPciLpEvent.c: multi-adapter bridge %d/%d/%d failed\n",
148 eventParm->eventData.nodeFailed.busNumber,
149 eventParm->eventData.nodeFailed.subBusNumber,
150 eventParm->eventData.nodeFailed.deviceId);
151 break;
152 case XmPciLpEvent_NodeRecovered:
153 printk(KERN_INFO
154 "XmPciLpEvent.c: multi-adapter bridge %d/%d/%d recovered\n",
155 eventParm->eventData.nodeRecovered.busNumber,
156 eventParm->eventData.nodeRecovered.subBusNumber,
157 eventParm->eventData.nodeRecovered.deviceId);
158 break;
159 default:
160 printk(KERN_ERR
161 "XmPciLpEvent.c: unrecognized event subtype 0x%x\n",
162 eventParm->hvLpEvent.xSubtype);
163 break;
164 }
165}
166
167
168/* This should be called sometime prior to buswalk (init_IRQ would be good) */
169int XmPciLpEvent_init()
170{
171 int xRc;
172
173 PPCDBG(PPCDBG_BUSWALK,
174 "XmPciLpEvent_init, Register Event type 0x%04X\n",
175 HvLpEvent_Type_PciIo);
176
177 xRc = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo,
178 &XmPciLpEvent_handler);
179 if (xRc == 0) {
180 xRc = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
181 if (xRc != 0)
182 printk(KERN_ERR
183 "XmPciLpEvent.c: open event path failed with rc 0x%x\n",
184 xRc);
185 } else
186 printk(KERN_ERR
187 "XmPciLpEvent.c: register handler failed with rc 0x%x\n",
188 xRc);
189 return xRc;
190}
diff --git a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c
index 0094ac79a18c..abb9e5b5da03 100644
--- a/arch/ppc64/kernel/asm-offsets.c
+++ b/arch/ppc64/kernel/asm-offsets.c
@@ -31,7 +31,6 @@
31 31
32#include <asm/paca.h> 32#include <asm/paca.h>
33#include <asm/lppaca.h> 33#include <asm/lppaca.h>
34#include <asm/iSeries/ItLpQueue.h>
35#include <asm/iSeries/HvLpEvent.h> 34#include <asm/iSeries/HvLpEvent.h>
36#include <asm/rtas.h> 35#include <asm/rtas.h>
37#include <asm/cputable.h> 36#include <asm/cputable.h>
diff --git a/arch/ppc64/kernel/dma.c b/arch/ppc64/kernel/dma.c
index ce714c927134..4da8e31b2b61 100644
--- a/arch/ppc64/kernel/dma.c
+++ b/arch/ppc64/kernel/dma.c
@@ -15,8 +15,10 @@
15 15
16static struct dma_mapping_ops *get_dma_ops(struct device *dev) 16static struct dma_mapping_ops *get_dma_ops(struct device *dev)
17{ 17{
18#ifdef CONFIG_PCI
18 if (dev->bus == &pci_bus_type) 19 if (dev->bus == &pci_bus_type)
19 return &pci_dma_ops; 20 return &pci_dma_ops;
21#endif
20#ifdef CONFIG_IBMVIO 22#ifdef CONFIG_IBMVIO
21 if (dev->bus == &vio_bus_type) 23 if (dev->bus == &vio_bus_type)
22 return &vio_dma_ops; 24 return &vio_dma_ops;
@@ -37,8 +39,10 @@ EXPORT_SYMBOL(dma_supported);
37 39
38int dma_set_mask(struct device *dev, u64 dma_mask) 40int dma_set_mask(struct device *dev, u64 dma_mask)
39{ 41{
42#ifdef CONFIG_PCI
40 if (dev->bus == &pci_bus_type) 43 if (dev->bus == &pci_bus_type)
41 return pci_set_dma_mask(to_pci_dev(dev), dma_mask); 44 return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
45#endif
42#ifdef CONFIG_IBMVIO 46#ifdef CONFIG_IBMVIO
43 if (dev->bus == &vio_bus_type) 47 if (dev->bus == &vio_bus_type)
44 return -EIO; 48 return -EIO;
diff --git a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c
index d63d41f3eecf..af5272fedadf 100644
--- a/arch/ppc64/kernel/eeh.c
+++ b/arch/ppc64/kernel/eeh.c
@@ -505,7 +505,7 @@ static inline unsigned long eeh_token_to_phys(unsigned long token)
505 pte_t *ptep; 505 pte_t *ptep;
506 unsigned long pa; 506 unsigned long pa;
507 507
508 ptep = find_linux_pte(ioremap_mm.pgd, token); 508 ptep = find_linux_pte(init_mm.pgd, token);
509 if (!ptep) 509 if (!ptep)
510 return token; 510 return token;
511 pa = pte_pfn(*ptep) << PAGE_SHIFT; 511 pa = pte_pfn(*ptep) << PAGE_SHIFT;
diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S
index 346dbf606b5d..02c8f4e3e4bc 100644
--- a/arch/ppc64/kernel/head.S
+++ b/arch/ppc64/kernel/head.S
@@ -2121,10 +2121,6 @@ empty_zero_page:
2121swapper_pg_dir: 2121swapper_pg_dir:
2122 .space 4096 2122 .space 4096
2123 2123
2124 .globl ioremap_dir
2125ioremap_dir:
2126 .space 4096
2127
2128#ifdef CONFIG_SMP 2124#ifdef CONFIG_SMP
2129/* 1 page segment table per cpu (max 48, cpu0 allocated at STAB0_PHYS_ADDR) */ 2125/* 1 page segment table per cpu (max 48, cpu0 allocated at STAB0_PHYS_ADDR) */
2130 .globl stab_array 2126 .globl stab_array
diff --git a/arch/ppc64/kernel/iSeries_VpdInfo.c b/arch/ppc64/kernel/iSeries_VpdInfo.c
index a6f0ff2d0239..d11c732daf81 100644
--- a/arch/ppc64/kernel/iSeries_VpdInfo.c
+++ b/arch/ppc64/kernel/iSeries_VpdInfo.c
@@ -1,31 +1,31 @@
1/************************************************************************/ 1/*
2/* File iSeries_vpdInfo.c created by Allan Trautman on Fri Feb 2 2001. */ 2 * File iSeries_vpdInfo.c created by Allan Trautman on Fri Feb 2 2001.
3/************************************************************************/ 3 *
4/* This code gets the card location of the hardware */ 4 * This code gets the card location of the hardware
5/* Copyright (C) 20yy <Allan H Trautman> <IBM Corp> */ 5 * Copyright (C) 2001 <Allan H Trautman> <IBM Corp>
6/* */ 6 * Copyright (C) 2005 Stephen Rothwel, IBM Corp
7/* This program is free software; you can redistribute it and/or modify */ 7 *
8/* it under the terms of the GNU General Public License as published by */ 8 * This program is free software; you can redistribute it and/or modify
9/* the Free Software Foundation; either version 2 of the License, or */ 9 * it under the terms of the GNU General Public License as published by
10/* (at your option) any later version. */ 10 * the Free Software Foundation; either version 2 of the License, or
11/* */ 11 * (at your option) any later version.
12/* This program is distributed in the hope that it will be useful, */ 12 *
13/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ 13 * This program is distributed in the hope that it will be useful,
14/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15/* GNU General Public License for more details. */ 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16/* */ 16 * GNU General Public License for more details.
17/* You should have received a copy of the GNU General Public License */ 17 *
18/* along with this program; if not, write to the: */ 18 * You should have received a copy of the GNU General Public License
19/* Free Software Foundation, Inc., */ 19 * along with this program; if not, write to the:
20/* 59 Temple Place, Suite 330, */ 20 * Free Software Foundation, Inc.,
21/* Boston, MA 02111-1307 USA */ 21 * 59 Temple Place, Suite 330,
22/************************************************************************/ 22 * Boston, MA 02111-1307 USA
23/* Change Activity: */ 23 *
24/* Created, Feb 2, 2001 */ 24 * Change Activity:
25/* Ported to ppc64, August 20, 2001 */ 25 * Created, Feb 2, 2001
26/* End Change Activity */ 26 * Ported to ppc64, August 20, 2001
27/************************************************************************/ 27 * End Change Activity
28#include <linux/config.h> 28 */
29#include <linux/init.h> 29#include <linux/init.h>
30#include <linux/module.h> 30#include <linux/module.h>
31#include <linux/pci.h> 31#include <linux/pci.h>
@@ -34,30 +34,25 @@
34 34
35#include <asm/iSeries/HvCallPci.h> 35#include <asm/iSeries/HvCallPci.h>
36#include <asm/iSeries/HvTypes.h> 36#include <asm/iSeries/HvTypes.h>
37#include <asm/iSeries/mf.h>
38#include <asm/iSeries/LparData.h>
39#include <asm/iSeries/iSeries_pci.h> 37#include <asm/iSeries/iSeries_pci.h>
40#include "pci.h"
41 38
42/* 39/*
43 * Size of Bus VPD data 40 * Size of Bus VPD data
44 */ 41 */
45#define BUS_VPDSIZE 1024 42#define BUS_VPDSIZE 1024
43
46/* 44/*
47 * Bus Vpd Tags 45 * Bus Vpd Tags
48 */ 46 */
49#define VpdEndOfDataTag 0x78
50#define VpdEndOfAreaTag 0x79 47#define VpdEndOfAreaTag 0x79
51#define VpdIdStringTag 0x82 48#define VpdIdStringTag 0x82
52#define VpdVendorAreaTag 0x84 49#define VpdVendorAreaTag 0x84
50
53/* 51/*
54 * Mfg Area Tags 52 * Mfg Area Tags
55 */ 53 */
56#define VpdFruFlag 0x4647 // "FG"
57#define VpdFruFrameId 0x4649 // "FI" 54#define VpdFruFrameId 0x4649 // "FI"
58#define VpdSlotMapFormat 0x4D46 // "MF" 55#define VpdSlotMapFormat 0x4D46 // "MF"
59#define VpdAsmPartNumber 0x504E // "PN"
60#define VpdFruSerial 0x534E // "SN"
61#define VpdSlotMap 0x534D // "SM" 56#define VpdSlotMap 0x534D // "SM"
62 57
63/* 58/*
@@ -79,74 +74,33 @@ struct SlotMapStruct {
79 char CardLocation[3]; 74 char CardLocation[3];
80 char Parms[8]; 75 char Parms[8];
81 char Reserved[2]; 76 char Reserved[2];
82}; 77};
83typedef struct SlotMapStruct SlotMap; 78typedef struct SlotMapStruct SlotMap;
84#define SLOT_ENTRY_SIZE 16 79#define SLOT_ENTRY_SIZE 16
85 80
86/* 81/*
87 * Formats the device information.
88 * - Pass in pci_dev* pointer to the device.
89 * - Pass in buffer to place the data. Danger here is the buffer must
90 * be as big as the client says it is. Should be at least 128 bytes.
91 * Return will the length of the string data put in the buffer.
92 * Format:
93 * PCI: Bus 0, Device 26, Vendor 0x12AE Frame 1, Card C10 Ethernet
94 * controller
95 */
96int iSeries_Device_Information(struct pci_dev *PciDev, char *buffer,
97 int BufferSize)
98{
99 struct iSeries_Device_Node *DevNode =
100 (struct iSeries_Device_Node *)PciDev->sysdata;
101 int len;
102
103 if (DevNode == NULL)
104 return sprintf(buffer,
105 "PCI: iSeries_Device_Information DevNode is NULL");
106
107 if (BufferSize < 128)
108 return 0;
109
110 len = sprintf(buffer, "PCI: Bus%3d, Device%3d, Vendor %04X ",
111 ISERIES_BUS(DevNode), PCI_SLOT(PciDev->devfn),
112 PciDev->vendor);
113 len += sprintf(buffer + len, "Frame%3d, Card %4s ",
114 DevNode->FrameId, DevNode->CardLocation);
115#ifdef CONFIG_PCI
116 if (pci_class_name(PciDev->class >> 8) == 0)
117 len += sprintf(buffer + len, "0x%04X ",
118 (int)(PciDev->class >> 8));
119 else
120 len += sprintf(buffer + len, "%s",
121 pci_class_name(PciDev->class >> 8));
122#endif
123 return len;
124}
125
126/*
127 * Parse the Slot Area 82 * Parse the Slot Area
128 */ 83 */
129void iSeries_Parse_SlotArea(SlotMap *MapPtr, int MapLen, 84static void __init iSeries_Parse_SlotArea(SlotMap *MapPtr, int MapLen,
130 struct iSeries_Device_Node *DevNode) 85 HvAgentId agent, u8 *PhbId, char card[4])
131{ 86{
132 int SlotMapLen = MapLen; 87 int SlotMapLen = MapLen;
133 SlotMap *SlotMapPtr = MapPtr; 88 SlotMap *SlotMapPtr = MapPtr;
134 89
135 /* 90 /*
136 * Parse Slot label until we find the one requrested 91 * Parse Slot label until we find the one requested
137 */ 92 */
138 while (SlotMapLen > 0) { 93 while (SlotMapLen > 0) {
139 if (SlotMapPtr->AgentId == DevNode->AgentId ) { 94 if (SlotMapPtr->AgentId == agent) {
140 /* 95 /*
141 * If Phb wasn't found, grab the entry first one found. 96 * If Phb wasn't found, grab the entry first one found.
142 */ 97 */
143 if (DevNode->PhbId == 0xff) 98 if (*PhbId == 0xff)
144 DevNode->PhbId = SlotMapPtr->PhbId; 99 *PhbId = SlotMapPtr->PhbId;
145 /* Found it, extract the data. */ 100 /* Found it, extract the data. */
146 if (SlotMapPtr->PhbId == DevNode->PhbId ) { 101 if (SlotMapPtr->PhbId == *PhbId) {
147 memcpy(&DevNode->CardLocation, 102 memcpy(card, &SlotMapPtr->CardLocation, 3);
148 &SlotMapPtr->CardLocation, 3); 103 card[3] = 0;
149 DevNode->CardLocation[3] = 0;
150 break; 104 break;
151 } 105 }
152 } 106 }
@@ -159,8 +113,9 @@ void iSeries_Parse_SlotArea(SlotMap *MapPtr, int MapLen,
159/* 113/*
160 * Parse the Mfg Area 114 * Parse the Mfg Area
161 */ 115 */
162static void iSeries_Parse_MfgArea(u8 *AreaData, int AreaLen, 116static void __init iSeries_Parse_MfgArea(u8 *AreaData, int AreaLen,
163 struct iSeries_Device_Node *DevNode) 117 HvAgentId agent, u8 *PhbId,
118 u8 *frame, char card[4])
164{ 119{
165 MfgArea *MfgAreaPtr = (MfgArea *)AreaData; 120 MfgArea *MfgAreaPtr = (MfgArea *)AreaData;
166 int MfgAreaLen = AreaLen; 121 int MfgAreaLen = AreaLen;
@@ -171,7 +126,7 @@ static void iSeries_Parse_MfgArea(u8 *AreaData, int AreaLen,
171 int MfgTagLen = MfgAreaPtr->TagLength; 126 int MfgTagLen = MfgAreaPtr->TagLength;
172 /* Frame ID (FI 4649020310 ) */ 127 /* Frame ID (FI 4649020310 ) */
173 if (MfgAreaPtr->Tag == VpdFruFrameId) /* FI */ 128 if (MfgAreaPtr->Tag == VpdFruFrameId) /* FI */
174 DevNode->FrameId = MfgAreaPtr->AreaData1; 129 *frame = MfgAreaPtr->AreaData1;
175 /* Slot Map Format (MF 4D46020004 ) */ 130 /* Slot Map Format (MF 4D46020004 ) */
176 else if (MfgAreaPtr->Tag == VpdSlotMapFormat) /* MF */ 131 else if (MfgAreaPtr->Tag == VpdSlotMapFormat) /* MF */
177 SlotMapFmt = (MfgAreaPtr->AreaData1 * 256) 132 SlotMapFmt = (MfgAreaPtr->AreaData1 * 256)
@@ -183,10 +138,11 @@ static void iSeries_Parse_MfgArea(u8 *AreaData, int AreaLen,
183 if (SlotMapFmt == 0x1004) 138 if (SlotMapFmt == 0x1004)
184 SlotMapPtr = (SlotMap *)((char *)MfgAreaPtr 139 SlotMapPtr = (SlotMap *)((char *)MfgAreaPtr
185 + MFG_ENTRY_SIZE + 1); 140 + MFG_ENTRY_SIZE + 1);
186 else 141 else
187 SlotMapPtr = (SlotMap *)((char *)MfgAreaPtr 142 SlotMapPtr = (SlotMap *)((char *)MfgAreaPtr
188 + MFG_ENTRY_SIZE); 143 + MFG_ENTRY_SIZE);
189 iSeries_Parse_SlotArea(SlotMapPtr, MfgTagLen, DevNode); 144 iSeries_Parse_SlotArea(SlotMapPtr, MfgTagLen,
145 agent, PhbId, card);
190 } 146 }
191 /* 147 /*
192 * Point to the next Mfg Area 148 * Point to the next Mfg Area
@@ -194,19 +150,19 @@ static void iSeries_Parse_MfgArea(u8 *AreaData, int AreaLen,
194 */ 150 */
195 MfgAreaPtr = (MfgArea *)((char *)MfgAreaPtr + MfgTagLen 151 MfgAreaPtr = (MfgArea *)((char *)MfgAreaPtr + MfgTagLen
196 + MFG_ENTRY_SIZE); 152 + MFG_ENTRY_SIZE);
197 MfgAreaLen -= (MfgTagLen + MFG_ENTRY_SIZE); 153 MfgAreaLen -= (MfgTagLen + MFG_ENTRY_SIZE);
198 } 154 }
199} 155}
200 156
201/* 157/*
202 * Look for "BUS".. Data is not Null terminated. 158 * Look for "BUS".. Data is not Null terminated.
203 * PHBID of 0xFF indicates PHB was not found in VPD Data. 159 * PHBID of 0xFF indicates PHB was not found in VPD Data.
204 */ 160 */
205static int iSeries_Parse_PhbId(u8 *AreaPtr, int AreaLength) 161static int __init iSeries_Parse_PhbId(u8 *AreaPtr, int AreaLength)
206{ 162{
207 u8 *PhbPtr = AreaPtr; 163 u8 *PhbPtr = AreaPtr;
208 int DataLen = AreaLength; 164 int DataLen = AreaLength;
209 char PhbId = 0xFF; 165 char PhbId = 0xFF;
210 166
211 while (DataLen > 0) { 167 while (DataLen > 0) {
212 if ((*PhbPtr == 'B') && (*(PhbPtr + 1) == 'U') 168 if ((*PhbPtr == 'B') && (*(PhbPtr + 1) == 'U')
@@ -216,7 +172,7 @@ static int iSeries_Parse_PhbId(u8 *AreaPtr, int AreaLength)
216 ++PhbPtr; 172 ++PhbPtr;
217 PhbId = (*PhbPtr & 0x0F); 173 PhbId = (*PhbPtr & 0x0F);
218 break; 174 break;
219 } 175 }
220 ++PhbPtr; 176 ++PhbPtr;
221 --DataLen; 177 --DataLen;
222 } 178 }
@@ -226,52 +182,90 @@ static int iSeries_Parse_PhbId(u8 *AreaPtr, int AreaLength)
226/* 182/*
227 * Parse out the VPD Areas 183 * Parse out the VPD Areas
228 */ 184 */
229static void iSeries_Parse_Vpd(u8 *VpdData, int VpdDataLen, 185static void __init iSeries_Parse_Vpd(u8 *VpdData, int VpdDataLen,
230 struct iSeries_Device_Node *DevNode) 186 HvAgentId agent, u8 *frame, char card[4])
231{ 187{
232 u8 *TagPtr = VpdData; 188 u8 *TagPtr = VpdData;
233 int DataLen = VpdDataLen - 3; 189 int DataLen = VpdDataLen - 3;
190 u8 PhbId;
234 191
235 while ((*TagPtr != VpdEndOfAreaTag) && (DataLen > 0)) { 192 while ((*TagPtr != VpdEndOfAreaTag) && (DataLen > 0)) {
236 int AreaLen = *(TagPtr + 1) + (*(TagPtr + 2) * 256); 193 int AreaLen = *(TagPtr + 1) + (*(TagPtr + 2) * 256);
237 u8 *AreaData = TagPtr + 3; 194 u8 *AreaData = TagPtr + 3;
238 195
239 if (*TagPtr == VpdIdStringTag) 196 if (*TagPtr == VpdIdStringTag)
240 DevNode->PhbId = iSeries_Parse_PhbId(AreaData, AreaLen); 197 PhbId = iSeries_Parse_PhbId(AreaData, AreaLen);
241 else if (*TagPtr == VpdVendorAreaTag) 198 else if (*TagPtr == VpdVendorAreaTag)
242 iSeries_Parse_MfgArea(AreaData, AreaLen, DevNode); 199 iSeries_Parse_MfgArea(AreaData, AreaLen,
200 agent, &PhbId, frame, card);
243 /* Point to next Area. */ 201 /* Point to next Area. */
244 TagPtr = AreaData + AreaLen; 202 TagPtr = AreaData + AreaLen;
245 DataLen -= AreaLen; 203 DataLen -= AreaLen;
246 } 204 }
247} 205}
248 206
249void iSeries_Get_Location_Code(struct iSeries_Device_Node *DevNode) 207static void __init iSeries_Get_Location_Code(u16 bus, HvAgentId agent,
208 u8 *frame, char card[4])
250{ 209{
251 int BusVpdLen = 0; 210 int BusVpdLen = 0;
252 u8 *BusVpdPtr = (u8 *)kmalloc(BUS_VPDSIZE, GFP_KERNEL); 211 u8 *BusVpdPtr = kmalloc(BUS_VPDSIZE, GFP_KERNEL);
253 212
254 if (BusVpdPtr == NULL) { 213 if (BusVpdPtr == NULL) {
255 printk("PCI: Bus VPD Buffer allocation failure.\n"); 214 printk("PCI: Bus VPD Buffer allocation failure.\n");
256 return; 215 return;
257 } 216 }
258 BusVpdLen = HvCallPci_getBusVpd(ISERIES_BUS(DevNode), 217 BusVpdLen = HvCallPci_getBusVpd(bus, ISERIES_HV_ADDR(BusVpdPtr),
259 ISERIES_HV_ADDR(BusVpdPtr),
260 BUS_VPDSIZE); 218 BUS_VPDSIZE);
261 if (BusVpdLen == 0) { 219 if (BusVpdLen == 0) {
262 kfree(BusVpdPtr);
263 printk("PCI: Bus VPD Buffer zero length.\n"); 220 printk("PCI: Bus VPD Buffer zero length.\n");
264 return; 221 goto out_free;
265 } 222 }
266 /* printk("PCI: BusVpdPtr: %p, %d\n",BusVpdPtr, BusVpdLen); */ 223 /* printk("PCI: BusVpdPtr: %p, %d\n",BusVpdPtr, BusVpdLen); */
267 /* Make sure this is what I think it is */ 224 /* Make sure this is what I think it is */
268 if (*BusVpdPtr != VpdIdStringTag) { /* 0x82 */ 225 if (*BusVpdPtr != VpdIdStringTag) { /* 0x82 */
269 printk("PCI: Bus VPD Buffer missing starting tag.\n"); 226 printk("PCI: Bus VPD Buffer missing starting tag.\n");
270 kfree(BusVpdPtr); 227 goto out_free;
271 return;
272 } 228 }
273 iSeries_Parse_Vpd(BusVpdPtr,BusVpdLen, DevNode); 229 iSeries_Parse_Vpd(BusVpdPtr, BusVpdLen, agent, frame, card);
274 sprintf(DevNode->Location, "Frame%3d, Card %-4s", DevNode->FrameId, 230out_free:
275 DevNode->CardLocation);
276 kfree(BusVpdPtr); 231 kfree(BusVpdPtr);
277} 232}
233
234/*
235 * Prints the device information.
236 * - Pass in pci_dev* pointer to the device.
237 * - Pass in the device count
238 *
239 * Format:
240 * PCI: Bus 0, Device 26, Vendor 0x12AE Frame 1, Card C10 Ethernet
241 * controller
242 */
243void __init iSeries_Device_Information(struct pci_dev *PciDev, int count)
244{
245 struct iSeries_Device_Node *DevNode = PciDev->sysdata;
246 u16 bus;
247 u8 frame;
248 char card[4];
249 HvSubBusNumber subbus;
250 HvAgentId agent;
251
252 if (DevNode == NULL) {
253 printk("%d. PCI: iSeries_Device_Information DevNode is NULL\n",
254 count);
255 return;
256 }
257
258 bus = ISERIES_BUS(DevNode);
259 subbus = ISERIES_SUBBUS(DevNode);
260 agent = ISERIES_PCI_AGENTID(ISERIES_GET_DEVICE_FROM_SUBBUS(subbus),
261 ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus));
262 iSeries_Get_Location_Code(bus, agent, &frame, card);
263
264 printk("%d. PCI: Bus%3d, Device%3d, Vendor %04X Frame%3d, Card %4s ",
265 count, bus, PCI_SLOT(PciDev->devfn), PciDev->vendor,
266 frame, card);
267 if (pci_class_name(PciDev->class >> 8) == 0)
268 printk("0x%04X\n", (int)(PciDev->class >> 8));
269 else
270 printk("%s\n", pci_class_name(PciDev->class >> 8));
271}
diff --git a/arch/ppc64/kernel/iSeries_iommu.c b/arch/ppc64/kernel/iSeries_iommu.c
index 4e1a47c8a802..f8ff1bb054dc 100644
--- a/arch/ppc64/kernel/iSeries_iommu.c
+++ b/arch/ppc64/kernel/iSeries_iommu.c
@@ -83,7 +83,7 @@ static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages)
83 } 83 }
84} 84}
85 85
86 86#ifdef CONFIG_PCI
87/* 87/*
88 * This function compares the known tables to find an iommu_table 88 * This function compares the known tables to find an iommu_table
89 * that has already been built for hardware TCEs. 89 * that has already been built for hardware TCEs.
@@ -159,6 +159,7 @@ void iommu_devnode_init_iSeries(struct iSeries_Device_Node *dn)
159 else 159 else
160 kfree(tbl); 160 kfree(tbl);
161} 161}
162#endif
162 163
163static void iommu_dev_setup_iSeries(struct pci_dev *dev) { } 164static void iommu_dev_setup_iSeries(struct pci_dev *dev) { }
164static void iommu_bus_setup_iSeries(struct pci_bus *bus) { } 165static void iommu_bus_setup_iSeries(struct pci_bus *bus) { }
diff --git a/arch/ppc64/kernel/iSeries_irq.c b/arch/ppc64/kernel/iSeries_irq.c
index f831d259dbb7..77376c1bd611 100644
--- a/arch/ppc64/kernel/iSeries_irq.c
+++ b/arch/ppc64/kernel/iSeries_irq.c
@@ -1,27 +1,29 @@
1/************************************************************************/ 1/*
2/* This module supports the iSeries PCI bus interrupt handling */ 2 * This module supports the iSeries PCI bus interrupt handling
3/* Copyright (C) 20yy <Robert L Holtorf> <IBM Corp> */ 3 * Copyright (C) 20yy <Robert L Holtorf> <IBM Corp>
4/* */ 4 * Copyright (C) 2004-2005 IBM Corporation
5/* This program is free software; you can redistribute it and/or modify */ 5 *
6/* it under the terms of the GNU General Public License as published by */ 6 * This program is free software; you can redistribute it and/or modify
7/* the Free Software Foundation; either version 2 of the License, or */ 7 * it under the terms of the GNU General Public License as published by
8/* (at your option) any later version. */ 8 * the Free Software Foundation; either version 2 of the License, or
9/* */ 9 * (at your option) any later version.
10/* This program is distributed in the hope that it will be useful, */ 10 *
11/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ 11 * This program is distributed in the hope that it will be useful,
12/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13/* GNU General Public License for more details. */ 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14/* */ 14 * GNU General Public License for more details.
15/* You should have received a copy of the GNU General Public License */ 15 *
16/* along with this program; if not, write to the: */ 16 * You should have received a copy of the GNU General Public License
17/* Free Software Foundation, Inc., */ 17 * along with this program; if not, write to the:
18/* 59 Temple Place, Suite 330, */ 18 * Free Software Foundation, Inc.,
19/* Boston, MA 02111-1307 USA */ 19 * 59 Temple Place, Suite 330,
20/************************************************************************/ 20 * Boston, MA 02111-1307 USA
21/* Change Activity: */ 21 *
22/* Created, December 13, 2000 by Wayne Holm */ 22 * Change Activity:
23/* End Change Activity */ 23 * Created, December 13, 2000 by Wayne Holm
24/************************************************************************/ 24 * End Change Activity
25 */
26#include <linux/config.h>
25#include <linux/pci.h> 27#include <linux/pci.h>
26#include <linux/init.h> 28#include <linux/init.h>
27#include <linux/threads.h> 29#include <linux/threads.h>
@@ -30,30 +32,15 @@
30#include <linux/string.h> 32#include <linux/string.h>
31#include <linux/bootmem.h> 33#include <linux/bootmem.h>
32#include <linux/ide.h> 34#include <linux/ide.h>
33
34#include <linux/irq.h> 35#include <linux/irq.h>
35#include <linux/spinlock.h> 36#include <linux/spinlock.h>
36#include <asm/ppcdebug.h>
37 37
38#include <asm/ppcdebug.h>
39#include <asm/iSeries/HvTypes.h>
40#include <asm/iSeries/HvLpEvent.h>
38#include <asm/iSeries/HvCallPci.h> 41#include <asm/iSeries/HvCallPci.h>
39#include <asm/iSeries/HvCallXm.h> 42#include <asm/iSeries/HvCallXm.h>
40#include <asm/iSeries/iSeries_irq.h> 43#include <asm/iSeries/iSeries_irq.h>
41#include <asm/iSeries/XmPciLpEvent.h>
42
43static unsigned int iSeries_startup_IRQ(unsigned int irq);
44static void iSeries_shutdown_IRQ(unsigned int irq);
45static void iSeries_enable_IRQ(unsigned int irq);
46static void iSeries_disable_IRQ(unsigned int irq);
47static void iSeries_end_IRQ(unsigned int irq);
48
49static hw_irq_controller iSeries_IRQ_handler = {
50 .typename = "iSeries irq controller",
51 .startup = iSeries_startup_IRQ,
52 .shutdown = iSeries_shutdown_IRQ,
53 .enable = iSeries_enable_IRQ,
54 .disable = iSeries_disable_IRQ,
55 .end = iSeries_end_IRQ
56};
57 44
58/* This maps virtual irq numbers to real irqs */ 45/* This maps virtual irq numbers to real irqs */
59unsigned int virt_irq_to_real_map[NR_IRQS]; 46unsigned int virt_irq_to_real_map[NR_IRQS];
@@ -62,37 +49,187 @@ unsigned int virt_irq_to_real_map[NR_IRQS];
62/* Note: the pcnet32 driver assumes irq numbers < 2 aren't valid. :( */ 49/* Note: the pcnet32 driver assumes irq numbers < 2 aren't valid. :( */
63static int next_virtual_irq = 2; 50static int next_virtual_irq = 2;
64 51
65/* This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c */ 52static long Pci_Interrupt_Count;
66void __init iSeries_init_IRQ(void) 53static long Pci_Event_Count;
54
55enum XmPciLpEvent_Subtype {
56 XmPciLpEvent_BusCreated = 0, // PHB has been created
57 XmPciLpEvent_BusError = 1, // PHB has failed
58 XmPciLpEvent_BusFailed = 2, // Msg to Secondary, Primary failed bus
59 XmPciLpEvent_NodeFailed = 4, // Multi-adapter bridge has failed
60 XmPciLpEvent_NodeRecovered = 5, // Multi-adapter bridge has recovered
61 XmPciLpEvent_BusRecovered = 12, // PHB has been recovered
62 XmPciLpEvent_UnQuiesceBus = 18, // Secondary bus unqiescing
63 XmPciLpEvent_BridgeError = 21, // Bridge Error
64 XmPciLpEvent_SlotInterrupt = 22 // Slot interrupt
65};
66
67struct XmPciLpEvent_BusInterrupt {
68 HvBusNumber busNumber;
69 HvSubBusNumber subBusNumber;
70};
71
72struct XmPciLpEvent_NodeInterrupt {
73 HvBusNumber busNumber;
74 HvSubBusNumber subBusNumber;
75 HvAgentId deviceId;
76};
77
78struct XmPciLpEvent {
79 struct HvLpEvent hvLpEvent;
80
81 union {
82 u64 alignData; // Align on an 8-byte boundary
83
84 struct {
85 u32 fisr;
86 HvBusNumber busNumber;
87 HvSubBusNumber subBusNumber;
88 HvAgentId deviceId;
89 } slotInterrupt;
90
91 struct XmPciLpEvent_BusInterrupt busFailed;
92 struct XmPciLpEvent_BusInterrupt busRecovered;
93 struct XmPciLpEvent_BusInterrupt busCreated;
94
95 struct XmPciLpEvent_NodeInterrupt nodeFailed;
96 struct XmPciLpEvent_NodeInterrupt nodeRecovered;
97
98 } eventData;
99
100};
101
102static void intReceived(struct XmPciLpEvent *eventParm,
103 struct pt_regs *regsParm)
67{ 104{
68 /* Register PCI event handler and open an event path */ 105 int irq;
69 XmPciLpEvent_init(); 106
107 ++Pci_Interrupt_Count;
108
109 switch (eventParm->hvLpEvent.xSubtype) {
110 case XmPciLpEvent_SlotInterrupt:
111 irq = eventParm->hvLpEvent.xCorrelationToken;
112 /* Dispatch the interrupt handlers for this irq */
113 ppc_irq_dispatch_handler(regsParm, irq);
114 HvCallPci_eoi(eventParm->eventData.slotInterrupt.busNumber,
115 eventParm->eventData.slotInterrupt.subBusNumber,
116 eventParm->eventData.slotInterrupt.deviceId);
117 break;
118 /* Ignore error recovery events for now */
119 case XmPciLpEvent_BusCreated:
120 printk(KERN_INFO "intReceived: system bus %d created\n",
121 eventParm->eventData.busCreated.busNumber);
122 break;
123 case XmPciLpEvent_BusError:
124 case XmPciLpEvent_BusFailed:
125 printk(KERN_INFO "intReceived: system bus %d failed\n",
126 eventParm->eventData.busFailed.busNumber);
127 break;
128 case XmPciLpEvent_BusRecovered:
129 case XmPciLpEvent_UnQuiesceBus:
130 printk(KERN_INFO "intReceived: system bus %d recovered\n",
131 eventParm->eventData.busRecovered.busNumber);
132 break;
133 case XmPciLpEvent_NodeFailed:
134 case XmPciLpEvent_BridgeError:
135 printk(KERN_INFO
136 "intReceived: multi-adapter bridge %d/%d/%d failed\n",
137 eventParm->eventData.nodeFailed.busNumber,
138 eventParm->eventData.nodeFailed.subBusNumber,
139 eventParm->eventData.nodeFailed.deviceId);
140 break;
141 case XmPciLpEvent_NodeRecovered:
142 printk(KERN_INFO
143 "intReceived: multi-adapter bridge %d/%d/%d recovered\n",
144 eventParm->eventData.nodeRecovered.busNumber,
145 eventParm->eventData.nodeRecovered.subBusNumber,
146 eventParm->eventData.nodeRecovered.deviceId);
147 break;
148 default:
149 printk(KERN_ERR
150 "intReceived: unrecognized event subtype 0x%x\n",
151 eventParm->hvLpEvent.xSubtype);
152 break;
153 }
154}
155
156static void XmPciLpEvent_handler(struct HvLpEvent *eventParm,
157 struct pt_regs *regsParm)
158{
159#ifdef CONFIG_PCI
160 ++Pci_Event_Count;
161
162 if (eventParm && (eventParm->xType == HvLpEvent_Type_PciIo)) {
163 switch (eventParm->xFlags.xFunction) {
164 case HvLpEvent_Function_Int:
165 intReceived((struct XmPciLpEvent *)eventParm, regsParm);
166 break;
167 case HvLpEvent_Function_Ack:
168 printk(KERN_ERR
169 "XmPciLpEvent_handler: unexpected ack received\n");
170 break;
171 default:
172 printk(KERN_ERR
173 "XmPciLpEvent_handler: unexpected event function %d\n",
174 (int)eventParm->xFlags.xFunction);
175 break;
176 }
177 } else if (eventParm)
178 printk(KERN_ERR
179 "XmPciLpEvent_handler: Unrecognized PCI event type 0x%x\n",
180 (int)eventParm->xType);
181 else
182 printk(KERN_ERR "XmPciLpEvent_handler: NULL event received\n");
183#endif
70} 184}
71 185
72/* 186/*
73 * This is called out of iSeries_scan_slot to allocate an IRQ for an EADS slot 187 * This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c
74 * It calculates the irq value for the slot. 188 * It must be called before the bus walk.
75 * Note that subBusNumber is always 0 (at the moment at least).
76 */ 189 */
77int __init iSeries_allocate_IRQ(HvBusNumber busNumber, 190void __init iSeries_init_IRQ(void)
78 HvSubBusNumber subBusNumber, HvAgentId deviceId)
79{ 191{
80 unsigned int realirq, virtirq; 192 /* Register PCI event handler and open an event path */
81 u8 idsel = (deviceId >> 4); 193 int xRc;
82 u8 function = deviceId & 7;
83
84 virtirq = next_virtual_irq++;
85 realirq = ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function;
86 virt_irq_to_real_map[virtirq] = realirq;
87 194
88 irq_desc[virtirq].handler = &iSeries_IRQ_handler; 195 xRc = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo,
89 return virtirq; 196 &XmPciLpEvent_handler);
197 if (xRc == 0) {
198 xRc = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
199 if (xRc != 0)
200 printk(KERN_ERR "iSeries_init_IRQ: open event path "
201 "failed with rc 0x%x\n", xRc);
202 } else
203 printk(KERN_ERR "iSeries_init_IRQ: register handler "
204 "failed with rc 0x%x\n", xRc);
90} 205}
91 206
92#define REAL_IRQ_TO_BUS(irq) ((((irq) >> 6) & 0xff) + 1) 207#define REAL_IRQ_TO_BUS(irq) ((((irq) >> 6) & 0xff) + 1)
93#define REAL_IRQ_TO_IDSEL(irq) ((((irq) >> 3) & 7) + 1) 208#define REAL_IRQ_TO_IDSEL(irq) ((((irq) >> 3) & 7) + 1)
94#define REAL_IRQ_TO_FUNC(irq) ((irq) & 7) 209#define REAL_IRQ_TO_FUNC(irq) ((irq) & 7)
95 210
211/*
212 * This will be called by device drivers (via enable_IRQ)
213 * to enable INTA in the bridge interrupt status register.
214 */
215static void iSeries_enable_IRQ(unsigned int irq)
216{
217 u32 bus, deviceId, function, mask;
218 const u32 subBus = 0;
219 unsigned int rirq = virt_irq_to_real_map[irq];
220
221 /* The IRQ has already been locked by the caller */
222 bus = REAL_IRQ_TO_BUS(rirq);
223 function = REAL_IRQ_TO_FUNC(rirq);
224 deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
225
226 /* Unmask secondary INTA */
227 mask = 0x80000000;
228 HvCallPci_unmaskInterrupts(bus, subBus, deviceId, mask);
229 PPCDBG(PPCDBG_BUSWALK, "iSeries_enable_IRQ 0x%02X.%02X.%02X 0x%04X\n",
230 bus, subBus, deviceId, irq);
231}
232
96/* This is called by iSeries_activate_IRQs */ 233/* This is called by iSeries_activate_IRQs */
97static unsigned int iSeries_startup_IRQ(unsigned int irq) 234static unsigned int iSeries_startup_IRQ(unsigned int irq)
98{ 235{
@@ -131,7 +268,7 @@ void __init iSeries_activate_IRQs()
131 desc->handler->startup(irq); 268 desc->handler->startup(irq);
132 spin_unlock_irqrestore(&desc->lock, flags); 269 spin_unlock_irqrestore(&desc->lock, flags);
133 } 270 }
134 } 271 }
135} 272}
136 273
137/* this is not called anywhere currently */ 274/* this is not called anywhere currently */
@@ -173,29 +310,7 @@ static void iSeries_disable_IRQ(unsigned int irq)
173 mask = 0x80000000; 310 mask = 0x80000000;
174 HvCallPci_maskInterrupts(bus, subBus, deviceId, mask); 311 HvCallPci_maskInterrupts(bus, subBus, deviceId, mask);
175 PPCDBG(PPCDBG_BUSWALK, "iSeries_disable_IRQ 0x%02X.%02X.%02X 0x%04X\n", 312 PPCDBG(PPCDBG_BUSWALK, "iSeries_disable_IRQ 0x%02X.%02X.%02X 0x%04X\n",
176 bus, subBus, deviceId, irq); 313 bus, subBus, deviceId, irq);
177}
178
179/*
180 * This will be called by device drivers (via enable_IRQ)
181 * to enable INTA in the bridge interrupt status register.
182 */
183static void iSeries_enable_IRQ(unsigned int irq)
184{
185 u32 bus, deviceId, function, mask;
186 const u32 subBus = 0;
187 unsigned int rirq = virt_irq_to_real_map[irq];
188
189 /* The IRQ has already been locked by the caller */
190 bus = REAL_IRQ_TO_BUS(rirq);
191 function = REAL_IRQ_TO_FUNC(rirq);
192 deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
193
194 /* Unmask secondary INTA */
195 mask = 0x80000000;
196 HvCallPci_unmaskInterrupts(bus, subBus, deviceId, mask);
197 PPCDBG(PPCDBG_BUSWALK, "iSeries_enable_IRQ 0x%02X.%02X.%02X 0x%04X\n",
198 bus, subBus, deviceId, irq);
199} 314}
200 315
201/* 316/*
@@ -207,3 +322,32 @@ static void iSeries_enable_IRQ(unsigned int irq)
207static void iSeries_end_IRQ(unsigned int irq) 322static void iSeries_end_IRQ(unsigned int irq)
208{ 323{
209} 324}
325
326static hw_irq_controller iSeries_IRQ_handler = {
327 .typename = "iSeries irq controller",
328 .startup = iSeries_startup_IRQ,
329 .shutdown = iSeries_shutdown_IRQ,
330 .enable = iSeries_enable_IRQ,
331 .disable = iSeries_disable_IRQ,
332 .end = iSeries_end_IRQ
333};
334
335/*
336 * This is called out of iSeries_scan_slot to allocate an IRQ for an EADS slot
337 * It calculates the irq value for the slot.
338 * Note that subBusNumber is always 0 (at the moment at least).
339 */
340int __init iSeries_allocate_IRQ(HvBusNumber busNumber,
341 HvSubBusNumber subBusNumber, HvAgentId deviceId)
342{
343 unsigned int realirq, virtirq;
344 u8 idsel = (deviceId >> 4);
345 u8 function = deviceId & 7;
346
347 virtirq = next_virtual_irq++;
348 realirq = ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function;
349 virt_irq_to_real_map[virtirq] = realirq;
350
351 irq_desc[virtirq].handler = &iSeries_IRQ_handler;
352 return virtirq;
353}
diff --git a/arch/ppc64/kernel/iSeries_pci.c b/arch/ppc64/kernel/iSeries_pci.c
index bd4c2554f1a0..356e4fd9a94f 100644
--- a/arch/ppc64/kernel/iSeries_pci.c
+++ b/arch/ppc64/kernel/iSeries_pci.c
@@ -38,9 +38,7 @@
38#include <asm/iommu.h> 38#include <asm/iommu.h>
39 39
40#include <asm/iSeries/HvCallPci.h> 40#include <asm/iSeries/HvCallPci.h>
41#include <asm/iSeries/HvCallSm.h>
42#include <asm/iSeries/HvCallXm.h> 41#include <asm/iSeries/HvCallXm.h>
43#include <asm/iSeries/LparData.h>
44#include <asm/iSeries/iSeries_irq.h> 42#include <asm/iSeries/iSeries_irq.h>
45#include <asm/iSeries/iSeries_pci.h> 43#include <asm/iSeries/iSeries_pci.h>
46#include <asm/iSeries/mf.h> 44#include <asm/iSeries/mf.h>
@@ -225,10 +223,7 @@ static struct iSeries_Device_Node *build_device_node(HvBusNumber Bus,
225 node->DsaAddr.Dsa.busNumber = Bus; 223 node->DsaAddr.Dsa.busNumber = Bus;
226 node->DsaAddr.Dsa.subBusNumber = SubBus; 224 node->DsaAddr.Dsa.subBusNumber = SubBus;
227 node->DsaAddr.Dsa.deviceId = 0x10; 225 node->DsaAddr.Dsa.deviceId = 0x10;
228 node->AgentId = AgentId;
229 node->DevFn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function); 226 node->DevFn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function);
230 node->IoRetry = 0;
231 iSeries_Get_Location_Code(node);
232 return node; 227 return node;
233} 228}
234 229
@@ -302,7 +297,6 @@ void __init iSeries_pci_final_fixup(void)
302{ 297{
303 struct pci_dev *pdev = NULL; 298 struct pci_dev *pdev = NULL;
304 struct iSeries_Device_Node *node; 299 struct iSeries_Device_Node *node;
305 char Buffer[256];
306 int DeviceCount = 0; 300 int DeviceCount = 0;
307 301
308 PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_fixup Entry.\n"); 302 PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_fixup Entry.\n");
@@ -324,9 +318,7 @@ void __init iSeries_pci_final_fixup(void)
324 "pdev 0x%p <==> DevNode 0x%p\n", 318 "pdev 0x%p <==> DevNode 0x%p\n",
325 pdev, node); 319 pdev, node);
326 allocate_device_bars(pdev); 320 allocate_device_bars(pdev);
327 iSeries_Device_Information(pdev, Buffer, 321 iSeries_Device_Information(pdev, DeviceCount);
328 sizeof(Buffer));
329 printk("%d. %s\n", DeviceCount, Buffer);
330 iommu_devnode_init_iSeries(node); 322 iommu_devnode_init_iSeries(node);
331 } else 323 } else
332 printk("PCI: Device Tree not found for 0x%016lX\n", 324 printk("PCI: Device Tree not found for 0x%016lX\n",
@@ -499,7 +491,6 @@ static int scan_bridge_slot(HvBusNumber Bus,
499 491
500 ++DeviceCount; 492 ++DeviceCount;
501 node = build_device_node(Bus, SubBus, EADsIdSel, Function); 493 node = build_device_node(Bus, SubBus, EADsIdSel, Function);
502 node->Vendor = VendorId;
503 node->Irq = Irq; 494 node->Irq = Irq;
504 node->LogicalSlot = BridgeInfo->logicalSlotNumber; 495 node->LogicalSlot = BridgeInfo->logicalSlotNumber;
505 496
@@ -661,38 +652,34 @@ static struct pci_ops iSeries_pci_ops = {
661 * Check Return Code 652 * Check Return Code
662 * -> On Failure, print and log information. 653 * -> On Failure, print and log information.
663 * Increment Retry Count, if exceeds max, panic partition. 654 * Increment Retry Count, if exceeds max, panic partition.
664 * -> If in retry, print and log success
665 * 655 *
666 * PCI: Device 23.90 ReadL I/O Error( 0): 0x1234 656 * PCI: Device 23.90 ReadL I/O Error( 0): 0x1234
667 * PCI: Device 23.90 ReadL Retry( 1) 657 * PCI: Device 23.90 ReadL Retry( 1)
668 * PCI: Device 23.90 ReadL Retry Successful(1) 658 * PCI: Device 23.90 ReadL Retry Successful(1)
669 */ 659 */
670static int CheckReturnCode(char *TextHdr, struct iSeries_Device_Node *DevNode, 660static int CheckReturnCode(char *TextHdr, struct iSeries_Device_Node *DevNode,
671 u64 ret) 661 int *retry, u64 ret)
672{ 662{
673 if (ret != 0) { 663 if (ret != 0) {
674 ++Pci_Error_Count; 664 ++Pci_Error_Count;
675 ++DevNode->IoRetry; 665 (*retry)++;
676 printk("PCI: %s: Device 0x%04X:%02X I/O Error(%2d): 0x%04X\n", 666 printk("PCI: %s: Device 0x%04X:%02X I/O Error(%2d): 0x%04X\n",
677 TextHdr, DevNode->DsaAddr.Dsa.busNumber, DevNode->DevFn, 667 TextHdr, DevNode->DsaAddr.Dsa.busNumber, DevNode->DevFn,
678 DevNode->IoRetry, (int)ret); 668 *retry, (int)ret);
679 /* 669 /*
680 * Bump the retry and check for retry count exceeded. 670 * Bump the retry and check for retry count exceeded.
681 * If, Exceeded, panic the system. 671 * If, Exceeded, panic the system.
682 */ 672 */
683 if ((DevNode->IoRetry > Pci_Retry_Max) && 673 if (((*retry) > Pci_Retry_Max) &&
684 (Pci_Error_Flag > 0)) { 674 (Pci_Error_Flag > 0)) {
685 mf_display_src(0xB6000103); 675 mf_display_src(0xB6000103);
686 panic_timeout = 0; 676 panic_timeout = 0;
687 panic("PCI: Hardware I/O Error, SRC B6000103, " 677 panic("PCI: Hardware I/O Error, SRC B6000103, "
688 "Automatic Reboot Disabled.\n"); 678 "Automatic Reboot Disabled.\n");
689 } 679 }
690 return -1; /* Retry Try */ 680 return -1; /* Retry Try */
691 } 681 }
692 /* If retry was in progress, log success and rest retry count */ 682 return 0;
693 if (DevNode->IoRetry > 0)
694 DevNode->IoRetry = 0;
695 return 0;
696} 683}
697 684
698/* 685/*
@@ -738,6 +725,7 @@ u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress)
738{ 725{
739 u64 BarOffset; 726 u64 BarOffset;
740 u64 dsa; 727 u64 dsa;
728 int retry = 0;
741 struct HvCallPci_LoadReturn ret; 729 struct HvCallPci_LoadReturn ret;
742 struct iSeries_Device_Node *DevNode = 730 struct iSeries_Device_Node *DevNode =
743 xlate_iomm_address(IoAddress, &dsa, &BarOffset); 731 xlate_iomm_address(IoAddress, &dsa, &BarOffset);
@@ -757,7 +745,7 @@ u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress)
757 do { 745 do {
758 ++Pci_Io_Read_Count; 746 ++Pci_Io_Read_Count;
759 HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0); 747 HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0);
760 } while (CheckReturnCode("RDB", DevNode, ret.rc) != 0); 748 } while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0);
761 749
762 return (u8)ret.value; 750 return (u8)ret.value;
763} 751}
@@ -767,6 +755,7 @@ u16 iSeries_Read_Word(const volatile void __iomem *IoAddress)
767{ 755{
768 u64 BarOffset; 756 u64 BarOffset;
769 u64 dsa; 757 u64 dsa;
758 int retry = 0;
770 struct HvCallPci_LoadReturn ret; 759 struct HvCallPci_LoadReturn ret;
771 struct iSeries_Device_Node *DevNode = 760 struct iSeries_Device_Node *DevNode =
772 xlate_iomm_address(IoAddress, &dsa, &BarOffset); 761 xlate_iomm_address(IoAddress, &dsa, &BarOffset);
@@ -787,7 +776,7 @@ u16 iSeries_Read_Word(const volatile void __iomem *IoAddress)
787 ++Pci_Io_Read_Count; 776 ++Pci_Io_Read_Count;
788 HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa, 777 HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa,
789 BarOffset, 0); 778 BarOffset, 0);
790 } while (CheckReturnCode("RDW", DevNode, ret.rc) != 0); 779 } while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0);
791 780
792 return swab16((u16)ret.value); 781 return swab16((u16)ret.value);
793} 782}
@@ -797,6 +786,7 @@ u32 iSeries_Read_Long(const volatile void __iomem *IoAddress)
797{ 786{
798 u64 BarOffset; 787 u64 BarOffset;
799 u64 dsa; 788 u64 dsa;
789 int retry = 0;
800 struct HvCallPci_LoadReturn ret; 790 struct HvCallPci_LoadReturn ret;
801 struct iSeries_Device_Node *DevNode = 791 struct iSeries_Device_Node *DevNode =
802 xlate_iomm_address(IoAddress, &dsa, &BarOffset); 792 xlate_iomm_address(IoAddress, &dsa, &BarOffset);
@@ -817,7 +807,7 @@ u32 iSeries_Read_Long(const volatile void __iomem *IoAddress)
817 ++Pci_Io_Read_Count; 807 ++Pci_Io_Read_Count;
818 HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa, 808 HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa,
819 BarOffset, 0); 809 BarOffset, 0);
820 } while (CheckReturnCode("RDL", DevNode, ret.rc) != 0); 810 } while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0);
821 811
822 return swab32((u32)ret.value); 812 return swab32((u32)ret.value);
823} 813}
@@ -834,6 +824,7 @@ void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress)
834{ 824{
835 u64 BarOffset; 825 u64 BarOffset;
836 u64 dsa; 826 u64 dsa;
827 int retry = 0;
837 u64 rc; 828 u64 rc;
838 struct iSeries_Device_Node *DevNode = 829 struct iSeries_Device_Node *DevNode =
839 xlate_iomm_address(IoAddress, &dsa, &BarOffset); 830 xlate_iomm_address(IoAddress, &dsa, &BarOffset);
@@ -853,7 +844,7 @@ void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress)
853 do { 844 do {
854 ++Pci_Io_Write_Count; 845 ++Pci_Io_Write_Count;
855 rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0); 846 rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0);
856 } while (CheckReturnCode("WWB", DevNode, rc) != 0); 847 } while (CheckReturnCode("WWB", DevNode, &retry, rc) != 0);
857} 848}
858EXPORT_SYMBOL(iSeries_Write_Byte); 849EXPORT_SYMBOL(iSeries_Write_Byte);
859 850
@@ -861,6 +852,7 @@ void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress)
861{ 852{
862 u64 BarOffset; 853 u64 BarOffset;
863 u64 dsa; 854 u64 dsa;
855 int retry = 0;
864 u64 rc; 856 u64 rc;
865 struct iSeries_Device_Node *DevNode = 857 struct iSeries_Device_Node *DevNode =
866 xlate_iomm_address(IoAddress, &dsa, &BarOffset); 858 xlate_iomm_address(IoAddress, &dsa, &BarOffset);
@@ -880,7 +872,7 @@ void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress)
880 do { 872 do {
881 ++Pci_Io_Write_Count; 873 ++Pci_Io_Write_Count;
882 rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0); 874 rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0);
883 } while (CheckReturnCode("WWW", DevNode, rc) != 0); 875 } while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0);
884} 876}
885EXPORT_SYMBOL(iSeries_Write_Word); 877EXPORT_SYMBOL(iSeries_Write_Word);
886 878
@@ -888,6 +880,7 @@ void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress)
888{ 880{
889 u64 BarOffset; 881 u64 BarOffset;
890 u64 dsa; 882 u64 dsa;
883 int retry = 0;
891 u64 rc; 884 u64 rc;
892 struct iSeries_Device_Node *DevNode = 885 struct iSeries_Device_Node *DevNode =
893 xlate_iomm_address(IoAddress, &dsa, &BarOffset); 886 xlate_iomm_address(IoAddress, &dsa, &BarOffset);
@@ -907,6 +900,6 @@ void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress)
907 do { 900 do {
908 ++Pci_Io_Write_Count; 901 ++Pci_Io_Write_Count;
909 rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0); 902 rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0);
910 } while (CheckReturnCode("WWL", DevNode, rc) != 0); 903 } while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0);
911} 904}
912EXPORT_SYMBOL(iSeries_Write_Long); 905EXPORT_SYMBOL(iSeries_Write_Long);
diff --git a/arch/ppc64/kernel/iSeries_pci_reset.c b/arch/ppc64/kernel/iSeries_pci_reset.c
deleted file mode 100644
index 0f785e4584f7..000000000000
--- a/arch/ppc64/kernel/iSeries_pci_reset.c
+++ /dev/null
@@ -1,104 +0,0 @@
1#define PCIFR(...)
2/************************************************************************/
3/* File iSeries_pci_reset.c created by Allan Trautman on Mar 21 2001. */
4/************************************************************************/
5/* This code supports the pci interface on the IBM iSeries systems. */
6/* Copyright (C) 20yy <Allan H Trautman> <IBM Corp> */
7/* */
8/* This program is free software; you can redistribute it and/or modify */
9/* it under the terms of the GNU General Public License as published by */
10/* the Free Software Foundation; either version 2 of the License, or */
11/* (at your option) any later version. */
12/* */
13/* This program is distributed in the hope that it will be useful, */
14/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
15/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
16/* GNU General Public License for more details. */
17/* */
18/* You should have received a copy of the GNU General Public License */
19/* along with this program; if not, write to the: */
20/* Free Software Foundation, Inc., */
21/* 59 Temple Place, Suite 330, */
22/* Boston, MA 02111-1307 USA */
23/************************************************************************/
24/* Change Activity: */
25/* Created, March 20, 2001 */
26/* April 30, 2001, Added return codes on functions. */
27/* September 10, 2001, Ported to ppc64. */
28/* End Change Activity */
29/************************************************************************/
30#include <linux/kernel.h>
31#include <linux/init.h>
32#include <linux/module.h>
33#include <linux/pci.h>
34#include <linux/irq.h>
35#include <linux/delay.h>
36
37#include <asm/io.h>
38#include <asm/iSeries/HvCallPci.h>
39#include <asm/iSeries/HvTypes.h>
40#include <asm/iSeries/mf.h>
41#include <asm/pci.h>
42
43#include <asm/iSeries/iSeries_pci.h>
44#include "pci.h"
45
46/*
47 * Interface to toggle the reset line
48 * Time is in .1 seconds, need for seconds.
49 */
50int iSeries_Device_ToggleReset(struct pci_dev *PciDev, int AssertTime,
51 int DelayTime)
52{
53 unsigned int AssertDelay, WaitDelay;
54 struct iSeries_Device_Node *DeviceNode =
55 (struct iSeries_Device_Node *)PciDev->sysdata;
56
57 if (DeviceNode == NULL) {
58 printk("PCI: Pci Reset Failed, Device Node not found for pci_dev %p\n",
59 PciDev);
60 return -1;
61 }
62 /*
63 * Set defaults, Assert is .5 second, Wait is 3 seconds.
64 */
65 if (AssertTime == 0)
66 AssertDelay = 500;
67 else
68 AssertDelay = AssertTime * 100;
69
70 if (DelayTime == 0)
71 WaitDelay = 3000;
72 else
73 WaitDelay = DelayTime * 100;
74
75 /*
76 * Assert reset
77 */
78 DeviceNode->ReturnCode = HvCallPci_setSlotReset(ISERIES_BUS(DeviceNode),
79 0x00, DeviceNode->AgentId, 1);
80 if (DeviceNode->ReturnCode == 0) {
81 msleep(AssertDelay); /* Sleep for the time */
82 DeviceNode->ReturnCode =
83 HvCallPci_setSlotReset(ISERIES_BUS(DeviceNode),
84 0x00, DeviceNode->AgentId, 0);
85
86 /*
87 * Wait for device to reset
88 */
89 msleep(WaitDelay);
90 }
91 if (DeviceNode->ReturnCode == 0)
92 PCIFR("Slot 0x%04X.%02 Reset\n", ISERIES_BUS(DeviceNode),
93 DeviceNode->AgentId);
94 else {
95 printk("PCI: Slot 0x%04X.%02X Reset Failed, RCode: %04X\n",
96 ISERIES_BUS(DeviceNode), DeviceNode->AgentId,
97 DeviceNode->ReturnCode);
98 PCIFR("Slot 0x%04X.%02X Reset Failed, RCode: %04X\n",
99 ISERIES_BUS(DeviceNode), DeviceNode->AgentId,
100 DeviceNode->ReturnCode);
101 }
102 return DeviceNode->ReturnCode;
103}
104EXPORT_SYMBOL(iSeries_Device_ToggleReset);
diff --git a/arch/ppc64/kernel/iSeries_proc.c b/arch/ppc64/kernel/iSeries_proc.c
index 0cc58ddf48de..356bd9931fcc 100644
--- a/arch/ppc64/kernel/iSeries_proc.c
+++ b/arch/ppc64/kernel/iSeries_proc.c
@@ -28,8 +28,7 @@
28#include <asm/iSeries/ItLpQueue.h> 28#include <asm/iSeries/ItLpQueue.h>
29#include <asm/iSeries/HvCallXm.h> 29#include <asm/iSeries/HvCallXm.h>
30#include <asm/iSeries/IoHriMainStore.h> 30#include <asm/iSeries/IoHriMainStore.h>
31#include <asm/iSeries/LparData.h> 31#include <asm/iSeries/IoHriProcessorVpd.h>
32#include <asm/iSeries/iSeries_proc.h>
33 32
34static int __init iseries_proc_create(void) 33static int __init iseries_proc_create(void)
35{ 34{
diff --git a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c
index 6d06eb550a3f..b31962436fe3 100644
--- a/arch/ppc64/kernel/iSeries_setup.c
+++ b/arch/ppc64/kernel/iSeries_setup.c
@@ -47,7 +47,7 @@
47#include <asm/paca.h> 47#include <asm/paca.h>
48#include <asm/cache.h> 48#include <asm/cache.h>
49#include <asm/sections.h> 49#include <asm/sections.h>
50#include <asm/iSeries/LparData.h> 50#include <asm/abs_addr.h>
51#include <asm/iSeries/HvCallHpt.h> 51#include <asm/iSeries/HvCallHpt.h>
52#include <asm/iSeries/HvLpConfig.h> 52#include <asm/iSeries/HvLpConfig.h>
53#include <asm/iSeries/HvCallEvent.h> 53#include <asm/iSeries/HvCallEvent.h>
@@ -55,10 +55,12 @@
55#include <asm/iSeries/HvCallXm.h> 55#include <asm/iSeries/HvCallXm.h>
56#include <asm/iSeries/ItLpQueue.h> 56#include <asm/iSeries/ItLpQueue.h>
57#include <asm/iSeries/IoHriMainStore.h> 57#include <asm/iSeries/IoHriMainStore.h>
58#include <asm/iSeries/iSeries_proc.h>
59#include <asm/iSeries/mf.h> 58#include <asm/iSeries/mf.h>
60#include <asm/iSeries/HvLpEvent.h> 59#include <asm/iSeries/HvLpEvent.h>
61#include <asm/iSeries/iSeries_irq.h> 60#include <asm/iSeries/iSeries_irq.h>
61#include <asm/iSeries/IoHriProcessorVpd.h>
62#include <asm/iSeries/ItVpdAreas.h>
63#include <asm/iSeries/LparMap.h>
62 64
63extern void hvlog(char *fmt, ...); 65extern void hvlog(char *fmt, ...);
64 66
@@ -74,7 +76,11 @@ extern void ppcdbg_initialize(void);
74static void build_iSeries_Memory_Map(void); 76static void build_iSeries_Memory_Map(void);
75static void setup_iSeries_cache_sizes(void); 77static void setup_iSeries_cache_sizes(void);
76static void iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr); 78static void iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr);
79#ifdef CONFIG_PCI
77extern void iSeries_pci_final_fixup(void); 80extern void iSeries_pci_final_fixup(void);
81#else
82static void iSeries_pci_final_fixup(void) { }
83#endif
78 84
79/* Global Variables */ 85/* Global Variables */
80static unsigned long procFreqHz; 86static unsigned long procFreqHz;
@@ -874,6 +880,10 @@ static int set_spread_lpevents(char *str)
874} 880}
875__setup("spread_lpevents=", set_spread_lpevents); 881__setup("spread_lpevents=", set_spread_lpevents);
876 882
883#ifndef CONFIG_PCI
884void __init iSeries_init_IRQ(void) { }
885#endif
886
877void __init iSeries_early_setup(void) 887void __init iSeries_early_setup(void)
878{ 888{
879 iSeries_fixup_klimit(); 889 iSeries_fixup_klimit();
diff --git a/arch/ppc64/kernel/iSeries_smp.c b/arch/ppc64/kernel/iSeries_smp.c
index ba1f084d5462..f74386e31638 100644
--- a/arch/ppc64/kernel/iSeries_smp.c
+++ b/arch/ppc64/kernel/iSeries_smp.c
@@ -38,9 +38,7 @@
38#include <asm/io.h> 38#include <asm/io.h>
39#include <asm/smp.h> 39#include <asm/smp.h>
40#include <asm/paca.h> 40#include <asm/paca.h>
41#include <asm/iSeries/LparData.h>
42#include <asm/iSeries/HvCall.h> 41#include <asm/iSeries/HvCall.h>
43#include <asm/iSeries/HvCallCfg.h>
44#include <asm/time.h> 42#include <asm/time.h>
45#include <asm/ppcdebug.h> 43#include <asm/ppcdebug.h>
46#include <asm/machdep.h> 44#include <asm/machdep.h>
diff --git a/arch/ppc64/kernel/idle.c b/arch/ppc64/kernel/idle.c
index f24ce2b87200..bdf13b4dc1c8 100644
--- a/arch/ppc64/kernel/idle.c
+++ b/arch/ppc64/kernel/idle.c
@@ -42,6 +42,11 @@ static int (*idle_loop)(void);
42static unsigned long maxYieldTime = 0; 42static unsigned long maxYieldTime = 0;
43static unsigned long minYieldTime = 0xffffffffffffffffUL; 43static unsigned long minYieldTime = 0xffffffffffffffffUL;
44 44
45static inline void process_iSeries_events(void)
46{
47 asm volatile ("li 0,0x5555; sc" : : : "r0", "r3");
48}
49
45static void yield_shared_processor(void) 50static void yield_shared_processor(void)
46{ 51{
47 unsigned long tb; 52 unsigned long tb;
@@ -292,7 +297,7 @@ static int native_idle(void)
292 if (need_resched()) 297 if (need_resched())
293 schedule(); 298 schedule();
294 299
295 if (cpu_is_offline(_smp_processor_id()) && 300 if (cpu_is_offline(raw_smp_processor_id()) &&
296 system_state == SYSTEM_RUNNING) 301 system_state == SYSTEM_RUNNING)
297 cpu_die(); 302 cpu_die();
298 } 303 }
diff --git a/arch/ppc64/kernel/iommu.c b/arch/ppc64/kernel/iommu.c
index 344164681d2c..8316426ccaf6 100644
--- a/arch/ppc64/kernel/iommu.c
+++ b/arch/ppc64/kernel/iommu.c
@@ -423,6 +423,9 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl)
423 tbl->it_largehint = tbl->it_halfpoint; 423 tbl->it_largehint = tbl->it_halfpoint;
424 spin_lock_init(&tbl->it_lock); 424 spin_lock_init(&tbl->it_lock);
425 425
426 /* Clear the hardware table in case firmware left allocations in it */
427 ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size);
428
426 if (!welcomed) { 429 if (!welcomed) {
427 printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n", 430 printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n",
428 novmerge ? "disabled" : "enabled"); 431 novmerge ? "disabled" : "enabled");
diff --git a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c
index 4fd7f203c1e3..d860467b8f09 100644
--- a/arch/ppc64/kernel/irq.c
+++ b/arch/ppc64/kernel/irq.c
@@ -52,7 +52,7 @@
52#include <asm/cache.h> 52#include <asm/cache.h>
53#include <asm/prom.h> 53#include <asm/prom.h>
54#include <asm/ptrace.h> 54#include <asm/ptrace.h>
55#include <asm/iSeries/LparData.h> 55#include <asm/iSeries/ItLpQueue.h>
56#include <asm/machdep.h> 56#include <asm/machdep.h>
57#include <asm/paca.h> 57#include <asm/paca.h>
58 58
diff --git a/arch/ppc64/kernel/lparcfg.c b/arch/ppc64/kernel/lparcfg.c
index a8fd32df848b..387923fcf9b0 100644
--- a/arch/ppc64/kernel/lparcfg.c
+++ b/arch/ppc64/kernel/lparcfg.c
@@ -28,12 +28,12 @@
28#include <asm/uaccess.h> 28#include <asm/uaccess.h>
29#include <asm/iSeries/HvLpConfig.h> 29#include <asm/iSeries/HvLpConfig.h>
30#include <asm/lppaca.h> 30#include <asm/lppaca.h>
31#include <asm/iSeries/LparData.h>
32#include <asm/hvcall.h> 31#include <asm/hvcall.h>
33#include <asm/cputable.h> 32#include <asm/cputable.h>
34#include <asm/rtas.h> 33#include <asm/rtas.h>
35#include <asm/system.h> 34#include <asm/system.h>
36#include <asm/time.h> 35#include <asm/time.h>
36#include <asm/iSeries/ItExtVpdPanel.h>
37 37
38#define MODULE_VERS "1.6" 38#define MODULE_VERS "1.6"
39#define MODULE_NAME "lparcfg" 39#define MODULE_NAME "lparcfg"
diff --git a/arch/ppc64/kernel/mf.c b/arch/ppc64/kernel/mf.c
index 5aca7e8005a8..d98bebf7042f 100644
--- a/arch/ppc64/kernel/mf.c
+++ b/arch/ppc64/kernel/mf.c
@@ -40,7 +40,6 @@
40#include <asm/iSeries/vio.h> 40#include <asm/iSeries/vio.h>
41#include <asm/iSeries/mf.h> 41#include <asm/iSeries/mf.h>
42#include <asm/iSeries/HvLpConfig.h> 42#include <asm/iSeries/HvLpConfig.h>
43#include <asm/iSeries/ItSpCommArea.h>
44#include <asm/iSeries/ItLpQueue.h> 43#include <asm/iSeries/ItLpQueue.h>
45 44
46/* 45/*
diff --git a/arch/ppc64/kernel/of_device.c b/arch/ppc64/kernel/of_device.c
index f4c825a69fa0..66bd5ab7c25a 100644
--- a/arch/ppc64/kernel/of_device.c
+++ b/arch/ppc64/kernel/of_device.c
@@ -161,7 +161,7 @@ void of_unregister_driver(struct of_platform_driver *drv)
161} 161}
162 162
163 163
164static ssize_t dev_show_devspec(struct device *dev, char *buf) 164static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
165{ 165{
166 struct of_device *ofdev; 166 struct of_device *ofdev;
167 167
diff --git a/arch/ppc64/kernel/pSeries_smp.c b/arch/ppc64/kernel/pSeries_smp.c
index fbad349ec58c..4203bd020c82 100644
--- a/arch/ppc64/kernel/pSeries_smp.c
+++ b/arch/ppc64/kernel/pSeries_smp.c
@@ -375,7 +375,7 @@ static int smp_pSeries_cpu_bootable(unsigned int nr)
375 * cpus are assumed to be secondary threads. 375 * cpus are assumed to be secondary threads.
376 */ 376 */
377 if (system_state < SYSTEM_RUNNING && 377 if (system_state < SYSTEM_RUNNING &&
378 cur_cpu_spec->cpu_features & CPU_FTR_SMT && 378 cpu_has_feature(CPU_FTR_SMT) &&
379 !smt_enabled_at_boot && nr % 2 != 0) 379 !smt_enabled_at_boot && nr % 2 != 0)
380 return 0; 380 return 0;
381 381
@@ -419,8 +419,8 @@ void __init smp_init_pSeries(void)
419#endif 419#endif
420 420
421 /* Mark threads which are still spinning in hold loops. */ 421 /* Mark threads which are still spinning in hold loops. */
422 if (cur_cpu_spec->cpu_features & CPU_FTR_SMT) 422 if (cpu_has_feature(CPU_FTR_SMT)) {
423 for_each_present_cpu(i) { 423 for_each_present_cpu(i) {
424 if (i % 2 == 0) 424 if (i % 2 == 0)
425 /* 425 /*
426 * Even-numbered logical cpus correspond to 426 * Even-numbered logical cpus correspond to
@@ -428,8 +428,9 @@ void __init smp_init_pSeries(void)
428 */ 428 */
429 cpu_set(i, of_spin_map); 429 cpu_set(i, of_spin_map);
430 } 430 }
431 else 431 } else {
432 of_spin_map = cpu_present_map; 432 of_spin_map = cpu_present_map;
433 }
433 434
434 cpu_clear(boot_cpuid, of_spin_map); 435 cpu_clear(boot_cpuid, of_spin_map);
435 436
diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c
index d786d4b6af0b..2bf0513f3eca 100644
--- a/arch/ppc64/kernel/pci.c
+++ b/arch/ppc64/kernel/pci.c
@@ -507,7 +507,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
507} 507}
508 508
509#ifdef CONFIG_PPC_MULTIPLATFORM 509#ifdef CONFIG_PPC_MULTIPLATFORM
510static ssize_t pci_show_devspec(struct device *dev, char *buf) 510static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
511{ 511{
512 struct pci_dev *pdev; 512 struct pci_dev *pdev;
513 struct device_node *np; 513 struct device_node *np;
diff --git a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c
index cdfecbeb331f..aba89554d89d 100644
--- a/arch/ppc64/kernel/process.c
+++ b/arch/ppc64/kernel/process.c
@@ -58,14 +58,6 @@ struct task_struct *last_task_used_math = NULL;
58struct task_struct *last_task_used_altivec = NULL; 58struct task_struct *last_task_used_altivec = NULL;
59#endif 59#endif
60 60
61struct mm_struct ioremap_mm = {
62 .pgd = ioremap_dir,
63 .mm_users = ATOMIC_INIT(2),
64 .mm_count = ATOMIC_INIT(1),
65 .cpu_vm_mask = CPU_MASK_ALL,
66 .page_table_lock = SPIN_LOCK_UNLOCKED,
67};
68
69/* 61/*
70 * Make sure the floating-point register state in the 62 * Make sure the floating-point register state in the
71 * the thread_struct is up to date for task tsk. 63 * the thread_struct is up to date for task tsk.
diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
index eb6538b58008..47727a6f7346 100644
--- a/arch/ppc64/kernel/prom.c
+++ b/arch/ppc64/kernel/prom.c
@@ -884,6 +884,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
884{ 884{
885 char *type = get_flat_dt_prop(node, "device_type", NULL); 885 char *type = get_flat_dt_prop(node, "device_type", NULL);
886 u32 *prop; 886 u32 *prop;
887 unsigned long size;
887 888
888 /* We are scanning "cpu" nodes only */ 889 /* We are scanning "cpu" nodes only */
889 if (type == NULL || strcmp(type, "cpu") != 0) 890 if (type == NULL || strcmp(type, "cpu") != 0)
@@ -929,6 +930,17 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
929 cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; 930 cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC;
930 } 931 }
931 932
933 /*
934 * Check for an SMT capable CPU and set the CPU feature. We do
935 * this by looking at the size of the ibm,ppc-interrupt-server#s
936 * property
937 */
938 prop = (u32 *)get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s",
939 &size);
940 cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT;
941 if (prop && ((size / sizeof(u32)) > 1))
942 cur_cpu_spec->cpu_features |= CPU_FTR_SMT;
943
932 return 0; 944 return 0;
933} 945}
934 946
diff --git a/arch/ppc64/kernel/ras.c b/arch/ppc64/kernel/ras.c
index 1c4c796b212b..3c00f7bfc1b5 100644
--- a/arch/ppc64/kernel/ras.c
+++ b/arch/ppc64/kernel/ras.c
@@ -47,7 +47,6 @@
47#include <asm/cache.h> 47#include <asm/cache.h>
48#include <asm/prom.h> 48#include <asm/prom.h>
49#include <asm/ptrace.h> 49#include <asm/ptrace.h>
50#include <asm/iSeries/LparData.h>
51#include <asm/machdep.h> 50#include <asm/machdep.h>
52#include <asm/rtas.h> 51#include <asm/rtas.h>
53#include <asm/ppcdebug.h> 52#include <asm/ppcdebug.h>
diff --git a/arch/ppc64/kernel/rtasd.c b/arch/ppc64/kernel/rtasd.c
index ff65dc33320e..b0c3b829fe47 100644
--- a/arch/ppc64/kernel/rtasd.c
+++ b/arch/ppc64/kernel/rtasd.c
@@ -440,7 +440,7 @@ static int rtasd(void *unused)
440 goto error; 440 goto error;
441 } 441 }
442 442
443 printk(KERN_ERR "RTAS daemon started\n"); 443 printk(KERN_INFO "RTAS daemon started\n");
444 444
445 DEBUG("will sleep for %d jiffies\n", (HZ*60/rtas_event_scan_rate) / 2); 445 DEBUG("will sleep for %d jiffies\n", (HZ*60/rtas_event_scan_rate) / 2);
446 446
@@ -485,7 +485,7 @@ static int __init rtas_init(void)
485 /* No RTAS, only warn if we are on a pSeries box */ 485 /* No RTAS, only warn if we are on a pSeries box */
486 if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) { 486 if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) {
487 if (systemcfg->platform & PLATFORM_PSERIES) 487 if (systemcfg->platform & PLATFORM_PSERIES)
488 printk(KERN_ERR "rtasd: no event-scan on system\n"); 488 printk(KERN_INFO "rtasd: no event-scan on system\n");
489 return 1; 489 return 1;
490 } 490 }
491 491
diff --git a/arch/ppc64/kernel/rtc.c b/arch/ppc64/kernel/rtc.c
index 67989055a9fe..de02aedbe080 100644
--- a/arch/ppc64/kernel/rtc.c
+++ b/arch/ppc64/kernel/rtc.c
@@ -42,10 +42,8 @@
42#include <asm/time.h> 42#include <asm/time.h>
43#include <asm/rtas.h> 43#include <asm/rtas.h>
44 44
45#include <asm/iSeries/LparData.h>
46#include <asm/iSeries/mf.h> 45#include <asm/iSeries/mf.h>
47#include <asm/machdep.h> 46#include <asm/machdep.h>
48#include <asm/iSeries/ItSpCommArea.h>
49 47
50extern int piranha_simulator; 48extern int piranha_simulator;
51 49
diff --git a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c
index dce198d39328..8e439a817642 100644
--- a/arch/ppc64/kernel/setup.c
+++ b/arch/ppc64/kernel/setup.c
@@ -41,7 +41,6 @@
41#include <asm/smp.h> 41#include <asm/smp.h>
42#include <asm/elf.h> 42#include <asm/elf.h>
43#include <asm/machdep.h> 43#include <asm/machdep.h>
44#include <asm/iSeries/LparData.h>
45#include <asm/paca.h> 44#include <asm/paca.h>
46#include <asm/ppcdebug.h> 45#include <asm/ppcdebug.h>
47#include <asm/time.h> 46#include <asm/time.h>
@@ -57,6 +56,8 @@
57#include <asm/cache.h> 56#include <asm/cache.h>
58#include <asm/page.h> 57#include <asm/page.h>
59#include <asm/mmu.h> 58#include <asm/mmu.h>
59#include <asm/lmb.h>
60#include <asm/iSeries/ItLpNaca.h>
60 61
61#ifdef DEBUG 62#ifdef DEBUG
62#define DBG(fmt...) udbg_printf(fmt) 63#define DBG(fmt...) udbg_printf(fmt)
diff --git a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c
index 9c8e317c598d..118436e8085a 100644
--- a/arch/ppc64/kernel/sys_ppc32.c
+++ b/arch/ppc64/kernel/sys_ppc32.c
@@ -741,6 +741,7 @@ asmlinkage int sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubu
741 741
742asmlinkage int sys32_pciconfig_iobase(u32 which, u32 in_bus, u32 in_devfn) 742asmlinkage int sys32_pciconfig_iobase(u32 which, u32 in_bus, u32 in_devfn)
743{ 743{
744#ifdef CONFIG_PCI
744 struct pci_controller* hose; 745 struct pci_controller* hose;
745 struct list_head *ln; 746 struct list_head *ln;
746 struct pci_bus *bus = NULL; 747 struct pci_bus *bus = NULL;
@@ -786,7 +787,7 @@ asmlinkage int sys32_pciconfig_iobase(u32 which, u32 in_bus, u32 in_devfn)
786 case IOBASE_ISA_MEM: 787 case IOBASE_ISA_MEM:
787 return -EINVAL; 788 return -EINVAL;
788 } 789 }
789 790#endif /* CONFIG_PCI */
790 return -EOPNOTSUPP; 791 return -EOPNOTSUPP;
791} 792}
792 793
diff --git a/arch/ppc64/kernel/vio.c b/arch/ppc64/kernel/vio.c
index cdd830cb2768..0c0ba71ac0e8 100644
--- a/arch/ppc64/kernel/vio.c
+++ b/arch/ppc64/kernel/vio.c
@@ -41,20 +41,25 @@ static const struct vio_device_id *vio_match_device(
41static struct iommu_table *vio_build_iommu_table(struct vio_dev *); 41static struct iommu_table *vio_build_iommu_table(struct vio_dev *);
42static int vio_num_address_cells; 42static int vio_num_address_cells;
43#endif 43#endif
44static struct vio_dev *vio_bus_device; /* fake "parent" device */
45
46#ifdef CONFIG_PPC_ISERIES 44#ifdef CONFIG_PPC_ISERIES
47static struct vio_dev *__init vio_register_device_iseries(char *type,
48 uint32_t unit_num);
49
50static struct iommu_table veth_iommu_table; 45static struct iommu_table veth_iommu_table;
51static struct iommu_table vio_iommu_table; 46static struct iommu_table vio_iommu_table;
52 47#endif
53static struct vio_dev _vio_dev = { 48static struct vio_dev vio_bus_device = { /* fake "parent" device */
49 .name = vio_bus_device.dev.bus_id,
50 .type = "",
51#ifdef CONFIG_PPC_ISERIES
54 .iommu_table = &vio_iommu_table, 52 .iommu_table = &vio_iommu_table,
55 .dev.bus = &vio_bus_type 53#endif
54 .dev.bus_id = "vio",
55 .dev.bus = &vio_bus_type,
56}; 56};
57struct device *iSeries_vio_dev = &_vio_dev.dev; 57
58#ifdef CONFIG_PPC_ISERIES
59static struct vio_dev *__init vio_register_device_iseries(char *type,
60 uint32_t unit_num);
61
62struct device *iSeries_vio_dev = &vio_bus_device.dev;
58EXPORT_SYMBOL(iSeries_vio_dev); 63EXPORT_SYMBOL(iSeries_vio_dev);
59 64
60#define device_is_compatible(a, b) 1 65#define device_is_compatible(a, b) 1
@@ -260,18 +265,10 @@ static int __init vio_bus_init(void)
260 } 265 }
261 266
262 /* the fake parent of all vio devices, just to give us a nice directory */ 267 /* the fake parent of all vio devices, just to give us a nice directory */
263 vio_bus_device = kmalloc(sizeof(struct vio_dev), GFP_KERNEL); 268 err = device_register(&vio_bus_device.dev);
264 if (!vio_bus_device) {
265 return 1;
266 }
267 memset(vio_bus_device, 0, sizeof(struct vio_dev));
268 strcpy(vio_bus_device->dev.bus_id, "vio");
269
270 err = device_register(&vio_bus_device->dev);
271 if (err) { 269 if (err) {
272 printk(KERN_WARNING "%s: device_register returned %i\n", __FUNCTION__, 270 printk(KERN_WARNING "%s: device_register returned %i\n", __FUNCTION__,
273 err); 271 err);
274 kfree(vio_bus_device);
275 return err; 272 return err;
276 } 273 }
277 274
@@ -300,7 +297,7 @@ static void __devinit vio_dev_release(struct device *dev)
300} 297}
301 298
302#ifdef CONFIG_PPC_PSERIES 299#ifdef CONFIG_PPC_PSERIES
303static ssize_t viodev_show_devspec(struct device *dev, char *buf) 300static ssize_t viodev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
304{ 301{
305 struct device_node *of_node = dev->platform_data; 302 struct device_node *of_node = dev->platform_data;
306 303
@@ -309,7 +306,7 @@ static ssize_t viodev_show_devspec(struct device *dev, char *buf)
309DEVICE_ATTR(devspec, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_devspec, NULL); 306DEVICE_ATTR(devspec, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_devspec, NULL);
310#endif 307#endif
311 308
312static ssize_t viodev_show_name(struct device *dev, char *buf) 309static ssize_t viodev_show_name(struct device *dev, struct device_attribute *attr, char *buf)
313{ 310{
314 return sprintf(buf, "%s\n", to_vio_dev(dev)->name); 311 return sprintf(buf, "%s\n", to_vio_dev(dev)->name);
315} 312}
@@ -326,7 +323,7 @@ static struct vio_dev * __devinit vio_register_device_common(
326 viodev->unit_address = unit_address; 323 viodev->unit_address = unit_address;
327 viodev->iommu_table = iommu_table; 324 viodev->iommu_table = iommu_table;
328 /* init generic 'struct device' fields: */ 325 /* init generic 'struct device' fields: */
329 viodev->dev.parent = &vio_bus_device->dev; 326 viodev->dev.parent = &vio_bus_device.dev;
330 viodev->dev.bus = &vio_bus_type; 327 viodev->dev.bus = &vio_bus_type;
331 viodev->dev.release = vio_dev_release; 328 viodev->dev.release = vio_dev_release;
332 329
@@ -636,5 +633,3 @@ struct bus_type vio_bus_type = {
636 .name = "vio", 633 .name = "vio",
637 .match = vio_bus_match, 634 .match = vio_bus_match,
638}; 635};
639
640EXPORT_SYMBOL(vio_bus_type);
diff --git a/arch/ppc64/kernel/viopath.c b/arch/ppc64/kernel/viopath.c
index 2ed8ee075680..2a6c4f01c45e 100644
--- a/arch/ppc64/kernel/viopath.c
+++ b/arch/ppc64/kernel/viopath.c
@@ -43,12 +43,10 @@
43#include <asm/system.h> 43#include <asm/system.h>
44#include <asm/uaccess.h> 44#include <asm/uaccess.h>
45#include <asm/iSeries/HvTypes.h> 45#include <asm/iSeries/HvTypes.h>
46#include <asm/iSeries/LparData.h> 46#include <asm/iSeries/ItExtVpdPanel.h>
47#include <asm/iSeries/HvLpEvent.h> 47#include <asm/iSeries/HvLpEvent.h>
48#include <asm/iSeries/HvLpConfig.h> 48#include <asm/iSeries/HvLpConfig.h>
49#include <asm/iSeries/HvCallCfg.h>
50#include <asm/iSeries/mf.h> 49#include <asm/iSeries/mf.h>
51#include <asm/iSeries/iSeries_proc.h>
52#include <asm/iSeries/vio.h> 50#include <asm/iSeries/vio.h>
53 51
54/* Status of the path to each other partition in the system. 52/* Status of the path to each other partition in the system.
@@ -365,7 +363,7 @@ void vio_set_hostlp(void)
365 * while we're active 363 * while we're active
366 */ 364 */
367 viopath_ourLp = HvLpConfig_getLpIndex(); 365 viopath_ourLp = HvLpConfig_getLpIndex();
368 viopath_hostLp = HvCallCfg_getHostingLpIndex(viopath_ourLp); 366 viopath_hostLp = HvLpConfig_getHostingLpIndex(viopath_ourLp);
369 367
370 if (viopath_hostLp != HvLpIndexInvalid) 368 if (viopath_hostLp != HvLpIndexInvalid)
371 vio_setHandler(viomajorsubtype_config, handleConfig); 369 vio_setHandler(viomajorsubtype_config, handleConfig);
@@ -487,7 +485,7 @@ int viopath_open(HvLpIndex remoteLp, int subtype, int numReq)
487 unsigned long flags; 485 unsigned long flags;
488 int tempNumAllocated; 486 int tempNumAllocated;
489 487
490 if ((remoteLp >= HvMaxArchitectedLps) || (remoteLp == HvLpIndexInvalid)) 488 if ((remoteLp >= HVMAXARCHITECTEDLPS) || (remoteLp == HvLpIndexInvalid))
491 return -EINVAL; 489 return -EINVAL;
492 490
493 subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT; 491 subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;
@@ -558,7 +556,7 @@ int viopath_close(HvLpIndex remoteLp, int subtype, int numReq)
558 int numOpen; 556 int numOpen;
559 struct alloc_parms parms; 557 struct alloc_parms parms;
560 558
561 if ((remoteLp >= HvMaxArchitectedLps) || (remoteLp == HvLpIndexInvalid)) 559 if ((remoteLp >= HVMAXARCHITECTEDLPS) || (remoteLp == HvLpIndexInvalid))
562 return -EINVAL; 560 return -EINVAL;
563 561
564 subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT; 562 subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;
diff --git a/arch/ppc64/lib/Makefile b/arch/ppc64/lib/Makefile
index bf7b5bbfc04e..76fbfa9f706f 100644
--- a/arch/ppc64/lib/Makefile
+++ b/arch/ppc64/lib/Makefile
@@ -12,7 +12,7 @@ lib-$(CONFIG_SMP) += locks.o
12 12
13# e2a provides EBCDIC to ASCII conversions. 13# e2a provides EBCDIC to ASCII conversions.
14ifdef CONFIG_PPC_ISERIES 14ifdef CONFIG_PPC_ISERIES
15obj-$(CONFIG_PCI) += e2a.o 15obj-y += e2a.o
16endif 16endif
17 17
18lib-$(CONFIG_DEBUG_KERNEL) += sstep.o 18lib-$(CONFIG_DEBUG_KERNEL) += sstep.o
diff --git a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c
index 0a0f97008d02..1647b1c6f28e 100644
--- a/arch/ppc64/mm/hash_utils.c
+++ b/arch/ppc64/mm/hash_utils.c
@@ -195,7 +195,7 @@ void __init htab_initialize(void)
195 memset((void *)table, 0, htab_size_bytes); 195 memset((void *)table, 0, htab_size_bytes);
196 } 196 }
197 197
198 mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX; 198 mode_rw = _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX;
199 199
200 /* On U3 based machines, we need to reserve the DART area and 200 /* On U3 based machines, we need to reserve the DART area and
201 * _NOT_ map it to avoid cache paradoxes as it's remapped non 201 * _NOT_ map it to avoid cache paradoxes as it's remapped non
@@ -310,10 +310,6 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
310 310
311 vsid = get_vsid(mm->context.id, ea); 311 vsid = get_vsid(mm->context.id, ea);
312 break; 312 break;
313 case IO_REGION_ID:
314 mm = &ioremap_mm;
315 vsid = get_kernel_vsid(ea);
316 break;
317 case VMALLOC_REGION_ID: 313 case VMALLOC_REGION_ID:
318 mm = &init_mm; 314 mm = &init_mm;
319 vsid = get_kernel_vsid(ea); 315 vsid = get_kernel_vsid(ea);
diff --git a/arch/ppc64/mm/hugetlbpage.c b/arch/ppc64/mm/hugetlbpage.c
index d3bf86a5c1ad..fdcfe97c75c1 100644
--- a/arch/ppc64/mm/hugetlbpage.c
+++ b/arch/ppc64/mm/hugetlbpage.c
@@ -121,7 +121,7 @@ static pte_t *hugepte_alloc(struct mm_struct *mm, pud_t *dir, unsigned long addr
121 return hugepte_offset(dir, addr); 121 return hugepte_offset(dir, addr);
122} 122}
123 123
124static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) 124pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
125{ 125{
126 pud_t *pud; 126 pud_t *pud;
127 127
@@ -134,7 +134,7 @@ static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
134 return hugepte_offset(pud, addr); 134 return hugepte_offset(pud, addr);
135} 135}
136 136
137static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr) 137pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
138{ 138{
139 pud_t *pud; 139 pud_t *pud;
140 140
@@ -147,25 +147,6 @@ static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
147 return hugepte_alloc(mm, pud, addr); 147 return hugepte_alloc(mm, pud, addr);
148} 148}
149 149
150static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma,
151 unsigned long addr, struct page *page,
152 pte_t *ptep, int write_access)
153{
154 pte_t entry;
155
156 add_mm_counter(mm, rss, HPAGE_SIZE / PAGE_SIZE);
157 if (write_access) {
158 entry =
159 pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
160 } else {
161 entry = pte_wrprotect(mk_pte(page, vma->vm_page_prot));
162 }
163 entry = pte_mkyoung(entry);
164 entry = pte_mkhuge(entry);
165
166 set_pte_at(mm, addr, ptep, entry);
167}
168
169/* 150/*
170 * This function checks for proper alignment of input addr and len parameters. 151 * This function checks for proper alignment of input addr and len parameters.
171 */ 152 */
@@ -259,80 +240,6 @@ int prepare_hugepage_range(unsigned long addr, unsigned long len)
259 return -EINVAL; 240 return -EINVAL;
260} 241}
261 242
262int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
263 struct vm_area_struct *vma)
264{
265 pte_t *src_pte, *dst_pte, entry;
266 struct page *ptepage;
267 unsigned long addr = vma->vm_start;
268 unsigned long end = vma->vm_end;
269 int err = -ENOMEM;
270
271 while (addr < end) {
272 dst_pte = huge_pte_alloc(dst, addr);
273 if (!dst_pte)
274 goto out;
275
276 src_pte = huge_pte_offset(src, addr);
277 entry = *src_pte;
278
279 ptepage = pte_page(entry);
280 get_page(ptepage);
281 add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
282 set_pte_at(dst, addr, dst_pte, entry);
283
284 addr += HPAGE_SIZE;
285 }
286
287 err = 0;
288 out:
289 return err;
290}
291
292int
293follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
294 struct page **pages, struct vm_area_struct **vmas,
295 unsigned long *position, int *length, int i)
296{
297 unsigned long vpfn, vaddr = *position;
298 int remainder = *length;
299
300 WARN_ON(!is_vm_hugetlb_page(vma));
301
302 vpfn = vaddr/PAGE_SIZE;
303 while (vaddr < vma->vm_end && remainder) {
304 if (pages) {
305 pte_t *pte;
306 struct page *page;
307
308 pte = huge_pte_offset(mm, vaddr);
309
310 /* hugetlb should be locked, and hence, prefaulted */
311 WARN_ON(!pte || pte_none(*pte));
312
313 page = &pte_page(*pte)[vpfn % (HPAGE_SIZE/PAGE_SIZE)];
314
315 WARN_ON(!PageCompound(page));
316
317 get_page(page);
318 pages[i] = page;
319 }
320
321 if (vmas)
322 vmas[i] = vma;
323
324 vaddr += PAGE_SIZE;
325 ++vpfn;
326 --remainder;
327 ++i;
328 }
329
330 *length = remainder;
331 *position = vaddr;
332
333 return i;
334}
335
336struct page * 243struct page *
337follow_huge_addr(struct mm_struct *mm, unsigned long address, int write) 244follow_huge_addr(struct mm_struct *mm, unsigned long address, int write)
338{ 245{
@@ -363,89 +270,6 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address,
363 return NULL; 270 return NULL;
364} 271}
365 272
366void unmap_hugepage_range(struct vm_area_struct *vma,
367 unsigned long start, unsigned long end)
368{
369 struct mm_struct *mm = vma->vm_mm;
370 unsigned long addr;
371 pte_t *ptep;
372 struct page *page;
373
374 WARN_ON(!is_vm_hugetlb_page(vma));
375 BUG_ON((start % HPAGE_SIZE) != 0);
376 BUG_ON((end % HPAGE_SIZE) != 0);
377
378 for (addr = start; addr < end; addr += HPAGE_SIZE) {
379 pte_t pte;
380
381 ptep = huge_pte_offset(mm, addr);
382 if (!ptep || pte_none(*ptep))
383 continue;
384
385 pte = *ptep;
386 page = pte_page(pte);
387 pte_clear(mm, addr, ptep);
388
389 put_page(page);
390 }
391 add_mm_counter(mm, rss, -((end - start) >> PAGE_SHIFT));
392 flush_tlb_pending();
393}
394
395int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
396{
397 struct mm_struct *mm = current->mm;
398 unsigned long addr;
399 int ret = 0;
400
401 WARN_ON(!is_vm_hugetlb_page(vma));
402 BUG_ON((vma->vm_start % HPAGE_SIZE) != 0);
403 BUG_ON((vma->vm_end % HPAGE_SIZE) != 0);
404
405 spin_lock(&mm->page_table_lock);
406 for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
407 unsigned long idx;
408 pte_t *pte = huge_pte_alloc(mm, addr);
409 struct page *page;
410
411 if (!pte) {
412 ret = -ENOMEM;
413 goto out;
414 }
415 if (! pte_none(*pte))
416 continue;
417
418 idx = ((addr - vma->vm_start) >> HPAGE_SHIFT)
419 + (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
420 page = find_get_page(mapping, idx);
421 if (!page) {
422 /* charge the fs quota first */
423 if (hugetlb_get_quota(mapping)) {
424 ret = -ENOMEM;
425 goto out;
426 }
427 page = alloc_huge_page();
428 if (!page) {
429 hugetlb_put_quota(mapping);
430 ret = -ENOMEM;
431 goto out;
432 }
433 ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
434 if (! ret) {
435 unlock_page(page);
436 } else {
437 hugetlb_put_quota(mapping);
438 free_huge_page(page);
439 goto out;
440 }
441 }
442 set_huge_pte(mm, vma, addr, page, pte, vma->vm_flags & VM_WRITE);
443 }
444out:
445 spin_unlock(&mm->page_table_lock);
446 return ret;
447}
448
449/* Because we have an exclusive hugepage region which lies within the 273/* Because we have an exclusive hugepage region which lies within the
450 * normal user address space, we have to take special measures to make 274 * normal user address space, we have to take special measures to make
451 * non-huge mmap()s evade the hugepage reserved regions. */ 275 * non-huge mmap()s evade the hugepage reserved regions. */
@@ -468,7 +292,12 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
468 && !is_hugepage_only_range(mm, addr,len)) 292 && !is_hugepage_only_range(mm, addr,len))
469 return addr; 293 return addr;
470 } 294 }
471 start_addr = addr = mm->free_area_cache; 295 if (len > mm->cached_hole_size) {
296 start_addr = addr = mm->free_area_cache;
297 } else {
298 start_addr = addr = TASK_UNMAPPED_BASE;
299 mm->cached_hole_size = 0;
300 }
472 301
473full_search: 302full_search:
474 vma = find_vma(mm, addr); 303 vma = find_vma(mm, addr);
@@ -492,6 +321,8 @@ full_search:
492 mm->free_area_cache = addr + len; 321 mm->free_area_cache = addr + len;
493 return addr; 322 return addr;
494 } 323 }
324 if (addr + mm->cached_hole_size < vma->vm_start)
325 mm->cached_hole_size = vma->vm_start - addr;
495 addr = vma->vm_end; 326 addr = vma->vm_end;
496 vma = vma->vm_next; 327 vma = vma->vm_next;
497 } 328 }
@@ -499,6 +330,7 @@ full_search:
499 /* Make sure we didn't miss any holes */ 330 /* Make sure we didn't miss any holes */
500 if (start_addr != TASK_UNMAPPED_BASE) { 331 if (start_addr != TASK_UNMAPPED_BASE) {
501 start_addr = addr = TASK_UNMAPPED_BASE; 332 start_addr = addr = TASK_UNMAPPED_BASE;
333 mm->cached_hole_size = 0;
502 goto full_search; 334 goto full_search;
503 } 335 }
504 return -ENOMEM; 336 return -ENOMEM;
@@ -520,6 +352,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
520 struct vm_area_struct *vma, *prev_vma; 352 struct vm_area_struct *vma, *prev_vma;
521 struct mm_struct *mm = current->mm; 353 struct mm_struct *mm = current->mm;
522 unsigned long base = mm->mmap_base, addr = addr0; 354 unsigned long base = mm->mmap_base, addr = addr0;
355 unsigned long largest_hole = mm->cached_hole_size;
523 int first_time = 1; 356 int first_time = 1;
524 357
525 /* requested length too big for entire address space */ 358 /* requested length too big for entire address space */
@@ -540,6 +373,10 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
540 return addr; 373 return addr;
541 } 374 }
542 375
376 if (len <= largest_hole) {
377 largest_hole = 0;
378 mm->free_area_cache = base;
379 }
543try_again: 380try_again:
544 /* make sure it can fit in the remaining address space */ 381 /* make sure it can fit in the remaining address space */
545 if (mm->free_area_cache < len) 382 if (mm->free_area_cache < len)
@@ -568,13 +405,21 @@ hugepage_recheck:
568 * vma->vm_start, use it: 405 * vma->vm_start, use it:
569 */ 406 */
570 if (addr+len <= vma->vm_start && 407 if (addr+len <= vma->vm_start &&
571 (!prev_vma || (addr >= prev_vma->vm_end))) 408 (!prev_vma || (addr >= prev_vma->vm_end))) {
572 /* remember the address as a hint for next time */ 409 /* remember the address as a hint for next time */
573 return (mm->free_area_cache = addr); 410 mm->cached_hole_size = largest_hole;
574 else 411 return (mm->free_area_cache = addr);
412 } else {
575 /* pull free_area_cache down to the first hole */ 413 /* pull free_area_cache down to the first hole */
576 if (mm->free_area_cache == vma->vm_end) 414 if (mm->free_area_cache == vma->vm_end) {
577 mm->free_area_cache = vma->vm_start; 415 mm->free_area_cache = vma->vm_start;
416 mm->cached_hole_size = largest_hole;
417 }
418 }
419
420 /* remember the largest hole we saw so far */
421 if (addr + largest_hole < vma->vm_start)
422 largest_hole = vma->vm_start - addr;
578 423
579 /* try just below the current vma->vm_start */ 424 /* try just below the current vma->vm_start */
580 addr = vma->vm_start-len; 425 addr = vma->vm_start-len;
@@ -587,6 +432,7 @@ fail:
587 */ 432 */
588 if (first_time) { 433 if (first_time) {
589 mm->free_area_cache = base; 434 mm->free_area_cache = base;
435 largest_hole = 0;
590 first_time = 0; 436 first_time = 0;
591 goto try_again; 437 goto try_again;
592 } 438 }
@@ -597,11 +443,13 @@ fail:
597 * allocations. 443 * allocations.
598 */ 444 */
599 mm->free_area_cache = TASK_UNMAPPED_BASE; 445 mm->free_area_cache = TASK_UNMAPPED_BASE;
446 mm->cached_hole_size = ~0UL;
600 addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags); 447 addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
601 /* 448 /*
602 * Restore the topdown base: 449 * Restore the topdown base:
603 */ 450 */
604 mm->free_area_cache = base; 451 mm->free_area_cache = base;
452 mm->cached_hole_size = ~0UL;
605 453
606 return addr; 454 return addr;
607} 455}
diff --git a/arch/ppc64/mm/imalloc.c b/arch/ppc64/mm/imalloc.c
index cb8727f3267a..b6e75b891ac0 100644
--- a/arch/ppc64/mm/imalloc.c
+++ b/arch/ppc64/mm/imalloc.c
@@ -15,6 +15,7 @@
15#include <asm/pgtable.h> 15#include <asm/pgtable.h>
16#include <asm/semaphore.h> 16#include <asm/semaphore.h>
17#include <asm/imalloc.h> 17#include <asm/imalloc.h>
18#include <asm/cacheflush.h>
18 19
19static DECLARE_MUTEX(imlist_sem); 20static DECLARE_MUTEX(imlist_sem);
20struct vm_struct * imlist = NULL; 21struct vm_struct * imlist = NULL;
@@ -285,29 +286,32 @@ struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
285 return area; 286 return area;
286} 287}
287 288
288unsigned long im_free(void * addr) 289void im_free(void * addr)
289{ 290{
290 struct vm_struct **p, *tmp; 291 struct vm_struct **p, *tmp;
291 unsigned long ret_size = 0;
292 292
293 if (!addr) 293 if (!addr)
294 return ret_size; 294 return;
295 if ((PAGE_SIZE-1) & (unsigned long) addr) { 295 if ((unsigned long) addr & ~PAGE_MASK) {
296 printk(KERN_ERR "Trying to %s bad address (%p)\n", __FUNCTION__, addr); 296 printk(KERN_ERR "Trying to %s bad address (%p)\n", __FUNCTION__, addr);
297 return ret_size; 297 return;
298 } 298 }
299 down(&imlist_sem); 299 down(&imlist_sem);
300 for (p = &imlist ; (tmp = *p) ; p = &tmp->next) { 300 for (p = &imlist ; (tmp = *p) ; p = &tmp->next) {
301 if (tmp->addr == addr) { 301 if (tmp->addr == addr) {
302 ret_size = tmp->size;
303 *p = tmp->next; 302 *p = tmp->next;
303
304 /* XXX: do we need the lock? */
305 spin_lock(&init_mm.page_table_lock);
306 unmap_vm_area(tmp);
307 spin_unlock(&init_mm.page_table_lock);
308
304 kfree(tmp); 309 kfree(tmp);
305 up(&imlist_sem); 310 up(&imlist_sem);
306 return ret_size; 311 return;
307 } 312 }
308 } 313 }
309 up(&imlist_sem); 314 up(&imlist_sem);
310 printk(KERN_ERR "Trying to %s nonexistent area (%p)\n", __FUNCTION__, 315 printk(KERN_ERR "Trying to %s nonexistent area (%p)\n", __FUNCTION__,
311 addr); 316 addr);
312 return ret_size;
313} 317}
diff --git a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c
index 4b42aff74d73..6fa1e6490b57 100644
--- a/arch/ppc64/mm/init.c
+++ b/arch/ppc64/mm/init.c
@@ -73,9 +73,6 @@ static unsigned long phbs_io_bot = PHBS_IO_BASE;
73extern pgd_t swapper_pg_dir[]; 73extern pgd_t swapper_pg_dir[];
74extern struct task_struct *current_set[NR_CPUS]; 74extern struct task_struct *current_set[NR_CPUS];
75 75
76extern pgd_t ioremap_dir[];
77pgd_t * ioremap_pgd = (pgd_t *)&ioremap_dir;
78
79unsigned long klimit = (unsigned long)_end; 76unsigned long klimit = (unsigned long)_end;
80 77
81unsigned long _SDR1=0; 78unsigned long _SDR1=0;
@@ -137,69 +134,6 @@ void iounmap(volatile void __iomem *addr)
137 134
138#else 135#else
139 136
140static void unmap_im_area_pte(pmd_t *pmd, unsigned long addr,
141 unsigned long end)
142{
143 pte_t *pte;
144
145 pte = pte_offset_kernel(pmd, addr);
146 do {
147 pte_t ptent = ptep_get_and_clear(&ioremap_mm, addr, pte);
148 WARN_ON(!pte_none(ptent) && !pte_present(ptent));
149 } while (pte++, addr += PAGE_SIZE, addr != end);
150}
151
152static inline void unmap_im_area_pmd(pud_t *pud, unsigned long addr,
153 unsigned long end)
154{
155 pmd_t *pmd;
156 unsigned long next;
157
158 pmd = pmd_offset(pud, addr);
159 do {
160 next = pmd_addr_end(addr, end);
161 if (pmd_none_or_clear_bad(pmd))
162 continue;
163 unmap_im_area_pte(pmd, addr, next);
164 } while (pmd++, addr = next, addr != end);
165}
166
167static inline void unmap_im_area_pud(pgd_t *pgd, unsigned long addr,
168 unsigned long end)
169{
170 pud_t *pud;
171 unsigned long next;
172
173 pud = pud_offset(pgd, addr);
174 do {
175 next = pud_addr_end(addr, end);
176 if (pud_none_or_clear_bad(pud))
177 continue;
178 unmap_im_area_pmd(pud, addr, next);
179 } while (pud++, addr = next, addr != end);
180}
181
182static void unmap_im_area(unsigned long addr, unsigned long end)
183{
184 struct mm_struct *mm = &ioremap_mm;
185 unsigned long next;
186 pgd_t *pgd;
187
188 spin_lock(&mm->page_table_lock);
189
190 pgd = pgd_offset_i(addr);
191 flush_cache_vunmap(addr, end);
192 do {
193 next = pgd_addr_end(addr, end);
194 if (pgd_none_or_clear_bad(pgd))
195 continue;
196 unmap_im_area_pud(pgd, addr, next);
197 } while (pgd++, addr = next, addr != end);
198 flush_tlb_kernel_range(start, end);
199
200 spin_unlock(&mm->page_table_lock);
201}
202
203/* 137/*
204 * map_io_page currently only called by __ioremap 138 * map_io_page currently only called by __ioremap
205 * map_io_page adds an entry to the ioremap page table 139 * map_io_page adds an entry to the ioremap page table
@@ -214,21 +148,21 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags)
214 unsigned long vsid; 148 unsigned long vsid;
215 149
216 if (mem_init_done) { 150 if (mem_init_done) {
217 spin_lock(&ioremap_mm.page_table_lock); 151 spin_lock(&init_mm.page_table_lock);
218 pgdp = pgd_offset_i(ea); 152 pgdp = pgd_offset_k(ea);
219 pudp = pud_alloc(&ioremap_mm, pgdp, ea); 153 pudp = pud_alloc(&init_mm, pgdp, ea);
220 if (!pudp) 154 if (!pudp)
221 return -ENOMEM; 155 return -ENOMEM;
222 pmdp = pmd_alloc(&ioremap_mm, pudp, ea); 156 pmdp = pmd_alloc(&init_mm, pudp, ea);
223 if (!pmdp) 157 if (!pmdp)
224 return -ENOMEM; 158 return -ENOMEM;
225 ptep = pte_alloc_kernel(&ioremap_mm, pmdp, ea); 159 ptep = pte_alloc_kernel(&init_mm, pmdp, ea);
226 if (!ptep) 160 if (!ptep)
227 return -ENOMEM; 161 return -ENOMEM;
228 pa = abs_to_phys(pa); 162 pa = abs_to_phys(pa);
229 set_pte_at(&ioremap_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, 163 set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT,
230 __pgprot(flags))); 164 __pgprot(flags)));
231 spin_unlock(&ioremap_mm.page_table_lock); 165 spin_unlock(&init_mm.page_table_lock);
232 } else { 166 } else {
233 unsigned long va, vpn, hash, hpteg; 167 unsigned long va, vpn, hash, hpteg;
234 168
@@ -267,13 +201,9 @@ static void __iomem * __ioremap_com(unsigned long addr, unsigned long pa,
267 201
268 for (i = 0; i < size; i += PAGE_SIZE) 202 for (i = 0; i < size; i += PAGE_SIZE)
269 if (map_io_page(ea+i, pa+i, flags)) 203 if (map_io_page(ea+i, pa+i, flags))
270 goto failure; 204 return NULL;
271 205
272 return (void __iomem *) (ea + (addr & ~PAGE_MASK)); 206 return (void __iomem *) (ea + (addr & ~PAGE_MASK));
273 failure:
274 if (mem_init_done)
275 unmap_im_area(ea, ea + size);
276 return NULL;
277} 207}
278 208
279 209
@@ -381,19 +311,14 @@ int __ioremap_explicit(unsigned long pa, unsigned long ea,
381 */ 311 */
382void iounmap(volatile void __iomem *token) 312void iounmap(volatile void __iomem *token)
383{ 313{
384 unsigned long address, size;
385 void *addr; 314 void *addr;
386 315
387 if (!mem_init_done) 316 if (!mem_init_done)
388 return; 317 return;
389 318
390 addr = (void *) ((unsigned long __force) token & PAGE_MASK); 319 addr = (void *) ((unsigned long __force) token & PAGE_MASK);
391
392 if ((size = im_free(addr)) == 0)
393 return;
394 320
395 address = (unsigned long)addr; 321 im_free(addr);
396 unmap_im_area(address, address + size);
397} 322}
398 323
399static int iounmap_subset_regions(unsigned long addr, unsigned long size) 324static int iounmap_subset_regions(unsigned long addr, unsigned long size)
diff --git a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c
index 3c0ccb2623ae..7f6e13a4b71e 100644
--- a/arch/ppc64/xmon/xmon.c
+++ b/arch/ppc64/xmon/xmon.c
@@ -2247,7 +2247,14 @@ scanhex(unsigned long *vp)
2247 tmpstr[i] = c; 2247 tmpstr[i] = c;
2248 } 2248 }
2249 tmpstr[i++] = 0; 2249 tmpstr[i++] = 0;
2250 *vp = kallsyms_lookup_name(tmpstr); 2250 *vp = 0;
2251 if (setjmp(bus_error_jmp) == 0) {
2252 catch_memory_errors = 1;
2253 sync();
2254 *vp = kallsyms_lookup_name(tmpstr);
2255 sync();
2256 }
2257 catch_memory_errors = 0;
2251 if (!(*vp)) { 2258 if (!(*vp)) {
2252 printf("unknown symbol '%s'\n", tmpstr); 2259 printf("unknown symbol '%s'\n", tmpstr);
2253 return 0; 2260 return 0;