Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
OpenBMC Firmware
talos-obmc-linux
Commits
adb2705a
Commit
adb2705a
authored
19 years ago
by
Linus Torvalds
Browse files
Options
Download
Plain Diff
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/pci-2.6
parents
f340c0d1
8644d2a4
Changes
69
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
607 additions
and
1670 deletions
+607
-1670
drivers/char/rio/rio_linux.c
drivers/char/rio/rio_linux.c
+2
-2
drivers/message/fusion/mptfc.c
drivers/message/fusion/mptfc.c
+1
-3
drivers/message/fusion/mptscsih.c
drivers/message/fusion/mptscsih.c
+5
-5
drivers/message/fusion/mptscsih.h
drivers/message/fusion/mptscsih.h
+1
-1
drivers/message/fusion/mptspi.c
drivers/message/fusion/mptspi.c
+1
-3
drivers/net/e100.c
drivers/net/e100.c
+2
-7
drivers/net/via-rhine.c
drivers/net/via-rhine.c
+4
-7
drivers/parisc/dino.c
drivers/parisc/dino.c
+1
-0
drivers/parisc/lba_pci.c
drivers/parisc/lba_pci.c
+2
-0
drivers/pci/bus.c
drivers/pci/bus.c
+7
-4
drivers/pci/hotplug/Makefile
drivers/pci/hotplug/Makefile
+1
-3
drivers/pci/hotplug/acpiphp.h
drivers/pci/hotplug/acpiphp.h
+2
-45
drivers/pci/hotplug/acpiphp_core.c
drivers/pci/hotplug/acpiphp_core.c
+5
-4
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/hotplug/acpiphp_glue.c
+512
-370
drivers/pci/hotplug/acpiphp_pci.c
drivers/pci/hotplug/acpiphp_pci.c
+0
-449
drivers/pci/hotplug/acpiphp_res.c
drivers/pci/hotplug/acpiphp_res.c
+0
-700
drivers/pci/hotplug/cpqphp_core.c
drivers/pci/hotplug/cpqphp_core.c
+3
-2
drivers/pci/msi.c
drivers/pci/msi.c
+33
-55
drivers/pci/msi.h
drivers/pci/msi.h
+4
-5
drivers/pci/pci-sysfs.c
drivers/pci/pci-sysfs.c
+21
-5
No files found.
drivers/char/rio/rio_linux.c
View file @
adb2705a
...
...
@@ -1095,7 +1095,7 @@ static int __init rio_init(void)
#ifdef CONFIG_PCI
/* First look for the JET devices: */
while
((
pdev
=
pci_
find
_device
(
PCI_VENDOR_ID_SPECIALIX
,
while
((
pdev
=
pci_
get
_device
(
PCI_VENDOR_ID_SPECIALIX
,
PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8
,
pdev
)))
{
if
(
pci_enable_device
(
pdev
))
continue
;
...
...
@@ -1169,7 +1169,7 @@ static int __init rio_init(void)
*/
/* Then look for the older RIO/PCI devices: */
while
((
pdev
=
pci_
find
_device
(
PCI_VENDOR_ID_SPECIALIX
,
while
((
pdev
=
pci_
get
_device
(
PCI_VENDOR_ID_SPECIALIX
,
PCI_DEVICE_ID_SPECIALIX_RIO
,
pdev
)))
{
if
(
pci_enable_device
(
pdev
))
continue
;
...
...
This diff is collapsed.
Click to expand it.
drivers/message/fusion/mptfc.c
View file @
adb2705a
...
...
@@ -364,9 +364,7 @@ static struct pci_driver mptfc_driver = {
.
id_table
=
mptfc_pci_table
,
.
probe
=
mptfc_probe
,
.
remove
=
__devexit_p
(
mptscsih_remove
),
.
driver
=
{
.
shutdown
=
mptscsih_shutdown
,
},
.
shutdown
=
mptscsih_shutdown
,
#ifdef CONFIG_PM
.
suspend
=
mptscsih_suspend
,
.
resume
=
mptscsih_resume
,
...
...
This diff is collapsed.
Click to expand it.
drivers/message/fusion/mptscsih.c
View file @
adb2705a
...
...
@@ -170,7 +170,7 @@ static void mptscsih_fillbuf(char *buffer, int size, int index, int width);
#endif
void mptscsih_remove(struct pci_dev *);
void mptscsih_shutdown(struct dev
ice
*);
void mptscsih_shutdown(struct
pci_
dev *);
#ifdef CONFIG_PM
int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
int mptscsih_resume(struct pci_dev *pdev);
...
...
@@ -988,7 +988,7 @@ mptscsih_remove(struct pci_dev *pdev)
#endif
#endif
mptscsih_shutdown(
&pdev->
dev);
mptscsih_shutdown(
p
dev);
sz1=0;
...
...
@@ -1026,9 +1026,9 @@ mptscsih_remove(struct pci_dev *pdev)
*
*/
void
mptscsih_shutdown(struct dev
ice
*
dev)
mptscsih_shutdown(struct
pci_
dev *
p
dev)
{
MPT_ADAPTER *ioc = pci_get_drvdata(
to_pci_dev(dev)
);
MPT_ADAPTER *ioc = pci_get_drvdata(
pdev
);
struct Scsi_Host *host = ioc->sh;
MPT_SCSI_HOST *hd;
...
...
@@ -1054,7 +1054,7 @@ mptscsih_shutdown(struct device * dev)
int
mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
{
mptscsih_shutdown(
&pdev->
dev);
mptscsih_shutdown(
p
dev);
return mpt_suspend(pdev,state);
}
...
...
This diff is collapsed.
Click to expand it.
drivers/message/fusion/mptscsih.h
View file @
adb2705a
...
...
@@ -82,7 +82,7 @@
#endif
extern
void
mptscsih_remove
(
struct
pci_dev
*
);
extern
void
mptscsih_shutdown
(
struct
dev
ice
*
);
extern
void
mptscsih_shutdown
(
struct
pci_
dev
*
);
#ifdef CONFIG_PM
extern
int
mptscsih_suspend
(
struct
pci_dev
*
pdev
,
u32
state
);
extern
int
mptscsih_resume
(
struct
pci_dev
*
pdev
);
...
...
This diff is collapsed.
Click to expand it.
drivers/message/fusion/mptspi.c
View file @
adb2705a
...
...
@@ -419,9 +419,7 @@ static struct pci_driver mptspi_driver = {
.
id_table
=
mptspi_pci_table
,
.
probe
=
mptspi_probe
,
.
remove
=
__devexit_p
(
mptscsih_remove
),
.
driver
=
{
.
shutdown
=
mptscsih_shutdown
,
},
.
shutdown
=
mptscsih_shutdown
,
#ifdef CONFIG_PM
.
suspend
=
mptscsih_suspend
,
.
resume
=
mptscsih_resume
,
...
...
This diff is collapsed.
Click to expand it.
drivers/net/e100.c
View file @
adb2705a
...
...
@@ -2447,9 +2447,8 @@ static int e100_resume(struct pci_dev *pdev)
#endif
static
void
e100_shutdown
(
struct
dev
ice
*
dev
)
static
void
e100_shutdown
(
struct
pci_
dev
*
p
dev
)
{
struct
pci_dev
*
pdev
=
container_of
(
dev
,
struct
pci_dev
,
dev
);
struct
net_device
*
netdev
=
pci_get_drvdata
(
pdev
);
struct
nic
*
nic
=
netdev_priv
(
netdev
);
...
...
@@ -2470,11 +2469,7 @@ static struct pci_driver e100_driver = {
.
suspend
=
e100_suspend
,
.
resume
=
e100_resume
,
#endif
.
driver
=
{
.
shutdown
=
e100_shutdown
,
}
.
shutdown
=
e100_shutdown
,
};
static
int
__init
e100_init_module
(
void
)
...
...
This diff is collapsed.
Click to expand it.
drivers/net/via-rhine.c
View file @
adb2705a
...
...
@@ -507,7 +507,7 @@ static struct net_device_stats *rhine_get_stats(struct net_device *dev);
static
int
netdev_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
rq
,
int
cmd
);
static
struct
ethtool_ops
netdev_ethtool_ops
;
static
int
rhine_close
(
struct
net_device
*
dev
);
static
void
rhine_shutdown
(
struct
dev
ice
*
g
dev
);
static
void
rhine_shutdown
(
struct
pci_
dev
*
p
dev
);
#define RHINE_WAIT_FOR(condition) do { \
int i=1024; \
...
...
@@ -1895,9 +1895,8 @@ static void __devexit rhine_remove_one(struct pci_dev *pdev)
pci_set_drvdata
(
pdev
,
NULL
);
}
static
void
rhine_shutdown
(
struct
device
*
gen
dev
)
static
void
rhine_shutdown
(
struct
pci_dev
*
p
dev
)
{
struct
pci_dev
*
pdev
=
to_pci_dev
(
gendev
);
struct
net_device
*
dev
=
pci_get_drvdata
(
pdev
);
struct
rhine_private
*
rp
=
netdev_priv
(
dev
);
void
__iomem
*
ioaddr
=
rp
->
base
;
...
...
@@ -1956,7 +1955,7 @@ static int rhine_suspend(struct pci_dev *pdev, pm_message_t state)
pci_save_state
(
pdev
);
spin_lock_irqsave
(
&
rp
->
lock
,
flags
);
rhine_shutdown
(
&
pdev
->
dev
);
rhine_shutdown
(
p
dev
);
spin_unlock_irqrestore
(
&
rp
->
lock
,
flags
);
free_irq
(
dev
->
irq
,
dev
);
...
...
@@ -2010,9 +2009,7 @@ static struct pci_driver rhine_driver = {
.
suspend
=
rhine_suspend
,
.
resume
=
rhine_resume
,
#endif
/* CONFIG_PM */
.
driver
=
{
.
shutdown
=
rhine_shutdown
,
}
.
shutdown
=
rhine_shutdown
,
};
...
...
This diff is collapsed.
Click to expand it.
drivers/parisc/dino.c
View file @
adb2705a
...
...
@@ -993,6 +993,7 @@ dino_driver_callback(struct parisc_device *dev)
bus
=
pci_scan_bus_parented
(
&
dev
->
dev
,
dino_current_bus
,
&
dino_cfg_ops
,
NULL
);
if
(
bus
)
{
pci_bus_add_devices
(
bus
);
/* This code *depends* on scanning being single threaded
* if it isn't, this global bus number count will fail
*/
...
...
This diff is collapsed.
Click to expand it.
drivers/parisc/lba_pci.c
View file @
adb2705a
...
...
@@ -1570,6 +1570,8 @@ lba_driver_probe(struct parisc_device *dev)
lba_bus
=
lba_dev
->
hba
.
hba_bus
=
pci_scan_bus_parented
(
&
dev
->
dev
,
lba_dev
->
hba
.
bus_num
.
start
,
cfg_ops
,
NULL
);
if
(
lba_bus
)
pci_bus_add_devices
(
lba_bus
);
/* This is in lieu of calling pci_assign_unassigned_resources() */
if
(
is_pdc_pat
())
{
...
...
This diff is collapsed.
Click to expand it.
drivers/pci/bus.c
View file @
adb2705a
...
...
@@ -121,10 +121,13 @@ void __devinit pci_bus_add_devices(struct pci_bus *bus)
* If there is an unattached subordinate bus, attach
* it and then scan for unattached PCI devices.
*/
if
(
dev
->
subordinate
&&
list_empty
(
&
dev
->
subordinate
->
node
))
{
spin_lock
(
&
pci_bus_lock
);
list_add_tail
(
&
dev
->
subordinate
->
node
,
&
dev
->
bus
->
children
);
spin_unlock
(
&
pci_bus_lock
);
if
(
dev
->
subordinate
)
{
if
(
list_empty
(
&
dev
->
subordinate
->
node
))
{
spin_lock
(
&
pci_bus_lock
);
list_add_tail
(
&
dev
->
subordinate
->
node
,
&
dev
->
bus
->
children
);
spin_unlock
(
&
pci_bus_lock
);
}
pci_bus_add_devices
(
dev
->
subordinate
);
sysfs_create_link
(
&
dev
->
subordinate
->
class_dev
.
kobj
,
&
dev
->
dev
.
kobj
,
"bridge"
);
...
...
This diff is collapsed.
Click to expand it.
drivers/pci/hotplug/Makefile
View file @
adb2705a
...
...
@@ -36,9 +36,7 @@ ibmphp-objs := ibmphp_core.o \
ibmphp_hpc.o
acpiphp-objs
:=
acpiphp_core.o
\
acpiphp_glue.o
\
acpiphp_pci.o
\
acpiphp_res.o
acpiphp_glue.o
rpaphp-objs
:=
rpaphp_core.o
\
rpaphp_pci.o
\
...
...
This diff is collapsed.
Click to expand it.
drivers/pci/hotplug/acpiphp.h
View file @
adb2705a
...
...
@@ -7,6 +7,8 @@
* Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
* Copyright (C) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com)
* Copyright (C) 2002,2003 NEC Corporation
* Copyright (C) 2003-2005 Matthew Wilcox (matthew.wilcox@hp.com)
* Copyright (C) 2003-2005 Hewlett Packard
*
* All rights reserved.
*
...
...
@@ -52,7 +54,6 @@
struct
acpiphp_bridge
;
struct
acpiphp_slot
;
struct
pci_resource
;
/*
* struct slot - slot information for each *physical* slot
...
...
@@ -65,15 +66,6 @@ struct slot {
struct
acpiphp_slot
*
acpi_slot
;
};
/*
* struct pci_resource - describes pci resource (mem, pfmem, io, bus)
*/
struct
pci_resource
{
struct
pci_resource
*
next
;
u64
base
;
u32
length
;
};
/**
* struct hpp_param - ACPI 2.0 _HPP Hot Plug Parameters
* @cache_line_size in DWORD
...
...
@@ -101,10 +93,6 @@ struct acpiphp_bridge {
int
type
;
int
nr_slots
;
u8
seg
;
u8
bus
;
u8
sub
;
u32
flags
;
/* This bus (host bridge) or Secondary bus (PCI-to-PCI bridge) */
...
...
@@ -117,12 +105,6 @@ struct acpiphp_bridge {
struct
hpp_param
hpp
;
spinlock_t
res_lock
;
/* available resources on this bus */
struct
pci_resource
*
mem_head
;
struct
pci_resource
*
p_mem_head
;
struct
pci_resource
*
io_head
;
struct
pci_resource
*
bus_head
;
};
...
...
@@ -163,12 +145,6 @@ struct acpiphp_func {
u8
function
;
/* pci function# */
u32
flags
;
/* see below */
/* resources used for this function */
struct
pci_resource
*
mem_head
;
struct
pci_resource
*
p_mem_head
;
struct
pci_resource
*
io_head
;
struct
pci_resource
*
bus_head
;
};
/**
...
...
@@ -243,25 +219,6 @@ extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot);
extern
u8
acpiphp_get_adapter_status
(
struct
acpiphp_slot
*
slot
);
extern
u32
acpiphp_get_address
(
struct
acpiphp_slot
*
slot
);
/* acpiphp_pci.c */
extern
struct
pci_dev
*
acpiphp_allocate_pcidev
(
struct
pci_bus
*
pbus
,
int
dev
,
int
fn
);
extern
int
acpiphp_configure_slot
(
struct
acpiphp_slot
*
slot
);
extern
int
acpiphp_configure_function
(
struct
acpiphp_func
*
func
);
extern
void
acpiphp_unconfigure_function
(
struct
acpiphp_func
*
func
);
extern
int
acpiphp_detect_pci_resource
(
struct
acpiphp_bridge
*
bridge
);
extern
int
acpiphp_init_func_resource
(
struct
acpiphp_func
*
func
);
/* acpiphp_res.c */
extern
struct
pci_resource
*
acpiphp_get_io_resource
(
struct
pci_resource
**
head
,
u32
size
);
extern
struct
pci_resource
*
acpiphp_get_resource
(
struct
pci_resource
**
head
,
u32
size
);
extern
struct
pci_resource
*
acpiphp_get_resource_with_base
(
struct
pci_resource
**
head
,
u64
base
,
u32
size
);
extern
int
acpiphp_resource_sort_and_combine
(
struct
pci_resource
**
head
);
extern
struct
pci_resource
*
acpiphp_make_resource
(
u64
base
,
u32
length
);
extern
void
acpiphp_move_resource
(
struct
pci_resource
**
from
,
struct
pci_resource
**
to
);
extern
void
acpiphp_free_resource
(
struct
pci_resource
**
res
);
extern
void
acpiphp_dump_resource
(
struct
acpiphp_bridge
*
bridge
);
/* debug */
extern
void
acpiphp_dump_func_resource
(
struct
acpiphp_func
*
func
);
/* debug */
/* variables */
extern
int
acpiphp_debug
;
...
...
This diff is collapsed.
Click to expand it.
drivers/pci/hotplug/acpiphp_core.c
View file @
adb2705a
...
...
@@ -7,6 +7,8 @@
* Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
* Copyright (C) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com)
* Copyright (C) 2002,2003 NEC Corporation
* Copyright (C) 2003-2005 Matthew Wilcox (matthew.wilcox@hp.com)
* Copyright (C) 2003-2005 Hewlett Packard
*
* All rights reserved.
*
...
...
@@ -53,8 +55,8 @@ int acpiphp_debug;
static
int
num_slots
;
static
struct
acpiphp_attention_info
*
attention_info
;
#define DRIVER_VERSION "0.
4
"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <gregkh@us.ibm.com>, Takayoshi Kochi <t-kochi@bq.jp.nec.com>"
#define DRIVER_VERSION "0.
5
"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <gregkh@us.ibm.com>, Takayoshi Kochi <t-kochi@bq.jp.nec.com>
, Matthew Wilcox <willy@hp.com>
"
#define DRIVER_DESC "ACPI Hot Plug PCI Controller Driver"
MODULE_AUTHOR
(
DRIVER_AUTHOR
);
...
...
@@ -281,8 +283,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
/**
* get_address - get pci address of a slot
* @hotplug_slot: slot to get status
* @busdev: pointer to struct pci_busdev (seg, bus, dev)
*
* @value: pointer to struct pci_busdev (seg, bus, dev)
*/
static
int
get_address
(
struct
hotplug_slot
*
hotplug_slot
,
u32
*
value
)
{
...
...
This diff is collapsed.
Click to expand it.
drivers/pci/hotplug/acpiphp_glue.c
View file @
adb2705a
This diff is collapsed.
Click to expand it.
drivers/pci/hotplug/acpiphp_pci.c
deleted
100644 → 0
View file @
f340c0d1
/*
* ACPI PCI HotPlug PCI configuration space management
*
* Copyright (C) 1995,2001 Compaq Computer Corporation
* Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (C) 2001,2002 IBM Corp.
* Copyright (C) 2002 Takayoshi Kochi (t-kochi@bq.jp.nec.com)
* Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
* Copyright (C) 2002 NEC Corporation
*
* 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 <t-kochi@bq.jp.nec.com>
*
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/acpi.h>
#include "../pci.h"
#include "pci_hotplug.h"
#include "acpiphp.h"
#define MY_NAME "acpiphp_pci"
/* allocate mem/pmem/io resource to a new function */
static
int
init_config_space
(
struct
acpiphp_func
*
func
)
{
u32
bar
,
len
;
u32
address
[]
=
{
PCI_BASE_ADDRESS_0
,
PCI_BASE_ADDRESS_1
,
PCI_BASE_ADDRESS_2
,
PCI_BASE_ADDRESS_3
,
PCI_BASE_ADDRESS_4
,
PCI_BASE_ADDRESS_5
,
0
};
int
count
;
struct
acpiphp_bridge
*
bridge
;
struct
pci_resource
*
res
;
struct
pci_bus
*
pbus
;
int
bus
,
device
,
function
;
unsigned
int
devfn
;
u16
tmp
;
bridge
=
func
->
slot
->
bridge
;
pbus
=
bridge
->
pci_bus
;
bus
=
bridge
->
bus
;
device
=
func
->
slot
->
device
;
function
=
func
->
function
;
devfn
=
PCI_DEVFN
(
device
,
function
);
for
(
count
=
0
;
address
[
count
];
count
++
)
{
/* for 6 BARs */
pci_bus_write_config_dword
(
pbus
,
devfn
,
address
[
count
],
0xFFFFFFFF
);
pci_bus_read_config_dword
(
pbus
,
devfn
,
address
[
count
],
&
bar
);
if
(
!
bar
)
/* This BAR is not implemented */
continue
;
dbg
(
"Device %02x.%02x BAR %d wants %x
\n
"
,
device
,
function
,
count
,
bar
);
if
(
bar
&
PCI_BASE_ADDRESS_SPACE_IO
)
{
/* This is IO */
len
=
bar
&
(
PCI_BASE_ADDRESS_IO_MASK
&
0xFFFF
);
len
=
len
&
~
(
len
-
1
);
dbg
(
"len in IO %x, BAR %d
\n
"
,
len
,
count
);
spin_lock
(
&
bridge
->
res_lock
);
res
=
acpiphp_get_io_resource
(
&
bridge
->
io_head
,
len
);
spin_unlock
(
&
bridge
->
res_lock
);
if
(
!
res
)
{
err
(
"cannot allocate requested io for %02x:%02x.%d len %x
\n
"
,
bus
,
device
,
function
,
len
);
return
-
1
;
}
pci_bus_write_config_dword
(
pbus
,
devfn
,
address
[
count
],
(
u32
)
res
->
base
);
res
->
next
=
func
->
io_head
;
func
->
io_head
=
res
;
}
else
{
/* This is Memory */
if
(
bar
&
PCI_BASE_ADDRESS_MEM_PREFETCH
)
{
/* pfmem */
len
=
bar
&
0xFFFFFFF0
;
len
=
~
len
+
1
;
dbg
(
"len in PFMEM %x, BAR %d
\n
"
,
len
,
count
);
spin_lock
(
&
bridge
->
res_lock
);
res
=
acpiphp_get_resource
(
&
bridge
->
p_mem_head
,
len
);
spin_unlock
(
&
bridge
->
res_lock
);
if
(
!
res
)
{
err
(
"cannot allocate requested pfmem for %02x:%02x.%d len %x
\n
"
,
bus
,
device
,
function
,
len
);
return
-
1
;
}
pci_bus_write_config_dword
(
pbus
,
devfn
,
address
[
count
],
(
u32
)
res
->
base
);
if
(
bar
&
PCI_BASE_ADDRESS_MEM_TYPE_64
)
{
/* takes up another dword */
dbg
(
"inside the pfmem 64 case, count %d
\n
"
,
count
);
count
+=
1
;
pci_bus_write_config_dword
(
pbus
,
devfn
,
address
[
count
],
(
u32
)(
res
->
base
>>
32
));
}
res
->
next
=
func
->
p_mem_head
;
func
->
p_mem_head
=
res
;
}
else
{
/* regular memory */
len
=
bar
&
0xFFFFFFF0
;
len
=
~
len
+
1
;
dbg
(
"len in MEM %x, BAR %d
\n
"
,
len
,
count
);
spin_lock
(
&
bridge
->
res_lock
);
res
=
acpiphp_get_resource
(
&
bridge
->
mem_head
,
len
);
spin_unlock
(
&
bridge
->
res_lock
);
if
(
!
res
)
{
err
(
"cannot allocate requested pfmem for %02x:%02x.%d len %x
\n
"
,
bus
,
device
,
function
,
len
);
return
-
1
;
}
pci_bus_write_config_dword
(
pbus
,
devfn
,
address
[
count
],
(
u32
)
res
->
base
);
if
(
bar
&
PCI_BASE_ADDRESS_MEM_TYPE_64
)
{
/* takes up another dword */
dbg
(
"inside mem 64 case, reg. mem, count %d
\n
"
,
count
);
count
+=
1
;
pci_bus_write_config_dword
(
pbus
,
devfn
,
address
[
count
],
(
u32
)(
res
->
base
>>
32
));
}
res
->
next
=
func
->
mem_head
;
func
->
mem_head
=
res
;
}
}
}
/* disable expansion rom */
pci_bus_write_config_dword
(
pbus
,
devfn
,
PCI_ROM_ADDRESS
,
0x00000000
);
/* set PCI parameters from _HPP */
pci_bus_write_config_byte
(
pbus
,
devfn
,
PCI_CACHE_LINE_SIZE
,
bridge
->
hpp
.
cache_line_size
);
pci_bus_write_config_byte
(
pbus
,
devfn
,
PCI_LATENCY_TIMER
,
bridge
->
hpp
.
latency_timer
);
pci_bus_read_config_word
(
pbus
,
devfn
,
PCI_COMMAND
,
&
tmp
);
if
(
bridge
->
hpp
.
enable_SERR
)
tmp
|=
PCI_COMMAND_SERR
;
if
(
bridge
->
hpp
.
enable_PERR
)
tmp
|=
PCI_COMMAND_PARITY
;
pci_bus_write_config_word
(
pbus
,
devfn
,
PCI_COMMAND
,
tmp
);
return
0
;
}
/* detect_used_resource - subtract resource under dev from bridge */
static
int
detect_used_resource
(
struct
acpiphp_bridge
*
bridge
,
struct
pci_dev
*
dev
)
{
int
count
;
dbg
(
"Device %s
\n
"
,
pci_name
(
dev
));
for
(
count
=
0
;
count
<
DEVICE_COUNT_RESOURCE
;
count
++
)
{
struct
pci_resource
*
res
;
struct
pci_resource
**
head
;
unsigned
long
base
=
dev
->
resource
[
count
].
start
;
unsigned
long
len
=
dev
->
resource
[
count
].
end
-
base
+
1
;
unsigned
long
flags
=
dev
->
resource
[
count
].
flags
;
if
(
!
flags
)
continue
;
dbg
(
"BAR[%d] 0x%lx - 0x%lx (0x%lx)
\n
"
,
count
,
base
,
base
+
len
-
1
,
flags
);
if
(
flags
&
IORESOURCE_IO
)
{
head
=
&
bridge
->
io_head
;
}
else
if
(
flags
&
IORESOURCE_PREFETCH
)
{
head
=
&
bridge
->
p_mem_head
;
}
else
{
head
=
&
bridge
->
mem_head
;
}
spin_lock
(
&
bridge
->
res_lock
);
res
=
acpiphp_get_resource_with_base
(
head
,
base
,
len
);
spin_unlock
(
&
bridge
->
res_lock
);
if
(
res
)
kfree
(
res
);
}
return
0
;
}
/**
* acpiphp_detect_pci_resource - detect resources under bridge
* @bridge: detect all resources already used under this bridge
*
* collect all resources already allocated for all devices under a bridge.
*/
int
acpiphp_detect_pci_resource
(
struct
acpiphp_bridge
*
bridge
)
{
struct
list_head
*
l
;
struct
pci_dev
*
dev
;
list_for_each
(
l
,
&
bridge
->
pci_bus
->
devices
)
{
dev
=
pci_dev_b
(
l
);
detect_used_resource
(
bridge
,
dev
);
}
return
0
;
}
/**
* acpiphp_init_slot_resource - gather resource usage information of a slot
* @slot: ACPI slot object to be checked, should have valid pci_dev member
*
* TBD: PCI-to-PCI bridge case
* use pci_dev->resource[]
*/
int
acpiphp_init_func_resource
(
struct
acpiphp_func
*
func
)
{
u64
base
;
u32
bar
,
len
;
u32
address
[]
=
{
PCI_BASE_ADDRESS_0
,
PCI_BASE_ADDRESS_1
,
PCI_BASE_ADDRESS_2
,
PCI_BASE_ADDRESS_3
,
PCI_BASE_ADDRESS_4
,
PCI_BASE_ADDRESS_5
,
0
};
int
count
;
struct
pci_resource
*
res
;
struct
pci_dev
*
dev
;
dev
=
func
->
pci_dev
;
dbg
(
"Hot-pluggable device %s
\n
"
,
pci_name
(
dev
));
for
(
count
=
0
;
address
[
count
];
count
++
)
{
/* for 6 BARs */
pci_read_config_dword
(
dev
,
address
[
count
],
&
bar
);
if
(
!
bar
)
/* This BAR is not implemented */
continue
;
pci_write_config_dword
(
dev
,
address
[
count
],
0xFFFFFFFF
);
pci_read_config_dword
(
dev
,
address
[
count
],
&
len
);
if
(
len
&
PCI_BASE_ADDRESS_SPACE_IO
)
{
/* This is IO */
base
=
bar
&
0xFFFFFFFC
;
len
=
len
&
(
PCI_BASE_ADDRESS_IO_MASK
&
0xFFFF
);
len
=
len
&
~
(
len
-
1
);
dbg
(
"BAR[%d] %08x - %08x (IO)
\n
"
,
count
,
(
u32
)
base
,
(
u32
)
base
+
len
-
1
);
res
=
acpiphp_make_resource
(
base
,
len
);
if
(
!
res
)
goto
no_memory
;
res
->
next
=
func
->
io_head
;
func
->
io_head
=
res
;
}
else
{
/* This is Memory */
base
=
bar
&
0xFFFFFFF0
;
if
(
len
&
PCI_BASE_ADDRESS_MEM_PREFETCH
)
{
/* pfmem */
len
&=
0xFFFFFFF0
;
len
=
~
len
+
1
;
if
(
len
&
PCI_BASE_ADDRESS_MEM_TYPE_64
)
{
/* takes up another dword */
dbg
(
"prefetch mem 64
\n
"
);
count
+=
1
;
}
dbg
(
"BAR[%d] %08x - %08x (PMEM)
\n
"
,
count
,
(
u32
)
base
,
(
u32
)
base
+
len
-
1
);
res
=
acpiphp_make_resource
(
base
,
len
);
if
(
!
res
)
goto
no_memory
;
res
->
next
=
func
->
p_mem_head
;
func
->
p_mem_head
=
res
;
}
else
{
/* regular memory */
len
&=
0xFFFFFFF0
;
len
=
~
len
+
1
;
if
(
len
&
PCI_BASE_ADDRESS_MEM_TYPE_64
)
{
/* takes up another dword */
dbg
(
"mem 64
\n
"
);
count
+=
1
;
}
dbg
(
"BAR[%d] %08x - %08x (MEM)
\n
"
,
count
,
(
u32
)
base
,
(
u32
)
base
+
len
-
1
);
res
=
acpiphp_make_resource
(
base
,
len
);
if
(
!
res
)
goto
no_memory
;
res
->
next
=
func
->
mem_head
;
func
->
mem_head
=
res
;
}
}
pci_write_config_dword
(
dev
,
address
[
count
],
bar
);
}
#if 1
acpiphp_dump_func_resource
(
func
);
#endif
return
0
;
no_memory:
err
(
"out of memory
\n
"
);
acpiphp_free_resource
(
&
func
->
io_head
);
acpiphp_free_resource
(
&
func
->
mem_head
);
acpiphp_free_resource
(
&
func
->
p_mem_head
);
return
-
1
;
}
/**
* acpiphp_configure_slot - allocate PCI resources
* @slot: slot to be configured
*
* initializes a PCI functions on a device inserted
* into the slot
*
*/
int
acpiphp_configure_slot
(
struct
acpiphp_slot
*
slot
)
{
struct
acpiphp_func
*
func
;
struct
list_head
*
l
;
u8
hdr
;
u32
dvid
;
int
retval
=
0
;
int
is_multi
=
0
;
pci_bus_read_config_byte
(
slot
->
bridge
->
pci_bus
,
PCI_DEVFN
(
slot
->
device
,
0
),
PCI_HEADER_TYPE
,
&
hdr
);
if
(
hdr
&
0x80
)
is_multi
=
1
;
list_for_each
(
l
,
&
slot
->
funcs
)
{
func
=
list_entry
(
l
,
struct
acpiphp_func
,
sibling
);
if
(
is_multi
||
func
->
function
==
0
)
{
pci_bus_read_config_dword
(
slot
->
bridge
->
pci_bus
,
PCI_DEVFN
(
slot
->
device
,
func
->
function
),
PCI_VENDOR_ID
,
&
dvid
);
if
(
dvid
!=
0xffffffff
)
{
retval
=
init_config_space
(
func
);
if
(
retval
)
break
;
}
}
}
return
retval
;
}
/**
* acpiphp_configure_function - configure PCI function
* @func: function to be configured
*
* initializes a PCI functions on a device inserted
* into the slot
*
*/
int
acpiphp_configure_function
(
struct
acpiphp_func
*
func
)
{
/* all handled by the pci core now */
return
0
;
}
/**
* acpiphp_unconfigure_function - unconfigure PCI function
* @func: function to be unconfigured
*
*/
void
acpiphp_unconfigure_function
(
struct
acpiphp_func
*
func
)
{
struct
acpiphp_bridge
*
bridge
;
/* if pci_dev is NULL, ignore it */
if
(
!
func
->
pci_dev
)
return
;
pci_remove_bus_device
(
func
->
pci_dev
);
/* free all resources */
bridge
=
func
->
slot
->
bridge
;
spin_lock
(
&
bridge
->
res_lock
);
acpiphp_move_resource
(
&
func
->
io_head
,
&
bridge
->
io_head
);
acpiphp_move_resource
(
&
func
->
mem_head
,
&
bridge
->
mem_head
);
acpiphp_move_resource
(
&
func
->
p_mem_head
,
&
bridge
->
p_mem_head
);
acpiphp_move_resource
(
&
func
->
bus_head
,
&
bridge
->
bus_head
);
spin_unlock
(
&
bridge
->
res_lock
);
}
This diff is collapsed.
Click to expand it.
drivers/pci/hotplug/acpiphp_res.c
deleted
100644 → 0
View file @
f340c0d1
/*
* ACPI PCI HotPlug Utility functions
*
* Copyright (C) 1995,2001 Compaq Computer Corporation
* Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (C) 2001 IBM Corp.
* Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
* Copyright (C) 2002 Takayoshi Kochi (t-kochi@bq.jp.nec.com)
* Copyright (C) 2002 NEC Corporation
*
* 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 <gregkh@us.ibm.com>, <t-kochi@bq.jp.nec.com>
*
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/sysctl.h>
#include <linux/pci.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/timer.h>
#include <linux/ioctl.h>
#include <linux/fcntl.h>
#include <linux/list.h>
#include "pci_hotplug.h"
#include "acpiphp.h"
#define MY_NAME "acpiphp_res"
/*
* sort_by_size - sort nodes by their length, smallest first
*/
static
int
sort_by_size
(
struct
pci_resource
**
head
)
{
struct
pci_resource
*
current_res
;
struct
pci_resource
*
next_res
;
int
out_of_order
=
1
;
if
(
!
(
*
head
))
return
1
;
if
(
!
((
*
head
)
->
next
))
return
0
;
while
(
out_of_order
)
{
out_of_order
=
0
;
/* Special case for swapping list head */
if
(((
*
head
)
->
next
)
&&
((
*
head
)
->
length
>
(
*
head
)
->
next
->
length
))
{
out_of_order
++
;
current_res
=
*
head
;
*
head
=
(
*
head
)
->
next
;
current_res
->
next
=
(
*
head
)
->
next
;
(
*
head
)
->
next
=
current_res
;
}
current_res
=
*
head
;
while
(
current_res
->
next
&&
current_res
->
next
->
next
)
{
if
(
current_res
->
next
->
length
>
current_res
->
next
->
next
->
length
)
{
out_of_order
++
;
next_res
=
current_res
->
next
;
current_res
->
next
=
current_res
->
next
->
next
;
current_res
=
current_res
->
next
;
next_res
->
next
=
current_res
->
next
;
current_res
->
next
=
next_res
;
}
else
current_res
=
current_res
->
next
;
}
}
/* End of out_of_order loop */
return
0
;
}
#if 0
/*
* sort_by_max_size - sort nodes by their length, largest first
*/
static int sort_by_max_size(struct pci_resource **head)
{
struct pci_resource *current_res;
struct pci_resource *next_res;
int out_of_order = 1;
if (!(*head))
return 1;
if (!((*head)->next))
return 0;
while (out_of_order) {
out_of_order = 0;
/* Special case for swapping list head */
if (((*head)->next) &&
((*head)->length < (*head)->next->length)) {
out_of_order++;
current_res = *head;
*head = (*head)->next;
current_res->next = (*head)->next;
(*head)->next = current_res;
}
current_res = *head;
while (current_res->next && current_res->next->next) {
if (current_res->next->length < current_res->next->next->length) {
out_of_order++;
next_res = current_res->next;
current_res->next = current_res->next->next;
current_res = current_res->next;
next_res->next = current_res->next;
current_res->next = next_res;
} else
current_res = current_res->next;
}
} /* End of out_of_order loop */
return 0;
}
#endif
/**
* get_io_resource - get resource for I/O ports
*
* this function sorts the resource list by size and then
* returns the first node of "size" length that is not in the
* ISA aliasing window. If it finds a node larger than "size"
* it will split it up.
*
* size must be a power of two.
*
* difference from get_resource is handling of ISA aliasing space.
*
*/
struct
pci_resource
*
acpiphp_get_io_resource
(
struct
pci_resource
**
head
,
u32
size
)
{
struct
pci_resource
*
prevnode
;
struct
pci_resource
*
node
;
struct
pci_resource
*
split_node
;
u64
temp_qword
;
if
(
!
(
*
head
))
return
NULL
;
if
(
acpiphp_resource_sort_and_combine
(
head
))
return
NULL
;
if
(
sort_by_size
(
head
))
return
NULL
;
for
(
node
=
*
head
;
node
;
node
=
node
->
next
)
{
if
(
node
->
length
<
size
)
continue
;
if
(
node
->
base
&
(
size
-
1
))
{
/* this one isn't base aligned properly
so we'll make a new entry and split it up */
temp_qword
=
(
node
->
base
|
(
size
-
1
))
+
1
;
/* Short circuit if adjusted size is too small */
if
((
node
->
length
-
(
temp_qword
-
node
->
base
))
<
size
)
continue
;
split_node
=
acpiphp_make_resource
(
node
->
base
,
temp_qword
-
node
->
base
);
if
(
!
split_node
)
return
NULL
;
node
->
base
=
temp_qword
;
node
->
length
-=
split_node
->
length
;
/* Put it in the list */
split_node
->
next
=
node
->
next
;
node
->
next
=
split_node
;
}
/* End of non-aligned base */
/* Don't need to check if too small since we already did */
if
(
node
->
length
>
size
)
{
/* this one is longer than we need
so we'll make a new entry and split it up */
split_node
=
acpiphp_make_resource
(
node
->
base
+
size
,
node
->
length
-
size
);
if
(
!
split_node
)
return
NULL
;
node
->
length
=
size
;
/* Put it in the list */
split_node
->
next
=
node
->
next
;
node
->
next
=
split_node
;
}
/* End of too big on top end */
/* For IO make sure it's not in the ISA aliasing space */
if
((
node
->
base
&
0x300L
)
&&
!
(
node
->
base
&
0xfffff000
))
continue
;
/* If we got here, then it is the right size
Now take it out of the list */
if
(
*
head
==
node
)
{
*
head
=
node
->
next
;
}
else
{
prevnode
=
*
head
;
while
(
prevnode
->
next
!=
node
)
prevnode
=
prevnode
->
next
;
prevnode
->
next
=
node
->
next
;
}
node
->
next
=
NULL
;
/* Stop looping */
break
;
}
return
node
;
}
#if 0
/**
* get_max_resource - get the largest resource
*
* Gets the largest node that is at least "size" big from the
* list pointed to by head. It aligns the node on top and bottom
* to "size" alignment before returning it.
*/
static struct pci_resource *acpiphp_get_max_resource (struct pci_resource **head, u32 size)
{
struct pci_resource *max;
struct pci_resource *temp;
struct pci_resource *split_node;
u64 temp_qword;
if (!(*head))
return NULL;
if (acpiphp_resource_sort_and_combine(head))
return NULL;
if (sort_by_max_size(head))
return NULL;
for (max = *head;max; max = max->next) {
/* If not big enough we could probably just bail,
instead we'll continue to the next. */
if (max->length < size)
continue;
if (max->base & (size - 1)) {
/* this one isn't base aligned properly
so we'll make a new entry and split it up */
temp_qword = (max->base | (size-1)) + 1;
/* Short circuit if adjusted size is too small */
if ((max->length - (temp_qword - max->base)) < size)
continue;
split_node = acpiphp_make_resource(max->base, temp_qword - max->base);
if (!split_node)
return NULL;
max->base = temp_qword;
max->length -= split_node->length;
/* Put it next in the list */
split_node->next = max->next;
max->next = split_node;
}
if ((max->base + max->length) & (size - 1)) {
/* this one isn't end aligned properly at the top
so we'll make a new entry and split it up */
temp_qword = ((max->base + max->length) & ~(size - 1));
split_node = acpiphp_make_resource(temp_qword,
max->length + max->base - temp_qword);
if (!split_node)
return NULL;
max->length -= split_node->length;
/* Put it in the list */
split_node->next = max->next;
max->next = split_node;
}
/* Make sure it didn't shrink too much when we aligned it */
if (max->length < size)
continue;
/* Now take it out of the list */
temp = (struct pci_resource*) *head;
if (temp == max) {
*head = max->next;
} else {
while (temp && temp->next != max) {
temp = temp->next;
}
temp->next = max->next;
}
max->next = NULL;
return max;
}
/* If we get here, we couldn't find one */
return NULL;
}
#endif
/**
* get_resource - get resource (mem, pfmem)
*
* this function sorts the resource list by size and then
* returns the first node of "size" length. If it finds a node
* larger than "size" it will split it up.
*
* size must be a power of two.
*
*/
struct
pci_resource
*
acpiphp_get_resource
(
struct
pci_resource
**
head
,
u32
size
)
{
struct
pci_resource
*
prevnode
;
struct
pci_resource
*
node
;
struct
pci_resource
*
split_node
;
u64
temp_qword
;
if
(
!
(
*
head
))
return
NULL
;
if
(
acpiphp_resource_sort_and_combine
(
head
))
return
NULL
;
if
(
sort_by_size
(
head
))
return
NULL
;
for
(
node
=
*
head
;
node
;
node
=
node
->
next
)
{
dbg
(
"%s: req_size =%x node=%p, base=%x, length=%x
\n
"
,
__FUNCTION__
,
size
,
node
,
(
u32
)
node
->
base
,
node
->
length
);
if
(
node
->
length
<
size
)
continue
;
if
(
node
->
base
&
(
size
-
1
))
{
dbg
(
"%s: not aligned
\n
"
,
__FUNCTION__
);
/* this one isn't base aligned properly
so we'll make a new entry and split it up */
temp_qword
=
(
node
->
base
|
(
size
-
1
))
+
1
;
/* Short circuit if adjusted size is too small */
if
((
node
->
length
-
(
temp_qword
-
node
->
base
))
<
size
)
continue
;
split_node
=
acpiphp_make_resource
(
node
->
base
,
temp_qword
-
node
->
base
);
if
(
!
split_node
)
return
NULL
;
node
->
base
=
temp_qword
;
node
->
length
-=
split_node
->
length
;
/* Put it in the list */
split_node
->
next
=
node
->
next
;
node
->
next
=
split_node
;
}
/* End of non-aligned base */
/* Don't need to check if too small since we already did */
if
(
node
->
length
>
size
)
{
dbg
(
"%s: too big
\n
"
,
__FUNCTION__
);
/* this one is longer than we need
so we'll make a new entry and split it up */
split_node
=
acpiphp_make_resource
(
node
->
base
+
size
,
node
->
length
-
size
);
if
(
!
split_node
)
return
NULL
;
node
->
length
=
size
;
/* Put it in the list */
split_node
->
next
=
node
->
next
;
node
->
next
=
split_node
;
}
/* End of too big on top end */
dbg
(
"%s: got one!!!
\n
"
,
__FUNCTION__
);
/* If we got here, then it is the right size
Now take it out of the list */
if
(
*
head
==
node
)
{
*
head
=
node
->
next
;
}
else
{
prevnode
=
*
head
;
while
(
prevnode
->
next
!=
node
)
prevnode
=
prevnode
->
next
;
prevnode
->
next
=
node
->
next
;
}
node
->
next
=
NULL
;
/* Stop looping */
break
;
}
return
node
;
}
/**
* get_resource_with_base - get resource with specific base address
*
* this function
* returns the first node of "size" length located at specified base address.
* If it finds a node larger than "size" it will split it up.
*
* size must be a power of two.
*
*/
struct
pci_resource
*
acpiphp_get_resource_with_base
(
struct
pci_resource
**
head
,
u64
base
,
u32
size
)
{
struct
pci_resource
*
prevnode
;
struct
pci_resource
*
node
;
struct
pci_resource
*
split_node
;
u64
temp_qword
;
if
(
!
(
*
head
))
return
NULL
;
if
(
acpiphp_resource_sort_and_combine
(
head
))
return
NULL
;
for
(
node
=
*
head
;
node
;
node
=
node
->
next
)
{
dbg
(
": 1st req_base=%x req_size =%x node=%p, base=%x, length=%x
\n
"
,
(
u32
)
base
,
size
,
node
,
(
u32
)
node
->
base
,
node
->
length
);
if
(
node
->
base
>
base
)
continue
;
if
((
node
->
base
+
node
->
length
)
<
(
base
+
size
))
continue
;
if
(
node
->
base
<
base
)
{
dbg
(
": split 1
\n
"
);
/* this one isn't base aligned properly
so we'll make a new entry and split it up */
temp_qword
=
base
;
/* Short circuit if adjusted size is too small */
if
((
node
->
length
-
(
temp_qword
-
node
->
base
))
<
size
)
continue
;
split_node
=
acpiphp_make_resource
(
node
->
base
,
temp_qword
-
node
->
base
);
if
(
!
split_node
)
return
NULL
;
node
->
base
=
temp_qword
;
node
->
length
-=
split_node
->
length
;
/* Put it in the list */
split_node
->
next
=
node
->
next
;
node
->
next
=
split_node
;
}
dbg
(
": 2nd req_base=%x req_size =%x node=%p, base=%x, length=%x
\n
"
,
(
u32
)
base
,
size
,
node
,
(
u32
)
node
->
base
,
node
->
length
);
/* Don't need to check if too small since we already did */
if
(
node
->
length
>
size
)
{
dbg
(
": split 2
\n
"
);
/* this one is longer than we need
so we'll make a new entry and split it up */
split_node
=
acpiphp_make_resource
(
node
->
base
+
size
,
node
->
length
-
size
);
if
(
!
split_node
)
return
NULL
;
node
->
length
=
size
;
/* Put it in the list */
split_node
->
next
=
node
->
next
;
node
->
next
=
split_node
;
}
/* End of too big on top end */
dbg
(
": got one!!!
\n
"
);
/* If we got here, then it is the right size
Now take it out of the list */
if
(
*
head
==
node
)
{
*
head
=
node
->
next
;
}
else
{
prevnode
=
*
head
;
while
(
prevnode
->
next
!=
node
)
prevnode
=
prevnode
->
next
;
prevnode
->
next
=
node
->
next
;
}
node
->
next
=
NULL
;
/* Stop looping */
break
;
}
return
node
;
}
/**
* acpiphp_resource_sort_and_combine
*
* Sorts all of the nodes in the list in ascending order by
* their base addresses. Also does garbage collection by
* combining adjacent nodes.
*
* returns 0 if success
*/
int
acpiphp_resource_sort_and_combine
(
struct
pci_resource
**
head
)
{
struct
pci_resource
*
node1
;
struct
pci_resource
*
node2
;
int
out_of_order
=
1
;
if
(
!
(
*
head
))
return
1
;
dbg
(
"*head->next = %p
\n
"
,(
*
head
)
->
next
);
if
(
!
(
*
head
)
->
next
)
return
0
;
/* only one item on the list, already sorted! */
dbg
(
"*head->base = 0x%x
\n
"
,(
u32
)(
*
head
)
->
base
);
dbg
(
"*head->next->base = 0x%x
\n
"
,
(
u32
)(
*
head
)
->
next
->
base
);
while
(
out_of_order
)
{
out_of_order
=
0
;
/* Special case for swapping list head */
if
(((
*
head
)
->
next
)
&&
((
*
head
)
->
base
>
(
*
head
)
->
next
->
base
))
{
node1
=
*
head
;
(
*
head
)
=
(
*
head
)
->
next
;
node1
->
next
=
(
*
head
)
->
next
;
(
*
head
)
->
next
=
node1
;
out_of_order
++
;
}
node1
=
(
*
head
);
while
(
node1
->
next
&&
node1
->
next
->
next
)
{
if
(
node1
->
next
->
base
>
node1
->
next
->
next
->
base
)
{
out_of_order
++
;
node2
=
node1
->
next
;
node1
->
next
=
node1
->
next
->
next
;
node1
=
node1
->
next
;
node2
->
next
=
node1
->
next
;
node1
->
next
=
node2
;
}
else
node1
=
node1
->
next
;
}
}
/* End of out_of_order loop */
node1
=
*
head
;
while
(
node1
&&
node1
->
next
)
{
if
((
node1
->
base
+
node1
->
length
)
==
node1
->
next
->
base
)
{
/* Combine */
dbg
(
"8..
\n
"
);
node1
->
length
+=
node1
->
next
->
length
;
node2
=
node1
->
next
;
node1
->
next
=
node1
->
next
->
next
;
kfree
(
node2
);
}
else
node1
=
node1
->
next
;
}
return
0
;
}
/**
* acpiphp_make_resource - make resource structure
* @base: base address of a resource
* @length: length of a resource
*/
struct
pci_resource
*
acpiphp_make_resource
(
u64
base
,
u32
length
)
{
struct
pci_resource
*
res
;
res
=
kmalloc
(
sizeof
(
struct
pci_resource
),
GFP_KERNEL
);
if
(
res
)
{
memset
(
res
,
0
,
sizeof
(
struct
pci_resource
));
res
->
base
=
base
;
res
->
length
=
length
;
}
return
res
;
}
/**
* acpiphp_move_resource - move linked resources from one to another
* @from: head of linked resource list
* @to: head of linked resource list
*/
void
acpiphp_move_resource
(
struct
pci_resource
**
from
,
struct
pci_resource
**
to
)
{
struct
pci_resource
*
tmp
;
while
(
*
from
)
{
tmp
=
(
*
from
)
->
next
;
(
*
from
)
->
next
=
*
to
;
*
to
=
*
from
;
*
from
=
tmp
;
}
/* *from = NULL is guaranteed */
}
/**
* acpiphp_free_resource - free all linked resources
* @res: head of linked resource list
*/
void
acpiphp_free_resource
(
struct
pci_resource
**
res
)
{
struct
pci_resource
*
tmp
;
while
(
*
res
)
{
tmp
=
(
*
res
)
->
next
;
kfree
(
*
res
);
*
res
=
tmp
;
}
/* *res = NULL is guaranteed */
}
/* debug support functions; will go away sometime :) */
static
void
dump_resource
(
struct
pci_resource
*
head
)
{
struct
pci_resource
*
p
;
int
cnt
;
p
=
head
;
cnt
=
0
;
while
(
p
)
{
dbg
(
"[%02d] %08x - %08x
\n
"
,
cnt
++
,
(
u32
)
p
->
base
,
(
u32
)
p
->
base
+
p
->
length
-
1
);
p
=
p
->
next
;
}
}
void
acpiphp_dump_resource
(
struct
acpiphp_bridge
*
bridge
)
{
dbg
(
"I/O resource:
\n
"
);
dump_resource
(
bridge
->
io_head
);
dbg
(
"MEM resource:
\n
"
);
dump_resource
(
bridge
->
mem_head
);
dbg
(
"PMEM resource:
\n
"
);
dump_resource
(
bridge
->
p_mem_head
);
dbg
(
"BUS resource:
\n
"
);
dump_resource
(
bridge
->
bus_head
);
}
void
acpiphp_dump_func_resource
(
struct
acpiphp_func
*
func
)
{
dbg
(
"I/O resource:
\n
"
);
dump_resource
(
func
->
io_head
);
dbg
(
"MEM resource:
\n
"
);
dump_resource
(
func
->
mem_head
);
dbg
(
"PMEM resource:
\n
"
);
dump_resource
(
func
->
p_mem_head
);
dbg
(
"BUS resource:
\n
"
);
dump_resource
(
func
->
bus_head
);
}
This diff is collapsed.
Click to expand it.
drivers/pci/hotplug/cpqphp_core.c
View file @
adb2705a
...
...
@@ -60,6 +60,7 @@ static void __iomem *smbios_start;
static
void
__iomem
*
cpqhp_rom_start
;
static
int
power_mode
;
static
int
debug
;
static
int
initialized
;
#define DRIVER_VERSION "0.9.8"
#define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>"
...
...
@@ -1271,7 +1272,6 @@ static int one_time_init(void)
{
int
loop
;
int
retval
=
0
;
static
int
initialized
=
0
;
if
(
initialized
)
return
0
;
...
...
@@ -1441,7 +1441,8 @@ static void __exit unload_cpqphpd(void)
}
// Stop the notification mechanism
cpqhp_event_stop_thread
();
if
(
initialized
)
cpqhp_event_stop_thread
();
//unmap the rom address
if
(
cpqhp_rom_start
)
...
...
This diff is collapsed.
Click to expand it.
drivers/pci/msi.c
View file @
adb2705a
...
...
@@ -28,10 +28,10 @@ static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL };
static
kmem_cache_t
*
msi_cachep
;
static
int
pci_msi_enable
=
1
;
static
int
last_alloc_vector
=
0
;
static
int
nr_released_vectors
=
0
;
static
int
last_alloc_vector
;
static
int
nr_released_vectors
;
static
int
nr_reserved_vectors
=
NR_HP_RESERVED_VECTORS
;
static
int
nr_msix_devices
=
0
;
static
int
nr_msix_devices
;
#ifndef CONFIG_X86_IO_APIC
int
vector_irq
[
NR_VECTORS
]
=
{
[
0
...
NR_VECTORS
-
1
]
=
-
1
};
...
...
@@ -170,44 +170,30 @@ static unsigned int startup_msi_irq_wo_maskbit(unsigned int vector)
return
0
;
/* never anything pending */
}
static
void
release_msi
(
unsigned
int
vector
);
static
void
shutdown_msi_irq
(
unsigned
int
vector
)
{
release_msi
(
vector
);
}
#define shutdown_msi_irq_wo_maskbit shutdown_msi_irq
static
void
enable_msi_irq_wo_maskbit
(
unsigned
int
vector
)
{}
static
void
disable_msi_irq_wo_maskbit
(
unsigned
int
vector
)
{}
static
void
ack_msi_irq_wo_maskbit
(
unsigned
int
vector
)
{}
static
void
end_msi_irq_wo_maskbit
(
unsigned
int
vector
)
static
unsigned
int
startup_msi_irq_w_maskbit
(
unsigned
int
vector
)
{
move_msi
(
vector
);
ack_APIC_irq
();
startup_msi_irq_wo_maskbit
(
vector
);
unmask_MSI_irq
(
vector
);
return
0
;
/* never anything pending */
}
static
unsigned
int
startup_msi_irq_w_maskbit
(
unsigned
int
vector
)
static
void
shutdown_msi_irq
(
unsigned
int
vector
)
{
struct
msi_desc
*
entry
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
msi_lock
,
flags
);
entry
=
msi_desc
[
vector
];
if
(
!
entry
||
!
entry
->
dev
)
{
spin_unlock_irqrestore
(
&
msi_lock
,
flags
);
return
0
;
}
entry
->
msi_attrib
.
state
=
1
;
/* Mark it active */
if
(
entry
&&
entry
->
dev
)
entry
->
msi_attrib
.
state
=
0
;
/* Mark it not active */
spin_unlock_irqrestore
(
&
msi_lock
,
flags
);
unmask_MSI_irq
(
vector
);
return
0
;
/* never anything pending */
}
#define shutdown_msi_irq_w_maskbit shutdown_msi_irq
#define enable_msi_irq_w_maskbit unmask_MSI_irq
#define disable_msi_irq_w_maskbit mask_MSI_irq
#define ack_msi_irq_w_maskbit mask_MSI_irq
static
void
end_msi_irq_wo_maskbit
(
unsigned
int
vector
)
{
move_msi
(
vector
);
ack_APIC_irq
();
}
static
void
end_msi_irq_w_maskbit
(
unsigned
int
vector
)
{
...
...
@@ -216,6 +202,10 @@ static void end_msi_irq_w_maskbit(unsigned int vector)
ack_APIC_irq
();
}
static
void
do_nothing
(
unsigned
int
vector
)
{
}
/*
* Interrupt Type for MSI-X PCI/PCI-X/PCI-Express Devices,
* which implement the MSI-X Capability Structure.
...
...
@@ -223,10 +213,10 @@ static void end_msi_irq_w_maskbit(unsigned int vector)
static
struct
hw_interrupt_type
msix_irq_type
=
{
.
typename
=
"PCI-MSI-X"
,
.
startup
=
startup_msi_irq_w_maskbit
,
.
shutdown
=
shutdown_msi_irq
_w_maskbit
,
.
enable
=
enable_msi_irq_w_maskbit
,
.
disable
=
disable_msi_irq_w_maskbit
,
.
ack
=
ack_msi_irq_w_maskbit
,
.
shutdown
=
shutdown_msi_irq
,
.
enable
=
unmask_MSI_irq
,
.
disable
=
mask_MSI_irq
,
.
ack
=
mask_MSI_irq
,
.
end
=
end_msi_irq_w_maskbit
,
.
set_affinity
=
set_msi_irq_affinity
};
...
...
@@ -239,10 +229,10 @@ static struct hw_interrupt_type msix_irq_type = {
static
struct
hw_interrupt_type
msi_irq_w_maskbit_type
=
{
.
typename
=
"PCI-MSI"
,
.
startup
=
startup_msi_irq_w_maskbit
,
.
shutdown
=
shutdown_msi_irq
_w_maskbit
,
.
enable
=
enable_msi_irq_w_maskbit
,
.
disable
=
disable_msi_irq_w_maskbit
,
.
ack
=
ack_msi_irq_w_maskbit
,
.
shutdown
=
shutdown_msi_irq
,
.
enable
=
unmask_MSI_irq
,
.
disable
=
mask_MSI_irq
,
.
ack
=
mask_MSI_irq
,
.
end
=
end_msi_irq_w_maskbit
,
.
set_affinity
=
set_msi_irq_affinity
};
...
...
@@ -255,10 +245,10 @@ static struct hw_interrupt_type msi_irq_w_maskbit_type = {
static
struct
hw_interrupt_type
msi_irq_wo_maskbit_type
=
{
.
typename
=
"PCI-MSI"
,
.
startup
=
startup_msi_irq_wo_maskbit
,
.
shutdown
=
shutdown_msi_irq
_wo_maskbit
,
.
enable
=
enable_msi_irq_wo_maskbit
,
.
disable
=
d
isable_msi_irq_wo_maskbit
,
.
ack
=
ack_msi_irq_wo_maskbit
,
.
shutdown
=
shutdown_msi_irq
,
.
enable
=
do_nothing
,
.
disable
=
d
o_nothing
,
.
ack
=
do_nothing
,
.
end
=
end_msi_irq_wo_maskbit
,
.
set_affinity
=
set_msi_irq_affinity
};
...
...
@@ -407,7 +397,7 @@ static struct msi_desc* alloc_msi_entry(void)
{
struct
msi_desc
*
entry
;
entry
=
(
struct
msi_desc
*
)
kmem_cache_alloc
(
msi_cachep
,
SLAB_KERNEL
);
entry
=
kmem_cache_alloc
(
msi_cachep
,
SLAB_KERNEL
);
if
(
!
entry
)
return
NULL
;
...
...
@@ -796,18 +786,6 @@ void pci_disable_msi(struct pci_dev* dev)
}
}
static
void
release_msi
(
unsigned
int
vector
)
{
struct
msi_desc
*
entry
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
msi_lock
,
flags
);
entry
=
msi_desc
[
vector
];
if
(
entry
&&
entry
->
dev
)
entry
->
msi_attrib
.
state
=
0
;
/* Mark it not active */
spin_unlock_irqrestore
(
&
msi_lock
,
flags
);
}
static
int
msi_free_vector
(
struct
pci_dev
*
dev
,
int
vector
,
int
reassign
)
{
struct
msi_desc
*
entry
;
...
...
@@ -924,7 +902,7 @@ static int reroute_msix_table(int head, struct msix_entry *entries, int *nvec)
/**
* pci_enable_msix - configure device's MSI-X capability structure
* @dev: pointer to the pci_dev data structure of MSI-X device function
* @
data
: pointer to an array of MSI-X entries
* @
entries
: pointer to an array of MSI-X entries
* @nvec: number of MSI-X vectors requested for allocation by device driver
*
* Setup the MSI-X capability structure of device function with the number
...
...
This diff is collapsed.
Click to expand it.
drivers/pci/msi.h
View file @
adb2705a
...
...
@@ -41,11 +41,11 @@ static inline void move_msi(int vector) {}
#define PCI_MSIX_FLAGS_BIRMASK (7 << 0)
#define PCI_MSIX_FLAGS_BITMASK (1 << 0)
#define PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET 0
#define PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET 4
#define PCI_MSIX_ENTRY_DATA_OFFSET 8
#define PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET 12
#define PCI_MSIX_ENTRY_SIZE 16
#define PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET 0
#define PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET 4
#define PCI_MSIX_ENTRY_DATA_OFFSET 8
#define PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET 12
#define msi_control_reg(base) (base + PCI_MSI_FLAGS)
#define msi_lower_address_reg(base) (base + PCI_MSI_ADDRESS_LO)
...
...
@@ -64,7 +64,6 @@ static inline void move_msi(int vector) {}
#define msi_enable(control, num) multi_msi_enable(control, num); \
control |= PCI_MSI_FLAGS_ENABLE
#define msix_control_reg msi_control_reg
#define msix_table_offset_reg(base) (base + 0x04)
#define msix_pba_offset_reg(base) (base + 0x08)
#define msix_enable(control) control |= PCI_MSIX_FLAGS_ENABLE
...
...
This diff is collapsed.
Click to expand it.
drivers/pci/pci-sysfs.c
View file @
adb2705a
...
...
@@ -60,15 +60,18 @@ resource_show(struct device * dev, struct device_attribute *attr, char * buf)
char
*
str
=
buf
;
int
i
;
int
max
=
7
;
u64
start
,
end
;
if
(
pci_dev
->
subordinate
)
max
=
DEVICE_COUNT_RESOURCE
;
for
(
i
=
0
;
i
<
max
;
i
++
)
{
str
+=
sprintf
(
str
,
"0x%016lx 0x%016lx 0x%016lx
\n
"
,
pci_resource_start
(
pci_dev
,
i
),
pci_resource_end
(
pci_dev
,
i
),
pci_resource_flags
(
pci_dev
,
i
));
struct
resource
*
res
=
&
pci_dev
->
resource
[
i
];
pci_resource_to_user
(
pci_dev
,
i
,
res
,
&
start
,
&
end
);
str
+=
sprintf
(
str
,
"0x%016llx 0x%016llx 0x%016llx
\n
"
,
(
unsigned
long
long
)
start
,
(
unsigned
long
long
)
end
,
(
unsigned
long
long
)
res
->
flags
);
}
return
(
str
-
buf
);
}
...
...
@@ -313,8 +316,21 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
struct
device
,
kobj
));
struct
resource
*
res
=
(
struct
resource
*
)
attr
->
private
;
enum
pci_mmap_state
mmap_type
;
u64
start
,
end
;
int
i
;
vma
->
vm_pgoff
+=
res
->
start
>>
PAGE_SHIFT
;
for
(
i
=
0
;
i
<
PCI_ROM_RESOURCE
;
i
++
)
if
(
res
==
&
pdev
->
resource
[
i
])
break
;
if
(
i
>=
PCI_ROM_RESOURCE
)
return
-
ENODEV
;
/* pci_mmap_page_range() expects the same kind of entry as coming
* from /proc/bus/pci/ which is a "user visible" value. If this is
* different from the resource itself, arch will do necessary fixup.
*/
pci_resource_to_user
(
pdev
,
i
,
res
,
&
start
,
&
end
);
vma
->
vm_pgoff
+=
start
>>
PAGE_SHIFT
;
mmap_type
=
res
->
flags
&
IORESOURCE_MEM
?
pci_mmap_mem
:
pci_mmap_io
;
return
pci_mmap_page_range
(
pdev
,
vma
,
mmap_type
,
0
);
...
...
This diff is collapsed.
Click to expand it.
Prev
1
2
3
4
Next
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