forked from Minki/linux
driver core fixes for 3.15-rc2
Here are some driver core fixes for 3.15-rc2. Also in here are some documentation updates, as well as an API removal that had to wait for after -rc1 due to the cleanups coming into you from multiple developer trees (this one and the PPC tree.) All have been in linux next successfully. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iEYEABECAAYFAlNRl6cACgkQMUfUDdst+yllxACfV9fZ/A6IQja60AdPEo+oa6Cw RiIAoJtH0D0G0eC4+/Qs9GSRMoB4jPPC =Wi3a -----END PGP SIGNATURE----- Merge tag 'driver-core-3.15-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core Pull driver core fixes from Greg KH: "Here are some driver core fixes for 3.15-rc2. Also in here are some documentation updates, as well as an API removal that had to wait for after -rc1 due to the cleanups coming into you from multiple developer trees (this one and the PPC tree.) All have been in linux next successfully" * tag 'driver-core-3.15-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: drivers/base/dd.c incorrect pr_debug() parameters Documentation: Update stable address in Chinese and Japanese translations topology: Fix compilation warning when not in SMP Chinese: add translation of io_ordering.txt stable_kernel_rules: spelling/word usage sysfs, driver-core: remove unused {sysfs|device}_schedule_callback_owner() kernfs: protect lazy kernfs_iattrs allocation with mutex fs: Don't return 0 from get_anon_bdev
This commit is contained in:
commit
60fbf2bda1
@ -315,7 +315,7 @@ Andrew Morton が Linux-kernel メーリングリストにカーネルリリー
|
||||
もし、3.x.y カーネルが存在しない場合には、番号が一番大きい 3.x が
|
||||
最新の安定版カーネルです。
|
||||
|
||||
3.x.y は "stable" チーム <stable@kernel.org> でメンテされており、必
|
||||
3.x.y は "stable" チーム <stable@vger.kernel.org> でメンテされており、必
|
||||
要に応じてリリースされます。通常のリリース期間は 2週間毎ですが、差し迫っ
|
||||
た問題がなければもう少し長くなることもあります。セキュリティ関連の問題
|
||||
の場合はこれに対してだいたいの場合、すぐにリリースがされます。
|
||||
|
@ -50,16 +50,16 @@ linux-2.6.29/Documentation/stable_kernel_rules.txt
|
||||
|
||||
-stable ツリーにパッチを送付する手続き-
|
||||
|
||||
- 上記の規則に従っているかを確認した後に、stable@kernel.org にパッチ
|
||||
- 上記の規則に従っているかを確認した後に、stable@vger.kernel.org にパッチ
|
||||
を送る。
|
||||
- 送信者はパッチがキューに受け付けられた際には ACK を、却下された場合
|
||||
には NAK を受け取る。この反応は開発者たちのスケジュールによって、数
|
||||
日かかる場合がある。
|
||||
- もし受け取られたら、パッチは他の開発者たちと関連するサブシステムの
|
||||
メンテナーによるレビューのために -stable キューに追加される。
|
||||
- パッチに stable@kernel.org のアドレスが付加されているときには、それ
|
||||
- パッチに stable@vger.kernel.org のアドレスが付加されているときには、それ
|
||||
が Linus のツリーに入る時に自動的に stable チームに email される。
|
||||
- セキュリティパッチはこのエイリアス (stable@kernel.org) に送られるべ
|
||||
- セキュリティパッチはこのエイリアス (stable@vger.kernel.org) に送られるべ
|
||||
きではなく、代わりに security@kernel.org のアドレスに送られる。
|
||||
|
||||
レビューサイクル-
|
||||
|
@ -39,7 +39,7 @@ Procedure for submitting patches to the -stable tree:
|
||||
the stable tree without anything else needing to be done by the author
|
||||
or subsystem maintainer.
|
||||
- If the patch requires other patches as prerequisites which can be
|
||||
cherry-picked than this can be specified in the following format in
|
||||
cherry-picked, then this can be specified in the following format in
|
||||
the sign-off area:
|
||||
|
||||
Cc: <stable@vger.kernel.org> # 3.3.x: a1f84a3: sched: Check for idle
|
||||
|
@ -237,7 +237,7 @@ kernel.org网站的pub/linux/kernel/v2.6/目录下找到它。它的开发遵循
|
||||
如果没有2.6.x.y版本内核存在,那么最新的2.6.x版本内核就相当于是当前的稳定
|
||||
版内核。
|
||||
|
||||
2.6.x.y版本由“稳定版”小组(邮件地址<stable@kernel.org>)维护,一般隔周发
|
||||
2.6.x.y版本由“稳定版”小组(邮件地址<stable@vger.kernel.org>)维护,一般隔周发
|
||||
布新版本。
|
||||
|
||||
内核源码中的Documentation/stable_kernel_rules.txt文件具体描述了可被稳定
|
||||
|
67
Documentation/zh_CN/io_ordering.txt
Normal file
67
Documentation/zh_CN/io_ordering.txt
Normal file
@ -0,0 +1,67 @@
|
||||
Chinese translated version of Documentation/io_orderings.txt
|
||||
|
||||
If you have any comment or update to the content, please contact the
|
||||
original document maintainer directly. However, if you have a problem
|
||||
communicating in English you can also ask the Chinese maintainer for
|
||||
help. Contact the Chinese maintainer if this translation is outdated
|
||||
or if there is a problem with the translation.
|
||||
|
||||
Chinese maintainer: Lin Yongting <linyongting@gmail.com>
|
||||
---------------------------------------------------------------------
|
||||
Documentation/io_ordering.txt 的中文翻译
|
||||
|
||||
如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
|
||||
交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
|
||||
译存在问题,请联系中文版维护者。
|
||||
|
||||
中文版维护者: 林永听 Lin Yongting <linyongting@gmail.com>
|
||||
中文版翻译者: 林永听 Lin Yongting <linyongting@gmail.com>
|
||||
中文版校译者: 林永听 Lin Yongting <linyongting@gmail.com>
|
||||
|
||||
|
||||
以下为正文
|
||||
---------------------------------------------------------------------
|
||||
|
||||
在某些平台上,所谓的内存映射I/O是弱顺序。在这些平台上,驱动开发者有责任
|
||||
保证I/O内存映射地址的写操作按程序图意的顺序达到设备。通常读取一个“安全”
|
||||
设备寄存器或桥寄存器,触发IO芯片清刷未处理的写操作到达设备后才处理读操作,
|
||||
而达到保证目的。驱动程序通常在spinlock保护的临界区退出之前使用这种技术。
|
||||
这也可以保证后面的写操作只在前面的写操作之后到达设备(这非常类似于内存
|
||||
屏障操作,mb(),不过仅适用于I/O)。
|
||||
|
||||
假设一个设备驱动程的具体例子:
|
||||
|
||||
...
|
||||
CPU A: spin_lock_irqsave(&dev_lock, flags)
|
||||
CPU A: val = readl(my_status);
|
||||
CPU A: ...
|
||||
CPU A: writel(newval, ring_ptr);
|
||||
CPU A: spin_unlock_irqrestore(&dev_lock, flags)
|
||||
...
|
||||
CPU B: spin_lock_irqsave(&dev_lock, flags)
|
||||
CPU B: val = readl(my_status);
|
||||
CPU B: ...
|
||||
CPU B: writel(newval2, ring_ptr);
|
||||
CPU B: spin_unlock_irqrestore(&dev_lock, flags)
|
||||
...
|
||||
|
||||
上述例子中,设备可能会先接收到newval2的值,然后接收到newval的值,问题就
|
||||
发生了。不过很容易通过下面方法来修复:
|
||||
|
||||
...
|
||||
CPU A: spin_lock_irqsave(&dev_lock, flags)
|
||||
CPU A: val = readl(my_status);
|
||||
CPU A: ...
|
||||
CPU A: writel(newval, ring_ptr);
|
||||
CPU A: (void)readl(safe_register); /* 配置寄存器?*/
|
||||
CPU A: spin_unlock_irqrestore(&dev_lock, flags)
|
||||
...
|
||||
CPU B: spin_lock_irqsave(&dev_lock, flags)
|
||||
CPU B: val = readl(my_status);
|
||||
CPU B: ...
|
||||
CPU B: writel(newval2, ring_ptr);
|
||||
CPU B: (void)readl(safe_register); /* 配置寄存器?*/
|
||||
CPU B: spin_unlock_irqrestore(&dev_lock, flags)
|
||||
|
||||
在解决方案中,读取safe_register寄存器,触发IO芯片清刷未处理的写操作,
|
||||
再处理后面的读操作,防止引发数据不一致问题。
|
@ -42,7 +42,7 @@ Documentation/stable_kernel_rules.txt 的中文翻译
|
||||
|
||||
向稳定版代码树提交补丁的过程:
|
||||
|
||||
- 在确认了补丁符合以上的规则后,将补丁发送到stable@kernel.org。
|
||||
- 在确认了补丁符合以上的规则后,将补丁发送到stable@vger.kernel.org。
|
||||
- 如果补丁被接受到队列里,发送者会收到一个ACK回复,如果没有被接受,收
|
||||
到的是NAK回复。回复需要几天的时间,这取决于开发者的时间安排。
|
||||
- 被接受的补丁会被加到稳定版本队列里,等待其他开发者的审查。
|
||||
|
@ -614,39 +614,6 @@ void device_remove_bin_file(struct device *dev,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_remove_bin_file);
|
||||
|
||||
/**
|
||||
* device_schedule_callback_owner - helper to schedule a callback for a device
|
||||
* @dev: device.
|
||||
* @func: callback function to invoke later.
|
||||
* @owner: module owning the callback routine
|
||||
*
|
||||
* Attribute methods must not unregister themselves or their parent device
|
||||
* (which would amount to the same thing). Attempts to do so will deadlock,
|
||||
* since unregistration is mutually exclusive with driver callbacks.
|
||||
*
|
||||
* Instead methods can call this routine, which will attempt to allocate
|
||||
* and schedule a workqueue request to call back @func with @dev as its
|
||||
* argument in the workqueue's process context. @dev will be pinned until
|
||||
* @func returns.
|
||||
*
|
||||
* This routine is usually called via the inline device_schedule_callback(),
|
||||
* which automatically sets @owner to THIS_MODULE.
|
||||
*
|
||||
* Returns 0 if the request was submitted, -ENOMEM if storage could not
|
||||
* be allocated, -ENODEV if a reference to @owner isn't available.
|
||||
*
|
||||
* NOTE: This routine won't work if CONFIG_SYSFS isn't set! It uses an
|
||||
* underlying sysfs routine (since it is intended for use by attribute
|
||||
* methods), and if sysfs isn't available you'll get nothing but -ENOSYS.
|
||||
*/
|
||||
int device_schedule_callback_owner(struct device *dev,
|
||||
void (*func)(struct device *), struct module *owner)
|
||||
{
|
||||
return sysfs_schedule_callback(&dev->kobj,
|
||||
(void (*)(void *)) func, dev, owner);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_schedule_callback_owner);
|
||||
|
||||
static void klist_children_get(struct klist_node *n)
|
||||
{
|
||||
struct device_private *p = to_device_private_parent(n);
|
||||
|
@ -187,8 +187,8 @@ static void driver_bound(struct device *dev)
|
||||
return;
|
||||
}
|
||||
|
||||
pr_debug("driver: '%s': %s: bound to device '%s'\n", dev_name(dev),
|
||||
__func__, dev->driver->name);
|
||||
pr_debug("driver: '%s': %s: bound to device '%s'\n", dev->driver->name,
|
||||
__func__, dev_name(dev));
|
||||
|
||||
klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices);
|
||||
|
||||
|
@ -39,8 +39,7 @@
|
||||
static ssize_t show_##name(struct device *dev, \
|
||||
struct device_attribute *attr, char *buf) \
|
||||
{ \
|
||||
unsigned int cpu = dev->id; \
|
||||
return sprintf(buf, "%d\n", topology_##name(cpu)); \
|
||||
return sprintf(buf, "%d\n", topology_##name(dev->id)); \
|
||||
}
|
||||
|
||||
#if defined(topology_thread_cpumask) || defined(topology_core_cpumask) || \
|
||||
|
@ -48,14 +48,18 @@ void __init kernfs_inode_init(void)
|
||||
|
||||
static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn)
|
||||
{
|
||||
static DEFINE_MUTEX(iattr_mutex);
|
||||
struct kernfs_iattrs *ret;
|
||||
struct iattr *iattrs;
|
||||
|
||||
mutex_lock(&iattr_mutex);
|
||||
|
||||
if (kn->iattr)
|
||||
return kn->iattr;
|
||||
goto out_unlock;
|
||||
|
||||
kn->iattr = kzalloc(sizeof(struct kernfs_iattrs), GFP_KERNEL);
|
||||
if (!kn->iattr)
|
||||
return NULL;
|
||||
goto out_unlock;
|
||||
iattrs = &kn->iattr->ia_iattr;
|
||||
|
||||
/* assign default attributes */
|
||||
@ -65,8 +69,10 @@ static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn)
|
||||
iattrs->ia_atime = iattrs->ia_mtime = iattrs->ia_ctime = CURRENT_TIME;
|
||||
|
||||
simple_xattrs_init(&kn->iattr->xattrs);
|
||||
|
||||
return kn->iattr;
|
||||
out_unlock:
|
||||
ret = kn->iattr;
|
||||
mutex_unlock(&iattr_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr)
|
||||
|
@ -800,7 +800,10 @@ void emergency_remount(void)
|
||||
|
||||
static DEFINE_IDA(unnamed_dev_ida);
|
||||
static DEFINE_SPINLOCK(unnamed_dev_lock);/* protects the above */
|
||||
static int unnamed_dev_start = 0; /* don't bother trying below it */
|
||||
/* Many userspace utilities consider an FSID of 0 invalid.
|
||||
* Always return at least 1 from get_anon_bdev.
|
||||
*/
|
||||
static int unnamed_dev_start = 1;
|
||||
|
||||
int get_anon_bdev(dev_t *p)
|
||||
{
|
||||
|
@ -453,95 +453,3 @@ void sysfs_remove_bin_file(struct kobject *kobj,
|
||||
kernfs_remove_by_name(kobj->sd, attr->attr.name);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sysfs_remove_bin_file);
|
||||
|
||||
struct sysfs_schedule_callback_struct {
|
||||
struct list_head workq_list;
|
||||
struct kobject *kobj;
|
||||
void (*func)(void *);
|
||||
void *data;
|
||||
struct module *owner;
|
||||
struct work_struct work;
|
||||
};
|
||||
|
||||
static struct workqueue_struct *sysfs_workqueue;
|
||||
static DEFINE_MUTEX(sysfs_workq_mutex);
|
||||
static LIST_HEAD(sysfs_workq);
|
||||
static void sysfs_schedule_callback_work(struct work_struct *work)
|
||||
{
|
||||
struct sysfs_schedule_callback_struct *ss = container_of(work,
|
||||
struct sysfs_schedule_callback_struct, work);
|
||||
|
||||
(ss->func)(ss->data);
|
||||
kobject_put(ss->kobj);
|
||||
module_put(ss->owner);
|
||||
mutex_lock(&sysfs_workq_mutex);
|
||||
list_del(&ss->workq_list);
|
||||
mutex_unlock(&sysfs_workq_mutex);
|
||||
kfree(ss);
|
||||
}
|
||||
|
||||
/**
|
||||
* sysfs_schedule_callback - helper to schedule a callback for a kobject
|
||||
* @kobj: object we're acting for.
|
||||
* @func: callback function to invoke later.
|
||||
* @data: argument to pass to @func.
|
||||
* @owner: module owning the callback code
|
||||
*
|
||||
* sysfs attribute methods must not unregister themselves or their parent
|
||||
* kobject (which would amount to the same thing). Attempts to do so will
|
||||
* deadlock, since unregistration is mutually exclusive with driver
|
||||
* callbacks.
|
||||
*
|
||||
* Instead methods can call this routine, which will attempt to allocate
|
||||
* and schedule a workqueue request to call back @func with @data as its
|
||||
* argument in the workqueue's process context. @kobj will be pinned
|
||||
* until @func returns.
|
||||
*
|
||||
* Returns 0 if the request was submitted, -ENOMEM if storage could not
|
||||
* be allocated, -ENODEV if a reference to @owner isn't available,
|
||||
* -EAGAIN if a callback has already been scheduled for @kobj.
|
||||
*/
|
||||
int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *),
|
||||
void *data, struct module *owner)
|
||||
{
|
||||
struct sysfs_schedule_callback_struct *ss, *tmp;
|
||||
|
||||
if (!try_module_get(owner))
|
||||
return -ENODEV;
|
||||
|
||||
mutex_lock(&sysfs_workq_mutex);
|
||||
list_for_each_entry_safe(ss, tmp, &sysfs_workq, workq_list)
|
||||
if (ss->kobj == kobj) {
|
||||
module_put(owner);
|
||||
mutex_unlock(&sysfs_workq_mutex);
|
||||
return -EAGAIN;
|
||||
}
|
||||
mutex_unlock(&sysfs_workq_mutex);
|
||||
|
||||
if (sysfs_workqueue == NULL) {
|
||||
sysfs_workqueue = create_singlethread_workqueue("sysfsd");
|
||||
if (sysfs_workqueue == NULL) {
|
||||
module_put(owner);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
ss = kmalloc(sizeof(*ss), GFP_KERNEL);
|
||||
if (!ss) {
|
||||
module_put(owner);
|
||||
return -ENOMEM;
|
||||
}
|
||||
kobject_get(kobj);
|
||||
ss->kobj = kobj;
|
||||
ss->func = func;
|
||||
ss->data = data;
|
||||
ss->owner = owner;
|
||||
INIT_WORK(&ss->work, sysfs_schedule_callback_work);
|
||||
INIT_LIST_HEAD(&ss->workq_list);
|
||||
mutex_lock(&sysfs_workq_mutex);
|
||||
list_add_tail(&ss->workq_list, &sysfs_workq);
|
||||
mutex_unlock(&sysfs_workq_mutex);
|
||||
queue_work(sysfs_workqueue, &ss->work);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sysfs_schedule_callback);
|
||||
|
@ -566,12 +566,6 @@ extern int __must_check device_create_bin_file(struct device *dev,
|
||||
const struct bin_attribute *attr);
|
||||
extern void device_remove_bin_file(struct device *dev,
|
||||
const struct bin_attribute *attr);
|
||||
extern int device_schedule_callback_owner(struct device *dev,
|
||||
void (*func)(struct device *dev), struct module *owner);
|
||||
|
||||
/* This is a macro to avoid include problems with THIS_MODULE */
|
||||
#define device_schedule_callback(dev, func) \
|
||||
device_schedule_callback_owner(dev, func, THIS_MODULE)
|
||||
|
||||
/* device resource management */
|
||||
typedef void (*dr_release_t)(struct device *dev, void *res);
|
||||
@ -932,10 +926,7 @@ extern int device_online(struct device *dev);
|
||||
extern struct device *__root_device_register(const char *name,
|
||||
struct module *owner);
|
||||
|
||||
/*
|
||||
* This is a macro to avoid include problems with THIS_MODULE,
|
||||
* just as per what is done for device_schedule_callback() above.
|
||||
*/
|
||||
/* This is a macro to avoid include problems with THIS_MODULE */
|
||||
#define root_device_register(name) \
|
||||
__root_device_register(name, THIS_MODULE)
|
||||
|
||||
|
@ -179,9 +179,6 @@ struct sysfs_ops {
|
||||
|
||||
#ifdef CONFIG_SYSFS
|
||||
|
||||
int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *),
|
||||
void *data, struct module *owner);
|
||||
|
||||
int __must_check sysfs_create_dir_ns(struct kobject *kobj, const void *ns);
|
||||
void sysfs_remove_dir(struct kobject *kobj);
|
||||
int __must_check sysfs_rename_dir_ns(struct kobject *kobj, const char *new_name,
|
||||
@ -255,12 +252,6 @@ static inline void sysfs_enable_ns(struct kernfs_node *kn)
|
||||
|
||||
#else /* CONFIG_SYSFS */
|
||||
|
||||
static inline int sysfs_schedule_callback(struct kobject *kobj,
|
||||
void (*func)(void *), void *data, struct module *owner)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int sysfs_create_dir_ns(struct kobject *kobj, const void *ns)
|
||||
{
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user