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
82670e1f
Commit
82670e1f
authored
Nov 05, 2002
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://linuxusb.bkbits.net/pci_hp-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
parents
42003664
d53e21af
Changes
40
Show whitespace changes
Inline
Side-by-side
Showing
40 changed files
with
2981 additions
and
304 deletions
+2981
-304
CREDITS
CREDITS
+9
-0
MAINTAINERS
MAINTAINERS
+21
-0
arch/alpha/kernel/pci.c
arch/alpha/kernel/pci.c
+1
-1
arch/i386/pci/common.c
arch/i386/pci/common.c
+5
-0
arch/i386/pci/fixup.c
arch/i386/pci/fixup.c
+2
-2
arch/mips/ddb5074/pci.c
arch/mips/ddb5074/pci.c
+2
-2
arch/mips/ddb5476/pci.c
arch/mips/ddb5476/pci.c
+2
-2
arch/mips64/sgi-ip27/ip27-pci.c
arch/mips64/sgi-ip27/ip27-pci.c
+1
-1
arch/mips64/sgi-ip32/ip32-pci.c
arch/mips64/sgi-ip32/ip32-pci.c
+2
-2
arch/parisc/kernel/pci.c
arch/parisc/kernel/pci.c
+1
-1
arch/ppc/kernel/pci.c
arch/ppc/kernel/pci.c
+1
-1
arch/ppc64/kernel/pci.c
arch/ppc64/kernel/pci.c
+2
-2
arch/sh/kernel/pci-dc.c
arch/sh/kernel/pci-dc.c
+1
-1
arch/sh/kernel/pci-sh7751.c
arch/sh/kernel/pci-sh7751.c
+2
-2
arch/sh/kernel/pci_st40.c
arch/sh/kernel/pci_st40.c
+1
-1
arch/sparc64/kernel/pci.c
arch/sparc64/kernel/pci.c
+2
-2
drivers/hotplug/Kconfig
drivers/hotplug/Kconfig
+43
-0
drivers/hotplug/Makefile
drivers/hotplug/Makefile
+7
-1
drivers/hotplug/acpiphp.h
drivers/hotplug/acpiphp.h
+4
-4
drivers/hotplug/acpiphp_core.c
drivers/hotplug/acpiphp_core.c
+83
-80
drivers/hotplug/acpiphp_glue.c
drivers/hotplug/acpiphp_glue.c
+91
-96
drivers/hotplug/acpiphp_pci.c
drivers/hotplug/acpiphp_pci.c
+32
-33
drivers/hotplug/acpiphp_res.c
drivers/hotplug/acpiphp_res.c
+24
-24
drivers/hotplug/cpci_hotplug.h
drivers/hotplug/cpci_hotplug.h
+100
-0
drivers/hotplug/cpci_hotplug_core.c
drivers/hotplug/cpci_hotplug_core.c
+927
-0
drivers/hotplug/cpci_hotplug_pci.c
drivers/hotplug/cpci_hotplug_pci.c
+685
-0
drivers/hotplug/cpcihp_generic.c
drivers/hotplug/cpcihp_generic.c
+290
-0
drivers/hotplug/cpcihp_zt5550.c
drivers/hotplug/cpcihp_zt5550.c
+306
-0
drivers/hotplug/cpcihp_zt5550.h
drivers/hotplug/cpcihp_zt5550.h
+79
-0
drivers/hotplug/pci_hotplug.h
drivers/hotplug/pci_hotplug.h
+4
-0
drivers/hotplug/pci_hotplug_util.c
drivers/hotplug/pci_hotplug_util.c
+67
-8
drivers/pci/Makefile
drivers/pci/Makefile
+6
-1
drivers/pci/hotplug.c
drivers/pci/hotplug.c
+1
-2
drivers/pci/pci.c
drivers/pci/pci.c
+89
-0
drivers/pci/probe.c
drivers/pci/probe.c
+3
-3
drivers/pci/quirks.c
drivers/pci/quirks.c
+25
-25
drivers/pci/search.c
drivers/pci/search.c
+40
-0
drivers/pci/setup-bus.c
drivers/pci/setup-bus.c
+10
-7
include/linux/pci.h
include/linux/pci.h
+7
-0
include/linux/pci_ids.h
include/linux/pci_ids.h
+3
-0
No files found.
CREDITS
View file @
82670e1f
...
...
@@ -2218,6 +2218,15 @@ S: 30 White Tail Lane
S: Lafayette, Indiana 47905
S: USA
N: Scott Murray
E: scottm@somanetworks.com
E: scott@spiteful.org
D: OPL3-SA2, OPL3-SA3 sound driver
D: CompactPCI hotplug core
D: Ziatech ZT5550 and generic CompactPCI hotplug drivers
S: Toronto, Ontario
S: Canada
N: Trond Myklebust
E: trond.myklebust@fys.uio.no
D: current NFS client hacker.
...
...
MAINTAINERS
View file @
82670e1f
...
...
@@ -317,6 +317,27 @@ L: codalist@coda.cs.cmu.edu
W: http://www.coda.cs.cmu.edu/
S: Maintained
COMPACTPCI HOTPLUG CORE
P: Scott Murray
M: scottm@somanetworks.com
M: scott@spiteful.org
L: pcihpd-discuss@lists.sourceforge.net
S: Supported
COMPACTPCI HOTPLUG ZIATECH ZT5550 DRIVER
P: Scott Murray
M: scottm@somanetworks.com
M: scott@spiteful.org
L: pcihpd-discuss@lists.sourceforge.net
S: Supported
COMPACTPCI HOTPLUG GENERIC DRIVER
P: Scott Murray
M: scottm@somanetworks.com
M: scott@spiteful.org
L: pcihpd-discuss@lists.sourceforge.net
S: Supported
COMPAQ FIBRE CHANNEL 64-bit/66MHz PCI non-intelligent HBA
P: Amy Vanzant-Hodge
M: Amy Vanzant-Hodge (fibrechannel@compaq.com)
...
...
arch/alpha/kernel/pci.c
View file @
82670e1f
...
...
@@ -340,7 +340,7 @@ common_swizzle(struct pci_dev *dev, u8 *pinp)
return
PCI_SLOT
(
dev
->
devfn
);
}
void
__init
void
__
dev
init
pcibios_fixup_pbus_ranges
(
struct
pci_bus
*
bus
,
struct
pbus_set_ranges_data
*
ranges
)
{
...
...
arch/i386/pci/common.c
View file @
82670e1f
...
...
@@ -90,6 +90,11 @@ static void __devinit pcibios_fixup_ghosts(struct pci_bus *b)
}
}
void
__devinit
pcibios_fixup_pbus_ranges
(
struct
pci_bus
*
bus
,
struct
pbus_set_ranges_data
*
ranges
)
{
}
/*
* Called after each bus is probed, but before its children
* are examined.
...
...
arch/i386/pci/fixup.c
View file @
82670e1f
...
...
@@ -138,7 +138,7 @@ static void __devinit pci_fixup_piix4_acpi(struct pci_dev *d)
#define VIA_8363_KL133_REVISION_ID 0x81
#define VIA_8363_KM133_REVISION_ID 0x84
static
void
__init
pci_fixup_via_northbridge_bug
(
struct
pci_dev
*
d
)
static
void
__
dev
init
pci_fixup_via_northbridge_bug
(
struct
pci_dev
*
d
)
{
u8
v
;
u8
revision
;
...
...
@@ -180,7 +180,7 @@ static void __init pci_fixup_via_northbridge_bug(struct pci_dev *d)
* system to PCI bus no matter what are their window settings, so they are
* "transparent" (or subtractive decoding) from programmers point of view.
*/
static
void
__init
pci_fixup_transparent_bridge
(
struct
pci_dev
*
dev
)
static
void
__
dev
init
pci_fixup_transparent_bridge
(
struct
pci_dev
*
dev
)
{
if
((
dev
->
class
>>
8
)
==
PCI_CLASS_BRIDGE_PCI
&&
(
dev
->
device
&
0xff00
)
==
0x2400
)
...
...
arch/mips/ddb5074/pci.c
View file @
82670e1f
...
...
@@ -297,7 +297,7 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq)
pci_write_config_byte
(
dev
,
PCI_INTERRUPT_LINE
,
irq
);
}
void
__init
pcibios_fixup_pbus_ranges
(
struct
pci_bus
*
bus
,
void
__
dev
init
pcibios_fixup_pbus_ranges
(
struct
pci_bus
*
bus
,
struct
pbus_set_ranges_data
*
ranges
)
{
}
...
...
arch/mips/ddb5476/pci.c
View file @
82670e1f
...
...
@@ -341,7 +341,7 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq)
pci_write_config_byte
(
dev
,
PCI_INTERRUPT_LINE
,
irq
);
}
void
__init
pcibios_fixup_pbus_ranges
(
struct
pci_bus
*
bus
,
void
__
dev
init
pcibios_fixup_pbus_ranges
(
struct
pci_bus
*
bus
,
struct
pbus_set_ranges_data
*
ranges
)
{
/*
...
...
arch/mips64/sgi-ip27/ip27-pci.c
View file @
82670e1f
...
...
@@ -234,7 +234,7 @@ pcibios_fixup_bus(struct pci_bus *b)
pci_fixup_irqs
(
pci_swizzle
,
pci_map_irq
);
}
void
__init
void
__
dev
init
pcibios_fixup_pbus_ranges
(
struct
pci_bus
*
bus
,
struct
pbus_set_ranges_data
*
ranges
)
{
...
...
arch/mips64/sgi-ip32/ip32-pci.c
View file @
82670e1f
...
...
@@ -349,7 +349,7 @@ void __init pcibios_fixup_bus (struct pci_bus *b)
}
/* XXX anybody know what this is supposed to do? */
void
__init
pcibios_fixup_pbus_ranges
(
struct
pci_bus
*
bus
,
void
__
dev
init
pcibios_fixup_pbus_ranges
(
struct
pci_bus
*
bus
,
struct
pbus_set_ranges_data
*
ranges
)
{
}
...
...
arch/parisc/kernel/pci.c
View file @
82670e1f
...
...
@@ -345,7 +345,7 @@ pcibios_link_hba_resources( struct resource *hba_res, struct resource *r)
/*
** called by drivers/pci/setup-res.c:pci_setup_bridge().
*/
void
pcibios_fixup_pbus_ranges
(
void
__devinit
pcibios_fixup_pbus_ranges
(
struct
pci_bus
*
bus
,
struct
pbus_set_ranges_data
*
ranges
)
...
...
arch/ppc/kernel/pci.c
View file @
82670e1f
...
...
@@ -1107,7 +1107,7 @@ common_swizzle(struct pci_dev *dev, unsigned char *pinp)
return
PCI_SLOT
(
dev
->
devfn
);
}
void
__init
void
__
dev
init
pcibios_fixup_pbus_ranges
(
struct
pci_bus
*
bus
,
struct
pbus_set_ranges_data
*
ranges
)
{
}
...
...
arch/ppc64/kernel/pci.c
View file @
82670e1f
...
...
@@ -121,7 +121,7 @@ static void fixup_windbond_82c105(struct pci_dev* dev)
}
void
pcibios_fixup_pbus_ranges
(
struct
pci_bus
*
pbus
,
void
__devinit
pcibios_fixup_pbus_ranges
(
struct
pci_bus
*
pbus
,
struct
pbus_set_ranges_data
*
pranges
)
{
}
...
...
arch/sh/kernel/pci-dc.c
View file @
82670e1f
...
...
@@ -113,7 +113,7 @@ void pci_free_consistent(struct pci_dev *hwdev, size_t size,
}
void
__init
pcibios_fixup_pbus_ranges
(
struct
pci_bus
*
bus
,
struct
pbus_set_ranges_data
*
ranges
)
void
__
dev
init
pcibios_fixup_pbus_ranges
(
struct
pci_bus
*
bus
,
struct
pbus_set_ranges_data
*
ranges
)
{
}
...
...
arch/sh/kernel/pci-sh7751.c
View file @
82670e1f
...
...
@@ -250,7 +250,7 @@ struct pci_fixup pcibios_fixups[] = {
{
0
}
};
void
__init
pcibios_fixup_pbus_ranges
(
struct
pci_bus
*
b
,
void
__
dev
init
pcibios_fixup_pbus_ranges
(
struct
pci_bus
*
b
,
struct
pbus_set_ranges_data
*
range
)
{
/* No fixups needed */
...
...
arch/sh/kernel/pci_st40.c
View file @
82670e1f
...
...
@@ -380,7 +380,7 @@ static int __init map_harp_irq(struct pci_dev *dev, u8 slot, u8 pin)
}
void
__init
void
__
dev
init
pcibios_fixup_pbus_ranges
(
struct
pci_bus
*
bus
,
struct
pbus_set_ranges_data
*
ranges
)
{
...
...
arch/sparc64/kernel/pci.c
View file @
82670e1f
...
...
@@ -479,7 +479,7 @@ void pcibios_update_irq(struct pci_dev *pdev, int irq)
{
}
void
pcibios_fixup_pbus_ranges
(
struct
pci_bus
*
pbus
,
void
__devinit
pcibios_fixup_pbus_ranges
(
struct
pci_bus
*
pbus
,
struct
pbus_set_ranges_data
*
pranges
)
{
}
...
...
drivers/hotplug/Kconfig
View file @
82670e1f
...
...
@@ -73,5 +73,48 @@ config HOTPLUG_PCI_ACPI
When in doubt, say N.
config HOTPLUG_PCI_CPCI
tristate "CompactPCI Hotplug driver"
depends on HOTPLUG_PCI
help
Say Y here if you have a CompactPCI system card with CompactPCI
hotswap support per the PICMG 2.1 specification.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called cpci_hotplug.o. If you want to compile it
as a module, say M here and read <file:Documentation/modules.txt>.
When in doubt, say N.
config HOTPLUG_PCI_CPCI_ZT5550
tristate "Ziatech ZT5550 CompactPCI Hotplug driver"
depends on HOTPLUG_PCI_CPCI && X86
help
Say Y here if you have an Performance Technologies (formerly Intel,
formerly just Ziatech) Ziatech ZT5550 CompactPCI system card.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called cpcihp_zt5550.o. If you want to compile it
as a module, say M here and read <file:Documentation/modules.txt>.
When in doubt, say N.
config HOTPLUG_PCI_CPCI_GENERIC
tristate "Generic port I/O CompactPCI Hotplug driver"
depends on HOTPLUG_PCI_CPCI && X86
help
Say Y here if you have a CompactPCI system card that exposes the #ENUM
hotswap signal as a bit in a system register that can be read through
standard port I/O.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called cpcihp_generic.o. If you want to compile it
as a module, say M here and read <file:Documentation/modules.txt>.
When in doubt, say N.
endmenu
drivers/hotplug/Makefile
View file @
82670e1f
...
...
@@ -2,12 +2,15 @@
# Makefile for the Linux kernel pci hotplug controller drivers.
#
export-objs
:=
pci_hotplug_core.o pci_hotplug_util.o
export-objs
:=
pci_hotplug_core.o pci_hotplug_util.o
cpci_hotplug_core.o
obj-$(CONFIG_HOTPLUG_PCI)
+=
pci_hotplug.o
obj-$(CONFIG_HOTPLUG_PCI_COMPAQ)
+=
cpqphp.o
obj-$(CONFIG_HOTPLUG_PCI_IBM)
+=
ibmphp.o
obj-$(CONFIG_HOTPLUG_PCI_ACPI)
+=
acpiphp.o
obj-$(CONFIG_HOTPLUG_PCI_CPCI)
+=
cpci_hotplug.o
obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550)
+=
cpcihp_zt5550.o
obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC)
+=
cpcihp_generic.o
pci_hotplug-objs
:=
pci_hotplug_core.o
\
pci_hotplug_util.o
...
...
@@ -28,6 +31,9 @@ acpiphp-objs := acpiphp_core.o \
acpiphp_pci.o
\
acpiphp_res.o
cpci_hotplug-objs
:=
cpci_hotplug_core.o
\
cpci_hotplug_pci.o
ifdef
CONFIG_HOTPLUG_PCI_ACPI
EXTRA_CFLAGS
+=
-D_LINUX
-I
$(TOPDIR)
/drivers/acpi
ifdef
CONFIG_ACPI_DEBUG
...
...
drivers/hotplug/acpiphp.h
View file @
82670e1f
...
...
@@ -41,12 +41,12 @@
#define dbg(format, arg...) \
do { \
if (acpiphp_debug) \
printk
(KERN_DEBUG "%s: " format "\n"
, \
printk
(KERN_DEBUG "%s: " format
, \
MY_NAME , ## arg); \
} while (0)
#define err(format, arg...) printk
(KERN_ERR "%s: " format "\n"
, MY_NAME , ## arg)
#define info(format, arg...) printk
(KERN_INFO "%s: " format "\n"
, MY_NAME , ## arg)
#define warn(format, arg...) printk
(KERN_WARNING "%s: " format "\n"
, MY_NAME , ## arg)
#define err(format, arg...) printk
(KERN_ERR "%s: " format
, MY_NAME , ## arg)
#define info(format, arg...) printk
(KERN_INFO "%s: " format
, MY_NAME , ## arg)
#define warn(format, arg...) printk
(KERN_WARNING "%s: " format
, MY_NAME , ## arg)
#define SLOT_MAGIC 0x67267322
/* name size which is used for entries in pcihpfs */
...
...
drivers/hotplug/acpiphp_core.c
View file @
82670e1f
...
...
@@ -50,6 +50,7 @@ static LIST_HEAD(slot_list);
#define MY_NAME THIS_MODULE->name
#endif
static
int
debug
;
int
acpiphp_debug
;
/* local variables */
...
...
@@ -62,8 +63,8 @@ static int num_slots;
MODULE_AUTHOR
(
DRIVER_AUTHOR
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
MODULE_PARM
(
acpiphp_
debug
,
"i"
);
MODULE_PARM_DESC
(
acpiphp_
debug
,
"Debugging mode enabled or not"
);
MODULE_PARM
(
debug
,
"i"
);
MODULE_PARM_DESC
(
debug
,
"Debugging mode enabled or not"
);
static
int
enable_slot
(
struct
hotplug_slot
*
slot
);
static
int
disable_slot
(
struct
hotplug_slot
*
slot
);
...
...
@@ -95,15 +96,15 @@ static struct hotplug_slot_ops acpi_hotplug_slot_ops = {
static
inline
int
slot_paranoia_check
(
struct
slot
*
slot
,
const
char
*
function
)
{
if
(
!
slot
)
{
dbg
(
"%s - slot == NULL"
,
function
);
dbg
(
"%s - slot == NULL
\n
"
,
function
);
return
-
1
;
}
if
(
slot
->
magic
!=
SLOT_MAGIC
)
{
dbg
(
"%s - bad magic number for slot"
,
function
);
dbg
(
"%s - bad magic number for slot
\n
"
,
function
);
return
-
1
;
}
if
(
!
slot
->
hotplug_slot
)
{
dbg
(
"%s - slot->hotplug_slot == NULL!"
,
function
);
dbg
(
"%s - slot->hotplug_slot == NULL!
\n
"
,
function
);
return
-
1
;
}
return
0
;
...
...
@@ -115,12 +116,12 @@ static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const ch
struct
slot
*
slot
;
if
(
!
hotplug_slot
)
{
dbg
(
"%s - hotplug_slot == NULL"
,
function
);
dbg
(
"%s - hotplug_slot == NULL
\n
"
,
function
);
return
NULL
;
}
slot
=
(
struct
slot
*
)
hotplug_slot
->
private
;
if
(
slot_paranoia_check
(
slot
,
function
))
if
(
slot_paranoia_check
(
slot
,
function
))
return
NULL
;
return
slot
;
}
...
...
@@ -135,16 +136,16 @@ static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const ch
*/
static
int
enable_slot
(
struct
hotplug_slot
*
hotplug_slot
)
{
struct
slot
*
slot
=
get_slot
(
hotplug_slot
,
__FUNCTION__
);
struct
slot
*
slot
=
get_slot
(
hotplug_slot
,
__FUNCTION__
);
int
retval
=
0
;
if
(
slot
==
NULL
)
return
-
ENODEV
;
dbg
(
"%s - physical_slot = %s
"
,
__FUNCTION__
,
hotplug_slot
->
name
);
dbg
(
"%s - physical_slot = %s
\n
"
,
__FUNCTION__
,
hotplug_slot
->
name
);
/* enable the specified slot */
retval
=
acpiphp_enable_slot
(
slot
->
acpi_slot
);
retval
=
acpiphp_enable_slot
(
slot
->
acpi_slot
);
return
retval
;
}
...
...
@@ -159,16 +160,16 @@ static int enable_slot (struct hotplug_slot *hotplug_slot)
*/
static
int
disable_slot
(
struct
hotplug_slot
*
hotplug_slot
)
{
struct
slot
*
slot
=
get_slot
(
hotplug_slot
,
__FUNCTION__
);
struct
slot
*
slot
=
get_slot
(
hotplug_slot
,
__FUNCTION__
);
int
retval
=
0
;
if
(
slot
==
NULL
)
return
-
ENODEV
;
dbg
(
"%s - physical_slot = %s
"
,
__FUNCTION__
,
hotplug_slot
->
name
);
dbg
(
"%s - physical_slot = %s
\n
"
,
__FUNCTION__
,
hotplug_slot
->
name
);
/* disable the specified slot */
retval
=
acpiphp_disable_slot
(
slot
->
acpi_slot
);
retval
=
acpiphp_disable_slot
(
slot
->
acpi_slot
);
return
retval
;
}
...
...
@@ -186,7 +187,7 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
{
int
retval
=
0
;
dbg
(
"%s - physical_slot = %s
"
,
__FUNCTION__
,
hotplug_slot
->
name
);
dbg
(
"%s - physical_slot = %s
\n
"
,
__FUNCTION__
,
hotplug_slot
->
name
);
switch
(
status
)
{
case
0
:
...
...
@@ -213,15 +214,15 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
*/
static
int
hardware_test
(
struct
hotplug_slot
*
hotplug_slot
,
u32
value
)
{
struct
slot
*
slot
=
get_slot
(
hotplug_slot
,
__FUNCTION__
);
struct
slot
*
slot
=
get_slot
(
hotplug_slot
,
__FUNCTION__
);
int
retval
=
0
;
if
(
slot
==
NULL
)
return
-
ENODEV
;
dbg
(
"%s - physical_slot = %s
"
,
__FUNCTION__
,
hotplug_slot
->
name
);
dbg
(
"%s - physical_slot = %s
\n
"
,
__FUNCTION__
,
hotplug_slot
->
name
);
err
(
"No hardware tests are defined for this driver
"
);
err
(
"No hardware tests are defined for this driver
\n
"
);
retval
=
-
ENODEV
;
return
retval
;
...
...
@@ -239,15 +240,15 @@ static int hardware_test (struct hotplug_slot *hotplug_slot, u32 value)
*/
static
int
get_power_status
(
struct
hotplug_slot
*
hotplug_slot
,
u8
*
value
)
{
struct
slot
*
slot
=
get_slot
(
hotplug_slot
,
__FUNCTION__
);
struct
slot
*
slot
=
get_slot
(
hotplug_slot
,
__FUNCTION__
);
int
retval
=
0
;
if
(
slot
==
NULL
)
return
-
ENODEV
;
dbg
(
"%s - physical_slot = %s"
,
__FUNCTION__
,
hotplug_slot
->
name
);
dbg
(
"%s - physical_slot = %s
\n
"
,
__FUNCTION__
,
hotplug_slot
->
name
);
*
value
=
acpiphp_get_power_status
(
slot
->
acpi_slot
);
*
value
=
acpiphp_get_power_status
(
slot
->
acpi_slot
);
return
retval
;
}
...
...
@@ -264,7 +265,7 @@ static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
{
int
retval
=
0
;
dbg
(
"%s - physical_slot = %s"
,
__FUNCTION__
,
hotplug_slot
->
name
);
dbg
(
"%s - physical_slot = %s
\n
"
,
__FUNCTION__
,
hotplug_slot
->
name
);
*
value
=
hotplug_slot
->
info
->
attention_status
;
...
...
@@ -283,15 +284,15 @@ static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
*/
static
int
get_latch_status
(
struct
hotplug_slot
*
hotplug_slot
,
u8
*
value
)
{
struct
slot
*
slot
=
get_slot
(
hotplug_slot
,
__FUNCTION__
);
struct
slot
*
slot
=
get_slot
(
hotplug_slot
,
__FUNCTION__
);
int
retval
=
0
;
if
(
slot
==
NULL
)
return
-
ENODEV
;
dbg
(
"%s - physical_slot = %s"
,
__FUNCTION__
,
hotplug_slot
->
name
);
dbg
(
"%s - physical_slot = %s
\n
"
,
__FUNCTION__
,
hotplug_slot
->
name
);
*
value
=
acpiphp_get_latch_status
(
slot
->
acpi_slot
);
*
value
=
acpiphp_get_latch_status
(
slot
->
acpi_slot
);
return
retval
;
}
...
...
@@ -308,15 +309,15 @@ static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value)
*/
static
int
get_adapter_status
(
struct
hotplug_slot
*
hotplug_slot
,
u8
*
value
)
{
struct
slot
*
slot
=
get_slot
(
hotplug_slot
,
__FUNCTION__
);
struct
slot
*
slot
=
get_slot
(
hotplug_slot
,
__FUNCTION__
);
int
retval
=
0
;
if
(
slot
==
NULL
)
return
-
ENODEV
;
dbg
(
"%s - physical_slot = %s"
,
__FUNCTION__
,
hotplug_slot
->
name
);
dbg
(
"%s - physical_slot = %s
\n
"
,
__FUNCTION__
,
hotplug_slot
->
name
);
*
value
=
acpiphp_get_adapter_status
(
slot
->
acpi_slot
);
*
value
=
acpiphp_get_adapter_status
(
slot
->
acpi_slot
);
return
retval
;
}
...
...
@@ -325,7 +326,7 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
/* return dummy value because ACPI doesn't provide any method... */
static
int
get_max_bus_speed
(
struct
hotplug_slot
*
hotplug_slot
,
enum
pci_bus_speed
*
value
)
{
struct
slot
*
slot
=
get_slot
(
hotplug_slot
,
__FUNCTION__
);
struct
slot
*
slot
=
get_slot
(
hotplug_slot
,
__FUNCTION__
);
if
(
slot
==
NULL
)
return
-
ENODEV
;
...
...
@@ -339,7 +340,7 @@ static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
/* return dummy value because ACPI doesn't provide any method... */
static
int
get_cur_bus_speed
(
struct
hotplug_slot
*
hotplug_slot
,
enum
pci_bus_speed
*
value
)
{
struct
slot
*
slot
=
get_slot
(
hotplug_slot
,
__FUNCTION__
);
struct
slot
*
slot
=
get_slot
(
hotplug_slot
,
__FUNCTION__
);
if
(
slot
==
NULL
)
return
-
ENODEV
;
...
...
@@ -375,7 +376,7 @@ static int init_acpi (void)
*/
static
void
make_slot_name
(
struct
slot
*
slot
)
{
snprintf
(
slot
->
hotplug_slot
->
name
,
SLOT_NAME_SIZE
,
"ACPI%d-%02x:%02x"
,
snprintf
(
slot
->
hotplug_slot
->
name
,
SLOT_NAME_SIZE
,
"ACPI%d-%02x:%02x"
,
slot
->
acpi_slot
->
sun
,
slot
->
acpi_slot
->
bridge
->
bus
,
slot
->
acpi_slot
->
device
);
...
...
@@ -392,31 +393,31 @@ static int init_slots (void)
int
i
;
for
(
i
=
0
;
i
<
num_slots
;
++
i
)
{
slot
=
kmalloc
(
sizeof
(
struct
slot
),
GFP_KERNEL
);
slot
=
kmalloc
(
sizeof
(
struct
slot
),
GFP_KERNEL
);
if
(
!
slot
)
return
-
ENOMEM
;
memset
(
slot
,
0
,
sizeof
(
struct
slot
));
slot
->
hotplug_slot
=
kmalloc
(
sizeof
(
struct
hotplug_slot
),
GFP_KERNEL
);
slot
->
hotplug_slot
=
kmalloc
(
sizeof
(
struct
hotplug_slot
),
GFP_KERNEL
);
if
(
!
slot
->
hotplug_slot
)
{
kfree
(
slot
);
kfree
(
slot
);
return
-
ENOMEM
;
}
memset
(
slot
->
hotplug_slot
,
0
,
sizeof
(
struct
hotplug_slot
));
memset
(
slot
->
hotplug_slot
,
0
,
sizeof
(
struct
hotplug_slot
));
slot
->
hotplug_slot
->
info
=
kmalloc
(
sizeof
(
struct
hotplug_slot_info
),
GFP_KERNEL
);
slot
->
hotplug_slot
->
info
=
kmalloc
(
sizeof
(
struct
hotplug_slot_info
),
GFP_KERNEL
);
if
(
!
slot
->
hotplug_slot
->
info
)
{
kfree
(
slot
->
hotplug_slot
);
kfree
(
slot
);
kfree
(
slot
->
hotplug_slot
);
kfree
(
slot
);
return
-
ENOMEM
;
}
memset
(
slot
->
hotplug_slot
->
info
,
0
,
sizeof
(
struct
hotplug_slot_info
));
memset
(
slot
->
hotplug_slot
->
info
,
0
,
sizeof
(
struct
hotplug_slot_info
));
slot
->
hotplug_slot
->
name
=
kmalloc
(
SLOT_NAME_SIZE
,
GFP_KERNEL
);
slot
->
hotplug_slot
->
name
=
kmalloc
(
SLOT_NAME_SIZE
,
GFP_KERNEL
);
if
(
!
slot
->
hotplug_slot
->
name
)
{
kfree
(
slot
->
hotplug_slot
->
info
);
kfree
(
slot
->
hotplug_slot
);
kfree
(
slot
);
kfree
(
slot
->
hotplug_slot
->
info
);
kfree
(
slot
->
hotplug_slot
);
kfree
(
slot
);
return
-
ENOMEM
;
}
...
...
@@ -426,27 +427,27 @@ static int init_slots (void)
slot
->
hotplug_slot
->
private
=
slot
;
slot
->
hotplug_slot
->
ops
=
&
acpi_hotplug_slot_ops
;
slot
->
acpi_slot
=
get_slot_from_id
(
i
);
slot
->
acpi_slot
=
get_slot_from_id
(
i
);
slot
->
hotplug_slot
->
info
->
power_status
=
acpiphp_get_power_status
(
slot
->
acpi_slot
);
slot
->
hotplug_slot
->
info
->
attention_status
=
acpiphp_get_attention_status
(
slot
->
acpi_slot
);
slot
->
hotplug_slot
->
info
->
latch_status
=
acpiphp_get_latch_status
(
slot
->
acpi_slot
);
slot
->
hotplug_slot
->
info
->
adapter_status
=
acpiphp_get_adapter_status
(
slot
->
acpi_slot
);
make_slot_name
(
slot
);
make_slot_name
(
slot
);
retval
=
pci_hp_register
(
slot
->
hotplug_slot
);
retval
=
pci_hp_register
(
slot
->
hotplug_slot
);
if
(
retval
)
{
err
(
"pci_hp_register failed with error %d
"
,
retval
);
kfree
(
slot
->
hotplug_slot
->
info
);
kfree
(
slot
->
hotplug_slot
->
name
);
kfree
(
slot
->
hotplug_slot
);
kfree
(
slot
);
err
(
"pci_hp_register failed with error %d
\n
"
,
retval
);
kfree
(
slot
->
hotplug_slot
->
info
);
kfree
(
slot
->
hotplug_slot
->
name
);
kfree
(
slot
->
hotplug_slot
);
kfree
(
slot
);
return
retval
;
}
/* add slot to our internal list */
list_add
(
&
slot
->
slot_list
,
&
slot_list
);
info
(
"Slot [%s] registered"
,
slot
->
hotplug_slot
->
name
);
list_add
(
&
slot
->
slot_list
,
&
slot_list
);
info
(
"Slot [%s] registered
\n
"
,
slot
->
hotplug_slot
->
name
);
}
return
retval
;
...
...
@@ -459,13 +460,13 @@ static void cleanup_slots (void)
struct
slot
*
slot
;
list_for_each_safe
(
tmp
,
n
,
&
slot_list
)
{
slot
=
list_entry
(
tmp
,
struct
slot
,
slot_list
);
list_del
(
&
slot
->
slot_list
);
pci_hp_deregister
(
slot
->
hotplug_slot
);
kfree
(
slot
->
hotplug_slot
->
info
);
kfree
(
slot
->
hotplug_slot
->
name
);
kfree
(
slot
->
hotplug_slot
);
kfree
(
slot
);
slot
=
list_entry
(
tmp
,
struct
slot
,
slot_list
);
list_del
(
&
slot
->
slot_list
);
pci_hp_deregister
(
slot
->
hotplug_slot
);
kfree
(
slot
->
hotplug_slot
->
info
);
kfree
(
slot
->
hotplug_slot
->
name
);
kfree
(
slot
->
hotplug_slot
);
kfree
(
slot
);
}
return
;
...
...
@@ -476,7 +477,9 @@ static int __init acpiphp_init(void)
{
int
retval
;
info
(
DRIVER_DESC
" version: "
DRIVER_VERSION
);
info
(
DRIVER_DESC
" version: "
DRIVER_VERSION
"
\n
"
);
acpiphp_debug
=
debug
;
/* read all the ACPI info from the system */
retval
=
init_acpi
();
...
...
drivers/hotplug/acpiphp_glue.c
View file @
82670e1f
...
...
@@ -153,7 +153,7 @@ register_slot (acpi_handle handle, u32 lvl, void *context, void **rv)
for
(
slot
=
bridge
->
slots
;
slot
;
slot
=
slot
->
next
)
if
(
slot
->
device
==
device
)
{
if
(
slot
->
sun
!=
sun
)
warn
(
"sibling found, but _SUN doesn't match!"
);
warn
(
"sibling found, but _SUN doesn't match!
\n
"
);
break
;
}
...
...
@@ -177,7 +177,7 @@ register_slot (acpi_handle handle, u32 lvl, void *context, void **rv)
bridge
->
nr_slots
++
;
dbg
(
"found ACPI PCI Hotplug slot at PCI %02x:%02x Slot:
0x%x
"
,
dbg
(
"found ACPI PCI Hotplug slot at PCI %02x:%02x Slot:
%d
\n
"
,
slot
->
bridge
->
bus
,
slot
->
device
,
slot
->
sun
);
}
...
...
@@ -202,7 +202,7 @@ register_slot (acpi_handle handle, u32 lvl, void *context, void **rv)
newfunc
);
if
(
ACPI_FAILURE
(
status
))
{
err
(
"failed to register interrupt notify handler"
);
err
(
"failed to register interrupt notify handler
\n
"
);
return
status
;
}
...
...
@@ -302,21 +302,21 @@ decode_acpi_resource (acpi_resource *resource, struct acpiphp_bridge *bridge)
switch
(
resource_type
)
{
case
ACPI_MEMORY_RANGE
:
if
(
cache_attribute
==
ACPI_PREFETCHABLE_MEMORY
)
{
dbg
(
"resource type: prefetchable memory 0x%x - 0x%x"
,
(
u32
)
min_address_range
,
(
u32
)
max_address_range
);
dbg
(
"resource type: prefetchable memory 0x%x - 0x%x
\n
"
,
(
u32
)
min_address_range
,
(
u32
)
max_address_range
);
res
=
acpiphp_make_resource
(
min_address_range
,
address_length
);
if
(
!
res
)
{
err
(
"out of memory"
);
err
(
"out of memory
\n
"
);
return
;
}
res
->
next
=
bridge
->
p_mem_head
;
bridge
->
p_mem_head
=
res
;
}
else
{
dbg
(
"resource type: memory 0x%x - 0x%x"
,
(
u32
)
min_address_range
,
(
u32
)
max_address_range
);
dbg
(
"resource type: memory 0x%x - 0x%x
\n
"
,
(
u32
)
min_address_range
,
(
u32
)
max_address_range
);
res
=
acpiphp_make_resource
(
min_address_range
,
address_length
);
if
(
!
res
)
{
err
(
"out of memory"
);
err
(
"out of memory
\n
"
);
return
;
}
res
->
next
=
bridge
->
mem_head
;
...
...
@@ -324,22 +324,22 @@ decode_acpi_resource (acpi_resource *resource, struct acpiphp_bridge *bridge)
}
break
;
case
ACPI_IO_RANGE
:
dbg
(
"resource type: io 0x%x - 0x%x"
,
(
u32
)
min_address_range
,
(
u32
)
max_address_range
);
dbg
(
"resource type: io 0x%x - 0x%x
\n
"
,
(
u32
)
min_address_range
,
(
u32
)
max_address_range
);
res
=
acpiphp_make_resource
(
min_address_range
,
address_length
);
if
(
!
res
)
{
err
(
"out of memory"
);
err
(
"out of memory
\n
"
);
return
;
}
res
->
next
=
bridge
->
io_head
;
bridge
->
io_head
=
res
;
break
;
case
ACPI_BUS_NUMBER_RANGE
:
dbg
(
"resource type: bus number %d - %d"
,
(
u32
)
min_address_range
,
(
u32
)
max_address_range
);
dbg
(
"resource type: bus number %d - %d
\n
"
,
(
u32
)
min_address_range
,
(
u32
)
max_address_range
);
res
=
acpiphp_make_resource
(
min_address_range
,
address_length
);
if
(
!
res
)
{
err
(
"out of memory"
);
err
(
"out of memory
\n
"
);
return
;
}
res
->
next
=
bridge
->
bus_head
;
...
...
@@ -356,10 +356,9 @@ decode_acpi_resource (acpi_resource *resource, struct acpiphp_bridge *bridge)
acpiphp_resource_sort_and_combine
(
&
bridge
->
mem_head
);
acpiphp_resource_sort_and_combine
(
&
bridge
->
p_mem_head
);
acpiphp_resource_sort_and_combine
(
&
bridge
->
bus_head
);
#if 1
info
(
"ACPI _CRS resource:
"
);
dbg
(
"ACPI _CRS resource:
\n
"
);
acpiphp_dump_resource
(
bridge
);
#endif
}
...
...
@@ -368,7 +367,7 @@ static struct pci_bus *find_pci_bus(const struct list_head *list, int bus)
{
const
struct
list_head
*
l
;
list_for_each
(
l
,
list
)
{
list_for_each
(
l
,
list
)
{
struct
pci_bus
*
b
=
pci_bus_b
(
l
);
if
(
b
->
number
==
bus
)
return
b
;
...
...
@@ -404,7 +403,7 @@ static void decode_hpp(struct acpiphp_bridge *bridge)
status
=
acpi_evaluate_object
(
bridge
->
handle
,
"_HPP"
,
NULL
,
&
buffer
);
if
(
ACPI_FAILURE
(
status
))
{
dbg
(
"_HPP evaluation failed"
);
dbg
(
"_HPP evaluation failed
\n
"
);
return
;
}
...
...
@@ -412,13 +411,13 @@ static void decode_hpp(struct acpiphp_bridge *bridge)
if
(
!
package
||
package
->
type
!=
ACPI_TYPE_PACKAGE
||
package
->
package
.
count
!=
4
||
!
package
->
package
.
elements
)
{
err
(
"invalid _HPP object; ignoring"
);
err
(
"invalid _HPP object; ignoring
\n
"
);
goto
err_exit
;
}
for
(
i
=
0
;
i
<
4
;
i
++
)
{
if
(
package
->
package
.
elements
[
i
].
type
!=
ACPI_TYPE_INTEGER
)
{
err
(
"invalid _HPP parameter type; ignoring"
);
err
(
"invalid _HPP parameter type; ignoring
\n
"
);
goto
err_exit
;
}
}
...
...
@@ -428,7 +427,7 @@ static void decode_hpp(struct acpiphp_bridge *bridge)
bridge
->
hpp
.
enable_SERR
=
package
->
package
.
elements
[
2
].
integer
.
value
;
bridge
->
hpp
.
enable_PERR
=
package
->
package
.
elements
[
3
].
integer
.
value
;
dbg
(
"_HPP parameter = (%02x, %02x, %02x, %02x)"
,
dbg
(
"_HPP parameter = (%02x, %02x, %02x, %02x)
\n
"
,
bridge
->
hpp
.
cache_line_size
,
bridge
->
hpp
.
latency_timer
,
bridge
->
hpp
.
enable_SERR
,
...
...
@@ -463,15 +462,13 @@ static void init_bridge_misc (struct acpiphp_bridge *bridge)
bridge
);
if
(
ACPI_FAILURE
(
status
))
{
err
(
"failed to register interrupt notify handler"
);
err
(
"failed to register interrupt notify handler
\n
"
);
}
list_add
(
&
bridge
->
list
,
&
bridge_list
);
#if 1
dbg
(
"Bridge resource:"
);
dbg
(
"Bridge resource:
\n
"
);
acpiphp_dump_resource
(
bridge
);
#endif
}
...
...
@@ -507,7 +504,7 @@ static void add_host_bridge (acpi_handle *handle, int seg, int bus)
status
=
acpi_get_current_resources
(
handle
,
&
buffer
);
if
(
ACPI_FAILURE
(
status
))
{
err
(
"failed to decode bridge resources"
);
err
(
"failed to decode bridge resources
\n
"
);
kfree
(
bridge
);
return
;
}
...
...
@@ -535,7 +532,7 @@ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int
bridge
=
kmalloc
(
sizeof
(
struct
acpiphp_bridge
),
GFP_KERNEL
);
if
(
bridge
==
NULL
)
{
err
(
"out of memory"
);
err
(
"out of memory
\n
"
);
return
;
}
...
...
@@ -547,14 +544,14 @@ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int
bridge
->
pci_dev
=
pci_find_slot
(
bus
,
PCI_DEVFN
(
dev
,
fn
));
if
(
!
bridge
->
pci_dev
)
{
err
(
"Can't get pci_dev"
);
err
(
"Can't get pci_dev
\n
"
);
kfree
(
bridge
);
return
;
}
bridge
->
pci_bus
=
bridge
->
pci_dev
->
subordinate
;
if
(
!
bridge
->
pci_bus
)
{
err
(
"This is not a PCI-to-PCI bridge!"
);
err
(
"This is not a PCI-to-PCI bridge!
\n
"
);
kfree
(
bridge
);
return
;
}
...
...
@@ -580,10 +577,10 @@ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int
limit
=
((
limit
<<
8
)
&
0xf000
)
+
0xfff
;
bridge
->
io_head
=
acpiphp_make_resource
((
u64
)
base
,
limit
-
base
+
1
);
if
(
!
bridge
->
io_head
)
{
err
(
"out of memory"
);
err
(
"out of memory
\n
"
);
return
;
}
dbg
(
"16bit I/O range: %04x-%04x"
,
dbg
(
"16bit I/O range: %04x-%04x
\n
"
,
(
u32
)
bridge
->
io_head
->
base
,
(
u32
)(
bridge
->
io_head
->
base
+
bridge
->
io_head
->
length
-
1
));
break
;
...
...
@@ -594,18 +591,18 @@ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int
limit
=
(((
u32
)
tmp16
<<
16
)
|
((
limit
<<
8
)
&
0xf000
))
+
0xfff
;
bridge
->
io_head
=
acpiphp_make_resource
((
u64
)
base
,
limit
-
base
+
1
);
if
(
!
bridge
->
io_head
)
{
err
(
"out of memory"
);
err
(
"out of memory
\n
"
);
return
;
}
dbg
(
"32bit I/O range: %08x-%08x"
,
dbg
(
"32bit I/O range: %08x-%08x
\n
"
,
(
u32
)
bridge
->
io_head
->
base
,
(
u32
)(
bridge
->
io_head
->
base
+
bridge
->
io_head
->
length
-
1
));
break
;
case
0x0f
:
dbg
(
"I/O space unsupported"
);
dbg
(
"I/O space unsupported
\n
"
);
break
;
default:
warn
(
"Unknown I/O range type"
);
warn
(
"Unknown I/O range type
\n
"
);
}
/* Memory resources (mandatory for P2P bridge) */
...
...
@@ -615,10 +612,10 @@ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int
limit
=
((
tmp16
&
0xfff0
)
<<
16
)
|
0xfffff
;
bridge
->
mem_head
=
acpiphp_make_resource
((
u64
)
base
,
limit
-
base
+
1
);
if
(
!
bridge
->
mem_head
)
{
err
(
"out of memory"
);
err
(
"out of memory
\n
"
);
return
;
}
dbg
(
"32bit Memory range: %08x-%08x"
,
dbg
(
"32bit Memory range: %08x-%08x
\n
"
,
(
u32
)
bridge
->
mem_head
->
base
,
(
u32
)(
bridge
->
mem_head
->
base
+
bridge
->
mem_head
->
length
-
1
));
...
...
@@ -634,10 +631,10 @@ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int
limit
=
((
limit
&
0xfff0
)
<<
16
)
|
0xfffff
;
bridge
->
p_mem_head
=
acpiphp_make_resource
((
u64
)
base
,
limit
-
base
+
1
);
if
(
!
bridge
->
p_mem_head
)
{
err
(
"out of memory"
);
err
(
"out of memory
\n
"
);
return
;
}
dbg
(
"32bit Prefetchable memory range: %08x-%08x"
,
dbg
(
"32bit Prefetchable memory range: %08x-%08x
\n
"
,
(
u32
)
bridge
->
p_mem_head
->
base
,
(
u32
)(
bridge
->
p_mem_head
->
base
+
bridge
->
p_mem_head
->
length
-
1
));
break
;
...
...
@@ -649,10 +646,10 @@ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int
bridge
->
p_mem_head
=
acpiphp_make_resource
(
base64
,
limit64
-
base64
+
1
);
if
(
!
bridge
->
p_mem_head
)
{
err
(
"out of memory"
);
err
(
"out of memory
\n
"
);
return
;
}
dbg
(
"64bit Prefetchable memory range: %08x%08x-%08x%08x"
,
dbg
(
"64bit Prefetchable memory range: %08x%08x-%08x%08x
\n
"
,
(
u32
)(
bridge
->
p_mem_head
->
base
>>
32
),
(
u32
)(
bridge
->
p_mem_head
->
base
&
0xffffffff
),
(
u32
)((
bridge
->
p_mem_head
->
base
+
bridge
->
p_mem_head
->
length
-
1
)
>>
32
),
...
...
@@ -661,7 +658,7 @@ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int
case
0x0f
:
break
;
default:
warn
(
"Unknown prefetchale memory type"
);
warn
(
"Unknown prefetchale memory type
\n
"
);
}
init_bridge_misc
(
bridge
);
...
...
@@ -689,7 +686,7 @@ find_p2p_bridge (acpi_handle handle, u32 lvl, void *context, void **rv)
status
=
acpi_evaluate_integer
(
handle
,
"_ADR"
,
NULL
,
&
tmp
);
if
(
ACPI_FAILURE
(
status
))
{
dbg
(
"%s: _ADR evaluation failure"
,
__FUNCTION__
);
dbg
(
"%s: _ADR evaluation failure
\n
"
,
__FUNCTION__
);
return
AE_OK
;
}
...
...
@@ -706,7 +703,7 @@ find_p2p_bridge (acpi_handle handle, u32 lvl, void *context, void **rv)
/* check if this bridge has ejectable slots */
if
(
detect_ejectable_slots
(
handle
)
>
0
)
{
dbg
(
"found PCI-to-PCI bridge at PCI %
02x:%02x.%d"
,
bus
,
device
,
function
);
dbg
(
"found PCI-to-PCI bridge at PCI %
s
\n
"
,
dev
->
slot_name
);
add_p2p_bridge
(
handle
,
seg
,
bus
,
device
,
function
);
}
...
...
@@ -727,7 +724,7 @@ static int add_bridges (acpi_handle *handle)
if
(
ACPI_SUCCESS
(
status
))
{
status
=
acpi_evaluate_integer
(
handle
,
"_STA"
,
NULL
,
&
tmp
);
if
(
ACPI_FAILURE
(
status
))
{
dbg
(
"%s: _STA evaluation failure"
,
__FUNCTION__
);
dbg
(
"%s: _STA evaluation failure
\n
"
,
__FUNCTION__
);
return
0
;
}
if
((
tmp
&
ACPI_STA_FUNCTIONING
)
==
0
)
...
...
@@ -746,13 +743,13 @@ static int add_bridges (acpi_handle *handle)
if
(
ACPI_SUCCESS
(
status
))
{
bus
=
tmp
;
}
else
{
warn
(
"can't get bus number, assuming 0"
);
warn
(
"can't get bus number, assuming 0
\n
"
);
bus
=
0
;
}
/* check if this bridge has ejectable slots */
if
(
detect_ejectable_slots
(
handle
)
>
0
)
{
dbg
(
"found PCI host-bus bridge with hot-pluggable slots"
);
dbg
(
"found PCI host-bus bridge with hot-pluggable slots
\n
"
);
add_host_bridge
(
handle
,
seg
,
bus
);
return
0
;
}
...
...
@@ -764,7 +761,7 @@ static int add_bridges (acpi_handle *handle)
find_p2p_bridge
,
&
tmp
,
NULL
);
if
(
ACPI_FAILURE
(
status
))
warn
(
"find_p2p_bridge faied (error code = 0x%x)"
,
status
);
warn
(
"find_p2p_bridge faied (error code = 0x%x)
\n
"
,
status
);
return
0
;
}
...
...
@@ -782,7 +779,7 @@ find_host_bridge (acpi_handle handle, u32 lvl, void *context, void **rv)
status
=
acpi_get_object_info
(
handle
,
&
info
);
if
(
ACPI_FAILURE
(
status
))
{
dbg
(
"%s: failed to get bridge information"
,
__FUNCTION__
);
dbg
(
"%s: failed to get bridge information
\n
"
,
__FUNCTION__
);
return
AE_OK
;
/* continue */
}
...
...
@@ -793,7 +790,7 @@ find_host_bridge (acpi_handle handle, u32 lvl, void *context, void **rv)
(
info
.
valid
&
ACPI_VALID_HID
)
&&
strcmp
(
info
.
hardware_id
,
ACPI_PCI_HOST_HID
)
==
0
)
{
acpi_get_name
(
handle
,
ACPI_SINGLE_NAME
,
&
buffer
);
dbg
(
"checking PCI-hotplug capable bridges under [%s]"
,
objname
);
dbg
(
"checking PCI-hotplug capable bridges under [%s]
\n
"
,
objname
);
add_bridges
(
handle
);
}
return
AE_OK
;
...
...
@@ -811,15 +808,15 @@ static int power_on_slot (struct acpiphp_slot *slot)
if
(
slot
->
flags
&
SLOT_POWEREDON
)
goto
err_exit
;
list_for_each
(
l
,
&
slot
->
funcs
)
{
list_for_each
(
l
,
&
slot
->
funcs
)
{
func
=
list_entry
(
l
,
struct
acpiphp_func
,
sibling
);
if
(
func
->
flags
&
FUNC_HAS_PS0
)
{
dbg
(
"%s: executing _PS0 on %
02x:%02x.%d
"
,
__FUNCTION__
,
slot
->
bridge
->
bus
,
slot
->
device
,
func
->
function
);
dbg
(
"%s: executing _PS0 on %
s
\n
"
,
__FUNCTION__
,
func
->
pci_dev
->
slot_name
);
status
=
acpi_evaluate_object
(
func
->
handle
,
"_PS0"
,
NULL
,
NULL
);
if
(
ACPI_FAILURE
(
status
))
{
warn
(
"%s: _PS0 failed"
,
__FUNCTION__
);
warn
(
"%s: _PS0 failed
\n
"
,
__FUNCTION__
);
retval
=
-
1
;
goto
err_exit
;
}
...
...
@@ -849,27 +846,27 @@ static int power_off_slot (struct acpiphp_slot *slot)
if
((
slot
->
flags
&
SLOT_POWEREDON
)
==
0
)
goto
err_exit
;
list_for_each
(
l
,
&
slot
->
funcs
)
{
list_for_each
(
l
,
&
slot
->
funcs
)
{
func
=
list_entry
(
l
,
struct
acpiphp_func
,
sibling
);
if
(
func
->
flags
&
FUNC_HAS_PS3
)
{
dbg
(
"%s: executing _PS3 on %
02x:%02x.%d
"
,
__FUNCTION__
,
slot
->
bridge
->
bus
,
slot
->
device
,
func
->
function
);
dbg
(
"%s: executing _PS3 on %
s
\n
"
,
__FUNCTION__
,
func
->
pci_dev
->
slot_name
);
status
=
acpi_evaluate_object
(
func
->
handle
,
"_PS3"
,
NULL
,
NULL
);
if
(
ACPI_FAILURE
(
status
))
{
warn
(
"%s: _PS3 failed"
,
__FUNCTION__
);
warn
(
"%s: _PS3 failed
\n
"
,
__FUNCTION__
);
retval
=
-
1
;
goto
err_exit
;
}
}
}
list_for_each
(
l
,
&
slot
->
funcs
)
{
list_for_each
(
l
,
&
slot
->
funcs
)
{
func
=
list_entry
(
l
,
struct
acpiphp_func
,
sibling
);
if
(
func
->
flags
&
FUNC_HAS_EJ0
)
{
dbg
(
"%s: executing _EJ0 on %
02x:%02x.%d
"
,
__FUNCTION__
,
slot
->
bridge
->
bus
,
slot
->
device
,
func
->
function
);
dbg
(
"%s: executing _EJ0 on %
s
\n
"
,
__FUNCTION__
,
func
->
pci_dev
->
slot_name
);
/* _EJ0 method take one argument */
arg_list
.
count
=
1
;
...
...
@@ -879,7 +876,7 @@ static int power_off_slot (struct acpiphp_slot *slot)
status
=
acpi_evaluate_object
(
func
->
handle
,
"_EJ0"
,
&
arg_list
,
NULL
);
if
(
ACPI_FAILURE
(
status
))
{
warn
(
"%s: _EJ0 failed"
,
__FUNCTION__
);
warn
(
"%s: _EJ0 failed
\n
"
,
__FUNCTION__
);
retval
=
-
1
;
goto
err_exit
;
}
...
...
@@ -919,7 +916,7 @@ static int enable_device (struct acpiphp_slot *slot)
dev
=
pci_find_slot
(
slot
->
bridge
->
bus
,
PCI_DEVFN
(
slot
->
device
,
0
));
if
(
dev
)
{
/* This case shouldn't happen */
err
(
"pci_dev structure already exists."
);
err
(
"pci_dev structure already exists.
\n
"
);
retval
=
-
1
;
goto
err_exit
;
}
...
...
@@ -941,7 +938,7 @@ static int enable_device (struct acpiphp_slot *slot)
dev
=
pci_scan_slot
(
&
dev0
);
if
(
!
dev
)
{
err
(
"No new device found"
);
err
(
"No new device found
\n
"
);
retval
=
-
1
;
goto
err_exit
;
}
...
...
@@ -953,7 +950,7 @@ static int enable_device (struct acpiphp_slot *slot)
}
/* associate pci_dev to our representation */
list_for_each
(
l
,
&
slot
->
funcs
)
{
list_for_each
(
l
,
&
slot
->
funcs
)
{
func
=
list_entry
(
l
,
struct
acpiphp_func
,
sibling
);
func
->
pci_dev
=
pci_find_slot
(
slot
->
bridge
->
bus
,
...
...
@@ -970,10 +967,8 @@ static int enable_device (struct acpiphp_slot *slot)
slot
->
flags
|=
SLOT_ENABLED
;
#if 1
dbg
(
"Available resources:"
);
dbg
(
"Available resources:
\n
"
);
acpiphp_dump_resource
(
slot
->
bridge
);
#endif
err_exit:
return
retval
;
...
...
@@ -993,14 +988,14 @@ static int disable_device (struct acpiphp_slot *slot)
if
(
!
(
slot
->
flags
&
SLOT_ENABLED
))
goto
err_exit
;
list_for_each
(
l
,
&
slot
->
funcs
)
{
list_for_each
(
l
,
&
slot
->
funcs
)
{
func
=
list_entry
(
l
,
struct
acpiphp_func
,
sibling
);
if
(
func
->
pci_dev
)
{
if
(
acpiphp_unconfigure_function
(
func
)
==
0
)
{
func
->
pci_dev
=
NULL
;
}
else
{
err
(
"failed to unconfigure device"
);
err
(
"failed to unconfigure device
\n
"
);
retval
=
-
1
;
goto
err_exit
;
}
...
...
@@ -1033,7 +1028,7 @@ static unsigned int get_slot_status (struct acpiphp_slot *slot)
struct
list_head
*
l
;
struct
acpiphp_func
*
func
;
list_for_each
(
l
,
&
slot
->
funcs
)
{
list_for_each
(
l
,
&
slot
->
funcs
)
{
func
=
list_entry
(
l
,
struct
acpiphp_func
,
sibling
);
if
(
func
->
flags
&
FUNC_HAS_STA
)
{
...
...
@@ -1084,28 +1079,28 @@ static void handle_hotplug_event_bridge (acpi_handle handle, u32 type, void *con
switch
(
type
)
{
case
ACPI_NOTIFY_BUS_CHECK
:
/* bus re-enumerate */
dbg
(
"%s: Bus check notify on %s"
,
__FUNCTION__
,
objname
);
dbg
(
"%s: Bus check notify on %s
\n
"
,
__FUNCTION__
,
objname
);
acpiphp_check_bridge
(
bridge
);
break
;
case
ACPI_NOTIFY_DEVICE_CHECK
:
/* device check */
dbg
(
"%s: Device check notify on %s"
,
__FUNCTION__
,
objname
);
dbg
(
"%s: Device check notify on %s
\n
"
,
__FUNCTION__
,
objname
);
acpiphp_check_bridge
(
bridge
);
break
;
case
ACPI_NOTIFY_DEVICE_WAKE
:
/* wake event */
dbg
(
"%s: Device wake notify on %s"
,
__FUNCTION__
,
objname
);
dbg
(
"%s: Device wake notify on %s
\n
"
,
__FUNCTION__
,
objname
);
break
;
case
ACPI_NOTIFY_EJECT_REQUEST
:
/* request device eject */
dbg
(
"%s: Device eject notify on %s"
,
__FUNCTION__
,
objname
);
dbg
(
"%s: Device eject notify on %s
\n
"
,
__FUNCTION__
,
objname
);
break
;
default:
warn
(
"notify_handler: unknown event type 0x%x for %s"
,
type
,
objname
);
warn
(
"notify_handler: unknown event type 0x%x for %s
\n
"
,
type
,
objname
);
break
;
}
}
...
...
@@ -1135,29 +1130,29 @@ static void handle_hotplug_event_func (acpi_handle handle, u32 type, void *conte
switch
(
type
)
{
case
ACPI_NOTIFY_BUS_CHECK
:
/* bus re-enumerate */
dbg
(
"%s: Bus check notify on %s"
,
__FUNCTION__
,
objname
);
dbg
(
"%s: Bus check notify on %s
\n
"
,
__FUNCTION__
,
objname
);
acpiphp_enable_slot
(
func
->
slot
);
break
;
case
ACPI_NOTIFY_DEVICE_CHECK
:
/* device check : re-enumerate from parent bus */
dbg
(
"%s: Device check notify on %s"
,
__FUNCTION__
,
objname
);
dbg
(
"%s: Device check notify on %s
\n
"
,
__FUNCTION__
,
objname
);
acpiphp_check_bridge
(
func
->
slot
->
bridge
);
break
;
case
ACPI_NOTIFY_DEVICE_WAKE
:
/* wake event */
dbg
(
"%s: Device wake notify on %s"
,
__FUNCTION__
,
objname
);
dbg
(
"%s: Device wake notify on %s
\n
"
,
__FUNCTION__
,
objname
);
break
;
case
ACPI_NOTIFY_EJECT_REQUEST
:
/* request device eject */
dbg
(
"%s: Device eject notify on %s"
,
__FUNCTION__
,
objname
);
dbg
(
"%s: Device eject notify on %s
\n
"
,
__FUNCTION__
,
objname
);
acpiphp_disable_slot
(
func
->
slot
);
break
;
default:
warn
(
"notify_handler: unknown event type 0x%x for %s"
,
type
,
objname
);
warn
(
"notify_handler: unknown event type 0x%x for %s
\n
"
,
type
,
objname
);
break
;
}
}
...
...
@@ -1179,7 +1174,7 @@ int acpiphp_glue_init (void)
NULL
,
NULL
);
if
(
ACPI_FAILURE
(
status
))
{
err
(
"%s: acpi_walk_namespace() failed"
,
__FUNCTION__
);
err
(
"%s: acpi_walk_namespace() failed
\n
"
,
__FUNCTION__
);
return
-
1
;
}
...
...
@@ -1200,12 +1195,12 @@ void acpiphp_glue_exit (void)
struct
acpiphp_func
*
func
;
acpi_status
status
;
list_for_each_safe
(
l1
,
n1
,
&
bridge_list
)
{
list_for_each_safe
(
l1
,
n1
,
&
bridge_list
)
{
bridge
=
(
struct
acpiphp_bridge
*
)
l1
;
slot
=
bridge
->
slots
;
while
(
slot
)
{
next
=
slot
->
next
;
list_for_each_safe
(
l2
,
n2
,
&
slot
->
funcs
)
{
list_for_each_safe
(
l2
,
n2
,
&
slot
->
funcs
)
{
func
=
list_entry
(
l2
,
struct
acpiphp_func
,
sibling
);
acpiphp_free_resource
(
&
func
->
io_head
);
acpiphp_free_resource
(
&
func
->
mem_head
);
...
...
@@ -1215,7 +1210,7 @@ void acpiphp_glue_exit (void)
ACPI_SYSTEM_NOTIFY
,
handle_hotplug_event_func
);
if
(
ACPI_FAILURE
(
status
))
err
(
"failed to remove notify handler"
);
err
(
"failed to remove notify handler
\n
"
);
kfree
(
func
);
}
kfree
(
slot
);
...
...
@@ -1224,7 +1219,7 @@ void acpiphp_glue_exit (void)
status
=
acpi_remove_notify_handler
(
bridge
->
handle
,
ACPI_SYSTEM_NOTIFY
,
handle_hotplug_event_bridge
);
if
(
ACPI_FAILURE
(
status
))
err
(
"failed to remove notify handler"
);
err
(
"failed to remove notify handler
\n
"
);
acpiphp_free_resource
(
&
bridge
->
io_head
);
acpiphp_free_resource
(
&
bridge
->
mem_head
);
...
...
@@ -1247,13 +1242,13 @@ int acpiphp_get_num_slots (void)
num_slots
=
0
;
list_for_each
(
node
,
&
bridge_list
)
{
list_for_each
(
node
,
&
bridge_list
)
{
bridge
=
(
struct
acpiphp_bridge
*
)
node
;
dbg
(
"Bus%d %dslot(s)"
,
bridge
->
bus
,
bridge
->
nr_slots
);
dbg
(
"Bus%d %dslot(s)
\n
"
,
bridge
->
bus
,
bridge
->
nr_slots
);
num_slots
+=
bridge
->
nr_slots
;
}
dbg
(
"Total %dslots"
,
num_slots
);
dbg
(
"Total %dslots
\n
"
,
num_slots
);
return
num_slots
;
}
...
...
@@ -1271,7 +1266,7 @@ int acpiphp_for_each_slot(acpiphp_callback fn, void *data)
struct
acpiphp_slot
*
slot
;
int
retval
=
0
;
list_for_each
(
node
,
&
bridge_list
)
{
list_for_each
(
node
,
&
bridge_list
)
{
bridge
=
(
struct
acpiphp_bridge
*
)
node
;
for
(
slot
=
bridge
->
slots
;
slot
;
slot
=
slot
->
next
)
{
retval
=
fn
(
slot
,
data
);
...
...
@@ -1292,7 +1287,7 @@ struct acpiphp_slot *get_slot_from_id (int id)
struct
acpiphp_bridge
*
bridge
;
struct
acpiphp_slot
*
slot
;
list_for_each
(
node
,
&
bridge_list
)
{
list_for_each
(
node
,
&
bridge_list
)
{
bridge
=
(
struct
acpiphp_bridge
*
)
node
;
for
(
slot
=
bridge
->
slots
;
slot
;
slot
=
slot
->
next
)
if
(
slot
->
id
==
id
)
...
...
@@ -1300,7 +1295,7 @@ struct acpiphp_slot *get_slot_from_id (int id)
}
/* should never happen! */
err
(
"%s: no object for id %d"
,
__FUNCTION__
,
id
);
err
(
"%s: no object for id %d
\n
"
,
__FUNCTION__
,
id
);
return
0
;
}
...
...
@@ -1352,7 +1347,7 @@ int acpiphp_disable_slot (struct acpiphp_slot *slot)
acpiphp_resource_sort_and_combine
(
&
slot
->
bridge
->
mem_head
);
acpiphp_resource_sort_and_combine
(
&
slot
->
bridge
->
p_mem_head
);
acpiphp_resource_sort_and_combine
(
&
slot
->
bridge
->
bus_head
);
dbg
(
"Available resources:"
);
dbg
(
"Available resources:
\n
"
);
acpiphp_dump_resource
(
slot
->
bridge
);
err_exit:
...
...
@@ -1380,7 +1375,7 @@ int acpiphp_check_bridge (struct acpiphp_bridge *bridge)
if
(
sta
!=
ACPI_STA_ALL
)
{
retval
=
acpiphp_disable_slot
(
slot
);
if
(
retval
)
{
err
(
"Error occured in enabling"
);
err
(
"Error occured in enabling
\n
"
);
up
(
&
slot
->
crit_sect
);
goto
err_exit
;
}
...
...
@@ -1391,7 +1386,7 @@ int acpiphp_check_bridge (struct acpiphp_bridge *bridge)
if
(
sta
==
ACPI_STA_ALL
)
{
retval
=
acpiphp_enable_slot
(
slot
);
if
(
retval
)
{
err
(
"Error occured in enabling"
);
err
(
"Error occured in enabling
\n
"
);
up
(
&
slot
->
crit_sect
);
goto
err_exit
;
}
...
...
@@ -1400,7 +1395,7 @@ int acpiphp_check_bridge (struct acpiphp_bridge *bridge)
}
}
dbg
(
"%s: %d enabled, %d disabled"
,
__FUNCTION__
,
enabled
,
disabled
);
dbg
(
"%s: %d enabled, %d disabled
\n
"
,
__FUNCTION__
,
enabled
,
disabled
);
err_exit:
return
retval
;
...
...
drivers/hotplug/acpiphp_pci.c
View file @
82670e1f
...
...
@@ -77,7 +77,7 @@ static int init_config_space (struct acpiphp_func *func)
if
(
!
bar
)
/* This BAR is not implemented */
continue
;
dbg
(
"Device %02x.%02x BAR %d wants %x"
,
device
,
function
,
count
,
bar
);
dbg
(
"Device %02x.%02x BAR %d wants %x
\n
"
,
device
,
function
,
count
,
bar
);
if
(
bar
&
PCI_BASE_ADDRESS_SPACE_IO
)
{
/* This is IO */
...
...
@@ -85,7 +85,7 @@ static int init_config_space (struct acpiphp_func *func)
len
=
bar
&
0xFFFFFFFC
;
len
=
~
len
+
1
;
dbg
(
"len in IO %x, BAR %d
"
,
len
,
count
);
dbg
(
"len in IO %x, BAR %d
\n
"
,
len
,
count
);
spin_lock
(
&
bridge
->
res_lock
);
res
=
acpiphp_get_io_resource
(
&
bridge
->
io_head
,
len
);
...
...
@@ -110,7 +110,7 @@ static int init_config_space (struct acpiphp_func *func)
len
=
bar
&
0xFFFFFFF0
;
len
=
~
len
+
1
;
dbg
(
"len in PFMEM %x, BAR %d"
,
len
,
count
);
dbg
(
"len in PFMEM %x, BAR %d
\n
"
,
len
,
count
);
spin_lock
(
&
bridge
->
res_lock
);
res
=
acpiphp_get_resource
(
&
bridge
->
p_mem_head
,
len
);
...
...
@@ -127,7 +127,7 @@ static int init_config_space (struct acpiphp_func *func)
(
u32
)
res
->
base
);
if
(
bar
&
PCI_BASE_ADDRESS_MEM_TYPE_64
)
{
/* takes up another dword */
dbg
(
"inside the pfmem 64 case, count %d
"
,
count
);
dbg
(
"inside the pfmem 64 case, count %d
\n
"
,
count
);
count
+=
1
;
pci_bus_write_config_dword
(
pbus
,
devfn
,
address
[
count
],
...
...
@@ -143,7 +143,7 @@ static int init_config_space (struct acpiphp_func *func)
len
=
bar
&
0xFFFFFFF0
;
len
=
~
len
+
1
;
dbg
(
"len in MEM %x, BAR %d"
,
len
,
count
);
dbg
(
"len in MEM %x, BAR %d
\n
"
,
len
,
count
);
spin_lock
(
&
bridge
->
res_lock
);
res
=
acpiphp_get_resource
(
&
bridge
->
mem_head
,
len
);
...
...
@@ -161,7 +161,7 @@ static int init_config_space (struct acpiphp_func *func)
if
(
bar
&
PCI_BASE_ADDRESS_MEM_TYPE_64
)
{
/* takes up another dword */
dbg
(
"inside mem 64 case, reg. mem, count %d
"
,
count
);
dbg
(
"inside mem 64 case, reg. mem, count %d
\n
"
,
count
);
count
+=
1
;
pci_bus_write_config_dword
(
pbus
,
devfn
,
address
[
count
],
...
...
@@ -212,7 +212,7 @@ static int configure_pci_dev (struct pci_dev_wrapped *wrapped_dev, struct pci_bu
//pci_proc_attach_device(dev);
//pci_announce_device_to_drivers(dev);
info
(
"Device %s configured"
,
dev
->
slot_name
);
info
(
"Device %s configured
\n
"
,
dev
->
slot_name
);
return
0
;
}
...
...
@@ -263,13 +263,13 @@ static int unconfigure_pci_dev_driver (struct pci_dev_wrapped *wrapped_dev, stru
{
struct
pci_dev
*
dev
=
wrapped_dev
->
dev
;
dbg
(
"attempting removal of driver for device %s"
,
dev
->
slot_name
);
dbg
(
"attempting removal of driver for device %s
\n
"
,
dev
->
slot_name
);
/* Now, remove the Linux Driver Representation */
if
(
dev
->
driver
)
{
if
(
dev
->
driver
->
remove
)
{
dev
->
driver
->
remove
(
dev
);
dbg
(
"driver was properly removed"
);
dbg
(
"driver was properly removed
\n
"
);
}
dev
->
driver
=
NULL
;
}
...
...
@@ -286,7 +286,7 @@ static int unconfigure_pci_dev (struct pci_dev_wrapped *wrapped_dev, struct pci_
/* Now, remove the Linux Representation */
if
(
dev
)
{
if
(
pci_hp_remove_device
(
dev
)
==
0
)
{
info
(
"Device %s removed"
,
dev
->
slot_name
);
info
(
"Device %s removed
\n
"
,
dev
->
slot_name
);
kfree
(
dev
);
/* Now, remove */
}
else
{
return
-
1
;
/* problems while freeing, abort visitation */
...
...
@@ -338,7 +338,7 @@ static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *
int
count
;
struct
pci_resource
*
res
;
dbg
(
"Device %s"
,
dev
->
slot_name
);
dbg
(
"Device %s
\n
"
,
dev
->
slot_name
);
for
(
count
=
0
;
address
[
count
];
count
++
)
{
/* for 6 BARs */
pci_read_config_dword
(
dev
,
address
[
count
],
&
bar
);
...
...
@@ -355,7 +355,7 @@ static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *
len
&=
0xFFFFFFFC
;
len
=
~
len
+
1
;
dbg
(
"BAR[%d] %08x - %08x (IO)"
,
count
,
(
u32
)
base
,
(
u32
)
base
+
len
-
1
);
dbg
(
"BAR[%d] %08x - %08x (IO)
\n
"
,
count
,
(
u32
)
base
,
(
u32
)
base
+
len
-
1
);
spin_lock
(
&
bridge
->
res_lock
);
res
=
acpiphp_get_resource_with_base
(
&
bridge
->
io_head
,
base
,
len
);
...
...
@@ -372,10 +372,10 @@ static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *
len
=
~
len
+
1
;
if
(
len
&
PCI_BASE_ADDRESS_MEM_TYPE_64
)
{
/* takes up another dword */
dbg
(
"prefetch mem 64
"
);
dbg
(
"prefetch mem 64
\n
"
);
count
+=
1
;
}
dbg
(
"BAR[%d] %08x - %08x (PMEM)"
,
count
,
(
u32
)
base
,
(
u32
)
base
+
len
-
1
);
dbg
(
"BAR[%d] %08x - %08x (PMEM)
\n
"
,
count
,
(
u32
)
base
,
(
u32
)
base
+
len
-
1
);
spin_lock
(
&
bridge
->
res_lock
);
res
=
acpiphp_get_resource_with_base
(
&
bridge
->
p_mem_head
,
base
,
len
);
spin_unlock
(
&
bridge
->
res_lock
);
...
...
@@ -389,10 +389,10 @@ static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *
if
(
len
&
PCI_BASE_ADDRESS_MEM_TYPE_64
)
{
/* takes up another dword */
dbg
(
"mem 64
"
);
dbg
(
"mem 64
\n
"
);
count
+=
1
;
}
dbg
(
"BAR[%d] %08x - %08x (MEM)"
,
count
,
(
u32
)
base
,
(
u32
)
base
+
len
-
1
);
dbg
(
"BAR[%d] %08x - %08x (MEM)
\n
"
,
count
,
(
u32
)
base
,
(
u32
)
base
+
len
-
1
);
spin_lock
(
&
bridge
->
res_lock
);
res
=
acpiphp_get_resource_with_base
(
&
bridge
->
mem_head
,
base
,
len
);
spin_unlock
(
&
bridge
->
res_lock
);
...
...
@@ -414,7 +414,7 @@ static void detect_used_resource_bus(struct acpiphp_bridge *bridge, struct pci_b
struct
list_head
*
l
;
struct
pci_dev
*
dev
;
list_for_each
(
l
,
&
bus
->
devices
)
{
list_for_each
(
l
,
&
bus
->
devices
)
{
dev
=
pci_dev_b
(
l
);
detect_used_resource
(
bridge
,
dev
);
/* XXX recursive call */
...
...
@@ -463,16 +463,16 @@ int acpiphp_init_func_resource (struct acpiphp_func *func)
struct
pci_dev
*
dev
;
dev
=
func
->
pci_dev
;
dbg
(
"Hot-pluggable device %s"
,
dev
->
slot_name
);
dbg
(
"Hot-pluggable device %s
\n
"
,
dev
->
slot_name
);
for
(
count
=
0
;
address
[
count
];
count
++
)
{
/* for 6 BARs */
pci_read_config_dword
(
dev
,
address
[
count
],
&
bar
);
pci_read_config_dword
(
dev
,
address
[
count
],
&
bar
);
if
(
!
bar
)
/* This BAR is not implemented */
continue
;
pci_write_config_dword
(
dev
,
address
[
count
],
0xFFFFFFFF
);
pci_read_config_dword
(
dev
,
address
[
count
],
&
len
);
pci_write_config_dword
(
dev
,
address
[
count
],
0xFFFFFFFF
);
pci_read_config_dword
(
dev
,
address
[
count
],
&
len
);
if
(
len
&
PCI_BASE_ADDRESS_SPACE_IO
)
{
/* This is IO */
...
...
@@ -480,7 +480,7 @@ int acpiphp_init_func_resource (struct acpiphp_func *func)
len
&=
0xFFFFFFFC
;
len
=
~
len
+
1
;
dbg
(
"BAR[%d] %08x - %08x (IO)"
,
count
,
(
u32
)
base
,
(
u32
)
base
+
len
-
1
);
dbg
(
"BAR[%d] %08x - %08x (IO)
\n
"
,
count
,
(
u32
)
base
,
(
u32
)
base
+
len
-
1
);
res
=
acpiphp_make_resource
(
base
,
len
);
if
(
!
res
)
...
...
@@ -499,10 +499,10 @@ int acpiphp_init_func_resource (struct acpiphp_func *func)
len
=
~
len
+
1
;
if
(
len
&
PCI_BASE_ADDRESS_MEM_TYPE_64
)
{
/* takes up another dword */
dbg
(
"prefetch mem 64
"
);
dbg
(
"prefetch mem 64
\n
"
);
count
+=
1
;
}
dbg
(
"BAR[%d] %08x - %08x (PMEM)"
,
count
,
(
u32
)
base
,
(
u32
)
base
+
len
-
1
);
dbg
(
"BAR[%d] %08x - %08x (PMEM)
\n
"
,
count
,
(
u32
)
base
,
(
u32
)
base
+
len
-
1
);
res
=
acpiphp_make_resource
(
base
,
len
);
if
(
!
res
)
goto
no_memory
;
...
...
@@ -518,10 +518,10 @@ int acpiphp_init_func_resource (struct acpiphp_func *func)
if
(
len
&
PCI_BASE_ADDRESS_MEM_TYPE_64
)
{
/* takes up another dword */
dbg
(
"mem 64
"
);
dbg
(
"mem 64
\n
"
);
count
+=
1
;
}
dbg
(
"BAR[%d] %08x - %08x (MEM)"
,
count
,
(
u32
)
base
,
(
u32
)
base
+
len
-
1
);
dbg
(
"BAR[%d] %08x - %08x (MEM)
\n
"
,
count
,
(
u32
)
base
,
(
u32
)
base
+
len
-
1
);
res
=
acpiphp_make_resource
(
base
,
len
);
if
(
!
res
)
goto
no_memory
;
...
...
@@ -532,7 +532,7 @@ int acpiphp_init_func_resource (struct acpiphp_func *func)
}
}
pci_write_config_dword
(
dev
,
address
[
count
],
bar
);
pci_write_config_dword
(
dev
,
address
[
count
],
bar
);
}
#if 1
acpiphp_dump_func_resource
(
func
);
...
...
@@ -541,7 +541,7 @@ int acpiphp_init_func_resource (struct acpiphp_func *func)
return
0
;
no_memory:
err
(
"out of memory"
);
err
(
"out of memory
\n
"
);
acpiphp_free_resource
(
&
func
->
io_head
);
acpiphp_free_resource
(
&
func
->
mem_head
);
acpiphp_free_resource
(
&
func
->
p_mem_head
);
...
...
@@ -574,7 +574,7 @@ int acpiphp_configure_slot (struct acpiphp_slot *slot)
if
(
hdr
&
0x80
)
is_multi
=
1
;
list_for_each
(
l
,
&
slot
->
funcs
)
{
list_for_each
(
l
,
&
slot
->
funcs
)
{
func
=
list_entry
(
l
,
struct
acpiphp_func
,
sibling
);
if
(
is_multi
||
func
->
function
==
0
)
{
pci_bus_read_config_dword
(
slot
->
bridge
->
pci_bus
,
...
...
@@ -583,7 +583,6 @@ int acpiphp_configure_slot (struct acpiphp_slot *slot)
PCI_VENDOR_ID
,
&
dvid
);
if
(
dvid
!=
0xffffffff
)
{
retval
=
init_config_space
(
func
);
if
(
retval
)
break
;
}
...
...
drivers/hotplug/acpiphp_res.c
View file @
82670e1f
...
...
@@ -370,13 +370,13 @@ struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size)
return
NULL
;
for
(
node
=
*
head
;
node
;
node
=
node
->
next
)
{
dbg
(
"%s: req_size =%x node=%p, base=%x, length=%x"
,
dbg
(
"%s: req_size =%x node=%p, base=%x, length=%x
\n
"
,
__FUNCTION__
,
size
,
node
,
(
u32
)
node
->
base
,
node
->
length
);
if
(
node
->
length
<
size
)
continue
;
if
(
node
->
base
&
(
size
-
1
))
{
dbg
(
"%s: not aligned"
,
__FUNCTION__
);
dbg
(
"%s: not aligned
\n
"
,
__FUNCTION__
);
/* this one isn't base aligned properly
so we'll make a new entry and split it up */
temp_qword
=
(
node
->
base
|
(
size
-
1
))
+
1
;
...
...
@@ -400,7 +400,7 @@ struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size)
/* Don't need to check if too small since we already did */
if
(
node
->
length
>
size
)
{
dbg
(
"%s: too big"
,
__FUNCTION__
);
dbg
(
"%s: too big
\n
"
,
__FUNCTION__
);
/* this one is longer than we need
so we'll make a new entry and split it up */
split_node
=
acpiphp_make_resource
(
node
->
base
+
size
,
node
->
length
-
size
);
...
...
@@ -415,7 +415,7 @@ struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size)
node
->
next
=
split_node
;
}
/* End of too big on top end */
dbg
(
"%s: got one!!!"
,
__FUNCTION__
);
dbg
(
"%s: got one!!!
\n
"
,
__FUNCTION__
);
/* If we got here, then it is the right size
Now take it out of the list */
if
(
*
head
==
node
)
{
...
...
@@ -458,7 +458,7 @@ struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head,
return
NULL
;
for
(
node
=
*
head
;
node
;
node
=
node
->
next
)
{
dbg
(
": 1st req_base=%x req_size =%x node=%p, base=%x, length=%x"
,
dbg
(
": 1st req_base=%x req_size =%x node=%p, base=%x, length=%x
\n
"
,
(
u32
)
base
,
size
,
node
,
(
u32
)
node
->
base
,
node
->
length
);
if
(
node
->
base
>
base
)
continue
;
...
...
@@ -467,7 +467,7 @@ struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head,
continue
;
if
(
node
->
base
<
base
)
{
dbg
(
": split 1"
);
dbg
(
": split 1
\n
"
);
/* this one isn't base aligned properly
so we'll make a new entry and split it up */
temp_qword
=
base
;
...
...
@@ -489,12 +489,12 @@ struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head,
node
->
next
=
split_node
;
}
dbg
(
": 2nd req_base=%x req_size =%x node=%p, base=%x, length=%x"
,
dbg
(
": 2nd req_base=%x req_size =%x node=%p, base=%x, length=%x
\n
"
,
(
u32
)
base
,
size
,
node
,
(
u32
)
node
->
base
,
node
->
length
);
/* Don't need to check if too small since we already did */
if
(
node
->
length
>
size
)
{
dbg
(
": split 2"
);
dbg
(
": split 2
\n
"
);
/* this one is longer than we need
so we'll make a new entry and split it up */
split_node
=
acpiphp_make_resource
(
node
->
base
+
size
,
node
->
length
-
size
);
...
...
@@ -509,7 +509,7 @@ struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head,
node
->
next
=
split_node
;
}
/* End of too big on top end */
dbg
(
": got one!!!"
);
dbg
(
": got one!!!
\n
"
);
/* If we got here, then it is the right size
Now take it out of the list */
if
(
*
head
==
node
)
{
...
...
@@ -547,13 +547,13 @@ int acpiphp_resource_sort_and_combine (struct pci_resource **head)
if
(
!
(
*
head
))
return
1
;
dbg
(
"*head->next = %p"
,(
*
head
)
->
next
);
dbg
(
"*head->next = %p
\n
"
,(
*
head
)
->
next
);
if
(
!
(
*
head
)
->
next
)
return
0
;
/* only one item on the list, already sorted! */
dbg
(
"*head->base = 0x%x"
,(
u32
)(
*
head
)
->
base
);
dbg
(
"*head->next->base = 0x%x"
,
(
u32
)(
*
head
)
->
next
->
base
);
dbg
(
"*head->base = 0x%x
\n
"
,(
u32
)(
*
head
)
->
base
);
dbg
(
"*head->next->base = 0x%x
\n
"
,
(
u32
)(
*
head
)
->
next
->
base
);
while
(
out_of_order
)
{
out_of_order
=
0
;
...
...
@@ -587,7 +587,7 @@ int acpiphp_resource_sort_and_combine (struct pci_resource **head)
while
(
node1
&&
node1
->
next
)
{
if
((
node1
->
base
+
node1
->
length
)
==
node1
->
next
->
base
)
{
/* Combine */
dbg
(
"8.."
);
dbg
(
"8..
\n
"
);
node1
->
length
+=
node1
->
next
->
length
;
node2
=
node1
->
next
;
node1
->
next
=
node1
->
next
->
next
;
...
...
@@ -668,7 +668,7 @@ static void dump_resource(struct pci_resource *head)
cnt
=
0
;
while
(
p
)
{
dbg
(
"[%02d] %08x - %08x"
,
dbg
(
"[%02d] %08x - %08x
\n
"
,
cnt
++
,
(
u32
)
p
->
base
,
(
u32
)
p
->
base
+
p
->
length
-
1
);
p
=
p
->
next
;
}
...
...
@@ -676,24 +676,24 @@ static void dump_resource(struct pci_resource *head)
void
acpiphp_dump_resource
(
struct
acpiphp_bridge
*
bridge
)
{
dbg
(
"I/O resource:"
);
dbg
(
"I/O resource:
\n
"
);
dump_resource
(
bridge
->
io_head
);
dbg
(
"MEM resource:"
);
dbg
(
"MEM resource:
\n
"
);
dump_resource
(
bridge
->
mem_head
);
dbg
(
"PMEM resource:"
);
dbg
(
"PMEM resource:
\n
"
);
dump_resource
(
bridge
->
p_mem_head
);
dbg
(
"BUS resource:"
);
dbg
(
"BUS resource:
\n
"
);
dump_resource
(
bridge
->
bus_head
);
}
void
acpiphp_dump_func_resource
(
struct
acpiphp_func
*
func
)
{
dbg
(
"I/O resource:"
);
dbg
(
"I/O resource:
\n
"
);
dump_resource
(
func
->
io_head
);
dbg
(
"MEM resource:"
);
dbg
(
"MEM resource:
\n
"
);
dump_resource
(
func
->
mem_head
);
dbg
(
"PMEM resource:"
);
dbg
(
"PMEM resource:
\n
"
);
dump_resource
(
func
->
p_mem_head
);
dbg
(
"BUS resource:"
);
dbg
(
"BUS resource:
\n
"
);
dump_resource
(
func
->
bus_head
);
}
drivers/hotplug/cpci_hotplug.h
0 → 100644
View file @
82670e1f
/*
* CompactPCI Hot Plug Core Functions
*
* Copyright (c) 2002 SOMA Networks, Inc.
* Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (c) 2001 IBM Corp.
*
* 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 <scottm@somanetworks.com>
*/
#ifndef _CPCI_HOTPLUG_H
#define _CPCI_HOTPLUG_H
#include <linux/types.h>
#include <linux/pci.h>
/* PICMG 2.12 R2.0 HS CSR bits: */
#define HS_CSR_INS 0x0080
#define HS_CSR_EXT 0x0040
#define HS_CSR_PI 0x0030
#define HS_CSR_LOO 0x0008
#define HS_CSR_PIE 0x0004
#define HS_CSR_EIM 0x0002
#define HS_CSR_DHA 0x0001
#define SLOT_MAGIC 0x67267322
struct
slot
{
u32
magic
;
u8
number
;
unsigned
int
devfn
;
struct
pci_bus
*
bus
;
struct
pci_dev
*
dev
;
unsigned
int
extracting
;
struct
hotplug_slot
*
hotplug_slot
;
struct
list_head
slot_list
;
};
struct
cpci_hp_controller_ops
{
int
(
*
query_enum
)
(
void
);
int
(
*
enable_irq
)
(
void
);
int
(
*
disable_irq
)
(
void
);
int
(
*
check_irq
)
(
void
*
dev_id
);
int
(
*
hardware_test
)
(
struct
slot
*
slot
,
u32
value
);
u8
(
*
get_power
)
(
struct
slot
*
slot
);
int
(
*
set_power
)
(
struct
slot
*
slot
,
int
value
);
};
struct
cpci_hp_controller
{
unsigned
int
irq
;
unsigned
long
irq_flags
;
char
*
devname
;
void
*
dev_id
;
char
*
name
;
struct
cpci_hp_controller_ops
*
ops
;
};
extern
int
cpci_hp_register_controller
(
struct
cpci_hp_controller
*
controller
);
extern
int
cpci_hp_unregister_controller
(
struct
cpci_hp_controller
*
controller
);
extern
int
cpci_hp_register_bus
(
struct
pci_bus
*
bus
,
u8
first
,
u8
last
);
extern
int
cpci_hp_unregister_bus
(
struct
pci_bus
*
bus
);
extern
struct
slot
*
cpci_find_slot
(
struct
pci_bus
*
bus
,
unsigned
int
devfn
);
extern
int
cpci_hp_start
(
void
);
extern
int
cpci_hp_stop
(
void
);
/*
* Internal function prototypes, these functions should not be used by
* board/chassis drivers.
*/
extern
u8
cpci_get_attention_status
(
struct
slot
*
slot
);
extern
u8
cpci_get_latch_status
(
struct
slot
*
slot
);
extern
u8
cpci_get_adapter_status
(
struct
slot
*
slot
);
extern
u16
cpci_get_hs_csr
(
struct
slot
*
slot
);
extern
u16
cpci_set_hs_csr
(
struct
slot
*
slot
,
u16
hs_csr
);
extern
int
cpci_set_attention_status
(
struct
slot
*
slot
,
int
status
);
extern
int
cpci_check_and_clear_ins
(
struct
slot
*
slot
);
extern
int
cpci_check_ext
(
struct
slot
*
slot
);
extern
int
cpci_clear_ext
(
struct
slot
*
slot
);
extern
int
cpci_led_on
(
struct
slot
*
slot
);
extern
int
cpci_led_off
(
struct
slot
*
slot
);
extern
int
cpci_configure_slot
(
struct
slot
*
slot
);
extern
int
cpci_unconfigure_slot
(
struct
slot
*
slot
);
#endif
/* _CPCI_HOTPLUG_H */
drivers/hotplug/cpci_hotplug_core.c
0 → 100644
View file @
82670e1f
/*
* CompactPCI Hot Plug Driver
*
* Copyright (c) 2002 SOMA Networks, Inc.
* Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (c) 2001 IBM Corp.
*
* 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 <scottm@somanetworks.com>
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/smp_lock.h>
#include "pci_hotplug.h"
#include "cpci_hotplug.h"
#define DRIVER_VERSION "0.2"
#define DRIVER_AUTHOR "Scott Murray <scottm@somanetworks.com>"
#define DRIVER_DESC "CompactPCI Hot Plug Core"
#if !defined(CONFIG_HOTPLUG_CPCI_MODULE)
#define MY_NAME "cpci_hotplug"
#else
#define MY_NAME THIS_MODULE->name
#endif
#define dbg(format, arg...) \
do { \
if(cpci_debug) \
printk (KERN_DEBUG "%s: " format "\n", \
MY_NAME , ## arg); \
} while(0)
#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
/* local variables */
static
spinlock_t
list_lock
;
static
LIST_HEAD
(
slot_list
);
static
int
slots
;
int
cpci_debug
;
static
struct
cpci_hp_controller
*
controller
;
static
struct
semaphore
event_semaphore
;
/* mutex for process loop (up if something to process) */
static
struct
semaphore
thread_exit
;
/* guard ensure thread has exited before calling it quits */
static
int
thread_finished
=
1
;
static
int
enable_slot
(
struct
hotplug_slot
*
slot
);
static
int
disable_slot
(
struct
hotplug_slot
*
slot
);
static
int
set_attention_status
(
struct
hotplug_slot
*
slot
,
u8
value
);
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_latch_status
(
struct
hotplug_slot
*
slot
,
u8
*
value
);
static
int
get_adapter_status
(
struct
hotplug_slot
*
slot
,
u8
*
value
);
static
struct
hotplug_slot_ops
cpci_hotplug_slot_ops
=
{
.
owner
=
THIS_MODULE
,
.
enable_slot
=
enable_slot
,
.
disable_slot
=
disable_slot
,
.
set_attention_status
=
set_attention_status
,
.
hardware_test
=
NULL
,
.
get_power_status
=
get_power_status
,
.
get_attention_status
=
get_attention_status
,
.
get_latch_status
=
get_latch_status
,
.
get_adapter_status
=
get_adapter_status
,
};
/* Inline functions to check the sanity of a pointer that is passed to us */
static
inline
int
slot_paranoia_check
(
struct
slot
*
slot
,
const
char
*
function
)
{
if
(
!
slot
)
{
dbg
(
"%s - slot == NULL"
,
function
);
return
-
1
;
}
if
(
slot
->
magic
!=
SLOT_MAGIC
)
{
dbg
(
"%s - bad magic number for slot"
,
function
);
return
-
1
;
}
if
(
!
slot
->
hotplug_slot
)
{
dbg
(
"%s - slot->hotplug_slot == NULL!"
,
function
);
return
-
1
;
}
return
0
;
}
static
inline
struct
slot
*
get_slot
(
struct
hotplug_slot
*
hotplug_slot
,
const
char
*
function
)
{
struct
slot
*
slot
;
if
(
!
hotplug_slot
)
{
dbg
(
"%s - hotplug_slot == NULL"
,
function
);
return
NULL
;
}
slot
=
(
struct
slot
*
)
hotplug_slot
->
private
;
if
(
slot_paranoia_check
(
slot
,
function
))
return
NULL
;
return
slot
;
}
static
int
update_latch_status
(
struct
hotplug_slot
*
hotplug_slot
,
u8
value
)
{
struct
hotplug_slot_info
info
;
if
(
!
(
hotplug_slot
&&
hotplug_slot
->
info
))
return
-
EINVAL
;
memcpy
(
&
info
,
hotplug_slot
->
info
,
sizeof
(
struct
hotplug_slot_info
));
info
.
latch_status
=
value
;
return
pci_hp_change_slot_info
(
hotplug_slot
->
name
,
&
info
);
}
static
int
update_adapter_status
(
struct
hotplug_slot
*
hotplug_slot
,
u8
value
)
{
struct
hotplug_slot_info
info
;
if
(
!
(
hotplug_slot
&&
hotplug_slot
->
info
))
return
-
EINVAL
;
memcpy
(
&
info
,
hotplug_slot
->
info
,
sizeof
(
struct
hotplug_slot_info
));
info
.
adapter_status
=
value
;
return
pci_hp_change_slot_info
(
hotplug_slot
->
name
,
&
info
);
}
static
int
enable_slot
(
struct
hotplug_slot
*
hotplug_slot
)
{
struct
slot
*
slot
=
get_slot
(
hotplug_slot
,
__FUNCTION__
);
int
retval
=
0
;
if
(
slot
==
NULL
)
return
-
ENODEV
;
dbg
(
"%s - physical_slot = %s"
,
__FUNCTION__
,
hotplug_slot
->
name
);
if
(
controller
->
ops
->
set_power
)
{
retval
=
controller
->
ops
->
set_power
(
slot
,
1
);
}
return
retval
;
}
static
int
disable_slot
(
struct
hotplug_slot
*
hotplug_slot
)
{
struct
slot
*
slot
=
get_slot
(
hotplug_slot
,
__FUNCTION__
);
int
retval
=
0
;
if
(
slot
==
NULL
)
return
-
ENODEV
;
dbg
(
"%s - physical_slot = %s"
,
__FUNCTION__
,
hotplug_slot
->
name
);
/* Unconfigure device */
dbg
(
"%s - unconfiguring slot %s"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
);
if
((
retval
=
cpci_unconfigure_slot
(
slot
)))
{
err
(
"%s - could not unconfigure slot %s"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
);
return
retval
;
}
dbg
(
"%s - finished unconfiguring slot %s"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
);
/* Clear EXT (by setting it) */
if
(
cpci_clear_ext
(
slot
))
{
err
(
"%s - could not clear EXT for slot %s"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
);
retval
=
-
ENODEV
;
}
cpci_led_on
(
slot
);
if
(
controller
->
ops
->
set_power
)
{
retval
=
controller
->
ops
->
set_power
(
slot
,
0
);
}
if
(
update_adapter_status
(
slot
->
hotplug_slot
,
0
))
{
warn
(
"failure to update adapter file"
);
}
slot
->
extracting
=
0
;
return
retval
;
}
static
u8
cpci_get_power_status
(
struct
slot
*
slot
)
{
u8
power
=
1
;
if
(
controller
->
ops
->
get_power
)
{
power
=
controller
->
ops
->
get_power
(
slot
);
}
return
power
;
}
static
int
get_power_status
(
struct
hotplug_slot
*
hotplug_slot
,
u8
*
value
)
{
struct
slot
*
slot
=
get_slot
(
hotplug_slot
,
__FUNCTION__
);
if
(
slot
==
NULL
)
return
-
ENODEV
;
*
value
=
cpci_get_power_status
(
slot
);
return
0
;
}
static
int
get_attention_status
(
struct
hotplug_slot
*
hotplug_slot
,
u8
*
value
)
{
struct
slot
*
slot
=
get_slot
(
hotplug_slot
,
__FUNCTION__
);
if
(
slot
==
NULL
)
return
-
ENODEV
;
*
value
=
cpci_get_attention_status
(
slot
);
return
0
;
}
static
int
set_attention_status
(
struct
hotplug_slot
*
hotplug_slot
,
u8
status
)
{
struct
slot
*
slot
=
get_slot
(
hotplug_slot
,
__FUNCTION__
);
if
(
slot
==
NULL
)
return
-
ENODEV
;
switch
(
status
)
{
case
0
:
cpci_set_attention_status
(
slot
,
0
);
break
;
case
1
:
default:
cpci_set_attention_status
(
slot
,
1
);
break
;
}
return
0
;
}
static
int
get_latch_status
(
struct
hotplug_slot
*
hotplug_slot
,
u8
*
value
)
{
if
(
hotplug_slot
==
NULL
||
hotplug_slot
->
info
==
NULL
)
return
-
ENODEV
;
*
value
=
hotplug_slot
->
info
->
latch_status
;
return
0
;
}
static
int
get_adapter_status
(
struct
hotplug_slot
*
hotplug_slot
,
u8
*
value
)
{
if
(
hotplug_slot
==
NULL
||
hotplug_slot
->
info
==
NULL
)
return
-
ENODEV
;
*
value
=
hotplug_slot
->
info
->
adapter_status
;
return
0
;
}
#define SLOT_NAME_SIZE 6
static
void
make_slot_name
(
struct
slot
*
slot
)
{
snprintf
(
slot
->
hotplug_slot
->
name
,
SLOT_NAME_SIZE
,
"%02x:%02x"
,
slot
->
bus
->
number
,
slot
->
number
);
}
int
cpci_hp_register_bus
(
struct
pci_bus
*
bus
,
u8
first
,
u8
last
)
{
struct
slot
*
slot
;
struct
hotplug_slot
*
hotplug_slot
;
struct
hotplug_slot_info
*
info
;
char
*
name
;
int
status
=
0
;
int
i
;
if
(
!
(
controller
&&
bus
))
{
return
-
ENODEV
;
}
if
(
last
<
first
)
{
return
-
EINVAL
;
}
/*
* Create a structure for each slot, and register that slot
* with the pci_hotplug subsystem.
*/
for
(
i
=
first
;
i
<=
last
;
++
i
)
{
slot
=
kmalloc
(
sizeof
(
struct
slot
),
GFP_KERNEL
);
if
(
!
slot
)
return
-
ENOMEM
;
memset
(
slot
,
0
,
sizeof
(
struct
slot
));
hotplug_slot
=
kmalloc
(
sizeof
(
struct
hotplug_slot
),
GFP_KERNEL
);
if
(
!
hotplug_slot
)
{
kfree
(
slot
);
return
-
ENOMEM
;
}
memset
(
hotplug_slot
,
0
,
sizeof
(
struct
hotplug_slot
));
slot
->
hotplug_slot
=
hotplug_slot
;
info
=
kmalloc
(
sizeof
(
struct
hotplug_slot_info
),
GFP_KERNEL
);
if
(
!
info
)
{
kfree
(
hotplug_slot
);
kfree
(
slot
);
return
-
ENOMEM
;
}
memset
(
info
,
0
,
sizeof
(
struct
hotplug_slot_info
));
hotplug_slot
->
info
=
info
;
name
=
kmalloc
(
SLOT_NAME_SIZE
,
GFP_KERNEL
);
if
(
!
name
)
{
kfree
(
info
);
kfree
(
hotplug_slot
);
kfree
(
slot
);
return
-
ENOMEM
;
}
hotplug_slot
->
name
=
name
;
slot
->
magic
=
SLOT_MAGIC
;
slot
->
bus
=
bus
;
slot
->
number
=
i
;
slot
->
devfn
=
PCI_DEVFN
(
i
,
0
);
hotplug_slot
->
private
=
slot
;
make_slot_name
(
slot
);
hotplug_slot
->
ops
=
&
cpci_hotplug_slot_ops
;
/*
* Initialize the slot info structure with some known
* good values.
*/
dbg
(
"initializing slot %s"
,
slot
->
hotplug_slot
->
name
);
info
->
power_status
=
cpci_get_power_status
(
slot
);
info
->
attention_status
=
cpci_get_attention_status
(
slot
);
dbg
(
"registering slot %s"
,
slot
->
hotplug_slot
->
name
);
status
=
pci_hp_register
(
slot
->
hotplug_slot
);
if
(
status
)
{
err
(
"pci_hp_register failed with error %d"
,
status
);
kfree
(
info
);
kfree
(
name
);
kfree
(
hotplug_slot
);
kfree
(
slot
);
return
status
;
}
/* Add slot to our internal list */
spin_lock
(
&
list_lock
);
list_add
(
&
slot
->
slot_list
,
&
slot_list
);
slots
++
;
spin_unlock
(
&
list_lock
);
}
return
status
;
}
int
cpci_hp_unregister_bus
(
struct
pci_bus
*
bus
)
{
struct
slot
*
slot
;
struct
list_head
*
tmp
;
int
status
;
if
(
!
bus
)
{
return
-
ENODEV
;
}
spin_lock
(
&
list_lock
);
if
(
!
slots
)
{
spin_unlock
(
&
list_lock
);
return
-
1
;
}
list_for_each
(
tmp
,
&
slot_list
)
{
slot
=
list_entry
(
tmp
,
struct
slot
,
slot_list
);
if
(
slot
->
bus
==
bus
)
{
dbg
(
"deregistering slot %s"
,
slot
->
hotplug_slot
->
name
);
status
=
pci_hp_deregister
(
slot
->
hotplug_slot
);
if
(
status
)
{
err
(
"pci_hp_deregister failed with error %d"
,
status
);
return
status
;
}
list_del
(
&
slot
->
slot_list
);
kfree
(
slot
->
hotplug_slot
->
info
);
kfree
(
slot
->
hotplug_slot
->
name
);
kfree
(
slot
->
hotplug_slot
);
kfree
(
slot
);
slots
--
;
}
}
spin_unlock
(
&
list_lock
);
return
0
;
}
struct
slot
*
cpci_find_slot
(
struct
pci_bus
*
bus
,
unsigned
int
devfn
)
{
struct
slot
*
slot
;
struct
slot
*
found
;
struct
list_head
*
tmp
;
if
(
!
bus
)
{
return
NULL
;
}
spin_lock
(
&
list_lock
);
if
(
!
slots
)
{
spin_unlock
(
&
list_lock
);
return
NULL
;
}
found
=
NULL
;
list_for_each
(
tmp
,
&
slot_list
)
{
slot
=
list_entry
(
tmp
,
struct
slot
,
slot_list
);
if
(
slot
->
bus
==
bus
&&
slot
->
devfn
==
devfn
)
{
found
=
slot
;
break
;
}
}
spin_unlock
(
&
list_lock
);
return
found
;
}
/* This is the interrupt mode interrupt handler */
void
cpci_hp_intr
(
int
irq
,
void
*
data
,
struct
pt_regs
*
regs
)
{
dbg
(
"entered cpci_hp_intr"
);
/* Check to see if it was our interrupt */
if
((
controller
->
irq_flags
&
SA_SHIRQ
)
&&
!
controller
->
ops
->
check_irq
(
controller
->
dev_id
))
{
dbg
(
"exited cpci_hp_intr, not our interrupt"
);
return
;
}
/* Disable ENUM interrupt */
controller
->
ops
->
disable_irq
();
/* Trigger processing by the event thread */
dbg
(
"Signal event_semaphore"
);
up
(
&
event_semaphore
);
dbg
(
"exited cpci_hp_intr"
);
}
/*
* According to PICMG 2.12 R2.0, section 6.3.2, upon
* initialization, the system driver shall clear the
* INS bits of the cold-inserted devices.
*/
static
int
init_slots
(
void
)
{
struct
slot
*
slot
;
struct
list_head
*
tmp
;
struct
pci_dev
*
dev
;
dbg
(
"%s - enter"
,
__FUNCTION__
);
spin_lock
(
&
list_lock
);
if
(
!
slots
)
{
spin_unlock
(
&
list_lock
);
return
-
1
;
}
list_for_each
(
tmp
,
&
slot_list
)
{
slot
=
list_entry
(
tmp
,
struct
slot
,
slot_list
);
dbg
(
"%s - looking at slot %s"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
);
if
(
cpci_check_and_clear_ins
(
slot
))
{
dbg
(
"%s - cleared INS for slot %s"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
);
dev
=
pci_find_slot
(
slot
->
bus
->
number
,
PCI_DEVFN
(
slot
->
number
,
0
));
if
(
dev
)
{
if
(
update_adapter_status
(
slot
->
hotplug_slot
,
1
))
{
warn
(
"failure to update adapter file"
);
}
if
(
update_latch_status
(
slot
->
hotplug_slot
,
1
))
{
warn
(
"failure to update latch file"
);
}
slot
->
dev
=
dev
;
}
else
{
err
(
"%s - no driver attached to device in slot %s"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
);
}
}
}
spin_unlock
(
&
list_lock
);
dbg
(
"%s - exit"
,
__FUNCTION__
);
return
0
;
}
static
int
check_slots
(
void
)
{
struct
slot
*
slot
;
struct
list_head
*
tmp
;
int
extracted
;
int
inserted
;
spin_lock
(
&
list_lock
);
if
(
!
slots
)
{
spin_unlock
(
&
list_lock
);
err
(
"no slots registered, shutting down"
);
return
-
1
;
}
extracted
=
inserted
=
0
;
list_for_each
(
tmp
,
&
slot_list
)
{
slot
=
list_entry
(
tmp
,
struct
slot
,
slot_list
);
dbg
(
"%s - looking at slot %s"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
);
if
(
cpci_check_and_clear_ins
(
slot
))
{
u16
hs_csr
;
/* Some broken hardware (e.g. PLX 9054AB) asserts ENUM# twice... */
if
(
slot
->
dev
)
{
warn
(
"slot %s already inserted"
,
slot
->
hotplug_slot
->
name
);
inserted
++
;
continue
;
}
/* Process insertion */
dbg
(
"%s - slot %s inserted"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
);
/* GSM, debug */
hs_csr
=
cpci_get_hs_csr
(
slot
);
dbg
(
"%s - slot %s HS_CSR (1) = %04x"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
,
hs_csr
);
/* Configure device */
dbg
(
"%s - configuring slot %s"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
);
if
(
cpci_configure_slot
(
slot
))
{
err
(
"%s - could not configure slot %s"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
);
continue
;
}
dbg
(
"%s - finished configuring slot %s"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
);
/* GSM, debug */
hs_csr
=
cpci_get_hs_csr
(
slot
);
dbg
(
"%s - slot %s HS_CSR (2) = %04x"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
,
hs_csr
);
if
(
update_latch_status
(
slot
->
hotplug_slot
,
1
))
{
warn
(
"failure to update latch file"
);
}
if
(
update_adapter_status
(
slot
->
hotplug_slot
,
1
))
{
warn
(
"failure to update adapter file"
);
}
cpci_led_off
(
slot
);
/* GSM, debug */
hs_csr
=
cpci_get_hs_csr
(
slot
);
dbg
(
"%s - slot %s HS_CSR (3) = %04x"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
,
hs_csr
);
inserted
++
;
}
else
if
(
cpci_check_ext
(
slot
))
{
u16
hs_csr
;
/* Process extraction request */
dbg
(
"%s - slot %s extracted"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
);
/* GSM, debug */
hs_csr
=
cpci_get_hs_csr
(
slot
);
dbg
(
"%s - slot %s HS_CSR = %04x"
,
__FUNCTION__
,
slot
->
hotplug_slot
->
name
,
hs_csr
);
if
(
!
slot
->
extracting
)
{
if
(
update_latch_status
(
slot
->
hotplug_slot
,
0
))
{
warn
(
"failure to update latch file"
);
}
slot
->
extracting
=
1
;
}
extracted
++
;
}
}
spin_unlock
(
&
list_lock
);
if
(
inserted
||
extracted
)
{
return
extracted
;
}
else
{
err
(
"cannot find ENUM# source, shutting down"
);
return
-
1
;
}
}
/* This is the interrupt mode worker thread body */
static
int
event_thread
(
void
*
data
)
{
int
rc
;
struct
slot
*
slot
;
struct
list_head
*
tmp
;
lock_kernel
();
daemonize
();
strcpy
(
current
->
comm
,
"cpci_hp_eventd"
);
unlock_kernel
();
dbg
(
"%s - event thread started"
,
__FUNCTION__
);
while
(
1
)
{
dbg
(
"event thread sleeping"
);
down_interruptible
(
&
event_semaphore
);
dbg
(
"event thread woken, thread_finished = %d"
,
thread_finished
);
if
(
thread_finished
||
signal_pending
(
current
))
break
;
while
(
controller
->
ops
->
query_enum
())
{
rc
=
check_slots
();
if
(
rc
>
0
)
{
/* Give userspace a chance to handle extraction */
set_current_state
(
TASK_INTERRUPTIBLE
);
schedule_timeout
(
HZ
/
2
);
}
else
if
(
rc
<
0
)
{
dbg
(
"%s - error checking slots"
,
__FUNCTION__
);
thread_finished
=
1
;
break
;
}
}
/* Check for someone yanking out a board */
list_for_each
(
tmp
,
&
slot_list
)
{
slot
=
list_entry
(
tmp
,
struct
slot
,
slot_list
);
if
(
slot
->
extracting
)
{
/*
* Hmmm, we're likely hosed at this point, should we
* bother trying to tell the driver or not?
*/
err
(
"card in slot %s was improperly removed"
,
slot
->
hotplug_slot
->
name
);
if
(
update_adapter_status
(
slot
->
hotplug_slot
,
0
))
{
warn
(
"failure to update adapter file"
);
}
slot
->
extracting
=
0
;
}
}
/* Re-enable ENUM# interrupt */
dbg
(
"%s - re-enabling irq"
,
__FUNCTION__
);
controller
->
ops
->
enable_irq
();
}
dbg
(
"%s - event thread signals exit"
,
__FUNCTION__
);
up
(
&
thread_exit
);
return
0
;
}
/* This is the polling mode worker thread body */
static
int
poll_thread
(
void
*
data
)
{
int
rc
;
struct
slot
*
slot
;
struct
list_head
*
tmp
;
lock_kernel
();
daemonize
();
strcpy
(
current
->
comm
,
"cpci_hp_polld"
);
unlock_kernel
();
while
(
1
)
{
if
(
thread_finished
||
signal_pending
(
current
))
break
;
while
(
controller
->
ops
->
query_enum
())
{
rc
=
check_slots
();
if
(
rc
>
0
)
{
/* Give userspace a chance to handle extraction */
set_current_state
(
TASK_INTERRUPTIBLE
);
schedule_timeout
(
HZ
/
2
);
}
else
if
(
rc
<
0
)
{
dbg
(
"%s - error checking slots"
,
__FUNCTION__
);
thread_finished
=
1
;
break
;
}
}
/* Check for someone yanking out a board */
list_for_each
(
tmp
,
&
slot_list
)
{
slot
=
list_entry
(
tmp
,
struct
slot
,
slot_list
);
if
(
slot
->
extracting
)
{
/*
* Hmmm, we're likely hosed at this point, should we
* bother trying to tell the driver or not?
*/
err
(
"card in slot %s was improperly removed"
,
slot
->
hotplug_slot
->
name
);
if
(
update_adapter_status
(
slot
->
hotplug_slot
,
0
))
{
warn
(
"failure to update adapter file"
);
}
slot
->
extracting
=
0
;
}
}
set_current_state
(
TASK_INTERRUPTIBLE
);
schedule_timeout
(
HZ
/
10
);
}
dbg
(
"poll thread signals exit"
);
up
(
&
thread_exit
);
return
0
;
}
static
int
cpci_start_thread
(
void
)
{
int
pid
;
/* initialize our semaphores */
init_MUTEX_LOCKED
(
&
event_semaphore
);
init_MUTEX_LOCKED
(
&
thread_exit
);
thread_finished
=
0
;
if
(
controller
->
irq
)
{
pid
=
kernel_thread
(
event_thread
,
0
,
0
);
}
else
{
pid
=
kernel_thread
(
poll_thread
,
0
,
0
);
}
if
(
pid
<
0
)
{
err
(
"Can't start up our thread"
);
return
-
1
;
}
dbg
(
"Our thread pid = %d"
,
pid
);
return
0
;
}
static
void
cpci_stop_thread
(
void
)
{
thread_finished
=
1
;
dbg
(
"thread finish command given"
);
if
(
controller
->
irq
)
{
up
(
&
event_semaphore
);
}
dbg
(
"wait for thread to exit"
);
down
(
&
thread_exit
);
}
int
cpci_hp_register_controller
(
struct
cpci_hp_controller
*
new_controller
)
{
int
status
=
0
;
if
(
!
controller
)
{
controller
=
new_controller
;
if
(
controller
->
irq
)
{
if
(
request_irq
(
controller
->
irq
,
cpci_hp_intr
,
controller
->
irq_flags
,
MY_NAME
,
controller
->
dev_id
))
{
err
(
"Can't get irq %d for the hotplug cPCI controller"
,
controller
->
irq
);
status
=
-
ENODEV
;
}
dbg
(
"%s - acquired controller irq %d"
,
__FUNCTION__
,
controller
->
irq
);
}
}
else
{
err
(
"cPCI hotplug controller already registered"
);
status
=
-
1
;
}
return
status
;
}
int
cpci_hp_unregister_controller
(
struct
cpci_hp_controller
*
old_controller
)
{
int
status
=
0
;
if
(
controller
)
{
if
(
!
thread_finished
)
{
cpci_stop_thread
();
}
if
(
controller
->
irq
)
{
free_irq
(
controller
->
irq
,
controller
->
dev_id
);
}
controller
=
NULL
;
}
else
{
status
=
-
ENODEV
;
}
return
status
;
}
int
cpci_hp_start
(
void
)
{
static
int
first
=
1
;
int
status
;
dbg
(
"%s - enter"
,
__FUNCTION__
);
if
(
!
controller
)
{
return
-
ENODEV
;
}
spin_lock
(
&
list_lock
);
if
(
!
slots
)
{
spin_unlock
(
&
list_lock
);
return
-
ENODEV
;
}
spin_unlock
(
&
list_lock
);
if
(
first
)
{
status
=
init_slots
();
if
(
status
)
{
return
status
;
}
first
=
0
;
}
status
=
cpci_start_thread
();
if
(
status
)
{
return
status
;
}
dbg
(
"%s - thread started"
,
__FUNCTION__
);
if
(
controller
->
irq
)
{
/* Start enum interrupt processing */
dbg
(
"%s - enabling irq"
,
__FUNCTION__
);
controller
->
ops
->
enable_irq
();
}
dbg
(
"%s - exit"
,
__FUNCTION__
);
return
0
;
}
int
cpci_hp_stop
(
void
)
{
if
(
!
controller
)
{
return
-
ENODEV
;
}
if
(
controller
->
irq
)
{
/* Stop enum interrupt processing */
dbg
(
"%s - disabling irq"
,
__FUNCTION__
);
controller
->
ops
->
disable_irq
();
}
cpci_stop_thread
();
return
0
;
}
static
void
__exit
cleanup_slots
(
void
)
{
struct
list_head
*
tmp
;
struct
slot
*
slot
;
/*
* Unregister all of our slots with the pci_hotplug subsystem,
* and free up all memory that we had allocated.
*/
spin_lock
(
&
list_lock
);
if
(
!
slots
)
{
goto
null_cleanup
;
}
list_for_each
(
tmp
,
&
slot_list
)
{
slot
=
list_entry
(
tmp
,
struct
slot
,
slot_list
);
list_del
(
&
slot
->
slot_list
);
pci_hp_deregister
(
slot
->
hotplug_slot
);
kfree
(
slot
->
hotplug_slot
->
info
);
kfree
(
slot
->
hotplug_slot
->
name
);
kfree
(
slot
->
hotplug_slot
);
kfree
(
slot
);
}
null_cleanup:
spin_unlock
(
&
list_lock
);
return
;
}
static
int
__init
cpci_hotplug_init
(
void
)
{
spin_lock_init
(
&
list_lock
);
info
(
DRIVER_DESC
" version: "
DRIVER_VERSION
);
return
0
;
}
static
void
__exit
cpci_hotplug_exit
(
void
)
{
/*
* Clean everything up.
*/
cleanup_slots
();
}
module_init
(
cpci_hotplug_init
);
module_exit
(
cpci_hotplug_exit
);
MODULE_AUTHOR
(
DRIVER_AUTHOR
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
MODULE_PARM
(
cpci_debug
,
"i"
);
MODULE_PARM_DESC
(
cpci_debug
,
"Debugging mode"
);
EXPORT_SYMBOL_GPL
(
cpci_hp_register_controller
);
EXPORT_SYMBOL_GPL
(
cpci_hp_unregister_controller
);
EXPORT_SYMBOL_GPL
(
cpci_hp_register_bus
);
EXPORT_SYMBOL_GPL
(
cpci_hp_unregister_bus
);
EXPORT_SYMBOL_GPL
(
cpci_find_slot
);
EXPORT_SYMBOL_GPL
(
cpci_hp_start
);
EXPORT_SYMBOL_GPL
(
cpci_hp_stop
);
drivers/hotplug/cpci_hotplug_pci.c
0 → 100644
View file @
82670e1f
/*
* CompactPCI Hot Plug Driver PCI functions
*
* Copyright (c) 2002 by SOMA Networks, Inc.
*
* 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 <scottm@somanetworks.com>
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/proc_fs.h>
#include "pci_hotplug.h"
#include "cpci_hotplug.h"
#if !defined(CONFIG_HOTPLUG_CPCI_MODULE)
#define MY_NAME "cpci_hotplug"
#else
#define MY_NAME THIS_MODULE->name
#endif
extern
int
cpci_debug
;
#define dbg(format, arg...) \
do { \
if(cpci_debug) \
printk (KERN_DEBUG "%s: " format "\n", \
MY_NAME , ## arg); \
} while(0)
#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
u8
cpci_get_attention_status
(
struct
slot
*
slot
)
{
int
hs_cap
;
u16
hs_csr
;
hs_cap
=
pci_bus_find_capability
(
slot
->
bus
,
slot
->
devfn
,
PCI_CAP_ID_CHSWP
);
if
(
!
hs_cap
)
{
return
0
;
}
if
(
pci_bus_read_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
&
hs_csr
))
{
return
0
;
}
return
hs_csr
&
0x0008
?
1
:
0
;
}
int
cpci_set_attention_status
(
struct
slot
*
slot
,
int
status
)
{
int
hs_cap
;
u16
hs_csr
;
hs_cap
=
pci_bus_find_capability
(
slot
->
bus
,
slot
->
devfn
,
PCI_CAP_ID_CHSWP
);
if
(
!
hs_cap
)
{
return
0
;
}
if
(
pci_bus_read_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
&
hs_csr
))
{
return
0
;
}
if
(
status
)
{
hs_csr
|=
HS_CSR_LOO
;
}
else
{
hs_csr
&=
~
HS_CSR_LOO
;
}
if
(
pci_bus_write_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
hs_csr
))
{
return
0
;
}
return
1
;
}
u16
cpci_get_hs_csr
(
struct
slot
*
slot
)
{
int
hs_cap
;
u16
hs_csr
;
hs_cap
=
pci_bus_find_capability
(
slot
->
bus
,
slot
->
devfn
,
PCI_CAP_ID_CHSWP
);
if
(
!
hs_cap
)
{
return
0xFFFF
;
}
if
(
pci_bus_read_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
&
hs_csr
))
{
return
0xFFFF
;
}
return
hs_csr
;
}
u16
cpci_set_hs_csr
(
struct
slot
*
slot
,
u16
hs_csr
)
{
int
hs_cap
;
u16
new_hs_csr
;
hs_cap
=
pci_bus_find_capability
(
slot
->
bus
,
slot
->
devfn
,
PCI_CAP_ID_CHSWP
);
if
(
!
hs_cap
)
{
return
0xFFFF
;
}
/* Write out the new value */
if
(
pci_bus_write_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
hs_csr
))
{
return
0xFFFF
;
}
/* Read back what we just wrote out */
if
(
pci_bus_read_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
&
new_hs_csr
))
{
return
0xFFFF
;
}
return
new_hs_csr
;
}
int
cpci_check_and_clear_ins
(
struct
slot
*
slot
)
{
int
hs_cap
;
u16
hs_csr
;
int
ins
=
0
;
hs_cap
=
pci_bus_find_capability
(
slot
->
bus
,
slot
->
devfn
,
PCI_CAP_ID_CHSWP
);
if
(
!
hs_cap
)
{
return
0
;
}
if
(
pci_bus_read_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
&
hs_csr
))
{
return
0
;
}
if
(
hs_csr
&
HS_CSR_INS
)
{
/* Clear INS (by setting it) */
if
(
pci_bus_write_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
hs_csr
))
{
ins
=
0
;
}
ins
=
1
;
}
return
ins
;
}
int
cpci_check_ext
(
struct
slot
*
slot
)
{
int
hs_cap
;
u16
hs_csr
;
int
ext
=
0
;
hs_cap
=
pci_bus_find_capability
(
slot
->
bus
,
slot
->
devfn
,
PCI_CAP_ID_CHSWP
);
if
(
!
hs_cap
)
{
return
0
;
}
if
(
pci_bus_read_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
&
hs_csr
))
{
return
0
;
}
if
(
hs_csr
&
HS_CSR_EXT
)
{
ext
=
1
;
}
return
ext
;
}
int
cpci_clear_ext
(
struct
slot
*
slot
)
{
int
hs_cap
;
u16
hs_csr
;
hs_cap
=
pci_bus_find_capability
(
slot
->
bus
,
slot
->
devfn
,
PCI_CAP_ID_CHSWP
);
if
(
!
hs_cap
)
{
return
-
ENODEV
;
}
if
(
pci_bus_read_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
&
hs_csr
))
{
return
-
ENODEV
;
}
if
(
hs_csr
&
HS_CSR_EXT
)
{
/* Clear EXT (by setting it) */
if
(
pci_bus_write_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
hs_csr
))
{
return
-
ENODEV
;
}
}
return
0
;
}
int
cpci_led_on
(
struct
slot
*
slot
)
{
int
hs_cap
;
u16
hs_csr
;
hs_cap
=
pci_bus_find_capability
(
slot
->
bus
,
slot
->
devfn
,
PCI_CAP_ID_CHSWP
);
if
(
!
hs_cap
)
{
return
-
ENODEV
;
}
if
(
pci_bus_read_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
&
hs_csr
))
{
return
-
ENODEV
;
}
if
((
hs_csr
&
HS_CSR_LOO
)
!=
HS_CSR_LOO
)
{
/* Set LOO */
hs_csr
|=
HS_CSR_LOO
;
if
(
pci_bus_write_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
hs_csr
))
{
err
(
"Could not set LOO for slot %s"
,
slot
->
hotplug_slot
->
name
);
return
-
ENODEV
;
}
}
return
0
;
}
int
cpci_led_off
(
struct
slot
*
slot
)
{
int
hs_cap
;
u16
hs_csr
;
hs_cap
=
pci_bus_find_capability
(
slot
->
bus
,
slot
->
devfn
,
PCI_CAP_ID_CHSWP
);
if
(
!
hs_cap
)
{
return
-
ENODEV
;
}
if
(
pci_bus_read_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
&
hs_csr
))
{
return
-
ENODEV
;
}
if
(
hs_csr
&
HS_CSR_LOO
)
{
/* Clear LOO */
hs_csr
&=
~
HS_CSR_LOO
;
if
(
pci_bus_write_config_word
(
slot
->
bus
,
slot
->
devfn
,
hs_cap
+
2
,
hs_csr
))
{
err
(
"Could not clear LOO for slot %s"
,
slot
->
hotplug_slot
->
name
);
return
-
ENODEV
;
}
}
return
0
;
}
/*
* Device configuration functions
*/
static
int
cpci_configure_dev
(
struct
pci_bus
*
bus
,
struct
pci_dev
*
dev
)
{
u8
irq_pin
;
int
r
;
dbg
(
"%s - enter"
,
__FUNCTION__
);
/* NOTE: device already setup from prior scan */
/* FIXME: How would we know if we need to enable the expansion ROM? */
pci_write_config_word
(
dev
,
PCI_ROM_ADDRESS
,
0x00L
);
/* Assign resources */
dbg
(
"assigning resources for %02x:%02x.%x"
,
dev
->
bus
->
number
,
PCI_SLOT
(
dev
->
devfn
),
PCI_FUNC
(
dev
->
devfn
));
for
(
r
=
0
;
r
<
6
;
r
++
)
{
struct
resource
*
res
=
dev
->
resource
+
r
;
if
(
res
->
flags
)
pci_assign_resource
(
dev
,
r
);
}
dbg
(
"finished assigning resources for %02x:%02x.%x"
,
dev
->
bus
->
number
,
PCI_SLOT
(
dev
->
devfn
),
PCI_FUNC
(
dev
->
devfn
));
/* Does this function have an interrupt at all? */
dbg
(
"checking for function interrupt"
);
pci_read_config_byte
(
dev
,
PCI_INTERRUPT_PIN
,
&
irq_pin
);
if
(
irq_pin
)
{
dbg
(
"function uses interrupt pin %d"
,
irq_pin
);
}
/*
* Need to explicitly set irq field to 0 so that it'll get assigned
* by the pcibios platform dependant code called by pci_enable_device.
*/
dev
->
irq
=
0
;
dbg
(
"enabling device"
);
pci_enable_device
(
dev
);
/* XXX check return */
dbg
(
"now dev->irq = %d"
,
dev
->
irq
);
if
(
irq_pin
&&
dev
->
irq
)
{
pci_write_config_byte
(
dev
,
PCI_INTERRUPT_LINE
,
dev
->
irq
);
}
/* Can't use pci_insert_device at the moment, do it manually for now */
pci_proc_attach_device
(
dev
);
dbg
(
"notifying drivers"
);
//pci_announce_device_to_drivers(dev);
dbg
(
"%s - exit"
,
__FUNCTION__
);
return
0
;
}
static
int
cpci_configure_bridge
(
struct
pci_bus
*
bus
,
struct
pci_dev
*
dev
)
{
int
rc
;
struct
pci_bus
*
child
;
struct
resource
*
r
;
u8
max
,
n
;
u16
command
;
dbg
(
"%s - enter"
,
__FUNCTION__
);
/* Do basic bridge initialization */
rc
=
pci_write_config_byte
(
dev
,
PCI_LATENCY_TIMER
,
0x40
);
if
(
rc
)
{
printk
(
KERN_ERR
"%s - write of PCI_LATENCY_TIMER failed
\n
"
,
__FUNCTION__
);
}
rc
=
pci_write_config_byte
(
dev
,
PCI_SEC_LATENCY_TIMER
,
0x40
);
if
(
rc
)
{
printk
(
KERN_ERR
"%s - write of PCI_SEC_LATENCY_TIMER failed
\n
"
,
__FUNCTION__
);
}
rc
=
pci_write_config_byte
(
dev
,
PCI_CACHE_LINE_SIZE
,
L1_CACHE_BYTES
/
4
);
if
(
rc
)
{
printk
(
KERN_ERR
"%s - write of PCI_CACHE_LINE_SIZE failed
\n
"
,
__FUNCTION__
);
}
/*
* Set parent bridge's subordinate field so that configuration space
* access will work in pci_scan_bridge and friends.
*/
max
=
pci_max_busnr
();
bus
->
subordinate
=
max
+
1
;
pci_write_config_byte
(
bus
->
self
,
PCI_SUBORDINATE_BUS
,
max
+
1
);
/* Scan behind bridge */
n
=
pci_scan_bridge
(
bus
,
dev
,
max
,
2
);
child
=
pci_find_bus
(
max
+
1
);
#ifdef CONFIG_PROC_FS
pci_proc_attach_bus
(
child
);
#endif
/*
* Update parent bridge's subordinate field if there were more bridges
* behind the bridge that was scanned.
*/
if
(
n
>
max
)
{
bus
->
subordinate
=
n
;
pci_write_config_byte
(
bus
->
self
,
PCI_SUBORDINATE_BUS
,
n
);
}
/*
* Update the bridge resources of the bridge to accommodate devices
* behind it.
*/
pbus_size_bridges
(
child
);
pbus_assign_resources
(
child
);
/* Enable resource mapping via command register */
command
=
PCI_COMMAND_MASTER
|
PCI_COMMAND_INVALIDATE
|
PCI_COMMAND_PARITY
|
PCI_COMMAND_SERR
;
r
=
child
->
resource
[
0
];
if
(
r
&&
r
->
start
)
{
command
|=
PCI_COMMAND_IO
;
}
r
=
child
->
resource
[
1
];
if
(
r
&&
r
->
start
)
{
command
|=
PCI_COMMAND_MEMORY
;
}
r
=
child
->
resource
[
2
];
if
(
r
&&
r
->
start
)
{
command
|=
PCI_COMMAND_MEMORY
;
}
rc
=
pci_write_config_word
(
dev
,
PCI_COMMAND
,
command
);
if
(
rc
)
{
err
(
"Error setting command register"
);
return
rc
;
}
/* Set bridge control register */
command
=
PCI_BRIDGE_CTL_PARITY
|
PCI_BRIDGE_CTL_SERR
|
PCI_BRIDGE_CTL_NO_ISA
;
rc
=
pci_write_config_word
(
dev
,
PCI_BRIDGE_CONTROL
,
command
);
if
(
rc
)
{
err
(
"Error setting bridge control register"
);
return
rc
;
}
dbg
(
"%s - exit"
,
__FUNCTION__
);
return
0
;
}
static
int
configure_visit_pci_dev
(
struct
pci_dev_wrapped
*
wrapped_dev
,
struct
pci_bus_wrapped
*
wrapped_bus
)
{
int
rc
;
struct
pci_dev
*
dev
=
wrapped_dev
->
dev
;
struct
pci_bus
*
bus
=
wrapped_bus
->
bus
;
struct
slot
*
slot
;
dbg
(
"%s - enter"
,
__FUNCTION__
);
/*
* We need to fix up the hotplug representation with the Linux
* representation.
*/
slot
=
cpci_find_slot
(
dev
->
bus
,
dev
->
devfn
);
if
(
slot
)
{
slot
->
dev
=
dev
;
}
/* If it's a bridge, scan behind it for devices */
if
(
dev
->
hdr_type
==
PCI_HEADER_TYPE_BRIDGE
)
{
rc
=
cpci_configure_bridge
(
bus
,
dev
);
if
(
rc
)
return
rc
;
}
/* Actually configure device */
if
(
dev
)
{
rc
=
cpci_configure_dev
(
bus
,
dev
);
if
(
rc
)
return
rc
;
}
dbg
(
"%s - exit"
,
__FUNCTION__
);
return
0
;
}
static
int
unconfigure_visit_pci_dev_phase1
(
struct
pci_dev_wrapped
*
wrapped_dev
,
struct
pci_bus_wrapped
*
wrapped_bus
)
{
struct
pci_dev
*
dev
=
wrapped_dev
->
dev
;
dbg
(
"%s - enter"
,
__FUNCTION__
);
dbg
(
"attempting removal of driver for device %02x:%02x.%x"
,
dev
->
bus
->
number
,
PCI_SLOT
(
dev
->
devfn
),
PCI_FUNC
(
dev
->
devfn
));
/* Now, remove the Linux Driver representation */
if
(
dev
->
driver
)
{
dbg
(
"device is attached to a driver"
);
if
(
dev
->
driver
->
remove
)
{
dev
->
driver
->
remove
(
dev
);
dbg
(
"driver was removed"
);
}
dev
->
driver
=
NULL
;
}
dbg
(
"%s - exit"
,
__FUNCTION__
);
return
pci_is_dev_in_use
(
dev
);
}
static
int
unconfigure_visit_pci_dev_phase2
(
struct
pci_dev_wrapped
*
wrapped_dev
,
struct
pci_bus_wrapped
*
wrapped_bus
)
{
struct
pci_dev
*
dev
=
wrapped_dev
->
dev
;
struct
slot
*
slot
;
dbg
(
"%s - enter"
,
__FUNCTION__
);
if
(
!
dev
)
return
-
ENODEV
;
/* Remove the Linux representation */
if
(
pci_remove_device_safe
(
dev
)
==
0
)
{
kfree
(
dev
);
}
else
{
err
(
"Could not remove device
\n
"
);
return
-
1
;
}
/*
* Now remove the hotplug representation.
*/
slot
=
cpci_find_slot
(
dev
->
bus
,
dev
->
devfn
);
if
(
slot
)
{
slot
->
dev
=
NULL
;
}
else
{
dbg
(
"No hotplug representation for %02x:%02x.%x"
,
dev
->
bus
->
number
,
PCI_SLOT
(
dev
->
devfn
),
PCI_FUNC
(
dev
->
devfn
));
}
dbg
(
"%s - exit"
,
__FUNCTION__
);
return
0
;
}
static
int
unconfigure_visit_pci_bus_phase2
(
struct
pci_bus_wrapped
*
wrapped_bus
,
struct
pci_dev_wrapped
*
wrapped_dev
)
{
struct
pci_bus
*
bus
=
wrapped_bus
->
bus
;
struct
pci_bus
*
parent
=
bus
->
self
->
bus
;
dbg
(
"%s - enter"
,
__FUNCTION__
);
/* The cleanup code for proc entries regarding buses should be in the kernel... */
if
(
bus
->
procdir
)
dbg
(
"detach_pci_bus %s"
,
bus
->
procdir
->
name
);
pci_proc_detach_bus
(
bus
);
/* The cleanup code should live in the kernel... */
bus
->
self
->
subordinate
=
NULL
;
/* unlink from parent bus */
list_del
(
&
bus
->
node
);
/* Now, remove */
if
(
bus
)
kfree
(
bus
);
/* Update parent's subordinate field */
if
(
parent
)
{
u8
n
=
pci_bus_max_busnr
(
parent
);
if
(
n
<
parent
->
subordinate
)
{
parent
->
subordinate
=
n
;
pci_write_config_byte
(
parent
->
self
,
PCI_SUBORDINATE_BUS
,
n
);
}
}
dbg
(
"%s - exit"
,
__FUNCTION__
);
return
0
;
}
static
struct
pci_visit
configure_functions
=
{
visit_pci_dev:
configure_visit_pci_dev
,
};
static
struct
pci_visit
unconfigure_functions_phase1
=
{
post_visit_pci_dev:
unconfigure_visit_pci_dev_phase1
};
static
struct
pci_visit
unconfigure_functions_phase2
=
{
post_visit_pci_bus:
unconfigure_visit_pci_bus_phase2
,
post_visit_pci_dev:
unconfigure_visit_pci_dev_phase2
};
int
cpci_configure_slot
(
struct
slot
*
slot
)
{
int
rc
=
0
;
dbg
(
"%s - enter"
,
__FUNCTION__
);
if
(
slot
->
dev
==
NULL
)
{
dbg
(
"pci_dev null, finding %02x:%02x:%x"
,
slot
->
bus
->
number
,
PCI_SLOT
(
slot
->
devfn
),
PCI_FUNC
(
slot
->
devfn
));
slot
->
dev
=
pci_find_slot
(
slot
->
bus
->
number
,
slot
->
devfn
);
}
/* Still NULL? Well then scan for it! */
if
(
slot
->
dev
==
NULL
)
{
struct
pci_dev
dev0
;
dbg
(
"pci_dev still null"
);
memset
(
&
dev0
,
0
,
sizeof
(
struct
pci_dev
));
dev0
.
bus
=
slot
->
bus
;
dev0
.
devfn
=
slot
->
devfn
;
dev0
.
sysdata
=
slot
->
bus
->
self
->
sysdata
;
/*
* This will generate pci_dev structures for all functions, but
* we will only call this case when lookup fails.
*/
slot
->
dev
=
pci_scan_slot
(
&
dev0
);
if
(
slot
->
dev
==
NULL
)
{
err
(
"Could not find PCI device for slot %02x"
,
slot
->
number
);
return
0
;
}
}
dbg
(
"slot->dev = %p"
,
slot
->
dev
);
if
(
slot
->
dev
)
{
struct
pci_dev
*
dev
;
struct
pci_dev_wrapped
wrapped_dev
;
struct
pci_bus_wrapped
wrapped_bus
;
int
i
;
memset
(
&
wrapped_dev
,
0
,
sizeof
(
struct
pci_dev_wrapped
));
memset
(
&
wrapped_bus
,
0
,
sizeof
(
struct
pci_bus_wrapped
));
for
(
i
=
0
;
i
<
8
;
i
++
)
{
dev
=
pci_find_slot
(
slot
->
bus
->
number
,
PCI_DEVFN
(
PCI_SLOT
(
slot
->
dev
->
devfn
),
i
));
if
(
!
dev
)
continue
;
wrapped_dev
.
dev
=
dev
;
wrapped_bus
.
bus
=
slot
->
dev
->
bus
;
rc
=
pci_visit_dev
(
&
configure_functions
,
&
wrapped_dev
,
&
wrapped_bus
);
}
}
dbg
(
"%s - exit, rc = %d"
,
__FUNCTION__
,
rc
);
return
rc
;
}
int
cpci_unconfigure_slot
(
struct
slot
*
slot
)
{
int
rc
=
0
;
int
i
;
struct
pci_dev_wrapped
wrapped_dev
;
struct
pci_bus_wrapped
wrapped_bus
;
struct
pci_dev
*
dev
;
dbg
(
"%s - enter"
,
__FUNCTION__
);
if
(
!
slot
->
dev
)
{
err
(
"No device for slot %02x
\n
"
,
slot
->
number
);
return
-
ENODEV
;
}
memset
(
&
wrapped_dev
,
0
,
sizeof
(
struct
pci_dev_wrapped
));
memset
(
&
wrapped_bus
,
0
,
sizeof
(
struct
pci_bus_wrapped
));
for
(
i
=
0
;
i
<
8
;
i
++
)
{
dev
=
pci_find_slot
(
slot
->
bus
->
number
,
PCI_DEVFN
(
PCI_SLOT
(
slot
->
devfn
),
i
));
if
(
dev
)
{
wrapped_dev
.
dev
=
dev
;
wrapped_bus
.
bus
=
dev
->
bus
;
dbg
(
"%s - unconfigure phase 1"
,
__FUNCTION__
);
rc
=
pci_visit_dev
(
&
unconfigure_functions_phase1
,
&
wrapped_dev
,
&
wrapped_bus
);
if
(
rc
)
{
break
;
}
dbg
(
"%s - unconfigure phase 2"
,
__FUNCTION__
);
rc
=
pci_visit_dev
(
&
unconfigure_functions_phase2
,
&
wrapped_dev
,
&
wrapped_bus
);
if
(
rc
)
break
;
}
}
dbg
(
"%s - exit, rc = %d"
,
__FUNCTION__
,
rc
);
return
rc
;
}
drivers/hotplug/cpcihp_generic.c
0 → 100644
View file @
82670e1f
/*
* cpcihp_generic.c
*
* Generic port I/O CompactPCI driver
*
* Copyright 2002 SOMA Networks, Inc.
* Copyright 2001 Intel San Luis Obispo
* Copyright 2000,2001 MontaVista Software Inc.
*
* 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 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.
*
* This generic CompactPCI hotplug driver should allow using the PCI hotplug
* mechanism on any CompactPCI board that exposes the #ENUM signal as a bit
* in a system register that can be read through standard port I/O.
*
* Send feedback to <scottm@somanetworks.com>
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/pci.h>
#include "cpci_hotplug.h"
#define DRIVER_VERSION "0.1"
#define DRIVER_AUTHOR "Scott Murray <scottm@somanetworks.com>"
#define DRIVER_DESC "Generic port I/O CompactPCI Hot Plug Driver"
#if !defined(CONFIG_HOTPLUG_CPCI_GENERIC_MODULE)
#define MY_NAME "cpcihp_generic"
#else
#define MY_NAME THIS_MODULE->name
#endif
#define dbg(format, arg...) \
do { \
if(debug) \
printk (KERN_DEBUG "%s: " format "\n", \
MY_NAME , ## arg); \
} while(0)
#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
/* local variables */
static
int
debug
;
static
char
*
bridge
;
static
u8
bridge_busnr
;
static
u8
bridge_slot
;
static
struct
pci_bus
*
bus
;
static
u8
first_slot
;
static
u8
last_slot
;
static
u16
port
;
static
unsigned
int
enum_bit
;
static
u8
enum_mask
;
static
struct
cpci_hp_controller_ops
generic_hpc_ops
;
static
struct
cpci_hp_controller
generic_hpc
;
/* The following allows configuring the driver when it's compiled into the kernel */
#ifndef MODULE
static
int
__init
cpcihp_generic_setup
(
char
*
str
)
{
char
*
p
;
unsigned
long
tmp
;
if
(
!
str
)
return
-
EINVAL
;
bridge
=
str
;
p
=
strchr
(
str
,
','
);
str
=
p
+
1
;
if
(
!
(
p
&&
*
str
&&
*
p
==
','
))
goto
setup_error
;
tmp
=
simple_strtoul
(
str
,
&
p
,
0
);
if
(
p
==
str
||
tmp
>
0xff
)
{
err
(
"hotplug bus first slot number out of range"
);
goto
setup_error
;
}
first_slot
=
(
u8
)
tmp
;
str
=
p
+
1
;
if
(
!
(
*
str
&&
*
p
==
','
))
return
-
EINVAL
;
tmp
=
simple_strtoul
(
str
,
&
p
,
0
);
if
(
p
==
str
||
tmp
>
0xff
)
{
err
(
"hotplug bus last slot number out of range"
);
goto
setup_error
;
}
last_slot
=
(
u8
)
tmp
;
str
=
p
+
1
;
if
(
!
(
*
str
&&
*
p
==
','
))
goto
setup_error
;
tmp
=
simple_strtoul
(
str
,
&
p
,
0
);
if
(
p
==
str
||
tmp
>
0xffff
)
{
err
(
"port number out of range"
);
goto
setup_error
;
}
port
=
(
u16
)
tmp
;
str
=
p
+
1
;
if
(
!
(
*
str
&&
*
p
==
','
))
goto
setup_error
;
tmp
=
simple_strtoul
(
str
,
&
p
,
0
);
if
(
p
==
str
)
{
err
(
"invalid #ENUM bit number"
);
goto
setup_error
;
}
enum_bit
=
(
u8
)
tmp
;
str
=
p
+
1
;
if
(
*
str
&&
*
p
==
','
)
{
tmp
=
simple_strtoul
(
str
,
&
p
,
0
);
if
(
p
!=
str
)
debug
=
(
int
)
tmp
;
}
return
0
;
setup_error:
bridge
=
NULL
;
return
-
EINVAL
;
}
__setup
(
"cpcihp_generic="
,
cpcihp_generic_setup
);
#endif
static
int
__init
validate_parameters
(
void
)
{
char
*
str
;
char
*
p
;
unsigned
long
tmp
;
if
(
!
bridge
)
{
info
(
"not configured, disabling."
);
return
1
;
}
str
=
bridge
;
if
(
!*
str
)
return
-
EINVAL
;
tmp
=
simple_strtoul
(
str
,
&
p
,
16
);
if
(
p
==
str
||
tmp
>
0xff
)
{
err
(
"Invalid hotplug bus bridge device bus number"
);
return
-
EINVAL
;
}
bridge_busnr
=
(
u8
)
tmp
;
dbg
(
"bridge_busnr = 0x%02x"
,
bridge_busnr
);
if
(
*
p
!=
':'
)
{
err
(
"Invalid hotplug bus bridge device"
);
return
-
EINVAL
;
}
str
=
p
+
1
;
tmp
=
simple_strtoul
(
str
,
&
p
,
16
);
if
(
p
==
str
||
tmp
>
0x1f
)
{
err
(
"Invalid hotplug bus bridge device slot number"
);
return
-
EINVAL
;
}
bridge_slot
=
(
u8
)
tmp
;
dbg
(
"bridge_slot = 0x%02x"
,
bridge_slot
);
dbg
(
"first_slot = 0x%02x"
,
first_slot
);
dbg
(
"last_slot = 0x%02x"
,
last_slot
);
if
(
!
(
first_slot
&&
last_slot
))
{
err
(
"Need to specify first_slot and last_slot"
);
return
-
EINVAL
;
}
if
(
last_slot
<
first_slot
)
{
err
(
"first_slot must be less than last_slot"
);
return
-
EINVAL
;
}
dbg
(
"port = 0x%04x"
,
port
);
dbg
(
"enum_bit = 0x%02x"
,
enum_bit
);
if
(
enum_bit
>
7
)
{
err
(
"Invalid #ENUM bit"
);
return
-
EINVAL
;
}
enum_mask
=
1
<<
enum_bit
;
return
0
;
}
static
int
query_enum
(
void
)
{
u8
value
;
value
=
inb_p
(
port
);
return
((
value
&
enum_mask
)
==
enum_mask
);
}
static
int
__init
cpcihp_generic_init
(
void
)
{
int
status
;
struct
resource
*
r
;
struct
pci_dev
*
dev
;
info
(
DRIVER_DESC
" version: "
DRIVER_VERSION
);
status
=
validate_parameters
();
if
(
status
!=
0
)
return
status
;
r
=
request_region
(
port
,
1
,
"#ENUM hotswap signal register"
);
if
(
!
r
)
return
-
EBUSY
;
dev
=
pci_find_slot
(
bridge_busnr
,
PCI_DEVFN
(
bridge_slot
,
0
));
if
(
!
dev
||
dev
->
hdr_type
!=
PCI_HEADER_TYPE_BRIDGE
)
{
err
(
"Invalid bridge device %s"
,
bridge
);
return
-
EINVAL
;
}
bus
=
dev
->
subordinate
;
memset
(
&
generic_hpc
,
0
,
sizeof
(
struct
cpci_hp_controller
));
generic_hpc_ops
.
query_enum
=
query_enum
;
generic_hpc
.
ops
=
&
generic_hpc_ops
;
status
=
cpci_hp_register_controller
(
&
generic_hpc
);
if
(
status
!=
0
)
{
err
(
"Could not register cPCI hotplug controller"
);
return
-
ENODEV
;
}
dbg
(
"registered controller"
);
status
=
cpci_hp_register_bus
(
bus
,
first_slot
,
last_slot
);
if
(
status
!=
0
)
{
err
(
"Could not register cPCI hotplug bus"
);
goto
init_bus_register_error
;
}
dbg
(
"registered bus"
);
status
=
cpci_hp_start
();
if
(
status
!=
0
)
{
err
(
"Could not started cPCI hotplug system"
);
goto
init_start_error
;
}
dbg
(
"started cpci hp system"
);
return
0
;
init_start_error:
cpci_hp_unregister_bus
(
bus
);
init_bus_register_error:
cpci_hp_unregister_controller
(
&
generic_hpc
);
err
(
"status = %d"
,
status
);
return
status
;
}
static
void
__exit
cpcihp_generic_exit
(
void
)
{
cpci_hp_stop
();
cpci_hp_unregister_bus
(
bus
);
cpci_hp_unregister_controller
(
&
generic_hpc
);
release_region
(
port
,
1
);
}
module_init
(
cpcihp_generic_init
);
module_exit
(
cpcihp_generic_exit
);
MODULE_AUTHOR
(
DRIVER_AUTHOR
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
MODULE_PARM
(
debug
,
"i"
);
MODULE_PARM_DESC
(
debug
,
"Debugging mode enabled or not"
);
MODULE_PARM
(
bridge
,
"s"
);
MODULE_PARM_DESC
(
bridge
,
"Hotswap bus bridge device, <bus>:<slot> (bus and slot are in hexadecimal)"
);
MODULE_PARM
(
first_slot
,
"b"
);
MODULE_PARM_DESC
(
first_slot
,
"Hotswap bus first slot number"
);
MODULE_PARM
(
last_slot
,
"b"
);
MODULE_PARM_DESC
(
last_slot
,
"Hotswap bus last slot number"
);
MODULE_PARM
(
port
,
"h"
);
MODULE_PARM_DESC
(
port
,
"#ENUM signal I/O port"
);
MODULE_PARM
(
enum_bit
,
"i"
);
MODULE_PARM_DESC
(
enum_bit
,
"#ENUM signal bit (0-7)"
);
drivers/hotplug/cpcihp_zt5550.c
0 → 100644
View file @
82670e1f
/*
* cpcihp_zt5550.c
*
* Intel/Ziatech ZT5550 CompactPCI Host Controller driver
*
* Copyright 2002 SOMA Networks, Inc.
* Copyright 2001 Intel San Luis Obispo
* Copyright 2000,2001 MontaVista Software Inc.
*
* 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 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 <scottm@somanetworks.com>
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/pci.h>
#include "cpci_hotplug.h"
#include "cpcihp_zt5550.h"
#define DRIVER_VERSION "0.2"
#define DRIVER_AUTHOR "Scott Murray <scottm@somanetworks.com>"
#define DRIVER_DESC "ZT5550 CompactPCI Hot Plug Driver"
#if !defined(CONFIG_HOTPLUG_PCI_CPCI_ZT5550_MODULE)
#define MY_NAME "cpcihp_zt5550"
#else
#define MY_NAME THIS_MODULE->name
#endif
#define dbg(format, arg...) \
do { \
if(debug) \
printk (KERN_DEBUG "%s: " format "\n", \
MY_NAME , ## arg); \
} while(0)
#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
/* local variables */
static
int
debug
;
static
int
poll
;
static
struct
cpci_hp_controller_ops
zt5550_hpc_ops
;
static
struct
cpci_hp_controller
zt5550_hpc
;
/* Primary cPCI bus bridge device */
static
struct
pci_dev
*
bus0_dev
;
static
struct
pci_bus
*
bus0
;
/* Host controller device */
static
struct
pci_dev
*
hc_dev
;
/* Host controller register addresses */
static
void
*
hc_registers
;
static
void
*
csr_hc_index
;
static
void
*
csr_hc_data
;
static
void
*
csr_int_status
;
static
void
*
csr_int_mask
;
static
int
zt5550_hc_config
(
struct
pci_dev
*
pdev
)
{
/* Since we know that no boards exist with two HC chips, treat it as an error */
if
(
hc_dev
)
{
err
(
"too many host controller devices?"
);
return
-
EBUSY
;
}
hc_dev
=
pdev
;
dbg
(
"hc_dev = %p"
,
hc_dev
);
dbg
(
"pci resource start %lx"
,
pci_resource_start
(
hc_dev
,
1
));
dbg
(
"pci resource len %lx"
,
pci_resource_len
(
hc_dev
,
1
));
if
(
!
request_mem_region
(
pci_resource_start
(
hc_dev
,
1
),
pci_resource_len
(
hc_dev
,
1
),
MY_NAME
))
{
err
(
"cannot reserve MMIO region"
);
return
-
ENOMEM
;
}
hc_registers
=
ioremap
(
pci_resource_start
(
hc_dev
,
1
),
pci_resource_len
(
hc_dev
,
1
));
if
(
!
hc_registers
)
{
err
(
"cannot remap MMIO region %lx @ %lx"
,
pci_resource_len
(
hc_dev
,
1
),
pci_resource_start
(
hc_dev
,
1
));
release_mem_region
(
pci_resource_start
(
hc_dev
,
1
),
pci_resource_len
(
hc_dev
,
1
));
return
-
ENODEV
;
}
csr_hc_index
=
hc_registers
+
CSR_HCINDEX
;
csr_hc_data
=
hc_registers
+
CSR_HCDATA
;
csr_int_status
=
hc_registers
+
CSR_INTSTAT
;
csr_int_mask
=
hc_registers
+
CSR_INTMASK
;
/*
* Disable host control, fault and serial interrupts
*/
dbg
(
"disabling host control, fault and serial interrupts"
);
writeb
((
u8
)
HC_INT_MASK_REG
,
csr_hc_index
);
writeb
((
u8
)
ALL_INDEXED_INTS_MASK
,
csr_hc_data
);
dbg
(
"disabled host control, fault and serial interrupts"
);
/*
* Disable timer0, timer1 and ENUM interrupts
*/
dbg
(
"disabling timer0, timer1 and ENUM interrupts"
);
writeb
((
u8
)
ALL_DIRECT_INTS_MASK
,
csr_int_mask
);
dbg
(
"disabled timer0, timer1 and ENUM interrupts"
);
return
0
;
}
static
int
zt5550_hc_cleanup
(
void
)
{
if
(
!
hc_dev
)
return
-
ENODEV
;
release_mem_region
(
pci_resource_start
(
hc_dev
,
1
),
pci_resource_len
(
hc_dev
,
1
));
return
0
;
}
static
int
zt5550_hc_query_enum
(
void
)
{
u8
value
;
value
=
inb_p
(
ENUM_PORT
);
return
((
value
&
ENUM_MASK
)
==
ENUM_MASK
);
}
static
int
zt5550_hc_check_irq
(
void
*
dev_id
)
{
int
ret
;
u8
reg
;
ret
=
0
;
if
(
dev_id
==
zt5550_hpc
.
dev_id
)
{
reg
=
readb
(
csr_int_status
);
if
(
reg
)
ret
=
1
;
}
return
ret
;
}
static
int
zt5550_hc_enable_irq
(
void
)
{
u8
reg
;
if
(
hc_dev
==
NULL
)
{
return
-
ENODEV
;
}
reg
=
readb
(
csr_int_mask
);
reg
=
reg
&
~
ENUM_INT_MASK
;
writeb
(
reg
,
csr_int_mask
);
return
0
;
}
int
zt5550_hc_disable_irq
(
void
)
{
u8
reg
;
if
(
hc_dev
==
NULL
)
{
return
-
ENODEV
;
}
reg
=
readb
(
csr_int_mask
);
reg
=
reg
|
ENUM_INT_MASK
;
writeb
(
reg
,
csr_int_mask
);
return
0
;
}
static
int
__devinit
zt5550_hc_init_one
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
ent
)
{
int
status
;
status
=
zt5550_hc_config
(
pdev
);
if
(
status
!=
0
)
{
return
status
;
}
dbg
(
"returned from zt5550_hc_config"
);
memset
(
&
zt5550_hpc
,
0
,
sizeof
(
struct
cpci_hp_controller
));
zt5550_hpc_ops
.
query_enum
=
zt5550_hc_query_enum
;
zt5550_hpc
.
ops
=
&
zt5550_hpc_ops
;
if
(
!
poll
)
{
zt5550_hpc
.
irq
=
hc_dev
->
irq
;
zt5550_hpc
.
irq_flags
=
SA_SHIRQ
;
zt5550_hpc
.
dev_id
=
hc_dev
;
zt5550_hpc_ops
.
enable_irq
=
zt5550_hc_enable_irq
;
zt5550_hpc_ops
.
disable_irq
=
zt5550_hc_disable_irq
;
zt5550_hpc_ops
.
check_irq
=
zt5550_hc_check_irq
;
}
else
{
info
(
"using ENUM# polling mode"
);
}
status
=
cpci_hp_register_controller
(
&
zt5550_hpc
);
if
(
status
!=
0
)
{
err
(
"could not register cPCI hotplug controller"
);
goto
init_hc_error
;
}
dbg
(
"registered controller"
);
/* Look for first device matching cPCI bus's bridge vendor and device IDs */
if
(
!
(
bus0_dev
=
pci_find_device
(
PCI_VENDOR_ID_DEC
,
PCI_DEVICE_ID_DEC_21154
,
NULL
)))
{
status
=
-
ENODEV
;
goto
init_register_error
;
}
bus0
=
bus0_dev
->
subordinate
;
status
=
cpci_hp_register_bus
(
bus0
,
0x0a
,
0x0f
);
if
(
status
!=
0
)
{
err
(
"could not register cPCI hotplug bus"
);
goto
init_register_error
;
}
dbg
(
"registered bus"
);
status
=
cpci_hp_start
();
if
(
status
!=
0
)
{
err
(
"could not started cPCI hotplug system"
);
cpci_hp_unregister_bus
(
bus0
);
goto
init_register_error
;
}
dbg
(
"started cpci hp system"
);
return
0
;
init_register_error:
cpci_hp_unregister_controller
(
&
zt5550_hpc
);
init_hc_error:
err
(
"status = %d"
,
status
);
zt5550_hc_cleanup
();
return
status
;
}
static
void
__devexit
zt5550_hc_remove_one
(
struct
pci_dev
*
pdev
)
{
cpci_hp_stop
();
cpci_hp_unregister_bus
(
bus0
);
cpci_hp_unregister_controller
(
&
zt5550_hpc
);
zt5550_hc_cleanup
();
}
static
struct
pci_device_id
zt5550_hc_pci_tbl
[]
__devinitdata
=
{
{
PCI_VENDOR_ID_ZIATECH
,
PCI_DEVICE_ID_ZIATECH_5550_HC
,
PCI_ANY_ID
,
PCI_ANY_ID
,
},
{
0
,
}
};
MODULE_DEVICE_TABLE
(
pci
,
zt5550_hc_pci_tbl
);
static
struct
pci_driver
zt5550_hc_driver
=
{
.
name
=
"zt5550_hc"
,
.
id_table
=
zt5550_hc_pci_tbl
,
.
probe
=
zt5550_hc_init_one
,
.
remove
=
__devexit_p
(
zt5550_hc_remove_one
),
};
static
int
__init
zt5550_init
(
void
)
{
struct
resource
*
r
;
info
(
DRIVER_DESC
" version: "
DRIVER_VERSION
);
r
=
request_region
(
ENUM_PORT
,
1
,
"#ENUM hotswap signal register"
);
if
(
!
r
)
return
-
EBUSY
;
return
pci_module_init
(
&
zt5550_hc_driver
);
}
static
void
__exit
zt5550_exit
(
void
)
{
pci_unregister_driver
(
&
zt5550_hc_driver
);
release_region
(
ENUM_PORT
,
1
);
}
module_init
(
zt5550_init
);
module_exit
(
zt5550_exit
);
MODULE_AUTHOR
(
DRIVER_AUTHOR
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
MODULE_PARM
(
debug
,
"i"
);
MODULE_PARM_DESC
(
debug
,
"Debugging mode enabled or not"
);
MODULE_PARM
(
poll
,
"i"
);
MODULE_PARM_DESC
(
poll
,
"#ENUM polling mode enabled or not"
);
drivers/hotplug/cpcihp_zt5550.h
0 → 100644
View file @
82670e1f
/*
* cpcihp_zt5550.h
*
* Intel/Ziatech ZT5550 CompactPCI Host Controller driver definitions
*
* Copyright 2002 SOMA Networks, Inc.
* Copyright 2001 Intel San Luis Obispo
* Copyright 2000,2001 MontaVista Software Inc.
*
* 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 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 <scottm@somanetworks.com>
*/
#ifndef _CPCIHP_ZT5550_H
#define _CPCIHP_ZT5550_H
/* Direct registers */
#define CSR_HCINDEX 0x00
#define CSR_HCDATA 0x04
#define CSR_INTSTAT 0x08
#define CSR_INTMASK 0x09
#define CSR_CNT0CMD 0x0C
#define CSR_CNT1CMD 0x0E
#define CSR_CNT0 0x10
#define CSR_CNT1 0x14
/* Masks for interrupt bits in CSR_INTMASK direct register */
#define CNT0_INT_MASK 0x01
#define CNT1_INT_MASK 0x02
#define ENUM_INT_MASK 0x04
#define ALL_DIRECT_INTS_MASK 0x07
/* Indexed registers (through CSR_INDEX, CSR_DATA) */
#define HC_INT_MASK_REG 0x04
#define HC_STATUS_REG 0x08
#define HC_CMD_REG 0x0C
#define ARB_CONFIG_GNT_REG 0x10
#define ARB_CONFIG_CFG_REG 0x12
#define ARB_CONFIG_REG 0x10
#define ISOL_CONFIG_REG 0x18
#define FAULT_STATUS_REG 0x20
#define FAULT_CONFIG_REG 0x24
#define WD_CONFIG_REG 0x2C
#define HC_DIAG_REG 0x30
#define SERIAL_COMM_REG 0x34
#define SERIAL_OUT_REG 0x38
#define SERIAL_IN_REG 0x3C
/* Masks for interrupt bits in HC_INT_MASK_REG indexed register */
#define SERIAL_INT_MASK 0x01
#define FAULT_INT_MASK 0x02
#define HCF_INT_MASK 0x04
#define ALL_INDEXED_INTS_MASK 0x07
/* Digital I/O port storing ENUM# */
#define ENUM_PORT 0xE1
/* Mask to get to the ENUM# bit on the bus */
#define ENUM_MASK 0x40
#endif
/* _CPCIHP_ZT5550_H */
drivers/hotplug/pci_hotplug.h
View file @
82670e1f
...
...
@@ -167,5 +167,9 @@ extern int pci_visit_dev (struct pci_visit *fn,
struct
pci_dev_wrapped
*
wrapped_dev
,
struct
pci_bus_wrapped
*
wrapped_parent
);
int
pci_is_dev_in_use
(
struct
pci_dev
*
dev
);
int
pci_remove_device_safe
(
struct
pci_dev
*
dev
);
#endif
drivers/hotplug/pci_hotplug_util.c
View file @
82670e1f
...
...
@@ -94,15 +94,12 @@ static int pci_visit_bus (struct pci_visit * fn, struct pci_bus_wrapped *wrapped
static
int
pci_visit_bridge
(
struct
pci_visit
*
fn
,
struct
pci_dev_wrapped
*
wrapped_dev
,
struct
pci_bus_wrapped
*
wrapped_parent
)
{
struct
pci_bus
*
bus
=
wrapped_dev
->
dev
->
subordinate
;
struct
pci_bus
*
bus
;
struct
pci_bus_wrapped
wrapped_bus
;
int
result
;
memset
(
&
wrapped_bus
,
0
,
sizeof
(
struct
pci_bus_wrapped
));
wrapped_bus
.
bus
=
bus
;
int
result
=
0
;
dbg
(
"scanning bridge %02x, %02x
\n
"
,
wrapped_dev
->
dev
->
devfn
>>
3
,
wrapped_dev
->
dev
->
devfn
&
0x7
);
dbg
(
"scanning bridge %02x, %02x
\n
"
,
PCI_SLOT
(
wrapped_dev
->
dev
->
devfn
)
,
PCI_FUNC
(
wrapped_dev
->
dev
->
devfn
)
);
if
(
fn
->
visit_pci_dev
)
{
result
=
fn
->
visit_pci_dev
(
wrapped_dev
,
wrapped_parent
);
...
...
@@ -110,7 +107,13 @@ static int pci_visit_bridge (struct pci_visit * fn, struct pci_dev_wrapped *wrap
return
result
;
}
bus
=
wrapped_dev
->
dev
->
subordinate
;
if
(
bus
)
{
memset
(
&
wrapped_bus
,
0
,
sizeof
(
struct
pci_bus_wrapped
));
wrapped_bus
.
bus
=
bus
;
result
=
pci_visit_bus
(
fn
,
&
wrapped_bus
,
wrapped_dev
);
}
return
result
;
}
...
...
@@ -153,6 +156,62 @@ int pci_visit_dev (struct pci_visit *fn, struct pci_dev_wrapped *wrapped_dev, st
return
result
;
}
/**
* pci_is_dev_in_use - query devices' usage
* @dev: PCI device to query
*
* Queries whether a given PCI device is in use by a driver or not.
* Returns 1 if the device is in use, 0 if it is not.
*/
int
pci_is_dev_in_use
(
struct
pci_dev
*
dev
)
{
/*
* dev->driver will be set if the device is in use by a new-style
* driver -- otherwise, check the device's regions to see if any
* driver has claimed them.
*/
int
i
;
int
inuse
=
0
;
if
(
dev
->
driver
)
{
/* Assume driver feels responsible */
return
1
;
}
for
(
i
=
0
;
!
dev
->
driver
&&
!
inuse
&&
(
i
<
6
);
i
++
)
{
if
(
!
pci_resource_start
(
dev
,
i
))
continue
;
if
(
pci_resource_flags
(
dev
,
i
)
&
IORESOURCE_IO
)
{
inuse
=
check_region
(
pci_resource_start
(
dev
,
i
),
pci_resource_len
(
dev
,
i
));
}
else
if
(
pci_resource_flags
(
dev
,
i
)
&
IORESOURCE_MEM
)
{
inuse
=
check_mem_region
(
pci_resource_start
(
dev
,
i
),
pci_resource_len
(
dev
,
i
));
}
}
return
inuse
;
}
/**
* pci_remove_device_safe - remove an unused hotplug device
* @dev: the device to remove
*
* Delete the device structure from the device lists and
* notify userspace (/sbin/hotplug), but only if the device
* in question is not being used by a driver.
* Returns 0 on success.
*/
int
pci_remove_device_safe
(
struct
pci_dev
*
dev
)
{
if
(
pci_is_dev_in_use
(
dev
))
{
return
-
EBUSY
;
}
pci_remove_device
(
dev
);
return
0
;
}
EXPORT_SYMBOL
(
pci_visit_dev
);
EXPORT_SYMBOL
(
pci_is_dev_in_use
);
EXPORT_SYMBOL
(
pci_remove_device_safe
);
drivers/pci/Makefile
View file @
82670e1f
...
...
@@ -3,7 +3,7 @@
#
export-objs
:=
access.o hotplug.o pci-driver.o pci.o pool.o
\
probe.o proc.o search.o compat.o
probe.o proc.o search.o compat.o
setup-bus.o
obj-y
+=
access.o probe.o pci.o pool.o quirks.o
\
compat.o names.o pci-driver.o search.o hotplug.o
...
...
@@ -25,6 +25,11 @@ obj-$(CONFIG_PPC32) += setup-irq.o
obj-$(CONFIG_DDB5476)
+=
setup-bus.o
obj-$(CONFIG_SGI_IP27)
+=
setup-irq.o
# CompactPCI hotplug requires the pbus_* functions
ifdef
CONFIG_HOTPLUG_PCI_CPCI
obj-y
+=
setup-bus.o
endif
ifndef
CONFIG_X86
obj-y
+=
syscall.o
endif
...
...
drivers/pci/hotplug.c
View file @
82670e1f
...
...
@@ -71,8 +71,7 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp,
* @bus: where to insert it
*
* Link the device to both the global PCI device chain and the
* per-bus list of devices, add the /proc entry, and notify
* userspace (/sbin/hotplug).
* per-bus list of devices, add the /proc entry.
*/
void
pci_insert_device
(
struct
pci_dev
*
dev
,
struct
pci_bus
*
bus
)
...
...
drivers/pci/pci.c
View file @
82670e1f
...
...
@@ -24,6 +24,49 @@
#define DBG(x...)
#endif
/**
* pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
* @bus: pointer to PCI bus structure to search
*
* Given a PCI bus, returns the highest PCI bus number present in the set
* including the given PCI bus and its list of child PCI buses.
*/
unsigned
char
__devinit
pci_bus_max_busnr
(
struct
pci_bus
*
bus
)
{
struct
list_head
*
tmp
;
unsigned
char
max
,
n
;
max
=
bus
->
number
;
list_for_each
(
tmp
,
&
bus
->
children
)
{
n
=
pci_bus_max_busnr
(
pci_bus_b
(
tmp
));
if
(
n
>
max
)
max
=
n
;
}
return
max
;
}
/**
* pci_max_busnr - returns maximum PCI bus number
*
* Returns the highest PCI bus number present in the system global list of
* PCI buses.
*/
unsigned
char
__devinit
pci_max_busnr
(
void
)
{
struct
pci_bus
*
bus
;
unsigned
char
max
,
n
;
max
=
0
;
pci_for_each_bus
(
bus
)
{
n
=
pci_bus_max_busnr
(
bus
);
if
(
n
>
max
)
max
=
n
;
}
return
max
;
}
/**
* pci_find_capability - query for devices' capabilities
* @dev: PCI device to query
...
...
@@ -79,6 +122,49 @@ pci_find_capability(struct pci_dev *dev, int cap)
return
0
;
}
/**
* pci_bus_find_capability - query for devices' capabilities
* @dev: PCI device to query
* @cap: capability code
*
* Like pci_find_capability() but works for pci devices that do not have a
* pci_dev structure set up yet.
* Returns the address of the requested capability structure within the
* device's PCI configuration space or 0 in case the device does not
* support it.
*/
int
pci_bus_find_capability
(
struct
pci_bus
*
bus
,
unsigned
int
devfn
,
int
cap
)
{
u16
status
;
u8
pos
,
id
;
int
ttl
=
48
;
struct
pci_dev
*
dev
=
bus
->
self
;
pci_bus_read_config_word
(
bus
,
devfn
,
PCI_STATUS
,
&
status
);
if
(
!
(
status
&
PCI_STATUS_CAP_LIST
))
return
0
;
switch
(
dev
->
hdr_type
)
{
case
PCI_HEADER_TYPE_NORMAL
:
case
PCI_HEADER_TYPE_BRIDGE
:
pci_bus_read_config_byte
(
bus
,
devfn
,
PCI_CAPABILITY_LIST
,
&
pos
);
break
;
case
PCI_HEADER_TYPE_CARDBUS
:
pci_bus_read_config_byte
(
bus
,
devfn
,
PCI_CB_CAPABILITY_LIST
,
&
pos
);
break
;
default:
return
0
;
}
while
(
ttl
--
&&
pos
>=
0x40
)
{
pos
&=
~
3
;
pci_bus_read_config_byte
(
bus
,
devfn
,
pos
+
PCI_CAP_LIST_ID
,
&
id
);
if
(
id
==
0xff
)
break
;
if
(
id
==
cap
)
return
pos
;
pci_bus_read_config_byte
(
bus
,
devfn
,
pos
+
PCI_CAP_LIST_NEXT
,
&
pos
);
}
return
0
;
}
/**
* pci_find_parent_resource - return resource region of parent bus of given region
...
...
@@ -649,7 +735,10 @@ EXPORT_SYMBOL(isa_bridge);
EXPORT_SYMBOL
(
pci_enable_device
);
EXPORT_SYMBOL
(
pci_disable_device
);
EXPORT_SYMBOL
(
pci_max_busnr
);
EXPORT_SYMBOL
(
pci_bus_max_busnr
);
EXPORT_SYMBOL
(
pci_find_capability
);
EXPORT_SYMBOL
(
pci_bus_find_capability
);
EXPORT_SYMBOL
(
pci_release_regions
);
EXPORT_SYMBOL
(
pci_request_regions
);
EXPORT_SYMBOL
(
pci_release_region
);
...
...
drivers/pci/probe.c
View file @
82670e1f
...
...
@@ -254,7 +254,7 @@ struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_de
* them, we proceed to assigning numbers to the remaining buses in
* order to avoid overlaps between old and new bus numbers.
*/
static
int
__devinit
pci_scan_bridge
(
struct
pci_bus
*
bus
,
struct
pci_dev
*
dev
,
int
max
,
int
pass
)
int
__devinit
pci_scan_bridge
(
struct
pci_bus
*
bus
,
struct
pci_dev
*
dev
,
int
max
,
int
pass
)
{
unsigned
int
buses
;
unsigned
short
cr
;
...
...
@@ -480,8 +480,7 @@ struct pci_dev * __devinit pci_scan_slot(struct pci_dev *temp)
/*
* Link the device to both the global PCI device chain and
* the per-bus list of devices and call /sbin/hotplug if we
* should.
* the per-bus list of devices and add the /proc entry.
*/
pci_insert_device
(
dev
,
bus
);
...
...
@@ -596,4 +595,5 @@ EXPORT_SYMBOL(pci_add_new_bus);
EXPORT_SYMBOL
(
pci_do_scan_bus
);
EXPORT_SYMBOL
(
pci_scan_slot
);
EXPORT_SYMBOL
(
pci_scan_bus
);
EXPORT_SYMBOL
(
pci_scan_bridge
);
#endif
drivers/pci/quirks.c
View file @
82670e1f
...
...
@@ -23,7 +23,7 @@
/* Deal with broken BIOS'es that neglect to enable passive release,
which can cause problems in combination with the 82441FX/PPro MTRRs */
static
void
__init
quirk_passive_release
(
struct
pci_dev
*
dev
)
static
void
__
dev
init
quirk_passive_release
(
struct
pci_dev
*
dev
)
{
struct
pci_dev
*
d
=
NULL
;
unsigned
char
dlc
;
...
...
@@ -50,7 +50,7 @@ static void __init quirk_passive_release(struct pci_dev *dev)
int
isa_dma_bridge_buggy
;
/* Exported */
static
void
__init
quirk_isa_dma_hangs
(
struct
pci_dev
*
dev
)
static
void
__
dev
init
quirk_isa_dma_hangs
(
struct
pci_dev
*
dev
)
{
if
(
!
isa_dma_bridge_buggy
)
{
isa_dma_bridge_buggy
=
1
;
...
...
@@ -64,7 +64,7 @@ int pci_pci_problems;
* Chipsets where PCI->PCI transfers vanish or hang
*/
static
void
__init
quirk_nopcipci
(
struct
pci_dev
*
dev
)
static
void
__
dev
init
quirk_nopcipci
(
struct
pci_dev
*
dev
)
{
if
((
pci_pci_problems
&
PCIPCI_FAIL
)
==
0
)
{
...
...
@@ -77,7 +77,7 @@ static void __init quirk_nopcipci(struct pci_dev *dev)
* Triton requires workarounds to be used by the drivers
*/
static
void
__init
quirk_triton
(
struct
pci_dev
*
dev
)
static
void
__
dev
init
quirk_triton
(
struct
pci_dev
*
dev
)
{
if
((
pci_pci_problems
&
PCIPCI_TRITON
)
==
0
)
{
...
...
@@ -96,7 +96,7 @@ static void __init quirk_triton(struct pci_dev *dev)
* Updated based on further information from the site and also on
* information provided by VIA
*/
static
void
__init
quirk_vialatency
(
struct
pci_dev
*
dev
)
static
void
__
dev
init
quirk_vialatency
(
struct
pci_dev
*
dev
)
{
struct
pci_dev
*
p
;
u8
rev
;
...
...
@@ -150,7 +150,7 @@ static void __init quirk_vialatency(struct pci_dev *dev)
* VIA Apollo VP3 needs ETBF on BT848/878
*/
static
void
__init
quirk_viaetbf
(
struct
pci_dev
*
dev
)
static
void
__
dev
init
quirk_viaetbf
(
struct
pci_dev
*
dev
)
{
if
((
pci_pci_problems
&
PCIPCI_VIAETBF
)
==
0
)
{
...
...
@@ -158,7 +158,7 @@ static void __init quirk_viaetbf(struct pci_dev *dev)
pci_pci_problems
|=
PCIPCI_VIAETBF
;
}
}
static
void
__init
quirk_vsfx
(
struct
pci_dev
*
dev
)
static
void
__
dev
init
quirk_vsfx
(
struct
pci_dev
*
dev
)
{
if
((
pci_pci_problems
&
PCIPCI_VSFX
)
==
0
)
{
...
...
@@ -173,7 +173,7 @@ static void __init quirk_vsfx(struct pci_dev *dev)
* at least
*/
static
void
__init
quirk_natoma
(
struct
pci_dev
*
dev
)
static
void
__
dev
init
quirk_natoma
(
struct
pci_dev
*
dev
)
{
if
((
pci_pci_problems
&
PCIPCI_NATOMA
)
==
0
)
{
...
...
@@ -187,7 +187,7 @@ static void __init quirk_natoma(struct pci_dev *dev)
* If it's needed, re-allocate the region.
*/
static
void
__init
quirk_s3_64M
(
struct
pci_dev
*
dev
)
static
void
__
dev
init
quirk_s3_64M
(
struct
pci_dev
*
dev
)
{
struct
resource
*
r
=
&
dev
->
resource
[
0
];
...
...
@@ -197,7 +197,7 @@ static void __init quirk_s3_64M(struct pci_dev *dev)
}
}
static
void
__init
quirk_io_region
(
struct
pci_dev
*
dev
,
unsigned
region
,
unsigned
size
,
int
nr
)
static
void
__
dev
init
quirk_io_region
(
struct
pci_dev
*
dev
,
unsigned
region
,
unsigned
size
,
int
nr
)
{
region
&=
~
(
size
-
1
);
if
(
region
)
{
...
...
@@ -222,7 +222,7 @@ static void __init quirk_io_region(struct pci_dev *dev, unsigned region, unsigne
* 0xE0 (64 bytes of ACPI registers)
* 0xE2 (32 bytes of SMB registers)
*/
static
void
__init
quirk_ali7101_acpi
(
struct
pci_dev
*
dev
)
static
void
__
dev
init
quirk_ali7101_acpi
(
struct
pci_dev
*
dev
)
{
u16
region
;
...
...
@@ -237,7 +237,7 @@ static void __init quirk_ali7101_acpi(struct pci_dev *dev)
* 0x40 (64 bytes of ACPI registers)
* 0x90 (32 bytes of SMB registers)
*/
static
void
__init
quirk_piix4_acpi
(
struct
pci_dev
*
dev
)
static
void
__
dev
init
quirk_piix4_acpi
(
struct
pci_dev
*
dev
)
{
u32
region
;
...
...
@@ -251,7 +251,7 @@ static void __init quirk_piix4_acpi(struct pci_dev *dev)
* VIA ACPI: One IO region pointed to by longword at
* 0x48 or 0x20 (256 bytes of ACPI registers)
*/
static
void
__init
quirk_vt82c586_acpi
(
struct
pci_dev
*
dev
)
static
void
__
dev
init
quirk_vt82c586_acpi
(
struct
pci_dev
*
dev
)
{
u8
rev
;
u32
region
;
...
...
@@ -270,7 +270,7 @@ static void __init quirk_vt82c586_acpi(struct pci_dev *dev)
* 0x70 (128 bytes of hardware monitoring register)
* 0x90 (16 bytes of SMB registers)
*/
static
void
__init
quirk_vt82c686_acpi
(
struct
pci_dev
*
dev
)
static
void
__
dev
init
quirk_vt82c686_acpi
(
struct
pci_dev
*
dev
)
{
u16
hm
;
u32
smb
;
...
...
@@ -297,7 +297,7 @@ extern int nr_ioapics;
* TODO: When we have device-specific interrupt routers,
* this code will go away from quirks.
*/
static
void
__init
quirk_via_ioapic
(
struct
pci_dev
*
dev
)
static
void
__
dev
init
quirk_via_ioapic
(
struct
pci_dev
*
dev
)
{
u8
tmp
;
...
...
@@ -338,7 +338,7 @@ static void __init quirk_via_ioapic(struct pci_dev *dev)
* value of the ACPI SCI interrupt is only done for convenience.
* -jgarzik
*/
static
void
__init
quirk_via_acpi
(
struct
pci_dev
*
d
)
static
void
__
dev
init
quirk_via_acpi
(
struct
pci_dev
*
d
)
{
/*
* VIA ACPI device: SCI IRQ line in PCI config byte 0x42
...
...
@@ -350,7 +350,7 @@ static void __init quirk_via_acpi(struct pci_dev *d)
d
->
irq
=
irq
;
}
static
void
__init
quirk_via_irqpic
(
struct
pci_dev
*
dev
)
static
void
__
dev
init
quirk_via_irqpic
(
struct
pci_dev
*
dev
)
{
u8
irq
,
new_irq
=
dev
->
irq
&
0xf
;
...
...
@@ -377,7 +377,7 @@ static void __init quirk_via_irqpic(struct pci_dev *dev)
*
* We mask out all r/wc bits, too.
*/
static
void
__init
quirk_piix3_usb
(
struct
pci_dev
*
dev
)
static
void
__
dev
init
quirk_piix3_usb
(
struct
pci_dev
*
dev
)
{
u16
legsup
;
...
...
@@ -392,7 +392,7 @@ static void __init quirk_piix3_usb(struct pci_dev *dev)
* We need to switch it off to be able to recognize the real
* type of the chip.
*/
static
void
__init
quirk_vt82c598_id
(
struct
pci_dev
*
dev
)
static
void
__
dev
init
quirk_vt82c598_id
(
struct
pci_dev
*
dev
)
{
pci_write_config_byte
(
dev
,
0xfc
,
0
);
pci_read_config_word
(
dev
,
PCI_DEVICE_ID
,
&
dev
->
device
);
...
...
@@ -404,7 +404,7 @@ static void __init quirk_vt82c598_id(struct pci_dev *dev)
* do this even if the Linux CardBus driver is not loaded, because
* the Linux i82365 driver does not (and should not) handle CardBus.
*/
static
void
__init
quirk_cardbus_legacy
(
struct
pci_dev
*
dev
)
static
void
__
dev
init
quirk_cardbus_legacy
(
struct
pci_dev
*
dev
)
{
if
((
PCI_CLASS_BRIDGE_CARDBUS
<<
8
)
^
dev
->
class
)
return
;
...
...
@@ -421,7 +421,7 @@ static void __init quirk_cardbus_legacy(struct pci_dev *dev)
* of course. However the advice is demonstrably good even if so..
*/
static
void
__init
quirk_amd_ioapic
(
struct
pci_dev
*
dev
)
static
void
__
dev
init
quirk_amd_ioapic
(
struct
pci_dev
*
dev
)
{
u8
rev
;
...
...
@@ -441,7 +441,7 @@ static void __init quirk_amd_ioapic(struct pci_dev *dev)
* who turn it off!
*/
static
void
__init
quirk_amd_ordering
(
struct
pci_dev
*
dev
)
static
void
__
dev
init
quirk_amd_ordering
(
struct
pci_dev
*
dev
)
{
u32
pcic
;
pci_read_config_dword
(
dev
,
0x4C
,
&
pcic
);
...
...
@@ -464,14 +464,14 @@ static void __init quirk_amd_ordering(struct pci_dev *dev)
* nothing gets put too close to it.
*/
static
void
__init
quirk_dunord
(
struct
pci_dev
*
dev
)
static
void
__
dev
init
quirk_dunord
(
struct
pci_dev
*
dev
)
{
struct
resource
*
r
=
&
dev
->
resource
[
1
];
r
->
start
=
0
;
r
->
end
=
0xffffff
;
}
static
void
__init
quirk_transparent_bridge
(
struct
pci_dev
*
dev
)
static
void
__
dev
init
quirk_transparent_bridge
(
struct
pci_dev
*
dev
)
{
dev
->
transparent
=
1
;
}
...
...
@@ -480,7 +480,7 @@ static void __init quirk_transparent_bridge(struct pci_dev *dev)
* The main table of quirks.
*/
static
struct
pci_fixup
pci_fixups
[]
__initdata
=
{
static
struct
pci_fixup
pci_fixups
[]
__
dev
initdata
=
{
{
PCI_FIXUP_HEADER
,
PCI_VENDOR_ID_DUNORD
,
PCI_DEVICE_ID_DUNORD_I3000
,
quirk_dunord
},
{
PCI_FIXUP_FINAL
,
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_82441
,
quirk_passive_release
},
{
PCI_FIXUP_FINAL
,
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_82441
,
quirk_passive_release
},
...
...
drivers/pci/search.c
View file @
82670e1f
#include <linux/pci.h>
#include <linux/module.h>
static
struct
pci_bus
*
pci_do_find_bus
(
struct
pci_bus
*
bus
,
unsigned
char
busnr
)
{
struct
pci_bus
*
child
;
struct
list_head
*
tmp
;
if
(
bus
->
number
==
busnr
)
return
bus
;
list_for_each
(
tmp
,
&
bus
->
children
)
{
child
=
pci_do_find_bus
(
pci_bus_b
(
tmp
),
busnr
);
if
(
child
)
return
child
;
}
return
NULL
;
}
/**
* pci_find_bus - locate PCI bus from a given bus number
* @busnr: number of desired PCI bus
*
* Given a PCI bus number, the desired PCI bus is located in system
* global list of PCI buses. If the bus is found, a pointer to its
* data structure is returned. If no bus is found, %NULL is returned.
*/
struct
pci_bus
*
pci_find_bus
(
unsigned
char
busnr
)
{
struct
pci_bus
*
bus
;
struct
pci_bus
*
tmp_bus
;
pci_for_each_bus
(
bus
)
{
tmp_bus
=
pci_do_find_bus
(
bus
,
busnr
);
if
(
tmp_bus
)
return
tmp_bus
;
}
return
NULL
;
}
/**
* pci_find_slot - locate PCI device from a given PCI slot
* @bus: number of PCI bus on which desired PCI device resides
...
...
@@ -104,6 +143,7 @@ pci_find_class(unsigned int class, const struct pci_dev *from)
return
NULL
;
}
EXPORT_SYMBOL
(
pci_find_bus
);
EXPORT_SYMBOL
(
pci_find_class
);
EXPORT_SYMBOL
(
pci_find_device
);
EXPORT_SYMBOL
(
pci_find_slot
);
...
...
drivers/pci/setup-bus.c
View file @
82670e1f
...
...
@@ -19,6 +19,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/errno.h>
#include <linux/ioport.h>
...
...
@@ -35,7 +36,7 @@
#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
static
int
__init
static
int
__
dev
init
pbus_assign_resources_sorted
(
struct
pci_bus
*
bus
)
{
struct
list_head
*
ln
;
...
...
@@ -85,7 +86,7 @@ pbus_assign_resources_sorted(struct pci_bus *bus)
requires that if there is no I/O ports or memory behind the
bridge, corresponding range must be turned off by writing base
value greater than limit to the bridge's base/limit registers. */
static
void
__init
static
void
__
dev
init
pci_setup_bridge
(
struct
pci_bus
*
bus
)
{
struct
pbus_set_ranges_data
ranges
;
...
...
@@ -168,7 +169,7 @@ pci_setup_bridge(struct pci_bus *bus)
/* Check whether the bridge supports optional I/O and
prefetchable memory ranges. If not, the respective
base/limit registers must be read-only and read as 0. */
static
void
__init
static
void
__
dev
init
pci_bridge_check_ranges
(
struct
pci_bus
*
bus
)
{
u16
io
;
...
...
@@ -210,7 +211,7 @@ pci_bridge_check_ranges(struct pci_bus *bus)
since these windows have 4K granularity and the IO ranges
of non-bridge PCI devices are limited to 256 bytes.
We must be careful with the ISA aliasing though. */
static
void
__init
static
void
__
dev
init
pbus_size_io
(
struct
pci_bus
*
bus
)
{
struct
list_head
*
ln
;
...
...
@@ -259,7 +260,7 @@ pbus_size_io(struct pci_bus *bus)
/* Calculate the size of the bus and minimal alignment which
guarantees that all child resources fit in this size. */
static
void
__init
static
void
__
dev
init
pbus_size_mem
(
struct
pci_bus
*
bus
,
unsigned
long
mask
,
unsigned
long
type
)
{
struct
list_head
*
ln
;
...
...
@@ -331,7 +332,7 @@ pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type)
b_res
->
end
=
size
+
min_align
-
1
;
}
void
__init
void
__
dev
init
pbus_size_bridges
(
struct
pci_bus
*
bus
)
{
struct
list_head
*
ln
;
...
...
@@ -357,8 +358,9 @@ pbus_size_bridges(struct pci_bus *bus)
}
pbus_size_mem
(
bus
,
mask
,
type
);
}
EXPORT_SYMBOL
(
pbus_size_bridges
);
void
__init
void
__
dev
init
pbus_assign_resources
(
struct
pci_bus
*
bus
)
{
struct
list_head
*
ln
;
...
...
@@ -379,6 +381,7 @@ pbus_assign_resources(struct pci_bus *bus)
pci_setup_bridge
(
b
);
}
}
EXPORT_SYMBOL
(
pbus_assign_resources
);
void
__init
pci_assign_unassigned_resources
(
void
)
...
...
include/linux/pci.h
View file @
82670e1f
...
...
@@ -557,8 +557,12 @@ struct pci_dev *pci_find_subsys (unsigned int vendor, unsigned int device,
unsigned
int
ss_vendor
,
unsigned
int
ss_device
,
const
struct
pci_dev
*
from
);
struct
pci_dev
*
pci_find_class
(
unsigned
int
class
,
const
struct
pci_dev
*
from
);
struct
pci_bus
*
pci_find_bus
(
unsigned
char
busnr
);
struct
pci_dev
*
pci_find_slot
(
unsigned
int
bus
,
unsigned
int
devfn
);
unsigned
char
pci_bus_max_busnr
(
struct
pci_bus
*
bus
);
unsigned
char
pci_max_busnr
(
void
);
int
pci_find_capability
(
struct
pci_dev
*
dev
,
int
cap
);
int
pci_bus_find_capability
(
struct
pci_bus
*
bus
,
unsigned
int
devfn
,
int
cap
);
int
pci_bus_read_config_byte
(
struct
pci_bus
*
bus
,
unsigned
int
devfn
,
int
where
,
u8
*
val
);
int
pci_bus_read_config_word
(
struct
pci_bus
*
bus
,
unsigned
int
devfn
,
int
where
,
u16
*
val
);
...
...
@@ -613,6 +617,8 @@ int pci_enable_wake(struct pci_dev *dev, u32 state, int enable);
/* Helper functions for low-level code (drivers/pci/setup-[bus,res].c) */
void
pbus_assign_resources
(
struct
pci_bus
*
bus
);
void
pbus_size_bridges
(
struct
pci_bus
*
bus
);
int
pci_claim_resource
(
struct
pci_dev
*
,
int
);
void
pci_assign_unassigned_resources
(
void
);
void
pdev_enable_device
(
struct
pci_dev
*
);
...
...
@@ -634,6 +640,7 @@ struct pci_driver *pci_dev_driver(const struct pci_dev *);
const
struct
pci_device_id
*
pci_match_device
(
const
struct
pci_device_id
*
ids
,
const
struct
pci_dev
*
dev
);
unsigned
int
pci_do_scan_bus
(
struct
pci_bus
*
bus
);
struct
pci_bus
*
pci_add_new_bus
(
struct
pci_bus
*
parent
,
struct
pci_dev
*
dev
,
int
busnr
);
int
pci_scan_bridge
(
struct
pci_bus
*
bus
,
struct
pci_dev
*
dev
,
int
max
,
int
pass
);
/* kmem_cache style wrapper around pci_alloc_consistent() */
struct
pci_pool
*
pci_pool_create
(
const
char
*
name
,
struct
pci_dev
*
dev
,
...
...
include/linux/pci_ids.h
View file @
82670e1f
...
...
@@ -1101,6 +1101,9 @@
#define PCI_DEVICE_ID_EICON_MAESTRAQ_U 0xe013
#define PCI_DEVICE_ID_EICON_MAESTRAP 0xe014
#define PCI_VENDOR_ID_ZIATECH 0x1138
#define PCI_DEVICE_ID_ZIATECH_5550_HC 0x5550
#define PCI_VENDOR_ID_CYCLONE 0x113c
#define PCI_DEVICE_ID_CYCLONE_SDK 0x0001
...
...
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