Commit 82670e1f authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://linuxusb.bkbits.net/pci_hp-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 42003664 d53e21af
...@@ -2218,6 +2218,15 @@ S: 30 White Tail Lane ...@@ -2218,6 +2218,15 @@ S: 30 White Tail Lane
S: Lafayette, Indiana 47905 S: Lafayette, Indiana 47905
S: USA 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 N: Trond Myklebust
E: trond.myklebust@fys.uio.no E: trond.myklebust@fys.uio.no
D: current NFS client hacker. D: current NFS client hacker.
......
...@@ -317,6 +317,27 @@ L: codalist@coda.cs.cmu.edu ...@@ -317,6 +317,27 @@ L: codalist@coda.cs.cmu.edu
W: http://www.coda.cs.cmu.edu/ W: http://www.coda.cs.cmu.edu/
S: Maintained 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 COMPAQ FIBRE CHANNEL 64-bit/66MHz PCI non-intelligent HBA
P: Amy Vanzant-Hodge P: Amy Vanzant-Hodge
M: Amy Vanzant-Hodge (fibrechannel@compaq.com) M: Amy Vanzant-Hodge (fibrechannel@compaq.com)
......
...@@ -340,7 +340,7 @@ common_swizzle(struct pci_dev *dev, u8 *pinp) ...@@ -340,7 +340,7 @@ common_swizzle(struct pci_dev *dev, u8 *pinp)
return PCI_SLOT(dev->devfn); return PCI_SLOT(dev->devfn);
} }
void __init void __devinit
pcibios_fixup_pbus_ranges(struct pci_bus * bus, pcibios_fixup_pbus_ranges(struct pci_bus * bus,
struct pbus_set_ranges_data * ranges) struct pbus_set_ranges_data * ranges)
{ {
......
...@@ -90,6 +90,11 @@ static void __devinit pcibios_fixup_ghosts(struct pci_bus *b) ...@@ -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 * Called after each bus is probed, but before its children
* are examined. * are examined.
......
...@@ -138,7 +138,7 @@ static void __devinit pci_fixup_piix4_acpi(struct pci_dev *d) ...@@ -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_KL133_REVISION_ID 0x81
#define VIA_8363_KM133_REVISION_ID 0x84 #define VIA_8363_KM133_REVISION_ID 0x84
static void __init pci_fixup_via_northbridge_bug(struct pci_dev *d) static void __devinit pci_fixup_via_northbridge_bug(struct pci_dev *d)
{ {
u8 v; u8 v;
u8 revision; u8 revision;
...@@ -180,7 +180,7 @@ static void __init pci_fixup_via_northbridge_bug(struct pci_dev *d) ...@@ -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 * system to PCI bus no matter what are their window settings, so they are
* "transparent" (or subtractive decoding) from programmers point of view. * "transparent" (or subtractive decoding) from programmers point of view.
*/ */
static void __init pci_fixup_transparent_bridge(struct pci_dev *dev) static void __devinit pci_fixup_transparent_bridge(struct pci_dev *dev)
{ {
if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI &&
(dev->device & 0xff00) == 0x2400) (dev->device & 0xff00) == 0x2400)
......
...@@ -297,7 +297,7 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq) ...@@ -297,7 +297,7 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq)
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
} }
void __init pcibios_fixup_pbus_ranges(struct pci_bus *bus, void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *bus,
struct pbus_set_ranges_data *ranges) struct pbus_set_ranges_data *ranges)
{ {
} }
......
...@@ -341,7 +341,7 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq) ...@@ -341,7 +341,7 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq)
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
} }
void __init pcibios_fixup_pbus_ranges(struct pci_bus *bus, void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *bus,
struct pbus_set_ranges_data *ranges) struct pbus_set_ranges_data *ranges)
{ {
/* /*
......
...@@ -234,7 +234,7 @@ pcibios_fixup_bus(struct pci_bus *b) ...@@ -234,7 +234,7 @@ pcibios_fixup_bus(struct pci_bus *b)
pci_fixup_irqs(pci_swizzle, pci_map_irq); pci_fixup_irqs(pci_swizzle, pci_map_irq);
} }
void __init void __devinit
pcibios_fixup_pbus_ranges(struct pci_bus * bus, pcibios_fixup_pbus_ranges(struct pci_bus * bus,
struct pbus_set_ranges_data * ranges) struct pbus_set_ranges_data * ranges)
{ {
......
...@@ -349,7 +349,7 @@ void __init pcibios_fixup_bus (struct pci_bus *b) ...@@ -349,7 +349,7 @@ void __init pcibios_fixup_bus (struct pci_bus *b)
} }
/* XXX anybody know what this is supposed to do? */ /* XXX anybody know what this is supposed to do? */
void __init pcibios_fixup_pbus_ranges(struct pci_bus * bus, void __devinit pcibios_fixup_pbus_ranges(struct pci_bus * bus,
struct pbus_set_ranges_data * ranges) struct pbus_set_ranges_data * ranges)
{ {
} }
......
...@@ -345,7 +345,7 @@ pcibios_link_hba_resources( struct resource *hba_res, struct resource *r) ...@@ -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(). ** 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 pci_bus *bus,
struct pbus_set_ranges_data *ranges struct pbus_set_ranges_data *ranges
) )
......
...@@ -1107,7 +1107,7 @@ common_swizzle(struct pci_dev *dev, unsigned char *pinp) ...@@ -1107,7 +1107,7 @@ common_swizzle(struct pci_dev *dev, unsigned char *pinp)
return PCI_SLOT(dev->devfn); return PCI_SLOT(dev->devfn);
} }
void __init void __devinit
pcibios_fixup_pbus_ranges(struct pci_bus * bus, struct pbus_set_ranges_data * ranges) pcibios_fixup_pbus_ranges(struct pci_bus * bus, struct pbus_set_ranges_data * ranges)
{ {
} }
......
...@@ -121,7 +121,7 @@ static void fixup_windbond_82c105(struct pci_dev* dev) ...@@ -121,7 +121,7 @@ static void fixup_windbond_82c105(struct pci_dev* dev)
} }
void pcibios_fixup_pbus_ranges(struct pci_bus *pbus, void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *pbus,
struct pbus_set_ranges_data *pranges) struct pbus_set_ranges_data *pranges)
{ {
} }
......
...@@ -113,7 +113,7 @@ void pci_free_consistent(struct pci_dev *hwdev, size_t size, ...@@ -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 __devinit pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *ranges)
{ {
} }
......
...@@ -250,7 +250,7 @@ struct pci_fixup pcibios_fixups[] = { ...@@ -250,7 +250,7 @@ struct pci_fixup pcibios_fixups[] = {
{ 0 } { 0 }
}; };
void __init pcibios_fixup_pbus_ranges(struct pci_bus *b, void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *b,
struct pbus_set_ranges_data *range) struct pbus_set_ranges_data *range)
{ {
/* No fixups needed */ /* No fixups needed */
......
...@@ -380,7 +380,7 @@ static int __init map_harp_irq(struct pci_dev *dev, u8 slot, u8 pin) ...@@ -380,7 +380,7 @@ static int __init map_harp_irq(struct pci_dev *dev, u8 slot, u8 pin)
} }
void __init void __devinit
pcibios_fixup_pbus_ranges(struct pci_bus *bus, pcibios_fixup_pbus_ranges(struct pci_bus *bus,
struct pbus_set_ranges_data *ranges) struct pbus_set_ranges_data *ranges)
{ {
......
...@@ -479,7 +479,7 @@ void pcibios_update_irq(struct pci_dev *pdev, int irq) ...@@ -479,7 +479,7 @@ void pcibios_update_irq(struct pci_dev *pdev, int irq)
{ {
} }
void pcibios_fixup_pbus_ranges(struct pci_bus *pbus, void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *pbus,
struct pbus_set_ranges_data *pranges) struct pbus_set_ranges_data *pranges)
{ {
} }
......
...@@ -73,5 +73,48 @@ config HOTPLUG_PCI_ACPI ...@@ -73,5 +73,48 @@ config HOTPLUG_PCI_ACPI
When in doubt, say N. 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 endmenu
...@@ -2,12 +2,15 @@ ...@@ -2,12 +2,15 @@
# Makefile for the Linux kernel pci hotplug controller drivers. # 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) += pci_hotplug.o
obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o
obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o
obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.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-objs := pci_hotplug_core.o \
pci_hotplug_util.o pci_hotplug_util.o
...@@ -28,6 +31,9 @@ acpiphp-objs := acpiphp_core.o \ ...@@ -28,6 +31,9 @@ acpiphp-objs := acpiphp_core.o \
acpiphp_pci.o \ acpiphp_pci.o \
acpiphp_res.o acpiphp_res.o
cpci_hotplug-objs := cpci_hotplug_core.o \
cpci_hotplug_pci.o
ifdef CONFIG_HOTPLUG_PCI_ACPI ifdef CONFIG_HOTPLUG_PCI_ACPI
EXTRA_CFLAGS += -D_LINUX -I$(TOPDIR)/drivers/acpi EXTRA_CFLAGS += -D_LINUX -I$(TOPDIR)/drivers/acpi
ifdef CONFIG_ACPI_DEBUG ifdef CONFIG_ACPI_DEBUG
......
...@@ -41,12 +41,12 @@ ...@@ -41,12 +41,12 @@
#define dbg(format, arg...) \ #define dbg(format, arg...) \
do { \ do { \
if (acpiphp_debug) \ if (acpiphp_debug) \
printk (KERN_DEBUG "%s: " format "\n", \ printk(KERN_DEBUG "%s: " format, \
MY_NAME , ## arg); \ MY_NAME , ## arg); \
} while (0) } while (0)
#define err(format, arg...) printk (KERN_ERR "%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 "\n", MY_NAME , ## arg) #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
#define warn(format, arg...) printk (KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
#define SLOT_MAGIC 0x67267322 #define SLOT_MAGIC 0x67267322
/* name size which is used for entries in pcihpfs */ /* name size which is used for entries in pcihpfs */
......
...@@ -50,6 +50,7 @@ static LIST_HEAD(slot_list); ...@@ -50,6 +50,7 @@ static LIST_HEAD(slot_list);
#define MY_NAME THIS_MODULE->name #define MY_NAME THIS_MODULE->name
#endif #endif
static int debug;
int acpiphp_debug; int acpiphp_debug;
/* local variables */ /* local variables */
...@@ -62,8 +63,8 @@ static int num_slots; ...@@ -62,8 +63,8 @@ static int num_slots;
MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC); MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_PARM(acpiphp_debug, "i"); MODULE_PARM(debug, "i");
MODULE_PARM_DESC(acpiphp_debug, "Debugging mode enabled or not"); MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
static int enable_slot (struct hotplug_slot *slot); static int enable_slot (struct hotplug_slot *slot);
static int disable_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 = { ...@@ -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) static inline int slot_paranoia_check (struct slot *slot, const char *function)
{ {
if (!slot) { if (!slot) {
dbg("%s - slot == NULL", function); dbg("%s - slot == NULL\n", function);
return -1; return -1;
} }
if (slot->magic != SLOT_MAGIC) { if (slot->magic != SLOT_MAGIC) {
dbg("%s - bad magic number for slot", function); dbg("%s - bad magic number for slot\n", function);
return -1; return -1;
} }
if (!slot->hotplug_slot) { if (!slot->hotplug_slot) {
dbg("%s - slot->hotplug_slot == NULL!", function); dbg("%s - slot->hotplug_slot == NULL!\n", function);
return -1; return -1;
} }
return 0; return 0;
...@@ -115,12 +116,12 @@ static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const ch ...@@ -115,12 +116,12 @@ static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const ch
struct slot *slot; struct slot *slot;
if (!hotplug_slot) { if (!hotplug_slot) {
dbg("%s - hotplug_slot == NULL", function); dbg("%s - hotplug_slot == NULL\n", function);
return NULL; return NULL;
} }
slot = (struct slot *)hotplug_slot->private; slot = (struct slot *)hotplug_slot->private;
if (slot_paranoia_check (slot, function)) if (slot_paranoia_check(slot, function))
return NULL; return NULL;
return slot; return slot;
} }
...@@ -135,16 +136,16 @@ static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const ch ...@@ -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) 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; int retval = 0;
if (slot == NULL) if (slot == NULL)
return -ENODEV; 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 */ /* enable the specified slot */
retval = acpiphp_enable_slot (slot->acpi_slot); retval = acpiphp_enable_slot(slot->acpi_slot);
return retval; return retval;
} }
...@@ -159,16 +160,16 @@ static int enable_slot (struct hotplug_slot *hotplug_slot) ...@@ -159,16 +160,16 @@ static int enable_slot (struct hotplug_slot *hotplug_slot)
*/ */
static int disable_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; int retval = 0;
if (slot == NULL) if (slot == NULL)
return -ENODEV; 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 */ /* disable the specified slot */
retval = acpiphp_disable_slot (slot->acpi_slot); retval = acpiphp_disable_slot(slot->acpi_slot);
return retval; return retval;
} }
...@@ -186,7 +187,7 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) ...@@ -186,7 +187,7 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
{ {
int retval = 0; int retval = 0;
dbg ("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
switch (status) { switch (status) {
case 0: case 0:
...@@ -213,15 +214,15 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) ...@@ -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) 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; int retval = 0;
if (slot == NULL) if (slot == NULL)
return -ENODEV; return -ENODEV;
dbg ("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
err ("No hardware tests are defined for this driver"); err("No hardware tests are defined for this driver\n");
retval = -ENODEV; retval = -ENODEV;
return retval; return retval;
...@@ -239,15 +240,15 @@ static int hardware_test (struct hotplug_slot *hotplug_slot, u32 value) ...@@ -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) 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; int retval = 0;
if (slot == NULL) if (slot == NULL)
return -ENODEV; return -ENODEV;
dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
*value = acpiphp_get_power_status (slot->acpi_slot); *value = acpiphp_get_power_status(slot->acpi_slot);
return retval; return retval;
} }
...@@ -264,7 +265,7 @@ static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) ...@@ -264,7 +265,7 @@ static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
{ {
int retval = 0; 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; *value = hotplug_slot->info->attention_status;
...@@ -283,15 +284,15 @@ static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) ...@@ -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) 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; int retval = 0;
if (slot == NULL) if (slot == NULL)
return -ENODEV; return -ENODEV;
dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
*value = acpiphp_get_latch_status (slot->acpi_slot); *value = acpiphp_get_latch_status(slot->acpi_slot);
return retval; return retval;
} }
...@@ -308,15 +309,15 @@ static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) ...@@ -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) 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; int retval = 0;
if (slot == NULL) if (slot == NULL)
return -ENODEV; return -ENODEV;
dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
*value = acpiphp_get_adapter_status (slot->acpi_slot); *value = acpiphp_get_adapter_status(slot->acpi_slot);
return retval; return retval;
} }
...@@ -325,7 +326,7 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) ...@@ -325,7 +326,7 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
/* return dummy value because ACPI doesn't provide any method... */ /* 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) 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) if (slot == NULL)
return -ENODEV; return -ENODEV;
...@@ -339,7 +340,7 @@ static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp ...@@ -339,7 +340,7 @@ static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
/* return dummy value because ACPI doesn't provide any method... */ /* 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) 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) if (slot == NULL)
return -ENODEV; return -ENODEV;
...@@ -375,7 +376,7 @@ static int init_acpi (void) ...@@ -375,7 +376,7 @@ static int init_acpi (void)
*/ */
static void make_slot_name (struct slot *slot) static void make_slot_name (struct slot *slot)
{ {
snprintf (slot->hotplug_slot->name, SLOT_NAME_SIZE, "ACPI%d-%02x:%02x", snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "ACPI%d-%02x:%02x",
slot->acpi_slot->sun, slot->acpi_slot->sun,
slot->acpi_slot->bridge->bus, slot->acpi_slot->bridge->bus,
slot->acpi_slot->device); slot->acpi_slot->device);
...@@ -392,31 +393,31 @@ static int init_slots (void) ...@@ -392,31 +393,31 @@ static int init_slots (void)
int i; int i;
for (i = 0; i < num_slots; ++i) { for (i = 0; i < num_slots; ++i) {
slot = kmalloc (sizeof (struct slot), GFP_KERNEL); slot = kmalloc(sizeof(struct slot), GFP_KERNEL);
if (!slot) if (!slot)
return -ENOMEM; return -ENOMEM;
memset(slot, 0, sizeof(struct slot)); 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) { if (!slot->hotplug_slot) {
kfree (slot); kfree(slot);
return -ENOMEM; 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) { if (!slot->hotplug_slot->info) {
kfree (slot->hotplug_slot); kfree(slot->hotplug_slot);
kfree (slot); kfree(slot);
return -ENOMEM; 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) { if (!slot->hotplug_slot->name) {
kfree (slot->hotplug_slot->info); kfree(slot->hotplug_slot->info);
kfree (slot->hotplug_slot); kfree(slot->hotplug_slot);
kfree (slot); kfree(slot);
return -ENOMEM; return -ENOMEM;
} }
...@@ -426,27 +427,27 @@ static int init_slots (void) ...@@ -426,27 +427,27 @@ static int init_slots (void)
slot->hotplug_slot->private = slot; slot->hotplug_slot->private = slot;
slot->hotplug_slot->ops = &acpi_hotplug_slot_ops; 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->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->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->latch_status = acpiphp_get_latch_status(slot->acpi_slot);
slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_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) { if (retval) {
err ("pci_hp_register failed with error %d", retval); err("pci_hp_register failed with error %d\n", retval);
kfree (slot->hotplug_slot->info); kfree(slot->hotplug_slot->info);
kfree (slot->hotplug_slot->name); kfree(slot->hotplug_slot->name);
kfree (slot->hotplug_slot); kfree(slot->hotplug_slot);
kfree (slot); kfree(slot);
return retval; return retval;
} }
/* add slot to our internal list */ /* add slot to our internal list */
list_add (&slot->slot_list, &slot_list); list_add(&slot->slot_list, &slot_list);
info("Slot [%s] registered", slot->hotplug_slot->name); info("Slot [%s] registered\n", slot->hotplug_slot->name);
} }
return retval; return retval;
...@@ -459,13 +460,13 @@ static void cleanup_slots (void) ...@@ -459,13 +460,13 @@ static void cleanup_slots (void)
struct slot *slot; struct slot *slot;
list_for_each_safe (tmp, n, &slot_list) { list_for_each_safe (tmp, n, &slot_list) {
slot = list_entry (tmp, struct slot, slot_list); slot = list_entry(tmp, struct slot, slot_list);
list_del (&slot->slot_list); list_del(&slot->slot_list);
pci_hp_deregister (slot->hotplug_slot); pci_hp_deregister(slot->hotplug_slot);
kfree (slot->hotplug_slot->info); kfree(slot->hotplug_slot->info);
kfree (slot->hotplug_slot->name); kfree(slot->hotplug_slot->name);
kfree (slot->hotplug_slot); kfree(slot->hotplug_slot);
kfree (slot); kfree(slot);
} }
return; return;
...@@ -476,7 +477,9 @@ static int __init acpiphp_init(void) ...@@ -476,7 +477,9 @@ static int __init acpiphp_init(void)
{ {
int retval; 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 */ /* read all the ACPI info from the system */
retval = init_acpi(); retval = init_acpi();
......
...@@ -153,7 +153,7 @@ register_slot (acpi_handle handle, u32 lvl, void *context, void **rv) ...@@ -153,7 +153,7 @@ register_slot (acpi_handle handle, u32 lvl, void *context, void **rv)
for (slot = bridge->slots; slot; slot = slot->next) for (slot = bridge->slots; slot; slot = slot->next)
if (slot->device == device) { if (slot->device == device) {
if (slot->sun != sun) if (slot->sun != sun)
warn("sibling found, but _SUN doesn't match!"); warn("sibling found, but _SUN doesn't match!\n");
break; break;
} }
...@@ -177,7 +177,7 @@ register_slot (acpi_handle handle, u32 lvl, void *context, void **rv) ...@@ -177,7 +177,7 @@ register_slot (acpi_handle handle, u32 lvl, void *context, void **rv)
bridge->nr_slots++; 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); slot->bridge->bus, slot->device, slot->sun);
} }
...@@ -202,7 +202,7 @@ register_slot (acpi_handle handle, u32 lvl, void *context, void **rv) ...@@ -202,7 +202,7 @@ register_slot (acpi_handle handle, u32 lvl, void *context, void **rv)
newfunc); newfunc);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
err("failed to register interrupt notify handler"); err("failed to register interrupt notify handler\n");
return status; return status;
} }
...@@ -302,21 +302,21 @@ decode_acpi_resource (acpi_resource *resource, struct acpiphp_bridge *bridge) ...@@ -302,21 +302,21 @@ decode_acpi_resource (acpi_resource *resource, struct acpiphp_bridge *bridge)
switch (resource_type) { switch (resource_type) {
case ACPI_MEMORY_RANGE: case ACPI_MEMORY_RANGE:
if (cache_attribute == ACPI_PREFETCHABLE_MEMORY) { 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, res = acpiphp_make_resource(min_address_range,
address_length); address_length);
if (!res) { if (!res) {
err("out of memory"); err("out of memory\n");
return; return;
} }
res->next = bridge->p_mem_head; res->next = bridge->p_mem_head;
bridge->p_mem_head = res; bridge->p_mem_head = res;
} else { } 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, res = acpiphp_make_resource(min_address_range,
address_length); address_length);
if (!res) { if (!res) {
err("out of memory"); err("out of memory\n");
return; return;
} }
res->next = bridge->mem_head; res->next = bridge->mem_head;
...@@ -324,22 +324,22 @@ decode_acpi_resource (acpi_resource *resource, struct acpiphp_bridge *bridge) ...@@ -324,22 +324,22 @@ decode_acpi_resource (acpi_resource *resource, struct acpiphp_bridge *bridge)
} }
break; break;
case ACPI_IO_RANGE: 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, res = acpiphp_make_resource(min_address_range,
address_length); address_length);
if (!res) { if (!res) {
err("out of memory"); err("out of memory\n");
return; return;
} }
res->next = bridge->io_head; res->next = bridge->io_head;
bridge->io_head = res; bridge->io_head = res;
break; break;
case ACPI_BUS_NUMBER_RANGE: 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, res = acpiphp_make_resource(min_address_range,
address_length); address_length);
if (!res) { if (!res) {
err("out of memory"); err("out of memory\n");
return; return;
} }
res->next = bridge->bus_head; res->next = bridge->bus_head;
...@@ -356,10 +356,9 @@ decode_acpi_resource (acpi_resource *resource, struct acpiphp_bridge *bridge) ...@@ -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->mem_head);
acpiphp_resource_sort_and_combine(&bridge->p_mem_head); acpiphp_resource_sort_and_combine(&bridge->p_mem_head);
acpiphp_resource_sort_and_combine(&bridge->bus_head); acpiphp_resource_sort_and_combine(&bridge->bus_head);
#if 1
info("ACPI _CRS resource:"); dbg("ACPI _CRS resource:\n");
acpiphp_dump_resource(bridge); acpiphp_dump_resource(bridge);
#endif
} }
...@@ -368,7 +367,7 @@ static struct pci_bus *find_pci_bus(const struct list_head *list, int bus) ...@@ -368,7 +367,7 @@ static struct pci_bus *find_pci_bus(const struct list_head *list, int bus)
{ {
const struct list_head *l; const struct list_head *l;
list_for_each(l, list) { list_for_each (l, list) {
struct pci_bus *b = pci_bus_b(l); struct pci_bus *b = pci_bus_b(l);
if (b->number == bus) if (b->number == bus)
return b; return b;
...@@ -404,7 +403,7 @@ static void decode_hpp(struct acpiphp_bridge *bridge) ...@@ -404,7 +403,7 @@ static void decode_hpp(struct acpiphp_bridge *bridge)
status = acpi_evaluate_object(bridge->handle, "_HPP", NULL, &buffer); status = acpi_evaluate_object(bridge->handle, "_HPP", NULL, &buffer);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
dbg("_HPP evaluation failed"); dbg("_HPP evaluation failed\n");
return; return;
} }
...@@ -412,13 +411,13 @@ static void decode_hpp(struct acpiphp_bridge *bridge) ...@@ -412,13 +411,13 @@ static void decode_hpp(struct acpiphp_bridge *bridge)
if (!package || package->type != ACPI_TYPE_PACKAGE || if (!package || package->type != ACPI_TYPE_PACKAGE ||
package->package.count != 4 || !package->package.elements) { package->package.count != 4 || !package->package.elements) {
err("invalid _HPP object; ignoring"); err("invalid _HPP object; ignoring\n");
goto err_exit; goto err_exit;
} }
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
if (package->package.elements[i].type != ACPI_TYPE_INTEGER) { 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; goto err_exit;
} }
} }
...@@ -428,7 +427,7 @@ static void decode_hpp(struct acpiphp_bridge *bridge) ...@@ -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_SERR = package->package.elements[2].integer.value;
bridge->hpp.enable_PERR = package->package.elements[3].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.cache_line_size,
bridge->hpp.latency_timer, bridge->hpp.latency_timer,
bridge->hpp.enable_SERR, bridge->hpp.enable_SERR,
...@@ -463,15 +462,13 @@ static void init_bridge_misc (struct acpiphp_bridge *bridge) ...@@ -463,15 +462,13 @@ static void init_bridge_misc (struct acpiphp_bridge *bridge)
bridge); bridge);
if (ACPI_FAILURE(status)) { 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); list_add(&bridge->list, &bridge_list);
#if 1 dbg("Bridge resource:\n");
dbg("Bridge resource:");
acpiphp_dump_resource(bridge); acpiphp_dump_resource(bridge);
#endif
} }
...@@ -507,7 +504,7 @@ static void add_host_bridge (acpi_handle *handle, int seg, int bus) ...@@ -507,7 +504,7 @@ static void add_host_bridge (acpi_handle *handle, int seg, int bus)
status = acpi_get_current_resources(handle, &buffer); status = acpi_get_current_resources(handle, &buffer);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
err("failed to decode bridge resources"); err("failed to decode bridge resources\n");
kfree(bridge); kfree(bridge);
return; return;
} }
...@@ -535,7 +532,7 @@ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int ...@@ -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); bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
if (bridge == NULL) { if (bridge == NULL) {
err("out of memory"); err("out of memory\n");
return; return;
} }
...@@ -547,14 +544,14 @@ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int ...@@ -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)); bridge->pci_dev = pci_find_slot(bus, PCI_DEVFN(dev, fn));
if (!bridge->pci_dev) { if (!bridge->pci_dev) {
err("Can't get pci_dev"); err("Can't get pci_dev\n");
kfree(bridge); kfree(bridge);
return; return;
} }
bridge->pci_bus = bridge->pci_dev->subordinate; bridge->pci_bus = bridge->pci_dev->subordinate;
if (!bridge->pci_bus) { 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); kfree(bridge);
return; return;
} }
...@@ -580,10 +577,10 @@ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int ...@@ -580,10 +577,10 @@ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int
limit = ((limit << 8) & 0xf000) + 0xfff; limit = ((limit << 8) & 0xf000) + 0xfff;
bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1); bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1);
if (!bridge->io_head) { if (!bridge->io_head) {
err("out of memory"); err("out of memory\n");
return; 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,
(u32)(bridge->io_head->base + bridge->io_head->length - 1)); (u32)(bridge->io_head->base + bridge->io_head->length - 1));
break; break;
...@@ -594,18 +591,18 @@ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int ...@@ -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; limit = (((u32)tmp16 << 16) | ((limit << 8) & 0xf000)) + 0xfff;
bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1); bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1);
if (!bridge->io_head) { if (!bridge->io_head) {
err("out of memory"); err("out of memory\n");
return; 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,
(u32)(bridge->io_head->base + bridge->io_head->length - 1)); (u32)(bridge->io_head->base + bridge->io_head->length - 1));
break; break;
case 0x0f: case 0x0f:
dbg("I/O space unsupported"); dbg("I/O space unsupported\n");
break; break;
default: default:
warn("Unknown I/O range type"); warn("Unknown I/O range type\n");
} }
/* Memory resources (mandatory for P2P bridge) */ /* 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 ...@@ -615,10 +612,10 @@ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int
limit = ((tmp16 & 0xfff0) << 16) | 0xfffff; limit = ((tmp16 & 0xfff0) << 16) | 0xfffff;
bridge->mem_head = acpiphp_make_resource((u64)base, limit - base + 1); bridge->mem_head = acpiphp_make_resource((u64)base, limit - base + 1);
if (!bridge->mem_head) { if (!bridge->mem_head) {
err("out of memory"); err("out of memory\n");
return; return;
} }
dbg("32bit Memory range: %08x-%08x", dbg("32bit Memory range: %08x-%08x\n",
(u32)bridge->mem_head->base, (u32)bridge->mem_head->base,
(u32)(bridge->mem_head->base + bridge->mem_head->length-1)); (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 ...@@ -634,10 +631,10 @@ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int
limit = ((limit & 0xfff0) << 16) | 0xfffff; limit = ((limit & 0xfff0) << 16) | 0xfffff;
bridge->p_mem_head = acpiphp_make_resource((u64)base, limit - base + 1); bridge->p_mem_head = acpiphp_make_resource((u64)base, limit - base + 1);
if (!bridge->p_mem_head) { if (!bridge->p_mem_head) {
err("out of memory"); err("out of memory\n");
return; 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,
(u32)(bridge->p_mem_head->base + bridge->p_mem_head->length - 1)); (u32)(bridge->p_mem_head->base + bridge->p_mem_head->length - 1));
break; break;
...@@ -649,10 +646,10 @@ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int ...@@ -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); bridge->p_mem_head = acpiphp_make_resource(base64, limit64 - base64 + 1);
if (!bridge->p_mem_head) { if (!bridge->p_mem_head) {
err("out of memory"); err("out of memory\n");
return; 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 >> 32),
(u32)(bridge->p_mem_head->base & 0xffffffff), (u32)(bridge->p_mem_head->base & 0xffffffff),
(u32)((bridge->p_mem_head->base + bridge->p_mem_head->length - 1) >> 32), (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 ...@@ -661,7 +658,7 @@ static void add_p2p_bridge (acpi_handle *handle, int seg, int bus, int dev, int
case 0x0f: case 0x0f:
break; break;
default: default:
warn("Unknown prefetchale memory type"); warn("Unknown prefetchale memory type\n");
} }
init_bridge_misc(bridge); init_bridge_misc(bridge);
...@@ -689,7 +686,7 @@ find_p2p_bridge (acpi_handle handle, u32 lvl, void *context, void **rv) ...@@ -689,7 +686,7 @@ find_p2p_bridge (acpi_handle handle, u32 lvl, void *context, void **rv)
status = acpi_evaluate_integer(handle, "_ADR", NULL, &tmp); status = acpi_evaluate_integer(handle, "_ADR", NULL, &tmp);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
dbg("%s: _ADR evaluation failure", __FUNCTION__); dbg("%s: _ADR evaluation failure\n", __FUNCTION__);
return AE_OK; return AE_OK;
} }
...@@ -706,7 +703,7 @@ find_p2p_bridge (acpi_handle handle, u32 lvl, void *context, void **rv) ...@@ -706,7 +703,7 @@ find_p2p_bridge (acpi_handle handle, u32 lvl, void *context, void **rv)
/* check if this bridge has ejectable slots */ /* check if this bridge has ejectable slots */
if (detect_ejectable_slots(handle) > 0) { 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); add_p2p_bridge(handle, seg, bus, device, function);
} }
...@@ -727,7 +724,7 @@ static int add_bridges (acpi_handle *handle) ...@@ -727,7 +724,7 @@ static int add_bridges (acpi_handle *handle)
if (ACPI_SUCCESS(status)) { if (ACPI_SUCCESS(status)) {
status = acpi_evaluate_integer(handle, "_STA", NULL, &tmp); status = acpi_evaluate_integer(handle, "_STA", NULL, &tmp);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
dbg("%s: _STA evaluation failure", __FUNCTION__); dbg("%s: _STA evaluation failure\n", __FUNCTION__);
return 0; return 0;
} }
if ((tmp & ACPI_STA_FUNCTIONING) == 0) if ((tmp & ACPI_STA_FUNCTIONING) == 0)
...@@ -746,13 +743,13 @@ static int add_bridges (acpi_handle *handle) ...@@ -746,13 +743,13 @@ static int add_bridges (acpi_handle *handle)
if (ACPI_SUCCESS(status)) { if (ACPI_SUCCESS(status)) {
bus = tmp; bus = tmp;
} else { } else {
warn("can't get bus number, assuming 0"); warn("can't get bus number, assuming 0\n");
bus = 0; bus = 0;
} }
/* check if this bridge has ejectable slots */ /* check if this bridge has ejectable slots */
if (detect_ejectable_slots(handle) > 0) { 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); add_host_bridge(handle, seg, bus);
return 0; return 0;
} }
...@@ -764,7 +761,7 @@ static int add_bridges (acpi_handle *handle) ...@@ -764,7 +761,7 @@ static int add_bridges (acpi_handle *handle)
find_p2p_bridge, &tmp, NULL); find_p2p_bridge, &tmp, NULL);
if (ACPI_FAILURE(status)) 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; return 0;
} }
...@@ -782,7 +779,7 @@ find_host_bridge (acpi_handle handle, u32 lvl, void *context, void **rv) ...@@ -782,7 +779,7 @@ find_host_bridge (acpi_handle handle, u32 lvl, void *context, void **rv)
status = acpi_get_object_info(handle, &info); status = acpi_get_object_info(handle, &info);
if (ACPI_FAILURE(status)) { 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 */ return AE_OK; /* continue */
} }
...@@ -793,7 +790,7 @@ find_host_bridge (acpi_handle handle, u32 lvl, void *context, void **rv) ...@@ -793,7 +790,7 @@ find_host_bridge (acpi_handle handle, u32 lvl, void *context, void **rv)
(info.valid & ACPI_VALID_HID) && (info.valid & ACPI_VALID_HID) &&
strcmp(info.hardware_id, ACPI_PCI_HOST_HID) == 0) { strcmp(info.hardware_id, ACPI_PCI_HOST_HID) == 0) {
acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer); 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); add_bridges(handle);
} }
return AE_OK; return AE_OK;
...@@ -811,15 +808,15 @@ static int power_on_slot (struct acpiphp_slot *slot) ...@@ -811,15 +808,15 @@ static int power_on_slot (struct acpiphp_slot *slot)
if (slot->flags & SLOT_POWEREDON) if (slot->flags & SLOT_POWEREDON)
goto err_exit; goto err_exit;
list_for_each(l, &slot->funcs) { list_for_each (l, &slot->funcs) {
func = list_entry(l, struct acpiphp_func, sibling); func = list_entry(l, struct acpiphp_func, sibling);
if (func->flags & FUNC_HAS_PS0) { if (func->flags & FUNC_HAS_PS0) {
dbg("%s: executing _PS0 on %02x:%02x.%d", __FUNCTION__, dbg("%s: executing _PS0 on %s\n", __FUNCTION__,
slot->bridge->bus, slot->device, func->function); func->pci_dev->slot_name);
status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL); status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
warn("%s: _PS0 failed", __FUNCTION__); warn("%s: _PS0 failed\n", __FUNCTION__);
retval = -1; retval = -1;
goto err_exit; goto err_exit;
} }
...@@ -849,27 +846,27 @@ static int power_off_slot (struct acpiphp_slot *slot) ...@@ -849,27 +846,27 @@ static int power_off_slot (struct acpiphp_slot *slot)
if ((slot->flags & SLOT_POWEREDON) == 0) if ((slot->flags & SLOT_POWEREDON) == 0)
goto err_exit; goto err_exit;
list_for_each(l, &slot->funcs) { list_for_each (l, &slot->funcs) {
func = list_entry(l, struct acpiphp_func, sibling); func = list_entry(l, struct acpiphp_func, sibling);
if (func->flags & FUNC_HAS_PS3) { if (func->flags & FUNC_HAS_PS3) {
dbg("%s: executing _PS3 on %02x:%02x.%d", __FUNCTION__, dbg("%s: executing _PS3 on %s\n", __FUNCTION__,
slot->bridge->bus, slot->device, func->function); func->pci_dev->slot_name);
status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL); status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
warn("%s: _PS3 failed", __FUNCTION__); warn("%s: _PS3 failed\n", __FUNCTION__);
retval = -1; retval = -1;
goto err_exit; goto err_exit;
} }
} }
} }
list_for_each(l, &slot->funcs) { list_for_each (l, &slot->funcs) {
func = list_entry(l, struct acpiphp_func, sibling); func = list_entry(l, struct acpiphp_func, sibling);
if (func->flags & FUNC_HAS_EJ0) { if (func->flags & FUNC_HAS_EJ0) {
dbg("%s: executing _EJ0 on %02x:%02x.%d", __FUNCTION__, dbg("%s: executing _EJ0 on %s\n", __FUNCTION__,
slot->bridge->bus, slot->device, func->function); func->pci_dev->slot_name);
/* _EJ0 method take one argument */ /* _EJ0 method take one argument */
arg_list.count = 1; arg_list.count = 1;
...@@ -879,7 +876,7 @@ static int power_off_slot (struct acpiphp_slot *slot) ...@@ -879,7 +876,7 @@ static int power_off_slot (struct acpiphp_slot *slot)
status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL); status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
warn("%s: _EJ0 failed", __FUNCTION__); warn("%s: _EJ0 failed\n", __FUNCTION__);
retval = -1; retval = -1;
goto err_exit; goto err_exit;
} }
...@@ -919,7 +916,7 @@ static int enable_device (struct acpiphp_slot *slot) ...@@ -919,7 +916,7 @@ static int enable_device (struct acpiphp_slot *slot)
dev = pci_find_slot(slot->bridge->bus, PCI_DEVFN(slot->device, 0)); dev = pci_find_slot(slot->bridge->bus, PCI_DEVFN(slot->device, 0));
if (dev) { if (dev) {
/* This case shouldn't happen */ /* This case shouldn't happen */
err("pci_dev structure already exists."); err("pci_dev structure already exists.\n");
retval = -1; retval = -1;
goto err_exit; goto err_exit;
} }
...@@ -941,7 +938,7 @@ static int enable_device (struct acpiphp_slot *slot) ...@@ -941,7 +938,7 @@ static int enable_device (struct acpiphp_slot *slot)
dev = pci_scan_slot (&dev0); dev = pci_scan_slot (&dev0);
if (!dev) { if (!dev) {
err("No new device found"); err("No new device found\n");
retval = -1; retval = -1;
goto err_exit; goto err_exit;
} }
...@@ -953,7 +950,7 @@ static int enable_device (struct acpiphp_slot *slot) ...@@ -953,7 +950,7 @@ static int enable_device (struct acpiphp_slot *slot)
} }
/* associate pci_dev to our representation */ /* 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 = list_entry(l, struct acpiphp_func, sibling);
func->pci_dev = pci_find_slot(slot->bridge->bus, func->pci_dev = pci_find_slot(slot->bridge->bus,
...@@ -970,10 +967,8 @@ static int enable_device (struct acpiphp_slot *slot) ...@@ -970,10 +967,8 @@ static int enable_device (struct acpiphp_slot *slot)
slot->flags |= SLOT_ENABLED; slot->flags |= SLOT_ENABLED;
#if 1 dbg("Available resources:\n");
dbg("Available resources:");
acpiphp_dump_resource(slot->bridge); acpiphp_dump_resource(slot->bridge);
#endif
err_exit: err_exit:
return retval; return retval;
...@@ -993,14 +988,14 @@ static int disable_device (struct acpiphp_slot *slot) ...@@ -993,14 +988,14 @@ static int disable_device (struct acpiphp_slot *slot)
if (!(slot->flags & SLOT_ENABLED)) if (!(slot->flags & SLOT_ENABLED))
goto err_exit; goto err_exit;
list_for_each(l, &slot->funcs) { list_for_each (l, &slot->funcs) {
func = list_entry(l, struct acpiphp_func, sibling); func = list_entry(l, struct acpiphp_func, sibling);
if (func->pci_dev) { if (func->pci_dev) {
if (acpiphp_unconfigure_function(func) == 0) { if (acpiphp_unconfigure_function(func) == 0) {
func->pci_dev = NULL; func->pci_dev = NULL;
} else { } else {
err("failed to unconfigure device"); err("failed to unconfigure device\n");
retval = -1; retval = -1;
goto err_exit; goto err_exit;
} }
...@@ -1033,7 +1028,7 @@ static unsigned int get_slot_status (struct acpiphp_slot *slot) ...@@ -1033,7 +1028,7 @@ static unsigned int get_slot_status (struct acpiphp_slot *slot)
struct list_head *l; struct list_head *l;
struct acpiphp_func *func; struct acpiphp_func *func;
list_for_each(l, &slot->funcs) { list_for_each (l, &slot->funcs) {
func = list_entry(l, struct acpiphp_func, sibling); func = list_entry(l, struct acpiphp_func, sibling);
if (func->flags & FUNC_HAS_STA) { if (func->flags & FUNC_HAS_STA) {
...@@ -1084,28 +1079,28 @@ static void handle_hotplug_event_bridge (acpi_handle handle, u32 type, void *con ...@@ -1084,28 +1079,28 @@ static void handle_hotplug_event_bridge (acpi_handle handle, u32 type, void *con
switch (type) { switch (type) {
case ACPI_NOTIFY_BUS_CHECK: case ACPI_NOTIFY_BUS_CHECK:
/* bus re-enumerate */ /* 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); acpiphp_check_bridge(bridge);
break; break;
case ACPI_NOTIFY_DEVICE_CHECK: case ACPI_NOTIFY_DEVICE_CHECK:
/* 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); acpiphp_check_bridge(bridge);
break; break;
case ACPI_NOTIFY_DEVICE_WAKE: case ACPI_NOTIFY_DEVICE_WAKE:
/* wake event */ /* wake event */
dbg("%s: Device wake notify on %s", __FUNCTION__, objname); dbg("%s: Device wake notify on %s\n", __FUNCTION__, objname);
break; break;
case ACPI_NOTIFY_EJECT_REQUEST: case ACPI_NOTIFY_EJECT_REQUEST:
/* request device eject */ /* request device eject */
dbg("%s: Device eject notify on %s", __FUNCTION__, objname); dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname);
break; break;
default: 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; break;
} }
} }
...@@ -1135,29 +1130,29 @@ static void handle_hotplug_event_func (acpi_handle handle, u32 type, void *conte ...@@ -1135,29 +1130,29 @@ static void handle_hotplug_event_func (acpi_handle handle, u32 type, void *conte
switch (type) { switch (type) {
case ACPI_NOTIFY_BUS_CHECK: case ACPI_NOTIFY_BUS_CHECK:
/* bus re-enumerate */ /* 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); acpiphp_enable_slot(func->slot);
break; break;
case ACPI_NOTIFY_DEVICE_CHECK: case ACPI_NOTIFY_DEVICE_CHECK:
/* device check : re-enumerate from parent bus */ /* 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); acpiphp_check_bridge(func->slot->bridge);
break; break;
case ACPI_NOTIFY_DEVICE_WAKE: case ACPI_NOTIFY_DEVICE_WAKE:
/* wake event */ /* wake event */
dbg("%s: Device wake notify on %s", __FUNCTION__, objname); dbg("%s: Device wake notify on %s\n", __FUNCTION__, objname);
break; break;
case ACPI_NOTIFY_EJECT_REQUEST: case ACPI_NOTIFY_EJECT_REQUEST:
/* request device eject */ /* 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); acpiphp_disable_slot(func->slot);
break; break;
default: 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; break;
} }
} }
...@@ -1179,7 +1174,7 @@ int acpiphp_glue_init (void) ...@@ -1179,7 +1174,7 @@ int acpiphp_glue_init (void)
NULL, NULL); NULL, NULL);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
err("%s: acpi_walk_namespace() failed", __FUNCTION__); err("%s: acpi_walk_namespace() failed\n", __FUNCTION__);
return -1; return -1;
} }
...@@ -1200,12 +1195,12 @@ void acpiphp_glue_exit (void) ...@@ -1200,12 +1195,12 @@ void acpiphp_glue_exit (void)
struct acpiphp_func *func; struct acpiphp_func *func;
acpi_status status; acpi_status status;
list_for_each_safe(l1, n1, &bridge_list) { list_for_each_safe (l1, n1, &bridge_list) {
bridge = (struct acpiphp_bridge *)l1; bridge = (struct acpiphp_bridge *)l1;
slot = bridge->slots; slot = bridge->slots;
while (slot) { while (slot) {
next = slot->next; 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); func = list_entry(l2, struct acpiphp_func, sibling);
acpiphp_free_resource(&func->io_head); acpiphp_free_resource(&func->io_head);
acpiphp_free_resource(&func->mem_head); acpiphp_free_resource(&func->mem_head);
...@@ -1215,7 +1210,7 @@ void acpiphp_glue_exit (void) ...@@ -1215,7 +1210,7 @@ void acpiphp_glue_exit (void)
ACPI_SYSTEM_NOTIFY, ACPI_SYSTEM_NOTIFY,
handle_hotplug_event_func); handle_hotplug_event_func);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
err("failed to remove notify handler"); err("failed to remove notify handler\n");
kfree(func); kfree(func);
} }
kfree(slot); kfree(slot);
...@@ -1224,7 +1219,7 @@ void acpiphp_glue_exit (void) ...@@ -1224,7 +1219,7 @@ void acpiphp_glue_exit (void)
status = acpi_remove_notify_handler(bridge->handle, ACPI_SYSTEM_NOTIFY, status = acpi_remove_notify_handler(bridge->handle, ACPI_SYSTEM_NOTIFY,
handle_hotplug_event_bridge); handle_hotplug_event_bridge);
if (ACPI_FAILURE(status)) 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->io_head);
acpiphp_free_resource(&bridge->mem_head); acpiphp_free_resource(&bridge->mem_head);
...@@ -1247,13 +1242,13 @@ int acpiphp_get_num_slots (void) ...@@ -1247,13 +1242,13 @@ int acpiphp_get_num_slots (void)
num_slots = 0; num_slots = 0;
list_for_each(node, &bridge_list) { list_for_each (node, &bridge_list) {
bridge = (struct acpiphp_bridge *)node; 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; num_slots += bridge->nr_slots;
} }
dbg("Total %dslots", num_slots); dbg("Total %dslots\n", num_slots);
return num_slots; return num_slots;
} }
...@@ -1271,7 +1266,7 @@ int acpiphp_for_each_slot(acpiphp_callback fn, void *data) ...@@ -1271,7 +1266,7 @@ int acpiphp_for_each_slot(acpiphp_callback fn, void *data)
struct acpiphp_slot *slot; struct acpiphp_slot *slot;
int retval = 0; int retval = 0;
list_for_each(node, &bridge_list) { list_for_each (node, &bridge_list) {
bridge = (struct acpiphp_bridge *)node; bridge = (struct acpiphp_bridge *)node;
for (slot = bridge->slots; slot; slot = slot->next) { for (slot = bridge->slots; slot; slot = slot->next) {
retval = fn(slot, data); retval = fn(slot, data);
...@@ -1292,7 +1287,7 @@ struct acpiphp_slot *get_slot_from_id (int id) ...@@ -1292,7 +1287,7 @@ struct acpiphp_slot *get_slot_from_id (int id)
struct acpiphp_bridge *bridge; struct acpiphp_bridge *bridge;
struct acpiphp_slot *slot; struct acpiphp_slot *slot;
list_for_each(node, &bridge_list) { list_for_each (node, &bridge_list) {
bridge = (struct acpiphp_bridge *)node; bridge = (struct acpiphp_bridge *)node;
for (slot = bridge->slots; slot; slot = slot->next) for (slot = bridge->slots; slot; slot = slot->next)
if (slot->id == id) if (slot->id == id)
...@@ -1300,7 +1295,7 @@ struct acpiphp_slot *get_slot_from_id (int id) ...@@ -1300,7 +1295,7 @@ struct acpiphp_slot *get_slot_from_id (int id)
} }
/* should never happen! */ /* should never happen! */
err("%s: no object for id %d",__FUNCTION__, id); err("%s: no object for id %d\n",__FUNCTION__, id);
return 0; return 0;
} }
...@@ -1352,7 +1347,7 @@ int acpiphp_disable_slot (struct acpiphp_slot *slot) ...@@ -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->mem_head);
acpiphp_resource_sort_and_combine(&slot->bridge->p_mem_head); acpiphp_resource_sort_and_combine(&slot->bridge->p_mem_head);
acpiphp_resource_sort_and_combine(&slot->bridge->bus_head); acpiphp_resource_sort_and_combine(&slot->bridge->bus_head);
dbg("Available resources:"); dbg("Available resources:\n");
acpiphp_dump_resource(slot->bridge); acpiphp_dump_resource(slot->bridge);
err_exit: err_exit:
...@@ -1380,7 +1375,7 @@ int acpiphp_check_bridge (struct acpiphp_bridge *bridge) ...@@ -1380,7 +1375,7 @@ int acpiphp_check_bridge (struct acpiphp_bridge *bridge)
if (sta != ACPI_STA_ALL) { if (sta != ACPI_STA_ALL) {
retval = acpiphp_disable_slot(slot); retval = acpiphp_disable_slot(slot);
if (retval) { if (retval) {
err("Error occured in enabling"); err("Error occured in enabling\n");
up(&slot->crit_sect); up(&slot->crit_sect);
goto err_exit; goto err_exit;
} }
...@@ -1391,7 +1386,7 @@ int acpiphp_check_bridge (struct acpiphp_bridge *bridge) ...@@ -1391,7 +1386,7 @@ int acpiphp_check_bridge (struct acpiphp_bridge *bridge)
if (sta == ACPI_STA_ALL) { if (sta == ACPI_STA_ALL) {
retval = acpiphp_enable_slot(slot); retval = acpiphp_enable_slot(slot);
if (retval) { if (retval) {
err("Error occured in enabling"); err("Error occured in enabling\n");
up(&slot->crit_sect); up(&slot->crit_sect);
goto err_exit; goto err_exit;
} }
...@@ -1400,7 +1395,7 @@ int acpiphp_check_bridge (struct acpiphp_bridge *bridge) ...@@ -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: err_exit:
return retval; return retval;
......
...@@ -77,7 +77,7 @@ static int init_config_space (struct acpiphp_func *func) ...@@ -77,7 +77,7 @@ static int init_config_space (struct acpiphp_func *func)
if (!bar) /* This BAR is not implemented */ if (!bar) /* This BAR is not implemented */
continue; 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) { if (bar & PCI_BASE_ADDRESS_SPACE_IO) {
/* This is IO */ /* This is IO */
...@@ -85,7 +85,7 @@ static int init_config_space (struct acpiphp_func *func) ...@@ -85,7 +85,7 @@ static int init_config_space (struct acpiphp_func *func)
len = bar & 0xFFFFFFFC; len = bar & 0xFFFFFFFC;
len = ~len + 1; 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); spin_lock(&bridge->res_lock);
res = acpiphp_get_io_resource(&bridge->io_head, len); res = acpiphp_get_io_resource(&bridge->io_head, len);
...@@ -110,7 +110,7 @@ static int init_config_space (struct acpiphp_func *func) ...@@ -110,7 +110,7 @@ static int init_config_space (struct acpiphp_func *func)
len = bar & 0xFFFFFFF0; len = bar & 0xFFFFFFF0;
len = ~len + 1; 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); spin_lock(&bridge->res_lock);
res = acpiphp_get_resource(&bridge->p_mem_head, len); res = acpiphp_get_resource(&bridge->p_mem_head, len);
...@@ -127,7 +127,7 @@ static int init_config_space (struct acpiphp_func *func) ...@@ -127,7 +127,7 @@ static int init_config_space (struct acpiphp_func *func)
(u32)res->base); (u32)res->base);
if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */ 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; count += 1;
pci_bus_write_config_dword(pbus, devfn, pci_bus_write_config_dword(pbus, devfn,
address[count], address[count],
...@@ -143,7 +143,7 @@ static int init_config_space (struct acpiphp_func *func) ...@@ -143,7 +143,7 @@ static int init_config_space (struct acpiphp_func *func)
len = bar & 0xFFFFFFF0; len = bar & 0xFFFFFFF0;
len = ~len + 1; 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); spin_lock(&bridge->res_lock);
res = acpiphp_get_resource(&bridge->mem_head, len); res = acpiphp_get_resource(&bridge->mem_head, len);
...@@ -161,7 +161,7 @@ static int init_config_space (struct acpiphp_func *func) ...@@ -161,7 +161,7 @@ static int init_config_space (struct acpiphp_func *func)
if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) { if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) {
/* takes up another dword */ /* 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; count += 1;
pci_bus_write_config_dword(pbus, devfn, pci_bus_write_config_dword(pbus, devfn,
address[count], address[count],
...@@ -212,7 +212,7 @@ static int configure_pci_dev (struct pci_dev_wrapped *wrapped_dev, struct pci_bu ...@@ -212,7 +212,7 @@ static int configure_pci_dev (struct pci_dev_wrapped *wrapped_dev, struct pci_bu
//pci_proc_attach_device(dev); //pci_proc_attach_device(dev);
//pci_announce_device_to_drivers(dev); //pci_announce_device_to_drivers(dev);
info("Device %s configured", dev->slot_name); info("Device %s configured\n", dev->slot_name);
return 0; return 0;
} }
...@@ -263,13 +263,13 @@ static int unconfigure_pci_dev_driver (struct pci_dev_wrapped *wrapped_dev, stru ...@@ -263,13 +263,13 @@ static int unconfigure_pci_dev_driver (struct pci_dev_wrapped *wrapped_dev, stru
{ {
struct pci_dev *dev = wrapped_dev->dev; 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 */ /* Now, remove the Linux Driver Representation */
if (dev->driver) { if (dev->driver) {
if (dev->driver->remove) { if (dev->driver->remove) {
dev->driver->remove(dev); dev->driver->remove(dev);
dbg("driver was properly removed"); dbg("driver was properly removed\n");
} }
dev->driver = NULL; dev->driver = NULL;
} }
...@@ -286,7 +286,7 @@ static int unconfigure_pci_dev (struct pci_dev_wrapped *wrapped_dev, struct pci_ ...@@ -286,7 +286,7 @@ static int unconfigure_pci_dev (struct pci_dev_wrapped *wrapped_dev, struct pci_
/* Now, remove the Linux Representation */ /* Now, remove the Linux Representation */
if (dev) { if (dev) {
if (pci_hp_remove_device(dev) == 0) { 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 */ kfree(dev); /* Now, remove */
} else { } else {
return -1; /* problems while freeing, abort visitation */ return -1; /* problems while freeing, abort visitation */
...@@ -338,7 +338,7 @@ static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev * ...@@ -338,7 +338,7 @@ static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *
int count; int count;
struct pci_resource *res; 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 */ 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);
...@@ -355,7 +355,7 @@ static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev * ...@@ -355,7 +355,7 @@ static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *
len &= 0xFFFFFFFC; len &= 0xFFFFFFFC;
len = ~len + 1; 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); spin_lock(&bridge->res_lock);
res = acpiphp_get_resource_with_base(&bridge->io_head, base, len); 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 * ...@@ -372,10 +372,10 @@ static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *
len = ~len + 1; len = ~len + 1;
if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */ if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */
dbg ("prefetch mem 64"); dbg("prefetch mem 64\n");
count += 1; 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); spin_lock(&bridge->res_lock);
res = acpiphp_get_resource_with_base(&bridge->p_mem_head, base, len); res = acpiphp_get_resource_with_base(&bridge->p_mem_head, base, len);
spin_unlock(&bridge->res_lock); spin_unlock(&bridge->res_lock);
...@@ -389,10 +389,10 @@ static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev * ...@@ -389,10 +389,10 @@ static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *
if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {
/* takes up another dword */ /* takes up another dword */
dbg ("mem 64"); dbg("mem 64\n");
count += 1; 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); spin_lock(&bridge->res_lock);
res = acpiphp_get_resource_with_base(&bridge->mem_head, base, len); res = acpiphp_get_resource_with_base(&bridge->mem_head, base, len);
spin_unlock(&bridge->res_lock); spin_unlock(&bridge->res_lock);
...@@ -414,7 +414,7 @@ static void detect_used_resource_bus(struct acpiphp_bridge *bridge, struct pci_b ...@@ -414,7 +414,7 @@ static void detect_used_resource_bus(struct acpiphp_bridge *bridge, struct pci_b
struct list_head *l; struct list_head *l;
struct pci_dev *dev; struct pci_dev *dev;
list_for_each(l, &bus->devices) { list_for_each (l, &bus->devices) {
dev = pci_dev_b(l); dev = pci_dev_b(l);
detect_used_resource(bridge, dev); detect_used_resource(bridge, dev);
/* XXX recursive call */ /* XXX recursive call */
...@@ -463,16 +463,16 @@ int acpiphp_init_func_resource (struct acpiphp_func *func) ...@@ -463,16 +463,16 @@ int acpiphp_init_func_resource (struct acpiphp_func *func)
struct pci_dev *dev; struct pci_dev *dev;
dev = func->pci_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 */ 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 */ if (!bar) /* This BAR is not implemented */
continue; continue;
pci_write_config_dword (dev, address[count], 0xFFFFFFFF); pci_write_config_dword(dev, address[count], 0xFFFFFFFF);
pci_read_config_dword (dev, address[count], &len); pci_read_config_dword(dev, address[count], &len);
if (len & PCI_BASE_ADDRESS_SPACE_IO) { if (len & PCI_BASE_ADDRESS_SPACE_IO) {
/* This is IO */ /* This is IO */
...@@ -480,7 +480,7 @@ int acpiphp_init_func_resource (struct acpiphp_func *func) ...@@ -480,7 +480,7 @@ int acpiphp_init_func_resource (struct acpiphp_func *func)
len &= 0xFFFFFFFC; len &= 0xFFFFFFFC;
len = ~len + 1; 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); res = acpiphp_make_resource(base, len);
if (!res) if (!res)
...@@ -499,10 +499,10 @@ int acpiphp_init_func_resource (struct acpiphp_func *func) ...@@ -499,10 +499,10 @@ int acpiphp_init_func_resource (struct acpiphp_func *func)
len = ~len + 1; len = ~len + 1;
if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */ if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */
dbg ("prefetch mem 64"); dbg("prefetch mem 64\n");
count += 1; 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); res = acpiphp_make_resource(base, len);
if (!res) if (!res)
goto no_memory; goto no_memory;
...@@ -518,10 +518,10 @@ int acpiphp_init_func_resource (struct acpiphp_func *func) ...@@ -518,10 +518,10 @@ int acpiphp_init_func_resource (struct acpiphp_func *func)
if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {
/* takes up another dword */ /* takes up another dword */
dbg ("mem 64"); dbg("mem 64\n");
count += 1; 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); res = acpiphp_make_resource(base, len);
if (!res) if (!res)
goto no_memory; goto no_memory;
...@@ -532,7 +532,7 @@ int acpiphp_init_func_resource (struct acpiphp_func *func) ...@@ -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 #if 1
acpiphp_dump_func_resource(func); acpiphp_dump_func_resource(func);
...@@ -541,7 +541,7 @@ int acpiphp_init_func_resource (struct acpiphp_func *func) ...@@ -541,7 +541,7 @@ int acpiphp_init_func_resource (struct acpiphp_func *func)
return 0; return 0;
no_memory: no_memory:
err("out of memory"); err("out of memory\n");
acpiphp_free_resource(&func->io_head); acpiphp_free_resource(&func->io_head);
acpiphp_free_resource(&func->mem_head); acpiphp_free_resource(&func->mem_head);
acpiphp_free_resource(&func->p_mem_head); acpiphp_free_resource(&func->p_mem_head);
...@@ -574,7 +574,7 @@ int acpiphp_configure_slot (struct acpiphp_slot *slot) ...@@ -574,7 +574,7 @@ int acpiphp_configure_slot (struct acpiphp_slot *slot)
if (hdr & 0x80) if (hdr & 0x80)
is_multi = 1; is_multi = 1;
list_for_each(l, &slot->funcs) { list_for_each (l, &slot->funcs) {
func = list_entry(l, struct acpiphp_func, sibling); func = list_entry(l, struct acpiphp_func, sibling);
if (is_multi || func->function == 0) { if (is_multi || func->function == 0) {
pci_bus_read_config_dword(slot->bridge->pci_bus, pci_bus_read_config_dword(slot->bridge->pci_bus,
...@@ -583,7 +583,6 @@ int acpiphp_configure_slot (struct acpiphp_slot *slot) ...@@ -583,7 +583,6 @@ int acpiphp_configure_slot (struct acpiphp_slot *slot)
PCI_VENDOR_ID, &dvid); PCI_VENDOR_ID, &dvid);
if (dvid != 0xffffffff) { if (dvid != 0xffffffff) {
retval = init_config_space(func); retval = init_config_space(func);
if (retval) if (retval)
break; break;
} }
......
...@@ -370,13 +370,13 @@ struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size) ...@@ -370,13 +370,13 @@ struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size)
return NULL; return NULL;
for (node = *head; node; node = node->next) { 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); __FUNCTION__, size, node, (u32)node->base, node->length);
if (node->length < size) if (node->length < size)
continue; continue;
if (node->base & (size - 1)) { if (node->base & (size - 1)) {
dbg("%s: not aligned", __FUNCTION__); dbg("%s: not aligned\n", __FUNCTION__);
/* this one isn't base aligned properly /* this one isn't base aligned properly
so we'll make a new entry and split it up */ so we'll make a new entry and split it up */
temp_qword = (node->base | (size-1)) + 1; temp_qword = (node->base | (size-1)) + 1;
...@@ -400,7 +400,7 @@ struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size) ...@@ -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 */ /* Don't need to check if too small since we already did */
if (node->length > size) { if (node->length > size) {
dbg("%s: too big", __FUNCTION__); dbg("%s: too big\n", __FUNCTION__);
/* this one is longer than we need /* this one is longer than we need
so we'll make a new entry and split it up */ so we'll make a new entry and split it up */
split_node = acpiphp_make_resource(node->base + size, node->length - size); 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) ...@@ -415,7 +415,7 @@ struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size)
node->next = split_node; node->next = split_node;
} /* End of too big on top end */ } /* 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 /* If we got here, then it is the right size
Now take it out of the list */ Now take it out of the list */
if (*head == node) { if (*head == node) {
...@@ -458,7 +458,7 @@ struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head, ...@@ -458,7 +458,7 @@ struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head,
return NULL; return NULL;
for (node = *head; node; node = node->next) { 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); (u32)base, size, node, (u32)node->base, node->length);
if (node->base > base) if (node->base > base)
continue; continue;
...@@ -467,7 +467,7 @@ struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head, ...@@ -467,7 +467,7 @@ struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head,
continue; continue;
if (node->base < base) { if (node->base < base) {
dbg(": split 1"); dbg(": split 1\n");
/* this one isn't base aligned properly /* this one isn't base aligned properly
so we'll make a new entry and split it up */ so we'll make a new entry and split it up */
temp_qword = base; temp_qword = base;
...@@ -489,12 +489,12 @@ struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head, ...@@ -489,12 +489,12 @@ struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head,
node->next = split_node; 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); (u32)base, size, node, (u32)node->base, node->length);
/* Don't need to check if too small since we already did */ /* Don't need to check if too small since we already did */
if (node->length > size) { if (node->length > size) {
dbg(": split 2"); dbg(": split 2\n");
/* this one is longer than we need /* this one is longer than we need
so we'll make a new entry and split it up */ so we'll make a new entry and split it up */
split_node = acpiphp_make_resource(node->base + size, node->length - size); 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, ...@@ -509,7 +509,7 @@ struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head,
node->next = split_node; node->next = split_node;
} /* End of too big on top end */ } /* End of too big on top end */
dbg(": got one!!!"); dbg(": got one!!!\n");
/* If we got here, then it is the right size /* If we got here, then it is the right size
Now take it out of the list */ Now take it out of the list */
if (*head == node) { if (*head == node) {
...@@ -547,13 +547,13 @@ int acpiphp_resource_sort_and_combine (struct pci_resource **head) ...@@ -547,13 +547,13 @@ int acpiphp_resource_sort_and_combine (struct pci_resource **head)
if (!(*head)) if (!(*head))
return 1; return 1;
dbg("*head->next = %p",(*head)->next); dbg("*head->next = %p\n",(*head)->next);
if (!(*head)->next) if (!(*head)->next)
return 0; /* only one item on the list, already sorted! */ return 0; /* only one item on the list, already sorted! */
dbg("*head->base = 0x%x",(u32)(*head)->base); dbg("*head->base = 0x%x\n",(u32)(*head)->base);
dbg("*head->next->base = 0x%x", (u32)(*head)->next->base); dbg("*head->next->base = 0x%x\n", (u32)(*head)->next->base);
while (out_of_order) { while (out_of_order) {
out_of_order = 0; out_of_order = 0;
...@@ -587,7 +587,7 @@ int acpiphp_resource_sort_and_combine (struct pci_resource **head) ...@@ -587,7 +587,7 @@ int acpiphp_resource_sort_and_combine (struct pci_resource **head)
while (node1 && node1->next) { while (node1 && node1->next) {
if ((node1->base + node1->length) == node1->next->base) { if ((node1->base + node1->length) == node1->next->base) {
/* Combine */ /* Combine */
dbg("8.."); dbg("8..\n");
node1->length += node1->next->length; node1->length += node1->next->length;
node2 = node1->next; node2 = node1->next;
node1->next = node1->next->next; node1->next = node1->next->next;
...@@ -668,7 +668,7 @@ static void dump_resource(struct pci_resource *head) ...@@ -668,7 +668,7 @@ static void dump_resource(struct pci_resource *head)
cnt = 0; cnt = 0;
while (p) { while (p) {
dbg("[%02d] %08x - %08x", dbg("[%02d] %08x - %08x\n",
cnt++, (u32)p->base, (u32)p->base + p->length - 1); cnt++, (u32)p->base, (u32)p->base + p->length - 1);
p = p->next; p = p->next;
} }
...@@ -676,24 +676,24 @@ static void dump_resource(struct pci_resource *head) ...@@ -676,24 +676,24 @@ static void dump_resource(struct pci_resource *head)
void acpiphp_dump_resource(struct acpiphp_bridge *bridge) void acpiphp_dump_resource(struct acpiphp_bridge *bridge)
{ {
dbg("I/O resource:"); dbg("I/O resource:\n");
dump_resource(bridge->io_head); dump_resource(bridge->io_head);
dbg("MEM resource:"); dbg("MEM resource:\n");
dump_resource(bridge->mem_head); dump_resource(bridge->mem_head);
dbg("PMEM resource:"); dbg("PMEM resource:\n");
dump_resource(bridge->p_mem_head); dump_resource(bridge->p_mem_head);
dbg("BUS resource:"); dbg("BUS resource:\n");
dump_resource(bridge->bus_head); dump_resource(bridge->bus_head);
} }
void acpiphp_dump_func_resource(struct acpiphp_func *func) void acpiphp_dump_func_resource(struct acpiphp_func *func)
{ {
dbg("I/O resource:"); dbg("I/O resource:\n");
dump_resource(func->io_head); dump_resource(func->io_head);
dbg("MEM resource:"); dbg("MEM resource:\n");
dump_resource(func->mem_head); dump_resource(func->mem_head);
dbg("PMEM resource:"); dbg("PMEM resource:\n");
dump_resource(func->p_mem_head); dump_resource(func->p_mem_head);
dbg("BUS resource:"); dbg("BUS resource:\n");
dump_resource(func->bus_head); dump_resource(func->bus_head);
} }
/*
* 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 */
/*
* 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);
/*
* 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;
}
/*
* 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)");
/*
* 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");
/*
* 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 */
...@@ -167,5 +167,9 @@ extern int pci_visit_dev (struct pci_visit *fn, ...@@ -167,5 +167,9 @@ extern int pci_visit_dev (struct pci_visit *fn,
struct pci_dev_wrapped *wrapped_dev, struct pci_dev_wrapped *wrapped_dev,
struct pci_bus_wrapped *wrapped_parent); 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 #endif
...@@ -94,15 +94,12 @@ static int pci_visit_bus (struct pci_visit * fn, struct pci_bus_wrapped *wrapped ...@@ -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) 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; struct pci_bus_wrapped wrapped_bus;
int result; int result = 0;
memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped));
wrapped_bus.bus = bus;
dbg("scanning bridge %02x, %02x\n", wrapped_dev->dev->devfn >> 3, dbg("scanning bridge %02x, %02x\n", PCI_SLOT(wrapped_dev->dev->devfn),
wrapped_dev->dev->devfn & 0x7); PCI_FUNC(wrapped_dev->dev->devfn));
if (fn->visit_pci_dev) { if (fn->visit_pci_dev) {
result = fn->visit_pci_dev(wrapped_dev, wrapped_parent); 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 ...@@ -110,7 +107,13 @@ static int pci_visit_bridge (struct pci_visit * fn, struct pci_dev_wrapped *wrap
return result; return result;
} }
bus = wrapped_dev->dev->subordinate;
if(bus) {
memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped));
wrapped_bus.bus = bus;
result = pci_visit_bus(fn, &wrapped_bus, wrapped_dev); result = pci_visit_bus(fn, &wrapped_bus, wrapped_dev);
}
return result; return result;
} }
...@@ -153,6 +156,62 @@ int pci_visit_dev (struct pci_visit *fn, struct pci_dev_wrapped *wrapped_dev, st ...@@ -153,6 +156,62 @@ int pci_visit_dev (struct pci_visit *fn, struct pci_dev_wrapped *wrapped_dev, st
return result; 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_visit_dev);
EXPORT_SYMBOL(pci_is_dev_in_use);
EXPORT_SYMBOL(pci_remove_device_safe);
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# #
export-objs := access.o hotplug.o pci-driver.o pci.o pool.o \ 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 \ obj-y += access.o probe.o pci.o pool.o quirks.o \
compat.o names.o pci-driver.o search.o hotplug.o compat.o names.o pci-driver.o search.o hotplug.o
...@@ -25,6 +25,11 @@ obj-$(CONFIG_PPC32) += setup-irq.o ...@@ -25,6 +25,11 @@ obj-$(CONFIG_PPC32) += setup-irq.o
obj-$(CONFIG_DDB5476) += setup-bus.o obj-$(CONFIG_DDB5476) += setup-bus.o
obj-$(CONFIG_SGI_IP27) += setup-irq.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 ifndef CONFIG_X86
obj-y += syscall.o obj-y += syscall.o
endif endif
......
...@@ -71,8 +71,7 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp, ...@@ -71,8 +71,7 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp,
* @bus: where to insert it * @bus: where to insert it
* *
* Link the device to both the global PCI device chain and the * Link the device to both the global PCI device chain and the
* per-bus list of devices, add the /proc entry, and notify * per-bus list of devices, add the /proc entry.
* userspace (/sbin/hotplug).
*/ */
void void
pci_insert_device(struct pci_dev *dev, struct pci_bus *bus) pci_insert_device(struct pci_dev *dev, struct pci_bus *bus)
......
...@@ -24,6 +24,49 @@ ...@@ -24,6 +24,49 @@
#define DBG(x...) #define DBG(x...)
#endif #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 * pci_find_capability - query for devices' capabilities
* @dev: PCI device to query * @dev: PCI device to query
...@@ -79,6 +122,49 @@ pci_find_capability(struct pci_dev *dev, int cap) ...@@ -79,6 +122,49 @@ pci_find_capability(struct pci_dev *dev, int cap)
return 0; 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 * pci_find_parent_resource - return resource region of parent bus of given region
...@@ -649,7 +735,10 @@ EXPORT_SYMBOL(isa_bridge); ...@@ -649,7 +735,10 @@ EXPORT_SYMBOL(isa_bridge);
EXPORT_SYMBOL(pci_enable_device); EXPORT_SYMBOL(pci_enable_device);
EXPORT_SYMBOL(pci_disable_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_find_capability);
EXPORT_SYMBOL(pci_bus_find_capability);
EXPORT_SYMBOL(pci_release_regions); EXPORT_SYMBOL(pci_release_regions);
EXPORT_SYMBOL(pci_request_regions); EXPORT_SYMBOL(pci_request_regions);
EXPORT_SYMBOL(pci_release_region); EXPORT_SYMBOL(pci_release_region);
......
...@@ -254,7 +254,7 @@ struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_de ...@@ -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 * them, we proceed to assigning numbers to the remaining buses in
* order to avoid overlaps between old and new bus numbers. * 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 int buses;
unsigned short cr; unsigned short cr;
...@@ -480,8 +480,7 @@ struct pci_dev * __devinit pci_scan_slot(struct pci_dev *temp) ...@@ -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 * Link the device to both the global PCI device chain and
* the per-bus list of devices and call /sbin/hotplug if we * the per-bus list of devices and add the /proc entry.
* should.
*/ */
pci_insert_device (dev, bus); pci_insert_device (dev, bus);
...@@ -596,4 +595,5 @@ EXPORT_SYMBOL(pci_add_new_bus); ...@@ -596,4 +595,5 @@ EXPORT_SYMBOL(pci_add_new_bus);
EXPORT_SYMBOL(pci_do_scan_bus); EXPORT_SYMBOL(pci_do_scan_bus);
EXPORT_SYMBOL(pci_scan_slot); EXPORT_SYMBOL(pci_scan_slot);
EXPORT_SYMBOL(pci_scan_bus); EXPORT_SYMBOL(pci_scan_bus);
EXPORT_SYMBOL(pci_scan_bridge);
#endif #endif
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
/* Deal with broken BIOS'es that neglect to enable passive release, /* Deal with broken BIOS'es that neglect to enable passive release,
which can cause problems in combination with the 82441FX/PPro MTRRs */ which can cause problems in combination with the 82441FX/PPro MTRRs */
static void __init quirk_passive_release(struct pci_dev *dev) static void __devinit quirk_passive_release(struct pci_dev *dev)
{ {
struct pci_dev *d = NULL; struct pci_dev *d = NULL;
unsigned char dlc; unsigned char dlc;
...@@ -50,7 +50,7 @@ static void __init quirk_passive_release(struct pci_dev *dev) ...@@ -50,7 +50,7 @@ static void __init quirk_passive_release(struct pci_dev *dev)
int isa_dma_bridge_buggy; /* Exported */ int isa_dma_bridge_buggy; /* Exported */
static void __init quirk_isa_dma_hangs(struct pci_dev *dev) static void __devinit quirk_isa_dma_hangs(struct pci_dev *dev)
{ {
if (!isa_dma_bridge_buggy) { if (!isa_dma_bridge_buggy) {
isa_dma_bridge_buggy=1; isa_dma_bridge_buggy=1;
...@@ -64,7 +64,7 @@ int pci_pci_problems; ...@@ -64,7 +64,7 @@ int pci_pci_problems;
* Chipsets where PCI->PCI transfers vanish or hang * Chipsets where PCI->PCI transfers vanish or hang
*/ */
static void __init quirk_nopcipci(struct pci_dev *dev) static void __devinit quirk_nopcipci(struct pci_dev *dev)
{ {
if((pci_pci_problems&PCIPCI_FAIL)==0) if((pci_pci_problems&PCIPCI_FAIL)==0)
{ {
...@@ -77,7 +77,7 @@ static void __init quirk_nopcipci(struct pci_dev *dev) ...@@ -77,7 +77,7 @@ static void __init quirk_nopcipci(struct pci_dev *dev)
* Triton requires workarounds to be used by the drivers * Triton requires workarounds to be used by the drivers
*/ */
static void __init quirk_triton(struct pci_dev *dev) static void __devinit quirk_triton(struct pci_dev *dev)
{ {
if((pci_pci_problems&PCIPCI_TRITON)==0) if((pci_pci_problems&PCIPCI_TRITON)==0)
{ {
...@@ -96,7 +96,7 @@ static void __init quirk_triton(struct pci_dev *dev) ...@@ -96,7 +96,7 @@ static void __init quirk_triton(struct pci_dev *dev)
* Updated based on further information from the site and also on * Updated based on further information from the site and also on
* information provided by VIA * information provided by VIA
*/ */
static void __init quirk_vialatency(struct pci_dev *dev) static void __devinit quirk_vialatency(struct pci_dev *dev)
{ {
struct pci_dev *p; struct pci_dev *p;
u8 rev; u8 rev;
...@@ -150,7 +150,7 @@ static void __init quirk_vialatency(struct pci_dev *dev) ...@@ -150,7 +150,7 @@ static void __init quirk_vialatency(struct pci_dev *dev)
* VIA Apollo VP3 needs ETBF on BT848/878 * VIA Apollo VP3 needs ETBF on BT848/878
*/ */
static void __init quirk_viaetbf(struct pci_dev *dev) static void __devinit quirk_viaetbf(struct pci_dev *dev)
{ {
if((pci_pci_problems&PCIPCI_VIAETBF)==0) if((pci_pci_problems&PCIPCI_VIAETBF)==0)
{ {
...@@ -158,7 +158,7 @@ static void __init quirk_viaetbf(struct pci_dev *dev) ...@@ -158,7 +158,7 @@ static void __init quirk_viaetbf(struct pci_dev *dev)
pci_pci_problems|=PCIPCI_VIAETBF; pci_pci_problems|=PCIPCI_VIAETBF;
} }
} }
static void __init quirk_vsfx(struct pci_dev *dev) static void __devinit quirk_vsfx(struct pci_dev *dev)
{ {
if((pci_pci_problems&PCIPCI_VSFX)==0) if((pci_pci_problems&PCIPCI_VSFX)==0)
{ {
...@@ -173,7 +173,7 @@ static void __init quirk_vsfx(struct pci_dev *dev) ...@@ -173,7 +173,7 @@ static void __init quirk_vsfx(struct pci_dev *dev)
* at least * at least
*/ */
static void __init quirk_natoma(struct pci_dev *dev) static void __devinit quirk_natoma(struct pci_dev *dev)
{ {
if((pci_pci_problems&PCIPCI_NATOMA)==0) if((pci_pci_problems&PCIPCI_NATOMA)==0)
{ {
...@@ -187,7 +187,7 @@ static void __init quirk_natoma(struct pci_dev *dev) ...@@ -187,7 +187,7 @@ static void __init quirk_natoma(struct pci_dev *dev)
* If it's needed, re-allocate the region. * If it's needed, re-allocate the region.
*/ */
static void __init quirk_s3_64M(struct pci_dev *dev) static void __devinit quirk_s3_64M(struct pci_dev *dev)
{ {
struct resource *r = &dev->resource[0]; struct resource *r = &dev->resource[0];
...@@ -197,7 +197,7 @@ static void __init quirk_s3_64M(struct pci_dev *dev) ...@@ -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 __devinit quirk_io_region(struct pci_dev *dev, unsigned region, unsigned size, int nr)
{ {
region &= ~(size-1); region &= ~(size-1);
if (region) { if (region) {
...@@ -222,7 +222,7 @@ static void __init quirk_io_region(struct pci_dev *dev, unsigned region, unsigne ...@@ -222,7 +222,7 @@ static void __init quirk_io_region(struct pci_dev *dev, unsigned region, unsigne
* 0xE0 (64 bytes of ACPI registers) * 0xE0 (64 bytes of ACPI registers)
* 0xE2 (32 bytes of SMB registers) * 0xE2 (32 bytes of SMB registers)
*/ */
static void __init quirk_ali7101_acpi(struct pci_dev *dev) static void __devinit quirk_ali7101_acpi(struct pci_dev *dev)
{ {
u16 region; u16 region;
...@@ -237,7 +237,7 @@ static void __init quirk_ali7101_acpi(struct pci_dev *dev) ...@@ -237,7 +237,7 @@ static void __init quirk_ali7101_acpi(struct pci_dev *dev)
* 0x40 (64 bytes of ACPI registers) * 0x40 (64 bytes of ACPI registers)
* 0x90 (32 bytes of SMB registers) * 0x90 (32 bytes of SMB registers)
*/ */
static void __init quirk_piix4_acpi(struct pci_dev *dev) static void __devinit quirk_piix4_acpi(struct pci_dev *dev)
{ {
u32 region; u32 region;
...@@ -251,7 +251,7 @@ static void __init quirk_piix4_acpi(struct pci_dev *dev) ...@@ -251,7 +251,7 @@ static void __init quirk_piix4_acpi(struct pci_dev *dev)
* VIA ACPI: One IO region pointed to by longword at * VIA ACPI: One IO region pointed to by longword at
* 0x48 or 0x20 (256 bytes of ACPI registers) * 0x48 or 0x20 (256 bytes of ACPI registers)
*/ */
static void __init quirk_vt82c586_acpi(struct pci_dev *dev) static void __devinit quirk_vt82c586_acpi(struct pci_dev *dev)
{ {
u8 rev; u8 rev;
u32 region; u32 region;
...@@ -270,7 +270,7 @@ static void __init quirk_vt82c586_acpi(struct pci_dev *dev) ...@@ -270,7 +270,7 @@ static void __init quirk_vt82c586_acpi(struct pci_dev *dev)
* 0x70 (128 bytes of hardware monitoring register) * 0x70 (128 bytes of hardware monitoring register)
* 0x90 (16 bytes of SMB registers) * 0x90 (16 bytes of SMB registers)
*/ */
static void __init quirk_vt82c686_acpi(struct pci_dev *dev) static void __devinit quirk_vt82c686_acpi(struct pci_dev *dev)
{ {
u16 hm; u16 hm;
u32 smb; u32 smb;
...@@ -297,7 +297,7 @@ extern int nr_ioapics; ...@@ -297,7 +297,7 @@ extern int nr_ioapics;
* TODO: When we have device-specific interrupt routers, * TODO: When we have device-specific interrupt routers,
* this code will go away from quirks. * this code will go away from quirks.
*/ */
static void __init quirk_via_ioapic(struct pci_dev *dev) static void __devinit quirk_via_ioapic(struct pci_dev *dev)
{ {
u8 tmp; u8 tmp;
...@@ -338,7 +338,7 @@ static void __init quirk_via_ioapic(struct pci_dev *dev) ...@@ -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. * value of the ACPI SCI interrupt is only done for convenience.
* -jgarzik * -jgarzik
*/ */
static void __init quirk_via_acpi(struct pci_dev *d) static void __devinit quirk_via_acpi(struct pci_dev *d)
{ {
/* /*
* VIA ACPI device: SCI IRQ line in PCI config byte 0x42 * 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) ...@@ -350,7 +350,7 @@ static void __init quirk_via_acpi(struct pci_dev *d)
d->irq = irq; d->irq = irq;
} }
static void __init quirk_via_irqpic(struct pci_dev *dev) static void __devinit quirk_via_irqpic(struct pci_dev *dev)
{ {
u8 irq, new_irq = dev->irq & 0xf; u8 irq, new_irq = dev->irq & 0xf;
...@@ -377,7 +377,7 @@ static void __init quirk_via_irqpic(struct pci_dev *dev) ...@@ -377,7 +377,7 @@ static void __init quirk_via_irqpic(struct pci_dev *dev)
* *
* We mask out all r/wc bits, too. * We mask out all r/wc bits, too.
*/ */
static void __init quirk_piix3_usb(struct pci_dev *dev) static void __devinit quirk_piix3_usb(struct pci_dev *dev)
{ {
u16 legsup; u16 legsup;
...@@ -392,7 +392,7 @@ static void __init quirk_piix3_usb(struct pci_dev *dev) ...@@ -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 * We need to switch it off to be able to recognize the real
* type of the chip. * type of the chip.
*/ */
static void __init quirk_vt82c598_id(struct pci_dev *dev) static void __devinit quirk_vt82c598_id(struct pci_dev *dev)
{ {
pci_write_config_byte(dev, 0xfc, 0); pci_write_config_byte(dev, 0xfc, 0);
pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device); pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device);
...@@ -404,7 +404,7 @@ static void __init quirk_vt82c598_id(struct pci_dev *dev) ...@@ -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 * do this even if the Linux CardBus driver is not loaded, because
* the Linux i82365 driver does not (and should not) handle CardBus. * the Linux i82365 driver does not (and should not) handle CardBus.
*/ */
static void __init quirk_cardbus_legacy(struct pci_dev *dev) static void __devinit quirk_cardbus_legacy(struct pci_dev *dev)
{ {
if ((PCI_CLASS_BRIDGE_CARDBUS << 8) ^ dev->class) if ((PCI_CLASS_BRIDGE_CARDBUS << 8) ^ dev->class)
return; return;
...@@ -421,7 +421,7 @@ static void __init quirk_cardbus_legacy(struct pci_dev *dev) ...@@ -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.. * of course. However the advice is demonstrably good even if so..
*/ */
static void __init quirk_amd_ioapic(struct pci_dev *dev) static void __devinit quirk_amd_ioapic(struct pci_dev *dev)
{ {
u8 rev; u8 rev;
...@@ -441,7 +441,7 @@ static void __init quirk_amd_ioapic(struct pci_dev *dev) ...@@ -441,7 +441,7 @@ static void __init quirk_amd_ioapic(struct pci_dev *dev)
* who turn it off! * who turn it off!
*/ */
static void __init quirk_amd_ordering(struct pci_dev *dev) static void __devinit quirk_amd_ordering(struct pci_dev *dev)
{ {
u32 pcic; u32 pcic;
pci_read_config_dword(dev, 0x4C, &pcic); pci_read_config_dword(dev, 0x4C, &pcic);
...@@ -464,14 +464,14 @@ static void __init quirk_amd_ordering(struct pci_dev *dev) ...@@ -464,14 +464,14 @@ static void __init quirk_amd_ordering(struct pci_dev *dev)
* nothing gets put too close to it. * nothing gets put too close to it.
*/ */
static void __init quirk_dunord ( struct pci_dev * dev ) static void __devinit quirk_dunord ( struct pci_dev * dev )
{ {
struct resource * r = & dev -> resource [ 1 ]; struct resource * r = & dev -> resource [ 1 ];
r -> start = 0; r -> start = 0;
r -> end = 0xffffff; r -> end = 0xffffff;
} }
static void __init quirk_transparent_bridge(struct pci_dev *dev) static void __devinit quirk_transparent_bridge(struct pci_dev *dev)
{ {
dev->transparent = 1; dev->transparent = 1;
} }
...@@ -480,7 +480,7 @@ static void __init quirk_transparent_bridge(struct pci_dev *dev) ...@@ -480,7 +480,7 @@ static void __init quirk_transparent_bridge(struct pci_dev *dev)
* The main table of quirks. * The main table of quirks.
*/ */
static struct pci_fixup pci_fixups[] __initdata = { static struct pci_fixup pci_fixups[] __devinitdata = {
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_DUNORD, PCI_DEVICE_ID_DUNORD_I3000, quirk_dunord }, { 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 },
{ 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 },
......
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/module.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 * pci_find_slot - locate PCI device from a given PCI slot
* @bus: number of PCI bus on which desired PCI device resides * @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) ...@@ -104,6 +143,7 @@ pci_find_class(unsigned int class, const struct pci_dev *from)
return NULL; return NULL;
} }
EXPORT_SYMBOL(pci_find_bus);
EXPORT_SYMBOL(pci_find_class); EXPORT_SYMBOL(pci_find_class);
EXPORT_SYMBOL(pci_find_device); EXPORT_SYMBOL(pci_find_device);
EXPORT_SYMBOL(pci_find_slot); EXPORT_SYMBOL(pci_find_slot);
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/ioport.h> #include <linux/ioport.h>
...@@ -35,7 +36,7 @@ ...@@ -35,7 +36,7 @@
#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1)) #define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
static int __init static int __devinit
pbus_assign_resources_sorted(struct pci_bus *bus) pbus_assign_resources_sorted(struct pci_bus *bus)
{ {
struct list_head *ln; struct list_head *ln;
...@@ -85,7 +86,7 @@ pbus_assign_resources_sorted(struct pci_bus *bus) ...@@ -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 requires that if there is no I/O ports or memory behind the
bridge, corresponding range must be turned off by writing base bridge, corresponding range must be turned off by writing base
value greater than limit to the bridge's base/limit registers. */ value greater than limit to the bridge's base/limit registers. */
static void __init static void __devinit
pci_setup_bridge(struct pci_bus *bus) pci_setup_bridge(struct pci_bus *bus)
{ {
struct pbus_set_ranges_data ranges; struct pbus_set_ranges_data ranges;
...@@ -168,7 +169,7 @@ pci_setup_bridge(struct pci_bus *bus) ...@@ -168,7 +169,7 @@ pci_setup_bridge(struct pci_bus *bus)
/* Check whether the bridge supports optional I/O and /* Check whether the bridge supports optional I/O and
prefetchable memory ranges. If not, the respective prefetchable memory ranges. If not, the respective
base/limit registers must be read-only and read as 0. */ base/limit registers must be read-only and read as 0. */
static void __init static void __devinit
pci_bridge_check_ranges(struct pci_bus *bus) pci_bridge_check_ranges(struct pci_bus *bus)
{ {
u16 io; u16 io;
...@@ -210,7 +211,7 @@ pci_bridge_check_ranges(struct pci_bus *bus) ...@@ -210,7 +211,7 @@ pci_bridge_check_ranges(struct pci_bus *bus)
since these windows have 4K granularity and the IO ranges since these windows have 4K granularity and the IO ranges
of non-bridge PCI devices are limited to 256 bytes. of non-bridge PCI devices are limited to 256 bytes.
We must be careful with the ISA aliasing though. */ We must be careful with the ISA aliasing though. */
static void __init static void __devinit
pbus_size_io(struct pci_bus *bus) pbus_size_io(struct pci_bus *bus)
{ {
struct list_head *ln; struct list_head *ln;
...@@ -259,7 +260,7 @@ pbus_size_io(struct pci_bus *bus) ...@@ -259,7 +260,7 @@ pbus_size_io(struct pci_bus *bus)
/* Calculate the size of the bus and minimal alignment which /* Calculate the size of the bus and minimal alignment which
guarantees that all child resources fit in this size. */ guarantees that all child resources fit in this size. */
static void __init static void __devinit
pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type) pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type)
{ {
struct list_head *ln; struct list_head *ln;
...@@ -331,7 +332,7 @@ pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type) ...@@ -331,7 +332,7 @@ pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type)
b_res->end = size + min_align - 1; b_res->end = size + min_align - 1;
} }
void __init void __devinit
pbus_size_bridges(struct pci_bus *bus) pbus_size_bridges(struct pci_bus *bus)
{ {
struct list_head *ln; struct list_head *ln;
...@@ -357,8 +358,9 @@ pbus_size_bridges(struct pci_bus *bus) ...@@ -357,8 +358,9 @@ pbus_size_bridges(struct pci_bus *bus)
} }
pbus_size_mem(bus, mask, type); pbus_size_mem(bus, mask, type);
} }
EXPORT_SYMBOL(pbus_size_bridges);
void __init void __devinit
pbus_assign_resources(struct pci_bus *bus) pbus_assign_resources(struct pci_bus *bus)
{ {
struct list_head *ln; struct list_head *ln;
...@@ -379,6 +381,7 @@ pbus_assign_resources(struct pci_bus *bus) ...@@ -379,6 +381,7 @@ pbus_assign_resources(struct pci_bus *bus)
pci_setup_bridge(b); pci_setup_bridge(b);
} }
} }
EXPORT_SYMBOL(pbus_assign_resources);
void __init void __init
pci_assign_unassigned_resources(void) pci_assign_unassigned_resources(void)
......
...@@ -557,8 +557,12 @@ struct pci_dev *pci_find_subsys (unsigned int vendor, unsigned int device, ...@@ -557,8 +557,12 @@ struct pci_dev *pci_find_subsys (unsigned int vendor, unsigned int device,
unsigned int ss_vendor, unsigned int ss_device, unsigned int ss_vendor, unsigned int ss_device,
const struct pci_dev *from); const struct pci_dev *from);
struct pci_dev *pci_find_class (unsigned int class, 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); 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_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_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); 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); ...@@ -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) */ /* 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); int pci_claim_resource(struct pci_dev *, int);
void pci_assign_unassigned_resources(void); void pci_assign_unassigned_resources(void);
void pdev_enable_device(struct pci_dev *); void pdev_enable_device(struct pci_dev *);
...@@ -634,6 +640,7 @@ struct pci_driver *pci_dev_driver(const 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); 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); 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); 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() */ /* kmem_cache style wrapper around pci_alloc_consistent() */
struct pci_pool *pci_pool_create (const char *name, struct pci_dev *dev, struct pci_pool *pci_pool_create (const char *name, struct pci_dev *dev,
......
...@@ -1101,6 +1101,9 @@ ...@@ -1101,6 +1101,9 @@
#define PCI_DEVICE_ID_EICON_MAESTRAQ_U 0xe013 #define PCI_DEVICE_ID_EICON_MAESTRAQ_U 0xe013
#define PCI_DEVICE_ID_EICON_MAESTRAP 0xe014 #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_VENDOR_ID_CYCLONE 0x113c
#define PCI_DEVICE_ID_CYCLONE_SDK 0x0001 #define PCI_DEVICE_ID_CYCLONE_SDK 0x0001
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment