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
4960aefd
Commit
4960aefd
authored
Mar 09, 2004
by
Linda Xie
Committed by
Greg Kroah-Hartman
Mar 09, 2004
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] PCI Hotplug: rpaphp/rpadlpar latest (support for vio and multifunction devices )
parent
3d3c5375
Changes
7
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
1038 additions
and
761 deletions
+1038
-761
drivers/pci/hotplug/Makefile
drivers/pci/hotplug/Makefile
+3
-1
drivers/pci/hotplug/rpadlpar_core.c
drivers/pci/hotplug/rpadlpar_core.c
+132
-54
drivers/pci/hotplug/rpaphp.h
drivers/pci/hotplug/rpaphp.h
+61
-29
drivers/pci/hotplug/rpaphp_core.c
drivers/pci/hotplug/rpaphp_core.c
+193
-660
drivers/pci/hotplug/rpaphp_pci.c
drivers/pci/hotplug/rpaphp_pci.c
+340
-17
drivers/pci/hotplug/rpaphp_slot.c
drivers/pci/hotplug/rpaphp_slot.c
+188
-0
drivers/pci/hotplug/rpaphp_vio.c
drivers/pci/hotplug/rpaphp_vio.c
+121
-0
No files found.
drivers/pci/hotplug/Makefile
View file @
4960aefd
...
@@ -40,7 +40,9 @@ acpiphp-objs := acpiphp_core.o \
...
@@ -40,7 +40,9 @@ acpiphp-objs := acpiphp_core.o \
acpiphp_res.o
acpiphp_res.o
rpaphp-objs
:=
rpaphp_core.o
\
rpaphp-objs
:=
rpaphp_core.o
\
rpaphp_pci.o
rpaphp_pci.o
\
rpaphp_slot.o
\
rpaphp_vio.o
rpadlpar_io-objs
:=
rpadlpar_core.o
\
rpadlpar_io-objs
:=
rpadlpar_core.o
\
rpadlpar_sysfs.o
rpadlpar_sysfs.o
...
...
drivers/pci/hotplug/rpadlpar_core.c
View file @
4960aefd
...
@@ -43,7 +43,28 @@ static char *get_node_drc_name(struct device_node *dn)
...
@@ -43,7 +43,28 @@ static char *get_node_drc_name(struct device_node *dn)
return
ptr
;
return
ptr
;
}
}
static
struct
device_node
*
find_php_slot_node
(
char
*
drc_name
)
static
struct
device_node
*
find_php_slot_vio_node
(
char
*
drc_name
)
{
struct
device_node
*
child
;
struct
device_node
*
parent
=
of_find_node_by_name
(
NULL
,
"vdevice"
);
if
(
!
parent
)
return
NULL
;
for
(
child
=
of_get_next_child
(
parent
,
NULL
);
child
;
child
=
of_get_next_child
(
parent
,
child
))
{
char
*
loc_code
;
loc_code
=
get_property
(
child
,
"ibm,loc-code"
,
NULL
);
if
(
loc_code
&&
!
strcmp
(
loc_code
,
drc_name
))
return
child
;
}
return
NULL
;
}
static
struct
device_node
*
find_php_slot_pci_node
(
char
*
drc_name
)
{
{
struct
device_node
*
np
=
NULL
;
struct
device_node
*
np
=
NULL
;
char
*
name
;
char
*
name
;
...
@@ -72,7 +93,7 @@ static inline struct hotplug_slot *find_php_slot(char *drc_name)
...
@@ -72,7 +93,7 @@ static inline struct hotplug_slot *find_php_slot(char *drc_name)
static
struct
slot
*
find_slot
(
char
*
drc_name
)
static
struct
slot
*
find_slot
(
char
*
drc_name
)
{
{
struct
hotplug_slot
*
php_slot
=
find_php_slot
(
drc_name
);
struct
hotplug_slot
*
php_slot
=
find_php_slot
(
drc_name
);
if
(
!
php_slot
)
if
(
!
php_slot
)
return
NULL
;
return
NULL
;
...
@@ -127,14 +148,14 @@ static int pci_add_secondary_bus(struct device_node *dn,
...
@@ -127,14 +148,14 @@ static int pci_add_secondary_bus(struct device_node *dn,
rpadlpar_claim_one_bus
(
bridge_dev
->
bus
);
rpadlpar_claim_one_bus
(
bridge_dev
->
bus
);
if
(
hose
->
last_busno
<
child
->
number
)
if
(
hose
->
last_busno
<
child
->
number
)
hose
->
last_busno
=
child
->
number
;
hose
->
last_busno
=
child
->
number
;
dn
->
bussubno
=
child
->
number
;
dn
->
bussubno
=
child
->
number
;
/* ioremap() for child bus */
/* ioremap() for child bus */
if
(
remap_bus_range
(
child
))
{
if
(
remap_bus_range
(
child
))
{
printk
(
KERN_ERR
"%s: could not ioremap() child bus
\n
"
,
printk
(
KERN_ERR
"%s: could not ioremap() child bus
\n
"
,
__FUNCTION__
);
__FUNCTION__
);
return
1
;
return
1
;
}
}
...
@@ -162,9 +183,9 @@ static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn)
...
@@ -162,9 +183,9 @@ static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn)
return
NULL
;
return
NULL
;
}
}
if
(
dev
->
hdr_type
!=
PCI_HEADER_TYPE_BRIDGE
)
{
if
(
dev
->
hdr_type
!=
PCI_HEADER_TYPE_BRIDGE
)
{
printk
(
KERN_ERR
"%s: unexpected header type %d
\n
"
,
printk
(
KERN_ERR
"%s: unexpected header type %d
\n
"
,
__FUNCTION__
,
dev
->
hdr_type
);
__FUNCTION__
,
dev
->
hdr_type
);
return
NULL
;
return
NULL
;
}
}
...
@@ -180,7 +201,7 @@ static int dlpar_pci_remove_bus(struct pci_dev *bridge_dev)
...
@@ -180,7 +201,7 @@ static int dlpar_pci_remove_bus(struct pci_dev *bridge_dev)
if
(
!
bridge_dev
)
{
if
(
!
bridge_dev
)
{
printk
(
KERN_ERR
"%s: unexpected null device
\n
"
,
printk
(
KERN_ERR
"%s: unexpected null device
\n
"
,
__FUNCTION__
);
__FUNCTION__
);
return
1
;
return
1
;
}
}
...
@@ -188,11 +209,25 @@ static int dlpar_pci_remove_bus(struct pci_dev *bridge_dev)
...
@@ -188,11 +209,25 @@ static int dlpar_pci_remove_bus(struct pci_dev *bridge_dev)
if
(
unmap_bus_range
(
secondary_bus
))
{
if
(
unmap_bus_range
(
secondary_bus
))
{
printk
(
KERN_ERR
"%s: failed to unmap bus range
\n
"
,
printk
(
KERN_ERR
"%s: failed to unmap bus range
\n
"
,
__FUNCTION__
);
__FUNCTION__
);
return
1
;
return
1
;
}
}
pci_remove_bus_device
(
bridge_dev
);
pci_remove_bus_device
(
bridge_dev
);
return
0
;
}
static
inline
int
dlpar_add_pci_slot
(
char
*
drc_name
,
struct
device_node
*
dn
)
{
struct
pci_dev
*
dev
;
/* Add pci bus */
dev
=
dlpar_pci_add_bus
(
dn
);
if
(
!
dev
)
{
printk
(
KERN_ERR
"%s: unable to add bus %s
\n
"
,
__FUNCTION__
,
drc_name
);
return
-
EIO
;
}
return
0
;
return
0
;
}
}
...
@@ -212,37 +247,33 @@ static int dlpar_pci_remove_bus(struct pci_dev *bridge_dev)
...
@@ -212,37 +247,33 @@ static int dlpar_pci_remove_bus(struct pci_dev *bridge_dev)
*/
*/
int
dlpar_add_slot
(
char
*
drc_name
)
int
dlpar_add_slot
(
char
*
drc_name
)
{
{
struct
device_node
*
dn
=
find_php_slot_node
(
drc_name
);
struct
device_node
*
dn
;
struct
pci_dev
*
dev
;
int
rc
=
0
;
int
rc
=
0
;
if
(
down_interruptible
(
&
rpadlpar_sem
))
if
(
down_interruptible
(
&
rpadlpar_sem
))
return
-
ERESTARTSYS
;
return
-
ERESTARTSYS
;
if
(
!
dn
)
{
rc
=
-
ENODEV
;
goto
exit
;
}
/* Check for existing hotplug slot */
/* Check for existing hotplug slot */
if
(
find_slot
(
drc_name
))
{
if
(
find_slot
(
drc_name
))
{
rc
=
-
EINVAL
;
rc
=
-
EINVAL
;
goto
exit
;
goto
exit
;
}
}
/* Add pci bus */
dn
=
find_php_slot_vio_node
(
drc_name
);
dev
=
dlpar_pci_add_bus
(
dn
);
if
(
!
dn
)
{
if
(
!
dev
)
{
dn
=
find_php_slot_pci_node
(
drc_name
);
printk
(
KERN_ERR
"%s: unable to add bus %s
\n
"
,
__FUNCTION__
,
if
(
dn
)
drc_name
);
rc
=
dlpar_add_pci_slot
(
drc_name
,
dn
);
rc
=
-
EIO
;
else
{
goto
exit
;
rc
=
-
ENODEV
;
goto
exit
;
}
}
}
/* Add hotplug slot for new
bus
*/
/* Add hotplug slot for new
VIOA or PCI
*/
if
(
rpaphp_add_slot
(
drc_name
))
{
if
(
!
rc
&&
rpaphp_add_slot
(
dn
))
{
printk
(
KERN_ERR
"%s: unable to add hotplug slot %s
\n
"
,
printk
(
KERN_ERR
"%s: unable to add hotplug slot %s
\n
"
,
__FUNCTION__
,
drc_name
);
__FUNCTION__
,
drc_name
);
rc
=
-
EIO
;
rc
=
-
EIO
;
}
}
exit:
exit:
...
@@ -251,60 +282,107 @@ int dlpar_add_slot(char *drc_name)
...
@@ -251,60 +282,107 @@ int dlpar_add_slot(char *drc_name)
}
}
/**
/**
* dlpar_remove_
slot - DLPAR remove an
I/O Slot
* dlpar_remove_
vio_slot - DLPAR remove a virtual
I/O Slot
* @drc_name: drc-name of newly added slot
* @drc_name: drc-name of newly added slot
*
*
* Remove the kernel and hotplug representations
* Remove the kernel and hotplug representations
* of an I/O Slot.
* of an I/O Slot.
* Return Codes:
* Return Codes:
* 0 Success
* 0 Success
* -EIO Internal Error
*/
int
dlpar_remove_vio_slot
(
struct
slot
*
slot
,
char
*
drc_name
)
{
/* Remove hotplug slot */
if
(
rpaphp_remove_slot
(
slot
))
{
printk
(
KERN_ERR
"%s: unable to remove hotplug slot %s
\n
"
,
__FUNCTION__
,
drc_name
);
return
-
EIO
;
}
return
0
;
}
/**
* dlpar_remove_slot - DLPAR remove a PCI I/O Slot
* @drc_name: drc-name of newly added slot
*
* Remove the kernel and hotplug representations
* of a PCI I/O Slot.
* Return Codes:
* 0 Success
* -ENODEV Not a valid drc_name
* -ENODEV Not a valid drc_name
* -EINVAL Slot already removed
* -ERESTARTSYS Signalled before obtaining lock
* -EIO Internal PCI Error
* -EIO Internal PCI Error
*/
*/
int
dlpar_remove_
slot
(
char
*
drc_name
)
int
dlpar_remove_
pci_slot
(
struct
slot
*
slot
,
char
*
drc_name
)
{
{
struct
device_node
*
dn
=
find_php_slot_node
(
drc_name
);
struct
device_node
*
dn
=
find_php_slot_pci_node
(
drc_name
);
struct
slot
*
slot
;
struct
pci_dev
*
bridge_dev
;
struct
pci_dev
*
bridge_dev
;
int
rc
=
0
;
if
(
down_interruptible
(
&
rpadlpar_sem
))
return
-
ERESTARTSYS
;
if
(
!
dn
)
{
if
(
!
dn
)
rc
=
-
ENODEV
;
return
-
ENODEV
;
goto
exit
;
}
slot
=
find_slot
(
drc_name
);
if
(
!
slot
)
{
rc
=
-
EINVAL
;
goto
exit
;
}
bridge_dev
=
slot
->
bridge
;
bridge_dev
=
slot
->
bridge
;
if
(
!
bridge_dev
)
{
if
(
!
bridge_dev
)
{
printk
(
KERN_ERR
"%s: unexpected null bridge device
\n
"
,
printk
(
KERN_ERR
"%s: unexpected null bridge device
\n
"
,
__FUNCTION__
);
__FUNCTION__
);
rc
=
-
EIO
;
return
-
EIO
;
goto
exit
;
}
}
/* Remove hotplug slot */
/* Remove hotplug slot */
if
(
rpaphp_remove_slot
(
slot
))
{
if
(
rpaphp_remove_slot
(
slot
))
{
printk
(
KERN_ERR
"%s: unable to remove hotplug slot %s
\n
"
,
printk
(
KERN_ERR
"%s: unable to remove hotplug slot %s
\n
"
,
__FUNCTION__
,
drc_name
);
__FUNCTION__
,
drc_name
);
rc
=
-
EIO
;
return
-
EIO
;
goto
exit
;
}
}
/* Remove pci bus */
/* Remove pci bus */
if
(
dlpar_pci_remove_bus
(
bridge_dev
))
{
if
(
dlpar_pci_remove_bus
(
bridge_dev
))
{
printk
(
KERN_ERR
"%s: unable to remove pci bus %s
\n
"
,
printk
(
KERN_ERR
"%s: unable to remove pci bus %s
\n
"
,
__FUNCTION__
,
drc_name
);
__FUNCTION__
,
drc_name
);
rc
=
-
EIO
;
return
-
EIO
;
}
return
0
;
}
/**
* dlpar_remove_slot - DLPAR remove an I/O Slot
* @drc_name: drc-name of newly added slot
*
* Remove the kernel and hotplug representations
* of an I/O Slot.
* Return Codes:
* 0 Success
* -ENODEV Not a valid drc_name
* -EINVAL Slot already removed
* -ERESTARTSYS Signalled before obtaining lock
* -EIO Internal Error
*/
int
dlpar_remove_slot
(
char
*
drc_name
)
{
struct
slot
*
slot
;
int
rc
=
0
;
if
(
down_interruptible
(
&
rpadlpar_sem
))
return
-
ERESTARTSYS
;
slot
=
find_slot
(
drc_name
);
if
(
!
slot
)
{
rc
=
-
EINVAL
;
goto
exit
;
}
switch
(
slot
->
dev_type
)
{
case
PCI_DEV
:
rc
=
dlpar_remove_pci_slot
(
slot
,
drc_name
);
break
;
case
VIO_DEV
:
rc
=
dlpar_remove_vio_slot
(
slot
,
drc_name
);
break
;
default:
rc
=
-
EIO
;
}
}
exit:
exit:
up
(
&
rpadlpar_sem
);
up
(
&
rpadlpar_sem
);
...
@@ -324,7 +402,7 @@ int __init rpadlpar_io_init(void)
...
@@ -324,7 +402,7 @@ int __init rpadlpar_io_init(void)
if
(
!
is_dlpar_capable
())
{
if
(
!
is_dlpar_capable
())
{
printk
(
KERN_WARNING
"%s: partition not DLPAR capable
\n
"
,
printk
(
KERN_WARNING
"%s: partition not DLPAR capable
\n
"
,
__FUNCTION__
);
__FUNCTION__
);
return
-
EPERM
;
return
-
EPERM
;
}
}
...
...
drivers/pci/hotplug/rpaphp.h
View file @
4960aefd
...
@@ -26,6 +26,8 @@
...
@@ -26,6 +26,8 @@
#ifndef _PPC64PHP_H
#ifndef _PPC64PHP_H
#define _PPC64PHP_H
#define _PPC64PHP_H
#include <linux/pci.h>
#include "pci_hotplug.h"
#include "pci_hotplug.h"
#define DR_INDICATOR 9002
#define DR_INDICATOR 9002
...
@@ -34,24 +36,22 @@
...
@@ -34,24 +36,22 @@
#define POWER_ON 100
#define POWER_ON 100
#define POWER_OFF 0
#define POWER_OFF 0
#define LED_OFF 0
#define LED_OFF 0
#define LED_ON 1
/* continuous on */
#define LED_ON 1
/* continuous on */
#define LED_ID 2
/* slow blinking */
#define LED_ID 2
/* slow blinking */
#define LED_ACTION 3
/* fast blinking */
#define LED_ACTION 3
/* fast blinking */
#define SLOT_NAME_SIZE 12
/* Error status from rtas_get-sensor */
/* Error status from rtas_get-sensor */
#define NEED_POWER -9000
/* slot must be power up and unisolated to get state */
#define NEED_POWER -9000
/* slot must be power up and unisolated to get state */
#define PWR_ONLY -9001
/* slot must be powerd up to get state, leave isolated */
#define PWR_ONLY -9001
/* slot must be powerd up to get state, leave isolated */
#define ERR_SENSE_USE -9002
/* No DR operation will succeed, slot is unusable */
#define ERR_SENSE_USE -9002
/* No DR operation will succeed, slot is unusable */
/* Sensor values from rtas_get-sensor */
/* Sensor values from rtas_get-sensor */
#define EMPTY
0
/* No card in slot */
#define EMPTY
0
/* No card in slot */
#define PRESENT
1
/* Card in slot */
#define PRESENT
1
/* Card in slot */
#define MY_NAME "rpaphp"
#define MY_NAME "rpaphp"
extern
int
debug
;
#define dbg(format, arg...) \
#define dbg(format, arg...) \
do { \
do { \
if (debug) \
if (debug) \
...
@@ -64,6 +64,10 @@
...
@@ -64,6 +64,10 @@
#define SLOT_MAGIC 0x67267322
#define SLOT_MAGIC 0x67267322
/* slot types */
#define VIO_DEV 1
#define PCI_DEV 2
/* slot states */
/* slot states */
#define NOT_VALID 3
#define NOT_VALID 3
...
@@ -75,27 +79,55 @@
...
@@ -75,27 +79,55 @@
* struct slot - slot information for each *physical* slot
* struct slot - slot information for each *physical* slot
*/
*/
struct
slot
{
struct
slot
{
u32
magic
;
u32
magic
;
int
state
;
int
state
;
u32
index
;
u32
index
;
u32
type
;
u32
type
;
u32
power_domain
;
u32
power_domain
;
char
*
name
;
char
*
name
;
struct
device_node
*
dn
;
/* slot's device_node in OFDT */
struct
device_node
*
dn
;
/* slot's device_node in OFDT */
/* dn has phb info */
/* dn has phb info */
struct
pci_dev
*
bridge
;
/* slot's pci_dev in pci_devices */
struct
pci_dev
*
bridge
;
/* slot's pci_dev in pci_devices */
union
{
struct
pci_dev
*
dev
;
/* pci_dev of device in this slot */
struct
pci_dev
*
pci_dev
;
/* pci_dev of device in this slot */
/* it will be used for unconfig */
/* it will be used for unconfig */
/* NULL if slot is empty */
/* NULL if slot is empty */
struct
vio_dev
*
vio_dev
;
/* vio_dev of the device in this slot */
struct
hotplug_slot
*
hotplug_slot
;
}
dev
;
struct
list_head
rpaphp_slot_list
;
u8
dev_type
;
/* VIO or PCI */
struct
hotplug_slot
*
hotplug_slot
;
struct
list_head
rpaphp_slot_list
;
};
};
extern
struct
hotplug_slot_ops
rpaphp_hotplug_slot_ops
;
extern
struct
list_head
rpaphp_slot_head
;
extern
int
num_slots
;
/* function prototypes */
/* rpaphp_pci.c */
extern
struct
pci_dev
*
rpaphp_find_pci_dev
(
struct
device_node
*
dn
);
extern
struct
pci_dev
*
rpaphp_find_pci_dev
(
struct
device_node
*
dn
);
extern
int
rpaphp_add_slot
(
char
*
slot_name
);
extern
int
rpaphp_remove_slot
(
struct
slot
*
slot
);
extern
int
rpaphp_claim_resource
(
struct
pci_dev
*
dev
,
int
resource
);
extern
int
rpaphp_claim_resource
(
struct
pci_dev
*
dev
,
int
resource
);
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
);
/* rpaphp_core.c */
extern
int
rpaphp_add_slot
(
struct
device_node
*
dn
);
extern
int
rpaphp_remove_slot
(
struct
slot
*
slot
);
#endif
/* _PPC64PHP_H */
/* rpaphp_vio.c */
extern
int
rpaphp_get_vio_adapter_status
(
struct
slot
*
slot
,
int
is_init
,
u8
*
value
);
extern
int
rpaphp_unconfig_vio_adapter
(
struct
slot
*
slot
);
extern
int
register_vio_slot
(
struct
device_node
*
dn
);
extern
int
rpaphp_enable_vio_slot
(
struct
slot
*
slot
);
/* rpaphp_slot.c */
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
rpaphp_get_power_status
(
struct
slot
*
slot
,
u8
*
value
);
extern
int
rpaphp_set_attention_status
(
struct
slot
*
slot
,
u8
status
);
#endif
/* _PPC64PHP_H */
drivers/pci/hotplug/rpaphp_core.c
View file @
4960aefd
This diff is collapsed.
Click to expand it.
drivers/pci/hotplug/rpaphp_pci.c
View file @
4960aefd
This diff is collapsed.
Click to expand it.
drivers/pci/hotplug/rpaphp_slot.c
0 → 100644
View file @
4960aefd
/*
* RPA Virtual I/O device functions
* Copyright (C) 2004 Linda Xie <lxie@us.ibm.com>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
* NON INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Send feedback to <lxie@us.ibm.com>
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/pci.h>
#include "rpaphp.h"
/* free up the memory user by a slot */
static
void
rpaphp_release_slot
(
struct
hotplug_slot
*
hotplug_slot
)
{
struct
slot
*
slot
=
hotplug_slot
?
(
struct
slot
*
)
hotplug_slot
->
private
:
NULL
;
if
(
slot
==
NULL
)
return
;
dealloc_slot_struct
(
slot
);
}
void
dealloc_slot_struct
(
struct
slot
*
slot
)
{
kfree
(
slot
->
hotplug_slot
->
info
);
kfree
(
slot
->
hotplug_slot
->
name
);
kfree
(
slot
->
hotplug_slot
);
kfree
(
slot
);
return
;
}
struct
slot
*
alloc_slot_struct
(
struct
device_node
*
dn
,
int
drc_index
,
char
*
drc_name
,
int
power_domain
)
{
struct
slot
*
slot
;
dbg
(
"Enter alloc_slot_struct(): dn->full_name=%s drc_index=0x%x drc_name=%s
\n
"
,
dn
->
full_name
,
drc_index
,
drc_name
);
slot
=
kmalloc
(
sizeof
(
struct
slot
),
GFP_KERNEL
);
if
(
!
slot
)
return
(
NULL
);
memset
(
slot
,
0
,
sizeof
(
struct
slot
));
slot
->
hotplug_slot
=
kmalloc
(
sizeof
(
struct
hotplug_slot
),
GFP_KERNEL
);
if
(
!
slot
->
hotplug_slot
)
{
kfree
(
slot
);
return
(
NULL
);
}
memset
(
slot
->
hotplug_slot
,
0
,
sizeof
(
struct
hotplug_slot
));
slot
->
hotplug_slot
->
info
=
kmalloc
(
sizeof
(
struct
hotplug_slot_info
),
GFP_KERNEL
);
if
(
!
slot
->
hotplug_slot
->
info
)
{
kfree
(
slot
->
hotplug_slot
);
kfree
(
slot
);
return
(
NULL
);
}
memset
(
slot
->
hotplug_slot
->
info
,
0
,
sizeof
(
struct
hotplug_slot_info
));
slot
->
hotplug_slot
->
name
=
kmalloc
(
strlen
(
drc_name
)
+
1
,
GFP_KERNEL
);
if
(
!
slot
->
hotplug_slot
->
name
)
{
kfree
(
slot
->
hotplug_slot
->
info
);
kfree
(
slot
->
hotplug_slot
);
kfree
(
slot
);
return
(
NULL
);
}
slot
->
name
=
slot
->
hotplug_slot
->
name
;
slot
->
dn
=
dn
;
slot
->
index
=
drc_index
;
strcpy
(
slot
->
name
,
drc_name
);
slot
->
power_domain
=
power_domain
;
slot
->
magic
=
SLOT_MAGIC
;
slot
->
hotplug_slot
->
private
=
slot
;
slot
->
hotplug_slot
->
ops
=
&
rpaphp_hotplug_slot_ops
;
slot
->
hotplug_slot
->
release
=
&
rpaphp_release_slot
;
dbg
(
"Exit alloc_slot_struct(): slot->dn->full_name=%s drc_index=0x%x drc_name=%s
\n
"
,
slot
->
dn
->
full_name
,
slot
->
index
,
slot
->
name
);
return
(
slot
);
}
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
);
retval
=
pci_hp_register
(
slot
->
hotplug_slot
);
if
(
retval
)
{
err
(
"pci_hp_register failed with error %d
\n
"
,
retval
);
rpaphp_release_slot
(
slot
->
hotplug_slot
);
return
(
retval
);
}
switch
(
slot
->
dev_type
)
{
case
PCI_DEV
:
/* create symlink between slot->name and it's bus_id */
dbg
(
"%s: sysfs_create_link: %s --> %s
\n
"
,
__FUNCTION__
,
pci_name
(
slot
->
bridge
),
slot
->
name
);
retval
=
sysfs_create_link
(
slot
->
hotplug_slot
->
kobj
.
parent
,
&
slot
->
hotplug_slot
->
kobj
,
pci_name
(
slot
->
bridge
));
if
(
retval
)
{
err
(
"sysfs_create_link failed with error %d
\n
"
,
retval
);
rpaphp_release_slot
(
slot
->
hotplug_slot
);
return
(
retval
);
}
break
;
case
VIO_DEV
:
/* create symlink between slot->name and it's uni-address */
vio_uni_addr
=
strchr
(
slot
->
dn
->
full_name
,
'@'
);
if
(
!
vio_uni_addr
)
return
(
1
);
dbg
(
"%s: sysfs_create_link: %s --> %s
\n
"
,
__FUNCTION__
,
vio_uni_addr
,
slot
->
name
);
retval
=
sysfs_create_link
(
slot
->
hotplug_slot
->
kobj
.
parent
,
&
slot
->
hotplug_slot
->
kobj
,
vio_uni_addr
);
if
(
retval
)
{
err
(
"sysfs_create_link failed with error %d
\n
"
,
retval
);
rpaphp_release_slot
(
slot
->
hotplug_slot
);
return
(
retval
);
}
break
;
default:
return
(
1
);
}
/* 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
);
else
info
(
"Slot [%s](bus_id=%s) registered
\n
"
,
slot
->
name
,
pci_name
(
slot
->
bridge
));
num_slots
++
;
return
(
0
);
}
int
rpaphp_get_power_status
(
struct
slot
*
slot
,
u8
*
value
)
{
int
rc
;
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
);
return
rc
;
}
int
rpaphp_set_attention_status
(
struct
slot
*
slot
,
u8
status
)
{
int
rc
;
/* 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
);
return
rc
;
}
drivers/pci/hotplug/rpaphp_vio.c
0 → 100644
View file @
4960aefd
/*
* RPA Hot Plug Virtual I/O device functions
* Copyright (C) 2004 Linda Xie <lxie@us.ibm.com>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
* NON INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Send feedback to <lxie@us.ibm.com>
*
*/
#include <asm/vio.h>
#include "rpaphp.h"
/*
* get_vio_adapter_status - get the status of a slot
*
* status:
*
* 1-- adapter is configured
* 2-- adapter is not configured
* 3-- not valid
*/
inline
int
rpaphp_get_vio_adapter_status
(
struct
slot
*
slot
,
int
is_init
,
u8
*
value
)
{
*
value
=
slot
->
state
;
return
0
;
}
int
rpaphp_unconfig_vio_adapter
(
struct
slot
*
slot
)
{
int
retval
=
0
;
dbg
(
"Entry %s: slot[%s]
\n
"
,
__FUNCTION__
,
slot
->
name
);
if
(
!
slot
->
dev
.
vio_dev
)
{
info
(
"%s: no VIOA in slot[%s]
\n
"
,
__FUNCTION__
,
slot
->
name
);
retval
=
-
EINVAL
;
goto
exit
;
}
/* remove the device from the vio core */
vio_unregister_device
(
slot
->
dev
.
vio_dev
);
slot
->
state
=
NOT_CONFIGURED
;
info
(
"%s: adapter in slot[%s] unconfigured.
\n
"
,
__FUNCTION__
,
slot
->
name
);
exit:
dbg
(
"Exit %s, rc=0x%x
\n
"
,
__FUNCTION__
,
retval
);
return
retval
;
}
static
int
setup_vio_hotplug_slot_info
(
struct
slot
*
slot
)
{
slot
->
hotplug_slot
->
info
->
power_status
=
1
;
rpaphp_get_vio_adapter_status
(
slot
,
1
,
&
slot
->
hotplug_slot
->
info
->
adapter_status
);
return
0
;
}
int
register_vio_slot
(
struct
device_node
*
dn
)
{
u32
*
index
;
char
*
name
;
int
rc
=
1
;
struct
slot
*
slot
=
NULL
;
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
;
}
slot
->
dev_type
=
VIO_DEV
;
slot
->
dev
.
vio_dev
=
vio_find_node
(
dn
);
if
(
!
slot
->
dev
.
vio_dev
)
slot
->
dev
.
vio_dev
=
vio_register_device
(
dn
);
if
(
slot
->
dev
.
vio_dev
)
slot
->
state
=
CONFIGURED
;
else
slot
->
state
=
NOT_CONFIGURED
;
if
(
setup_vio_hotplug_slot_info
(
slot
))
goto
exit_rc
;
info
(
"%s: registered VIO device[name=%s vio_dev=%p]
\n
"
,
__FUNCTION__
,
slot
->
name
,
slot
->
dev
.
vio_dev
);
rc
=
register_slot
(
slot
);
exit_rc:
if
(
rc
&&
slot
)
dealloc_slot_struct
(
slot
);
return
(
rc
);
}
int
rpaphp_enable_vio_slot
(
struct
slot
*
slot
)
{
int
retval
=
0
;
if
((
slot
->
dev
.
vio_dev
=
vio_register_device
(
slot
->
dn
)))
{
info
(
"%s: VIO adapter %s in slot[%s] has been configured
\n
"
,
__FUNCTION__
,
slot
->
dn
->
name
,
slot
->
name
);
slot
->
state
=
CONFIGURED
;
}
else
{
info
(
"%s: no vio_dev struct for adapter in slot[%s]
\n
"
,
__FUNCTION__
,
slot
->
name
);
slot
->
state
=
NOT_CONFIGURED
;
}
return
retval
;
}
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