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
Kirill Smelkov
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
Hide 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,8 +297,8 @@ 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
,
struct
pbus_set_ranges_data
*
ranges
)
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,8 +341,8 @@ 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
,
struct
pbus_set_ranges_data
*
ranges
)
void
__
dev
init
pcibios_fixup_pbus_ranges
(
struct
pci_bus
*
bus
,
struct
pbus_set_ranges_data
*
ranges
)
{
/*
* our caller figure out range by going through the dev structures.
...
...
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,8 +349,8 @@ 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
,
struct
pbus_set_ranges_data
*
ranges
)
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,8 +121,8 @@ static void fixup_windbond_82c105(struct pci_dev* dev)
}
void
pcibios_fixup_pbus_ranges
(
struct
pci_bus
*
pbus
,
struct
pbus_set_ranges_data
*
pranges
)
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,8 +250,8 @@ struct pci_fixup pcibios_fixups[] = {
{
0
}
};
void
__init
pcibios_fixup_pbus_ranges
(
struct
pci_bus
*
b
,
struct
pbus_set_ranges_data
*
range
)
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,8 +479,8 @@ void pcibios_update_irq(struct pci_dev *pdev, int irq)
{
}
void
pcibios_fixup_pbus_ranges
(
struct
pci_bus
*
pbus
,
struct
pbus_set_ranges_data
*
pranges
)
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
;
...
...
@@ -111,16 +112,16 @@ static inline int slot_paranoia_check (struct slot *slot, const char *function)
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
);
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
;
}
...
...
@@ -185,8 +186,8 @@ static int disable_slot (struct hotplug_slot *hotplug_slot)
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
);
err
(
"No hardware tests are defined for this driver"
);
dbg
(
"%s - physical_slot = %s
\n
"
,
__FUNCTION__
,
hotplug_slot
->
name
);
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
);
*
value
=
acpiphp_get_power_status
(
slot
->
acpi_slot
);
dbg
(
"%s - physical_slot = %s
\n
"
,
__FUNCTION__
,
hotplug_slot
->
name
);
*
value
=
acpiphp_get_power_status
(
slot
->
acpi_slot
);
return
retval
;
}
...
...
@@ -263,8 +264,8 @@ static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
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
);
*
value
=
acpiphp_get_latch_status
(
slot
->
acpi_slot
);
dbg
(
"%s - physical_slot = %s
\n
"
,
__FUNCTION__
,
hotplug_slot
->
name
);
*
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
);
*
value
=
acpiphp_get_adapter_status
(
slot
->
acpi_slot
);
dbg
(
"%s - physical_slot = %s
\n
"
,
__FUNCTION__
,
hotplug_slot
->
name
);
*
value
=
acpiphp_get_adapter_status
(
slot
->
acpi_slot
);
return
retval
;
}
...
...
@@ -325,11 +326,11 @@ 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
;
*
value
=
PCI_SPEED_UNKNOWN
;
return
0
;
...
...
@@ -339,11 +340,11 @@ 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
;
*
value
=
PCI_SPEED_UNKNOWN
;
return
0
;
...
...
@@ -375,10 +376,10 @@ 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"
,
slot
->
acpi_slot
->
sun
,
slot
->
acpi_slot
->
bridge
->
bus
,
slot
->
acpi_slot
->
device
);
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
)
{
...
...
@@ -1063,7 +1058,7 @@ static unsigned int get_slot_status (struct acpiphp_slot *slot)
/**
* handle_hotplug_event_bridge - handle ACPI event on bridges
*
* @handle: Notify()'ed acpi_handle
* @handle: Notify()'ed acpi_handle
* @type: Notify code
* @context: pointer to acpiphp_bridge structure
*
...
...
@@ -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
;
}
}
...
...
@@ -1114,7 +1109,7 @@ static void handle_hotplug_event_bridge (acpi_handle handle, u32 type, void *con
/**
* handle_hotplug_event_func - handle ACPI event on functions (i.e. slots)
*
* @handle: Notify()'ed acpi_handle
* @handle: Notify()'ed acpi_handle
* @type: Notify code
* @context: pointer to acpiphp_func structure
*
...
...
@@ -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,16 +212,16 @@ 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
;
}
static
int
is_pci_dev_in_use
(
struct
pci_dev
*
dev
)
static
int
is_pci_dev_in_use
(
struct
pci_dev
*
dev
)
{
/*
* dev->driver will be set if the device is in use by a new-style
/*
* 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
*/
...
...
@@ -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
...
...
@@ -273,7 +273,7 @@ struct pci_resource *acpiphp_get_max_resource (struct pci_resource **head, u32 s
for
(
max
=
*
head
;
max
;
max
=
max
->
next
)
{
/* If not big enough we could probably just bail,
/* If not big enough we could probably just bail,
instead we'll continue to the next. */
if
(
max
->
length
<
size
)
continue
;
...
...
@@ -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
)
{
...
...
@@ -437,7 +437,7 @@ struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size)
/**
* get_resource_with_base - get resource with specific base address
*
* this function
* this function
* returns the first node of "size" length located at specified base address.
* If it finds a node larger than "size" it will split it up.
*
...
...
@@ -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
;
}
result
=
pci_visit_bus
(
fn
,
&
wrapped_bus
,
wrapped_dev
);
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
...
...
@@ -1100,6 +1100,9 @@
#define PCI_DEVICE_ID_EICON_MAESTRAQ 0xe012
#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