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
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