Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
3c80c502
Commit
3c80c502
authored
Nov 11, 2004
by
Greg Kroah-Hartman
Browse files
Options
Browse Files
Download
Plain Diff
merge
parents
5c79e500
435883d2
Changes
46
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
46 changed files
with
1308 additions
and
333 deletions
+1308
-333
Documentation/kernel-parameters.txt
Documentation/kernel-parameters.txt
+4
-0
arch/i386/kernel/quirks.c
arch/i386/kernel/quirks.c
+2
-2
arch/i386/pci/acpi.c
arch/i386/pci/acpi.c
+22
-8
arch/i386/pci/changelog
arch/i386/pci/changelog
+0
-62
arch/i386/pci/common.c
arch/i386/pci/common.c
+4
-0
arch/i386/pci/fixup.c
arch/i386/pci/fixup.c
+129
-0
arch/i386/pci/irq.c
arch/i386/pci/irq.c
+6
-10
arch/i386/pci/mmconfig.c
arch/i386/pci/mmconfig.c
+1
-4
arch/ia64/pci/pci.c
arch/ia64/pci/pci.c
+26
-7
arch/x86_64/pci/mmconfig.c
arch/x86_64/pci/mmconfig.c
+0
-3
drivers/atm/idt77252.c
drivers/atm/idt77252.c
+2
-2
drivers/char/cyclades.c
drivers/char/cyclades.c
+1
-1
drivers/char/watchdog/scx200_wdt.c
drivers/char/watchdog/scx200_wdt.c
+6
-6
drivers/ide/ide.c
drivers/ide/ide.c
+6
-1
drivers/isdn/tpam/tpam_main.c
drivers/isdn/tpam/tpam_main.c
+2
-2
drivers/media/video/zr36120.c
drivers/media/video/zr36120.c
+1
-4
drivers/misc/ibmasm/module.c
drivers/misc/ibmasm/module.c
+3
-3
drivers/net/tulip/de4x5.c
drivers/net/tulip/de4x5.c
+2
-2
drivers/pci/Makefile
drivers/pci/Makefile
+7
-1
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/hotplug/acpiphp_glue.c
+2
-2
drivers/pci/hotplug/cpcihp_generic.c
drivers/pci/hotplug/cpcihp_generic.c
+2
-2
drivers/pci/hotplug/fakephp.c
drivers/pci/hotplug/fakephp.c
+1
-1
drivers/pci/hotplug/ibmphp_core.c
drivers/pci/hotplug/ibmphp_core.c
+6
-4
drivers/pci/hotplug/pciehp.h
drivers/pci/hotplug/pciehp.h
+17
-4
drivers/pci/hotplug/pciehp_core.c
drivers/pci/hotplug/pciehp_core.c
+10
-8
drivers/pci/hotplug/pciehp_ctrl.c
drivers/pci/hotplug/pciehp_ctrl.c
+247
-138
drivers/pci/hotplug/pciehp_hpc.c
drivers/pci/hotplug/pciehp_hpc.c
+24
-12
drivers/pci/hotplug/pciehp_pci.c
drivers/pci/hotplug/pciehp_pci.c
+8
-0
drivers/pci/hotplug/pciehprm_acpi.c
drivers/pci/hotplug/pciehprm_acpi.c
+37
-6
drivers/pci/hotplug/shpchp_ctrl.c
drivers/pci/hotplug/shpchp_ctrl.c
+34
-0
drivers/pci/hotplug/shpchp_hpc.c
drivers/pci/hotplug/shpchp_hpc.c
+1
-0
drivers/pci/pci-acpi.c
drivers/pci/pci-acpi.c
+209
-0
drivers/pci/pci-driver.c
drivers/pci/pci-driver.c
+6
-9
drivers/pci/pci-sysfs.c
drivers/pci/pci-sysfs.c
+119
-1
drivers/pci/pci.c
drivers/pci/pci.c
+12
-0
drivers/pci/pci.h
drivers/pci/pci.h
+4
-2
drivers/pci/probe.c
drivers/pci/probe.c
+4
-1
drivers/pci/quirks.c
drivers/pci/quirks.c
+11
-7
drivers/pci/remove.c
drivers/pci/remove.c
+2
-0
drivers/pci/rom.c
drivers/pci/rom.c
+225
-0
drivers/pci/setup-res.c
drivers/pci/setup-res.c
+1
-1
include/asm-generic/vmlinux.lds.h
include/asm-generic/vmlinux.lds.h
+3
-0
include/linux/ioport.h
include/linux/ioport.h
+5
-0
include/linux/pci-acpi.h
include/linux/pci-acpi.h
+61
-0
include/linux/pci.h
include/linux/pci.h
+26
-16
include/linux/pci_ids.h
include/linux/pci_ids.h
+7
-1
No files found.
Documentation/kernel-parameters.txt
View file @
3c80c502
...
...
@@ -931,6 +931,10 @@ running once the system is up.
enabled.
noacpi [IA-32] Do not use ACPI for IRQ routing
or for PCI scanning.
routeirq Do IRQ routing for all PCI devices.
This is normally done in pci_enable_device(),
so this option is a temporary workaround
for broken drivers that don't call it.
firmware [ARM] Do not re-enumerate the bus but
instead just use the configuration
...
...
arch/i386/kernel/quirks.c
View file @
3c80c502
...
...
@@ -6,7 +6,7 @@
#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP)
void
__init
quirk_intel_irqbalance
(
struct
pci_dev
*
dev
)
void
__
dev
init
quirk_intel_irqbalance
(
struct
pci_dev
*
dev
)
{
u8
config
,
rev
;
u32
word
;
...
...
@@ -45,5 +45,5 @@ void __init quirk_intel_irqbalance(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_FINAL
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_E7320_MCH
,
quirk_intel_irqbalance
);
DECLARE_PCI_FIXUP_FINAL
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_E7525_MCH
,
quirk_intel_irqbalance
);
DECLARE_PCI_FIXUP_FINAL
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_
S
MCH
,
quirk_intel_irqbalance
);
DECLARE_PCI_FIXUP_FINAL
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_
E7520_
MCH
,
quirk_intel_irqbalance
);
#endif
arch/i386/pci/acpi.c
View file @
3c80c502
...
...
@@ -15,6 +15,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
return
pcibios_scan_root
(
busnum
);
}
extern
int
pci_routeirq
;
static
int
__init
pci_acpi_init
(
void
)
{
struct
pci_dev
*
dev
=
NULL
;
...
...
@@ -30,14 +31,27 @@ static int __init pci_acpi_init(void)
pcibios_scanned
++
;
pcibios_enable_irq
=
acpi_pci_irq_enable
;
if
(
pci_routeirq
)
{
/*
* PCI IRQ routing is set up by pci_enable_device(), but we
* also do it here in case there are still broken drivers that
* don't use pci_enable_device().
*/
while
((
dev
=
pci_find_device
(
PCI_ANY_ID
,
PCI_ANY_ID
,
dev
))
!=
NULL
)
printk
(
KERN_INFO
"** Routing PCI interrupts for all devices because
\"
pci=routeirq
\"\n
"
);
printk
(
KERN_INFO
"** was specified. If this was required to make a driver work,
\n
"
);
printk
(
KERN_INFO
"** please email the output of
\"
lspci
\"
to bjorn.helgaas@hp.com
\n
"
);
printk
(
KERN_INFO
"** so I can fix the driver.
\n
"
);
while
((
dev
=
pci_get_device
(
PCI_ANY_ID
,
PCI_ANY_ID
,
dev
))
!=
NULL
)
acpi_pci_irq_enable
(
dev
);
}
else
{
printk
(
KERN_INFO
"** PCI interrupts are no longer routed automatically. If this
\n
"
);
printk
(
KERN_INFO
"** causes a device to stop working, it is probably because the
\n
"
);
printk
(
KERN_INFO
"** driver failed to call pci_enable_device(). As a temporary
\n
"
);
printk
(
KERN_INFO
"** workaround, the
\"
pci=routeirq
\"
argument restores the old
\n
"
);
printk
(
KERN_INFO
"** behavior. If this argument makes the device work again,
\n
"
);
printk
(
KERN_INFO
"** please email the output of
\"
lspci
\"
to bjorn.helgaas@hp.com
\n
"
);
printk
(
KERN_INFO
"** so I can fix the driver.
\n
"
);
}
#ifdef CONFIG_X86_IO_APIC
if
(
acpi_ioapic
)
print_IO_APIC
();
...
...
arch/i386/pci/changelog
deleted
100644 → 0
View file @
5c79e500
/*
* CHANGELOG :
* Jun 17, 1994 : Modified to accommodate the broken pre-PCI BIOS SPECIFICATION
* Revision 2.0 present on <thys@dennis.ee.up.ac.za>'s ASUS mainboard.
*
* Jan 5, 1995 : Modified to probe PCI hardware at boot time by Frederic
* Potter, potter@cao-vlsi.ibp.fr
*
* Jan 10, 1995 : Modified to store the information about configured pci
* devices into a list, which can be accessed via /proc/pci by
* Curtis Varner, cvarner@cs.ucr.edu
*
* Jan 12, 1995 : CPU-PCI bridge optimization support by Frederic Potter.
* Alpha version. Intel & UMC chipset support only.
*
* Apr 16, 1995 : Source merge with the DEC Alpha PCI support. Most of the code
* moved to drivers/pci/pci.c.
*
* Dec 7, 1996 : Added support for direct configuration access of boards
* with Intel compatible access schemes (tsbogend@alpha.franken.de)
*
* Feb 3, 1997 : Set internal functions to static, save/restore flags
* avoid dead locks reading broken PCI BIOS, werner@suse.de
*
* Apr 26, 1997 : Fixed case when there is BIOS32, but not PCI BIOS
* (mj@atrey.karlin.mff.cuni.cz)
*
* May 7, 1997 : Added some missing cli()'s. [mj]
*
* Jun 20, 1997 : Corrected problems in "conf1" type accesses.
* (paubert@iram.es)
*
* Aug 2, 1997 : Split to PCI BIOS handling and direct PCI access parts
* and cleaned it up... Martin Mares <mj@atrey.karlin.mff.cuni.cz>
*
* Feb 6, 1998 : No longer using BIOS to find devices and device classes. [mj]
*
* May 1, 1998 : Support for peer host bridges. [mj]
*
* Jun 19, 1998 : Changed to use spinlocks, so that PCI configuration space
* can be accessed from interrupts even on SMP systems. [mj]
*
* August 1998 : Better support for peer host bridges and more paranoid
* checks for direct hardware access. Ugh, this file starts to look as
* a large gallery of common hardware bug workarounds (watch the comments)
* -- the PCI specs themselves are sane, but most implementors should be
* hit hard with \hammer scaled \magstep5. [mj]
*
* Jan 23, 1999 : More improvements to peer host bridge logic. i450NX fixup. [mj]
*
* Feb 8, 1999 : Added UM8886BF I/O address fixup. [mj]
*
* August 1999 : New resource management and configuration access stuff. [mj]
*
* Sep 19, 1999 : Use PCI IRQ routing tables for detection of peer host bridges.
* Based on ideas by Chris Frantz and David Hinds. [mj]
*
* Sep 28, 1999 : Handle unreported/unassigned IRQs. Thanks to Shuu Yamaguchi
* for a lot of patience during testing. [mj]
*
* Oct 8, 1999 : Split to pci-i386.c, pci-pc.c and pci-visws.c. [mj]
*/
\ No newline at end of file
arch/i386/pci/common.c
View file @
3c80c502
...
...
@@ -23,6 +23,7 @@ extern void pcibios_sort(void);
unsigned
int
pci_probe
=
PCI_PROBE_BIOS
|
PCI_PROBE_CONF1
|
PCI_PROBE_CONF2
|
PCI_PROBE_MMCONF
;
int
pci_routeirq
;
int
pcibios_last_bus
=
-
1
;
struct
pci_bus
*
pci_root_bus
=
NULL
;
struct
pci_raw_ops
*
raw_pci_ops
;
...
...
@@ -227,6 +228,9 @@ char * __devinit pcibios_setup(char *str)
}
else
if
(
!
strcmp
(
str
,
"assign-busses"
))
{
pci_probe
|=
PCI_ASSIGN_ALL_BUSSES
;
return
NULL
;
}
else
if
(
!
strcmp
(
str
,
"routeirq"
))
{
pci_routeirq
=
1
;
return
NULL
;
}
return
str
;
}
...
...
arch/i386/pci/fixup.c
View file @
3c80c502
...
...
@@ -255,3 +255,132 @@ static void __init pci_fixup_nforce2(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_HEADER
(
PCI_VENDOR_ID_NVIDIA
,
PCI_DEVICE_ID_NVIDIA_NFORCE2
,
pci_fixup_nforce2
);
/* Max PCI Express root ports */
#define MAX_PCIEROOT 6
static
int
quirk_aspm_offset
[
MAX_PCIEROOT
<<
3
];
#define GET_INDEX(a, b) (((a - PCI_DEVICE_ID_INTEL_MCH_PA) << 3) + b)
static
int
quirk_pcie_aspm_read
(
struct
pci_bus
*
bus
,
unsigned
int
devfn
,
int
where
,
int
size
,
u32
*
value
)
{
return
raw_pci_ops
->
read
(
0
,
bus
->
number
,
devfn
,
where
,
size
,
value
);
}
/*
* Replace the original pci bus ops for write with a new one that will filter
* the request to insure ASPM cannot be enabled.
*/
static
int
quirk_pcie_aspm_write
(
struct
pci_bus
*
bus
,
unsigned
int
devfn
,
int
where
,
int
size
,
u32
value
)
{
u8
offset
;
offset
=
quirk_aspm_offset
[
GET_INDEX
(
bus
->
self
->
device
,
devfn
)];
if
((
offset
)
&&
(
where
==
offset
))
value
=
value
&
0xfffffffc
;
return
raw_pci_ops
->
write
(
0
,
bus
->
number
,
devfn
,
where
,
size
,
value
);
}
struct
pci_ops
quirk_pcie_aspm_ops
=
{
.
read
=
quirk_pcie_aspm_read
,
.
write
=
quirk_pcie_aspm_write
,
};
/*
* Prevents PCI Express ASPM (Active State Power Management) being enabled.
*
* Save the register offset, where the ASPM control bits are located,
* for each PCI Express device that is in the device list of
* the root port in an array for fast indexing. Replace the bus ops
* with the modified one.
*/
void
pcie_rootport_aspm_quirk
(
struct
pci_dev
*
pdev
)
{
int
cap_base
,
i
;
struct
pci_bus
*
pbus
;
struct
pci_dev
*
dev
;
if
((
pbus
=
pdev
->
subordinate
)
==
NULL
)
return
;
/*
* Check if the DID of pdev matches one of the six root ports. This
* check is needed in the case this function is called directly by the
* hot-plug driver.
*/
if
((
pdev
->
device
<
PCI_DEVICE_ID_INTEL_MCH_PA
)
||
(
pdev
->
device
>
PCI_DEVICE_ID_INTEL_MCH_PC1
))
return
;
if
(
list_empty
(
&
pbus
->
devices
))
{
/*
* If no device is attached to the root port at power-up or
* after hot-remove, the pbus->devices is empty and this code
* will set the offsets to zero and the bus ops to parent's bus
* ops, which is unmodified.
*/
for
(
i
=
GET_INDEX
(
pdev
->
device
,
0
);
i
<=
GET_INDEX
(
pdev
->
device
,
7
);
++
i
)
quirk_aspm_offset
[
i
]
=
0
;
pbus
->
ops
=
pbus
->
parent
->
ops
;
}
else
{
/*
* If devices are attached to the root port at power-up or
* after hot-add, the code loops through the device list of
* each root port to save the register offsets and replace the
* bus ops.
*/
list_for_each_entry
(
dev
,
&
pbus
->
devices
,
bus_list
)
{
/* There are 0 to 8 devices attached to this bus */
cap_base
=
pci_find_capability
(
dev
,
PCI_CAP_ID_EXP
);
quirk_aspm_offset
[
GET_INDEX
(
pdev
->
device
,
dev
->
devfn
)]
=
cap_base
+
0x10
;
}
pbus
->
ops
=
&
quirk_pcie_aspm_ops
;
}
}
DECLARE_PCI_FIXUP_FINAL
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_MCH_PA
,
pcie_rootport_aspm_quirk
);
DECLARE_PCI_FIXUP_FINAL
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_MCH_PA1
,
pcie_rootport_aspm_quirk
);
DECLARE_PCI_FIXUP_FINAL
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_MCH_PB
,
pcie_rootport_aspm_quirk
);
DECLARE_PCI_FIXUP_FINAL
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_MCH_PB1
,
pcie_rootport_aspm_quirk
);
DECLARE_PCI_FIXUP_FINAL
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_MCH_PC
,
pcie_rootport_aspm_quirk
);
DECLARE_PCI_FIXUP_FINAL
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_MCH_PC1
,
pcie_rootport_aspm_quirk
);
/*
* Fixup to mark boot BIOS video selected by BIOS before it changes
*
* From information provided by "Jon Smirl" <jonsmirl@yahoo.com>
*
* The standard boot ROM sequence for an x86 machine uses the BIOS
* to select an initial video card for boot display. This boot video
* card will have it's BIOS copied to C0000 in system RAM.
* IORESOURCE_ROM_SHADOW is used to associate the boot video
* card with this copy. On laptops this copy has to be used since
* the main ROM may be compressed or combined with another image.
* See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW
* is marked here since the boot video device will be the only enabled
* video device at this point.
*
*/
static
void
__devinit
pci_fixup_video
(
struct
pci_dev
*
pdev
)
{
struct
pci_dev
*
bridge
;
struct
pci_bus
*
bus
;
u16
l
;
if
((
pdev
->
class
>>
8
)
!=
PCI_CLASS_DISPLAY_VGA
)
return
;
/* Is VGA routed to us? */
bus
=
pdev
->
bus
;
while
(
bus
)
{
bridge
=
bus
->
self
;
if
(
bridge
)
{
pci_read_config_word
(
bridge
,
PCI_BRIDGE_CONTROL
,
&
l
);
if
(
!
(
l
&
PCI_BRIDGE_CTL_VGA
))
return
;
}
bus
=
bus
->
parent
;
}
pdev
->
resource
[
PCI_ROM_RESOURCE
].
flags
|=
IORESOURCE_ROM_SHADOW
;
}
DECLARE_PCI_FIXUP_HEADER
(
PCI_ANY_ID
,
PCI_ANY_ID
,
pci_fixup_video
);
arch/i386/pci/irq.c
View file @
3c80c502
...
...
@@ -460,21 +460,17 @@ static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq,
#endif
static
__init
int
intel_router_probe
(
struct
irq_router
*
r
,
struct
pci_dev
*
router
,
u16
device
)
{
struct
pci_dev
*
dev1
,
*
dev2
;
static
struct
pci_device_id
pirq_440gx
[]
=
{
{
PCI_DEVICE
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_82443GX_0
)
},
{
PCI_DEVICE
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_82443GX_2
)
},
{
},
};
/* 440GX has a proprietary PIRQ router -- don't use it */
dev1
=
pci_get_device
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_82443GX_0
,
NULL
);
dev2
=
pci_get_device
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_82443GX_2
,
NULL
);
if
((
dev1
!=
NULL
)
||
(
dev2
!=
NULL
))
{
pci_dev_put
(
dev1
);
pci_dev_put
(
dev2
);
if
(
pci_dev_present
(
pirq_440gx
))
return
0
;
}
switch
(
device
)
{
...
...
arch/i386/pci/mmconfig.c
View file @
3c80c502
...
...
@@ -30,7 +30,7 @@ static inline void pci_exp_set_dev_base(int bus, int devfn)
u32
dev_base
=
pci_mmcfg_base_addr
|
(
bus
<<
20
)
|
(
devfn
<<
12
);
if
(
dev_base
!=
mmcfg_last_accessed_device
)
{
mmcfg_last_accessed_device
=
dev_base
;
set_fixmap
(
FIX_PCIE_MCFG
,
dev_base
);
set_fixmap
_nocache
(
FIX_PCIE_MCFG
,
dev_base
);
}
}
...
...
@@ -85,9 +85,6 @@ static int pci_mmcfg_write(int seg, int bus, int devfn, int reg, int len, u32 va
break
;
}
/* Dummy read to flush PCI write */
readl
(
mmcfg_virt_addr
);
spin_unlock_irqrestore
(
&
pci_config_lock
,
flags
);
return
0
;
...
...
arch/ia64/pci/pci.c
View file @
3c80c502
...
...
@@ -46,6 +46,8 @@
#define DBG(x...)
#endif
static
int
pci_routeirq
;
/*
* Low-level SAL-based PCI configuration access functions. Note that SAL
* calls are already serialized (via sal_lock), so we don't need another
...
...
@@ -141,13 +143,28 @@ extern acpi_status acpi_map_iosapic (acpi_handle, u32, void*, void**);
acpi_get_devices
(
NULL
,
acpi_map_iosapic
,
NULL
,
NULL
);
#endif
if
(
pci_routeirq
)
{
/*
* PCI IRQ routing is set up by pci_enable_device(), but we
* also do it here in case there are still broken drivers that
* don't use pci_enable_device().
*/
printk
(
KERN_INFO
"** Routing PCI interrupts for all devices because
\"
pci=routeirq
\"\n
"
);
printk
(
KERN_INFO
"** was specified. If this was required to make a driver work,
\n
"
);
printk
(
KERN_INFO
"** please email the output of
\"
lspci
\"
to bjorn.helgaas@hp.com
\n
"
);
printk
(
KERN_INFO
"** so I can fix the driver.
\n
"
);
while
((
dev
=
pci_find_device
(
PCI_ANY_ID
,
PCI_ANY_ID
,
dev
))
!=
NULL
)
acpi_pci_irq_enable
(
dev
);
}
else
{
printk
(
KERN_INFO
"** PCI interrupts are no longer routed automatically. If this
\n
"
);
printk
(
KERN_INFO
"** causes a device to stop working, it is probably because the
\n
"
);
printk
(
KERN_INFO
"** driver failed to call pci_enable_device(). As a temporary
\n
"
);
printk
(
KERN_INFO
"** workaround, the
\"
pci=routeirq
\"
argument restores the old
\n
"
);
printk
(
KERN_INFO
"** behavior. If this argument makes the device work again,
\n
"
);
printk
(
KERN_INFO
"** please email the output of
\"
lspci
\"
to bjorn.helgaas@hp.com
\n
"
);
printk
(
KERN_INFO
"** so I can fix the driver.
\n
"
);
}
return
0
;
}
...
...
@@ -475,6 +492,8 @@ pcibios_align_resource (void *data, struct resource *res,
char
*
__init
pcibios_setup
(
char
*
str
)
{
if
(
!
strcmp
(
str
,
"routeirq"
))
pci_routeirq
=
1
;
return
NULL
;
}
...
...
arch/x86_64/pci/mmconfig.c
View file @
3c80c502
...
...
@@ -63,9 +63,6 @@ static int pci_mmcfg_write(int seg, int bus, int devfn, int reg, int len, u32 va
break
;
}
/* Dummy read to flush PCI write */
readl
(
addr
);
return
0
;
}
...
...
drivers/atm/idt77252.c
View file @
3c80c502
...
...
@@ -3685,9 +3685,9 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
int
i
,
err
;
if
(
pci_enable_device
(
pcidev
))
{
if
(
(
err
=
pci_enable_device
(
pcidev
)
))
{
printk
(
"idt77252: can't enable PCI device at %s
\n
"
,
pci_name
(
pcidev
));
return
-
ENODEV
;
return
err
;
}
if
(
pci_read_config_word
(
pcidev
,
PCI_REVISION_ID
,
&
revision
))
{
...
...
drivers/char/cyclades.c
View file @
3c80c502
...
...
@@ -4725,7 +4725,7 @@ cy_detect_pci(void)
for
(
i
=
0
;
i
<
NR_CARDS
;
i
++
)
{
/* look for a Cyclades card by vendor and device id */
while
((
device_id
=
cy_pci_dev_id
[
dev_index
])
!=
0
)
{
if
((
pdev
=
pci_
find
_device
(
PCI_VENDOR_ID_CYCLADES
,
if
((
pdev
=
pci_
get
_device
(
PCI_VENDOR_ID_CYCLADES
,
device_id
,
pdev
))
==
NULL
)
{
dev_index
++
;
/* try next device id */
}
else
{
...
...
drivers/char/watchdog/scx200_wdt.c
View file @
3c80c502
...
...
@@ -217,6 +217,11 @@ static struct miscdevice scx200_wdt_miscdev = {
static
int
__init
scx200_wdt_init
(
void
)
{
int
r
;
static
struct
pci_device_id
ns_sc
[]
=
{
{
PCI_DEVICE
(
PCI_VENDOR_ID_NS
,
PCI_DEVICE_ID_NS_SCx200_BRIDGE
)
},
{
PCI_DEVICE
(
PCI_VENDOR_ID_NS
,
PCI_DEVICE_ID_NS_SC1100_BRIDGE
)
},
{
},
};
printk
(
KERN_DEBUG
NAME
": NatSemi SCx200 Watchdog Driver
\n
"
);
...
...
@@ -224,12 +229,7 @@ static int __init scx200_wdt_init(void)
* First check that this really is a NatSemi SCx200 CPU or a Geode
* SC1100 processor
*/
if
((
pci_find_device
(
PCI_VENDOR_ID_NS
,
PCI_DEVICE_ID_NS_SCx200_BRIDGE
,
NULL
))
==
NULL
&&
(
pci_find_device
(
PCI_VENDOR_ID_NS
,
PCI_DEVICE_ID_NS_SC1100_BRIDGE
,
NULL
))
==
NULL
)
if
(
!
pci_dev_present
(
ns_sc
))
return
-
ENODEV
;
/* More sanity checks, verify that the configuration block is there */
...
...
drivers/ide/ide.c
View file @
3c80c502
...
...
@@ -335,11 +335,16 @@ static void __init init_ide_data (void)
int
ide_system_bus_speed
(
void
)
{
static
struct
pci_device_id
pci_default
[]
=
{
{
PCI_DEVICE
(
PCI_ANY_ID
,
PCI_ANY_ID
)
},
{
}
};
if
(
!
system_bus_speed
)
{
if
(
idebus_parameter
)
{
/* user supplied value */
system_bus_speed
=
idebus_parameter
;
}
else
if
(
pci_
find_device
(
PCI_ANY_ID
,
PCI_ANY_ID
,
NULL
)
!=
NULL
)
{
}
else
if
(
pci_
dev_present
(
pci_default
)
)
{
/* safe default value for PCI */
system_bus_speed
=
33
;
}
else
{
...
...
drivers/isdn/tpam/tpam_main.c
View file @
3c80c502
...
...
@@ -88,10 +88,10 @@ static int __devinit tpam_probe(struct pci_dev *dev, const struct pci_device_id
tpam_card
*
card
,
*
c
;
int
i
,
err
;
if
(
pci_enable_device
(
dev
))
{
if
(
(
err
=
pci_enable_device
(
dev
)
))
{
printk
(
KERN_ERR
"TurboPAM: can't enable PCI device at %s
\n
"
,
pci_name
(
dev
));
return
-
ENODEV
;
return
err
;
}
/* allocate memory for the board structure */
...
...
drivers/media/video/zr36120.c
View file @
3c80c502
...
...
@@ -145,14 +145,11 @@ static struct { const char name[8]; uint mode; uint bpp; } palette2fmt[] = {
static
void
__init
handle_chipset
(
void
)
{
struct
pci_dev
*
dev
=
NULL
;
/* Just in case some nut set this to something dangerous */
if
(
triton1
)
triton1
=
ZORAN_VDC_TRICOM
;
while
((
dev
=
pci_find_device
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_82437
,
dev
)))
{
if
(
pci_pci_problems
&
PCIPCI_TRITON
)
{
printk
(
KERN_INFO
"zoran: Host bridge 82437FX Triton PIIX
\n
"
);
triton1
=
ZORAN_VDC_TRICOM
;
}
...
...
drivers/misc/ibmasm/module.c
View file @
3c80c502
...
...
@@ -59,13 +59,13 @@
static
int
__init
ibmasm_init_one
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
id
)
{
int
result
=
-
ENOMEM
;
int
err
,
result
=
-
ENOMEM
;
struct
service_processor
*
sp
;
if
(
pci_enable_device
(
pdev
))
{
if
(
(
err
=
pci_enable_device
(
pdev
)
))
{
printk
(
KERN_ERR
"%s: can't enable PCI device at %s
\n
"
,
DRIVER_NAME
,
pci_name
(
pdev
));
return
-
ENODEV
;
return
err
;
}
sp
=
kmalloc
(
sizeof
(
struct
service_processor
),
GFP_KERNEL
);
...
...
drivers/net/tulip/de4x5.c
View file @
3c80c502
...
...
@@ -2242,8 +2242,8 @@ static int __devinit de4x5_pci_probe (struct pci_dev *pdev,
return
-
ENODEV
;
/* Ok, the device seems to be for us. */
if
(
pci_enable_device
(
pdev
))
return
-
ENODEV
;
if
(
(
error
=
pci_enable_device
(
pdev
)
))
return
error
;
if
(
!
(
dev
=
alloc_etherdev
(
sizeof
(
struct
de4x5_private
))))
{
error
=
-
ENOMEM
;
...
...
drivers/pci/Makefile
View file @
3c80c502
...
...
@@ -3,7 +3,8 @@
#
obj-y
+=
access.o bus.o probe.o remove.o pci.o quirks.o
\
names.o pci-driver.o search.o pci-sysfs.o
names.o pci-driver.o search.o pci-sysfs.o
\
rom.o
obj-$(CONFIG_PROC_FS)
+=
proc.o
ifndef
CONFIG_SPARC64
...
...
@@ -28,6 +29,11 @@ obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o
obj-$(CONFIG_X86_VISWS)
+=
setup-irq.o
obj-$(CONFIG_PCI_MSI)
+=
msi.o
#
# ACPI Related PCI FW Functions
#
obj-$(CONFIG_ACPI)
+=
pci-acpi.o
# Cardbus & CompactPCI use setup-bus
obj-$(CONFIG_HOTPLUG)
+=
setup-bus.o
...
...
drivers/pci/hotplug/acpiphp_glue.c
View file @
3c80c502
...
...
@@ -389,7 +389,7 @@ static void add_host_bridge(acpi_handle *handle, int seg, int bus)
bridge
->
pci_bus
=
pci_find_bus
(
seg
,
bus
);
bridge
->
res_lock
=
SPIN_LOCK_UNLOCKED
;
spin_lock_init
(
&
bridge
->
res_lock
)
;
/* to be overridden when we decode _CRS */
bridge
->
sub
=
bridge
->
bus
;
...
...
@@ -457,7 +457,7 @@ static void add_p2p_bridge(acpi_handle *handle, int seg, int bus, int dev, int f
return
;
}
bridge
->
res_lock
=
SPIN_LOCK_UNLOCKED
;
spin_lock_init
(
&
bridge
->
res_lock
)
;
bridge
->
bus
=
bridge
->
pci_bus
->
number
;
bridge
->
sub
=
bridge
->
pci_bus
->
subordinate
;
...
...
drivers/pci/hotplug/cpcihp_generic.c
View file @
3c80c502
...
...
@@ -63,7 +63,7 @@
/* local variables */
static
int
debug
;
static
char
*
bridge
;
static
char
bridge
[
256
]
;
static
u8
bridge_busnr
;
static
u8
bridge_slot
;
static
struct
pci_bus
*
bus
;
...
...
@@ -209,7 +209,7 @@ module_exit(cpcihp_generic_exit);
MODULE_AUTHOR
(
DRIVER_AUTHOR
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
module_param
(
debug
,
bool
,
0644
);
module_param
(
debug
,
bool
,
S_IRUGO
|
S_IWUSR
);
MODULE_PARM_DESC
(
debug
,
"Debugging mode enabled or not"
);
module_param
(
bridge
,
charp
,
0
);
MODULE_PARM_DESC
(
bridge
,
"Hotswap bus bridge device, <bus>:<slot> (bus and slot are in hexadecimal)"
);
...
...
drivers/pci/hotplug/fakephp.c
View file @
3c80c502
...
...
@@ -227,6 +227,6 @@ module_exit(dummyphp_exit);
MODULE_AUTHOR
(
DRIVER_AUTHOR
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
module_param
(
debug
,
bool
,
0644
);
module_param
(
debug
,
bool
,
S_IRUGO
|
S_IWUSR
);
MODULE_PARM_DESC
(
debug
,
"Debugging mode enabled or not"
);
drivers/pci/hotplug/ibmphp_core.c
View file @
3c80c502
...
...
@@ -51,7 +51,7 @@
int
ibmphp_debug
;
static
int
debug
;
module_param
(
debug
,
bool
,
0644
);
module_param
(
debug
,
bool
,
S_IRUGO
|
S_IWUSR
);
MODULE_PARM_DESC
(
debug
,
"Debugging mode enabled or not"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
...
...
@@ -838,8 +838,11 @@ static int set_bus (struct slot * slot_cur)
int
rc
;
u8
speed
;
u8
cmd
=
0x0
;
struct
pci_dev
*
dev
=
NULL
;
int
retval
;
static
struct
pci_device_id
ciobx
[]
=
{
{
PCI_DEVICE
(
PCI_VENDOR_ID_SERVERWORKS
,
0x0101
)
},
{
},
};
debug
(
"%s - entry slot # %d
\n
"
,
__FUNCTION__
,
slot_cur
->
number
);
if
(
SET_BUS_STATUS
(
slot_cur
->
ctrl
)
&&
is_bus_empty
(
slot_cur
))
{
...
...
@@ -886,8 +889,7 @@ static int set_bus (struct slot * slot_cur)
break
;
case
BUS_SPEED_133
:
/* This is to take care of the bug in CIOBX chip */
while
((
dev
=
pci_get_device
(
PCI_VENDOR_ID_SERVERWORKS
,
0x0101
,
dev
))
!=
NULL
)
if
(
pci_dev_present
(
ciobx
))
ibmphp_hpc_writeslot
(
slot_cur
,
HPC_BUS_100PCIXMODE
);
cmd
=
HPC_BUS_133PCIXMODE
;
break
;
...
...
drivers/pci/hotplug/pciehp.h
View file @
3c80c502
...
...
@@ -127,8 +127,7 @@ struct controller {
enum
pci_bus_speed
speed
;
u32
first_slot
;
/* First physical slot number */
/* PCIE only has 1 slot */
u8
slot_bus
;
/* Bus where the slots handled by this controller sit */
u8
push_flag
;
u16
ctlrcap
;
u8
ctrlcap
;
u16
vendor_id
;
};
...
...
@@ -180,6 +179,21 @@ struct resource_lists {
#define DISABLE_CARD 1
/* Field definitions in Slot Capabilities Register */
#define ATTN_BUTTN_PRSN 0x00000001
#define PWR_CTRL_PRSN 0x00000002
#define MRL_SENS_PRSN 0x00000004
#define ATTN_LED_PRSN 0x00000008
#define PWR_LED_PRSN 0x00000010
#define HP_SUPR_RM_SUP 0x00000020
#define ATTN_BUTTN(cap) (cap & ATTN_BUTTN_PRSN)
#define POWER_CTRL(cap) (cap & PWR_CTRL_PRSN)
#define MRL_SENS(cap) (cap & MRL_SENS_PRSN)
#define ATTN_LED(cap) (cap & ATTN_LED_PRSN)
#define PWR_LED(cap) (cap & PWR_LED_PRSN)
#define HP_SUPR_RM(cap) (cap & HP_SUPR_RM_SUP)
/*
* error Messages
*/
...
...
@@ -312,8 +326,7 @@ int pcie_get_ctlr_slot_config(struct controller *ctrl,
int
*
num_ctlr_slots
,
int
*
first_device_num
,
int
*
physical_slot_num
,
int
*
updown
,
int
*
flags
);
u8
*
ctrlcap
);
struct
hpc_ops
{
int
(
*
power_on_slot
)
(
struct
slot
*
slot
);
...
...
drivers/pci/hotplug/pciehp_core.c
View file @
3c80c502
...
...
@@ -204,11 +204,10 @@ static int get_ctlr_slot_config(struct controller *ctrl)
int
num_ctlr_slots
;
/* Not needed; PCI Express has 1 slot per port*/
int
first_device_num
;
/* Not needed */
int
physical_slot_num
;
int
updown
;
/* Not needed */
u8
ctrlcap
;
int
rc
;
int
flags
;
/* Not needed */
rc
=
pcie_get_ctlr_slot_config
(
ctrl
,
&
num_ctlr_slots
,
&
first_device_num
,
&
physical_slot_num
,
&
updown
,
&
flags
);
rc
=
pcie_get_ctlr_slot_config
(
ctrl
,
&
num_ctlr_slots
,
&
first_device_num
,
&
physical_slot_num
,
&
ctrlcap
);
if
(
rc
)
{
err
(
"%s: get_ctlr_slot_config fail for b:d (%x:%x)
\n
"
,
__FUNCTION__
,
ctrl
->
bus
,
ctrl
->
device
);
return
(
-
1
);
...
...
@@ -217,10 +216,10 @@ static int get_ctlr_slot_config(struct controller *ctrl)
ctrl
->
num_slots
=
num_ctlr_slots
;
/* PCI Express has 1 slot per port */
ctrl
->
slot_device_offset
=
first_device_num
;
ctrl
->
first_slot
=
physical_slot_num
;
ctrl
->
slot_num_inc
=
updown
;
/* Not needed */
/* either -1 or 1 */
ctrl
->
ctrlcap
=
ctrlcap
;
dbg
(
"%s: bus(0x%x) num_slot(0x%x) 1st_dev(0x%x) psn(0x%x)
updown(%d
) for b:d (%x:%x)
\n
"
,
__FUNCTION__
,
ctrl
->
slot_bus
,
num_ctlr_slots
,
first_device_num
,
physical_slot_num
,
updown
,
dbg
(
"%s: bus(0x%x) num_slot(0x%x) 1st_dev(0x%x) psn(0x%x)
ctrlcap(%x
) for b:d (%x:%x)
\n
"
,
__FUNCTION__
,
ctrl
->
slot_bus
,
num_ctlr_slots
,
first_device_num
,
physical_slot_num
,
ctrlcap
,
ctrl
->
bus
,
ctrl
->
device
);
return
(
0
);
...
...
@@ -237,6 +236,8 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
dbg
(
"%s - physical_slot = %s
\n
"
,
__FUNCTION__
,
hotplug_slot
->
name
);
hotplug_slot
->
info
->
attention_status
=
status
;
if
(
ATTN_LED
(
slot
->
ctrl
->
ctrlcap
))
slot
->
hpc_ops
->
set_attention_status
(
slot
,
status
);
return
0
;
...
...
@@ -451,7 +452,8 @@ static int pcie_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
t_slot
->
hpc_ops
->
get_adapter_status
(
t_slot
,
&
value
);
/* Check if slot is occupied */
dbg
(
"%s: adpater value %x
\n
"
,
__FUNCTION__
,
value
);
if
(
!
value
)
{
if
((
POWER_CTRL
(
ctrl
->
ctrlcap
))
&&
!
value
)
{
rc
=
t_slot
->
hpc_ops
->
power_off_slot
(
t_slot
);
/* Power off slot if not occupied*/
if
(
rc
)
{
/* Done with exclusive hardware access */
...
...
drivers/pci/hotplug/pciehp_ctrl.c
View file @
3c80c502
This diff is collapsed.
Click to expand it.
drivers/pci/hotplug/pciehp_hpc.c
View file @
3c80c502
...
...
@@ -182,7 +182,7 @@ static int pcie_cap_base = 0; /* Base of the PCI Express capability item struct
#define MRL_SENS_PRSN 0x00000004
#define ATTN_LED_PRSN 0x00000008
#define PWR_LED_PRSN 0x00000010
#define HP_SUPR_RM 0x00000020
#define HP_SUPR_RM
_SUP
0x00000020
#define HP_CAP 0x00000040
#define SLOT_PWR_VALUE 0x000003F8
#define SLOT_PWR_LIMIT 0x00000C00
...
...
@@ -237,8 +237,8 @@ struct php_ctlr_state_s {
static
spinlock_t
hpc_event_lock
;
DEFINE_DBG_BUFFER
/* Debug string buffer for entire HPC defined here */
static
struct
php_ctlr_state_s
*
php_ctlr_list_head
;
/* HPC state linked list */
static
int
ctlr_seq_num
;
/* Controller sequence # */
static
struct
php_ctlr_state_s
*
php_ctlr_list_head
=
0
;
/* HPC state linked list */
static
int
ctlr_seq_num
=
0
;
/* Controller sequence # */
static
spinlock_t
list_lock
;
static
irqreturn_t
pcie_isr
(
int
IRQ
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
...
...
@@ -691,8 +691,7 @@ int pcie_get_ctlr_slot_config(struct controller *ctrl,
int
*
num_ctlr_slots
,
/* number of slots in this HPC; only 1 in PCIE */
int
*
first_device_num
,
/* PCI dev num of the first slot in this PCIE */
int
*
physical_slot_num
,
/* phy slot num of the first slot in this PCIE */
int
*
updown
,
/* physical_slot_num increament: 1 or -1 */
int
*
flags
)
u8
*
ctrlcap
)
{
struct
php_ctlr_state_s
*
php_ctlr
=
ctrl
->
hpc_ctlr_handle
;
u32
slot_cap
;
...
...
@@ -716,8 +715,9 @@ int pcie_get_ctlr_slot_config(struct controller *ctrl,
}
*
physical_slot_num
=
slot_cap
>>
19
;
dbg
(
"%s: PSN %d
\n
"
,
__FUNCTION__
,
*
physical_slot_num
);
*
updown
=
-
1
;
*
ctrlcap
=
slot_cap
&
0x0000007f
;
DBG_LEAVE_ROUTINE
return
0
;
...
...
@@ -741,6 +741,8 @@ static void hpc_release_ctlr(struct controller *ctrl)
if
(
php_ctlr
->
irq
)
{
free_irq
(
php_ctlr
->
irq
,
ctrl
);
php_ctlr
->
irq
=
0
;
if
(
!
pcie_mch_quirk
)
pci_disable_msi
(
php_ctlr
->
pci_dev
);
}
}
if
(
php_ctlr
->
pci_dev
)
...
...
@@ -1259,7 +1261,7 @@ int pcie_init(struct controller * ctrl,
static
int
first
=
1
;
u16
temp_word
;
u16
cap_reg
;
u16
intr_enable
;
u16
intr_enable
=
0
;
u32
slot_cap
;
int
cap_base
,
saved_cap_base
;
u16
slot_status
,
slot_ctrl
;
...
...
@@ -1402,8 +1404,8 @@ int pcie_init(struct controller * ctrl,
start_int_poll_timer
(
php_ctlr
,
10
);
/* start with 10 second delay */
}
else
{
/* Installs the interrupt handler */
dbg
(
"%s: pcie
hp_msi_quirk = %x
\n
"
,
__FUNCTION__
,
pciehp_msi
_quirk
);
if
(
!
pcie
hp_msi
_quirk
)
{
dbg
(
"%s: pcie
_mch_quirk = %x
\n
"
,
__FUNCTION__
,
pcie_mch
_quirk
);
if
(
!
pcie
_mch
_quirk
)
{
rc
=
pci_enable_msi
(
pdev
);
if
(
rc
)
{
info
(
"Can't get msi for the hotplug controller
\n
"
);
...
...
@@ -1412,6 +1414,7 @@ int pcie_init(struct controller * ctrl,
}
else
php_ctlr
->
irq
=
pdev
->
irq
;
}
rc
=
request_irq
(
php_ctlr
->
irq
,
pcie_isr
,
SA_SHIRQ
,
MY_NAME
,
(
void
*
)
ctrl
);
dbg
(
"%s: request_irq %d for hpc%d (returns %d)
\n
"
,
__FUNCTION__
,
php_ctlr
->
irq
,
ctlr_seq_num
,
rc
);
if
(
rc
)
{
...
...
@@ -1426,9 +1429,18 @@ int pcie_init(struct controller * ctrl,
goto
abort_free_ctlr
;
}
dbg
(
"%s: SLOT_CTRL %x value read %x
\n
"
,
__FUNCTION__
,
SLOT_CTRL
,
temp_word
);
dbg
(
"%s: slot_cap %x
\n
"
,
__FUNCTION__
,
slot_cap
);
intr_enable
=
intr_enable
|
PRSN_DETECT_ENABLE
;
if
(
ATTN_BUTTN
(
slot_cap
))
intr_enable
=
intr_enable
|
ATTN_BUTTN_ENABLE
;
if
(
POWER_CTRL
(
slot_cap
))
intr_enable
=
intr_enable
|
PWR_FAULT_DETECT_ENABLE
;
i
ntr_enable
=
ATTN_BUTTN_ENABLE
|
PWR_FAULT_DETECT_ENABLE
|
MRL_DETECT_ENABLE
|
PRSN
_DETECT_ENABLE
;
i
f
(
MRL_SENS
(
slot_cap
))
intr_enable
=
intr_enable
|
MRL
_DETECT_ENABLE
;
temp_word
=
(
temp_word
&
~
intr_enable
)
|
intr_enable
;
...
...
drivers/pci/hotplug/pciehp_pci.c
View file @
3c80c502
...
...
@@ -82,9 +82,11 @@ int pciehp_unconfigure_device(struct pci_func* func)
{
int
rc
=
0
;
int
j
;
struct
pci_bus
*
pbus
;
dbg
(
"%s: bus/dev/func = %x/%x/%x
\n
"
,
__FUNCTION__
,
func
->
bus
,
func
->
device
,
func
->
function
);
pbus
=
func
->
pci_dev
->
bus
;
for
(
j
=
0
;
j
<
8
;
j
++
)
{
struct
pci_dev
*
temp
=
pci_find_slot
(
func
->
bus
,
...
...
@@ -93,6 +95,12 @@ int pciehp_unconfigure_device(struct pci_func* func)
pci_remove_bus_device
(
temp
);
}
}
/*
* Some PCI Express root ports require fixup after hot-plug operation.
*/
if
(
pcie_mch_quirk
)
pci_fixup_device
(
pci_fixup_final
,
pbus
->
self
);
return
rc
;
}
...
...
drivers/pci/hotplug/pciehprm_acpi.c
View file @
3c80c502
...
...
@@ -32,6 +32,7 @@
#include <linux/init.h>
#include <linux/acpi.h>
#include <linux/efi.h>
#include <linux/pci-acpi.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#ifdef CONFIG_IA64
...
...
@@ -50,6 +51,14 @@
#define METHOD_NAME__HPP "_HPP"
#define METHOD_NAME_OSHP "OSHP"
/* Status code for running acpi method to gain native control */
#define NC_NOT_RUN 0
#define OSC_NOT_EXIST 1
#define OSC_RUN_FAILED 2
#define OSHP_NOT_EXIST 3
#define OSHP_RUN_FAILED 4
#define NC_RUN_SUCCESS 5
#define PHP_RES_BUS 0xA0
#define PHP_RES_IO 0xA1
#define PHP_RES_MEM 0xA2
...
...
@@ -125,7 +134,9 @@ static u8 * acpi_path_name( acpi_handle handle)
}
static
void
acpi_get__hpp
(
struct
acpi_bridge
*
ab
);
static
void
acpi_run_oshp
(
struct
acpi_bridge
*
ab
);
static
int
acpi_run_oshp
(
struct
acpi_bridge
*
ab
);
static
int
osc_run_status
=
NC_NOT_RUN
;
static
int
oshp_run_status
=
NC_NOT_RUN
;
static
int
acpi_add_slot_to_php_slots
(
struct
acpi_bridge
*
ab
,
...
...
@@ -159,7 +170,8 @@ static int acpi_add_slot_to_php_slots(
if
(
!
ab
->
_hpp
)
acpi_get__hpp
(
ab
);
acpi_run_oshp
(
ab
);
if
(
osc_run_status
==
OSC_NOT_EXIST
)
oshp_run_status
=
acpi_run_oshp
(
ab
);
if
(
sun
!=
samesun
)
{
info
(
"acpi_pciehprm: Slot sun(%x) at s:b:d:f=0x%02x:%02x:%02x:%02x
\n
"
,
...
...
@@ -238,7 +250,7 @@ static void acpi_get__hpp ( struct acpi_bridge *ab)
kfree
(
ret_buf
.
pointer
);
}
static
void
acpi_run_oshp
(
struct
acpi_bridge
*
ab
)
static
int
acpi_run_oshp
(
struct
acpi_bridge
*
ab
)
{
acpi_status
status
;
u8
*
path_name
=
acpi_path_name
(
ab
->
handle
);
...
...
@@ -248,9 +260,13 @@ static void acpi_run_oshp ( struct acpi_bridge *ab)
status
=
acpi_evaluate_object
(
ab
->
handle
,
METHOD_NAME_OSHP
,
NULL
,
&
ret_buf
);
if
(
ACPI_FAILURE
(
status
))
{
err
(
"acpi_pciehprm:%s OSHP fails=0x%x
\n
"
,
path_name
,
status
);
}
else
oshp_run_status
=
(
status
==
AE_NOT_FOUND
)
?
OSHP_NOT_EXIST
:
OSHP_RUN_FAILED
;
}
else
{
oshp_run_status
=
NC_RUN_SUCCESS
;
dbg
(
"acpi_pciehprm:%s OSHP passes =0x%x
\n
"
,
path_name
,
status
);
return
;
dbg
(
"acpi_pciehprm:%s oshp_run_status =0x%x
\n
"
,
path_name
,
oshp_run_status
);
}
return
oshp_run_status
;
}
static
acpi_status
acpi_evaluate_crs
(
...
...
@@ -1056,6 +1072,16 @@ static struct acpi_bridge * add_host_bridge(
kfree
(
ab
);
return
NULL
;
}
status
=
pci_osc_control_set
(
OSC_PCI_EXPRESS_NATIVE_HP_CONTROL
);
if
(
ACPI_FAILURE
(
status
))
{
err
(
"%s: status %x
\n
"
,
__FUNCTION__
,
status
);
osc_run_status
=
(
status
==
AE_NOT_FOUND
)
?
OSC_NOT_EXIST
:
OSC_RUN_FAILED
;
}
else
{
osc_run_status
=
NC_RUN_SUCCESS
;
}
dbg
(
"%s: osc_run_status %x
\n
"
,
__FUNCTION__
,
osc_run_status
);
build_a_bridge
(
ab
,
ab
);
return
ab
;
...
...
@@ -1141,6 +1167,11 @@ int pciehprm_init(enum php_ctlr_type ctlr_type)
if
(
rc
)
return
rc
;
if
((
oshp_run_status
!=
NC_RUN_SUCCESS
)
&&
(
osc_run_status
!=
NC_RUN_SUCCESS
))
{
err
(
"Fails to gain control of native hot-plug
\n
"
);
rc
=
-
ENODEV
;
}
dbg
(
"pciehprm ACPI init %s
\n
"
,
(
rc
)
?
"fail"
:
"success"
);
return
rc
;
}
...
...
drivers/pci/hotplug/shpchp_ctrl.c
View file @
3c80c502
...
...
@@ -1157,6 +1157,40 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
return
-
1
;
}
if
((
ctrl
->
pci_dev
->
vendor
==
0x8086
)
&&
(
ctrl
->
pci_dev
->
device
==
0x0332
))
{
if
(
slots_not_empty
)
return
WRONG_BUS_FREQUENCY
;
if
((
rc
=
p_slot
->
hpc_ops
->
set_bus_speed_mode
(
p_slot
,
PCI_SPEED_33MHz
)))
{
err
(
"%s: Issue of set bus speed mode command failed
\n
"
,
__FUNCTION__
);
up
(
&
ctrl
->
crit_sect
);
return
WRONG_BUS_FREQUENCY
;
}
wait_for_ctrl_irq
(
ctrl
);
if
((
rc
=
p_slot
->
hpc_ops
->
check_cmd_status
(
ctrl
)))
{
err
(
"%s: Can't set bus speed/mode in the case of adapter & bus mismatch
\n
"
,
__FUNCTION__
);
err
(
"%s: Error code (%d)
\n
"
,
__FUNCTION__
,
rc
);
up
(
&
ctrl
->
crit_sect
);
return
WRONG_BUS_FREQUENCY
;
}
/* turn on board, blink green LED, turn off Amber LED */
if
((
rc
=
p_slot
->
hpc_ops
->
slot_enable
(
p_slot
)))
{
err
(
"%s: Issue of Slot Enable command failed
\n
"
,
__FUNCTION__
);
up
(
&
ctrl
->
crit_sect
);
return
rc
;
}
wait_for_ctrl_irq
(
ctrl
);
if
((
rc
=
p_slot
->
hpc_ops
->
check_cmd_status
(
ctrl
)))
{
err
(
"%s: Failed to enable slot, error code(%d)
\n
"
,
__FUNCTION__
,
rc
);
up
(
&
ctrl
->
crit_sect
);
return
rc
;
}
}
rc
=
p_slot
->
hpc_ops
->
get_adapter_speed
(
p_slot
,
&
adapter_speed
);
/* 0 = PCI 33Mhz, 1 = PCI 66 Mhz, 2 = PCI-X 66 PA, 4 = PCI-X 66 ECC, */
/* 5 = PCI-X 133 PA, 7 = PCI-X 133 ECC, 0xa = PCI-X 133 Mhz 266, */
...
...
drivers/pci/hotplug/shpchp_hpc.c
View file @
3c80c502
...
...
@@ -792,6 +792,7 @@ static void hpc_release_ctlr(struct controller *ctrl)
if
(
php_ctlr
->
irq
)
{
free_irq
(
php_ctlr
->
irq
,
ctrl
);
php_ctlr
->
irq
=
0
;
pci_disable_msi
(
php_ctlr
->
pci_dev
);
}
}
if
(
php_ctlr
->
pci_dev
)
{
...
...
drivers/pci/pci-acpi.c
0 → 100644
View file @
3c80c502
/*
* File: pci-acpi.c
* Purpose: Provide PCI supports in ACPI
*
* Copyright (C) 2004 Intel
* Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
*/
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/module.h>
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/acresrc.h>
#include <acpi/acpi_bus.h>
#include <linux/pci-acpi.h>
static
u32
ctrlset_buf
[
3
]
=
{
0
,
0
,
0
};
static
u32
global_ctrlsets
=
0
;
u8
OSC_UUID
[
16
]
=
{
0x5B
,
0x4D
,
0xDB
,
0x33
,
0xF7
,
0x1F
,
0x1C
,
0x40
,
0x96
,
0x57
,
0x74
,
0x41
,
0xC0
,
0x3D
,
0xD7
,
0x66
};
static
acpi_status
acpi_query_osc
(
acpi_handle
handle
,
u32
level
,
void
*
context
,
void
**
retval
)
{
acpi_status
status
;
struct
acpi_object_list
input
;
union
acpi_object
in_params
[
4
];
struct
acpi_buffer
output
;
union
acpi_object
out_obj
;
u32
osc_dw0
;
/* Setting up output buffer */
output
.
length
=
sizeof
(
out_obj
)
+
3
*
sizeof
(
u32
);
output
.
pointer
=
&
out_obj
;
/* Setting up input parameters */
input
.
count
=
4
;
input
.
pointer
=
in_params
;
in_params
[
0
].
type
=
ACPI_TYPE_BUFFER
;
in_params
[
0
].
buffer
.
length
=
16
;
in_params
[
0
].
buffer
.
pointer
=
OSC_UUID
;
in_params
[
1
].
type
=
ACPI_TYPE_INTEGER
;
in_params
[
1
].
integer
.
value
=
1
;
in_params
[
2
].
type
=
ACPI_TYPE_INTEGER
;
in_params
[
2
].
integer
.
value
=
3
;
in_params
[
3
].
type
=
ACPI_TYPE_BUFFER
;
in_params
[
3
].
buffer
.
length
=
12
;
in_params
[
3
].
buffer
.
pointer
=
(
u8
*
)
context
;
status
=
acpi_evaluate_object
(
handle
,
"_OSC"
,
&
input
,
&
output
);
if
(
ACPI_FAILURE
(
status
))
{
printk
(
KERN_DEBUG
"Evaluate _OSC Set fails. Status = 0x%04x
\n
"
,
status
);
return
status
;
}
if
(
out_obj
.
type
!=
ACPI_TYPE_BUFFER
)
{
printk
(
KERN_DEBUG
"Evaluate _OSC returns wrong type
\n
"
);
return
AE_TYPE
;
}
osc_dw0
=
*
((
u32
*
)
out_obj
.
buffer
.
pointer
);
if
(
osc_dw0
)
{
if
(
osc_dw0
&
OSC_REQUEST_ERROR
)
printk
(
KERN_DEBUG
"_OSC request fails
\n
"
);
if
(
osc_dw0
&
OSC_INVALID_UUID_ERROR
)
printk
(
KERN_DEBUG
"_OSC invalid UUID
\n
"
);
if
(
osc_dw0
&
OSC_INVALID_REVISION_ERROR
)
printk
(
KERN_DEBUG
"_OSC invalid revision
\n
"
);
if
(
osc_dw0
&
OSC_CAPABILITIES_MASK_ERROR
)
{
/* Update Global Control Set */
global_ctrlsets
=
*
((
u32
*
)(
out_obj
.
buffer
.
pointer
+
8
));
return
AE_OK
;
}
return
AE_ERROR
;
}
/* Update Global Control Set */
global_ctrlsets
=
*
((
u32
*
)(
out_obj
.
buffer
.
pointer
+
8
));
return
AE_OK
;
}
static
acpi_status
acpi_run_osc
(
acpi_handle
handle
,
u32
level
,
void
*
context
,
void
**
retval
)
{
acpi_status
status
;
struct
acpi_object_list
input
;
union
acpi_object
in_params
[
4
];
struct
acpi_buffer
output
;
union
acpi_object
out_obj
;
u32
osc_dw0
;
/* Setting up output buffer */
output
.
length
=
sizeof
(
out_obj
)
+
3
*
sizeof
(
u32
);
output
.
pointer
=
&
out_obj
;
/* Setting up input parameters */
input
.
count
=
4
;
input
.
pointer
=
in_params
;
in_params
[
0
].
type
=
ACPI_TYPE_BUFFER
;
in_params
[
0
].
buffer
.
length
=
16
;
in_params
[
0
].
buffer
.
pointer
=
OSC_UUID
;
in_params
[
1
].
type
=
ACPI_TYPE_INTEGER
;
in_params
[
1
].
integer
.
value
=
1
;
in_params
[
2
].
type
=
ACPI_TYPE_INTEGER
;
in_params
[
2
].
integer
.
value
=
3
;
in_params
[
3
].
type
=
ACPI_TYPE_BUFFER
;
in_params
[
3
].
buffer
.
length
=
12
;
in_params
[
3
].
buffer
.
pointer
=
(
u8
*
)
context
;
status
=
acpi_evaluate_object
(
handle
,
"_OSC"
,
&
input
,
&
output
);
if
(
ACPI_FAILURE
(
status
))
{
printk
(
KERN_DEBUG
"Evaluate _OSC Set fails. Status = 0x%04x
\n
"
,
status
);
return
status
;
}
if
(
out_obj
.
type
!=
ACPI_TYPE_BUFFER
)
{
printk
(
KERN_DEBUG
"Evaluate _OSC returns wrong type
\n
"
);
return
AE_TYPE
;
}
osc_dw0
=
*
((
u32
*
)
out_obj
.
buffer
.
pointer
);
if
(
osc_dw0
)
{
if
(
osc_dw0
&
OSC_REQUEST_ERROR
)
printk
(
KERN_DEBUG
"_OSC request fails
\n
"
);
if
(
osc_dw0
&
OSC_INVALID_UUID_ERROR
)
printk
(
KERN_DEBUG
"_OSC invalid UUID
\n
"
);
if
(
osc_dw0
&
OSC_INVALID_REVISION_ERROR
)
printk
(
KERN_DEBUG
"_OSC invalid revision
\n
"
);
if
(
osc_dw0
&
OSC_CAPABILITIES_MASK_ERROR
)
{
printk
(
KERN_DEBUG
"_OSC FW not grant req. control
\n
"
);
return
AE_SUPPORT
;
}
return
AE_ERROR
;
}
return
AE_OK
;
}
/**
* pci_osc_support_set - register OS support to Firmware
* @flags: OS support bits
*
* Update OS support fields and doing a _OSC Query to obtain an update
* from Firmware on supported control bits.
**/
acpi_status
pci_osc_support_set
(
u32
flags
)
{
u32
temp
;
if
(
!
(
flags
&
OSC_SUPPORT_MASKS
))
{
return
AE_TYPE
;
}
ctrlset_buf
[
OSC_SUPPORT_TYPE
]
|=
(
flags
&
OSC_SUPPORT_MASKS
);
/* do _OSC query for all possible controls */
temp
=
ctrlset_buf
[
OSC_CONTROL_TYPE
];
ctrlset_buf
[
OSC_QUERY_TYPE
]
=
OSC_QUERY_ENABLE
;
ctrlset_buf
[
OSC_CONTROL_TYPE
]
=
OSC_CONTROL_MASKS
;
acpi_get_devices
(
PCI_ROOT_HID_STRING
,
acpi_query_osc
,
ctrlset_buf
,
NULL
);
ctrlset_buf
[
OSC_QUERY_TYPE
]
=
!
OSC_QUERY_ENABLE
;
ctrlset_buf
[
OSC_CONTROL_TYPE
]
=
temp
;
return
AE_OK
;
}
EXPORT_SYMBOL
(
pci_osc_support_set
);
/**
* pci_osc_control_set - commit requested control to Firmware
* @flags: driver's requested control bits
*
* Attempt to take control from Firmware on requested control bits.
**/
acpi_status
pci_osc_control_set
(
u32
flags
)
{
acpi_status
status
;
u32
ctrlset
;
ctrlset
=
(
flags
&
OSC_CONTROL_MASKS
);
if
(
!
ctrlset
)
{
return
AE_TYPE
;
}
if
(
ctrlset_buf
[
OSC_SUPPORT_TYPE
]
&&
((
global_ctrlsets
&
ctrlset
)
!=
ctrlset
))
{
return
AE_SUPPORT
;
}
ctrlset_buf
[
OSC_CONTROL_TYPE
]
|=
ctrlset
;
status
=
acpi_get_devices
(
PCI_ROOT_HID_STRING
,
acpi_run_osc
,
ctrlset_buf
,
NULL
);
if
(
ACPI_FAILURE
(
status
))
{
ctrlset_buf
[
OSC_CONTROL_TYPE
]
&=
~
ctrlset
;
}
return
status
;
}
EXPORT_SYMBOL
(
pci_osc_control_set
);
drivers/pci/pci-driver.c
View file @
3c80c502
...
...
@@ -271,17 +271,14 @@ static int pci_device_remove(struct device * dev)
pci_dev
->
driver
=
NULL
;
}
#ifdef CONFIG_DEBUG_KERNEL
/*
* If the driver decides to stop using the device, it should
* call pci_disable_device().
* We would love to complain here if pci_dev->is_enabled is set, that
* the driver should have called pci_disable_device(), but the
* unfortunate fact is there are too many odd BIOS and bridge setups
* that don't like drivers doing that all of the time.
* Oh well, we can dream of sane hardware when we sleep, no matter how
* horrible the crap we have to deal with is when we are awake...
*/
if
(
pci_dev
->
is_enabled
)
{
dev_warn
(
&
pci_dev
->
dev
,
"Device was removed without properly "
"calling pci_disable_device(). This may need fixing.
\n
"
);
/* WARN_ON(1); */
}
#endif
/* CONFIG_DEBUG_KERNEL */
pci_dev_put
(
pci_dev
);
return
0
;
...
...
drivers/pci/pci-sysfs.c
View file @
3c80c502
...
...
@@ -5,6 +5,8 @@
* (C) Copyright 2002-2004 IBM Corp.
* (C) Copyright 2003 Matthew Wilcox
* (C) Copyright 2003 Hewlett-Packard
* (C) Copyright 2004 Jon Smirl <jonsmirl@yahoo.com>
* (C) Copyright 2004 Silicon Graphics, Inc. Jesse Barnes <jbarnes@sgi.com>
*
* File attributes for PCI devices
*
...
...
@@ -20,6 +22,8 @@
#include "pci.h"
static
int
sysfs_initialized
;
/* = 0 */
/* show configuration fields */
#define pci_config_attr(field, format_string) \
static ssize_t \
...
...
@@ -164,6 +168,65 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
return
count
;
}
/**
* pci_write_rom - used to enable access to the PCI ROM display
* @kobj: kernel object handle
* @buf: user input
* @off: file offset
* @count: number of byte in input
*
* writing anything except 0 enables it
*/
static
ssize_t
pci_write_rom
(
struct
kobject
*
kobj
,
char
*
buf
,
loff_t
off
,
size_t
count
)
{
struct
pci_dev
*
pdev
=
to_pci_dev
(
container_of
(
kobj
,
struct
device
,
kobj
));
if
((
off
==
0
)
&&
(
*
buf
==
'0'
)
&&
(
count
==
2
))
pdev
->
rom_attr_enabled
=
0
;
else
pdev
->
rom_attr_enabled
=
1
;
return
count
;
}
/**
* pci_read_rom - read a PCI ROM
* @kobj: kernel object handle
* @buf: where to put the data we read from the ROM
* @off: file offset
* @count: number of bytes to read
*
* Put @count bytes starting at @off into @buf from the ROM in the PCI
* device corresponding to @kobj.
*/
static
ssize_t
pci_read_rom
(
struct
kobject
*
kobj
,
char
*
buf
,
loff_t
off
,
size_t
count
)
{
struct
pci_dev
*
pdev
=
to_pci_dev
(
container_of
(
kobj
,
struct
device
,
kobj
));
void
__iomem
*
rom
;
size_t
size
;
if
(
!
pdev
->
rom_attr_enabled
)
return
-
EINVAL
;
rom
=
pci_map_rom
(
pdev
,
&
size
);
/* size starts out as PCI window size */
if
(
!
rom
)
return
0
;
if
(
off
>=
size
)
count
=
0
;
else
{
if
(
off
+
count
>
size
)
count
=
size
-
off
;
memcpy_fromio
(
buf
,
rom
+
off
,
count
);
}
pci_unmap_rom
(
pdev
,
rom
);
return
count
;
}
static
struct
bin_attribute
pci_config_attr
=
{
.
attr
=
{
.
name
=
"config"
,
...
...
@@ -186,13 +249,68 @@ static struct bin_attribute pcie_config_attr = {
.
write
=
pci_write_config
,
};
void
pci_create_sysfs_dev_files
(
struct
pci_dev
*
pdev
)
int
pci_create_sysfs_dev_files
(
struct
pci_dev
*
pdev
)
{
if
(
!
sysfs_initialized
)
return
-
EACCES
;
if
(
pdev
->
cfg_size
<
4096
)
sysfs_create_bin_file
(
&
pdev
->
dev
.
kobj
,
&
pci_config_attr
);
else
sysfs_create_bin_file
(
&
pdev
->
dev
.
kobj
,
&
pcie_config_attr
);
/* If the device has a ROM, try to expose it in sysfs. */
if
(
pci_resource_len
(
pdev
,
PCI_ROM_RESOURCE
))
{
struct
bin_attribute
*
rom_attr
;
rom_attr
=
kmalloc
(
sizeof
(
*
rom_attr
),
GFP_ATOMIC
);
if
(
rom_attr
)
{
pdev
->
rom_attr
=
rom_attr
;
rom_attr
->
size
=
pci_resource_len
(
pdev
,
PCI_ROM_RESOURCE
);
rom_attr
->
attr
.
name
=
"rom"
;
rom_attr
->
attr
.
mode
=
S_IRUSR
;
rom_attr
->
attr
.
owner
=
THIS_MODULE
;
rom_attr
->
read
=
pci_read_rom
;
rom_attr
->
write
=
pci_write_rom
;
sysfs_create_bin_file
(
&
pdev
->
dev
.
kobj
,
rom_attr
);
}
}
/* add platform-specific attributes */
pcibios_add_platform_entries
(
pdev
);
return
0
;
}
/**
* pci_remove_sysfs_dev_files - cleanup PCI specific sysfs files
* @pdev: device whose entries we should free
*
* Cleanup when @pdev is removed from sysfs.
*/
void
pci_remove_sysfs_dev_files
(
struct
pci_dev
*
pdev
)
{
if
(
pdev
->
cfg_size
<
4096
)
sysfs_remove_bin_file
(
&
pdev
->
dev
.
kobj
,
&
pci_config_attr
);
else
sysfs_remove_bin_file
(
&
pdev
->
dev
.
kobj
,
&
pcie_config_attr
);
if
(
pci_resource_len
(
pdev
,
PCI_ROM_RESOURCE
))
{
if
(
pdev
->
rom_attr
)
{
sysfs_remove_bin_file
(
&
pdev
->
dev
.
kobj
,
pdev
->
rom_attr
);
kfree
(
pdev
->
rom_attr
);
}
}
}
static
int
__init
pci_sysfs_init
(
void
)
{
struct
pci_dev
*
pdev
=
NULL
;
sysfs_initialized
=
1
;
while
((
pdev
=
pci_find_device
(
PCI_ANY_ID
,
PCI_ANY_ID
,
pdev
))
!=
NULL
)
pci_create_sysfs_dev_files
(
pdev
);
return
0
;
}
__initcall
(
pci_sysfs_init
);
drivers/pci/pci.c
View file @
3c80c502
...
...
@@ -374,6 +374,16 @@ pci_enable_device(struct pci_dev *dev)
return
0
;
}
/**
* pcibios_disable_device - disable arch specific PCI resources for device dev
* @dev: the PCI device to disable
*
* Disables architecture specific PCI resources for the device. This
* is the default implementation. Architecture implementations can
* override this.
*/
void
__attribute__
((
weak
))
pcibios_disable_device
(
struct
pci_dev
*
dev
)
{}
/**
* pci_disable_device - Disable PCI device after use
* @dev: PCI device to be disabled
...
...
@@ -394,6 +404,8 @@ pci_disable_device(struct pci_dev *dev)
pci_command
&=
~
PCI_COMMAND_MASTER
;
pci_write_config_word
(
dev
,
PCI_COMMAND
,
pci_command
);
}
pcibios_disable_device
(
dev
);
}
/**
...
...
drivers/pci/pci.h
View file @
3c80c502
...
...
@@ -2,7 +2,9 @@
extern
int
pci_hotplug
(
struct
device
*
dev
,
char
**
envp
,
int
num_envp
,
char
*
buffer
,
int
buffer_size
);
extern
void
pci_create_sysfs_dev_files
(
struct
pci_dev
*
pdev
);
extern
int
pci_create_sysfs_dev_files
(
struct
pci_dev
*
pdev
);
extern
void
pci_remove_sysfs_dev_files
(
struct
pci_dev
*
pdev
);
extern
void
pci_cleanup_rom
(
struct
pci_dev
*
dev
);
extern
int
pci_bus_alloc_resource
(
struct
pci_bus
*
bus
,
struct
resource
*
res
,
unsigned
long
size
,
unsigned
long
align
,
unsigned
long
min
,
unsigned
int
type_mask
,
...
...
@@ -61,7 +63,7 @@ extern int pci_visit_dev(struct pci_visit *fn,
/* Lock for read/write access to pci device and bus lists */
extern
spinlock_t
pci_bus_lock
;
extern
int
pcie
hp_msi
_quirk
;
extern
int
pcie
_mch
_quirk
;
extern
struct
device_attribute
pci_dev_attrs
[];
/**
...
...
drivers/pci/probe.c
View file @
3c80c502
...
...
@@ -170,7 +170,7 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
if
(
sz
&&
sz
!=
0xffffffff
)
{
sz
=
pci_size
(
l
,
sz
,
PCI_ROM_ADDRESS_MASK
);
if
(
sz
)
{
res
->
flags
=
(
l
&
PCI_ROM_ADDRESS
_ENABLE
)
|
res
->
flags
=
(
l
&
IORESOURCE_ROM
_ENABLE
)
|
IORESOURCE_MEM
|
IORESOURCE_PREFETCH
|
IORESOURCE_READONLY
|
IORESOURCE_CACHEABLE
;
res
->
start
=
l
&
PCI_ROM_ADDRESS_MASK
;
...
...
@@ -478,6 +478,9 @@ static int pci_setup_device(struct pci_dev * dev)
/* "Unknown power state" */
dev
->
current_state
=
4
;
/* Early fixups, before probing the BARs */
pci_fixup_device
(
pci_fixup_early
,
dev
);
switch
(
dev
->
hdr_type
)
{
/* header type */
case
PCI_HEADER_TYPE_NORMAL
:
/* standard header */
if
(
class
==
PCI_CLASS_BRIDGE_PCI
)
...
...
drivers/pci/quirks.c
View file @
3c80c502
...
...
@@ -1136,7 +1136,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EESSC, quirk_a
#endif
#ifdef CONFIG_SCSI_SATA
static
void
__init
quirk_intel_ide_combined
(
struct
pci_dev
*
pdev
)
static
void
__
dev
init
quirk_intel_ide_combined
(
struct
pci_dev
*
pdev
)
{
u8
prog
,
comb
,
tmp
;
int
ich
=
0
;
...
...
@@ -1210,14 +1210,15 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_intel_ide_co
#endif
/* CONFIG_SCSI_SATA */
int
pcie
hp_msi
_quirk
;
int
pcie
_mch
_quirk
;
static
void
__devinit
quirk_pcie
hp_msi
(
struct
pci_dev
*
pdev
)
static
void
__devinit
quirk_pcie
_mch
(
struct
pci_dev
*
pdev
)
{
pcie
hp_msi
_quirk
=
1
;
pcie
_mch
_quirk
=
1
;
}
DECLARE_PCI_FIXUP_FINAL
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_SMCH
,
quirk_pciehp_msi
);
DECLARE_PCI_FIXUP_FINAL
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_E7520_MCH
,
quirk_pcie_mch
);
DECLARE_PCI_FIXUP_FINAL
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_E7320_MCH
,
quirk_pcie_mch
);
DECLARE_PCI_FIXUP_FINAL
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_E7525_MCH
,
quirk_pcie_mch
);
static
void
pci_do_fixups
(
struct
pci_dev
*
dev
,
struct
pci_fixup
*
f
,
struct
pci_fixup
*
end
)
{
...
...
@@ -1266,4 +1267,7 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
pci_do_fixups
(
dev
,
start
,
end
);
}
EXPORT_SYMBOL
(
pciehp_msi_quirk
);
EXPORT_SYMBOL
(
pcie_mch_quirk
);
#ifdef CONFIG_HOTPLUG
EXPORT_SYMBOL
(
pci_fixup_device
);
#endif
drivers/pci/remove.c
View file @
3c80c502
...
...
@@ -16,6 +16,7 @@ static void pci_free_resources(struct pci_dev *dev)
msi_remove_pci_irq_vectors
(
dev
);
pci_cleanup_rom
(
dev
);
for
(
i
=
0
;
i
<
PCI_NUM_RESOURCES
;
i
++
)
{
struct
resource
*
res
=
dev
->
resource
+
i
;
if
(
res
->
parent
)
...
...
@@ -26,6 +27,7 @@ static void pci_free_resources(struct pci_dev *dev)
static
void
pci_destroy_dev
(
struct
pci_dev
*
dev
)
{
pci_proc_detach_device
(
dev
);
pci_remove_sysfs_dev_files
(
dev
);
device_unregister
(
&
dev
->
dev
);
/* Remove the device from the device lists, and prevent any further
...
...
drivers/pci/rom.c
0 → 100644
View file @
3c80c502
/*
* drivers/pci/rom.c
*
* (C) Copyright 2004 Jon Smirl <jonsmirl@yahoo.com>
* (C) Copyright 2004 Silicon Graphics, Inc. Jesse Barnes <jbarnes@sgi.com>
*
* PCI ROM access routines
*
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include "pci.h"
/**
* pci_enable_rom - enable ROM decoding for a PCI device
* @dev: PCI device to enable
*
* Enable ROM decoding on @dev. This involves simply turning on the last
* bit of the PCI ROM BAR. Note that some cards may share address decoders
* between the ROM and other resources, so enabling it may disable access
* to MMIO registers or other card memory.
*/
static
void
pci_enable_rom
(
struct
pci_dev
*
pdev
)
{
u32
rom_addr
;
pci_read_config_dword
(
pdev
,
pdev
->
rom_base_reg
,
&
rom_addr
);
rom_addr
|=
PCI_ROM_ADDRESS_ENABLE
;
pci_write_config_dword
(
pdev
,
pdev
->
rom_base_reg
,
rom_addr
);
}
/**
* pci_disable_rom - disable ROM decoding for a PCI device
* @dev: PCI device to disable
*
* Disable ROM decoding on a PCI device by turning off the last bit in the
* ROM BAR.
*/
static
void
pci_disable_rom
(
struct
pci_dev
*
pdev
)
{
u32
rom_addr
;
pci_read_config_dword
(
pdev
,
pdev
->
rom_base_reg
,
&
rom_addr
);
rom_addr
&=
~
PCI_ROM_ADDRESS_ENABLE
;
pci_write_config_dword
(
pdev
,
pdev
->
rom_base_reg
,
rom_addr
);
}
/**
* pci_map_rom - map a PCI ROM to kernel space
* @dev: pointer to pci device struct
* @size: pointer to receive size of pci window over ROM
* @return: kernel virtual pointer to image of ROM
*
* Map a PCI ROM into kernel space. If ROM is boot video ROM,
* the shadow BIOS copy will be returned instead of the
* actual ROM.
*/
void
__iomem
*
pci_map_rom
(
struct
pci_dev
*
pdev
,
size_t
*
size
)
{
struct
resource
*
res
=
&
pdev
->
resource
[
PCI_ROM_RESOURCE
];
loff_t
start
;
void
__iomem
*
rom
;
void
__iomem
*
image
;
int
last_image
;
if
(
res
->
flags
&
IORESOURCE_ROM_SHADOW
)
{
/* IORESOURCE_ROM_SHADOW only set on x86 */
start
=
(
loff_t
)
0xC0000
;
/* primary video rom always starts here */
*
size
=
0x20000
;
/* cover C000:0 through E000:0 */
}
else
{
if
(
res
->
flags
&
IORESOURCE_ROM_COPY
)
{
*
size
=
pci_resource_len
(
pdev
,
PCI_ROM_RESOURCE
);
return
(
void
__iomem
*
)
pci_resource_start
(
pdev
,
PCI_ROM_RESOURCE
);
}
else
{
/* assign the ROM an address if it doesn't have one */
if
(
res
->
parent
==
NULL
)
pci_assign_resource
(
pdev
,
PCI_ROM_RESOURCE
);
start
=
pci_resource_start
(
pdev
,
PCI_ROM_RESOURCE
);
*
size
=
pci_resource_len
(
pdev
,
PCI_ROM_RESOURCE
);
if
(
*
size
==
0
)
return
NULL
;
/* Enable ROM space decodes */
pci_enable_rom
(
pdev
);
}
}
rom
=
ioremap
(
start
,
*
size
);
if
(
!
rom
)
{
/* restore enable if ioremap fails */
if
(
!
(
res
->
flags
&
(
IORESOURCE_ROM_ENABLE
|
IORESOURCE_ROM_SHADOW
|
IORESOURCE_ROM_COPY
)))
pci_disable_rom
(
pdev
);
return
NULL
;
}
/* Try to find the true size of the ROM since sometimes the PCI window */
/* size is much larger than the actual size of the ROM. */
/* True size is important if the ROM is going to be copied. */
image
=
rom
;
do
{
void
__iomem
*
pds
;
/* Standard PCI ROMs start out with these bytes 55 AA */
if
(
readb
(
image
)
!=
0x55
)
break
;
if
(
readb
(
image
+
1
)
!=
0xAA
)
break
;
/* get the PCI data structure and check its signature */
pds
=
image
+
readw
(
image
+
24
);
if
(
readb
(
pds
)
!=
'P'
)
break
;
if
(
readb
(
pds
+
1
)
!=
'C'
)
break
;
if
(
readb
(
pds
+
2
)
!=
'I'
)
break
;
if
(
readb
(
pds
+
3
)
!=
'R'
)
break
;
last_image
=
readb
(
pds
+
21
)
&
0x80
;
/* this length is reliable */
image
+=
readw
(
pds
+
16
)
*
512
;
}
while
(
!
last_image
);
*
size
=
image
-
rom
;
return
rom
;
}
/**
* pci_map_rom_copy - map a PCI ROM to kernel space, create a copy
* @dev: pointer to pci device struct
* @size: pointer to receive size of pci window over ROM
* @return: kernel virtual pointer to image of ROM
*
* Map a PCI ROM into kernel space. If ROM is boot video ROM,
* the shadow BIOS copy will be returned instead of the
* actual ROM.
*/
void
__iomem
*
pci_map_rom_copy
(
struct
pci_dev
*
pdev
,
size_t
*
size
)
{
struct
resource
*
res
=
&
pdev
->
resource
[
PCI_ROM_RESOURCE
];
void
__iomem
*
rom
;
rom
=
pci_map_rom
(
pdev
,
size
);
if
(
!
rom
)
return
NULL
;
if
(
res
->
flags
&
(
IORESOURCE_ROM_COPY
|
IORESOURCE_ROM_SHADOW
))
return
rom
;
res
->
start
=
(
unsigned
long
)
kmalloc
(
*
size
,
GFP_KERNEL
);
if
(
!
res
->
start
)
return
rom
;
res
->
end
=
res
->
start
+
*
size
;
memcpy_fromio
((
void
*
)
res
->
start
,
rom
,
*
size
);
pci_unmap_rom
(
pdev
,
rom
);
res
->
flags
|=
IORESOURCE_ROM_COPY
;
return
(
void
__iomem
*
)
res
->
start
;
}
/**
* pci_unmap_rom - unmap the ROM from kernel space
* @dev: pointer to pci device struct
* @rom: virtual address of the previous mapping
*
* Remove a mapping of a previously mapped ROM
*/
void
pci_unmap_rom
(
struct
pci_dev
*
pdev
,
void
__iomem
*
rom
)
{
struct
resource
*
res
=
&
pdev
->
resource
[
PCI_ROM_RESOURCE
];
if
(
res
->
flags
&
IORESOURCE_ROM_COPY
)
return
;
iounmap
(
rom
);
/* Disable again before continuing, leave enabled if pci=rom */
if
(
!
(
res
->
flags
&
(
IORESOURCE_ROM_ENABLE
|
IORESOURCE_ROM_SHADOW
)))
pci_disable_rom
(
pdev
);
}
/**
* pci_remove_rom - disable the ROM and remove its sysfs attribute
* @dev: pointer to pci device struct
*
*/
void
pci_remove_rom
(
struct
pci_dev
*
pdev
)
{
struct
resource
*
res
=
&
pdev
->
resource
[
PCI_ROM_RESOURCE
];
if
(
pci_resource_len
(
pdev
,
PCI_ROM_RESOURCE
))
sysfs_remove_bin_file
(
&
pdev
->
dev
.
kobj
,
pdev
->
rom_attr
);
if
(
!
(
res
->
flags
&
(
IORESOURCE_ROM_ENABLE
|
IORESOURCE_ROM_SHADOW
|
IORESOURCE_ROM_COPY
)))
pci_disable_rom
(
pdev
);
}
/**
* pci_cleanup_rom - internal routine for freeing the ROM copy created
* by pci_map_rom_copy called from remove.c
* @dev: pointer to pci device struct
*
*/
void
pci_cleanup_rom
(
struct
pci_dev
*
pdev
)
{
struct
resource
*
res
=
&
pdev
->
resource
[
PCI_ROM_RESOURCE
];
if
(
res
->
flags
&
IORESOURCE_ROM_COPY
)
{
kfree
((
void
*
)
res
->
start
);
res
->
flags
&=
~
IORESOURCE_ROM_COPY
;
res
->
start
=
0
;
res
->
end
=
0
;
}
}
EXPORT_SYMBOL
(
pci_map_rom
);
EXPORT_SYMBOL
(
pci_map_rom_copy
);
EXPORT_SYMBOL
(
pci_unmap_rom
);
EXPORT_SYMBOL
(
pci_remove_rom
);
drivers/pci/setup-res.c
View file @
3c80c502
...
...
@@ -56,7 +56,7 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
if
(
resno
<
6
)
{
reg
=
PCI_BASE_ADDRESS_0
+
4
*
resno
;
}
else
if
(
resno
==
PCI_ROM_RESOURCE
)
{
new
|=
res
->
flags
&
PCI_ROM_ADDRESS
_ENABLE
;
new
|=
res
->
flags
&
IORESOURCE_ROM
_ENABLE
;
reg
=
dev
->
rom_base_reg
;
}
else
{
/* Hmm, non-standard resource. */
...
...
include/asm-generic/vmlinux.lds.h
View file @
3c80c502
...
...
@@ -18,6 +18,9 @@
\
/* PCI quirks */
\
.pci_fixup : AT(ADDR(.pci_fixup) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start_pci_fixups_early) = .; \
*(.pci_fixup_early) \
VMLINUX_SYMBOL(__end_pci_fixups_early) = .; \
VMLINUX_SYMBOL(__start_pci_fixups_header) = .; \
*(.pci_fixup_header) \
VMLINUX_SYMBOL(__end_pci_fixups_header) = .; \
...
...
include/linux/ioport.h
View file @
3c80c502
...
...
@@ -82,6 +82,11 @@ struct resource_list {
#define IORESOURCE_MEM_SHADOWABLE (1<<5)
/* dup: IORESOURCE_SHADOWABLE */
#define IORESOURCE_MEM_EXPANSIONROM (1<<6)
/* PCI ROM control bits (IORESOURCE_BITS) */
#define IORESOURCE_ROM_ENABLE (1<<0)
/* ROM is enabled, same as PCI_ROM_ADDRESS_ENABLE */
#define IORESOURCE_ROM_SHADOW (1<<1)
/* ROM is copy at C000:0 */
#define IORESOURCE_ROM_COPY (1<<2)
/* ROM is alloc'd copy, resource field overlaid */
/* PC/ISA/whatever - the normal PC address spaces: IO and memory */
extern
struct
resource
ioport_resource
;
extern
struct
resource
iomem_resource
;
...
...
include/linux/pci-acpi.h
0 → 100644
View file @
3c80c502
/*
* File pci-acpi.h
*
* Copyright (C) 2004 Intel
* Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
*/
#ifndef _PCI_ACPI_H_
#define _PCI_ACPI_H_
#define OSC_QUERY_TYPE 0
#define OSC_SUPPORT_TYPE 1
#define OSC_CONTROL_TYPE 2
#define OSC_SUPPORT_MASKS 0x1f
/*
* _OSC DW0 Definition
*/
#define OSC_QUERY_ENABLE 1
#define OSC_REQUEST_ERROR 2
#define OSC_INVALID_UUID_ERROR 4
#define OSC_INVALID_REVISION_ERROR 8
#define OSC_CAPABILITIES_MASK_ERROR 16
/*
* _OSC DW1 Definition (OS Support Fields)
*/
#define OSC_EXT_PCI_CONFIG_SUPPORT 1
#define OSC_ACTIVE_STATE_PWR_SUPPORT 2
#define OSC_CLOCK_PWR_CAPABILITY_SUPPORT 4
#define OSC_PCI_SEGMENT_GROUPS_SUPPORT 8
#define OSC_MSI_SUPPORT 16
/*
* _OSC DW1 Definition (OS Control Fields)
*/
#define OSC_PCI_EXPRESS_NATIVE_HP_CONTROL 1
#define OSC_SHPC_NATIVE_HP_CONTROL 2
#define OSC_PCI_EXPRESS_PME_CONTROL 4
#define OSC_PCI_EXPRESS_AER_CONTROL 8
#define OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL 16
#define OSC_CONTROL_MASKS (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | \
OSC_SHPC_NATIVE_HP_CONTROL | \
OSC_PCI_EXPRESS_PME_CONTROL | \
OSC_PCI_EXPRESS_AER_CONTROL | \
OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL)
#ifdef CONFIG_ACPI
extern
acpi_status
pci_osc_control_set
(
u32
flags
);
extern
acpi_status
pci_osc_support_set
(
u32
flags
);
#else
#if !defined(acpi_status)
typedef
u32
acpi_status
;
#define AE_ERROR (acpi_status) (0x0001)
#endif
static
inline
acpi_status
pci_osc_control_set
(
u32
flags
)
{
return
AE_ERROR
;}
static
inline
acpi_status
pci_osc_support_set
(
u32
flags
)
{
return
AE_ERROR
;}
#endif
#endif
/* _PCI_ACPI_H_ */
include/linux/pci.h
View file @
3c80c502
...
...
@@ -537,6 +537,8 @@ struct pci_dev {
unsigned
int
is_busmaster
:
1
;
/* device is busmaster */
u32
saved_config_space
[
16
];
/* config space saved at suspend time */
struct
bin_attribute
*
rom_attr
;
/* attribute descriptor for sysfs ROM entry */
int
rom_attr_enabled
;
/* has display of the rom attribute been enabled? */
#ifdef CONFIG_PCI_NAMES
#define PCI_NAME_SIZE 96
#define PCI_NAME_HALF __stringify(43)
/* less than half to handle slop */
...
...
@@ -785,6 +787,12 @@ int pci_dac_set_dma_mask(struct pci_dev *dev, u64 mask);
int
pci_set_consistent_dma_mask
(
struct
pci_dev
*
dev
,
u64
mask
);
int
pci_assign_resource
(
struct
pci_dev
*
dev
,
int
i
);
/* ROM control related routines */
void
__iomem
*
pci_map_rom
(
struct
pci_dev
*
pdev
,
size_t
*
size
);
void
__iomem
*
pci_map_rom_copy
(
struct
pci_dev
*
pdev
,
size_t
*
size
);
void
pci_unmap_rom
(
struct
pci_dev
*
pdev
,
void
__iomem
*
rom
);
void
pci_remove_rom
(
struct
pci_dev
*
pdev
);
/* Power management related routines */
int
pci_save_state
(
struct
pci_dev
*
dev
);
int
pci_restore_state
(
struct
pci_dev
*
dev
);
...
...
@@ -994,26 +1002,28 @@ struct pci_fixup {
};
enum
pci_fixup_pass
{
pci_fixup_header
,
/* Called immediately after reading configuration header */
pci_fixup_early
,
/* Before probing BARs */
pci_fixup_header
,
/* After reading configuration header */
pci_fixup_final
,
/* Final phase of device fixups */
pci_fixup_enable
,
/* pci_enable_device() time */
};
/* Anonymous variables would be nice... */
#define DECLARE_PCI_FIXUP_SECTION(section, name, vendor, device, hook) \
static struct pci_fixup __pci_fixup_##name __attribute_used__ \
__attribute__((__section__(#section))) = { vendor, device, hook };
#define DECLARE_PCI_FIXUP_EARLY(vendor, device, hook) \
DECLARE_PCI_FIXUP_SECTION(.pci_fixup_early, \
vendor##device##hook, vendor, device, hook)
#define DECLARE_PCI_FIXUP_HEADER(vendor, device, hook) \
static struct pci_fixup __pci_fixup_##vendor##device##hook __attribute_used__ \
__attribute__((__section__(".pci_fixup_header"))) = { \
vendor, device, hook };
DECLARE_PCI_FIXUP_SECTION(.pci_fixup_header, \
vendor##device##hook, vendor, device, hook)
#define DECLARE_PCI_FIXUP_FINAL(vendor, device, hook) \
static struct pci_fixup __pci_fixup_##vendor##device##hook __attribute_used__ \
__attribute__((__section__(".pci_fixup_final"))) = { \
vendor, device, hook };
DECLARE_PCI_FIXUP_SECTION(.pci_fixup_final, \
vendor##device##hook, vendor, device, hook)
#define DECLARE_PCI_FIXUP_ENABLE(vendor, device, hook) \
static struct pci_fixup __pci_fixup_##vendor##device##hook __attribute_used__ \
__attribute__((__section__(".pci_fixup_enable"))) = { \
vendor, device, hook };
DECLARE_PCI_FIXUP_SECTION(.pci_fixup_enable, \
vendor##device##hook, vendor, device, hook)
void
pci_fixup_device
(
enum
pci_fixup_pass
pass
,
struct
pci_dev
*
dev
);
...
...
include/linux/pci_ids.h
View file @
3c80c502
...
...
@@ -2206,8 +2206,14 @@
#define PCI_DEVICE_ID_INTEL_82830_CGC 0x3577
#define PCI_DEVICE_ID_INTEL_82855GM_HB 0x3580
#define PCI_DEVICE_ID_INTEL_82855GM_IG 0x3582
#define PCI_DEVICE_ID_INTEL_
S
MCH 0x3590
#define PCI_DEVICE_ID_INTEL_
E7520_
MCH 0x3590
#define PCI_DEVICE_ID_INTEL_E7320_MCH 0x3592
#define PCI_DEVICE_ID_INTEL_MCH_PA 0x3595
#define PCI_DEVICE_ID_INTEL_MCH_PA1 0x3596
#define PCI_DEVICE_ID_INTEL_MCH_PB 0x3597
#define PCI_DEVICE_ID_INTEL_MCH_PB1 0x3598
#define PCI_DEVICE_ID_INTEL_MCH_PC 0x3599
#define PCI_DEVICE_ID_INTEL_MCH_PC1 0x359a
#define PCI_DEVICE_ID_INTEL_E7525_MCH 0x359e
#define PCI_DEVICE_ID_INTEL_80310 0x530d
#define PCI_DEVICE_ID_INTEL_82371SB_0 0x7000
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment