Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
c8f7a62c
R
raspberrypi-kernel
项目概览
openeuler
/
raspberrypi-kernel
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
raspberrypi-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
c8f7a62c
编写于
7月 09, 2006
作者:
L
Len Brown
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Revert "Revert "ACPI: dock driver""
This reverts
953969dd
commit.
上级
953969dd
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
788 addition
and
1 deletion
+788
-1
drivers/acpi/Kconfig
drivers/acpi/Kconfig
+7
-0
drivers/acpi/Makefile
drivers/acpi/Makefile
+1
-0
drivers/acpi/dock.c
drivers/acpi/dock.c
+739
-0
drivers/acpi/scan.c
drivers/acpi/scan.c
+23
-0
include/acpi/acpi_bus.h
include/acpi/acpi_bus.h
+1
-1
include/acpi/acpi_drivers.h
include/acpi/acpi_drivers.h
+17
-0
未找到文件。
drivers/acpi/Kconfig
浏览文件 @
c8f7a62c
...
...
@@ -133,6 +133,13 @@ config ACPI_FAN
This driver adds support for ACPI fan devices, allowing user-mode
applications to perform basic fan control (on, off, status).
config ACPI_DOCK
tristate "Dock"
depends on !ACPI_IBM_DOCK
default y
help
This driver adds support for ACPI controlled docking stations
config ACPI_PROCESSOR
tristate "Processor"
default y
...
...
drivers/acpi/Makefile
浏览文件 @
c8f7a62c
...
...
@@ -42,6 +42,7 @@ obj-$(CONFIG_ACPI_BATTERY) += battery.o
obj-$(CONFIG_ACPI_BUTTON)
+=
button.o
obj-$(CONFIG_ACPI_EC)
+=
ec.o
obj-$(CONFIG_ACPI_FAN)
+=
fan.o
obj-$(CONFIG_ACPI_DOCK)
+=
dock.o
obj-$(CONFIG_ACPI_VIDEO)
+=
video.o
obj-$(CONFIG_ACPI_HOTKEY)
+=
hotkey.o
obj-y
+=
pci_root.o pci_link.o pci_irq.o pci_bind.o
...
...
drivers/acpi/dock.c
0 → 100644
浏览文件 @
c8f7a62c
/*
* dock.c - ACPI dock station driver
*
* Copyright (C) 2006 Kristen Carlson Accardi <kristen.c.accardi@intel.com>
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/notifier.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#define ACPI_DOCK_DRIVER_NAME "ACPI Dock Station Driver"
ACPI_MODULE_NAME
(
"dock"
)
MODULE_AUTHOR
(
"Kristen Carlson Accardi"
);
MODULE_DESCRIPTION
(
ACPI_DOCK_DRIVER_NAME
);
MODULE_LICENSE
(
"GPL"
);
static
struct
atomic_notifier_head
dock_notifier_list
;
struct
dock_station
{
acpi_handle
handle
;
unsigned
long
last_dock_time
;
u32
flags
;
spinlock_t
dd_lock
;
spinlock_t
hp_lock
;
struct
list_head
dependent_devices
;
struct
list_head
hotplug_devices
;
};
struct
dock_dependent_device
{
struct
list_head
list
;
struct
list_head
hotplug_list
;
acpi_handle
handle
;
acpi_notify_handler
handler
;
void
*
context
;
};
#define DOCK_DOCKING 0x00000001
#define DOCK_EVENT KOBJ_DOCK
#define UNDOCK_EVENT KOBJ_UNDOCK
static
struct
dock_station
*
dock_station
;
/*****************************************************************************
* Dock Dependent device functions *
*****************************************************************************/
/**
* alloc_dock_dependent_device - allocate and init a dependent device
* @handle: the acpi_handle of the dependent device
*
* Allocate memory for a dependent device structure for a device referenced
* by the acpi handle
*/
static
struct
dock_dependent_device
*
alloc_dock_dependent_device
(
acpi_handle
handle
)
{
struct
dock_dependent_device
*
dd
;
dd
=
kzalloc
(
sizeof
(
*
dd
),
GFP_KERNEL
);
if
(
dd
)
{
dd
->
handle
=
handle
;
INIT_LIST_HEAD
(
&
dd
->
list
);
INIT_LIST_HEAD
(
&
dd
->
hotplug_list
);
}
return
dd
;
}
/**
* add_dock_dependent_device - associate a device with the dock station
* @ds: The dock station
* @dd: The dependent device
*
* Add the dependent device to the dock's dependent device list.
*/
static
void
add_dock_dependent_device
(
struct
dock_station
*
ds
,
struct
dock_dependent_device
*
dd
)
{
spin_lock
(
&
ds
->
dd_lock
);
list_add_tail
(
&
dd
->
list
,
&
ds
->
dependent_devices
);
spin_unlock
(
&
ds
->
dd_lock
);
}
/**
* dock_add_hotplug_device - associate a hotplug handler with the dock station
* @ds: The dock station
* @dd: The dependent device struct
*
* Add the dependent device to the dock's hotplug device list
*/
static
void
dock_add_hotplug_device
(
struct
dock_station
*
ds
,
struct
dock_dependent_device
*
dd
)
{
spin_lock
(
&
ds
->
hp_lock
);
list_add_tail
(
&
dd
->
hotplug_list
,
&
ds
->
hotplug_devices
);
spin_unlock
(
&
ds
->
hp_lock
);
}
/**
* dock_del_hotplug_device - remove a hotplug handler from the dock station
* @ds: The dock station
* @dd: the dependent device struct
*
* Delete the dependent device from the dock's hotplug device list
*/
static
void
dock_del_hotplug_device
(
struct
dock_station
*
ds
,
struct
dock_dependent_device
*
dd
)
{
spin_lock
(
&
ds
->
hp_lock
);
list_del
(
&
dd
->
hotplug_list
);
spin_unlock
(
&
ds
->
hp_lock
);
}
/**
* find_dock_dependent_device - get a device dependent on this dock
* @ds: the dock station
* @handle: the acpi_handle of the device we want
*
* iterate over the dependent device list for this dock. If the
* dependent device matches the handle, return.
*/
static
struct
dock_dependent_device
*
find_dock_dependent_device
(
struct
dock_station
*
ds
,
acpi_handle
handle
)
{
struct
dock_dependent_device
*
dd
;
spin_lock
(
&
ds
->
dd_lock
);
list_for_each_entry
(
dd
,
&
ds
->
dependent_devices
,
list
)
{
if
(
handle
==
dd
->
handle
)
{
spin_unlock
(
&
ds
->
dd_lock
);
return
dd
;
}
}
spin_unlock
(
&
ds
->
dd_lock
);
return
NULL
;
}
/*****************************************************************************
* Dock functions *
*****************************************************************************/
/**
* is_dock - see if a device is a dock station
* @handle: acpi handle of the device
*
* If an acpi object has a _DCK method, then it is by definition a dock
* station, so return true.
*/
static
int
is_dock
(
acpi_handle
handle
)
{
acpi_status
status
;
acpi_handle
tmp
;
status
=
acpi_get_handle
(
handle
,
"_DCK"
,
&
tmp
);
if
(
ACPI_FAILURE
(
status
))
return
0
;
return
1
;
}
/**
* is_dock_device - see if a device is on a dock station
* @handle: acpi handle of the device
*
* If this device is either the dock station itself,
* or is a device dependent on the dock station, then it
* is a dock device
*/
int
is_dock_device
(
acpi_handle
handle
)
{
if
(
!
dock_station
)
return
0
;
if
(
is_dock
(
handle
)
||
find_dock_dependent_device
(
dock_station
,
handle
))
return
1
;
return
0
;
}
EXPORT_SYMBOL_GPL
(
is_dock_device
);
/**
* dock_present - see if the dock station is present.
* @ds: the dock station
*
* execute the _STA method. note that present does not
* imply that we are docked.
*/
static
int
dock_present
(
struct
dock_station
*
ds
)
{
unsigned
long
sta
;
acpi_status
status
;
if
(
ds
)
{
status
=
acpi_evaluate_integer
(
ds
->
handle
,
"_STA"
,
NULL
,
&
sta
);
if
(
ACPI_SUCCESS
(
status
)
&&
sta
)
return
1
;
}
return
0
;
}
/**
* dock_create_acpi_device - add new devices to acpi
* @handle - handle of the device to add
*
* This function will create a new acpi_device for the given
* handle if one does not exist already. This should cause
* acpi to scan for drivers for the given devices, and call
* matching driver's add routine.
*
* Returns a pointer to the acpi_device corresponding to the handle.
*/
static
struct
acpi_device
*
dock_create_acpi_device
(
acpi_handle
handle
)
{
struct
acpi_device
*
device
=
NULL
;
struct
acpi_device
*
parent_device
;
acpi_handle
parent
;
int
ret
;
if
(
acpi_bus_get_device
(
handle
,
&
device
))
{
/*
* no device created for this object,
* so we should create one.
*/
acpi_get_parent
(
handle
,
&
parent
);
if
(
acpi_bus_get_device
(
parent
,
&
parent_device
))
parent_device
=
NULL
;
ret
=
acpi_bus_add
(
&
device
,
parent_device
,
handle
,
ACPI_BUS_TYPE_DEVICE
);
if
(
ret
)
{
pr_debug
(
"error adding bus, %x
\n
"
,
-
ret
);
return
NULL
;
}
}
return
device
;
}
/**
* dock_remove_acpi_device - remove the acpi_device struct from acpi
* @handle - the handle of the device to remove
*
* Tell acpi to remove the acpi_device. This should cause any loaded
* driver to have it's remove routine called.
*/
static
void
dock_remove_acpi_device
(
acpi_handle
handle
)
{
struct
acpi_device
*
device
;
int
ret
;
if
(
!
acpi_bus_get_device
(
handle
,
&
device
))
{
ret
=
acpi_bus_trim
(
device
,
1
);
if
(
ret
)
pr_debug
(
"error removing bus, %x
\n
"
,
-
ret
);
}
}
/**
* hotplug_dock_devices - insert or remove devices on the dock station
* @ds: the dock station
* @event: either bus check or eject request
*
* Some devices on the dock station need to have drivers called
* to perform hotplug operations after a dock event has occurred.
* Traverse the list of dock devices that have registered a
* hotplug handler, and call the handler.
*/
static
void
hotplug_dock_devices
(
struct
dock_station
*
ds
,
u32
event
)
{
struct
dock_dependent_device
*
dd
;
spin_lock
(
&
ds
->
hp_lock
);
/*
* First call driver specific hotplug functions
*/
list_for_each_entry
(
dd
,
&
ds
->
hotplug_devices
,
hotplug_list
)
{
if
(
dd
->
handler
)
dd
->
handler
(
dd
->
handle
,
event
,
dd
->
context
);
}
/*
* Now make sure that an acpi_device is created for each
* dependent device, or removed if this is an eject request.
* This will cause acpi_drivers to be stopped/started if they
* exist
*/
list_for_each_entry
(
dd
,
&
ds
->
dependent_devices
,
list
)
{
if
(
event
==
ACPI_NOTIFY_EJECT_REQUEST
)
dock_remove_acpi_device
(
dd
->
handle
);
else
dock_create_acpi_device
(
dd
->
handle
);
}
spin_unlock
(
&
ds
->
hp_lock
);
}
static
void
dock_event
(
struct
dock_station
*
ds
,
u32
event
,
int
num
)
{
struct
acpi_device
*
device
;
device
=
dock_create_acpi_device
(
ds
->
handle
);
if
(
device
)
kobject_uevent
(
&
device
->
kobj
,
num
);
}
/**
* eject_dock - respond to a dock eject request
* @ds: the dock station
*
* This is called after _DCK is called, to execute the dock station's
* _EJ0 method.
*/
static
void
eject_dock
(
struct
dock_station
*
ds
)
{
struct
acpi_object_list
arg_list
;
union
acpi_object
arg
;
acpi_status
status
;
acpi_handle
tmp
;
/* all dock devices should have _EJ0, but check anyway */
status
=
acpi_get_handle
(
ds
->
handle
,
"_EJ0"
,
&
tmp
);
if
(
ACPI_FAILURE
(
status
))
{
pr_debug
(
"No _EJ0 support for dock device
\n
"
);
return
;
}
arg_list
.
count
=
1
;
arg_list
.
pointer
=
&
arg
;
arg
.
type
=
ACPI_TYPE_INTEGER
;
arg
.
integer
.
value
=
1
;
if
(
ACPI_FAILURE
(
acpi_evaluate_object
(
ds
->
handle
,
"_EJ0"
,
&
arg_list
,
NULL
)))
pr_debug
(
"Failed to evaluate _EJ0!
\n
"
);
}
/**
* handle_dock - handle a dock event
* @ds: the dock station
* @dock: to dock, or undock - that is the question
*
* Execute the _DCK method in response to an acpi event
*/
static
void
handle_dock
(
struct
dock_station
*
ds
,
int
dock
)
{
acpi_status
status
;
struct
acpi_object_list
arg_list
;
union
acpi_object
arg
;
struct
acpi_buffer
buffer
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
struct
acpi_buffer
name_buffer
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
union
acpi_object
*
obj
;
acpi_get_name
(
ds
->
handle
,
ACPI_FULL_PATHNAME
,
&
name_buffer
);
obj
=
name_buffer
.
pointer
;
printk
(
KERN_INFO
PREFIX
"%s
\n
"
,
dock
?
"docking"
:
"undocking"
);
/* _DCK method has one argument */
arg_list
.
count
=
1
;
arg_list
.
pointer
=
&
arg
;
arg
.
type
=
ACPI_TYPE_INTEGER
;
arg
.
integer
.
value
=
dock
;
status
=
acpi_evaluate_object
(
ds
->
handle
,
"_DCK"
,
&
arg_list
,
&
buffer
);
if
(
ACPI_FAILURE
(
status
))
pr_debug
(
"%s: failed to execute _DCK
\n
"
,
obj
->
string
.
pointer
);
kfree
(
buffer
.
pointer
);
kfree
(
name_buffer
.
pointer
);
}
static
inline
void
dock
(
struct
dock_station
*
ds
)
{
handle_dock
(
ds
,
1
);
}
static
inline
void
undock
(
struct
dock_station
*
ds
)
{
handle_dock
(
ds
,
0
);
}
static
inline
void
begin_dock
(
struct
dock_station
*
ds
)
{
ds
->
flags
|=
DOCK_DOCKING
;
}
static
inline
void
complete_dock
(
struct
dock_station
*
ds
)
{
ds
->
flags
&=
~
(
DOCK_DOCKING
);
ds
->
last_dock_time
=
jiffies
;
}
/**
* dock_in_progress - see if we are in the middle of handling a dock event
* @ds: the dock station
*
* Sometimes while docking, false dock events can be sent to the driver
* because good connections aren't made or some other reason. Ignore these
* if we are in the middle of doing something.
*/
static
int
dock_in_progress
(
struct
dock_station
*
ds
)
{
if
((
ds
->
flags
&
DOCK_DOCKING
)
||
time_before
(
jiffies
,
(
ds
->
last_dock_time
+
HZ
)))
return
1
;
return
0
;
}
/**
* register_dock_notifier - add yourself to the dock notifier list
* @nb: the callers notifier block
*
* If a driver wishes to be notified about dock events, they can
* use this function to put a notifier block on the dock notifier list.
* this notifier call chain will be called after a dock event, but
* before hotplugging any new devices.
*/
int
register_dock_notifier
(
struct
notifier_block
*
nb
)
{
return
atomic_notifier_chain_register
(
&
dock_notifier_list
,
nb
);
}
EXPORT_SYMBOL_GPL
(
register_dock_notifier
);
/**
* unregister_dock_notifier - remove yourself from the dock notifier list
* @nb: the callers notifier block
*/
void
unregister_dock_notifier
(
struct
notifier_block
*
nb
)
{
atomic_notifier_chain_unregister
(
&
dock_notifier_list
,
nb
);
}
EXPORT_SYMBOL_GPL
(
unregister_dock_notifier
);
/**
* register_hotplug_dock_device - register a hotplug function
* @handle: the handle of the device
* @handler: the acpi_notifier_handler to call after docking
* @context: device specific data
*
* If a driver would like to perform a hotplug operation after a dock
* event, they can register an acpi_notifiy_handler to be called by
* the dock driver after _DCK is executed.
*/
int
register_hotplug_dock_device
(
acpi_handle
handle
,
acpi_notify_handler
handler
,
void
*
context
)
{
struct
dock_dependent_device
*
dd
;
if
(
!
dock_station
)
return
-
ENODEV
;
/*
* make sure this handle is for a device dependent on the dock,
* this would include the dock station itself
*/
dd
=
find_dock_dependent_device
(
dock_station
,
handle
);
if
(
dd
)
{
dd
->
handler
=
handler
;
dd
->
context
=
context
;
dock_add_hotplug_device
(
dock_station
,
dd
);
return
0
;
}
return
-
EINVAL
;
}
EXPORT_SYMBOL_GPL
(
register_hotplug_dock_device
);
/**
* unregister_hotplug_dock_device - remove yourself from the hotplug list
* @handle: the acpi handle of the device
*/
void
unregister_hotplug_dock_device
(
acpi_handle
handle
)
{
struct
dock_dependent_device
*
dd
;
if
(
!
dock_station
)
return
;
dd
=
find_dock_dependent_device
(
dock_station
,
handle
);
if
(
dd
)
dock_del_hotplug_device
(
dock_station
,
dd
);
}
EXPORT_SYMBOL_GPL
(
unregister_hotplug_dock_device
);
/**
* dock_notify - act upon an acpi dock notification
* @handle: the dock station handle
* @event: the acpi event
* @data: our driver data struct
*
* If we are notified to dock, then check to see if the dock is
* present and then dock. Notify all drivers of the dock event,
* and then hotplug and devices that may need hotplugging. For undock
* check to make sure the dock device is still present, then undock
* and hotremove all the devices that may need removing.
*/
static
void
dock_notify
(
acpi_handle
handle
,
u32
event
,
void
*
data
)
{
struct
dock_station
*
ds
=
(
struct
dock_station
*
)
data
;
switch
(
event
)
{
case
ACPI_NOTIFY_BUS_CHECK
:
if
(
!
dock_in_progress
(
ds
)
&&
dock_present
(
ds
))
{
begin_dock
(
ds
);
dock
(
ds
);
if
(
!
dock_present
(
ds
))
{
printk
(
KERN_ERR
PREFIX
"Unable to dock!
\n
"
);
break
;
}
atomic_notifier_call_chain
(
&
dock_notifier_list
,
event
,
NULL
);
hotplug_dock_devices
(
ds
,
event
);
complete_dock
(
ds
);
dock_event
(
ds
,
event
,
DOCK_EVENT
);
}
break
;
case
ACPI_NOTIFY_DEVICE_CHECK
:
/*
* According to acpi spec 3.0a, if a DEVICE_CHECK notification
* is sent and _DCK is present, it is assumed to mean an
* undock request. This notify routine will only be called
* for objects defining _DCK, so we will fall through to eject
* request here. However, we will pass an eject request through
* to the driver who wish to hotplug.
*/
case
ACPI_NOTIFY_EJECT_REQUEST
:
if
(
!
dock_in_progress
(
ds
)
&&
dock_present
(
ds
))
{
/*
* here we need to generate the undock
* event prior to actually doing the undock
* so that the device struct still exists.
*/
dock_event
(
ds
,
event
,
UNDOCK_EVENT
);
hotplug_dock_devices
(
ds
,
ACPI_NOTIFY_EJECT_REQUEST
);
undock
(
ds
);
eject_dock
(
ds
);
if
(
dock_present
(
ds
))
printk
(
KERN_ERR
PREFIX
"Unable to undock!
\n
"
);
}
break
;
default:
printk
(
KERN_ERR
PREFIX
"Unknown dock event %d
\n
"
,
event
);
}
}
/**
* find_dock_devices - find devices on the dock station
* @handle: the handle of the device we are examining
* @lvl: unused
* @context: the dock station private data
* @rv: unused
*
* This function is called by acpi_walk_namespace. It will
* check to see if an object has an _EJD method. If it does, then it
* will see if it is dependent on the dock station.
*/
static
acpi_status
find_dock_devices
(
acpi_handle
handle
,
u32
lvl
,
void
*
context
,
void
**
rv
)
{
acpi_status
status
;
acpi_handle
tmp
;
struct
dock_station
*
ds
=
(
struct
dock_station
*
)
context
;
struct
dock_dependent_device
*
dd
;
status
=
acpi_bus_get_ejd
(
handle
,
&
tmp
);
if
(
ACPI_FAILURE
(
status
))
return
AE_OK
;
if
(
tmp
==
ds
->
handle
)
{
dd
=
alloc_dock_dependent_device
(
handle
);
if
(
dd
)
add_dock_dependent_device
(
ds
,
dd
);
}
return
AE_OK
;
}
/**
* dock_add - add a new dock station
* @handle: the dock station handle
*
* allocated and initialize a new dock station device. Find all devices
* that are on the dock station, and register for dock event notifications.
*/
static
int
dock_add
(
acpi_handle
handle
)
{
int
ret
;
acpi_status
status
;
struct
dock_dependent_device
*
dd
;
/* allocate & initialize the dock_station private data */
dock_station
=
kzalloc
(
sizeof
(
*
dock_station
),
GFP_KERNEL
);
if
(
!
dock_station
)
return
-
ENOMEM
;
dock_station
->
handle
=
handle
;
dock_station
->
last_dock_time
=
jiffies
-
HZ
;
INIT_LIST_HEAD
(
&
dock_station
->
dependent_devices
);
INIT_LIST_HEAD
(
&
dock_station
->
hotplug_devices
);
spin_lock_init
(
&
dock_station
->
dd_lock
);
spin_lock_init
(
&
dock_station
->
hp_lock
);
/* Find dependent devices */
acpi_walk_namespace
(
ACPI_TYPE_DEVICE
,
ACPI_ROOT_OBJECT
,
ACPI_UINT32_MAX
,
find_dock_devices
,
dock_station
,
NULL
);
/* add the dock station as a device dependent on itself */
dd
=
alloc_dock_dependent_device
(
handle
);
if
(
!
dd
)
{
kfree
(
dock_station
);
return
-
ENOMEM
;
}
add_dock_dependent_device
(
dock_station
,
dd
);
/* register for dock events */
status
=
acpi_install_notify_handler
(
dock_station
->
handle
,
ACPI_SYSTEM_NOTIFY
,
dock_notify
,
dock_station
);
if
(
ACPI_FAILURE
(
status
))
{
printk
(
KERN_ERR
PREFIX
"Error installing notify handler
\n
"
);
ret
=
-
ENODEV
;
goto
dock_add_err
;
}
printk
(
KERN_INFO
PREFIX
"%s
\n
"
,
ACPI_DOCK_DRIVER_NAME
);
return
0
;
dock_add_err:
kfree
(
dock_station
);
kfree
(
dd
);
return
ret
;
}
/**
* dock_remove - free up resources related to the dock station
*/
static
int
dock_remove
(
void
)
{
struct
dock_dependent_device
*
dd
,
*
tmp
;
acpi_status
status
;
if
(
!
dock_station
)
return
0
;
/* remove dependent devices */
list_for_each_entry_safe
(
dd
,
tmp
,
&
dock_station
->
dependent_devices
,
list
)
kfree
(
dd
);
/* remove dock notify handler */
status
=
acpi_remove_notify_handler
(
dock_station
->
handle
,
ACPI_SYSTEM_NOTIFY
,
dock_notify
);
if
(
ACPI_FAILURE
(
status
))
printk
(
KERN_ERR
"Error removing notify handler
\n
"
);
/* free dock station memory */
kfree
(
dock_station
);
return
0
;
}
/**
* find_dock - look for a dock station
* @handle: acpi handle of a device
* @lvl: unused
* @context: counter of dock stations found
* @rv: unused
*
* This is called by acpi_walk_namespace to look for dock stations.
*/
static
acpi_status
find_dock
(
acpi_handle
handle
,
u32
lvl
,
void
*
context
,
void
**
rv
)
{
int
*
count
=
(
int
*
)
context
;
acpi_status
status
=
AE_OK
;
if
(
is_dock
(
handle
))
{
if
(
dock_add
(
handle
)
>=
0
)
{
(
*
count
)
++
;
status
=
AE_CTRL_TERMINATE
;
}
}
return
status
;
}
static
int
__init
dock_init
(
void
)
{
int
num
=
0
;
dock_station
=
NULL
;
/* look for a dock station */
acpi_walk_namespace
(
ACPI_TYPE_DEVICE
,
ACPI_ROOT_OBJECT
,
ACPI_UINT32_MAX
,
find_dock
,
&
num
,
NULL
);
if
(
!
num
)
return
-
ENODEV
;
return
0
;
}
static
void
__exit
dock_exit
(
void
)
{
dock_remove
();
}
postcore_initcall
(
dock_init
);
module_exit
(
dock_exit
);
drivers/acpi/scan.c
浏览文件 @
c8f7a62c
...
...
@@ -663,6 +663,29 @@ static int acpi_bus_find_driver(struct acpi_device *device)
Device Enumeration
-------------------------------------------------------------------------- */
acpi_status
acpi_bus_get_ejd
(
acpi_handle
handle
,
acpi_handle
*
ejd
)
{
acpi_status
status
;
acpi_handle
tmp
;
struct
acpi_buffer
buffer
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
union
acpi_object
*
obj
;
status
=
acpi_get_handle
(
handle
,
"_EJD"
,
&
tmp
);
if
(
ACPI_FAILURE
(
status
))
return
status
;
status
=
acpi_evaluate_object
(
handle
,
"_EJD"
,
NULL
,
&
buffer
);
if
(
ACPI_SUCCESS
(
status
))
{
obj
=
buffer
.
pointer
;
status
=
acpi_get_handle
(
NULL
,
obj
->
string
.
pointer
,
ejd
);
kfree
(
buffer
.
pointer
);
}
return
status
;
}
EXPORT_SYMBOL_GPL
(
acpi_bus_get_ejd
);
static
int
acpi_bus_get_flags
(
struct
acpi_device
*
device
)
{
acpi_status
status
=
AE_OK
;
...
...
include/acpi/acpi_bus.h
浏览文件 @
c8f7a62c
...
...
@@ -334,7 +334,7 @@ int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent,
acpi_handle
handle
,
int
type
);
int
acpi_bus_trim
(
struct
acpi_device
*
start
,
int
rmdevice
);
int
acpi_bus_start
(
struct
acpi_device
*
device
);
acpi_status
acpi_bus_get_ejd
(
acpi_handle
handle
,
acpi_handle
*
ejd
);
int
acpi_match_ids
(
struct
acpi_device
*
device
,
char
*
ids
);
int
acpi_create_dir
(
struct
acpi_device
*
);
void
acpi_remove_dir
(
struct
acpi_device
*
);
...
...
include/acpi/acpi_drivers.h
浏览文件 @
c8f7a62c
...
...
@@ -110,4 +110,21 @@ int acpi_processor_set_thermal_limit(acpi_handle handle, int type);
extern
int
acpi_specific_hotkey_enabled
;
/*--------------------------------------------------------------------------
Dock Station
-------------------------------------------------------------------------- */
#if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE)
extern
int
is_dock_device
(
acpi_handle
handle
);
extern
int
register_dock_notifier
(
struct
notifier_block
*
nb
);
extern
void
unregister_dock_notifier
(
struct
notifier_block
*
nb
);
extern
int
register_hotplug_dock_device
(
acpi_handle
handle
,
acpi_notify_handler
handler
,
void
*
context
);
extern
void
unregister_hotplug_dock_device
(
acpi_handle
handle
);
#else
#define is_dock_device(h) (0)
#define register_dock_notifier(nb) (-ENODEV)
#define unregister_dock_notifier(nb) do { } while(0)
#define register_hotplug_dock_device(h1, h2, c) (-ENODEV)
#define unregister_hotplug_dock_device(h) do { } while(0)
#endif
#endif
/*__ACPI_DRIVERS_H__*/
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录