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
5a7db1eb
Commit
5a7db1eb
authored
Jun 22, 2004
by
Greg Kroah-Hartman
Browse files
Options
Browse Files
Download
Plain Diff
merge fixups.
parents
3e13e3b2
4cd5d72a
Changes
20
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
692 additions
and
380 deletions
+692
-380
Documentation/pci.txt
Documentation/pci.txt
+3
-2
Documentation/power/pci.txt
Documentation/power/pci.txt
+4
-4
arch/i386/kernel/dmi_scan.c
arch/i386/kernel/dmi_scan.c
+30
-0
arch/i386/pci/irq.c
arch/i386/pci/irq.c
+9
-0
drivers/pci/hotplug/pciehp_ctrl.c
drivers/pci/hotplug/pciehp_ctrl.c
+49
-98
drivers/pci/hotplug/pciehp_hpc.c
drivers/pci/hotplug/pciehp_hpc.c
+3
-1
drivers/pci/hotplug/pciehprm_acpi.c
drivers/pci/hotplug/pciehprm_acpi.c
+17
-5
drivers/pci/hotplug/pciehprm_nonacpi.c
drivers/pci/hotplug/pciehprm_nonacpi.c
+13
-5
drivers/pci/hotplug/rpadlpar_core.c
drivers/pci/hotplug/rpadlpar_core.c
+5
-23
drivers/pci/hotplug/rpaphp.h
drivers/pci/hotplug/rpaphp.h
+22
-6
drivers/pci/hotplug/rpaphp_core.c
drivers/pci/hotplug/rpaphp_core.c
+137
-62
drivers/pci/hotplug/rpaphp_pci.c
drivers/pci/hotplug/rpaphp_pci.c
+228
-100
drivers/pci/hotplug/rpaphp_slot.c
drivers/pci/hotplug/rpaphp_slot.c
+113
-23
drivers/pci/hotplug/rpaphp_vio.c
drivers/pci/hotplug/rpaphp_vio.c
+3
-3
drivers/pci/hotplug/shpchp.h
drivers/pci/hotplug/shpchp.h
+1
-0
drivers/pci/hotplug/shpchp_ctrl.c
drivers/pci/hotplug/shpchp_ctrl.c
+23
-37
drivers/pci/hotplug/shpchp_pci.c
drivers/pci/hotplug/shpchp_pci.c
+1
-0
drivers/pci/hotplug/shpchprm_acpi.c
drivers/pci/hotplug/shpchprm_acpi.c
+17
-5
drivers/pci/hotplug/shpchprm_nonacpi.c
drivers/pci/hotplug/shpchprm_nonacpi.c
+13
-5
drivers/pci/pci.c
drivers/pci/pci.c
+1
-1
No files found.
Documentation/pci.txt
View file @
5a7db1eb
...
...
@@ -166,8 +166,9 @@ count on these devices by calling pci_dev_put().
~~~~~~~~~~~~~~~~~~~
Before you do anything with the device you've found, you need to enable
it by calling pci_enable_device() which enables I/O and memory regions of
the device, assigns missing resources if needed and wakes up the device
if it was in suspended state. Please note that this function can fail.
the device, allocates an IRQ if necessary, assigns missing resources if
needed and wakes up the device if it was in suspended state. Please note
that this function can fail.
If you want to use the device in bus mastering mode, call pci_set_master()
which enables the bus master bit in PCI_COMMAND register and also fixes
...
...
Documentation/power/pci.txt
View file @
5a7db1eb
...
...
@@ -286,11 +286,11 @@ wake event from:
+------------------+
| Bit | State |
+------------------+
| 1
5
| D0 |
| 1
4
| D1 |
| 1
1
| D0 |
| 1
2
| D1 |
| 13 | D2 |
| 1
2
| D3hot |
| 1
1
| D3cold |
| 1
4
| D3hot |
| 1
5
| D3cold |
+------------------+
A device can use this to enable wake events:
...
...
arch/i386/kernel/dmi_scan.c
View file @
5a7db1eb
...
...
@@ -313,6 +313,22 @@ static __init int disable_smbus(struct dmi_blacklist *d)
return
0
;
}
/*
* Work around broken Acer TravelMate 360 Notebooks which assign Cardbus to
* IRQ 11 even though it is actually wired to IRQ 10
*/
static
__init
int
fix_acer_tm360_irqrouting
(
struct
dmi_blacklist
*
d
)
{
#ifdef CONFIG_PCI
extern
int
acer_tm360_irqrouting
;
if
(
acer_tm360_irqrouting
==
0
)
{
acer_tm360_irqrouting
=
1
;
printk
(
KERN_INFO
"%s detected - fixing broken IRQ routing
\n
"
,
d
->
ident
);
}
#endif
return
0
;
}
/*
* Check for clue free BIOS implementations who use
* the following QA technique
...
...
@@ -799,6 +815,13 @@ static __initdata struct dmi_blacklist dmi_blacklist[]={
NO_MATCH
,
NO_MATCH
}
},
{
fix_acer_tm360_irqrouting
,
"Acer TravelMate 36x Laptop"
,
{
MATCH
(
DMI_SYS_VENDOR
,
"Acer"
),
MATCH
(
DMI_PRODUCT_NAME
,
"TravelMate 360"
),
NO_MATCH
,
NO_MATCH
}
},
/*
* Generic per vendor APM settings
*/
...
...
@@ -986,6 +1009,13 @@ static __initdata struct dmi_blacklist dmi_blacklist[]={
MATCH
(
DMI_BOARD_NAME
,
"PR-DLS"
),
MATCH
(
DMI_BIOS_VERSION
,
"ASUS PR-DLS ACPI BIOS Revision 1010"
),
MATCH
(
DMI_BIOS_DATE
,
"03/21/2003"
)
}},
{
disable_acpi_pci
,
"Acer TravelMate 36x Laptop"
,
{
MATCH
(
DMI_SYS_VENDOR
,
"Acer"
),
MATCH
(
DMI_PRODUCT_NAME
,
"TravelMate 360"
),
NO_MATCH
,
NO_MATCH
}
},
#endif
{
NULL
,
}
...
...
arch/i386/pci/irq.c
View file @
5a7db1eb
...
...
@@ -24,6 +24,7 @@
#define PIRQ_VERSION 0x0100
static
int
broken_hp_bios_irq9
;
int
acer_tm360_irqrouting
;
static
struct
irq_routing_table
*
pirq_table
;
...
...
@@ -746,6 +747,14 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
r
->
set
(
pirq_router_dev
,
dev
,
pirq
,
11
);
}
/* same for Acer Travelmate 360, but with CB and irq 11 -> 10 */
if
(
acer_tm360_irqrouting
&&
dev
->
irq
==
11
&&
dev
->
vendor
==
PCI_VENDOR_ID_O2
)
{
pirq
=
0x68
;
mask
=
0x400
;
dev
->
irq
=
r
->
get
(
pirq_router_dev
,
dev
,
pirq
);
pci_write_config_byte
(
dev
,
PCI_INTERRUPT_LINE
,
dev
->
irq
);
}
/*
* Find the best IRQ to assign: use the one
* reported by the device if possible.
...
...
drivers/pci/hotplug/pciehp_ctrl.c
View file @
5a7db1eb
...
...
@@ -1058,6 +1058,34 @@ static int is_bridge(struct pci_func * func)
hotplug controller logic
*/
static
void
set_slot_off
(
struct
controller
*
ctrl
,
struct
slot
*
pslot
)
{
/* Wait for exclusive access to hardware */
down
(
&
ctrl
->
crit_sect
);
/* turn off slot, turn on Amber LED, turn off Green LED */
if
(
pslot
->
hpc_ops
->
power_off_slot
(
pslot
))
{
err
(
"%s: Issue of Slot Power Off command failed
\n
"
,
__FUNCTION__
);
up
(
&
ctrl
->
crit_sect
);
return
;
}
wait_for_ctrl_irq
(
ctrl
);
pslot
->
hpc_ops
->
green_led_off
(
pslot
);
wait_for_ctrl_irq
(
ctrl
);
/* turn on Amber LED */
if
(
pslot
->
hpc_ops
->
set_attention_status
(
pslot
,
1
))
{
err
(
"%s: Issue of Set Attention Led command failed
\n
"
,
__FUNCTION__
);
up
(
&
ctrl
->
crit_sect
);
return
;
}
wait_for_ctrl_irq
(
ctrl
);
/* Done with exclusive hardware access */
up
(
&
ctrl
->
crit_sect
);
}
/**
* board_added - Called after a board has been added to the system.
...
...
@@ -1071,7 +1099,7 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
u8
hp_slot
;
int
index
;
u32
temp_register
=
0xFFFFFFFF
;
u32
r
etval
,
r
c
=
0
;
u32
rc
=
0
;
struct
pci_func
*
new_func
=
NULL
;
struct
slot
*
p_slot
;
struct
resource_lists
res_lists
;
...
...
@@ -1086,8 +1114,10 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
/* Power on slot */
rc
=
p_slot
->
hpc_ops
->
power_on_slot
(
p_slot
);
if
(
rc
)
if
(
rc
)
{
up
(
&
ctrl
->
crit_sect
);
return
-
1
;
}
/* Wait for the command to complete */
wait_for_ctrl_irq
(
ctrl
);
...
...
@@ -1105,11 +1135,12 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
wait_for_ctrl_irq
(
ctrl
);
dbg
(
"%s: afterlong_delay
\n
"
,
__FUNCTION__
);
/*
Make this to check for
link training status */
/*
Check
link training status */
rc
=
p_slot
->
hpc_ops
->
check_lnk_status
(
ctrl
);
if
(
rc
)
{
err
(
"%s: Failed to check link status
\n
"
,
__FUNCTION__
);
return
-
1
;
set_slot_off
(
ctrl
,
p_slot
);
return
rc
;
}
dbg
(
"%s: func status = %x
\n
"
,
__FUNCTION__
,
func
->
status
);
...
...
@@ -1159,36 +1190,7 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
pciehp_resource_sort_and_combine
(
&
(
ctrl
->
bus_head
));
if
(
rc
)
{
/* Wait for exclusive access to hardware */
down
(
&
ctrl
->
crit_sect
);
/* turn off slot, turn on Amber LED, turn off Green LED */
retval
=
p_slot
->
hpc_ops
->
power_off_slot
(
p_slot
);
/* In PCI Express, just power off slot */
if
(
retval
)
{
err
(
"%s: Issue of Slot Power Off command failed
\n
"
,
__FUNCTION__
);
return
retval
;
}
/* Wait for the command to complete */
wait_for_ctrl_irq
(
ctrl
);
p_slot
->
hpc_ops
->
green_led_off
(
p_slot
);
/* Wait for the command to complete */
wait_for_ctrl_irq
(
ctrl
);
/* turn on Amber LED */
retval
=
p_slot
->
hpc_ops
->
set_attention_status
(
p_slot
,
1
);
if
(
retval
)
{
err
(
"%s: Issue of Set Attention Led command failed
\n
"
,
__FUNCTION__
);
return
retval
;
}
/* Wait for the command to complete */
wait_for_ctrl_irq
(
ctrl
);
/* Done with exclusive hardware access */
up
(
&
ctrl
->
crit_sect
);
set_slot_off
(
ctrl
,
p_slot
);
return
rc
;
}
pciehp_save_slot_config
(
ctrl
,
func
);
...
...
@@ -1223,37 +1225,8 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
up
(
&
ctrl
->
crit_sect
);
}
else
{
/* Wait for exclusive access to hardware */
down
(
&
ctrl
->
crit_sect
);
/* turn off slot, turn on Amber LED, turn off Green LED */
retval
=
p_slot
->
hpc_ops
->
power_off_slot
(
p_slot
);
/* In PCI Express, just power off slot */
if
(
retval
)
{
err
(
"%s: Issue of Slot Power Off command failed
\n
"
,
__FUNCTION__
);
return
retval
;
}
/* Wait for the command to complete */
wait_for_ctrl_irq
(
ctrl
);
p_slot
->
hpc_ops
->
green_led_off
(
p_slot
);
/* Wait for the command to complete */
wait_for_ctrl_irq
(
ctrl
);
/* turn on Amber LED */
retval
=
p_slot
->
hpc_ops
->
set_attention_status
(
p_slot
,
1
);
if
(
retval
)
{
err
(
"%s: Issue of Set Attention Led command failed
\n
"
,
__FUNCTION__
);
return
retval
;
}
/* Wait for the command to complete */
wait_for_ctrl_irq
(
ctrl
);
/* Done with exclusive hardware access */
up
(
&
ctrl
->
crit_sect
);
return
rc
;
set_slot_off
(
ctrl
,
p_slot
);
return
-
1
;
}
return
0
;
}
...
...
@@ -1320,6 +1293,7 @@ static u32 remove_board(struct pci_func *func, struct controller *ctrl)
rc
=
p_slot
->
hpc_ops
->
power_off_slot
(
p_slot
);
if
(
rc
)
{
err
(
"%s: Issue of Slot Disable command failed
\n
"
,
__FUNCTION__
);
up
(
&
ctrl
->
crit_sect
);
return
rc
;
}
/* Wait for the command to complete */
...
...
@@ -1406,7 +1380,6 @@ static void pciehp_pushbutton_thread(unsigned long slot)
{
struct
slot
*
p_slot
=
(
struct
slot
*
)
slot
;
u8
getstatus
;
int
rc
;
pushbutton_pending
=
0
;
...
...
@@ -1420,23 +1393,7 @@ static void pciehp_pushbutton_thread(unsigned long slot)
p_slot
->
state
=
POWEROFF_STATE
;
dbg
(
"In power_down_board, b:d(%x:%x)
\n
"
,
p_slot
->
bus
,
p_slot
->
device
);
if
(
pciehp_disable_slot
(
p_slot
))
{
/* Wait for exclusive access to hardware */
down
(
&
p_slot
->
ctrl
->
crit_sect
);
/* Turn on the Attention LED */
rc
=
p_slot
->
hpc_ops
->
set_attention_status
(
p_slot
,
1
);
if
(
rc
)
{
err
(
"%s: Issue of Set Atten Indicator On command failed
\n
"
,
__FUNCTION__
);
return
;
}
/* Wait for the command to complete */
wait_for_ctrl_irq
(
p_slot
->
ctrl
);
/* Done with exclusive hardware access */
up
(
&
p_slot
->
ctrl
->
crit_sect
);
}
pciehp_disable_slot
(
p_slot
);
p_slot
->
state
=
STATIC_STATE
;
}
else
{
p_slot
->
state
=
POWERON_STATE
;
...
...
@@ -1446,15 +1403,6 @@ static void pciehp_pushbutton_thread(unsigned long slot)
/* Wait for exclusive access to hardware */
down
(
&
p_slot
->
ctrl
->
crit_sect
);
/* Turn off the green LED */
rc
=
p_slot
->
hpc_ops
->
set_attention_status
(
p_slot
,
1
);
if
(
rc
)
{
err
(
"%s: Issue of Set Atten Indicator On command failed
\n
"
,
__FUNCTION__
);
return
;
}
/* Wait for the command to complete */
wait_for_ctrl_irq
(
p_slot
->
ctrl
);
p_slot
->
hpc_ops
->
green_led_off
(
p_slot
);
/* Wait for the command to complete */
...
...
@@ -1664,7 +1612,10 @@ static void interrupt_event_handler(struct controller *ctrl)
down
(
&
ctrl
->
crit_sect
);
p_slot
->
hpc_ops
->
set_attention_status
(
p_slot
,
1
);
wait_for_ctrl_irq
(
ctrl
);
p_slot
->
hpc_ops
->
green_led_off
(
p_slot
);
wait_for_ctrl_irq
(
ctrl
);
/* Done with exclusive hardware access */
up
(
&
ctrl
->
crit_sect
);
...
...
@@ -1701,21 +1652,21 @@ int pciehp_enable_slot(struct slot *p_slot)
if
(
rc
||
!
getstatus
)
{
info
(
"%s: no adapter on slot(%x)
\n
"
,
__FUNCTION__
,
p_slot
->
number
);
up
(
&
p_slot
->
ctrl
->
crit_sect
);
return
0
;
return
1
;
}
rc
=
p_slot
->
hpc_ops
->
get_latch_status
(
p_slot
,
&
getstatus
);
if
(
rc
||
getstatus
)
{
info
(
"%s: latch open on slot(%x)
\n
"
,
__FUNCTION__
,
p_slot
->
number
);
up
(
&
p_slot
->
ctrl
->
crit_sect
);
return
0
;
return
1
;
}
rc
=
p_slot
->
hpc_ops
->
get_power_status
(
p_slot
,
&
getstatus
);
if
(
rc
||
getstatus
)
{
info
(
"%s: already enabled on slot(%x)
\n
"
,
__FUNCTION__
,
p_slot
->
number
);
up
(
&
p_slot
->
ctrl
->
crit_sect
);
return
0
;
return
1
;
}
up
(
&
p_slot
->
ctrl
->
crit_sect
);
...
...
@@ -1788,21 +1739,21 @@ int pciehp_disable_slot(struct slot *p_slot)
if
(
ret
||
!
getstatus
)
{
info
(
"%s: no adapter on slot(%x)
\n
"
,
__FUNCTION__
,
p_slot
->
number
);
up
(
&
p_slot
->
ctrl
->
crit_sect
);
return
0
;
return
1
;
}
ret
=
p_slot
->
hpc_ops
->
get_latch_status
(
p_slot
,
&
getstatus
);
if
(
ret
||
getstatus
)
{
info
(
"%s: latch open on slot(%x)
\n
"
,
__FUNCTION__
,
p_slot
->
number
);
up
(
&
p_slot
->
ctrl
->
crit_sect
);
return
0
;
return
1
;
}
ret
=
p_slot
->
hpc_ops
->
get_power_status
(
p_slot
,
&
getstatus
);
if
(
ret
||
!
getstatus
)
{
info
(
"%s: already disabled slot(%x)
\n
"
,
__FUNCTION__
,
p_slot
->
number
);
up
(
&
p_slot
->
ctrl
->
crit_sect
);
return
0
;
return
1
;
}
up
(
&
p_slot
->
ctrl
->
crit_sect
);
...
...
drivers/pci/hotplug/pciehp_hpc.c
View file @
5a7db1eb
...
...
@@ -349,7 +349,9 @@ static int hpc_check_lnk_status(struct controller *ctrl)
return
retval
;
}
if
(
(
lnk_status
&
(
LNK_TRN
|
LNK_TRN_ERR
))
==
0x0C00
)
{
dbg
(
"%s: lnk_status = %x
\n
"
,
__FUNCTION__
,
lnk_status
);
if
(
(
lnk_status
&
LNK_TRN
)
||
(
lnk_status
&
LNK_TRN_ERR
)
||
!
(
lnk_status
&
NEG_LINK_WD
))
{
err
(
"%s : Link Training Error occurs
\n
"
,
__FUNCTION__
);
retval
=
-
1
;
return
retval
;
...
...
drivers/pci/hotplug/pciehprm_acpi.c
View file @
5a7db1eb
...
...
@@ -218,6 +218,10 @@ static void acpi_get__hpp ( struct acpi_bridge *ab)
}
ab
->
_hpp
=
kmalloc
(
sizeof
(
struct
acpi__hpp
),
GFP_KERNEL
);
if
(
!
ab
->
_hpp
)
{
err
(
"acpi_pciehprm:%s alloc for _HPP failed
\n
"
,
path_name
);
goto
free_and_return
;
}
memset
(
ab
->
_hpp
,
0
,
sizeof
(
struct
acpi__hpp
));
ab
->
_hpp
->
cache_line_size
=
nui
[
0
];
...
...
@@ -1393,7 +1397,7 @@ static int configure_existing_function(
static
int
bind_pci_resources_to_slots
(
struct
controller
*
ctrl
)
{
struct
pci_func
*
func
;
struct
pci_func
*
func
,
new_func
;
int
busn
=
ctrl
->
slot_bus
;
int
devn
,
funn
;
u32
vid
;
...
...
@@ -1411,12 +1415,20 @@ static int bind_pci_resources_to_slots ( struct controller *ctrl)
if
(
vid
!=
0xFFFFFFFF
)
{
dbg
(
"%s: vid = %x
\n
"
,
__FUNCTION__
,
vid
);
func
=
pciehp_slot_find
(
busn
,
devn
,
funn
);
if
(
!
func
)
continue
;
if
(
!
func
)
{
memset
(
&
new_func
,
0
,
sizeof
(
struct
pci_func
));
new_func
.
bus
=
busn
;
new_func
.
device
=
devn
;
new_func
.
function
=
funn
;
new_func
.
is_a_board
=
1
;
configure_existing_function
(
ctrl
,
&
new_func
);
pciehprm_dump_func_res
(
&
new_func
);
}
else
{
configure_existing_function
(
ctrl
,
func
);
dbg
(
"aCCF:existing PCI 0x%x Func ResourceDump
\n
"
,
ctrl
->
bus
);
pciehprm_dump_func_res
(
func
);
}
dbg
(
"aCCF:existing PCI 0x%x Func ResourceDump
\n
"
,
ctrl
->
bus
);
}
}
}
...
...
drivers/pci/hotplug/pciehprm_nonacpi.c
View file @
5a7db1eb
...
...
@@ -276,7 +276,7 @@ static int pciehprm_delete_resource(
static
int
bind_pci_resources_to_slots
(
struct
controller
*
ctrl
)
{
struct
pci_func
*
func
;
struct
pci_func
*
func
,
new_func
;
int
busn
=
ctrl
->
slot_bus
;
int
devn
,
funn
;
u32
vid
;
...
...
@@ -297,12 +297,20 @@ static int bind_pci_resources_to_slots ( struct controller *ctrl)
vid
,
busn
,
devn
,
funn
);
func
=
pciehp_slot_find
(
busn
,
devn
,
funn
);
dbg
(
"%s: func = %p
\n
"
,
__FUNCTION__
,
func
);
if
(
!
func
)
continue
;
if
(
!
func
)
{
memset
(
&
new_func
,
0
,
sizeof
(
struct
pci_func
));
new_func
.
bus
=
busn
;
new_func
.
device
=
devn
;
new_func
.
function
=
funn
;
new_func
.
is_a_board
=
1
;
configure_existing_function
(
ctrl
,
&
new_func
);
phprm_dump_func_res
(
&
new_func
);
}
else
{
configure_existing_function
(
ctrl
,
func
);
dbg
(
"aCCF:existing PCI 0x%x Func ResourceDump
\n
"
,
ctrl
->
bus
);
phprm_dump_func_res
(
func
);
}
dbg
(
"aCCF:existing PCI 0x%x Func ResourceDump
\n
"
,
ctrl
->
bus
);
}
}
}
...
...
drivers/pci/hotplug/rpadlpar_core.c
View file @
5a7db1eb
...
...
@@ -24,25 +24,6 @@
static
DECLARE_MUTEX
(
rpadlpar_sem
);
static
inline
int
is_hotplug_capable
(
struct
device_node
*
dn
)
{
unsigned
char
*
ptr
=
get_property
(
dn
,
"ibm,fw-pci-hot-plug-ctrl"
,
NULL
);
return
(
int
)
(
ptr
!=
NULL
);
}
static
char
*
get_node_drc_name
(
struct
device_node
*
dn
)
{
char
*
ptr
=
NULL
;
int
*
drc_names
;
drc_names
=
(
int
*
)
get_property
(
dn
,
"ibm,drc-names"
,
NULL
);
if
(
drc_names
)
ptr
=
(
char
*
)
&
drc_names
[
1
];
return
ptr
;
}
static
struct
device_node
*
find_php_slot_vio_node
(
char
*
drc_name
)
{
struct
device_node
*
child
;
...
...
@@ -55,7 +36,7 @@ static struct device_node *find_php_slot_vio_node(char *drc_name)
for
(
child
=
of_get_next_child
(
parent
,
NULL
);
child
;
child
=
of_get_next_child
(
parent
,
child
))
{
loc_code
=
get_property
(
child
,
"ibm,loc-code"
,
NULL
);
if
(
loc_code
&&
!
str
cmp
(
loc_code
,
drc_name
))
if
(
loc_code
&&
!
str
ncmp
(
loc_code
,
drc_name
,
strlen
(
drc_name
)
))
return
child
;
}
...
...
@@ -69,7 +50,7 @@ static struct device_node *find_php_slot_pci_node(char *drc_name)
while
((
np
=
of_find_node_by_type
(
np
,
"pci"
)))
if
(
is_hotplug_capable
(
np
))
{
name
=
get_node
_drc_name
(
np
);
name
=
rpaphp_get
_drc_name
(
np
);
if
(
name
&&
(
!
strcmp
(
drc_name
,
name
)))
break
;
}
...
...
@@ -324,6 +305,7 @@ int dlpar_remove_pci_slot(struct slot *slot, char *drc_name)
}
/* Remove pci bus */
if
(
dlpar_pci_remove_bus
(
bridge_dev
))
{
printk
(
KERN_ERR
"%s: unable to remove pci bus %s
\n
"
,
__FUNCTION__
,
drc_name
);
...
...
drivers/pci/hotplug/rpaphp.h
View file @
5a7db1eb
...
...
@@ -30,6 +30,9 @@
#include <linux/pci.h>
#include "pci_hotplug.h"
#define HOTPLUG 1
#define EMBEDDED 0
#define DR_INDICATOR 9002
#define DR_ENTITY_SENSE 9003
...
...
@@ -73,6 +76,11 @@ extern int debug;
#define CONFIGURED 1
#define EMPTY 0
struct
rpaphp_pci_func
{
struct
pci_dev
*
pci_dev
;
struct
list_head
sibling
;
};
/*
* struct slot - slot information for each *physical* slot
*/
...
...
@@ -83,14 +91,13 @@ struct slot {
u32
power_domain
;
char
*
name
;
char
*
location
;
u8
removable
;
struct
device_node
*
dn
;
/* slot's device_node in OFDT */
/* dn has phb info */
struct
pci_dev
*
bridge
;
/* slot's pci_dev in pci_devices */
union
{
struct
pci_dev
*
pci_dev
;
/* pci_dev of device in this slot */
/* it will be used for unconfig */
/* NULL if slot is empty */
struct
vio_dev
*
vio_dev
;
/* vio_dev of the device in this slot */
struct
list_head
pci_funcs
;
/* pci_devs in PCI slot */
struct
vio_dev
*
vio_dev
;
/* vio_dev in VIO slot */
}
dev
;
u8
dev_type
;
/* VIO or PCI */
struct
hotplug_slot
*
hotplug_slot
;
...
...
@@ -101,6 +108,13 @@ extern struct hotplug_slot_ops rpaphp_hotplug_slot_ops;
extern
struct
list_head
rpaphp_slot_head
;
extern
int
num_slots
;
static
inline
int
is_hotplug_capable
(
struct
device_node
*
dn
)
{
unsigned
char
*
ptr
=
get_property
(
dn
,
"ibm,fw-pci-hot-plug-ctrl"
,
NULL
);
return
(
int
)
(
ptr
!=
NULL
);
}
/* function prototypes */
/* rpaphp_pci.c */
...
...
@@ -110,10 +124,12 @@ extern int rpaphp_enable_pci_slot(struct slot *slot);
extern
int
register_pci_slot
(
struct
slot
*
slot
);
extern
int
rpaphp_unconfig_pci_adapter
(
struct
slot
*
slot
);
extern
int
rpaphp_get_pci_adapter_status
(
struct
slot
*
slot
,
int
is_init
,
u8
*
value
);
extern
struct
hotplug_slot
*
rpaphp_find_hotplug_slot
(
struct
pci_dev
*
dev
);
/* rpaphp_core.c */
extern
int
rpaphp_add_slot
(
struct
device_node
*
dn
);
extern
int
rpaphp_remove_slot
(
struct
slot
*
slot
);
extern
char
*
rpaphp_get_drc_name
(
struct
device_node
*
dn
);
/* rpaphp_vio.c */
extern
int
rpaphp_get_vio_adapter_status
(
struct
slot
*
slot
,
int
is_init
,
u8
*
value
);
...
...
@@ -125,8 +141,8 @@ extern int rpaphp_enable_vio_slot(struct slot *slot);
extern
void
dealloc_slot_struct
(
struct
slot
*
slot
);
extern
struct
slot
*
alloc_slot_struct
(
struct
device_node
*
dn
,
int
drc_index
,
char
*
drc_name
,
int
power_domain
);
extern
int
register_slot
(
struct
slot
*
slot
);
extern
int
deregister_slot
(
struct
slot
*
slot
);
extern
int
rpaphp_get_power_status
(
struct
slot
*
slot
,
u8
*
value
);
extern
int
rpaphp_set_attention_status
(
struct
slot
*
slot
,
u8
status
);
extern
void
rpaphp_sysfs_remove_attr_location
(
struct
hotplug_slot
*
slot
);
#endif
/* _PPC64PHP_H */
drivers/pci/hotplug/rpaphp_core.c
View file @
5a7db1eb
...
...
@@ -54,6 +54,8 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
void
eeh_register_disable_func
(
int
(
*
)(
struct
pci_dev
*
));
module_param
(
debug
,
bool
,
0644
);
static
int
enable_slot
(
struct
hotplug_slot
*
slot
);
...
...
@@ -63,6 +65,7 @@ static int get_power_status(struct hotplug_slot *slot, u8 * value);
static
int
get_attention_status
(
struct
hotplug_slot
*
slot
,
u8
*
value
);
static
int
get_adapter_status
(
struct
hotplug_slot
*
slot
,
u8
*
value
);
static
int
get_max_bus_speed
(
struct
hotplug_slot
*
hotplug_slot
,
enum
pci_bus_speed
*
value
);
static
int
rpaphp_disable_slot
(
struct
pci_dev
*
dev
);
struct
hotplug_slot_ops
rpaphp_hotplug_slot_ops
=
{
.
owner
=
THIS_MODULE
,
...
...
@@ -89,7 +92,7 @@ static int rpaphp_get_attention_status(struct slot *slot)
*/
static
int
set_attention_status
(
struct
hotplug_slot
*
hotplug_slot
,
u8
value
)
{
int
retval
;
int
retval
=
0
;
struct
slot
*
slot
=
(
struct
slot
*
)
hotplug_slot
->
private
;
down
(
&
rpaphp_sem
);
...
...
@@ -208,47 +211,53 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
int
rpaphp_remove_slot
(
struct
slot
*
slot
)
{
int
retval
=
0
;
struct
hotplug_slot
*
php_slot
=
slot
->
hotplug_slot
;
return
deregister_slot
(
slot
)
;
}
list_del
(
&
slot
->
rpaphp_slot_list
);
static
int
get_dn_properties
(
struct
device_node
*
dn
,
int
**
indexes
,
int
**
names
,
int
**
types
,
int
**
power_domains
)
{
*
indexes
=
(
int
*
)
get_property
(
dn
,
"ibm,drc-indexes"
,
NULL
);
/* &names[1] contains NULL terminated slot names */
*
names
=
(
int
*
)
get_property
(
dn
,
"ibm,drc-names"
,
NULL
);
/*
remove "php_location" file
*/
rpaphp_sysfs_remove_attr_location
(
php_slot
);
/*
&types[1] contains NULL terminated slot types
*/
*
types
=
(
int
*
)
get_property
(
dn
,
"ibm,drc-types"
,
NULL
);
retval
=
pci_hp_deregister
(
php_slot
);
if
(
retval
)
err
(
"Problem unregistering a slot %s
\n
"
,
slot
->
name
);
/* power_domains[1...n] are the slot power domains */
*
power_domains
=
(
int
*
)
get_property
(
dn
,
"ibm,drc-power-domains"
,
NULL
);
num_slots
--
;
if
(
*
indexes
&&
*
names
&&
*
types
&&
*
power_domains
)
return
(
1
);
dbg
(
"%s - Exit: rc[%d]
\n
"
,
__FUNCTION__
,
retval
);
return
retval
;
return
(
0
);
}
static
int
is_php_dn
(
struct
device_node
*
dn
,
int
**
indexes
,
int
**
names
,
int
**
types
,
int
**
power_domains
)
{
*
indexes
=
(
int
*
)
get_property
(
dn
,
"ibm,drc-indexes"
,
NULL
);
if
(
!*
indexes
)
return
0
;
/* &names[1] contains NULL terminated slot names */
*
names
=
(
int
*
)
get_property
(
dn
,
"ibm,drc-names"
,
NULL
);
if
(
!*
names
)
return
0
;
/* &types[1] contains NULL terminated slot types */
*
types
=
(
int
*
)
get_property
(
dn
,
"ibm,drc-types"
,
NULL
);
if
(
!*
types
)
return
0
;
/* power_domains[1...n] are the slot power domains */
*
power_domains
=
(
int
*
)
get_property
(
dn
,
"ibm,drc-power-domains"
,
NULL
);
if
(
!*
power_domains
)
return
0
;
if
(
strcmp
(
dn
->
name
,
"pci"
)
==
0
&&
!
get_property
(
dn
,
"ibm,fw-pci-hot-plug-ctrl"
,
NULL
))
return
0
;
return
1
;
if
(
!
is_hotplug_capable
(
dn
))
return
(
0
);
if
(
!
get_dn_properties
(
dn
,
indexes
,
names
,
types
,
power_domains
))
return
(
0
);
return
(
1
);
}
static
int
is_dr_dn
(
struct
device_node
*
dn
,
int
**
indexes
,
int
**
names
,
int
**
types
,
int
**
power_domains
,
int
**
my_drc_index
)
{
if
(
!
is_hotplug_capable
(
dn
))
return
(
0
);
*
my_drc_index
=
(
int
*
)
get_property
(
dn
,
"ibm,my-drc-index"
,
NULL
);
if
(
!*
my_drc_index
)
return
(
0
);
if
(
!
dn
->
parent
)
return
(
0
);
return
get_dn_properties
(
dn
->
parent
,
indexes
,
names
,
types
,
power_domains
);
}
static
inline
int
is_vdevice_root
(
struct
device_node
*
dn
)
...
...
@@ -256,15 +265,48 @@ static inline int is_vdevice_root(struct device_node *dn)
return
!
strcmp
(
dn
->
name
,
"vdevice"
);
}
/**
* rpaphp_add_slot: Add Hot Plug slot(s) to sysfs
*
*/
char
*
rpaphp_get_drc_name
(
struct
device_node
*
dn
)
{
char
*
name
,
*
ptr
=
NULL
;
int
*
drc_names
,
*
drc_indexes
,
i
;
struct
device_node
*
parent
=
dn
->
parent
;
u32
*
my_drc_index
;
if
(
!
parent
)
return
NULL
;
my_drc_index
=
(
u32
*
)
get_property
(
dn
,
"ibm,my-drc-index"
,
NULL
);
if
(
!
my_drc_index
)
return
NULL
;
drc_names
=
(
int
*
)
get_property
(
parent
,
"ibm,drc-names"
,
NULL
);
drc_indexes
=
(
int
*
)
get_property
(
parent
,
"ibm,drc-indexes"
,
NULL
);
if
(
!
drc_names
||
!
drc_indexes
)
return
NULL
;
name
=
(
char
*
)
&
drc_names
[
1
];
for
(
i
=
0
;
i
<
drc_indexes
[
0
];
i
++
,
name
+=
(
strlen
(
name
)
+
1
))
{
if
(
drc_indexes
[
i
+
1
]
==
*
my_drc_index
)
{
ptr
=
(
char
*
)
name
;
break
;
}
}
return
ptr
;
}
/****************************************************************
* rpaphp not only registers PCI hotplug slots(HOTPLUG),
* but also logical DR slots(EMBEDDED).
* HOTPLUG slot: An adapter can be physically added/removed.
* EMBEDDED slot: An adapter can be logically removed/added
* from/to a partition with the slot.
***************************************************************/
int
rpaphp_add_slot
(
struct
device_node
*
dn
)
{
struct
slot
*
slot
;
int
retval
=
0
;
int
i
;
int
i
,
*
my_drc_index
,
slot_type
;
int
*
indexes
,
*
names
,
*
types
,
*
power_domains
;
char
*
name
,
*
type
;
...
...
@@ -277,42 +319,65 @@ int rpaphp_add_slot(struct device_node *dn)
}
/* register PCI devices */
if
(
dn
->
name
!=
0
&&
strcmp
(
dn
->
name
,
"pci"
)
==
0
&&
is_php_dn
(
dn
,
&
indexes
,
&
names
,
&
types
,
&
power_domains
))
{
if
(
dn
->
name
!=
0
&&
strcmp
(
dn
->
name
,
"pci"
)
==
0
)
{
if
(
is_php_dn
(
dn
,
&
indexes
,
&
names
,
&
types
,
&
power_domains
))
slot_type
=
HOTPLUG
;
else
if
(
is_dr_dn
(
dn
,
&
indexes
,
&
names
,
&
types
,
&
power_domains
,
&
my_drc_index
))
slot_type
=
EMBEDDED
;
else
goto
exit
;
name
=
(
char
*
)
&
names
[
1
];
type
=
(
char
*
)
&
types
[
1
];
for
(
i
=
0
;
i
<
indexes
[
0
];
i
++
,
name
+=
(
strlen
(
name
)
+
1
),
type
+=
(
strlen
(
type
)
+
1
))
{
for
(
i
=
0
;
i
<
indexes
[
0
];
i
++
,
name
+=
(
strlen
(
name
)
+
1
),
type
+=
(
strlen
(
type
)
+
1
))
{
if
(
slot_type
==
HOTPLUG
||
(
slot_type
==
EMBEDDED
&&
indexes
[
i
+
1
]
==
my_drc_index
[
0
]))
{
if
(
!
(
slot
=
alloc_slot_struct
(
dn
,
indexes
[
i
+
1
],
name
,
power_domains
[
i
+
1
])))
{
retval
=
-
ENOMEM
;
goto
exit
;
}
if
(
slot_type
==
EMBEDDED
)
slot
->
type
=
EMBEDDED
;
else
slot
->
type
=
simple_strtoul
(
type
,
NULL
,
10
);
if
(
slot
->
type
<
1
||
slot
->
type
>
16
)
slot
->
type
=
0
;
retval
=
register_pci_slot
(
slot
);
}
/* for indexes */
}
/* end of PCI device_node */
dbg
(
" Found drc-index:0x%x drc-name:%s drc-type:%s
\n
"
,
indexes
[
i
+
1
],
name
,
type
);
retval
=
register_pci_slot
(
slot
);
if
(
slot_type
==
EMBEDDED
)
goto
exit
;
}
}
}
exit:
dbg
(
"%s - Exit: num_slots=%d rc[%d]
\n
"
,
__FUNCTION__
,
num_slots
,
retval
);
return
retval
;
}
static
int
__init
init_rpa
(
void
)
/*
* init_slots - initialize 'struct slot' structures for each slot
*
*/
static
void
init_slots
(
void
)
{
struct
device_node
*
dn
;
for
(
dn
=
find_all_nodes
();
dn
;
dn
=
dn
->
next
)
rpaphp_add_slot
(
dn
);
}
static
int
__init
init_rpa
(
void
)
{
init_MUTEX
(
&
rpaphp_sem
);
/* initialize internal data structure etc. */
for
(
dn
=
find_all_nodes
();
dn
;
dn
=
dn
->
next
)
rpaphp_add_slot
(
dn
);
init_slots
();
if
(
!
num_slots
)
return
-
ENODEV
;
...
...
@@ -342,12 +407,18 @@ static int __init rpaphp_init(void)
{
info
(
DRIVER_DESC
" version: "
DRIVER_VERSION
"
\n
"
);
/* let EEH know they can use hotplug */
eeh_register_disable_func
(
&
rpaphp_disable_slot
);
/* read all the PRA info from the system */
return
init_rpa
();
}
static
void
__exit
rpaphp_exit
(
void
)
{
/* let EEH know we are going away */
eeh_register_disable_func
(
NULL
);
cleanup_slots
();
}
...
...
@@ -374,11 +445,16 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
retval
=
-
EINVAL
;
}
up
(
&
rpaphp_sem
);
exit:
exit:
dbg
(
"%s - Exit: rc[%d]
\n
"
,
__FUNCTION__
,
retval
);
return
retval
;
}
static
int
rpaphp_disable_slot
(
struct
pci_dev
*
dev
)
{
return
disable_slot
(
rpaphp_find_hotplug_slot
(
dev
));
}
static
int
disable_slot
(
struct
hotplug_slot
*
hotplug_slot
)
{
int
retval
;
...
...
@@ -395,9 +471,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
down
(
&
rpaphp_sem
);
switch
(
slot
->
dev_type
)
{
case
PCI_DEV
:
rpaphp_set_attention_status
(
slot
,
LED_ID
);
retval
=
rpaphp_unconfig_pci_adapter
(
slot
);
rpaphp_set_attention_status
(
slot
,
LED_OFF
);
break
;
case
VIO_DEV
:
retval
=
rpaphp_unconfig_vio_adapter
(
slot
);
...
...
@@ -406,7 +480,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
retval
=
-
ENODEV
;
}
up
(
&
rpaphp_sem
);
exit:
exit:
dbg
(
"%s - Exit: rc[%d]
\n
"
,
__FUNCTION__
,
retval
);
return
retval
;
}
...
...
@@ -417,3 +491,4 @@ module_exit(rpaphp_exit);
EXPORT_SYMBOL_GPL
(
rpaphp_add_slot
);
EXPORT_SYMBOL_GPL
(
rpaphp_remove_slot
);
EXPORT_SYMBOL_GPL
(
rpaphp_slot_head
);
EXPORT_SYMBOL_GPL
(
rpaphp_get_drc_name
);
drivers/pci/hotplug/rpaphp_pci.c
View file @
5a7db1eb
...
...
@@ -30,24 +30,18 @@
struct
pci_dev
*
rpaphp_find_pci_dev
(
struct
device_node
*
dn
)
{
struct
pci_dev
*
retval_dev
=
NULL
,
*
dev
;
struct
pci_dev
*
retval_dev
=
NULL
,
*
dev
=
NULL
;
char
bus_id
[
BUS_ID_SIZE
];
sprintf
(
bus_id
,
"%04x:%02x:%02x.%d"
,
dn
->
phb
->
global_number
,
dn
->
busno
,
PCI_SLOT
(
dn
->
devfn
),
PCI_FUNC
(
dn
->
devfn
));
dbg
(
"Enter rpaphp_find_pci_dev() full_name=%s bus_id=%s
\n
"
,
dn
->
full_name
,
bus_id
);
while
((
dev
=
pci_find_device
(
PCI_ANY_ID
,
PCI_ANY_ID
,
dev
))
!=
NULL
)
{
if
(
!
strcmp
(
pci_name
(
dev
),
bus_id
))
{
retval_dev
=
dev
;
dbg
(
"rpaphp_find_pci_dev(): found dev=%p
\n\n
"
,
dev
);
break
;
}
}
return
retval_dev
;
}
EXPORT_SYMBOL_GPL
(
rpaphp_find_pci_dev
);
...
...
@@ -79,11 +73,6 @@ static struct pci_dev *rpaphp_find_bridge_pdev(struct slot *slot)
return
rpaphp_find_pci_dev
(
slot
->
dn
);
}
static
struct
pci_dev
*
rpaphp_find_adapter_pdev
(
struct
slot
*
slot
)
{
return
rpaphp_find_pci_dev
(
slot
->
dn
->
child
);
}
static
int
rpaphp_get_sensor_state
(
struct
slot
*
slot
,
int
*
state
)
{
int
rc
;
...
...
@@ -144,7 +133,8 @@ int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value)
else
if
(
rpaphp_find_pci_dev
(
slot
->
dn
->
child
))
*
value
=
CONFIGURED
;
else
{
dbg
(
"%s: can't find pdev of adapter in slot[%s]
\n
"
,
__FUNCTION__
,
slot
->
name
);
err
(
"%s: can't find pdev of adapter in slot[%s]
\n
"
,
__FUNCTION__
,
slot
->
dn
->
full_name
);
*
value
=
NOT_CONFIGURED
;
}
}
...
...
@@ -158,7 +148,8 @@ int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value)
}
/* Must be called before pci_bus_add_devices */
static
void
rpaphp_fixup_new_pci_devices
(
struct
pci_bus
*
bus
)
static
void
rpaphp_fixup_new_pci_devices
(
struct
pci_bus
*
bus
,
int
fix_bus
)
{
struct
pci_dev
*
dev
;
...
...
@@ -170,6 +161,7 @@ static void rpaphp_fixup_new_pci_devices(struct pci_bus *bus)
if
(
list_empty
(
&
dev
->
global_list
))
{
int
i
;
if
(
fix_bus
)
pcibios_fixup_device_resources
(
dev
,
bus
);
pci_read_irq_line
(
dev
);
for
(
i
=
0
;
i
<
PCI_NUM_RESOURCES
;
i
++
)
{
...
...
@@ -183,69 +175,139 @@ static void rpaphp_fixup_new_pci_devices(struct pci_bus *bus)
}
}
static
void
rpaphp_pci_config_device
(
struct
pci_bus
*
pci_bus
,
struct
device_node
*
dn
)
{
int
num
;
num
=
pci_scan_slot
(
pci_bus
,
PCI_DEVFN
(
PCI_SLOT
(
dn
->
devfn
),
0
));
if
(
num
)
{
rpaphp_fixup_new_pci_devices
(
pci_bus
);
pci_bus_add_devices
(
pci_bus
);
}
}
static
int
rpaphp_pci_config_bridge
(
struct
pci_dev
*
dev
,
struct
device_node
*
dn
);
static
int
rpaphp_pci_config_bridge
(
struct
pci_dev
*
dev
);
/*****************************************************************************
rpaphp_pci_config_
dn() will recursively
configure all devices under the
given slot->dn and return the
dn's
pci_dev.
rpaphp_pci_config_
slot() will
configure all devices under the
given slot->dn and return the
the first
pci_dev.
*****************************************************************************/
static
struct
pci_dev
*
rpaphp_pci_config_
dn
(
struct
device_node
*
dn
,
struct
pci_bus
*
bus
)
rpaphp_pci_config_
slot
(
struct
device_node
*
dn
,
struct
pci_bus
*
bus
)
{
struct
device_node
*
local
;
struct
device_node
*
eads_first_child
=
dn
->
child
;
struct
pci_dev
*
dev
;
int
num
;
dbg
(
"Enter %s: dn=%s bus=%s
\n
"
,
__FUNCTION__
,
dn
->
full_name
,
bus
->
name
);
for
(
local
=
dn
->
child
;
local
;
local
=
local
->
sibling
)
{
rpaphp_pci_config_device
(
bus
,
local
);
dev
=
rpaphp_find_pci_dev
(
local
);
if
(
!
rpaphp_pci_config_bridge
(
dev
,
local
))
if
(
eads_first_child
)
{
/* pci_scan_slot should find all children of EADs */
num
=
pci_scan_slot
(
bus
,
PCI_DEVFN
(
PCI_SLOT
(
eads_first_child
->
devfn
),
0
));
if
(
num
)
{
rpaphp_fixup_new_pci_devices
(
bus
,
1
);
pci_bus_add_devices
(
bus
);
}
dev
=
rpaphp_find_pci_dev
(
eads_first_child
);
if
(
!
dev
)
{
err
(
"No new device found
\n
"
);
return
NULL
;
}
if
(
dev
->
hdr_type
==
PCI_HEADER_TYPE_BRIDGE
)
rpaphp_pci_config_bridge
(
dev
);
}
return
dev
;
}
static
int
rpaphp_pci_config_bridge
(
struct
pci_dev
*
dev
,
struct
device_node
*
dn
)
static
int
rpaphp_pci_config_bridge
(
struct
pci_dev
*
dev
)
{
if
(
dev
&&
dn
->
child
)
{
/* dn is a PCI bridge node */
struct
pci_bus
*
child
;
u8
sec_busno
;
struct
pci_bus
*
child_bus
;
struct
pci_dev
*
child_dev
;
dbg
(
"Enter %s: BRIDGE dev=%s
\n
"
,
__FUNCTION__
,
pci_name
(
dev
));
/* get busno of downstream bus */
pci_read_config_byte
(
dev
,
PCI_SECONDARY_BUS
,
&
sec_busno
);
/* add to children of PCI bridge dev->bus */
child
=
pci_add_new_bus
(
dev
->
bus
,
dev
,
sec_busno
);
if
(
!
child
)
{
child_bus
=
pci_add_new_bus
(
dev
->
bus
,
dev
,
sec_busno
);
if
(
!
child_bus
)
{
err
(
"%s: could not add second bus
\n
"
,
__FUNCTION__
);
return
-
EIO
;
}
sprintf
(
child_bus
->
name
,
"PCI Bus #%02x"
,
child_bus
->
number
);
/* do pci_scan_child_bus */
pci_scan_child_bus
(
child_bus
);
list_for_each_entry
(
child_dev
,
&
child_bus
->
devices
,
bus_list
)
{
eeh_add_device_late
(
child_dev
);
}
/* fixup new pci devices without touching bus struct */
rpaphp_fixup_new_pci_devices
(
child_bus
,
0
);
/* Make the discovered devices available */
pci_bus_add_devices
(
child_bus
);
return
0
;
}
static
void
enable_eeh
(
struct
device_node
*
dn
)
{
struct
device_node
*
sib
;
for
(
sib
=
dn
->
child
;
sib
;
sib
=
sib
->
sibling
)
enable_eeh
(
sib
);
eeh_add_device_early
(
dn
);
return
;
}
#ifdef DEBUG
static
void
print_slot_pci_funcs
(
struct
slot
*
slot
)
{
struct
list_head
*
l
;
if
(
slot
->
dev_type
==
PCI_DEV
)
{
printk
(
"pci_funcs of slot[%s]
\n
"
,
slot
->
name
);
if
(
list_empty
(
&
slot
->
dev
.
pci_funcs
))
printk
(
" pci_funcs is EMPTY
\n
"
);
list_for_each
(
l
,
&
slot
->
dev
.
pci_funcs
)
{
struct
rpaphp_pci_func
*
func
=
list_entry
(
l
,
struct
rpaphp_pci_func
,
sibling
);
printk
(
" FOUND dev=%s
\n
"
,
pci_name
(
func
->
pci_dev
));
}
}
sprintf
(
child
->
name
,
"PCI Bus #%02x"
,
child
->
number
);
/* Fixup subordinate bridge bases and resureces */
pcibios_fixup_bus
(
child
);
return
;
}
#else
static
void
print_slot_pci_funcs
(
struct
slot
*
slot
)
{
return
;
}
#endif
/* may need do more stuff here */
rpaphp_pci_config_dn
(
dn
,
dev
->
subordinate
);
static
int
init_slot_pci_funcs
(
struct
slot
*
slot
)
{
struct
device_node
*
child
;
for
(
child
=
slot
->
dn
->
child
;
child
!=
NULL
;
child
=
child
->
sibling
)
{
struct
pci_dev
*
pdev
=
rpaphp_find_pci_dev
(
child
);
if
(
pdev
)
{
struct
rpaphp_pci_func
*
func
;
func
=
kmalloc
(
sizeof
(
struct
rpaphp_pci_func
),
GFP_KERNEL
);
if
(
!
func
)
return
-
ENOMEM
;
memset
(
func
,
0
,
sizeof
(
struct
rpaphp_pci_func
));
INIT_LIST_HEAD
(
&
func
->
sibling
);
func
->
pci_dev
=
pdev
;
list_add_tail
(
&
func
->
sibling
,
&
slot
->
dev
.
pci_funcs
);
print_slot_pci_funcs
(
slot
);
}
else
{
err
(
"%s: dn=%s has no pci_dev
\n
"
,
__FUNCTION__
,
child
->
full_name
);
return
-
EIO
;
}
return
1
;
}
return
0
;
}
static
struct
pci_dev
*
rpaphp_config_pci_adapter
(
struct
slot
*
slot
)
static
int
rpaphp_config_pci_adapter
(
struct
slot
*
slot
)
{
struct
pci_bus
*
pci_bus
;
struct
pci_dev
*
dev
=
NULL
;
struct
pci_dev
*
dev
;
int
rc
=
-
ENODEV
;
dbg
(
"Entry %s: slot[%s]
\n
"
,
__FUNCTION__
,
slot
->
name
);
...
...
@@ -256,38 +318,74 @@ static struct pci_dev *rpaphp_config_pci_adapter(struct slot *slot)
err
(
"%s: can't find bus structure
\n
"
,
__FUNCTION__
);
goto
exit
;
}
eeh_add_device_early
(
slot
->
dn
->
child
);
dev
=
rpaphp_pci_config_dn
(
slot
->
dn
,
pci_bus
);
eeh_add_device_late
(
dev
);
enable_eeh
(
slot
->
dn
);
dev
=
rpaphp_pci_config_slot
(
slot
->
dn
,
pci_bus
);
if
(
!
dev
)
{
err
(
"%s: can't find any devices.
\n
"
,
__FUNCTION__
);
goto
exit
;
}
/* associate corresponding pci_dev */
rc
=
init_slot_pci_funcs
(
slot
);
if
(
rc
)
goto
exit
;
print_slot_pci_funcs
(
slot
);
if
(
!
list_empty
(
&
slot
->
dev
.
pci_funcs
))
rc
=
0
;
}
else
{
/* slot is not enabled */
err
(
"slot doesn't have pci_dev structure
\n
"
);
dev
=
NULL
;
}
exit:
dbg
(
"Exit %s: pci_dev %s
\n
"
,
__FUNCTION__
,
dev
?
"found"
:
"not found"
);
return
dev
;
dbg
(
"Exit %s: rc=%d
\n
"
,
__FUNCTION__
,
rc
);
return
rc
;
}
static
void
rpaphp_eeh_remove_bus_device
(
struct
pci_dev
*
dev
)
{
eeh_remove_device
(
dev
);
if
(
dev
->
hdr_type
==
PCI_HEADER_TYPE_BRIDGE
)
{
struct
pci_bus
*
bus
=
dev
->
subordinate
;
struct
list_head
*
ln
;
if
(
!
bus
)
return
;
for
(
ln
=
bus
->
devices
.
next
;
ln
!=
&
bus
->
devices
;
ln
=
ln
->
next
)
{
struct
pci_dev
*
pdev
=
pci_dev_b
(
ln
);
if
(
pdev
)
rpaphp_eeh_remove_bus_device
(
pdev
);
}
}
return
;
}
int
rpaphp_unconfig_pci_adapter
(
struct
slot
*
slot
)
{
int
retval
=
0
;
struct
list_head
*
ln
;
dbg
(
"Entry %s: slot[%s]
\n
"
,
__FUNCTION__
,
slot
->
name
);
if
(
!
slot
->
dev
.
pci_dev
)
{
info
(
"%s: no card in slot[%s]
\n
"
,
__FUNCTION__
,
slot
->
name
);
if
(
list_empty
(
&
slot
->
dev
.
pci_funcs
))
{
err
(
"%s: slot[%s] doesn't have any devices.
\n
"
,
__FUNCTION__
,
slot
->
name
);
retval
=
-
EINVAL
;
goto
exit
;
}
/* remove the device from the pci core */
eeh_remove_device
(
slot
->
dev
.
pci_dev
);
pci_remove_bus_device
(
slot
->
dev
.
pci_dev
);
/* remove the devices from the pci core */
list_for_each
(
ln
,
&
slot
->
dev
.
pci_funcs
)
{
struct
rpaphp_pci_func
*
func
;
func
=
list_entry
(
ln
,
struct
rpaphp_pci_func
,
sibling
);
if
(
func
->
pci_dev
)
{
rpaphp_eeh_remove_bus_device
(
func
->
pci_dev
);
pci_remove_bus_device
(
func
->
pci_dev
);
}
kfree
(
func
);
}
INIT_LIST_HEAD
(
&
slot
->
dev
.
pci_funcs
);
slot
->
state
=
NOT_CONFIGURED
;
info
(
"%s:
adapter
in slot[%s] unconfigured.
\n
"
,
__FUNCTION__
,
info
(
"%s:
devices
in slot[%s] unconfigured.
\n
"
,
__FUNCTION__
,
slot
->
name
);
exit:
dbg
(
"Exit %s, rc=0x%x
\n
"
,
__FUNCTION__
,
retval
);
...
...
@@ -303,7 +401,7 @@ static int setup_pci_hotplug_slot_info(struct slot *slot)
&
slot
->
hotplug_slot
->
info
->
adapter_status
);
if
(
slot
->
hotplug_slot
->
info
->
adapter_status
==
NOT_VALID
)
{
dbg
(
"%s: NOT_VALID: skip dn->full_name=%s
\n
"
,
err
(
"%s: NOT_VALID: skip dn->full_name=%s
\n
"
,
__FUNCTION__
,
slot
->
dn
->
full_name
);
return
-
1
;
}
...
...
@@ -314,26 +412,29 @@ static int setup_pci_slot(struct slot *slot)
{
slot
->
bridge
=
rpaphp_find_bridge_pdev
(
slot
);
if
(
!
slot
->
bridge
)
{
/* slot being added doesn't have pci_dev yet */
dbg
(
"%s: no pci_dev for bridge dn %s
\n
"
,
__FUNCTION__
,
slot
->
name
);
dealloc_slot_struct
(
slot
);
return
1
;
err
(
"%s: no pci_dev for bridge dn %s
\n
"
,
__FUNCTION__
,
slot
->
name
);
goto
exit_rc
;
}
dbg
(
"%s set slot->name to %s
\n
"
,
__FUNCTION__
,
pci_name
(
slot
->
bridge
));
strcpy
(
slot
->
name
,
pci_name
(
slot
->
bridge
));
/* find slot's pci_dev if it's not empty */
if
(
slot
->
hotplug_slot
->
info
->
adapter_status
==
EMPTY
)
{
slot
->
state
=
EMPTY
;
/* slot is empty */
slot
->
dev
.
pci_dev
=
NULL
;
}
else
{
/* slot is occupied */
if
(
!
(
slot
->
dn
->
child
))
{
/* non-empty slot has to have child */
err
(
"%s: slot[%s]'s device_node doesn't have child for adapter
\n
"
,
__FUNCTION__
,
slot
->
name
);
dealloc_slot_struct
(
slot
);
return
1
;
err
(
"%s: slot[%s]'s device_node doesn't have child for adapter
\n
"
,
__FUNCTION__
,
slot
->
name
);
goto
exit_rc
;
}
if
(
init_slot_pci_funcs
(
slot
))
{
err
(
"%s: init_slot_pci_funcs failed
\n
"
,
__FUNCTION__
);
goto
exit_rc
;
}
slot
->
dev
.
pci_dev
=
rpaphp_find_adapter_pdev
(
slot
);
if
(
slot
->
dev
.
pci_dev
)
{
print_slot_pci_funcs
(
slot
);
if
(
!
list_empty
(
&
slot
->
dev
.
pci_funcs
)
)
{
slot
->
state
=
CONFIGURED
;
}
else
{
...
...
@@ -343,6 +444,9 @@ static int setup_pci_slot(struct slot *slot)
}
}
return
0
;
exit_rc:
dealloc_slot_struct
(
slot
);
return
1
;
}
int
register_pci_slot
(
struct
slot
*
slot
)
...
...
@@ -350,14 +454,17 @@ int register_pci_slot(struct slot *slot)
int
rc
=
1
;
slot
->
dev_type
=
PCI_DEV
;
if
(
slot
->
type
==
EMBEDDED
)
slot
->
removable
=
EMBEDDED
;
else
slot
->
removable
=
HOTPLUG
;
INIT_LIST_HEAD
(
&
slot
->
dev
.
pci_funcs
);
if
(
setup_pci_hotplug_slot_info
(
slot
))
goto
exit_rc
;
if
(
setup_pci_slot
(
slot
))
goto
exit_rc
;
rc
=
register_slot
(
slot
);
exit_rc:
if
(
rc
)
dealloc_slot_struct
(
slot
);
return
rc
;
}
...
...
@@ -371,12 +478,12 @@ int rpaphp_enable_pci_slot(struct slot *slot)
dbg
(
"%s: sensor state[%d]
\n
"
,
__FUNCTION__
,
state
);
/* if slot is not empty, enable the adapter */
if
(
state
==
PRESENT
)
{
dbg
(
"%s : slot[%s] is occupid.
\n
"
,
__FUNCTION__
,
slot
->
name
);
if
((
slot
->
dev
.
pci_dev
=
rpaphp_config_pci_adapter
(
slot
))
!=
NULL
)
{
dbg
(
"%s : slot[%s] is occupi
e
d.
\n
"
,
__FUNCTION__
,
slot
->
name
);
retval
=
rpaphp_config_pci_adapter
(
slot
);
if
(
!
retval
)
{
slot
->
state
=
CONFIGURED
;
dbg
(
"%s: PCI
adapter %
s in slot[%s] has been configured
\n
"
,
__FUNCTION__
,
pci_name
(
slot
->
dev
.
pci_dev
),
slot
->
name
);
dbg
(
"%s: PCI
device
s in slot[%s] has been configured
\n
"
,
__FUNCTION__
,
slot
->
name
);
}
else
{
slot
->
state
=
NOT_CONFIGURED
;
dbg
(
"%s: no pci_dev struct for adapter in slot[%s]
\n
"
,
...
...
@@ -392,10 +499,31 @@ int rpaphp_enable_pci_slot(struct slot *slot)
retval
=
-
EINVAL
;
}
exit:
if
(
slot
->
state
!=
NOT_VALID
)
rpaphp_set_attention_status
(
slot
,
LED_ON
);
else
rpaphp_set_attention_status
(
slot
,
LED_ID
);
dbg
(
"%s - Exit: rc[%d]
\n
"
,
__FUNCTION__
,
retval
);
return
retval
;
}
struct
hotplug_slot
*
rpaphp_find_hotplug_slot
(
struct
pci_dev
*
dev
)
{
struct
list_head
*
tmp
,
*
n
;
struct
slot
*
slot
;
list_for_each_safe
(
tmp
,
n
,
&
rpaphp_slot_head
)
{
struct
pci_bus
*
bus
;
struct
list_head
*
ln
;
slot
=
list_entry
(
tmp
,
struct
slot
,
rpaphp_slot_list
);
bus
=
slot
->
bridge
->
subordinate
;
if
(
!
bus
)
return
NULL
;
/* shouldn't be here */
for
(
ln
=
bus
->
devices
.
next
;
ln
!=
&
bus
->
devices
;
ln
=
ln
->
next
)
{
struct
pci_dev
*
pdev
=
pci_dev_b
(
ln
);
if
(
pdev
==
dev
)
return
slot
->
hotplug_slot
;
}
}
return
NULL
;
}
EXPORT_SYMBOL_GPL
(
rpaphp_find_hotplug_slot
);
drivers/pci/hotplug/rpaphp_slot.c
View file @
5a7db1eb
...
...
@@ -29,6 +29,35 @@
#include <linux/pci.h>
#include "rpaphp.h"
static
ssize_t
removable_read_file
(
struct
hotplug_slot
*
php_slot
,
char
*
buf
)
{
u8
value
;
int
retval
=
-
ENOENT
;
struct
slot
*
slot
=
(
struct
slot
*
)
php_slot
->
private
;
if
(
!
slot
)
return
retval
;
value
=
slot
->
removable
;
retval
=
sprintf
(
buf
,
"%d
\n
"
,
value
);
return
retval
;
}
static
struct
hotplug_slot_attribute
hotplug_slot_attr_removable
=
{
.
attr
=
{.
name
=
"phy_removable"
,
.
mode
=
S_IFREG
|
S_IRUGO
},
.
show
=
removable_read_file
,
};
static
void
rpaphp_sysfs_add_attr_removable
(
struct
hotplug_slot
*
slot
)
{
sysfs_create_file
(
&
slot
->
kobj
,
&
hotplug_slot_attr_removable
.
attr
);
}
static
void
rpaphp_sysfs_remove_attr_removable
(
struct
hotplug_slot
*
slot
)
{
sysfs_remove_file
(
&
slot
->
kobj
,
&
hotplug_slot_attr_removable
.
attr
);
}
static
ssize_t
location_read_file
(
struct
hotplug_slot
*
php_slot
,
char
*
buf
)
{
char
*
value
;
...
...
@@ -53,7 +82,7 @@ static void rpaphp_sysfs_add_attr_location (struct hotplug_slot *slot)
sysfs_create_file
(
&
slot
->
kobj
,
&
hotplug_slot_attr_location
.
attr
);
}
void
rpaphp_sysfs_remove_attr_location
(
struct
hotplug_slot
*
slot
)
static
void
rpaphp_sysfs_remove_attr_location
(
struct
hotplug_slot
*
slot
)
{
sysfs_remove_file
(
&
slot
->
kobj
,
&
hotplug_slot_attr_location
.
attr
);
}
...
...
@@ -68,6 +97,17 @@ static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot)
void
dealloc_slot_struct
(
struct
slot
*
slot
)
{
struct
list_head
*
ln
,
*
n
;
if
(
slot
->
dev_type
==
PCI_DEV
)
{
list_for_each_safe
(
ln
,
n
,
&
slot
->
dev
.
pci_funcs
)
{
struct
rpaphp_pci_func
*
func
;
func
=
list_entry
(
ln
,
struct
rpaphp_pci_func
,
sibling
);
kfree
(
func
);
}
}
kfree
(
slot
->
hotplug_slot
->
info
);
kfree
(
slot
->
hotplug_slot
->
name
);
kfree
(
slot
->
hotplug_slot
);
...
...
@@ -107,9 +147,8 @@ struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_
slot
->
hotplug_slot
->
private
=
slot
;
slot
->
hotplug_slot
->
ops
=
&
rpaphp_hotplug_slot_ops
;
slot
->
hotplug_slot
->
release
=
&
rpaphp_release_slot
;
slot
->
hotplug_slot
->
info
->
cur_bus_speed
=
PCI_SPEED_UNKNOWN
;
return
slot
;
return
(
slot
)
;
error_name:
kfree
(
slot
->
hotplug_slot
->
name
);
...
...
@@ -123,15 +162,56 @@ struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_
return
NULL
;
}
static
int
is_registered
(
struct
slot
*
slot
)
{
struct
slot
*
tmp_slot
;
list_for_each_entry
(
tmp_slot
,
&
rpaphp_slot_head
,
rpaphp_slot_list
)
{
if
(
!
strcmp
(
tmp_slot
->
name
,
slot
->
name
))
return
1
;
}
return
0
;
}
int
deregister_slot
(
struct
slot
*
slot
)
{
int
retval
=
0
;
struct
hotplug_slot
*
php_slot
=
slot
->
hotplug_slot
;
dbg
(
"%s - Entry: deregistering slot=%s
\n
"
,
__FUNCTION__
,
slot
->
name
);
list_del
(
&
slot
->
rpaphp_slot_list
);
/* remove "phy_location" file */
rpaphp_sysfs_remove_attr_location
(
php_slot
);
/* remove "phy_removable" file */
rpaphp_sysfs_remove_attr_removable
(
php_slot
);
retval
=
pci_hp_deregister
(
php_slot
);
if
(
retval
)
err
(
"Problem unregistering a slot %s
\n
"
,
slot
->
name
);
else
num_slots
--
;
dbg
(
"%s - Exit: rc[%d]
\n
"
,
__FUNCTION__
,
retval
);
return
retval
;
}
int
register_slot
(
struct
slot
*
slot
)
{
int
retval
;
char
*
vio_uni_addr
=
NULL
;
dbg
(
"%s registering slot:path[%s] index[%x], name[%s] pdomain[%x] type[%d]
\n
"
,
__FUNCTION__
,
slot
->
dn
->
full_name
,
slot
->
index
,
slot
->
name
,
slot
->
power_domain
,
slot
->
type
);
/* should not try to register the same slot twice */
if
(
is_registered
(
slot
))
{
/* should't be here */
err
(
"register_slot: slot[%s] is already registered
\n
"
,
slot
->
name
);
rpaphp_release_slot
(
slot
->
hotplug_slot
);
return
1
;
}
retval
=
pci_hp_register
(
slot
->
hotplug_slot
);
if
(
retval
)
{
err
(
"pci_hp_register failed with error %d
\n
"
,
retval
);
...
...
@@ -142,30 +222,40 @@ int register_slot(struct slot *slot)
/* create "phy_locatoin" file */
rpaphp_sysfs_add_attr_location
(
slot
->
hotplug_slot
);
/* create "phy_removable" file */
rpaphp_sysfs_add_attr_removable
(
slot
->
hotplug_slot
);
/* add slot to our internal list */
dbg
(
"%s adding slot[%s] to rpaphp_slot_list
\n
"
,
__FUNCTION__
,
slot
->
name
);
list_add
(
&
slot
->
rpaphp_slot_list
,
&
rpaphp_slot_head
);
if
(
vio_uni_addr
)
info
(
"Slot [%s](
vio_uni_addr
=%s) registered
\n
"
,
slot
->
name
,
vio_uni_addr
);
if
(
slot
->
dev_type
==
VIO_DEV
)
info
(
"Slot [%s](
VIO location
=%s) registered
\n
"
,
slot
->
name
,
slot
->
location
);
else
info
(
"Slot [%s](
bus_id
=%s) registered
\n
"
,
slot
->
name
,
pci_name
(
slot
->
bridge
)
);
info
(
"Slot [%s](
PCI location
=%s) registered
\n
"
,
slot
->
name
,
slot
->
location
);
num_slots
++
;
return
0
;
}
int
rpaphp_get_power_status
(
struct
slot
*
slot
,
u8
*
value
)
{
int
rc
;
int
rc
=
0
;
if
(
slot
->
type
==
EMBEDDED
)
{
dbg
(
"%s set to POWER_ON for EMBEDDED slot %s
\n
"
,
__FUNCTION__
,
slot
->
location
);
*
value
=
POWER_ON
;
}
else
{
rc
=
rtas_get_power_level
(
slot
->
power_domain
,
(
int
*
)
value
);
if
(
rc
)
err
(
"failed to get power-level for slot(%s), rc=0x%x
\n
"
,
slot
->
name
,
rc
);
slot
->
location
,
rc
);
}
return
rc
;
}
...
...
@@ -177,8 +267,8 @@ int rpaphp_set_attention_status(struct slot *slot, u8 status)
/* status: LED_OFF or LED_ON */
rc
=
rtas_set_indicator
(
DR_INDICATOR
,
slot
->
index
,
status
);
if
(
rc
)
err
(
"slot(
%s
) set attention-status(%d) failed! rc=0x%x
\n
"
,
slot
->
name
,
status
,
rc
);
err
(
"slot(
name=%s location=%s index=0x%x
) set attention-status(%d) failed! rc=0x%x
\n
"
,
slot
->
name
,
s
lot
->
location
,
slot
->
index
,
s
tatus
,
rc
);
return
rc
;
}
drivers/pci/hotplug/rpaphp_vio.c
View file @
5a7db1eb
...
...
@@ -74,12 +74,12 @@ int register_vio_slot(struct device_node *dn)
int
rc
=
1
;
struct
slot
*
slot
=
NULL
;
name
=
rpaphp_get_drc_name
(
dn
);
if
(
!
name
)
goto
exit_rc
;
index
=
(
u32
*
)
get_property
(
dn
,
"ibm,my-drc-index"
,
NULL
);
if
(
!
index
)
goto
exit_rc
;
name
=
get_property
(
dn
,
"ibm,loc-code"
,
NULL
);
if
(
!
name
)
goto
exit_rc
;
if
(
!
(
slot
=
alloc_slot_struct
(
dn
,
*
index
,
name
,
0
)))
{
rc
=
-
ENOMEM
;
goto
exit_rc
;
...
...
drivers/pci/hotplug/shpchp.h
View file @
5a7db1eb
...
...
@@ -61,6 +61,7 @@ struct pci_func {
u8
configured
;
u8
switch_save
;
u8
presence_save
;
u8
pwr_save
;
u32
base_length
[
0x06
];
u8
base_type
[
0x06
];
u16
reserved2
;
...
...
drivers/pci/hotplug/shpchp_ctrl.c
View file @
5a7db1eb
...
...
@@ -137,6 +137,8 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id)
p_slot
=
shpchp_find_slot
(
ctrl
,
hp_slot
+
ctrl
->
slot_device_offset
);
p_slot
->
hpc_ops
->
get_adapter_status
(
p_slot
,
&
(
func
->
presence_save
));
p_slot
->
hpc_ops
->
get_latch_status
(
p_slot
,
&
getstatus
);
dbg
(
"%s: Card present %x Power status %x
\n
"
,
__FUNCTION__
,
func
->
presence_save
,
func
->
pwr_save
);
if
(
getstatus
)
{
/*
...
...
@@ -145,6 +147,10 @@ u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id)
info
(
"Latch open on Slot(%d)
\n
"
,
ctrl
->
first_slot
+
hp_slot
);
func
->
switch_save
=
0
;
taskInfo
->
event_type
=
INT_SWITCH_OPEN
;
if
(
func
->
pwr_save
&&
func
->
presence_save
)
{
taskInfo
->
event_type
=
INT_POWER_FAULT
;
err
(
"Surprise Removal of card
\n
"
);
}
}
else
{
/*
* Switch closed
...
...
@@ -1427,6 +1433,7 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
rc
=
p_slot
->
hpc_ops
->
set_bus_speed_mode
(
p_slot
,
adapter_speed
);
if
(
rc
)
{
err
(
"%s: Issue of set bus speed mode command failed
\n
"
,
__FUNCTION__
);
up
(
&
ctrl
->
crit_sect
);
return
WRONG_BUS_FREQUENCY
;
}
...
...
@@ -1438,6 +1445,7 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
err
(
"%s: Can't set bus speed/mode in the case of adapter & bus mismatch
\n
"
,
__FUNCTION__
);
err
(
"%s: Error code (%d)
\n
"
,
__FUNCTION__
,
rc
);
up
(
&
ctrl
->
crit_sect
);
return
WRONG_BUS_FREQUENCY
;
}
/* Done with exclusive hardware access */
...
...
@@ -1589,8 +1597,9 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
func
->
status
=
0
;
func
->
switch_save
=
0x10
;
func
->
is_a_board
=
0x01
;
func
->
pwr_save
=
1
;
/*
n
ext, we will instantiate the linux pci_dev structures
/*
N
ext, we will instantiate the linux pci_dev structures
* (with appropriate driver notification, if already present)
*/
index
=
0
;
...
...
@@ -1781,6 +1790,7 @@ static u32 remove_board(struct pci_func *func, struct controller *ctrl)
func
->
function
=
0
;
func
->
configured
=
0
;
func
->
switch_save
=
0x10
;
func
->
pwr_save
=
0
;
func
->
is_a_board
=
0
;
}
...
...
@@ -1807,7 +1817,6 @@ static void shpchp_pushbutton_thread (unsigned long slot)
{
struct
slot
*
p_slot
=
(
struct
slot
*
)
slot
;
u8
getstatus
;
int
rc
;
pushbutton_pending
=
0
;
...
...
@@ -1821,23 +1830,7 @@ static void shpchp_pushbutton_thread (unsigned long slot)
p_slot
->
state
=
POWEROFF_STATE
;
dbg
(
"In power_down_board, b:d(%x:%x)
\n
"
,
p_slot
->
bus
,
p_slot
->
device
);
if
(
shpchp_disable_slot
(
p_slot
))
{
/* Wait for exclusive access to hardware */
down
(
&
p_slot
->
ctrl
->
crit_sect
);
/* Turn on the Attention LED */
rc
=
p_slot
->
hpc_ops
->
set_attention_status
(
p_slot
,
1
);
if
(
rc
)
{
err
(
"%s: Issue of Set Atten Indicator On command failed
\n
"
,
__FUNCTION__
);
return
;
}
/* Wait for the command to complete */
wait_for_ctrl_irq
(
p_slot
->
ctrl
);
/* Done with exclusive hardware access */
up
(
&
p_slot
->
ctrl
->
crit_sect
);
}
shpchp_disable_slot
(
p_slot
);
p_slot
->
state
=
STATIC_STATE
;
}
else
{
p_slot
->
state
=
POWERON_STATE
;
...
...
@@ -1847,15 +1840,6 @@ static void shpchp_pushbutton_thread (unsigned long slot)
/* Wait for exclusive access to hardware */
down
(
&
p_slot
->
ctrl
->
crit_sect
);
/* Turn off the green LED */
rc
=
p_slot
->
hpc_ops
->
set_attention_status
(
p_slot
,
1
);
if
(
rc
)
{
err
(
"%s: Issue of Set Atten Indicator On command failed
\n
"
,
__FUNCTION__
);
return
;
}
/* Wait for the command to complete */
wait_for_ctrl_irq
(
p_slot
->
ctrl
);
p_slot
->
hpc_ops
->
green_led_off
(
p_slot
);
/* Wait for the command to complete */
...
...
@@ -2096,7 +2080,7 @@ int shpchp_enable_slot (struct slot *p_slot)
func
=
shpchp_slot_find
(
p_slot
->
bus
,
p_slot
->
device
,
0
);
if
(
!
func
)
{
dbg
(
"%s: Error! slot NULL
\n
"
,
__FUNCTION__
);
return
(
1
)
;
return
1
;
}
/* Check to see if (latch closed, card present, power off) */
...
...
@@ -2105,19 +2089,19 @@ int shpchp_enable_slot (struct slot *p_slot)
if
(
rc
||
!
getstatus
)
{
info
(
"%s: no adapter on slot(%x)
\n
"
,
__FUNCTION__
,
p_slot
->
number
);
up
(
&
p_slot
->
ctrl
->
crit_sect
);
return
(
0
)
;
return
1
;
}
rc
=
p_slot
->
hpc_ops
->
get_latch_status
(
p_slot
,
&
getstatus
);
if
(
rc
||
getstatus
)
{
info
(
"%s: latch open on slot(%x)
\n
"
,
__FUNCTION__
,
p_slot
->
number
);
up
(
&
p_slot
->
ctrl
->
crit_sect
);
return
(
0
)
;
return
1
;
}
rc
=
p_slot
->
hpc_ops
->
get_power_status
(
p_slot
,
&
getstatus
);
if
(
rc
||
getstatus
)
{
info
(
"%s: already enabled on slot(%x)
\n
"
,
__FUNCTION__
,
p_slot
->
number
);
up
(
&
p_slot
->
ctrl
->
crit_sect
);
return
(
0
)
;
return
1
;
}
up
(
&
p_slot
->
ctrl
->
crit_sect
);
...
...
@@ -2125,7 +2109,7 @@ int shpchp_enable_slot (struct slot *p_slot)
func
=
shpchp_slot_create
(
p_slot
->
bus
);
if
(
func
==
NULL
)
return
(
1
)
;
return
1
;
func
->
bus
=
p_slot
->
bus
;
func
->
device
=
p_slot
->
device
;
...
...
@@ -2135,6 +2119,8 @@ int shpchp_enable_slot (struct slot *p_slot)
/* We have to save the presence info for these slots */
p_slot
->
hpc_ops
->
get_adapter_status
(
p_slot
,
&
(
func
->
presence_save
));
p_slot
->
hpc_ops
->
get_power_status
(
p_slot
,
&
(
func
->
pwr_save
));
dbg
(
"%s: func->pwr_save %x
\n
"
,
__FUNCTION__
,
func
->
pwr_save
);
p_slot
->
hpc_ops
->
get_latch_status
(
p_slot
,
&
getstatus
);
func
->
switch_save
=
!
getstatus
?
0x10
:
0
;
...
...
@@ -2181,7 +2167,7 @@ int shpchp_disable_slot (struct slot *p_slot)
struct
pci_func
*
func
;
if
(
!
p_slot
->
ctrl
)
return
(
1
)
;
return
1
;
/* Check to see if (latch closed, card present, power on) */
down
(
&
p_slot
->
ctrl
->
crit_sect
);
...
...
@@ -2190,19 +2176,19 @@ int shpchp_disable_slot (struct slot *p_slot)
if
(
ret
||
!
getstatus
)
{
info
(
"%s: no adapter on slot(%x)
\n
"
,
__FUNCTION__
,
p_slot
->
number
);
up
(
&
p_slot
->
ctrl
->
crit_sect
);
return
(
0
)
;
return
1
;
}
ret
=
p_slot
->
hpc_ops
->
get_latch_status
(
p_slot
,
&
getstatus
);
if
(
ret
||
getstatus
)
{
info
(
"%s: latch open on slot(%x)
\n
"
,
__FUNCTION__
,
p_slot
->
number
);
up
(
&
p_slot
->
ctrl
->
crit_sect
);
return
(
0
)
;
return
1
;
}
ret
=
p_slot
->
hpc_ops
->
get_power_status
(
p_slot
,
&
getstatus
);
if
(
ret
||
!
getstatus
)
{
info
(
"%s: already disabled slot(%x)
\n
"
,
__FUNCTION__
,
p_slot
->
number
);
up
(
&
p_slot
->
ctrl
->
crit_sect
);
return
(
0
)
;
return
1
;
}
up
(
&
p_slot
->
ctrl
->
crit_sect
);
...
...
drivers/pci/hotplug/shpchp_pci.c
View file @
5a7db1eb
...
...
@@ -263,6 +263,7 @@ int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slot
new_slot
->
function
=
(
u8
)
function
;
new_slot
->
is_a_board
=
1
;
new_slot
->
switch_save
=
0x10
;
new_slot
->
pwr_save
=
1
;
/* In case of unsupported board */
new_slot
->
status
=
DevError
;
new_slot
->
pci_dev
=
pci_find_slot
(
new_slot
->
bus
,
...
...
drivers/pci/hotplug/shpchprm_acpi.c
View file @
5a7db1eb
...
...
@@ -218,6 +218,10 @@ static void acpi_get__hpp ( struct acpi_bridge *ab)
}
ab
->
_hpp
=
kmalloc
(
sizeof
(
struct
acpi__hpp
),
GFP_KERNEL
);
if
(
!
ab
->
_hpp
)
{
err
(
"acpi_shpchprm:%s alloc for _HPP failed
\n
"
,
path_name
);
goto
free_and_return
;
}
memset
(
ab
->
_hpp
,
0
,
sizeof
(
struct
acpi__hpp
));
ab
->
_hpp
->
cache_line_size
=
nui
[
0
];
...
...
@@ -1391,7 +1395,7 @@ static int configure_existing_function(
static
int
bind_pci_resources_to_slots
(
struct
controller
*
ctrl
)
{
struct
pci_func
*
func
;
struct
pci_func
*
func
,
new_func
;
int
busn
=
ctrl
->
bus
;
int
devn
,
funn
;
u32
vid
;
...
...
@@ -1406,12 +1410,20 @@ static int bind_pci_resources_to_slots ( struct controller *ctrl)
if
(
vid
!=
0xFFFFFFFF
)
{
func
=
shpchp_slot_find
(
busn
,
devn
,
funn
);
if
(
!
func
)
continue
;
if
(
!
func
)
{
memset
(
&
new_func
,
0
,
sizeof
(
struct
pci_func
));
new_func
.
bus
=
busn
;
new_func
.
device
=
devn
;
new_func
.
function
=
funn
;
new_func
.
is_a_board
=
1
;
configure_existing_function
(
ctrl
,
&
new_func
);
shpchprm_dump_func_res
(
&
new_func
);
}
else
{
configure_existing_function
(
ctrl
,
func
);
dbg
(
"aCCF:existing PCI 0x%x Func ResourceDump
\n
"
,
ctrl
->
bus
);
shpchprm_dump_func_res
(
func
);
}
dbg
(
"aCCF:existing PCI 0x%x Func ResourceDump
\n
"
,
ctrl
->
bus
);
}
}
}
...
...
drivers/pci/hotplug/shpchprm_nonacpi.c
View file @
5a7db1eb
...
...
@@ -208,7 +208,7 @@ static int configure_existing_function(
static
int
bind_pci_resources_to_slots
(
struct
controller
*
ctrl
)
{
struct
pci_func
*
func
;
struct
pci_func
*
func
,
new_func
;
int
busn
=
ctrl
->
slot_bus
;
int
devn
,
funn
;
u32
vid
;
...
...
@@ -226,12 +226,20 @@ static int bind_pci_resources_to_slots ( struct controller *ctrl)
if
(
vid
!=
0xFFFFFFFF
)
{
func
=
shpchp_slot_find
(
busn
,
devn
,
funn
);
if
(
!
func
)
continue
;
if
(
!
func
)
{
memset
(
&
new_func
,
0
,
sizeof
(
struct
pci_func
));
new_func
.
bus
=
busn
;
new_func
.
device
=
devn
;
new_func
.
function
=
funn
;
new_func
.
is_a_board
=
1
;
configure_existing_function
(
ctrl
,
&
new_func
);
phprm_dump_func_res
(
&
new_func
);
}
else
{
configure_existing_function
(
ctrl
,
func
);
dbg
(
"aCCF:existing PCI 0x%x Func ResourceDump
\n
"
,
ctrl
->
bus
);
phprm_dump_func_res
(
func
);
}
dbg
(
"aCCF:existing PCI 0x%x Func ResourceDump
\n
"
,
ctrl
->
bus
);
}
}
}
...
...
drivers/pci/pci.c
View file @
5a7db1eb
...
...
@@ -442,7 +442,7 @@ int pci_enable_wake(struct pci_dev *dev, u32 state, int enable)
pci_read_config_word
(
dev
,
pm
+
PCI_PM_PMC
,
&
value
);
value
&=
PCI_PM_CAP_PME_MASK
;
value
>>=
ffs
(
value
)
;
/* First bit of mask */
value
>>=
ffs
(
PCI_PM_CAP_PME_MASK
)
-
1
;
/* First bit of mask */
/* Check if it can generate PME# from requested state. */
if
(
!
value
||
!
(
value
&
(
1
<<
state
)))
...
...
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