Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
5c11ad95
Commit
5c11ad95
authored
Dec 15, 2011
by
Joerg Roedel
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'pci/pri-changes' into x86/amd
parents
a06ec394
91f57d5e
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
269 additions
and
105 deletions
+269
-105
Documentation/ABI/testing/sysfs-bus-pci
Documentation/ABI/testing/sysfs-bus-pci
+18
-0
drivers/acpi/pci_root.c
drivers/acpi/pci_root.c
+7
-0
drivers/pci/ats.c
drivers/pci/ats.c
+45
-45
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/hotplug/acpiphp_glue.c
+2
-2
drivers/pci/hotplug/pciehp.h
drivers/pci/hotplug/pciehp.h
+0
-1
drivers/pci/hotplug/pciehp_core.c
drivers/pci/hotplug/pciehp_core.c
+1
-10
drivers/pci/hotplug/pciehp_ctrl.c
drivers/pci/hotplug/pciehp_ctrl.c
+2
-2
drivers/pci/hotplug/pciehp_hpc.c
drivers/pci/hotplug/pciehp_hpc.c
+0
-1
drivers/pci/msi.c
drivers/pci/msi.c
+121
-0
drivers/pci/pci-acpi.c
drivers/pci/pci-acpi.c
+8
-5
drivers/pci/pcie/aspm.c
drivers/pci/pcie/aspm.c
+37
-21
include/linux/acpi.h
include/linux/acpi.h
+4
-0
include/linux/msi.h
include/linux/msi.h
+3
-0
include/linux/pci-aspm.h
include/linux/pci-aspm.h
+2
-2
include/linux/pci.h
include/linux/pci.h
+1
-0
include/linux/pci_regs.h
include/linux/pci_regs.h
+18
-16
No files found.
Documentation/ABI/testing/sysfs-bus-pci
View file @
5c11ad95
...
...
@@ -66,6 +66,24 @@ Description:
re-discover previously removed devices.
Depends on CONFIG_HOTPLUG.
What: /sys/bus/pci/devices/.../msi_irqs/
Date: September, 2011
Contact: Neil Horman <nhorman@tuxdriver.com>
Description:
The /sys/devices/.../msi_irqs directory contains a variable set
of sub-directories, with each sub-directory being named after a
corresponding msi irq vector allocated to that device. Each
numbered sub-directory N contains attributes of that irq.
Note that this directory is not created for device drivers which
do not support msi irqs
What: /sys/bus/pci/devices/.../msi_irqs/<N>/mode
Date: September 2011
Contact: Neil Horman <nhorman@tuxdriver.com>
Description:
This attribute indicates the mode that the irq vector named by
the parent directory is in (msi vs. msix)
What: /sys/bus/pci/devices/.../remove
Date: January 2009
Contact: Linux PCI developers <linux-pci@vger.kernel.org>
...
...
drivers/acpi/pci_root.c
View file @
5c11ad95
...
...
@@ -596,6 +596,13 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
if
(
ACPI_SUCCESS
(
status
))
{
dev_info
(
root
->
bus
->
bridge
,
"ACPI _OSC control (0x%02x) granted
\n
"
,
flags
);
if
(
acpi_gbl_FADT
.
boot_flags
&
ACPI_FADT_NO_ASPM
)
{
/*
* We have ASPM control, but the FADT indicates
* that it's unsupported. Clear it.
*/
pcie_clear_aspm
(
root
->
bus
);
}
}
else
{
dev_info
(
root
->
bus
->
bridge
,
"ACPI _OSC request failed (%s), "
...
...
drivers/pci/ats.c
View file @
5c11ad95
...
...
@@ -174,21 +174,22 @@ int pci_enable_pri(struct pci_dev *pdev, u32 reqs)
u32
max_requests
;
int
pos
;
pos
=
pci_find_ext_capability
(
pdev
,
PCI_
PRI_CAP
);
pos
=
pci_find_ext_capability
(
pdev
,
PCI_
EXT_CAP_ID_PRI
);
if
(
!
pos
)
return
-
EINVAL
;
pci_read_config_word
(
pdev
,
pos
+
PCI_PRI_CONTROL_OFF
,
&
control
);
pci_read_config_word
(
pdev
,
pos
+
PCI_PRI_STATUS_OFF
,
&
status
);
if
((
control
&
PCI_PRI_ENABLE
)
||
!
(
status
&
PCI_PRI_STATUS_STOPPED
))
pci_read_config_word
(
pdev
,
pos
+
PCI_PRI_CTRL
,
&
control
);
pci_read_config_word
(
pdev
,
pos
+
PCI_PRI_STATUS
,
&
status
);
if
((
control
&
PCI_PRI_CTRL_ENABLE
)
||
!
(
status
&
PCI_PRI_STATUS_STOPPED
))
return
-
EBUSY
;
pci_read_config_dword
(
pdev
,
pos
+
PCI_PRI_MAX_REQ
_OFF
,
&
max_requests
);
pci_read_config_dword
(
pdev
,
pos
+
PCI_PRI_MAX_REQ
,
&
max_requests
);
reqs
=
min
(
max_requests
,
reqs
);
pci_write_config_dword
(
pdev
,
pos
+
PCI_PRI_ALLOC_REQ
_OFF
,
reqs
);
pci_write_config_dword
(
pdev
,
pos
+
PCI_PRI_ALLOC_REQ
,
reqs
);
control
|=
PCI_PRI_ENABLE
;
pci_write_config_word
(
pdev
,
pos
+
PCI_PRI_C
ONTROL_OFF
,
control
);
control
|=
PCI_PRI_
CTRL_
ENABLE
;
pci_write_config_word
(
pdev
,
pos
+
PCI_PRI_C
TRL
,
control
);
return
0
;
}
...
...
@@ -205,13 +206,13 @@ void pci_disable_pri(struct pci_dev *pdev)
u16
control
;
int
pos
;
pos
=
pci_find_ext_capability
(
pdev
,
PCI_
PRI_CAP
);
pos
=
pci_find_ext_capability
(
pdev
,
PCI_
EXT_CAP_ID_PRI
);
if
(
!
pos
)
return
;
pci_read_config_word
(
pdev
,
pos
+
PCI_PRI_C
ONTROL_OFF
,
&
control
);
control
&=
~
PCI_PRI_ENABLE
;
pci_write_config_word
(
pdev
,
pos
+
PCI_PRI_C
ONTROL_OFF
,
control
);
pci_read_config_word
(
pdev
,
pos
+
PCI_PRI_C
TRL
,
&
control
);
control
&=
~
PCI_PRI_
CTRL_
ENABLE
;
pci_write_config_word
(
pdev
,
pos
+
PCI_PRI_C
TRL
,
control
);
}
EXPORT_SYMBOL_GPL
(
pci_disable_pri
);
...
...
@@ -226,13 +227,13 @@ bool pci_pri_enabled(struct pci_dev *pdev)
u16
control
;
int
pos
;
pos
=
pci_find_ext_capability
(
pdev
,
PCI_
PRI_CAP
);
pos
=
pci_find_ext_capability
(
pdev
,
PCI_
EXT_CAP_ID_PRI
);
if
(
!
pos
)
return
false
;
pci_read_config_word
(
pdev
,
pos
+
PCI_PRI_C
ONTROL_OFF
,
&
control
);
pci_read_config_word
(
pdev
,
pos
+
PCI_PRI_C
TRL
,
&
control
);
return
(
control
&
PCI_PRI_ENABLE
)
?
true
:
false
;
return
(
control
&
PCI_PRI_
CTRL_
ENABLE
)
?
true
:
false
;
}
EXPORT_SYMBOL_GPL
(
pci_pri_enabled
);
...
...
@@ -248,17 +249,17 @@ int pci_reset_pri(struct pci_dev *pdev)
u16
control
;
int
pos
;
pos
=
pci_find_ext_capability
(
pdev
,
PCI_
PRI_CAP
);
pos
=
pci_find_ext_capability
(
pdev
,
PCI_
EXT_CAP_ID_PRI
);
if
(
!
pos
)
return
-
EINVAL
;
pci_read_config_word
(
pdev
,
pos
+
PCI_PRI_C
ONTROL_OFF
,
&
control
);
if
(
control
&
PCI_PRI_ENABLE
)
pci_read_config_word
(
pdev
,
pos
+
PCI_PRI_C
TRL
,
&
control
);
if
(
control
&
PCI_PRI_
CTRL_
ENABLE
)
return
-
EBUSY
;
control
|=
PCI_PRI_RESET
;
control
|=
PCI_PRI_
CTRL_
RESET
;
pci_write_config_word
(
pdev
,
pos
+
PCI_PRI_C
ONTROL_OFF
,
control
);
pci_write_config_word
(
pdev
,
pos
+
PCI_PRI_C
TRL
,
control
);
return
0
;
}
...
...
@@ -281,14 +282,14 @@ bool pci_pri_stopped(struct pci_dev *pdev)
u16
control
,
status
;
int
pos
;
pos
=
pci_find_ext_capability
(
pdev
,
PCI_
PRI_CAP
);
pos
=
pci_find_ext_capability
(
pdev
,
PCI_
EXT_CAP_ID_PRI
);
if
(
!
pos
)
return
true
;
pci_read_config_word
(
pdev
,
pos
+
PCI_PRI_C
ONTROL_OFF
,
&
control
);
pci_read_config_word
(
pdev
,
pos
+
PCI_PRI_STATUS
_OFF
,
&
status
);
pci_read_config_word
(
pdev
,
pos
+
PCI_PRI_C
TRL
,
&
control
);
pci_read_config_word
(
pdev
,
pos
+
PCI_PRI_STATUS
,
&
status
);
if
(
control
&
PCI_PRI_ENABLE
)
if
(
control
&
PCI_PRI_
CTRL_
ENABLE
)
return
false
;
return
(
status
&
PCI_PRI_STATUS_STOPPED
)
?
true
:
false
;
...
...
@@ -310,15 +311,15 @@ int pci_pri_status(struct pci_dev *pdev)
u16
status
,
control
;
int
pos
;
pos
=
pci_find_ext_capability
(
pdev
,
PCI_
PRI_CAP
);
pos
=
pci_find_ext_capability
(
pdev
,
PCI_
EXT_CAP_ID_PRI
);
if
(
!
pos
)
return
-
EINVAL
;
pci_read_config_word
(
pdev
,
pos
+
PCI_PRI_C
ONTROL_OFF
,
&
control
);
pci_read_config_word
(
pdev
,
pos
+
PCI_PRI_STATUS
_OFF
,
&
status
);
pci_read_config_word
(
pdev
,
pos
+
PCI_PRI_C
TRL
,
&
control
);
pci_read_config_word
(
pdev
,
pos
+
PCI_PRI_STATUS
,
&
status
);
/* Stopped bit is undefined when enable == 1, so clear it */
if
(
control
&
PCI_PRI_ENABLE
)
if
(
control
&
PCI_PRI_
CTRL_
ENABLE
)
status
&=
~
PCI_PRI_STATUS_STOPPED
;
return
status
;
...
...
@@ -341,25 +342,25 @@ int pci_enable_pasid(struct pci_dev *pdev, int features)
u16
control
,
supported
;
int
pos
;
pos
=
pci_find_ext_capability
(
pdev
,
PCI_
PASID_CAP
);
pos
=
pci_find_ext_capability
(
pdev
,
PCI_
EXT_CAP_ID_PASID
);
if
(
!
pos
)
return
-
EINVAL
;
pci_read_config_word
(
pdev
,
pos
+
PCI_PASID_C
ONTROL_OFF
,
&
control
);
pci_read_config_word
(
pdev
,
pos
+
PCI_PASID_CAP
_OFF
,
&
supported
);
pci_read_config_word
(
pdev
,
pos
+
PCI_PASID_C
TRL
,
&
control
);
pci_read_config_word
(
pdev
,
pos
+
PCI_PASID_CAP
,
&
supported
);
if
(
!
(
supported
&
PCI_PASID_ENABLE
)
)
if
(
control
&
PCI_PASID_CTRL_ENABLE
)
return
-
EINVAL
;
supported
&=
PCI_PASID_
EXEC
|
PCI_PASID
_PRIV
;
supported
&=
PCI_PASID_
CAP_EXEC
|
PCI_PASID_CAP
_PRIV
;
/* User wants to enable anything unsupported? */
if
((
supported
&
features
)
!=
features
)
return
-
EINVAL
;
control
=
PCI_PASID_ENABLE
|
features
;
control
=
PCI_PASID_
CTRL_
ENABLE
|
features
;
pci_write_config_word
(
pdev
,
pos
+
PCI_PASID_C
ONTROL_OFF
,
control
);
pci_write_config_word
(
pdev
,
pos
+
PCI_PASID_C
TRL
,
control
);
return
0
;
}
...
...
@@ -375,11 +376,11 @@ void pci_disable_pasid(struct pci_dev *pdev)
u16
control
=
0
;
int
pos
;
pos
=
pci_find_ext_capability
(
pdev
,
PCI_
PASID_CAP
);
pos
=
pci_find_ext_capability
(
pdev
,
PCI_
EXT_CAP_ID_PASID
);
if
(
!
pos
)
return
;
pci_write_config_word
(
pdev
,
pos
+
PCI_PASID_C
ONTROL_OFF
,
control
);
pci_write_config_word
(
pdev
,
pos
+
PCI_PASID_C
TRL
,
control
);
}
EXPORT_SYMBOL_GPL
(
pci_disable_pasid
);
...
...
@@ -390,22 +391,21 @@ EXPORT_SYMBOL_GPL(pci_disable_pasid);
* Returns a negative value when no PASI capability is present.
* Otherwise is returns a bitmask with supported features. Current
* features reported are:
* PCI_PASID_ENABLE - PASID capability can be enabled
* PCI_PASID_EXEC - Execute permission supported
* PCI_PASID_PRIV - Priviledged mode supported
* PCI_PASID_CAP_EXEC - Execute permission supported
* PCI_PASID_CAP_PRIV - Priviledged mode supported
*/
int
pci_pasid_features
(
struct
pci_dev
*
pdev
)
{
u16
supported
;
int
pos
;
pos
=
pci_find_ext_capability
(
pdev
,
PCI_
PASID_CAP
);
pos
=
pci_find_ext_capability
(
pdev
,
PCI_
EXT_CAP_ID_PASID
);
if
(
!
pos
)
return
-
EINVAL
;
pci_read_config_word
(
pdev
,
pos
+
PCI_PASID_CAP
_OFF
,
&
supported
);
pci_read_config_word
(
pdev
,
pos
+
PCI_PASID_CAP
,
&
supported
);
supported
&=
PCI_PASID_
ENABLE
|
PCI_PASID_EXEC
|
PCI_PASID
_PRIV
;
supported
&=
PCI_PASID_
CAP_EXEC
|
PCI_PASID_CAP
_PRIV
;
return
supported
;
}
...
...
@@ -425,11 +425,11 @@ int pci_max_pasids(struct pci_dev *pdev)
u16
supported
;
int
pos
;
pos
=
pci_find_ext_capability
(
pdev
,
PCI_
PASID_CAP
);
pos
=
pci_find_ext_capability
(
pdev
,
PCI_
EXT_CAP_ID_PASID
);
if
(
!
pos
)
return
-
EINVAL
;
pci_read_config_word
(
pdev
,
pos
+
PCI_PASID_CAP
_OFF
,
&
supported
);
pci_read_config_word
(
pdev
,
pos
+
PCI_PASID_CAP
,
&
supported
);
supported
=
(
supported
&
PASID_NUMBER_MASK
)
>>
PASID_NUMBER_SHIFT
;
...
...
drivers/pci/hotplug/acpiphp_glue.c
View file @
5c11ad95
...
...
@@ -467,7 +467,7 @@ static int add_bridge(acpi_handle handle)
* granted by the BIOS for it.
*/
root
=
acpi_pci_find_root
(
handle
);
if
(
root
&&
(
root
->
osc_control_set
&
OSC_PCI_
EXPRESS_NATIVE_HP_CONTROL
))
if
(
root
&&
(
root
->
osc_control_set
&
OSC_PCI_
NATIVE_HOTPLUG
))
return
-
ENODEV
;
/* if the bridge doesn't have _STA, we assume it is always there */
...
...
@@ -1395,7 +1395,7 @@ find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
if
(
!
root
)
return
AE_OK
;
if
(
root
->
osc_control_set
&
OSC_PCI_
EXPRESS_NATIVE_HP_CONTROL
)
if
(
root
->
osc_control_set
&
OSC_PCI_
NATIVE_HOTPLUG
)
return
AE_OK
;
(
*
count
)
++
;
...
...
drivers/pci/hotplug/pciehp.h
View file @
5c11ad95
...
...
@@ -45,7 +45,6 @@ extern int pciehp_poll_time;
extern
int
pciehp_debug
;
extern
int
pciehp_force
;
extern
struct
workqueue_struct
*
pciehp_wq
;
extern
struct
workqueue_struct
*
pciehp_ordered_wq
;
#define dbg(format, arg...) \
do { \
...
...
drivers/pci/hotplug/pciehp_core.c
View file @
5c11ad95
...
...
@@ -43,7 +43,6 @@ int pciehp_poll_mode;
int
pciehp_poll_time
;
int
pciehp_force
;
struct
workqueue_struct
*
pciehp_wq
;
struct
workqueue_struct
*
pciehp_ordered_wq
;
#define DRIVER_VERSION "0.4"
#define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
...
...
@@ -345,18 +344,11 @@ static int __init pcied_init(void)
if
(
!
pciehp_wq
)
return
-
ENOMEM
;
pciehp_ordered_wq
=
alloc_ordered_workqueue
(
"pciehp_ordered"
,
0
);
if
(
!
pciehp_ordered_wq
)
{
destroy_workqueue
(
pciehp_wq
);
return
-
ENOMEM
;
}
pciehp_firmware_init
();
retval
=
pcie_port_service_register
(
&
hpdriver_portdrv
);
dbg
(
"pcie_port_service_register = %d
\n
"
,
retval
);
info
(
DRIVER_DESC
" version: "
DRIVER_VERSION
"
\n
"
);
if
(
retval
)
{
destroy_workqueue
(
pciehp_ordered_wq
);
destroy_workqueue
(
pciehp_wq
);
dbg
(
"Failure to register service
\n
"
);
}
...
...
@@ -366,9 +358,8 @@ static int __init pcied_init(void)
static
void
__exit
pcied_cleanup
(
void
)
{
dbg
(
"unload_pciehpd()
\n
"
);
destroy_workqueue
(
pciehp_ordered_wq
);
destroy_workqueue
(
pciehp_wq
);
pcie_port_service_unregister
(
&
hpdriver_portdrv
);
destroy_workqueue
(
pciehp_wq
);
info
(
DRIVER_DESC
" version: "
DRIVER_VERSION
" unloaded
\n
"
);
}
...
...
drivers/pci/hotplug/pciehp_ctrl.c
View file @
5c11ad95
...
...
@@ -344,7 +344,7 @@ void pciehp_queue_pushbutton_work(struct work_struct *work)
kfree
(
info
);
goto
out
;
}
queue_work
(
pciehp_
ordered_
wq
,
&
info
->
work
);
queue_work
(
pciehp_wq
,
&
info
->
work
);
out:
mutex_unlock
(
&
p_slot
->
lock
);
}
...
...
@@ -439,7 +439,7 @@ static void handle_surprise_event(struct slot *p_slot)
else
p_slot
->
state
=
POWERON_STATE
;
queue_work
(
pciehp_
ordered_
wq
,
&
info
->
work
);
queue_work
(
pciehp_wq
,
&
info
->
work
);
}
static
void
interrupt_event_handler
(
struct
work_struct
*
work
)
...
...
drivers/pci/hotplug/pciehp_hpc.c
View file @
5c11ad95
...
...
@@ -806,7 +806,6 @@ static void pcie_cleanup_slot(struct controller *ctrl)
struct
slot
*
slot
=
ctrl
->
slot
;
cancel_delayed_work
(
&
slot
->
work
);
flush_workqueue
(
pciehp_wq
);
flush_workqueue
(
pciehp_ordered_wq
);
kfree
(
slot
);
}
...
...
drivers/pci/msi.c
View file @
5c11ad95
...
...
@@ -323,6 +323,8 @@ static void free_msi_irqs(struct pci_dev *dev)
if
(
list_is_last
(
&
entry
->
list
,
&
dev
->
msi_list
))
iounmap
(
entry
->
mask_base
);
}
kobject_del
(
&
entry
->
kobj
);
kobject_put
(
&
entry
->
kobj
);
list_del
(
&
entry
->
list
);
kfree
(
entry
);
}
...
...
@@ -403,6 +405,98 @@ void pci_restore_msi_state(struct pci_dev *dev)
}
EXPORT_SYMBOL_GPL
(
pci_restore_msi_state
);
#define to_msi_attr(obj) container_of(obj, struct msi_attribute, attr)
#define to_msi_desc(obj) container_of(obj, struct msi_desc, kobj)
struct
msi_attribute
{
struct
attribute
attr
;
ssize_t
(
*
show
)(
struct
msi_desc
*
entry
,
struct
msi_attribute
*
attr
,
char
*
buf
);
ssize_t
(
*
store
)(
struct
msi_desc
*
entry
,
struct
msi_attribute
*
attr
,
const
char
*
buf
,
size_t
count
);
};
static
ssize_t
show_msi_mode
(
struct
msi_desc
*
entry
,
struct
msi_attribute
*
atr
,
char
*
buf
)
{
return
sprintf
(
buf
,
"%s
\n
"
,
entry
->
msi_attrib
.
is_msix
?
"msix"
:
"msi"
);
}
static
ssize_t
msi_irq_attr_show
(
struct
kobject
*
kobj
,
struct
attribute
*
attr
,
char
*
buf
)
{
struct
msi_attribute
*
attribute
=
to_msi_attr
(
attr
);
struct
msi_desc
*
entry
=
to_msi_desc
(
kobj
);
if
(
!
attribute
->
show
)
return
-
EIO
;
return
attribute
->
show
(
entry
,
attribute
,
buf
);
}
static
const
struct
sysfs_ops
msi_irq_sysfs_ops
=
{
.
show
=
msi_irq_attr_show
,
};
static
struct
msi_attribute
mode_attribute
=
__ATTR
(
mode
,
S_IRUGO
,
show_msi_mode
,
NULL
);
struct
attribute
*
msi_irq_default_attrs
[]
=
{
&
mode_attribute
.
attr
,
NULL
};
void
msi_kobj_release
(
struct
kobject
*
kobj
)
{
struct
msi_desc
*
entry
=
to_msi_desc
(
kobj
);
pci_dev_put
(
entry
->
dev
);
}
static
struct
kobj_type
msi_irq_ktype
=
{
.
release
=
msi_kobj_release
,
.
sysfs_ops
=
&
msi_irq_sysfs_ops
,
.
default_attrs
=
msi_irq_default_attrs
,
};
static
int
populate_msi_sysfs
(
struct
pci_dev
*
pdev
)
{
struct
msi_desc
*
entry
;
struct
kobject
*
kobj
;
int
ret
;
int
count
=
0
;
pdev
->
msi_kset
=
kset_create_and_add
(
"msi_irqs"
,
NULL
,
&
pdev
->
dev
.
kobj
);
if
(
!
pdev
->
msi_kset
)
return
-
ENOMEM
;
list_for_each_entry
(
entry
,
&
pdev
->
msi_list
,
list
)
{
kobj
=
&
entry
->
kobj
;
kobj
->
kset
=
pdev
->
msi_kset
;
pci_dev_get
(
pdev
);
ret
=
kobject_init_and_add
(
kobj
,
&
msi_irq_ktype
,
NULL
,
"%u"
,
entry
->
irq
);
if
(
ret
)
goto
out_unroll
;
count
++
;
}
return
0
;
out_unroll:
list_for_each_entry
(
entry
,
&
pdev
->
msi_list
,
list
)
{
if
(
!
count
)
break
;
kobject_del
(
&
entry
->
kobj
);
kobject_put
(
&
entry
->
kobj
);
count
--
;
}
return
ret
;
}
/**
* msi_capability_init - configure device's MSI capability structure
* @dev: pointer to the pci_dev data structure of MSI device function
...
...
@@ -454,6 +548,13 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)
return
ret
;
}
ret
=
populate_msi_sysfs
(
dev
);
if
(
ret
)
{
msi_mask_irq
(
entry
,
mask
,
~
mask
);
free_msi_irqs
(
dev
);
return
ret
;
}
/* Set MSI enabled bits */
pci_intx_for_msi
(
dev
,
0
);
msi_set_enable
(
dev
,
pos
,
1
);
...
...
@@ -574,6 +675,12 @@ static int msix_capability_init(struct pci_dev *dev,
msix_program_entries
(
dev
,
entries
);
ret
=
populate_msi_sysfs
(
dev
);
if
(
ret
)
{
ret
=
0
;
goto
error
;
}
/* Set MSI-X enabled bits and unmask the function */
pci_intx_for_msi
(
dev
,
0
);
dev
->
msix_enabled
=
1
;
...
...
@@ -732,6 +839,8 @@ void pci_disable_msi(struct pci_dev *dev)
pci_msi_shutdown
(
dev
);
free_msi_irqs
(
dev
);
kset_unregister
(
dev
->
msi_kset
);
dev
->
msi_kset
=
NULL
;
}
EXPORT_SYMBOL
(
pci_disable_msi
);
...
...
@@ -830,6 +939,8 @@ void pci_disable_msix(struct pci_dev *dev)
pci_msix_shutdown
(
dev
);
free_msi_irqs
(
dev
);
kset_unregister
(
dev
->
msi_kset
);
dev
->
msi_kset
=
NULL
;
}
EXPORT_SYMBOL
(
pci_disable_msix
);
...
...
@@ -870,5 +981,15 @@ EXPORT_SYMBOL(pci_msi_enabled);
void
pci_msi_init_pci_dev
(
struct
pci_dev
*
dev
)
{
int
pos
;
INIT_LIST_HEAD
(
&
dev
->
msi_list
);
/* Disable the msi hardware to avoid screaming interrupts
* during boot. This is the power on reset default so
* usually this should be a noop.
*/
pos
=
pci_find_capability
(
dev
,
PCI_CAP_ID_MSI
);
if
(
pos
)
msi_set_enable
(
dev
,
pos
,
0
);
msix_set_enable
(
dev
,
0
);
}
drivers/pci/pci-acpi.c
View file @
5c11ad95
...
...
@@ -45,16 +45,20 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
{
struct
pci_dev
*
pci_dev
=
context
;
if
(
event
==
ACPI_NOTIFY_DEVICE_WAKE
&&
pci_dev
)
{
if
(
event
!=
ACPI_NOTIFY_DEVICE_WAKE
||
!
pci_dev
)
return
;
if
(
!
pci_dev
->
pm_cap
||
!
pci_dev
->
pme_support
||
pci_check_pme_status
(
pci_dev
))
{
if
(
pci_dev
->
pme_poll
)
pci_dev
->
pme_poll
=
false
;
pci_wakeup_event
(
pci_dev
);
pci_check_pme_status
(
pci_dev
);
pm_runtime_resume
(
&
pci_dev
->
dev
);
if
(
pci_dev
->
subordinate
)
pci_pme_wakeup_bus
(
pci_dev
->
subordinate
);
}
if
(
pci_dev
->
subordinate
)
pci_pme_wakeup_bus
(
pci_dev
->
subordinate
);
}
/**
...
...
@@ -395,7 +399,6 @@ static int __init acpi_pci_init(void)
if
(
acpi_gbl_FADT
.
boot_flags
&
ACPI_FADT_NO_ASPM
)
{
printk
(
KERN_INFO
"ACPI FADT declares the system doesn't support PCIe ASPM, so disable it
\n
"
);
pcie_clear_aspm
();
pcie_no_aspm
();
}
...
...
drivers/pci/pcie/aspm.c
View file @
5c11ad95
...
...
@@ -68,7 +68,7 @@ struct pcie_link_state {
struct
aspm_latency
acceptable
[
8
];
};
static
int
aspm_disabled
,
aspm_force
,
aspm_clear_state
;
static
int
aspm_disabled
,
aspm_force
;
static
bool
aspm_support_enabled
=
true
;
static
DEFINE_MUTEX
(
aspm_lock
);
static
LIST_HEAD
(
link_list
);
...
...
@@ -500,9 +500,6 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
int
pos
;
u32
reg32
;
if
(
aspm_clear_state
)
return
-
EINVAL
;
/*
* Some functions in a slot might not all be PCIe functions,
* very strange. Disable ASPM for the whole slot
...
...
@@ -574,9 +571,6 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
pdev
->
pcie_type
!=
PCI_EXP_TYPE_DOWNSTREAM
)
return
;
if
(
aspm_disabled
&&
!
aspm_clear_state
)
return
;
/* VIA has a strange chipset, root port is under a bridge */
if
(
pdev
->
pcie_type
==
PCI_EXP_TYPE_ROOT_PORT
&&
pdev
->
bus
->
self
)
...
...
@@ -608,7 +602,7 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
* the BIOS's expectation, we'll do so once pci_enable_device() is
* called.
*/
if
(
aspm_policy
!=
POLICY_POWERSAVE
||
aspm_clear_state
)
{
if
(
aspm_policy
!=
POLICY_POWERSAVE
)
{
pcie_config_aspm_path
(
link
);
pcie_set_clkpm
(
link
,
policy_to_clkpm_state
(
link
));
}
...
...
@@ -649,8 +643,7 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev)
struct
pci_dev
*
parent
=
pdev
->
bus
->
self
;
struct
pcie_link_state
*
link
,
*
root
,
*
parent_link
;
if
((
aspm_disabled
&&
!
aspm_clear_state
)
||
!
pci_is_pcie
(
pdev
)
||
!
parent
||
!
parent
->
link_state
)
if
(
!
pci_is_pcie
(
pdev
)
||
!
parent
||
!
parent
->
link_state
)
return
;
if
((
parent
->
pcie_type
!=
PCI_EXP_TYPE_ROOT_PORT
)
&&
(
parent
->
pcie_type
!=
PCI_EXP_TYPE_DOWNSTREAM
))
...
...
@@ -734,13 +727,18 @@ void pcie_aspm_powersave_config_link(struct pci_dev *pdev)
* pci_disable_link_state - disable pci device's link state, so the link will
* never enter specific states
*/
static
void
__pci_disable_link_state
(
struct
pci_dev
*
pdev
,
int
state
,
bool
sem
)
static
void
__pci_disable_link_state
(
struct
pci_dev
*
pdev
,
int
state
,
bool
sem
,
bool
force
)
{
struct
pci_dev
*
parent
=
pdev
->
bus
->
self
;
struct
pcie_link_state
*
link
;
if
(
aspm_disabled
||
!
pci_is_pcie
(
pdev
))
if
(
aspm_disabled
&&
!
force
)
return
;
if
(
!
pci_is_pcie
(
pdev
))
return
;
if
(
pdev
->
pcie_type
==
PCI_EXP_TYPE_ROOT_PORT
||
pdev
->
pcie_type
==
PCI_EXP_TYPE_DOWNSTREAM
)
parent
=
pdev
;
...
...
@@ -768,16 +766,31 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
void
pci_disable_link_state_locked
(
struct
pci_dev
*
pdev
,
int
state
)
{
__pci_disable_link_state
(
pdev
,
state
,
false
);
__pci_disable_link_state
(
pdev
,
state
,
false
,
false
);
}
EXPORT_SYMBOL
(
pci_disable_link_state_locked
);
void
pci_disable_link_state
(
struct
pci_dev
*
pdev
,
int
state
)
{
__pci_disable_link_state
(
pdev
,
state
,
true
);
__pci_disable_link_state
(
pdev
,
state
,
true
,
false
);
}
EXPORT_SYMBOL
(
pci_disable_link_state
);
void
pcie_clear_aspm
(
struct
pci_bus
*
bus
)
{
struct
pci_dev
*
child
;
/*
* Clear any ASPM setup that the firmware has carried out on this bus
*/
list_for_each_entry
(
child
,
&
bus
->
devices
,
bus_list
)
{
__pci_disable_link_state
(
child
,
PCIE_LINK_STATE_L0S
|
PCIE_LINK_STATE_L1
|
PCIE_LINK_STATE_CLKPM
,
false
,
true
);
}
}
static
int
pcie_aspm_set_policy
(
const
char
*
val
,
struct
kernel_param
*
kp
)
{
int
i
;
...
...
@@ -935,6 +948,7 @@ void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev)
static
int
__init
pcie_aspm_disable
(
char
*
str
)
{
if
(
!
strcmp
(
str
,
"off"
))
{
aspm_policy
=
POLICY_DEFAULT
;
aspm_disabled
=
1
;
aspm_support_enabled
=
false
;
printk
(
KERN_INFO
"PCIe ASPM is disabled
\n
"
);
...
...
@@ -947,16 +961,18 @@ static int __init pcie_aspm_disable(char *str)
__setup
(
"pcie_aspm="
,
pcie_aspm_disable
);
void
pcie_clear_aspm
(
void
)
{
if
(
!
aspm_force
)
aspm_clear_state
=
1
;
}
void
pcie_no_aspm
(
void
)
{
if
(
!
aspm_force
)
/*
* Disabling ASPM is intended to prevent the kernel from modifying
* existing hardware state, not to clear existing state. To that end:
* (a) set policy to POLICY_DEFAULT in order to avoid changing state
* (b) prevent userspace from changing policy
*/
if
(
!
aspm_force
)
{
aspm_policy
=
POLICY_DEFAULT
;
aspm_disabled
=
1
;
}
}
/**
...
...
include/linux/acpi.h
View file @
5c11ad95
...
...
@@ -302,6 +302,10 @@ extern bool osc_sb_apei_support_acked;
OSC_PCI_EXPRESS_PME_CONTROL | \
OSC_PCI_EXPRESS_AER_CONTROL | \
OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL)
#define OSC_PCI_NATIVE_HOTPLUG (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | \
OSC_SHPC_NATIVE_HP_CONTROL)
extern
acpi_status
acpi_pci_osc_control_set
(
acpi_handle
handle
,
u32
*
mask
,
u32
req
);
extern
void
acpi_early_init
(
void
);
...
...
include/linux/msi.h
View file @
5c11ad95
#ifndef LINUX_MSI_H
#define LINUX_MSI_H
#include <linux/kobject.h>
#include <linux/list.h>
struct
msi_msg
{
...
...
@@ -44,6 +45,8 @@ struct msi_desc {
/* Last set MSI message */
struct
msi_msg
msg
;
struct
kobject
kobj
;
};
/*
...
...
include/linux/pci-aspm.h
View file @
5c11ad95
...
...
@@ -29,7 +29,7 @@ extern void pcie_aspm_pm_state_change(struct pci_dev *pdev);
extern
void
pcie_aspm_powersave_config_link
(
struct
pci_dev
*
pdev
);
extern
void
pci_disable_link_state
(
struct
pci_dev
*
pdev
,
int
state
);
extern
void
pci_disable_link_state_locked
(
struct
pci_dev
*
pdev
,
int
state
);
extern
void
pcie_clear_aspm
(
void
);
extern
void
pcie_clear_aspm
(
struct
pci_bus
*
bus
);
extern
void
pcie_no_aspm
(
void
);
#else
static
inline
void
pcie_aspm_init_link_state
(
struct
pci_dev
*
pdev
)
...
...
@@ -47,7 +47,7 @@ static inline void pcie_aspm_powersave_config_link(struct pci_dev *pdev)
static
inline
void
pci_disable_link_state
(
struct
pci_dev
*
pdev
,
int
state
)
{
}
static
inline
void
pcie_clear_aspm
(
void
)
static
inline
void
pcie_clear_aspm
(
struct
pci_bus
*
bus
)
{
}
static
inline
void
pcie_no_aspm
(
void
)
...
...
include/linux/pci.h
View file @
5c11ad95
...
...
@@ -336,6 +336,7 @@ struct pci_dev {
struct
bin_attribute
*
res_attr_wc
[
DEVICE_COUNT_RESOURCE
];
/* sysfs file for WC mapping of resources */
#ifdef CONFIG_PCI_MSI
struct
list_head
msi_list
;
struct
kset
*
msi_kset
;
#endif
struct
pci_vpd
*
vpd
;
#ifdef CONFIG_PCI_ATS
...
...
include/linux/pci_regs.h
View file @
5c11ad95
...
...
@@ -537,7 +537,9 @@
#define PCI_EXT_CAP_ID_ARI 14
#define PCI_EXT_CAP_ID_ATS 15
#define PCI_EXT_CAP_ID_SRIOV 16
#define PCI_EXT_CAP_ID_PRI 19
#define PCI_EXT_CAP_ID_LTR 24
#define PCI_EXT_CAP_ID_PASID 27
/* Advanced Error Reporting */
#define PCI_ERR_UNCOR_STATUS 4
/* Uncorrectable Error Status */
...
...
@@ -664,24 +666,24 @@
#define PCI_ATS_MIN_STU 12
/* shift of minimum STU block */
/* Page Request Interface */
#define PCI_PRI_CAP 0x13
/* PRI capability ID */
#define PCI_PRI_CONTROL_OFF 0x04
/* Offset of control register */
#define PCI_PRI_STATUS_OFF 0x06
/* Offset of status register */
#define PCI_PRI_ENABLE 0x0001
/* Enable mask */
#define PCI_PRI_RESET 0x0002
/* Reset bit mask */
#define PCI_PRI_STATUS_RF 0x0001
/* Request Failure */
#define PCI_PRI_STATUS_UPRGI 0x0002
/* Unexpected PRG index */
#define PCI_PRI_STATUS_STOPPED 0x0100
/* PRI Stopped */
#define PCI_PRI_MAX_REQ_OFF 0x08
/* Cap offset for max reqs supported */
#define PCI_PRI_ALLOC_REQ_OFF 0x0c
/* Cap offset for max reqs allowed */
#define PCI_PRI_CTRL 0x04
/* PRI control register */
#define PCI_PRI_CTRL_ENABLE 0x01
/* Enable */
#define PCI_PRI_CTRL_RESET 0x02
/* Reset */
#define PCI_PRI_STATUS 0x06
/* PRI status register */
#define PCI_PRI_STATUS_RF 0x001
/* Response Failure */
#define PCI_PRI_STATUS_UPRGI 0x002
/* Unexpected PRG index */
#define PCI_PRI_STATUS_STOPPED 0x100
/* PRI Stopped */
#define PCI_PRI_MAX_REQ 0x08
/* PRI max reqs supported */
#define PCI_PRI_ALLOC_REQ 0x0c
/* PRI max reqs allowed */
/* PASID capability */
#define PCI_PASID_CAP 0x1b
/* PASID capability ID */
#define PCI_PASID_CAP_OFF 0x04
/* PASID feature register */
#define PCI_PASID_CONTROL_OFF 0x06
/* PASID control register */
#define PCI_PASID_ENABLE 0x01
/* Enable/Supported bit */
#define PCI_PASID_EXEC 0x02
/* Exec permissions Enable/Supported */
#define PCI_PASID_PRIV 0x04
/* Priviledge Mode Enable/Support */
#define PCI_PASID_CAP 0x04
/* PASID feature register */
#define PCI_PASID_CAP_EXEC 0x02
/* Exec permissions Supported */
#define PCI_PASID_CAP_PRIV 0x04
/* Priviledge Mode Supported */
#define PCI_PASID_CTRL 0x06
/* PASID control register */
#define PCI_PASID_CTRL_ENABLE 0x01
/* Enable bit */
#define PCI_PASID_CTRL_EXEC 0x02
/* Exec permissions Enable */
#define PCI_PASID_CTRL_PRIV 0x04
/* Priviledge Mode Enable */
/* Single Root I/O Virtualization */
#define PCI_SRIOV_CAP 0x04
/* SR-IOV Capabilities */
...
...
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