Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
4b49b9fe
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 4 年多
通知
15
Star
8
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kernel_linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
4b49b9fe
编写于
2月 12, 2014
作者:
R
Rafael J. Wysocki
浏览文件
操作
浏览文件
下载
差异文件
Merge back earlier 'acpi-pci-hotplug' material.
Conflicts: drivers/pci/hotplug/acpiphp_glue.c
上级
72820594
21369c77
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
332 addition
and
402 deletion
+332
-402
drivers/acpi/acpica/nsxfeval.c
drivers/acpi/acpica/nsxfeval.c
+30
-3
drivers/acpi/bus.c
drivers/acpi/bus.c
+39
-22
drivers/acpi/internal.h
drivers/acpi/internal.h
+1
-0
drivers/acpi/pci_root.c
drivers/acpi/pci_root.c
+1
-1
drivers/acpi/scan.c
drivers/acpi/scan.c
+93
-88
drivers/pci/hotplug/acpiphp.h
drivers/pci/hotplug/acpiphp.h
+12
-4
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/hotplug/acpiphp_glue.c
+124
-281
include/acpi/acpi_bus.h
include/acpi/acpi_bus.h
+26
-1
include/acpi/acpixf.h
include/acpi/acpixf.h
+4
-0
include/linux/pci-acpi.h
include/linux/pci-acpi.h
+2
-2
未找到文件。
drivers/acpi/acpica/nsxfeval.c
浏览文件 @
4b49b9fe
...
...
@@ -923,19 +923,22 @@ ACPI_EXPORT_SYMBOL(acpi_detach_data)
/*******************************************************************************
*
* FUNCTION: acpi_get_data
* FUNCTION: acpi_get_data
_full
*
* PARAMETERS: obj_handle - Namespace node
* handler - Handler used in call to attach_data
* data - Where the data is returned
* callback - function to execute before returning
*
* RETURN: Status
*
* DESCRIPTION: Retrieve data that was previously attached to a namespace node.
* DESCRIPTION: Retrieve data that was previously attached to a namespace node
* and execute a callback before returning.
*
******************************************************************************/
acpi_status
acpi_get_data
(
acpi_handle
obj_handle
,
acpi_object_handler
handler
,
void
**
data
)
acpi_get_data_full
(
acpi_handle
obj_handle
,
acpi_object_handler
handler
,
void
**
data
,
void
(
*
callback
)(
void
*
))
{
struct
acpi_namespace_node
*
node
;
acpi_status
status
;
...
...
@@ -960,10 +963,34 @@ acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data)
}
status
=
acpi_ns_get_attached_data
(
node
,
handler
,
data
);
if
(
ACPI_SUCCESS
(
status
)
&&
callback
)
{
callback
(
*
data
);
}
unlock_and_exit:
(
void
)
acpi_ut_release_mutex
(
ACPI_MTX_NAMESPACE
);
return
(
status
);
}
ACPI_EXPORT_SYMBOL
(
acpi_get_data_full
)
/*******************************************************************************
*
* FUNCTION: acpi_get_data
*
* PARAMETERS: obj_handle - Namespace node
* handler - Handler used in call to attach_data
* data - Where the data is returned
*
* RETURN: Status
*
* DESCRIPTION: Retrieve data that was previously attached to a namespace node.
*
******************************************************************************/
acpi_status
acpi_get_data
(
acpi_handle
obj_handle
,
acpi_object_handler
handler
,
void
**
data
)
{
return
acpi_get_data_full
(
obj_handle
,
handler
,
data
,
NULL
);
}
ACPI_EXPORT_SYMBOL
(
acpi_get_data
)
drivers/acpi/bus.c
浏览文件 @
4b49b9fe
...
...
@@ -340,60 +340,77 @@ static void acpi_bus_osc_support(void)
*/
static
void
acpi_bus_notify
(
acpi_handle
handle
,
u32
type
,
void
*
data
)
{
struct
acpi_device
*
device
=
NULL
;
struct
acpi_device
*
adev
;
struct
acpi_driver
*
driver
;
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Notification %#02x to handle %p
\n
"
,
type
,
handle
));
acpi_status
status
;
u32
ost_code
=
ACPI_OST_SC_NON_SPECIFIC_FAILURE
;
switch
(
type
)
{
case
ACPI_NOTIFY_BUS_CHECK
:
/* TBD */
acpi_handle_debug
(
handle
,
"ACPI_NOTIFY_BUS_CHECK event
\n
"
);
break
;
case
ACPI_NOTIFY_DEVICE_CHECK
:
/* TBD */
acpi_handle_debug
(
handle
,
"ACPI_NOTIFY_DEVICE_CHECK event
\n
"
);
break
;
case
ACPI_NOTIFY_DEVICE_WAKE
:
/* TBD */
acpi_handle_debug
(
handle
,
"ACPI_NOTIFY_DEVICE_WAKE event
\n
"
);
break
;
case
ACPI_NOTIFY_EJECT_REQUEST
:
/* TBD */
acpi_handle_debug
(
handle
,
"ACPI_NOTIFY_EJECT_REQUEST event
\n
"
);
break
;
case
ACPI_NOTIFY_DEVICE_CHECK_LIGHT
:
acpi_handle_debug
(
handle
,
"ACPI_NOTIFY_DEVICE_CHECK_LIGHT event
\n
"
);
/* TBD: Exactly what does 'light' mean? */
break
;
case
ACPI_NOTIFY_FREQUENCY_MISMATCH
:
/* TBD */
acpi_handle_err
(
handle
,
"Device cannot be configured due "
"to a frequency mismatch
\n
"
);
break
;
case
ACPI_NOTIFY_BUS_MODE_MISMATCH
:
/* TBD */
acpi_handle_err
(
handle
,
"Device cannot be configured due "
"to a bus mode mismatch
\n
"
);
break
;
case
ACPI_NOTIFY_POWER_FAULT
:
/* TBD */
acpi_handle_err
(
handle
,
"Device has suffered a power fault
\n
"
);
break
;
default:
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Received unknown/unsupported notification [%08x]
\n
"
,
type
));
break
;
acpi_handle_warn
(
handle
,
"Unsupported event type 0x%x
\n
"
,
type
);
ost_code
=
ACPI_OST_SC_UNRECOGNIZED_NOTIFY
;
goto
err
;
}
acpi_bus_get_device
(
handle
,
&
device
);
if
(
device
)
{
driver
=
device
->
driver
;
if
(
driver
&&
driver
->
ops
.
notify
&&
(
driver
->
flags
&
ACPI_DRIVER_ALL_NOTIFY_EVENTS
))
driver
->
ops
.
notify
(
device
,
type
);
adev
=
acpi_bus_get_acpi_device
(
handle
);
if
(
!
adev
)
goto
err
;
driver
=
adev
->
driver
;
if
(
driver
&&
driver
->
ops
.
notify
&&
(
driver
->
flags
&
ACPI_DRIVER_ALL_NOTIFY_EVENTS
))
driver
->
ops
.
notify
(
adev
,
type
);
switch
(
type
)
{
case
ACPI_NOTIFY_BUS_CHECK
:
case
ACPI_NOTIFY_DEVICE_CHECK
:
case
ACPI_NOTIFY_EJECT_REQUEST
:
status
=
acpi_hotplug_execute
(
acpi_device_hotplug
,
adev
,
type
);
if
(
ACPI_SUCCESS
(
status
))
return
;
default:
break
;
}
acpi_bus_put_acpi_device
(
adev
);
return
;
err:
acpi_evaluate_hotplug_ost
(
handle
,
type
,
ost_code
,
NULL
);
}
/* --------------------------------------------------------------------------
...
...
drivers/acpi/internal.h
浏览文件 @
4b49b9fe
...
...
@@ -73,6 +73,7 @@ static inline void acpi_lpss_init(void) {}
#endif
bool
acpi_queue_hotplug_work
(
struct
work_struct
*
work
);
void
acpi_device_hotplug
(
void
*
data
,
u32
src
);
bool
acpi_scan_is_offline
(
struct
acpi_device
*
adev
,
bool
uevent
);
/* --------------------------------------------------------------------------
...
...
drivers/acpi/pci_root.c
浏览文件 @
4b49b9fe
...
...
@@ -51,7 +51,7 @@ static void acpi_pci_root_remove(struct acpi_device *device);
static
int
acpi_pci_root_scan_dependent
(
struct
acpi_device
*
adev
)
{
acpiphp_check_host_bridge
(
adev
->
handle
);
acpiphp_check_host_bridge
(
adev
);
return
0
;
}
...
...
drivers/acpi/scan.c
浏览文件 @
4b49b9fe
...
...
@@ -41,6 +41,7 @@ static DEFINE_MUTEX(acpi_scan_lock);
static
LIST_HEAD
(
acpi_scan_handlers_list
);
DEFINE_MUTEX
(
acpi_device_lock
);
LIST_HEAD
(
acpi_wakeup_device_list
);
static
DEFINE_MUTEX
(
acpi_hp_context_lock
);
struct
acpi_device_bus_id
{
char
bus_id
[
15
];
...
...
@@ -60,6 +61,16 @@ void acpi_scan_lock_release(void)
}
EXPORT_SYMBOL_GPL
(
acpi_scan_lock_release
);
void
acpi_lock_hp_context
(
void
)
{
mutex_lock
(
&
acpi_hp_context_lock
);
}
void
acpi_unlock_hp_context
(
void
)
{
mutex_unlock
(
&
acpi_hp_context_lock
);
}
int
acpi_scan_add_handler
(
struct
acpi_scan_handler
*
handler
)
{
if
(
!
handler
||
!
handler
->
attach
)
...
...
@@ -439,90 +450,74 @@ static int acpi_scan_bus_check(struct acpi_device *adev)
return
0
;
}
static
void
acpi_device_hotplug
(
void
*
data
,
u32
src
)
static
int
acpi_generic_hotplug_event
(
struct
acpi_device
*
adev
,
u32
type
)
{
switch
(
type
)
{
case
ACPI_NOTIFY_BUS_CHECK
:
return
acpi_scan_bus_check
(
adev
);
case
ACPI_NOTIFY_DEVICE_CHECK
:
return
acpi_scan_device_check
(
adev
);
case
ACPI_NOTIFY_EJECT_REQUEST
:
case
ACPI_OST_EC_OSPM_EJECT
:
if
(
adev
->
handler
&&
!
adev
->
handler
->
hotplug
.
enabled
)
{
dev_info
(
&
adev
->
dev
,
"Eject disabled
\n
"
);
return
-
EPERM
;
}
acpi_evaluate_hotplug_ost
(
adev
->
handle
,
ACPI_NOTIFY_EJECT_REQUEST
,
ACPI_OST_SC_EJECT_IN_PROGRESS
,
NULL
);
return
acpi_scan_hot_remove
(
adev
);
}
return
-
EINVAL
;
}
void
acpi_device_hotplug
(
void
*
data
,
u32
src
)
{
u32
ost_code
=
ACPI_OST_SC_NON_SPECIFIC_FAILURE
;
struct
acpi_device
*
adev
=
data
;
int
error
;
int
error
=
-
ENODEV
;
lock_device_hotplug
();
mutex_lock
(
&
acpi_scan_lock
);
/*
* The device object's ACPI handle cannot become invalid as long as we
* are holding acpi_scan_lock, but it m
ay
have become invalid before
* are holding acpi_scan_lock, but it m
ight
have become invalid before
* that lock was acquired.
*/
if
(
adev
->
handle
==
INVALID_ACPI_HANDLE
)
goto
out
;
switch
(
src
)
{
case
ACPI_NOTIFY_BUS_CHECK
:
error
=
acpi_scan_bus_check
(
adev
);
break
;
case
ACPI_NOTIFY_DEVICE_CHECK
:
error
=
acpi_scan_device_check
(
adev
);
break
;
case
ACPI_NOTIFY_EJECT_REQUEST
:
case
ACPI_OST_EC_OSPM_EJECT
:
error
=
acpi_scan_hot_remove
(
adev
);
break
;
default:
error
=
-
EINVAL
;
break
;
}
if
(
!
error
)
ost_code
=
ACPI_OST_SC_SUCCESS
;
out:
acpi_evaluate_hotplug_ost
(
adev
->
handle
,
src
,
ost_code
,
NULL
);
put_device
(
&
adev
->
dev
);
mutex_unlock
(
&
acpi_scan_lock
);
unlock_device_hotplug
();
}
static
void
acpi_hotplug_notify_cb
(
acpi_handle
handle
,
u32
type
,
void
*
data
)
{
u32
ost_code
=
ACPI_OST_SC_NON_SPECIFIC_FAILURE
;
struct
acpi_device
*
adev
;
acpi_status
status
;
if
(
acpi_bus_get_device
(
handle
,
&
adev
))
goto
err_out
;
switch
(
type
)
{
case
ACPI_NOTIFY_BUS_CHECK
:
acpi_handle_debug
(
handle
,
"ACPI_NOTIFY_BUS_CHECK event
\n
"
);
break
;
case
ACPI_NOTIFY_DEVICE_CHECK
:
acpi_handle_debug
(
handle
,
"ACPI_NOTIFY_DEVICE_CHECK event
\n
"
);
break
;
case
ACPI_NOTIFY_EJECT_REQUEST
:
acpi_handle_debug
(
handle
,
"ACPI_NOTIFY_EJECT_REQUEST event
\n
"
);
if
(
!
adev
->
handler
)
goto
err_out
;
if
(
!
adev
->
handler
->
hotplug
.
enabled
)
{
acpi_handle_err
(
handle
,
"Eject disabled
\n
"
);
if
(
adev
->
flags
.
hotplug_notify
)
{
error
=
acpi_generic_hotplug_event
(
adev
,
src
);
if
(
error
==
-
EPERM
)
{
ost_code
=
ACPI_OST_SC_EJECT_NOT_SUPPORTED
;
goto
err_out
;
}
acpi_evaluate_hotplug_ost
(
handle
,
ACPI_NOTIFY_EJECT_REQUEST
,
ACPI_OST_SC_EJECT_IN_PROGRESS
,
NULL
);
break
;
default:
/* non-hotplug event; possibly handled by other handler */
return
;
}
get_device
(
&
adev
->
dev
);
status
=
acpi_hotplug_execute
(
acpi_device_hotplug
,
adev
,
type
);
if
(
ACPI_SUCCESS
(
status
))
return
;
}
else
{
int
(
*
event
)(
struct
acpi_device
*
,
u32
);
put_device
(
&
adev
->
dev
);
acpi_lock_hp_context
();
event
=
adev
->
hp
?
adev
->
hp
->
event
:
NULL
;
acpi_unlock_hp_context
();
/*
* There may be additional notify handlers for device objects
* without the .event() callback, so ignore them here.
*/
if
(
event
)
error
=
event
(
adev
,
src
);
else
goto
out
;
}
if
(
!
error
)
ost_code
=
ACPI_OST_SC_SUCCESS
;
err_out:
acpi_evaluate_hotplug_ost
(
handle
,
type
,
ost_code
,
NULL
);
acpi_evaluate_hotplug_ost
(
adev
->
handle
,
src
,
ost_code
,
NULL
);
out:
acpi_bus_put_acpi_device
(
adev
);
mutex_unlock
(
&
acpi_scan_lock
);
unlock_device_hotplug
();
}
static
ssize_t
real_power_state_show
(
struct
device
*
dev
,
...
...
@@ -570,8 +565,6 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
if
(
ACPI_FAILURE
(
status
)
||
!
acpi_device
->
flags
.
ejectable
)
return
-
ENODEV
;
acpi_evaluate_hotplug_ost
(
acpi_device
->
handle
,
ACPI_OST_EC_OSPM_EJECT
,
ACPI_OST_SC_EJECT_IN_PROGRESS
,
NULL
);
get_device
(
&
acpi_device
->
dev
);
status
=
acpi_hotplug_execute
(
acpi_device_hotplug
,
acpi_device
,
ACPI_OST_EC_OSPM_EJECT
);
...
...
@@ -1114,14 +1107,16 @@ static void acpi_scan_drop_device(acpi_handle handle, void *context)
mutex_unlock
(
&
acpi_device_del_lock
);
}
int
acpi_bus_get_device
(
acpi_handle
handle
,
struct
acpi_device
**
device
)
static
int
acpi_get_device_data
(
acpi_handle
handle
,
struct
acpi_device
**
device
,
void
(
*
callback
)(
void
*
))
{
acpi_status
status
;
if
(
!
device
)
return
-
EINVAL
;
status
=
acpi_get_data
(
handle
,
acpi_scan_drop_device
,
(
void
**
)
device
);
status
=
acpi_get_data_full
(
handle
,
acpi_scan_drop_device
,
(
void
**
)
device
,
callback
);
if
(
ACPI_FAILURE
(
status
)
||
!*
device
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"No context for object [%p]
\n
"
,
handle
));
...
...
@@ -1129,8 +1124,32 @@ int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
}
return
0
;
}
int
acpi_bus_get_device
(
acpi_handle
handle
,
struct
acpi_device
**
device
)
{
return
acpi_get_device_data
(
handle
,
device
,
NULL
);
}
EXPORT_SYMBOL
(
acpi_bus_get_device
);
static
void
get_acpi_device
(
void
*
dev
)
{
if
(
dev
)
get_device
(
&
((
struct
acpi_device
*
)
dev
)
->
dev
);
}
struct
acpi_device
*
acpi_bus_get_acpi_device
(
acpi_handle
handle
)
{
struct
acpi_device
*
adev
=
NULL
;
acpi_get_device_data
(
handle
,
&
adev
,
get_acpi_device
);
return
adev
;
}
void
acpi_bus_put_acpi_device
(
struct
acpi_device
*
adev
)
{
put_device
(
&
adev
->
dev
);
}
int
acpi_device_add
(
struct
acpi_device
*
device
,
void
(
*
release
)(
struct
device
*
))
{
...
...
@@ -1941,33 +1960,19 @@ void acpi_scan_hotplug_enabled(struct acpi_hotplug_profile *hotplug, bool val)
mutex_unlock
(
&
acpi_scan_lock
);
}
static
void
acpi_scan_init_hotplug
(
acpi_handle
handle
,
int
type
)
static
void
acpi_scan_init_hotplug
(
struct
acpi_device
*
adev
)
{
struct
acpi_device_pnp
pnp
=
{};
struct
acpi_hardware_id
*
hwid
;
struct
acpi_scan_handler
*
handler
;
INIT_LIST_HEAD
(
&
pnp
.
ids
);
acpi_set_pnp_ids
(
handle
,
&
pnp
,
type
);
if
(
!
pnp
.
type
.
hardware_id
)
goto
out
;
list_for_each_entry
(
hwid
,
&
adev
->
pnp
.
ids
,
list
)
{
struct
acpi_scan_handler
*
handler
;
/*
* This relies on the fact that acpi_install_notify_handler() will not
* install the same notify handler routine twice for the same handle.
*/
list_for_each_entry
(
hwid
,
&
pnp
.
ids
,
list
)
{
handler
=
acpi_scan_match_handler
(
hwid
->
id
,
NULL
);
if
(
handler
)
{
acpi_install_notify_handler
(
handle
,
ACPI_SYSTEM_NOTIFY
,
acpi_hotplug_notify_cb
,
handler
);
adev
->
flags
.
hotplug_notify
=
true
;
break
;
}
}
out:
acpi_free_pnp_ids
(
&
pnp
);
}
static
acpi_status
acpi_bus_check_add
(
acpi_handle
handle
,
u32
lvl_not_used
,
...
...
@@ -1991,12 +1996,12 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
return
AE_OK
;
}
acpi_scan_init_hotplug
(
handle
,
type
);
acpi_add_single_object
(
&
device
,
handle
,
type
,
sta
);
if
(
!
device
)
return
AE_CTRL_DEPTH
;
acpi_scan_init_hotplug
(
device
);
out:
if
(
!*
return_value
)
*
return_value
=
device
;
...
...
drivers/pci/hotplug/acpiphp.h
浏览文件 @
4b49b9fe
...
...
@@ -93,7 +93,6 @@ struct acpiphp_slot {
struct
list_head
funcs
;
/* one slot may have different
objects (i.e. for each function) */
struct
slot
*
slot
;
struct
mutex
crit_sect
;
u8
device
;
/* pci device# */
u32
flags
;
/* see below */
...
...
@@ -117,20 +116,30 @@ struct acpiphp_func {
};
struct
acpiphp_context
{
acpi_handle
handle
;
struct
acpi_hotplug_context
hp
;
struct
acpiphp_func
func
;
struct
acpiphp_bridge
*
bridge
;
unsigned
int
refcount
;
};
static
inline
struct
acpiphp_context
*
to_acpiphp_context
(
struct
acpi_hotplug_context
*
hp
)
{
return
container_of
(
hp
,
struct
acpiphp_context
,
hp
);
}
static
inline
struct
acpiphp_context
*
func_to_context
(
struct
acpiphp_func
*
func
)
{
return
container_of
(
func
,
struct
acpiphp_context
,
func
);
}
static
inline
struct
acpi_device
*
func_to_acpi_device
(
struct
acpiphp_func
*
func
)
{
return
func_to_context
(
func
)
->
hp
.
self
;
}
static
inline
acpi_handle
func_to_handle
(
struct
acpiphp_func
*
func
)
{
return
func_to_
context
(
func
)
->
handle
;
return
func_to_
acpi_device
(
func
)
->
handle
;
}
/*
...
...
@@ -158,7 +167,6 @@ struct acpiphp_attention_info
#define FUNC_HAS_STA (0x00000001)
#define FUNC_HAS_EJ0 (0x00000002)
#define FUNC_HAS_DCK (0x00000004)
/* function prototypes */
...
...
drivers/pci/hotplug/acpiphp_glue.c
浏览文件 @
4b49b9fe
...
...
@@ -58,71 +58,57 @@
static
LIST_HEAD
(
bridge_list
);
static
DEFINE_MUTEX
(
bridge_mutex
);
static
DEFINE_MUTEX
(
acpiphp_context_lock
);
static
void
handle_hotplug_event
(
acpi_handle
handle
,
u32
type
,
void
*
data
);
static
int
acpiphp_hotplug_event
(
struct
acpi_device
*
adev
,
u32
type
);
static
void
acpiphp_sanitize_bus
(
struct
pci_bus
*
bus
);
static
void
acpiphp_set_hpp_values
(
struct
pci_bus
*
bus
);
static
void
hotplug_event
(
acpi_handle
handle
,
u32
type
,
void
*
data
);
static
void
hotplug_event
(
u32
type
,
struct
acpiphp_context
*
context
);
static
void
free_bridge
(
struct
kref
*
kref
);
static
void
acpiphp_context_handler
(
acpi_handle
handle
,
void
*
context
)
{
/* Intentionally empty. */
}
/**
* acpiphp_init_context - Create hotplug context and grab a reference to it.
* @
handle: ACPI object handle
to create the context for.
* @
adev: ACPI device object
to create the context for.
*
* Call under acpi
p
hp_context_lock.
* Call under acpi
_
hp_context_lock.
*/
static
struct
acpiphp_context
*
acpiphp_init_context
(
acpi_handle
handle
)
static
struct
acpiphp_context
*
acpiphp_init_context
(
struct
acpi_device
*
adev
)
{
struct
acpiphp_context
*
context
;
acpi_status
status
;
context
=
kzalloc
(
sizeof
(
*
context
),
GFP_KERNEL
);
if
(
!
context
)
return
NULL
;
context
->
handle
=
handle
;
context
->
refcount
=
1
;
status
=
acpi_attach_data
(
handle
,
acpiphp_context_handler
,
context
);
if
(
ACPI_FAILURE
(
status
))
{
kfree
(
context
);
return
NULL
;
}
acpi_set_hp_context
(
adev
,
&
context
->
hp
,
acpiphp_hotplug_event
);
return
context
;
}
/**
* acpiphp_get_context - Get hotplug context and grab a reference to it.
* @
handle: ACPI object handle
to get the context for.
* @
adev: ACPI device object
to get the context for.
*
* Call under acpi
p
hp_context_lock.
* Call under acpi
_
hp_context_lock.
*/
static
struct
acpiphp_context
*
acpiphp_get_context
(
acpi_handle
handle
)
static
struct
acpiphp_context
*
acpiphp_get_context
(
struct
acpi_device
*
adev
)
{
struct
acpiphp_context
*
context
=
NULL
;
acpi_status
status
;
void
*
data
;
struct
acpiphp_context
*
context
;
status
=
acpi_get_data
(
handle
,
acpiphp_context_handler
,
&
data
);
if
(
ACPI_SUCCESS
(
status
))
{
context
=
data
;
context
->
refcount
++
;
}
if
(
!
adev
->
hp
)
return
NULL
;
context
=
to_acpiphp_context
(
adev
->
hp
)
;
context
->
refcount
++
;
return
context
;
}
/**
* acpiphp_put_context - Drop a reference to ACPI hotplug context.
* @
handle: ACPI object handle to put the context for
.
* @
context: ACPI hotplug context to drop a reference to
.
*
* The context object is removed if there are no more references to it.
*
* Call under acpi
p
hp_context_lock.
* Call under acpi
_
hp_context_lock.
*/
static
void
acpiphp_put_context
(
struct
acpiphp_context
*
context
)
{
...
...
@@ -130,7 +116,7 @@ static void acpiphp_put_context(struct acpiphp_context *context)
return
;
WARN_ON
(
context
->
bridge
);
acpi_detach_data
(
context
->
handle
,
acpiphp_context_handler
)
;
context
->
hp
.
self
->
hp
=
NULL
;
kfree
(
context
);
}
...
...
@@ -151,7 +137,7 @@ static void free_bridge(struct kref *kref)
struct
acpiphp_slot
*
slot
,
*
next
;
struct
acpiphp_func
*
func
,
*
tmp
;
mutex_lock
(
&
acpiphp_context_lock
);
acpi_lock_hp_context
(
);
bridge
=
container_of
(
kref
,
struct
acpiphp_bridge
,
ref
);
...
...
@@ -175,7 +161,7 @@ static void free_bridge(struct kref *kref)
pci_dev_put
(
bridge
->
pci_dev
);
kfree
(
bridge
);
mutex_unlock
(
&
acpiphp_context_lock
);
acpi_unlock_hp_context
(
);
}
/*
...
...
@@ -212,22 +198,13 @@ static void post_dock_fixups(acpi_handle not_used, u32 event, void *data)
static
void
dock_event
(
acpi_handle
handle
,
u32
type
,
void
*
data
)
{
struct
acpi
php_context
*
context
;
struct
acpi
_device
*
adev
;
mutex_lock
(
&
acpiphp_context_lock
);
context
=
acpiphp_get_context
(
handle
);
if
(
!
context
||
WARN_ON
(
context
->
handle
!=
handle
)
||
context
->
func
.
parent
->
is_going_away
)
{
mutex_unlock
(
&
acpiphp_context_lock
);
return
;
adev
=
acpi_bus_get_acpi_device
(
handle
);
if
(
adev
)
{
acpiphp_hotplug_event
(
adev
,
type
);
acpi_bus_put_acpi_device
(
adev
);
}
get_bridge
(
context
->
func
.
parent
);
acpiphp_put_context
(
context
);
mutex_unlock
(
&
acpiphp_context_lock
);
hotplug_event
(
handle
,
type
,
data
);
put_bridge
(
context
->
func
.
parent
);
}
static
const
struct
acpi_dock_ops
acpiphp_dock_ops
=
{
...
...
@@ -284,6 +261,7 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,
{
struct
acpiphp_bridge
*
bridge
=
data
;
struct
acpiphp_context
*
context
;
struct
acpi_device
*
adev
;
struct
acpiphp_slot
*
slot
;
struct
acpiphp_func
*
newfunc
;
acpi_status
status
=
AE_OK
;
...
...
@@ -303,21 +281,22 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,
"can't evaluate _ADR (%#x)
\n
"
,
status
);
return
AE_OK
;
}
if
(
acpi_bus_get_device
(
handle
,
&
adev
))
return
AE_OK
;
device
=
(
adr
>>
16
)
&
0xffff
;
function
=
adr
&
0xffff
;
mutex_lock
(
&
acpiphp_context_lock
);
context
=
acpiphp_init_context
(
handle
);
acpi_lock_hp_context
(
);
context
=
acpiphp_init_context
(
adev
);
if
(
!
context
)
{
mutex_unlock
(
&
acpiphp_context_lock
);
acpi_unlock_hp_context
(
);
acpi_handle_err
(
handle
,
"No hotplug context
\n
"
);
return
AE_NOT_EXIST
;
}
newfunc
=
&
context
->
func
;
newfunc
->
function
=
function
;
newfunc
->
parent
=
bridge
;
mutex_unlock
(
&
acpiphp_context_lock
);
if
(
acpi_has_method
(
handle
,
"_EJ0"
))
newfunc
->
flags
=
FUNC_HAS_EJ0
;
...
...
@@ -325,8 +304,14 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,
if
(
acpi_has_method
(
handle
,
"_STA"
))
newfunc
->
flags
|=
FUNC_HAS_STA
;
/*
* Dock stations' notify handler should be used for dock devices instead
* of the common one, so clear hp.event in their contexts.
*/
if
(
acpi_has_method
(
handle
,
"_DCK"
))
newfunc
->
flags
|=
FUNC_HAS_DCK
;
context
->
hp
.
event
=
NULL
;
acpi_unlock_hp_context
();
/* search for objects that share the same slot */
list_for_each_entry
(
slot
,
&
bridge
->
slots
,
node
)
...
...
@@ -335,14 +320,15 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,
slot
=
kzalloc
(
sizeof
(
struct
acpiphp_slot
),
GFP_KERNEL
);
if
(
!
slot
)
{
status
=
AE_NO_MEMORY
;
goto
err
;
acpi_lock_hp_context
();
acpiphp_put_context
(
context
);
acpi_unlock_hp_context
();
return
AE_NO_MEMORY
;
}
slot
->
bus
=
bridge
->
pci_bus
;
slot
->
device
=
device
;
INIT_LIST_HEAD
(
&
slot
->
funcs
);
mutex_init
(
&
slot
->
crit_sect
);
list_add_tail
(
&
slot
->
node
,
&
bridge
->
slots
);
...
...
@@ -393,32 +379,16 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,
pr_debug
(
"failed to register dock device
\n
"
);
}
/* install notify handler */
if
(
!
(
newfunc
->
flags
&
FUNC_HAS_DCK
))
{
status
=
acpi_install_notify_handler
(
handle
,
ACPI_SYSTEM_NOTIFY
,
handle_hotplug_event
,
context
);
if
(
ACPI_FAILURE
(
status
))
acpi_handle_err
(
handle
,
"failed to install notify handler
\n
"
);
}
return
AE_OK
;
err:
mutex_lock
(
&
acpiphp_context_lock
);
acpiphp_put_context
(
context
);
mutex_unlock
(
&
acpiphp_context_lock
);
return
status
;
}
static
struct
acpiphp_bridge
*
acpiphp_
handle_to_bridge
(
acpi_handle
handle
)
static
struct
acpiphp_bridge
*
acpiphp_
dev_to_bridge
(
struct
acpi_device
*
adev
)
{
struct
acpiphp_context
*
context
;
struct
acpiphp_bridge
*
bridge
=
NULL
;
mutex_lock
(
&
acpiphp_context_lock
);
context
=
acpiphp_get_context
(
handle
);
acpi_lock_hp_context
(
);
context
=
acpiphp_get_context
(
adev
);
if
(
context
)
{
bridge
=
context
->
bridge
;
if
(
bridge
)
...
...
@@ -426,7 +396,7 @@ static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle)
acpiphp_put_context
(
context
);
}
mutex_unlock
(
&
acpiphp_context_lock
);
acpi_unlock_hp_context
(
);
return
bridge
;
}
...
...
@@ -434,22 +404,17 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
{
struct
acpiphp_slot
*
slot
;
struct
acpiphp_func
*
func
;
acpi_status
status
;
list_for_each_entry
(
slot
,
&
bridge
->
slots
,
node
)
{
list_for_each_entry
(
func
,
&
slot
->
funcs
,
sibling
)
{
acpi_handle
handle
=
func_to_handl
e
(
func
);
struct
acpi_device
*
adev
=
func_to_acpi_devic
e
(
func
);
if
(
is_dock_device
(
handle
))
unregister_hotplug_dock_device
(
handle
);
if
(
is_dock_device
(
adev
->
handle
))
unregister_hotplug_dock_device
(
adev
->
handle
);
if
(
!
(
func
->
flags
&
FUNC_HAS_DCK
))
{
status
=
acpi_remove_notify_handler
(
handle
,
ACPI_SYSTEM_NOTIFY
,
handle_hotplug_event
);
if
(
ACPI_FAILURE
(
status
))
pr_err
(
"failed to remove notify handler
\n
"
);
}
acpi_lock_hp_context
();
adev
->
hp
->
event
=
NULL
;
acpi_unlock_hp_context
();
}
slot
->
flags
|=
SLOT_IS_GOING_AWAY
;
if
(
slot
->
slot
)
...
...
@@ -460,9 +425,9 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
list_del
(
&
bridge
->
list
);
mutex_unlock
(
&
bridge_mutex
);
mutex_lock
(
&
acpiphp_context_lock
);
acpi_lock_hp_context
(
);
bridge
->
is_going_away
=
true
;
mutex_unlock
(
&
acpiphp_context_lock
);
acpi_unlock_hp_context
(
);
}
/**
...
...
@@ -492,33 +457,6 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus)
return
max
;
}
/**
* acpiphp_bus_trim - Trim device objects in an ACPI namespace subtree.
* @handle: ACPI device object handle to start from.
*/
static
void
acpiphp_bus_trim
(
acpi_handle
handle
)
{
struct
acpi_device
*
adev
=
NULL
;
acpi_bus_get_device
(
handle
,
&
adev
);
if
(
adev
)
acpi_bus_trim
(
adev
);
}
/**
* acpiphp_bus_add - Scan ACPI namespace subtree.
* @handle: ACPI object handle to start the scan from.
*/
static
void
acpiphp_bus_add
(
acpi_handle
handle
)
{
struct
acpi_device
*
adev
=
NULL
;
acpi_bus_scan
(
handle
);
acpi_bus_get_device
(
handle
,
&
adev
);
if
(
acpi_device_enumerated
(
adev
))
acpi_device_set_power
(
adev
,
ACPI_STATE_D0
);
}
static
void
acpiphp_set_acpi_region
(
struct
acpiphp_slot
*
slot
)
{
struct
acpiphp_func
*
func
;
...
...
@@ -558,9 +496,13 @@ static int acpiphp_rescan_slot(struct acpiphp_slot *slot)
{
struct
acpiphp_func
*
func
;
list_for_each_entry
(
func
,
&
slot
->
funcs
,
sibling
)
acpiphp_bus_add
(
func_to_handle
(
func
)
);
list_for_each_entry
(
func
,
&
slot
->
funcs
,
sibling
)
{
struct
acpi_device
*
adev
=
func_to_acpi_device
(
func
);
acpi_bus_scan
(
adev
->
handle
);
if
(
acpi_device_enumerated
(
adev
))
acpi_device_set_power
(
adev
,
ACPI_STATE_D0
);
}
return
pci_scan_slot
(
slot
->
bus
,
PCI_DEVFN
(
slot
->
device
,
0
));
}
...
...
@@ -625,32 +567,15 @@ static void __ref enable_slot(struct acpiphp_slot *slot)
}
}
/* return first device in slot, acquiring a reference on it */
static
struct
pci_dev
*
dev_in_slot
(
struct
acpiphp_slot
*
slot
)
{
struct
pci_bus
*
bus
=
slot
->
bus
;
struct
pci_dev
*
dev
;
struct
pci_dev
*
ret
=
NULL
;
down_read
(
&
pci_bus_sem
);
list_for_each_entry
(
dev
,
&
bus
->
devices
,
bus_list
)
if
(
PCI_SLOT
(
dev
->
devfn
)
==
slot
->
device
)
{
ret
=
pci_dev_get
(
dev
);
break
;
}
up_read
(
&
pci_bus_sem
);
return
ret
;
}
/**
* disable_slot - disable a slot
* @slot: ACPI PHP slot
*/
static
void
disable_slot
(
struct
acpiphp_slot
*
slot
)
{
struct
pci_bus
*
bus
=
slot
->
bus
;
struct
pci_dev
*
dev
,
*
prev
;
struct
acpiphp_func
*
func
;
struct
pci_dev
*
pdev
;
/*
* enable_slot() enumerates all functions in this device via
...
...
@@ -658,22 +583,18 @@ static void disable_slot(struct acpiphp_slot *slot)
* methods (_EJ0, etc.) or not. Therefore, we remove all functions
* here.
*/
while
((
pdev
=
dev_in_slot
(
slot
)))
{
pci_stop_and_remove_bus_device
(
pdev
);
pci_dev_put
(
pdev
);
}
list_for_each_entry_safe_reverse
(
dev
,
prev
,
&
bus
->
devices
,
bus_list
)
if
(
PCI_SLOT
(
dev
->
devfn
)
==
slot
->
device
)
pci_stop_and_remove_bus_device
(
dev
);
list_for_each_entry
(
func
,
&
slot
->
funcs
,
sibling
)
acpi
php_bus_trim
(
func_to_handl
e
(
func
));
acpi
_bus_trim
(
func_to_acpi_devic
e
(
func
));
slot
->
flags
&=
(
~
SLOT_ENABLED
);
}
static
bool
acpiphp_no_hotplug
(
acpi_handle
handle
)
static
bool
acpiphp_no_hotplug
(
struct
acpi_device
*
adev
)
{
struct
acpi_device
*
adev
=
NULL
;
acpi_bus_get_device
(
handle
,
&
adev
);
return
adev
&&
adev
->
flags
.
no_hotplug
;
}
...
...
@@ -682,7 +603,7 @@ static bool slot_no_hotplug(struct acpiphp_slot *slot)
struct
acpiphp_func
*
func
;
list_for_each_entry
(
func
,
&
slot
->
funcs
,
sibling
)
if
(
acpiphp_no_hotplug
(
func_to_
handl
e
(
func
)))
if
(
acpiphp_no_hotplug
(
func_to_
acpi_devic
e
(
func
)))
return
true
;
return
false
;
...
...
@@ -747,17 +668,17 @@ static inline bool device_status_valid(unsigned int sta)
*/
static
void
trim_stale_devices
(
struct
pci_dev
*
dev
)
{
acpi_handle
handle
=
ACPI_HANDLE
(
&
dev
->
dev
);
struct
acpi_device
*
adev
=
ACPI_COMPANION
(
&
dev
->
dev
);
struct
pci_bus
*
bus
=
dev
->
subordinate
;
bool
alive
=
false
;
if
(
handle
)
{
if
(
adev
)
{
acpi_status
status
;
unsigned
long
long
sta
;
status
=
acpi_evaluate_integer
(
handle
,
"_STA"
,
NULL
,
&
sta
);
status
=
acpi_evaluate_integer
(
adev
->
handle
,
"_STA"
,
NULL
,
&
sta
);
alive
=
(
ACPI_SUCCESS
(
status
)
&&
device_status_valid
(
sta
))
||
acpiphp_no_hotplug
(
handle
);
||
acpiphp_no_hotplug
(
adev
);
}
if
(
!
alive
)
{
u32
v
;
...
...
@@ -767,8 +688,8 @@ static void trim_stale_devices(struct pci_dev *dev)
}
if
(
!
alive
)
{
pci_stop_and_remove_bus_device
(
dev
);
if
(
handle
)
acpi
php_bus_trim
(
handle
);
if
(
adev
)
acpi
_bus_trim
(
adev
);
}
else
if
(
bus
)
{
struct
pci_dev
*
child
,
*
tmp
;
...
...
@@ -800,7 +721,6 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
struct
pci_bus
*
bus
=
slot
->
bus
;
struct
pci_dev
*
dev
,
*
tmp
;
mutex_lock
(
&
slot
->
crit_sect
);
if
(
slot_no_hotplug
(
slot
))
{
;
/* do nothing */
}
else
if
(
device_status_valid
(
get_slot_status
(
slot
)))
{
...
...
@@ -815,7 +735,6 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
}
else
{
disable_slot
(
slot
);
}
mutex_unlock
(
&
slot
->
crit_sect
);
}
}
...
...
@@ -855,11 +774,11 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus)
* ACPI event handlers
*/
void
acpiphp_check_host_bridge
(
acpi_handle
handle
)
void
acpiphp_check_host_bridge
(
struct
acpi_device
*
adev
)
{
struct
acpiphp_bridge
*
bridge
;
bridge
=
acpiphp_
handle_to_bridge
(
handle
);
bridge
=
acpiphp_
dev_to_bridge
(
adev
);
if
(
bridge
)
{
pci_lock_rescan_remove
();
...
...
@@ -872,73 +791,52 @@ void acpiphp_check_host_bridge(acpi_handle handle)
static
int
acpiphp_disable_and_eject_slot
(
struct
acpiphp_slot
*
slot
);
static
void
hotplug_event
(
acpi_handle
handle
,
u32
type
,
void
*
data
)
static
void
hotplug_event
(
u32
type
,
struct
acpiphp_context
*
context
)
{
struct
acpiphp_context
*
context
=
data
;
acpi_handle
handle
=
context
->
hp
.
self
->
handle
;
struct
acpiphp_func
*
func
=
&
context
->
func
;
struct
acpiphp_slot
*
slot
=
func
->
slot
;
struct
acpiphp_bridge
*
bridge
;
char
objname
[
64
];
struct
acpi_buffer
buffer
=
{
.
length
=
sizeof
(
objname
),
.
pointer
=
objname
};
mutex_lock
(
&
acpiphp_context_lock
);
acpi_lock_hp_context
(
);
bridge
=
context
->
bridge
;
if
(
bridge
)
get_bridge
(
bridge
);
mutex_unlock
(
&
acpiphp_context_lock
);
acpi_unlock_hp_context
(
);
pci_lock_rescan_remove
();
acpi_get_name
(
handle
,
ACPI_FULL_PATHNAME
,
&
buffer
);
switch
(
type
)
{
case
ACPI_NOTIFY_BUS_CHECK
:
/* bus re-enumerate */
pr_debug
(
"%s: Bus check notify on %s
\n
"
,
__func__
,
objname
);
pr_debug
(
"%s: re-enumerating slots under %s
\n
"
,
__func__
,
objname
);
if
(
bridge
)
{
acpi_handle_debug
(
handle
,
"Bus check in %s()
\n
"
,
__func__
);
if
(
bridge
)
acpiphp_check_bridge
(
bridge
);
}
else
{
struct
acpiphp_slot
*
slot
=
func
->
slot
;
if
(
slot
->
flags
&
SLOT_IS_GOING_AWAY
)
break
;
mutex_lock
(
&
slot
->
crit_sect
);
else
if
(
!
(
slot
->
flags
&
SLOT_IS_GOING_AWAY
))
enable_slot
(
slot
);
mutex_unlock
(
&
slot
->
crit_sect
);
}
break
;
case
ACPI_NOTIFY_DEVICE_CHECK
:
/* device check */
pr_debug
(
"%s: Device check notify on %s
\n
"
,
__func__
,
objname
);
acpi_handle_debug
(
handle
,
"Device check in %s()
\n
"
,
__func__
);
if
(
bridge
)
{
acpiphp_check_bridge
(
bridge
);
}
else
{
struct
acpiphp_slot
*
slot
=
func
->
slot
;
int
ret
;
if
(
slot
->
flags
&
SLOT_IS_GOING_AWAY
)
break
;
}
else
if
(
!
(
slot
->
flags
&
SLOT_IS_GOING_AWAY
))
{
/*
* Check if anything has changed in the slot and rescan
* from the parent if that's the case.
*/
mutex_lock
(
&
slot
->
crit_sect
);
ret
=
acpiphp_rescan_slot
(
slot
);
mutex_unlock
(
&
slot
->
crit_sect
);
if
(
ret
)
if
(
acpiphp_rescan_slot
(
slot
))
acpiphp_check_bridge
(
func
->
parent
);
}
break
;
case
ACPI_NOTIFY_EJECT_REQUEST
:
/* request device eject */
pr_debug
(
"%s: Device eject notify on %s
\n
"
,
__func__
,
objname
);
acpiphp_disable_and_eject_slot
(
func
->
slot
);
acpi_handle_debug
(
handle
,
"Eject request in %s()
\n
"
,
__func__
);
acpiphp_disable_and_eject_slot
(
slot
);
break
;
}
...
...
@@ -947,106 +845,48 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data)
put_bridge
(
bridge
);
}
static
void
hotplug_event_work
(
void
*
data
,
u32
type
)
{
struct
acpiphp_context
*
context
=
data
;
acpi_handle
handle
=
context
->
handle
;
acpi_scan_lock_acquire
();
hotplug_event
(
handle
,
type
,
context
);
acpi_scan_lock_release
();
acpi_evaluate_hotplug_ost
(
handle
,
type
,
ACPI_OST_SC_SUCCESS
,
NULL
);
put_bridge
(
context
->
func
.
parent
);
}
/**
* handle_hotplug_event - handle ACPI hotplug event
* @handle: Notify()'ed acpi_handle
* @type: Notify code
* @data: pointer to acpiphp_context structure
*
* Handles ACPI event notification on slots.
*/
static
void
handle_hotplug_event
(
acpi_handle
handle
,
u32
type
,
void
*
data
)
static
int
acpiphp_hotplug_event
(
struct
acpi_device
*
adev
,
u32
type
)
{
struct
acpiphp_context
*
context
;
u32
ost_code
=
ACPI_OST_SC_SUCCESS
;
acpi_status
status
;
switch
(
type
)
{
case
ACPI_NOTIFY_BUS_CHECK
:
case
ACPI_NOTIFY_DEVICE_CHECK
:
break
;
case
ACPI_NOTIFY_EJECT_REQUEST
:
ost_code
=
ACPI_OST_SC_EJECT_IN_PROGRESS
;
acpi_evaluate_hotplug_ost
(
handle
,
type
,
ost_code
,
NULL
);
break
;
case
ACPI_NOTIFY_DEVICE_WAKE
:
return
;
case
ACPI_NOTIFY_FREQUENCY_MISMATCH
:
acpi_handle_err
(
handle
,
"Device cannot be configured due "
"to a frequency mismatch
\n
"
);
goto
out
;
case
ACPI_NOTIFY_BUS_MODE_MISMATCH
:
acpi_handle_err
(
handle
,
"Device cannot be configured due "
"to a bus mode mismatch
\n
"
);
goto
out
;
case
ACPI_NOTIFY_POWER_FAULT
:
acpi_handle_err
(
handle
,
"Device has suffered a power fault
\n
"
);
goto
out
;
default:
acpi_handle_warn
(
handle
,
"Unsupported event type 0x%x
\n
"
,
type
);
ost_code
=
ACPI_OST_SC_UNRECOGNIZED_NOTIFY
;
goto
out
;
acpi_lock_hp_context
();
context
=
acpiphp_get_context
(
adev
);
if
(
!
context
||
context
->
func
.
parent
->
is_going_away
)
{
acpi_unlock_hp_context
();
return
-
ENODATA
;
}
mutex_lock
(
&
acpiphp_context_lock
);
context
=
acpiphp_get_context
(
handle
);
if
(
!
context
||
WARN_ON
(
context
->
handle
!=
handle
)
||
context
->
func
.
parent
->
is_going_away
)
goto
err_out
;
get_bridge
(
context
->
func
.
parent
);
acpiphp_put_context
(
context
);
status
=
acpi_hotplug_execute
(
hotplug_event_work
,
context
,
type
);
if
(
ACPI_SUCCESS
(
status
))
{
mutex_unlock
(
&
acpiphp_context_lock
);
return
;
}
put_bridge
(
context
->
func
.
parent
);
acpi_unlock_hp_context
();
err_out:
mutex_unlock
(
&
acpiphp_context_lock
);
ost_code
=
ACPI_OST_SC_NON_SPECIFIC_FAILURE
;
hotplug_event
(
type
,
context
);
out:
acpi_evaluate_hotplug_ost
(
handle
,
type
,
ost_code
,
NULL
)
;
put_bridge
(
context
->
func
.
parent
);
return
0
;
}
/*
* Create hotplug slots for the PCI bus.
* It should always return 0 to avoid skipping following notifiers.
/**
* acpiphp_enumerate_slots - Enumerate PCI slots for a given bus.
* @bus: PCI bus to enumerate the slots for.
*
* A "slot" is an object associated with a PCI device number. All functions
* (PCI devices) with the same bus and device number belong to the same slot.
*/
void
acpiphp_enumerate_slots
(
struct
pci_bus
*
bus
)
{
struct
acpiphp_bridge
*
bridge
;
struct
acpi_device
*
adev
;
acpi_handle
handle
;
acpi_status
status
;
if
(
acpiphp_disabled
)
return
;
handle
=
ACPI_HANDLE
(
bus
->
bridge
);
if
(
!
handle
)
adev
=
ACPI_COMPANION
(
bus
->
bridge
);
if
(
!
adev
)
return
;
handle
=
adev
->
handle
;
bridge
=
kzalloc
(
sizeof
(
struct
acpiphp_bridge
),
GFP_KERNEL
);
if
(
!
bridge
)
{
acpi_handle_err
(
handle
,
"No memory for bridge object
\n
"
);
...
...
@@ -1074,10 +914,10 @@ void acpiphp_enumerate_slots(struct pci_bus *bus)
* parent is going to be handled by pciehp, in which case this
* bridge is not interesting to us either.
*/
mutex_lock
(
&
acpiphp_context_lock
);
context
=
acpiphp_get_context
(
handle
);
acpi_lock_hp_context
(
);
context
=
acpiphp_get_context
(
adev
);
if
(
!
context
)
{
mutex_unlock
(
&
acpiphp_context_lock
);
acpi_unlock_hp_context
(
);
put_device
(
&
bus
->
dev
);
pci_dev_put
(
bridge
->
pci_dev
);
kfree
(
bridge
);
...
...
@@ -1087,7 +927,7 @@ void acpiphp_enumerate_slots(struct pci_bus *bus)
context
->
bridge
=
bridge
;
/* Get a reference to the parent bridge. */
get_bridge
(
context
->
func
.
parent
);
mutex_unlock
(
&
acpiphp_context_lock
);
acpi_unlock_hp_context
(
);
}
/* must be added to the list prior to calling register_slot */
...
...
@@ -1105,7 +945,10 @@ void acpiphp_enumerate_slots(struct pci_bus *bus)
}
}
/* Destroy hotplug slots associated with the PCI bus */
/**
* acpiphp_remove_slots - Remove slot objects associated with a given bus.
* @bus: PCI bus to remove the slot objects for.
*/
void
acpiphp_remove_slots
(
struct
pci_bus
*
bus
)
{
struct
acpiphp_bridge
*
bridge
;
...
...
@@ -1136,13 +979,10 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot)
if
(
slot
->
flags
&
SLOT_IS_GOING_AWAY
)
return
-
ENODEV
;
mutex_lock
(
&
slot
->
crit_sect
);
/* configure all functions */
if
(
!
(
slot
->
flags
&
SLOT_ENABLED
))
enable_slot
(
slot
);
mutex_unlock
(
&
slot
->
crit_sect
);
pci_unlock_rescan_remove
();
return
0
;
}
...
...
@@ -1158,8 +998,6 @@ static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot)
if
(
slot
->
flags
&
SLOT_IS_GOING_AWAY
)
return
-
ENODEV
;
mutex_lock
(
&
slot
->
crit_sect
);
/* unconfigure all functions */
disable_slot
(
slot
);
...
...
@@ -1173,7 +1011,6 @@ static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot)
break
;
}
mutex_unlock
(
&
slot
->
crit_sect
);
return
0
;
}
...
...
@@ -1181,9 +1018,15 @@ int acpiphp_disable_slot(struct acpiphp_slot *slot)
{
int
ret
;
/*
* Acquire acpi_scan_lock to ensure that the execution of _EJ0 in
* acpiphp_disable_and_eject_slot() will be synchronized properly.
*/
acpi_scan_lock_acquire
();
pci_lock_rescan_remove
();
ret
=
acpiphp_disable_and_eject_slot
(
slot
);
pci_unlock_rescan_remove
();
acpi_scan_lock_release
();
return
ret
;
}
...
...
include/acpi/acpi_bus.h
浏览文件 @
4b49b9fe
...
...
@@ -136,6 +136,16 @@ struct acpi_scan_handler {
struct
acpi_hotplug_profile
hotplug
;
};
/*
* ACPI Hotplug Context
* --------------------
*/
struct
acpi_hotplug_context
{
struct
acpi_device
*
self
;
int
(
*
event
)(
struct
acpi_device
*
,
u32
);
};
/*
* ACPI Driver
* -----------
...
...
@@ -190,7 +200,8 @@ struct acpi_device_flags {
u32
initialized
:
1
;
u32
visited
:
1
;
u32
no_hotplug
:
1
;
u32
reserved
:
24
;
u32
hotplug_notify
:
1
;
u32
reserved
:
23
;
};
/* File System */
...
...
@@ -329,6 +340,7 @@ struct acpi_device {
struct
acpi_device_perf
performance
;
struct
acpi_device_dir
dir
;
struct
acpi_scan_handler
*
handler
;
struct
acpi_hotplug_context
*
hp
;
struct
acpi_driver
*
driver
;
void
*
driver_data
;
struct
device
dev
;
...
...
@@ -351,6 +363,15 @@ static inline void acpi_set_device_status(struct acpi_device *adev, u32 sta)
*
((
u32
*
)
&
adev
->
status
)
=
sta
;
}
static
inline
void
acpi_set_hp_context
(
struct
acpi_device
*
adev
,
struct
acpi_hotplug_context
*
hp
,
int
(
*
event
)(
struct
acpi_device
*
,
u32
))
{
hp
->
self
=
adev
;
hp
->
event
=
event
;
adev
->
hp
=
hp
;
}
/* acpi_device.dev.bus == &acpi_bus_type */
extern
struct
bus_type
acpi_bus_type
;
...
...
@@ -381,6 +402,8 @@ extern int unregister_acpi_notifier(struct notifier_block *);
*/
int
acpi_bus_get_device
(
acpi_handle
handle
,
struct
acpi_device
**
device
);
struct
acpi_device
*
acpi_bus_get_acpi_device
(
acpi_handle
handle
);
void
acpi_bus_put_acpi_device
(
struct
acpi_device
*
adev
);
acpi_status
acpi_bus_get_status_handle
(
acpi_handle
handle
,
unsigned
long
long
*
sta
);
int
acpi_bus_get_status
(
struct
acpi_device
*
device
);
...
...
@@ -402,6 +425,8 @@ static inline bool acpi_bus_can_wakeup(acpi_handle handle) { return false; }
void
acpi_scan_lock_acquire
(
void
);
void
acpi_scan_lock_release
(
void
);
void
acpi_lock_hp_context
(
void
);
void
acpi_unlock_hp_context
(
void
);
int
acpi_scan_add_handler
(
struct
acpi_scan_handler
*
handler
);
int
acpi_bus_register_driver
(
struct
acpi_driver
*
driver
);
void
acpi_bus_unregister_driver
(
struct
acpi_driver
*
driver
);
...
...
include/acpi/acpixf.h
浏览文件 @
4b49b9fe
...
...
@@ -229,6 +229,10 @@ acpi_attach_data(acpi_handle object, acpi_object_handler handler, void *data);
acpi_status
acpi_detach_data
(
acpi_handle
object
,
acpi_object_handler
handler
);
acpi_status
acpi_get_data_full
(
acpi_handle
object
,
acpi_object_handler
handler
,
void
**
data
,
void
(
*
callback
)(
void
*
));
acpi_status
acpi_get_data
(
acpi_handle
object
,
acpi_object_handler
handler
,
void
**
data
);
...
...
include/linux/pci-acpi.h
浏览文件 @
4b49b9fe
...
...
@@ -59,12 +59,12 @@ static inline void acpi_pci_slot_remove(struct pci_bus *bus) { }
void
acpiphp_init
(
void
);
void
acpiphp_enumerate_slots
(
struct
pci_bus
*
bus
);
void
acpiphp_remove_slots
(
struct
pci_bus
*
bus
);
void
acpiphp_check_host_bridge
(
acpi_handle
handle
);
void
acpiphp_check_host_bridge
(
struct
acpi_device
*
adev
);
#else
static
inline
void
acpiphp_init
(
void
)
{
}
static
inline
void
acpiphp_enumerate_slots
(
struct
pci_bus
*
bus
)
{
}
static
inline
void
acpiphp_remove_slots
(
struct
pci_bus
*
bus
)
{
}
static
inline
void
acpiphp_check_host_bridge
(
acpi_handle
handle
)
{
}
static
inline
void
acpiphp_check_host_bridge
(
struct
acpi_device
*
adev
)
{
}
#endif
#else
/* CONFIG_ACPI */
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录