Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
e54c378a
Commit
e54c378a
authored
Dec 08, 2002
by
Anton Blanchard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ppc64: EEH cleanup from Todd Inglett
parent
84f2d288
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
322 additions
and
312 deletions
+322
-312
arch/ppc64/kernel/chrp_setup.c
arch/ppc64/kernel/chrp_setup.c
+4
-3
arch/ppc64/kernel/eeh.c
arch/ppc64/kernel/eeh.c
+153
-100
arch/ppc64/kernel/htab.c
arch/ppc64/kernel/htab.c
+1
-1
arch/ppc64/kernel/pSeries_pci.c
arch/ppc64/kernel/pSeries_pci.c
+16
-67
arch/ppc64/kernel/pci.c
arch/ppc64/kernel/pci.c
+46
-16
arch/ppc64/kernel/pci.h
arch/ppc64/kernel/pci.h
+1
-0
arch/ppc64/mm/init.c
arch/ppc64/mm/init.c
+4
-6
include/asm-ppc64/eeh.h
include/asm-ppc64/eeh.h
+61
-45
include/asm-ppc64/io.h
include/asm-ppc64/io.h
+27
-73
include/asm-ppc64/page.h
include/asm-ppc64/page.h
+2
-0
include/asm-ppc64/prom.h
include/asm-ppc64/prom.h
+7
-1
No files found.
arch/ppc64/kernel/chrp_setup.c
View file @
e54c378a
...
@@ -141,11 +141,12 @@ chrp_setup_arch(void)
...
@@ -141,11 +141,12 @@ chrp_setup_arch(void)
fwnmi_init
();
fwnmi_init
();
#ifndef CONFIG_PPC_ISERIES
/* Find and initialize PCI host bridges */
/* Find and initialize PCI host bridges */
/* iSeries needs to be done much later. */
/* iSeries needs to be done much later. */
#ifndef CONFIG_PPC_ISERIES
eeh_init
();
find_and_init_phbs
();
find_and_init_phbs
();
#endif
#endif
/* Find the Open PIC if present */
/* Find the Open PIC if present */
root
=
find_path_device
(
"/"
);
root
=
find_path_device
(
"/"
);
...
...
arch/ppc64/kernel/eeh.c
View file @
e54c378a
...
@@ -43,25 +43,25 @@ static int ibm_set_eeh_option;
...
@@ -43,25 +43,25 @@ static int ibm_set_eeh_option;
static
int
ibm_set_slot_reset
;
static
int
ibm_set_slot_reset
;
static
int
ibm_read_slot_reset_state
;
static
int
ibm_read_slot_reset_state
;
int
eeh_implemented
;
static
int
eeh_implemented
;
#define EEH_MAX_OPTS 4096
#define EEH_MAX_OPTS 4096
static
char
*
eeh_opts
;
static
char
*
eeh_opts
;
static
int
eeh_opts_last
;
static
int
eeh_opts_last
;
static
int
eeh_check_opts_config
(
struct
pci_dev
*
dev
,
int
default_state
);
pte_t
*
find_linux_pte
(
pgd_t
*
pgdir
,
unsigned
long
va
);
/* from htab.c */
static
int
eeh_check_opts_config
(
struct
device_node
*
dn
,
int
class_code
,
int
vendor_id
,
int
device_id
,
int
default_state
);
unsigned
long
eeh_token
(
unsigned
long
phb
,
unsigned
long
bus
,
unsigned
long
devfn
,
unsigned
long
offset
)
unsigned
long
eeh_token
_to_phys
(
unsigned
long
token
)
{
{
if
(
phb
>
0xff
)
if
(
REGION_ID
(
token
)
==
EEH_REGION_ID
)
{
panic
(
"eeh_token: phb 0x%lx is too large
\n
"
,
phb
);
unsigned
long
vaddr
=
IO_TOKEN_TO_ADDR
(
token
);
if
(
offset
&
0x0fffffff00000000
)
pte_t
*
ptep
=
find_linux_pte
(
ioremap_mm
.
pgd
,
vaddr
);
panic
(
"eeh_token: offset 0x%lx is out of range
\n
"
,
offset
);
unsigned
long
pa
=
pte_pfn
(
*
ptep
)
<<
PAGE_SHIFT
;
return
((
IO_UNMAPPED_REGION_ID
<<
60
)
|
(
phb
<<
48UL
)
|
((
bus
&
0xff
)
<<
40UL
)
|
(
devfn
<<
32UL
)
|
(
offset
&
0xffffffff
));
return
pa
|
(
vaddr
&
(
PAGE_SIZE
-
1
));
}
}
else
return
token
;
int
eeh_get_state
(
unsigned
long
ea
)
{
return
0
;
}
}
/* Check for an eeh failure at the given token address.
/* Check for an eeh failure at the given token address.
...
@@ -73,40 +73,54 @@ int eeh_get_state(unsigned long ea)
...
@@ -73,40 +73,54 @@ int eeh_get_state(unsigned long ea)
*/
*/
unsigned
long
eeh_check_failure
(
void
*
token
,
unsigned
long
val
)
unsigned
long
eeh_check_failure
(
void
*
token
,
unsigned
long
val
)
{
{
unsigned
long
config_addr
=
(
unsigned
long
)
token
>>
24
;
/* PPBBDDRR */
unsigned
long
addr
;
unsigned
long
phbidx
=
(
config_addr
>>
24
)
&
0xff
;
struct
pci_dev
*
dev
;
struct
pci_controller
*
phb
;
struct
device_node
*
dn
;
unsigned
long
ret
,
rets
[
2
];
unsigned
long
ret
,
rets
[
2
];
config_addr
&=
0xffff00
;
/* 00BBDD00 */
/* IO BAR access could get us here...or if we manually force EEH
* operation on even if the hardware won't support it.
*/
if
(
!
eeh_implemented
||
ibm_read_slot_reset_state
==
RTAS_UNKNOWN_SERVICE
)
return
val
;
if
(
phbidx
>=
global_phb_number
)
{
/* Finding the phys addr + pci device is quite expensive.
panic
(
"EEH: checking token %p phb index of %ld is greater than max of %d
\n
"
,
token
,
phbidx
,
global_phb_number
-
1
);
* However, the RTAS call is MUCH slower.... :(
*/
addr
=
eeh_token_to_phys
((
unsigned
long
)
token
);
dev
=
pci_find_dev_by_addr
(
addr
);
if
(
!
dev
)
{
printk
(
"EEH: no pci dev found for addr=0x%lx
\n
"
,
addr
);
return
val
;
}
}
phb
=
phbtab
[
phbidx
];
dn
=
pci_device_to_OF_node
(
dev
);
if
(
!
dn
)
{
ret
=
rtas_call
(
ibm_read_slot_reset_state
,
3
,
3
,
rets
,
printk
(
"EEH: no pci dn found for addr=0x%lx
\n
"
,
addr
);
config_addr
,
BUID_HI
(
phb
->
buid
),
BUID_LO
(
phb
->
buid
));
return
val
;
if
(
ret
==
0
&&
rets
[
1
]
==
1
&&
rets
[
0
]
>=
2
)
{
}
struct
pci_dev
*
dev
;
int
bus
=
((
unsigned
long
)
token
>>
40
)
&
0xffff
;
/* include PHB# in bus */
/* Access to IO BARs might get this far and still not want checking. */
int
devfn
=
(
config_addr
>>
8
)
&
0xff
;
if
(
!
(
dn
->
eeh_mode
&
EEH_MODE_SUPPORTED
)
||
dn
->
eeh_mode
&
EEH_MODE_NOCHECK
)
return
val
;
dev
=
pci_find_slot
(
bus
,
devfn
);
if
(
dev
)
{
printk
(
KERN_ERR
"EEH: MMIO failure (%ld) on device:
\n
%s %s
\n
"
,
/* Now test for an EEH failure. This is VERY expensive.
rets
[
0
],
dev
->
slot_name
,
dev
->
dev
.
name
);
* Note that the eeh_config_addr may be a parent device
PPCDBG_ENTER_DEBUGGER
();
* in the case of a device behind a bridge, or it may be
* function zero of a multi-function device.
* In any case they must share a common PHB.
*/
if
(
dn
->
eeh_config_addr
)
{
ret
=
rtas_call
(
ibm_read_slot_reset_state
,
3
,
3
,
rets
,
dn
->
eeh_config_addr
,
BUID_HI
(
dn
->
phb
->
buid
),
BUID_LO
(
dn
->
phb
->
buid
));
if
(
ret
==
0
&&
rets
[
1
]
==
1
&&
rets
[
0
]
>=
2
)
{
panic
(
"EEH: MMIO failure (%ld) on device:
\n
%s %s
\n
"
,
panic
(
"EEH: MMIO failure (%ld) on device:
\n
%s %s
\n
"
,
rets
[
0
],
dev
->
slot_name
,
dev
->
dev
.
name
);
rets
[
0
],
dev
->
slot_name
,
dev
->
dev
.
name
);
}
else
{
printk
(
KERN_ERR
"EEH: MMIO failure (%ld) on device buid %lx, config_addr %lx
\n
"
,
rets
[
0
],
phb
->
buid
,
config_addr
);
PPCDBG_ENTER_DEBUGGER
();
panic
(
"EEH: MMIO failure (%ld) on device buid %lx, config_addr %lx
\n
"
,
rets
[
0
],
phb
->
buid
,
config_addr
);
}
}
}
}
eeh_false_positives
++
;
eeh_false_positives
++
;
return
val
;
/* good case */
return
val
;
/* good case */
}
}
struct
eeh_early_enable_info
{
struct
eeh_early_enable_info
{
...
@@ -120,13 +134,69 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
...
@@ -120,13 +134,69 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
{
{
struct
eeh_early_enable_info
*
info
=
data
;
struct
eeh_early_enable_info
*
info
=
data
;
long
ret
;
long
ret
;
char
*
status
=
get_property
(
dn
,
"status"
,
0
);
u32
*
class_code
=
(
u32
*
)
get_property
(
dn
,
"class-code"
,
0
);
u32
*
vendor_id
=
(
u32
*
)
get_property
(
dn
,
"vendor-id"
,
0
);
u32
*
device_id
=
(
u32
*
)
get_property
(
dn
,
"device-id"
,
0
);
u32
*
regs
;
int
enable
;
if
(
status
&&
strcmp
(
status
,
"ok"
)
!=
0
)
return
NULL
;
/* ignore devices with bad status */
/* Weed out PHBs or other bad nodes. */
if
(
!
class_code
||
!
vendor_id
||
!
device_id
)
return
NULL
;
/* Ignore known PHBs and EADs bridges */
if
(
*
vendor_id
==
PCI_VENDOR_ID_IBM
&&
(
*
device_id
==
0x0102
||
*
device_id
==
0x008b
||
*
device_id
==
0x0188
||
*
device_id
==
0x0302
))
return
NULL
;
/* Now decide if we are going to "Disable" EEH checking
* for this device. We still run with the EEH hardware active,
* but we won't be checking for ff's. This means a driver
* could return bad data (very bad!), an interrupt handler could
* hang waiting on status bits that won't change, etc.
* But there are a few cases like display devices that make sense.
*/
enable
=
1
;
/* i.e. we will do checking */
if
((
*
class_code
>>
16
)
==
PCI_BASE_CLASS_DISPLAY
)
enable
=
0
;
if
(
!
eeh_check_opts_config
(
dn
,
*
class_code
,
*
vendor_id
,
*
device_id
,
enable
))
{
if
(
enable
)
{
printk
(
KERN_INFO
"EEH: %s user requested to run without EEH.
\n
"
,
dn
->
full_name
);
enable
=
0
;
}
}
if
(
!
enable
)
dn
->
eeh_mode
=
EEH_MODE_NOCHECK
;
/* Try to enable eeh */
/* This device may already have an EEH parent. */
ret
=
rtas_call
(
ibm_set_eeh_option
,
4
,
1
,
NULL
,
if
(
dn
->
parent
&&
(
dn
->
parent
->
eeh_mode
&
EEH_MODE_SUPPORTED
))
{
CONFIG_ADDR
(
dn
->
busno
,
dn
->
devfn
),
/* Parent supports EEH. */
info
->
buid_hi
,
info
->
buid_lo
,
EEH_ENABLE
);
dn
->
eeh_mode
|=
EEH_MODE_SUPPORTED
;
if
(
ret
==
0
)
dn
->
eeh_config_addr
=
dn
->
parent
->
eeh_config_addr
;
info
->
adapters_enabled
++
;
return
NULL
;
}
/* Ok..see if this device supports EEH. */
regs
=
(
u32
*
)
get_property
(
dn
,
"reg"
,
0
);
if
(
regs
)
{
/* First register entry is addr (00BBSS00) */
/* Try to enable eeh */
ret
=
rtas_call
(
ibm_set_eeh_option
,
4
,
1
,
NULL
,
regs
[
0
],
info
->
buid_hi
,
info
->
buid_lo
,
EEH_ENABLE
);
if
(
ret
==
0
)
{
info
->
adapters_enabled
++
;
dn
->
eeh_mode
|=
EEH_MODE_SUPPORTED
;
dn
->
eeh_config_addr
=
regs
[
0
];
}
}
return
NULL
;
return
NULL
;
}
}
...
@@ -157,7 +227,13 @@ void eeh_init(void)
...
@@ -157,7 +227,13 @@ void eeh_init(void)
ibm_set_slot_reset
=
rtas_token
(
"ibm,set-slot-reset"
);
ibm_set_slot_reset
=
rtas_token
(
"ibm,set-slot-reset"
);
ibm_read_slot_reset_state
=
rtas_token
(
"ibm,read-slot-reset-state"
);
ibm_read_slot_reset_state
=
rtas_token
(
"ibm,read-slot-reset-state"
);
if
(
ibm_set_eeh_option
==
RTAS_UNKNOWN_SERVICE
)
/* Allow user to force eeh mode on or off -- even if the hardware
* doesn't exist. This allows driver writers to at least test use
* of I/O macros even if we can't actually test for EEH failure.
*/
if
(
eeh_force_on
>
eeh_force_off
)
eeh_implemented
=
1
;
else
if
(
ibm_set_eeh_option
==
RTAS_UNKNOWN_SERVICE
)
return
;
return
;
if
(
eeh_force_off
>
eeh_force_on
)
{
if
(
eeh_force_off
>
eeh_force_on
)
{
...
@@ -168,8 +244,6 @@ void eeh_init(void)
...
@@ -168,8 +244,6 @@ void eeh_init(void)
return
;
return
;
}
}
if
(
eeh_force_on
>
eeh_force_off
)
eeh_implemented
=
1
;
/* User is forcing it on. */
/* Enable EEH for all adapters. Note that eeh requires buid's */
/* Enable EEH for all adapters. Note that eeh requires buid's */
info
.
adapters_enabled
=
0
;
info
.
adapters_enabled
=
0
;
...
@@ -197,44 +271,6 @@ void eeh_init(void)
...
@@ -197,44 +271,6 @@ void eeh_init(void)
}
}
/* Given a PCI device check if eeh should be configured or not.
* This may look at firmware properties and/or kernel cmdline options.
*/
int
is_eeh_configured
(
struct
pci_dev
*
dev
)
{
struct
device_node
*
dn
=
pci_device_to_OF_node
(
dev
);
struct
pci_controller
*
phb
=
PCI_GET_PHB_PTR
(
dev
);
unsigned
long
ret
,
rets
[
2
];
int
eeh_capable
;
int
default_state
=
1
;
/* default enable EEH if we can. */
if
(
dn
==
NULL
||
phb
==
NULL
||
!
eeh_implemented
)
return
0
;
/* Hack: turn off eeh for display class devices by default.
* This fixes matrox accel framebuffer.
*/
if
((
dev
->
class
>>
16
)
==
PCI_BASE_CLASS_DISPLAY
)
default_state
=
0
;
/* Ignore known PHBs and EADs bridges */
if
(
dev
->
vendor
==
PCI_VENDOR_ID_IBM
&&
(
dev
->
device
==
0x0102
||
dev
->
device
==
0x008b
))
default_state
=
0
;
if
(
!
eeh_check_opts_config
(
dev
,
default_state
))
{
if
(
default_state
)
printk
(
KERN_INFO
"EEH: %s %s user requested to run without EEH.
\n
"
,
dev
->
slot_name
,
dev
->
dev
.
name
);
return
0
;
}
ret
=
rtas_call
(
ibm_read_slot_reset_state
,
3
,
3
,
rets
,
CONFIG_ADDR
(
dn
->
busno
,
dn
->
devfn
),
BUID_HI
(
phb
->
buid
),
BUID_LO
(
phb
->
buid
));
eeh_capable
=
(
ret
==
0
&&
rets
[
1
]
==
1
);
return
eeh_capable
;
}
int
eeh_set_option
(
struct
pci_dev
*
dev
,
int
option
)
int
eeh_set_option
(
struct
pci_dev
*
dev
,
int
option
)
{
{
struct
device_node
*
dn
=
pci_device_to_OF_node
(
dev
);
struct
device_node
*
dn
=
pci_device_to_OF_node
(
dev
);
...
@@ -249,6 +285,30 @@ int eeh_set_option(struct pci_dev *dev, int option)
...
@@ -249,6 +285,30 @@ int eeh_set_option(struct pci_dev *dev, int option)
}
}
/* If EEH is implemented, find the PCI device using given phys addr
* and check to see if eeh failure checking is disabled.
* Remap the addr (trivially) to the EEH region if not.
* For addresses not known to PCI the vaddr is simply returned unchanged.
*/
void
*
eeh_ioremap
(
unsigned
long
addr
,
void
*
vaddr
)
{
struct
pci_dev
*
dev
;
struct
device_node
*
dn
;
if
(
!
eeh_implemented
)
return
vaddr
;
dev
=
pci_find_dev_by_addr
(
addr
);
if
(
!
dev
)
return
vaddr
;
dn
=
pci_device_to_OF_node
(
dev
);
if
(
!
dn
)
return
vaddr
;
if
(
dn
->
eeh_mode
&
EEH_MODE_NOCHECK
)
return
vaddr
;
return
(
void
*
)
IO_ADDR_TO_TOKEN
(
vaddr
);
}
static
int
eeh_proc_falsepositive_read
(
char
*
page
,
char
**
start
,
off_t
off
,
static
int
eeh_proc_falsepositive_read
(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
void
*
data
)
int
count
,
int
*
eof
,
void
*
data
)
{
{
...
@@ -279,28 +339,24 @@ static int __init eeh_init_proc(void)
...
@@ -279,28 +339,24 @@ static int __init eeh_init_proc(void)
* This lets the user specify stupid combinations of options,
* This lets the user specify stupid combinations of options,
* but at least the result should be very predictable.
* but at least the result should be very predictable.
*/
*/
static
int
eeh_check_opts_config
(
struct
pci_dev
*
dev
,
int
default_state
)
static
int
eeh_check_opts_config
(
struct
device_node
*
dn
,
int
class_code
,
int
vendor_id
,
int
device_id
,
int
default_state
)
{
{
struct
device_node
*
dn
=
pci_device_to_OF_node
(
dev
);
char
devname
[
32
],
classname
[
32
];
struct
pci_controller
*
phb
=
PCI_GET_PHB_PTR
(
dev
);
char
devname
[
32
],
classname
[
32
],
phbname
[
32
];
char
*
strs
[
8
],
*
s
;
char
*
strs
[
8
],
*
s
;
int
nstrs
,
i
;
int
nstrs
,
i
;
int
ret
=
default_state
;
int
ret
=
default_state
;
if
(
dn
==
NULL
||
phb
==
NULL
)
return
0
;
/* Build list of strings to match */
/* Build list of strings to match */
nstrs
=
0
;
nstrs
=
0
;
s
=
(
char
*
)
get_property
(
dn
,
"ibm,loc-code"
,
0
);
s
=
(
char
*
)
get_property
(
dn
,
"ibm,loc-code"
,
0
);
if
(
s
)
if
(
s
)
strs
[
nstrs
++
]
=
s
;
strs
[
nstrs
++
]
=
s
;
sprintf
(
devname
,
"dev%04x:%04x"
,
dev
->
vendor
,
dev
->
device
);
sprintf
(
devname
,
"dev%04x:%04x"
,
vendor_id
,
device_id
);
strs
[
nstrs
++
]
=
devname
;
strs
[
nstrs
++
]
=
devname
;
sprintf
(
classname
,
"class%04x"
,
dev
->
class
);
sprintf
(
classname
,
"class%04x"
,
class_code
);
strs
[
nstrs
++
]
=
classname
;
strs
[
nstrs
++
]
=
classname
;
sprintf
(
phbname
,
"pci@%lx"
,
phb
->
buid
);
strs
[
nstrs
++
]
=
phbname
;
strs
[
nstrs
++
]
=
""
;
/* yes, this matches the empty string */
strs
[
nstrs
++
]
=
""
;
/* yes, this matches the empty string */
/* Now see if any string matches the eeh_opts list.
/* Now see if any string matches the eeh_opts list.
...
@@ -332,7 +388,6 @@ static int eeh_check_opts_config(struct pci_dev *dev, int default_state)
...
@@ -332,7 +388,6 @@ static int eeh_check_opts_config(struct pci_dev *dev, int default_state)
*
*
* dev#:# vendor:device id in hex (e.g. dev1022:2000)
* dev#:# vendor:device id in hex (e.g. dev1022:2000)
* class# class id in hex (e.g. class0200)
* class# class id in hex (e.g. class0200)
* pci@buid all devices under phb (e.g. pci@fef00000)
*
*
* If no location code is specified all devices are assumed
* If no location code is specified all devices are assumed
* so eeh-off means eeh by default is off.
* so eeh-off means eeh by default is off.
...
@@ -340,13 +395,11 @@ static int eeh_check_opts_config(struct pci_dev *dev, int default_state)
...
@@ -340,13 +395,11 @@ static int eeh_check_opts_config(struct pci_dev *dev, int default_state)
/* This is implemented as a null separated list of strings.
/* This is implemented as a null separated list of strings.
* Each string looks like this: "+X" or "-X"
* Each string looks like this: "+X" or "-X"
* where X is a loc code,
dev, class or pci string
(as shown above)
* where X is a loc code,
vendor:device, class
(as shown above)
* or empty which is used to indicate all.
* or empty which is used to indicate all.
*
*
* We interpret this option string list during the buswalk
* We interpret this option string list so that it will literally
* so that it will literally behave left-to-right even if
* behave left-to-right even if some combinations don't make sense.
* some combinations don't make sense. Give the user exactly
* what they want! :)
*/
*/
static
int
__init
eeh_parm
(
char
*
str
,
int
state
)
static
int
__init
eeh_parm
(
char
*
str
,
int
state
)
...
...
arch/ppc64/kernel/htab.c
View file @
e54c378a
...
@@ -393,7 +393,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
...
@@ -393,7 +393,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
mm
=
&
init_mm
;
mm
=
&
init_mm
;
vsid
=
get_kernel_vsid
(
ea
);
vsid
=
get_kernel_vsid
(
ea
);
break
;
break
;
case
IO_UNMAPPED
_REGION_ID
:
case
EEH
_REGION_ID
:
/*
/*
* Should only be hit if there is an access to MMIO space
* Should only be hit if there is an access to MMIO space
* which is protected by EEH.
* which is protected by EEH.
...
...
arch/ppc64/kernel/pSeries_pci.c
View file @
e54c378a
...
@@ -39,7 +39,6 @@
...
@@ -39,7 +39,6 @@
#include <asm/ppcdebug.h>
#include <asm/ppcdebug.h>
#include <asm/naca.h>
#include <asm/naca.h>
#include <asm/pci_dma.h>
#include <asm/pci_dma.h>
#include <asm/eeh.h>
#include "xics.h"
#include "xics.h"
#include "open_pic.h"
#include "open_pic.h"
...
@@ -250,8 +249,6 @@ find_and_init_phbs(void)
...
@@ -250,8 +249,6 @@ find_and_init_phbs(void)
ibm_read_pci_config
=
rtas_token
(
"ibm,read-pci-config"
);
ibm_read_pci_config
=
rtas_token
(
"ibm,read-pci-config"
);
ibm_write_pci_config
=
rtas_token
(
"ibm,write-pci-config"
);
ibm_write_pci_config
=
rtas_token
(
"ibm,write-pci-config"
);
eeh_init
();
if
(
naca
->
interrupt_controller
==
IC_OPEN_PIC
)
{
if
(
naca
->
interrupt_controller
==
IC_OPEN_PIC
)
{
opprop
=
(
unsigned
int
*
)
get_property
(
find_path_device
(
"/"
),
opprop
=
(
unsigned
int
*
)
get_property
(
find_path_device
(
"/"
),
"platform-open-pic"
,
NULL
);
"platform-open-pic"
,
NULL
);
...
@@ -350,24 +347,16 @@ find_and_init_phbs(void)
...
@@ -350,24 +347,16 @@ find_and_init_phbs(void)
res
=
&
phb
->
io_resource
;
res
=
&
phb
->
io_resource
;
res
->
name
=
Pci_Node
->
full_name
;
res
->
name
=
Pci_Node
->
full_name
;
res
->
flags
=
IORESOURCE_IO
;
res
->
flags
=
IORESOURCE_IO
;
if
(
is_eeh_implemented
())
{
phb
->
io_base_virt
=
__ioremap
(
phb
->
io_base_phys
,
range
.
size
,
_PAGE_NO_CACHE
);
if
(
!
isa_io_base
&&
has_isa
)
{
printk
(
"back
\n
"
);
/* map a page for ISA ports. Not EEH protected. */
if
(
!
pci_io_base
)
{
isa_io_base
=
(
unsigned
long
)
__ioremap
(
phb
->
io_base_phys
,
PAGE_SIZE
,
_PAGE_NO_CACHE
);
pci_io_base
=
(
unsigned
long
)
phb
->
io_base_virt
;
}
if
(
has_isa
)
res
->
start
=
phb
->
io_base_virt
=
eeh_token
(
index
,
0
,
0
,
0
);
isa_io_base
=
pci_io_base
;
res
->
end
=
eeh_token
(
index
,
0xff
,
0xff
,
0xffffffff
);
}
else
{
phb
->
io_base_virt
=
ioremap
(
phb
->
io_base_phys
,
range
.
size
);
if
(
!
pci_io_base
)
{
pci_io_base
=
(
unsigned
long
)
phb
->
io_base_virt
;
if
(
has_isa
)
isa_io_base
=
pci_io_base
;
}
res
->
start
=
((((
unsigned
long
)
range
.
child_addr
.
a_mid
)
<<
32
)
|
(
range
.
child_addr
.
a_lo
));
res
->
start
+=
(
unsigned
long
)
phb
->
io_base_virt
;
res
->
end
=
res
->
start
+
range
.
size
-
1
;
}
}
res
->
start
=
((((
unsigned
long
)
range
.
child_addr
.
a_mid
)
<<
32
)
|
(
range
.
child_addr
.
a_lo
));
res
->
start
+=
(
unsigned
long
)
phb
->
io_base_virt
-
pci_io_base
;
res
->
end
=
res
->
start
+
range
.
size
-
1
;
res
->
parent
=
NULL
;
res
->
parent
=
NULL
;
res
->
sibling
=
NULL
;
res
->
sibling
=
NULL
;
res
->
child
=
NULL
;
res
->
child
=
NULL
;
...
@@ -391,13 +380,8 @@ find_and_init_phbs(void)
...
@@ -391,13 +380,8 @@ find_and_init_phbs(void)
++
memno
;
++
memno
;
res
->
name
=
Pci_Node
->
full_name
;
res
->
name
=
Pci_Node
->
full_name
;
res
->
flags
=
IORESOURCE_MEM
;
res
->
flags
=
IORESOURCE_MEM
;
if
(
is_eeh_implemented
())
{
res
->
start
=
range
.
parent_addr
;
res
->
start
=
eeh_token
(
index
,
0
,
0
,
0
);
res
->
end
=
range
.
parent_addr
+
range
.
size
-
1
;
res
->
end
=
eeh_token
(
index
,
0xff
,
0xff
,
0xffffffff
);
}
else
{
res
->
start
=
range
.
parent_addr
;
res
->
end
=
range
.
parent_addr
+
range
.
size
-
1
;
}
res
->
parent
=
NULL
;
res
->
parent
=
NULL
;
res
->
sibling
=
NULL
;
res
->
sibling
=
NULL
;
res
->
child
=
NULL
;
res
->
child
=
NULL
;
...
@@ -574,7 +558,6 @@ fixup_resources(struct pci_dev *dev)
...
@@ -574,7 +558,6 @@ fixup_resources(struct pci_dev *dev)
int
i
;
int
i
;
struct
pci_controller
*
phb
=
PCI_GET_PHB_PTR
(
dev
);
struct
pci_controller
*
phb
=
PCI_GET_PHB_PTR
(
dev
);
struct
device_node
*
dn
;
struct
device_node
*
dn
;
unsigned
long
eeh_disable_bit
;
/* Add IBM loc code (slot) as a prefix to the device names for service */
/* Add IBM loc code (slot) as a prefix to the device names for service */
dn
=
pci_device_to_OF_node
(
dev
);
dn
=
pci_device_to_OF_node
(
dev
);
...
@@ -591,20 +574,6 @@ fixup_resources(struct pci_dev *dev)
...
@@ -591,20 +574,6 @@ fixup_resources(struct pci_dev *dev)
}
}
}
}
if
(
is_eeh_implemented
())
{
if
(
is_eeh_configured
(
dev
))
{
eeh_disable_bit
=
0
;
if
(
eeh_set_option
(
dev
,
EEH_ENABLE
)
!=
0
)
{
printk
(
"PCI: failed to enable EEH for %s %s
\n
"
,
dev
->
slot_name
,
dev
->
dev
.
name
);
eeh_disable_bit
=
EEH_TOKEN_DISABLED
;
}
}
else
{
/* Assume device is by default EEH_DISABLE'd */
printk
(
"PCI: eeh NOT configured for %s %s
\n
"
,
dev
->
slot_name
,
dev
->
dev
.
name
);
eeh_disable_bit
=
EEH_TOKEN_DISABLED
;
}
}
PPCDBG
(
PPCDBG_PHBINIT
,
"fixup_resources:
\n
"
);
PPCDBG
(
PPCDBG_PHBINIT
,
"fixup_resources:
\n
"
);
PPCDBG
(
PPCDBG_PHBINIT
,
"
\t
phb = 0x%016LX
\n
"
,
phb
);
PPCDBG
(
PPCDBG_PHBINIT
,
"
\t
phb = 0x%016LX
\n
"
,
phb
);
PPCDBG
(
PPCDBG_PHBINIT
,
"
\t
phb->pci_io_offset = 0x%016LX
\n
"
,
phb
->
pci_io_offset
);
PPCDBG
(
PPCDBG_PHBINIT
,
"
\t
phb->pci_io_offset = 0x%016LX
\n
"
,
phb
->
pci_io_offset
);
...
@@ -633,19 +602,9 @@ fixup_resources(struct pci_dev *dev)
...
@@ -633,19 +602,9 @@ fixup_resources(struct pci_dev *dev)
}
}
if
(
dev
->
resource
[
i
].
flags
&
IORESOURCE_IO
)
{
if
(
dev
->
resource
[
i
].
flags
&
IORESOURCE_IO
)
{
if
(
is_eeh_implemented
())
{
unsigned
long
offset
=
(
unsigned
long
)
phb
->
io_base_virt
-
pci_io_base
;
unsigned
int
busno
=
dev
->
bus
?
dev
->
bus
->
number
:
0
;
dev
->
resource
[
i
].
start
+=
offset
;
unsigned
long
size
=
dev
->
resource
[
i
].
end
-
dev
->
resource
[
i
].
start
;
dev
->
resource
[
i
].
end
+=
offset
;
unsigned
long
addr
=
(
unsigned
long
)
__ioremap
(
dev
->
resource
[
i
].
start
+
phb
->
io_base_phys
,
size
,
_PAGE_NO_CACHE
);
if
(
!
addr
)
panic
(
"fixup_resources: ioremap failed!
\n
"
);
dev
->
resource
[
i
].
start
=
eeh_token
(
phb
->
global_number
,
busno
,
dev
->
devfn
,
addr
)
|
eeh_disable_bit
;
dev
->
resource
[
i
].
end
=
dev
->
resource
[
i
].
start
+
size
;
}
else
{
unsigned
long
offset
=
(
unsigned
long
)
phb
->
io_base_virt
;
dev
->
resource
[
i
].
start
+=
offset
;
dev
->
resource
[
i
].
end
+=
offset
;
}
PPCDBG
(
PPCDBG_PHBINIT
,
"
\t\t
-> now [%lx .. %lx]
\n
"
,
PPCDBG
(
PPCDBG_PHBINIT
,
"
\t\t
-> now [%lx .. %lx]
\n
"
,
dev
->
resource
[
i
].
start
,
dev
->
resource
[
i
].
end
);
dev
->
resource
[
i
].
start
,
dev
->
resource
[
i
].
end
);
}
else
if
(
dev
->
resource
[
i
].
flags
&
IORESOURCE_MEM
)
{
}
else
if
(
dev
->
resource
[
i
].
flags
&
IORESOURCE_MEM
)
{
...
@@ -653,18 +612,8 @@ fixup_resources(struct pci_dev *dev)
...
@@ -653,18 +612,8 @@ fixup_resources(struct pci_dev *dev)
/* Bogus. Probably an unused bridge. */
/* Bogus. Probably an unused bridge. */
dev
->
resource
[
i
].
end
=
0
;
dev
->
resource
[
i
].
end
=
0
;
}
else
{
}
else
{
if
(
is_eeh_implemented
())
{
dev
->
resource
[
i
].
start
+=
phb
->
pci_mem_offset
;
unsigned
int
busno
=
dev
->
bus
?
dev
->
bus
->
number
:
0
;
dev
->
resource
[
i
].
end
+=
phb
->
pci_mem_offset
;
unsigned
long
size
=
dev
->
resource
[
i
].
end
-
dev
->
resource
[
i
].
start
;
unsigned
long
addr
=
(
unsigned
long
)
__ioremap
(
dev
->
resource
[
i
].
start
+
phb
->
pci_mem_offset
,
size
,
_PAGE_NO_CACHE
);
if
(
!
addr
)
panic
(
"fixup_resources: ioremap failed!
\n
"
);
dev
->
resource
[
i
].
start
=
eeh_token
(
phb
->
global_number
,
busno
,
dev
->
devfn
,
addr
)
|
eeh_disable_bit
;
dev
->
resource
[
i
].
end
=
dev
->
resource
[
i
].
start
+
size
;
}
else
{
dev
->
resource
[
i
].
start
+=
phb
->
pci_mem_offset
;
dev
->
resource
[
i
].
end
+=
phb
->
pci_mem_offset
;
}
}
}
PPCDBG
(
PPCDBG_PHBINIT
,
"
\t\t
-> now [%lx..%lx]
\n
"
,
PPCDBG
(
PPCDBG_PHBINIT
,
"
\t\t
-> now [%lx..%lx]
\n
"
,
dev
->
resource
[
i
].
start
,
dev
->
resource
[
i
].
end
);
dev
->
resource
[
i
].
start
,
dev
->
resource
[
i
].
end
);
...
...
arch/ppc64/kernel/pci.c
View file @
e54c378a
...
@@ -31,7 +31,6 @@
...
@@ -31,7 +31,6 @@
#include <asm/naca.h>
#include <asm/naca.h>
#include <asm/pci_dma.h>
#include <asm/pci_dma.h>
#include <asm/machdep.h>
#include <asm/machdep.h>
#include <asm/eeh.h>
#include "pci.h"
#include "pci.h"
...
@@ -121,6 +120,43 @@ static void fixup_windbond_82c105(struct pci_dev* dev)
...
@@ -121,6 +120,43 @@ static void fixup_windbond_82c105(struct pci_dev* dev)
}
}
/* Given an mmio phys address, find a pci device that implements
* this address. This is of course expensive, but only used
* for device initialization or error paths.
* For io BARs it is assumed the pci_io_base has already been added
* into addr.
*
* Bridges are ignored although they could be used to optimize the search.
*/
struct
pci_dev
*
pci_find_dev_by_addr
(
unsigned
long
addr
)
{
struct
pci_dev
*
dev
;
int
i
;
unsigned
long
ioaddr
;
ioaddr
=
(
addr
>
_IO_BASE
)
?
addr
-
_IO_BASE
:
0
;
pci_for_each_dev
(
dev
)
{
if
((
dev
->
class
>>
8
)
==
PCI_BASE_CLASS_BRIDGE
)
continue
;
for
(
i
=
0
;
i
<
DEVICE_COUNT_RESOURCE
;
i
++
)
{
unsigned
long
start
=
pci_resource_start
(
dev
,
i
);
unsigned
long
end
=
pci_resource_end
(
dev
,
i
);
unsigned
int
flags
=
pci_resource_flags
(
dev
,
i
);
if
(
start
==
0
||
~
start
==
0
||
end
==
0
||
~
end
==
0
)
continue
;
if
((
flags
&
IORESOURCE_IO
)
&&
(
ioaddr
>=
start
&&
ioaddr
<=
end
))
return
dev
;
else
if
((
flags
&
IORESOURCE_MEM
)
&&
(
addr
>=
start
&&
addr
<=
end
))
return
dev
;
}
}
return
NULL
;
}
void
__devinit
pcibios_fixup_pbus_ranges
(
struct
pci_bus
*
pbus
,
void
__devinit
pcibios_fixup_pbus_ranges
(
struct
pci_bus
*
pbus
,
struct
pbus_set_ranges_data
*
pranges
)
struct
pbus_set_ranges_data
*
pranges
)
{
{
...
@@ -486,21 +522,15 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
...
@@ -486,21 +522,15 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
/* Transparent resource -- don't try to "fix" it. */
/* Transparent resource -- don't try to "fix" it. */
continue
;
continue
;
}
}
if
(
is_eeh_implemented
())
{
if
(
res
->
flags
&
IORESOURCE_IO
)
{
if
(
res
->
flags
&
(
IORESOURCE_IO
|
IORESOURCE_MEM
))
{
unsigned
long
offset
=
(
unsigned
long
)
phb
->
io_base_virt
-
pci_io_base
;
res
->
start
=
eeh_token
(
phb
->
global_number
,
bus
->
number
,
0
,
0
);
res
->
start
+=
offset
;
res
->
end
=
eeh_token
(
phb
->
global_number
,
bus
->
number
,
0xff
,
0xffffffff
);
res
->
end
+=
offset
;
}
}
else
if
(
phb
->
pci_mem_offset
}
else
{
&&
(
res
->
flags
&
IORESOURCE_MEM
))
{
if
(
res
->
flags
&
IORESOURCE_IO
)
{
if
(
res
->
start
<
phb
->
pci_mem_offset
)
{
res
->
start
+=
(
unsigned
long
)
phb
->
io_base_virt
;
res
->
start
+=
phb
->
pci_mem_offset
;
res
->
end
+=
(
unsigned
long
)
phb
->
io_base_virt
;
res
->
end
+=
phb
->
pci_mem_offset
;
}
else
if
(
phb
->
pci_mem_offset
&&
(
res
->
flags
&
IORESOURCE_MEM
))
{
if
(
res
->
start
<
phb
->
pci_mem_offset
)
{
res
->
start
+=
phb
->
pci_mem_offset
;
res
->
end
+=
phb
->
pci_mem_offset
;
}
}
}
}
}
}
}
...
...
arch/ppc64/kernel/pci.h
View file @
e54c378a
...
@@ -56,6 +56,7 @@ typedef void *(*traverse_func)(struct device_node *me, void *data);
...
@@ -56,6 +56,7 @@ typedef void *(*traverse_func)(struct device_node *me, void *data);
void
*
traverse_pci_devices
(
struct
device_node
*
start
,
traverse_func
pre
,
traverse_func
post
,
void
*
data
);
void
*
traverse_pci_devices
(
struct
device_node
*
start
,
traverse_func
pre
,
traverse_func
post
,
void
*
data
);
void
*
traverse_all_pci_devices
(
traverse_func
pre
);
void
*
traverse_all_pci_devices
(
traverse_func
pre
);
struct
pci_dev
*
pci_find_dev_by_addr
(
unsigned
long
addr
);
void
pci_devs_phb_init
(
void
);
void
pci_devs_phb_init
(
void
);
void
pci_fix_bus_sysdata
(
void
);
void
pci_fix_bus_sysdata
(
void
);
struct
device_node
*
fetch_dev_dn
(
struct
pci_dev
*
dev
);
struct
device_node
*
fetch_dev_dn
(
struct
pci_dev
*
dev
);
...
...
arch/ppc64/mm/init.c
View file @
e54c378a
...
@@ -132,12 +132,10 @@ ioremap(unsigned long addr, unsigned long size)
...
@@ -132,12 +132,10 @@ ioremap(unsigned long addr, unsigned long size)
#ifdef CONFIG_PPC_ISERIES
#ifdef CONFIG_PPC_ISERIES
return
(
void
*
)
addr
;
return
(
void
*
)
addr
;
#else
#else
if
(
mem_init_done
&&
(
addr
>>
60UL
))
{
void
*
ret
=
__ioremap
(
addr
,
size
,
_PAGE_NO_CACHE
);
if
(
IS_EEH_TOKEN_DISABLED
(
addr
))
if
(
mem_init_done
)
return
(
void
*
)
IO_TOKEN_TO_ADDR
(
addr
);
return
eeh_ioremap
(
addr
,
ret
);
/* may remap the addr */
return
(
void
*
)
addr
;
/* already mapped address or EEH token. */
return
ret
;
}
return
__ioremap
(
addr
,
size
,
_PAGE_NO_CACHE
);
#endif
#endif
}
}
...
...
include/asm-ppc64/eeh.h
View file @
e54c378a
...
@@ -27,25 +27,26 @@
...
@@ -27,25 +27,26 @@
struct
pci_dev
;
struct
pci_dev
;
#define IO_UNMAPPED_REGION_ID 0xaUL
/* I/O addresses are converted to EEH "tokens" such that a driver will cause
* a bad page fault if the address is used directly (i.e. these addresses are
#define IO_TOKEN_TO_ADDR(token) ((((unsigned long)(token)) & 0xFFFFFFFF) | (0xEUL << 60))
* never actually mapped. Translation between IO <-> EEH region is 1 to 1.
/* Flag bits encoded in the 3 unused function bits of devfn */
*/
#define EEH_TOKEN_DISABLED (1UL << 34UL)
/* eeh is disabled for this token */
#define IO_TOKEN_TO_ADDR(token) (((unsigned long)(token) & ~(0xfUL << REGION_SHIFT)) | \
#define IS_EEH_TOKEN_DISABLED(token) ((unsigned long)(token) & EEH_TOKEN_DISABLED)
(IO_REGION_ID << REGION_SHIFT))
#define IO_ADDR_TO_TOKEN(addr) (((unsigned long)(addr) & ~(0xfUL << REGION_SHIFT)) | \
(EEH_REGION_ID << REGION_SHIFT))
#define EEH_STATE_OVERRIDE 1
/* IOA does not require eeh traps */
/* Values for eeh_mode bits in device_node */
#define EEH_STATE_FAILURE 16
/* */
#define EEH_MODE_SUPPORTED (1<<0)
#define EEH_MODE_NOCHECK (1<<1)
/* This is for profiling only */
/* This is for profiling only */
extern
unsigned
long
eeh_total_mmio_ffs
;
extern
unsigned
long
eeh_total_mmio_ffs
;
extern
int
eeh_implemented
;
void
eeh_init
(
void
);
void
eeh_init
(
void
);
static
inline
int
is_eeh_implemented
(
void
)
{
return
eeh_implemented
;
}
int
eeh_get_state
(
unsigned
long
ea
);
int
eeh_get_state
(
unsigned
long
ea
);
unsigned
long
eeh_check_failure
(
void
*
token
,
unsigned
long
val
);
unsigned
long
eeh_check_failure
(
void
*
token
,
unsigned
long
val
);
void
*
eeh_ioremap
(
unsigned
long
addr
,
void
*
vaddr
);
#define EEH_DISABLE 0
#define EEH_DISABLE 0
#define EEH_ENABLE 1
#define EEH_ENABLE 1
...
@@ -58,15 +59,11 @@ int eeh_set_option(struct pci_dev *dev, int options);
...
@@ -58,15 +59,11 @@ int eeh_set_option(struct pci_dev *dev, int options);
*/
*/
int
is_eeh_configured
(
struct
pci_dev
*
dev
);
int
is_eeh_configured
(
struct
pci_dev
*
dev
);
/* Generate an EEH token.
/* Translate a (possible) eeh token to a physical addr.
* The high nibble of the offset is cleared, otherwise bounds checking is performed.
* If "token" is not an eeh token it is simply returned under
* Use IO_TOKEN_TO_ADDR(token) to translate this token back to a mapped virtual addr.
* the assumption that it is already a physical addr.
* Do NOT do this to perform IO -- use the read/write macros!
*/
*/
unsigned
long
eeh_token
(
unsigned
long
phb
,
unsigned
long
eeh_token_to_phys
(
unsigned
long
token
);
unsigned
long
bus
,
unsigned
long
devfn
,
unsigned
long
offset
);
extern
void
*
memcpy
(
void
*
,
const
void
*
,
unsigned
long
);
extern
void
*
memcpy
(
void
*
,
const
void
*
,
unsigned
long
);
extern
void
*
memset
(
void
*
,
int
,
unsigned
long
);
extern
void
*
memset
(
void
*
,
int
,
unsigned
long
);
...
@@ -77,15 +74,16 @@ extern void *memset(void *,int, unsigned long);
...
@@ -77,15 +74,16 @@ extern void *memset(void *,int, unsigned long);
* If EEH is off for a device and it is a memory BAR, ioremap will
* If EEH is off for a device and it is a memory BAR, ioremap will
* map it to the IOREGION. In this case addr == vaddr and since these
* map it to the IOREGION. In this case addr == vaddr and since these
* should be in registers we compare them first. Next we check for
* should be in registers we compare them first. Next we check for
* all ones which is perhaps fastest as ~val. Finally we weed out
* ff's which indicates a (very) possible failure.
* EEH disabled IO BARs.
*
*
* If this macro yields TRUE, the caller relays to eeh_check_failure()
* If this macro yields TRUE, the caller relays to eeh_check_failure()
* which does further tests out of line.
* which does further tests out of line.
*/
*/
/* #define EEH_POSSIBLE_ERROR(addr, vaddr, val) ((vaddr) != (addr) && ~(val) == 0 && !IS_EEH_TOKEN_DISABLED(addr)) */
/* #define EEH_POSSIBLE_IO_ERROR(val) (~(val) == 0) */
/* #define EEH_POSSIBLE_ERROR(addr, vaddr, val) ((vaddr) != (addr) && EEH_POSSIBLE_IO_ERROR(val) */
/* This version is rearranged to collect some profiling data */
/* This version is rearranged to collect some profiling data */
#define EEH_POSSIBLE_ERROR(addr, vaddr, val) (~(val) == 0 && (++eeh_total_mmio_ffs, (vaddr) != (addr) && !IS_EEH_TOKEN_DISABLED(addr)))
#define EEH_POSSIBLE_IO_ERROR(val) (~(val) == 0 && ++eeh_total_mmio_ffs)
#define EEH_POSSIBLE_ERROR(addr, vaddr, val) (EEH_POSSIBLE_IO_ERROR(val) && (vaddr) != (addr))
/*
/*
* MMIO read/write operations with EEH support.
* MMIO read/write operations with EEH support.
...
@@ -149,38 +147,56 @@ static inline void eeh_memcpy_toio(void *dest, void *src, unsigned long n) {
...
@@ -149,38 +147,56 @@ static inline void eeh_memcpy_toio(void *dest, void *src, unsigned long n) {
memcpy
(
vdest
,
src
,
n
);
memcpy
(
vdest
,
src
,
n
);
}
}
static
inline
void
eeh_insb
(
volatile
u8
*
addr
,
void
*
buf
,
int
n
)
{
/* The I/O macros must handle ISA ports as well as PCI I/O bars.
volatile
u8
*
vaddr
=
(
volatile
u8
*
)
IO_TOKEN_TO_ADDR
(
addr
);
* ISA does not implement EEH and ISA may not exist in the system.
_insb
(
vaddr
,
buf
,
n
);
* For PCI we check for EEH failures.
/* ToDo: look for ff's in buf[n] */
*/
#define _IO_IS_ISA(port) ((port) < 0x10000)
#define _IO_HAS_ISA_BUS (isa_io_base != 0)
static
inline
u8
eeh_inb
(
unsigned
long
port
)
{
u8
val
;
if
(
_IO_IS_ISA
(
port
)
&&
!
_IO_HAS_ISA_BUS
)
return
~
0
;
val
=
in_8
((
u8
*
)(
port
+
pci_io_base
));
if
(
!
_IO_IS_ISA
(
port
)
&&
EEH_POSSIBLE_IO_ERROR
(
val
))
return
eeh_check_failure
((
void
*
)(
port
+
pci_io_base
),
val
);
return
val
;
}
}
static
inline
void
eeh_out
sb
(
volatile
u8
*
addr
,
const
void
*
buf
,
int
n
)
{
static
inline
void
eeh_out
b
(
u8
val
,
unsigned
long
port
)
{
volatile
u8
*
vaddr
=
(
volatile
u8
*
)
IO_TOKEN_TO_ADDR
(
addr
);
if
(
!
_IO_IS_ISA
(
port
)
||
_IO_HAS_ISA_BUS
)
_outsb
(
vaddr
,
buf
,
n
);
return
out_8
((
u8
*
)(
port
+
pci_io_base
),
val
);
}
}
static
inline
void
eeh_insw_ns
(
volatile
u16
*
addr
,
void
*
buf
,
int
n
)
{
static
inline
u16
eeh_inw
(
unsigned
long
port
)
{
volatile
u16
*
vaddr
=
(
volatile
u16
*
)
IO_TOKEN_TO_ADDR
(
addr
);
u16
val
;
_insw_ns
(
vaddr
,
buf
,
n
);
if
(
_IO_IS_ISA
(
port
)
&&
!
_IO_HAS_ISA_BUS
)
/* ToDo: look for ffff's in buf[n] */
return
~
0
;
val
=
in_le16
((
u16
*
)(
port
+
pci_io_base
));
if
(
!
_IO_IS_ISA
(
port
)
&&
EEH_POSSIBLE_IO_ERROR
(
val
))
return
eeh_check_failure
((
void
*
)(
port
+
pci_io_base
),
val
);
return
val
;
}
}
static
inline
void
eeh_out
sw_ns
(
volatile
u16
*
addr
,
const
void
*
buf
,
int
n
)
{
static
inline
void
eeh_out
w
(
u16
val
,
unsigned
long
port
)
{
volatile
u16
*
vaddr
=
(
volatile
u16
*
)
IO_TOKEN_TO_ADDR
(
addr
);
if
(
!
_IO_IS_ISA
(
port
)
||
_IO_HAS_ISA_BUS
)
_outsw_ns
(
vaddr
,
buf
,
n
);
return
out_le16
((
u16
*
)(
port
+
pci_io_base
),
val
);
}
}
static
inline
void
eeh_insl_ns
(
volatile
u32
*
addr
,
void
*
buf
,
int
n
)
{
static
inline
u32
eeh_inl
(
unsigned
long
port
)
{
volatile
u32
*
vaddr
=
(
volatile
u32
*
)
IO_TOKEN_TO_ADDR
(
addr
);
u32
val
;
_insl_ns
(
vaddr
,
buf
,
n
);
if
(
_IO_IS_ISA
(
port
)
&&
!
_IO_HAS_ISA_BUS
)
/* ToDo: look for ffffffff's in buf[n] */
return
~
0
;
val
=
in_le32
((
u32
*
)(
port
+
pci_io_base
));
if
(
!
_IO_IS_ISA
(
port
)
&&
EEH_POSSIBLE_IO_ERROR
(
val
))
return
eeh_check_failure
((
void
*
)(
port
+
pci_io_base
),
val
);
return
val
;
}
}
static
inline
void
eeh_out
sl_ns
(
volatile
u32
*
addr
,
const
void
*
buf
,
int
n
)
{
static
inline
void
eeh_out
l
(
u32
val
,
unsigned
long
port
)
{
volatile
u32
*
vaddr
=
(
volatile
u32
*
)
IO_TOKEN_TO_ADDR
(
addr
);
if
(
!
_IO_IS_ISA
(
port
)
||
_IO_HAS_ISA_BUS
)
_outsl_ns
(
vaddr
,
buf
,
n
);
return
out_le32
((
u32
*
)(
port
+
pci_io_base
),
val
);
}
}
#endif
/* _EEH_H */
#endif
/* _EEH_H */
include/asm-ppc64/io.h
View file @
e54c378a
...
@@ -50,36 +50,45 @@ extern int have_print;
...
@@ -50,36 +50,45 @@ extern int have_print;
#define outw(data,addr) writew(data,((unsigned long)(addr)))
#define outw(data,addr) writew(data,((unsigned long)(addr)))
#define outl(data,addr) writel(data,((unsigned long)(addr)))
#define outl(data,addr) writel(data,((unsigned long)(addr)))
#else
#else
#define IS_MAPPED_VADDR(port) ((unsigned long)(port) >> 60UL)
#define readb(addr) eeh_readb((void*)(addr))
#define readb(addr) eeh_readb((void*)(addr))
#define readw(addr) eeh_readw((void*)(addr))
#define readw(addr) eeh_readw((void*)(addr))
#define readl(addr) eeh_readl((void*)(addr))
#define readl(addr) eeh_readl((void*)(addr))
#define writeb(data, addr) eeh_writeb((data), ((void*)(addr)))
#define writeb(data, addr) eeh_writeb((data), ((void*)(addr)))
#define writew(data, addr) eeh_writew((data), ((void*)(addr)))
#define writew(data, addr) eeh_writew((data), ((void*)(addr)))
#define writel(data, addr) eeh_writel((data), ((void*)(addr)))
#define writel(data, addr) eeh_writel((data), ((void*)(addr)))
#define memset_io(a,b,c) eeh_memset((void *)(a),(b),(c))
#define memset_io(a,b,c) eeh_memset
_io
((void *)(a),(b),(c))
#define memcpy_fromio(a,b,c) eeh_memcpy_fromio((a),(void *)(b),(c))
#define memcpy_fromio(a,b,c) eeh_memcpy_fromio((a),(void *)(b),(c))
#define memcpy_toio(a,b,c) eeh_memcpy_toio((void *)(a),(b),(c))
#define memcpy_toio(a,b,c) eeh_memcpy_toio((void *)(a),(b),(c))
#define inb(port) _inb((unsigned long)port)
#define inb(port)
eeh
_inb((unsigned long)port)
#define outb(val, port) _outb(val, (unsigned long)port)
#define outb(val, port)
eeh
_outb(val, (unsigned long)port)
#define inw(port) _inw((unsigned long)port)
#define inw(port)
eeh
_inw((unsigned long)port)
#define outw(val, port) _outw(val, (unsigned long)port)
#define outw(val, port)
eeh
_outw(val, (unsigned long)port)
#define inl(port) _inl((unsigned long)port)
#define inl(port)
eeh
_inl((unsigned long)port)
#define outl(val, port) _outl(val, (unsigned long)port)
#define outl(val, port)
eeh
_outl(val, (unsigned long)port)
/*
/*
* The insw/outsw/insl/outsl macros don't do byte-swapping.
* The insw/outsw/insl/outsl macros don't do byte-swapping.
* They are only used in practice for transferring buffers which
* They are only used in practice for transferring buffers which
* are arrays of bytes, and byte-swapping is not appropriate in
* are arrays of bytes, and byte-swapping is not appropriate in
* that case. - paulus */
* that case. - paulus */
#define insb(port, buf, ns)
eeh_insb((u8 *)(port
), (buf), (ns))
#define insb(port, buf, ns)
_insb((u8 *)((port)+pci_io_base
), (buf), (ns))
#define outsb(port, buf, ns)
eeh_outsb((u8 *)(port
), (buf), (ns))
#define outsb(port, buf, ns)
_outsb((u8 *)((port)+pci_io_base
), (buf), (ns))
#define insw(port, buf, ns)
eeh_insw_ns((u16 *)(port
), (buf), (ns))
#define insw(port, buf, ns)
_insw_ns((u16 *)((port)+pci_io_base
), (buf), (ns))
#define outsw(port, buf, ns)
eeh_outsw_ns((u16 *)(port
), (buf), (ns))
#define outsw(port, buf, ns)
_outsw_ns((u16 *)((port)+pci_io_base
), (buf), (ns))
#define insl(port, buf, nl)
eeh_insl_ns((u32 *)(port
), (buf), (nl))
#define insl(port, buf, nl)
_insl_ns((u32 *)((port)+pci_io_base
), (buf), (nl))
#define outsl(port, buf, nl)
eeh_outsl_ns((u32 *)(port
), (buf), (nl))
#define outsl(port, buf, nl)
_outsl_ns((u32 *)((port)+pci_io_base
), (buf), (nl))
#endif
#endif
extern
void
_insb
(
volatile
u8
*
port
,
void
*
buf
,
int
ns
);
extern
void
_outsb
(
volatile
u8
*
port
,
const
void
*
buf
,
int
ns
);
extern
void
_insw
(
volatile
u16
*
port
,
void
*
buf
,
int
ns
);
extern
void
_outsw
(
volatile
u16
*
port
,
const
void
*
buf
,
int
ns
);
extern
void
_insl
(
volatile
u32
*
port
,
void
*
buf
,
int
nl
);
extern
void
_outsl
(
volatile
u32
*
port
,
const
void
*
buf
,
int
nl
);
extern
void
_insw_ns
(
volatile
u16
*
port
,
void
*
buf
,
int
ns
);
extern
void
_outsw_ns
(
volatile
u16
*
port
,
const
void
*
buf
,
int
ns
);
extern
void
_insl_ns
(
volatile
u32
*
port
,
void
*
buf
,
int
nl
);
extern
void
_outsl_ns
(
volatile
u32
*
port
,
const
void
*
buf
,
int
nl
);
/*
/*
* output pause versions need a delay at least for the
* output pause versions need a delay at least for the
...
@@ -92,27 +101,15 @@ extern int have_print;
...
@@ -92,27 +101,15 @@ extern int have_print;
#define inl_p(port) inl(port)
#define inl_p(port) inl(port)
#define outl_p(val, port) (udelay(1), outl((val, (port)))
#define outl_p(val, port) (udelay(1), outl((val, (port)))
extern
void
_insb
(
volatile
u8
*
port
,
void
*
buf
,
int
ns
);
extern
void
_outsb
(
volatile
u8
*
port
,
const
void
*
buf
,
int
ns
);
extern
void
_insw
(
volatile
u16
*
port
,
void
*
buf
,
int
ns
);
extern
void
_outsw
(
volatile
u16
*
port
,
const
void
*
buf
,
int
ns
);
extern
void
_insl
(
volatile
u32
*
port
,
void
*
buf
,
int
nl
);
extern
void
_outsl
(
volatile
u32
*
port
,
const
void
*
buf
,
int
nl
);
extern
void
_insw_ns
(
volatile
u16
*
port
,
void
*
buf
,
int
ns
);
extern
void
_outsw_ns
(
volatile
u16
*
port
,
const
void
*
buf
,
int
ns
);
extern
void
_insl_ns
(
volatile
u32
*
port
,
void
*
buf
,
int
nl
);
extern
void
_outsl_ns
(
volatile
u32
*
port
,
const
void
*
buf
,
int
nl
);
/*
/*
* The *_ns versions below don't do byte-swapping.
* The *_ns versions below don't do byte-swapping.
* Neither do the standard versions now, these are just here
* Neither do the standard versions now, these are just here
* for older code.
* for older code.
*/
*/
#define insw_ns(port, buf, ns)
insw(port, buf, ns
)
#define insw_ns(port, buf, ns)
_insw_ns((u16 *)((port)+pci_io_base), (buf), (ns)
)
#define outsw_ns(port, buf, ns)
outsw(port, buf, ns
)
#define outsw_ns(port, buf, ns)
_outsw_ns((u16 *)((port)+pci_io_base), (buf), (ns)
)
#define insl_ns(port, buf, nl)
insl(port, buf, nl
)
#define insl_ns(port, buf, nl)
_insl_ns((u32 *)((port)+pci_io_base), (buf), (nl)
)
#define outsl_ns(port, buf, nl)
outsl(port, buf, nl
)
#define outsl_ns(port, buf, nl)
_outsl_ns((u32 *)((port)+pci_io_base), (buf), (nl)
)
#define IO_SPACE_LIMIT ~(0UL)
#define IO_SPACE_LIMIT ~(0UL)
...
@@ -249,49 +246,6 @@ static inline void out_be32(volatile unsigned *addr, int val)
...
@@ -249,49 +246,6 @@ static inline void out_be32(volatile unsigned *addr, int val)
#ifndef CONFIG_PPC_ISERIES
#ifndef CONFIG_PPC_ISERIES
#include <asm/eeh.h>
#include <asm/eeh.h>
static
inline
u8
_inb
(
unsigned
long
port
)
{
if
(
IS_MAPPED_VADDR
(
port
))
return
readb
((
void
*
)
port
);
else
if
(
_IO_BASE
)
return
in_8
((
u8
*
)((
port
)
+
_IO_BASE
));
else
return
0xff
;
}
static
inline
void
_outb
(
u8
val
,
unsigned
long
port
)
{
if
(
IS_MAPPED_VADDR
(
port
))
return
writeb
(
val
,
(
void
*
)
port
);
else
if
(
_IO_BASE
)
out_8
((
u8
*
)((
port
)
+
_IO_BASE
),
val
);
}
static
inline
u16
_inw
(
unsigned
long
port
)
{
if
(
IS_MAPPED_VADDR
(
port
))
return
readw
((
void
*
)
port
);
else
if
(
_IO_BASE
)
return
in_le16
((
u16
*
)((
port
)
+
_IO_BASE
));
else
return
0xffff
;
}
static
inline
void
_outw
(
u16
val
,
unsigned
long
port
)
{
if
(
IS_MAPPED_VADDR
(
port
))
return
writew
(
val
,
(
void
*
)
port
);
else
if
(
_IO_BASE
)
out_le16
((
u16
*
)((
port
)
+
_IO_BASE
),
val
);
}
static
inline
u32
_inl
(
unsigned
long
port
)
{
if
(
IS_MAPPED_VADDR
(
port
))
return
readl
((
void
*
)
port
);
else
if
(
_IO_BASE
)
return
in_le32
((
u32
*
)((
port
)
+
_IO_BASE
));
else
return
0xffffffff
;
}
static
inline
void
_outl
(
u32
val
,
unsigned
long
port
)
{
if
(
IS_MAPPED_VADDR
(
port
))
return
writel
(
val
,
(
void
*
)
port
);
else
if
(
_IO_BASE
)
out_le32
((
u32
*
)((
port
)
+
_IO_BASE
),
val
);
}
#endif
#endif
#ifdef __KERNEL__
#ifdef __KERNEL__
...
...
include/asm-ppc64/page.h
View file @
e54c378a
...
@@ -168,8 +168,10 @@ static inline int get_order(unsigned long size)
...
@@ -168,8 +168,10 @@ static inline int get_order(unsigned long size)
#define KERNELBASE PAGE_OFFSET
#define KERNELBASE PAGE_OFFSET
#define VMALLOCBASE 0xD000000000000000
#define VMALLOCBASE 0xD000000000000000
#define IOREGIONBASE 0xE000000000000000
#define IOREGIONBASE 0xE000000000000000
#define EEHREGIONBASE 0xA000000000000000
#define IO_REGION_ID (IOREGIONBASE>>REGION_SHIFT)
#define IO_REGION_ID (IOREGIONBASE>>REGION_SHIFT)
#define EEH_REGION_ID (EEHREGIONBASE>>REGION_SHIFT)
#define VMALLOC_REGION_ID (VMALLOCBASE>>REGION_SHIFT)
#define VMALLOC_REGION_ID (VMALLOCBASE>>REGION_SHIFT)
#define KERNEL_REGION_ID (KERNELBASE>>REGION_SHIFT)
#define KERNEL_REGION_ID (KERNELBASE>>REGION_SHIFT)
#define USER_REGION_ID (0UL)
#define USER_REGION_ID (0UL)
...
...
include/asm-ppc64/prom.h
View file @
e54c378a
...
@@ -125,12 +125,18 @@ struct device_node {
...
@@ -125,12 +125,18 @@ struct device_node {
int
n_intrs
;
int
n_intrs
;
struct
interrupt_info
*
intrs
;
struct
interrupt_info
*
intrs
;
char
*
full_name
;
char
*
full_name
;
/* PCI stuff probably doesn't belong here */
int
busno
;
/* for pci devices */
int
busno
;
/* for pci devices */
int
bussubno
;
/* for pci devices */
int
bussubno
;
/* for pci devices */
int
devfn
;
/* for pci devices */
int
devfn
;
/* for pci devices */
#define DN_STATUS_BIST_FAILED (1<<0)
int
status
;
/* Current device status (non-zero is bad) */
int
eeh_mode
;
/* See eeh.h for possible EEH_MODEs */
int
eeh_config_addr
;
struct
pci_controller
*
phb
;
/* for pci devices */
struct
pci_controller
*
phb
;
/* for pci devices */
struct
TceTable
*
tce_table
;
/* for phb's or bridges */
struct
TceTable
*
tce_table
;
/* for phb's or bridges */
#define DN_STATUS_BIST_FAILED (1<<0)
struct
property
*
properties
;
struct
property
*
properties
;
struct
device_node
*
parent
;
struct
device_node
*
parent
;
struct
device_node
*
child
;
struct
device_node
*
child
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment