Commit 60fbf2bd authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'driver-core-3.15-rc2' of...

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
parents 8cb652bb 94f8cc0e
...@@ -315,7 +315,7 @@ Andrew Morton が Linux-kernel メーリングリストにカーネルリリー ...@@ -315,7 +315,7 @@ Andrew Morton が Linux-kernel メーリングリストにカーネルリリー
もし、3.x.y カーネルが存在しない場合には、番号が一番大きい 3.x が もし、3.x.y カーネルが存在しない場合には、番号が一番大きい 3.x が
最新の安定版カーネルです。 最新の安定版カーネルです。
3.x.y は "stable" チーム <stable@kernel.org> でメンテされており、必 3.x.y は "stable" チーム <stable@vger.kernel.org> でメンテされており、必
要に応じてリリースされます。通常のリリース期間は 2週間毎ですが、差し迫っ 要に応じてリリースされます。通常のリリース期間は 2週間毎ですが、差し迫っ
た問題がなければもう少し長くなることもあります。セキュリティ関連の問題 た問題がなければもう少し長くなることもあります。セキュリティ関連の問題
の場合はこれに対してだいたいの場合、すぐにリリースがされます。 の場合はこれに対してだいたいの場合、すぐにリリースがされます。
......
...@@ -50,16 +50,16 @@ linux-2.6.29/Documentation/stable_kernel_rules.txt ...@@ -50,16 +50,16 @@ linux-2.6.29/Documentation/stable_kernel_rules.txt
-stable ツリーにパッチを送付する手続き- -stable ツリーにパッチを送付する手続き-
- 上記の規則に従っているかを確認した後に、stable@kernel.org にパッチ - 上記の規則に従っているかを確認した後に、stable@vger.kernel.org にパッチ
を送る。 を送る。
- 送信者はパッチがキューに受け付けられた際には ACK を、却下された場合 - 送信者はパッチがキューに受け付けられた際には ACK を、却下された場合
には NAK を受け取る。この反応は開発者たちのスケジュールによって、数 には NAK を受け取る。この反応は開発者たちのスケジュールによって、数
日かかる場合がある。 日かかる場合がある。
- もし受け取られたら、パッチは他の開発者たちと関連するサブシステムの - もし受け取られたら、パッチは他の開発者たちと関連するサブシステムの
メンテナーによるレビューのために -stable キューに追加される。 メンテナーによるレビューのために -stable キューに追加される。
- パッチに stable@kernel.org のアドレスが付加されているときには、それ - パッチに stable@vger.kernel.org のアドレスが付加されているときには、それ
が Linus のツリーに入る時に自動的に stable チームに email される。 が Linus のツリーに入る時に自動的に stable チームに email される。
- セキュリティパッチはこのエイリアス (stable@kernel.org) に送られるべ - セキュリティパッチはこのエイリアス (stable@vger.kernel.org) に送られるべ
きではなく、代わりに security@kernel.org のアドレスに送られる。 きではなく、代わりに security@kernel.org のアドレスに送られる。
レビューサイクル- レビューサイクル-
......
...@@ -39,7 +39,7 @@ Procedure for submitting patches to the -stable tree: ...@@ -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 the stable tree without anything else needing to be done by the author
or subsystem maintainer. or subsystem maintainer.
- If the patch requires other patches as prerequisites which can be - 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: the sign-off area:
Cc: <stable@vger.kernel.org> # 3.3.x: a1f84a3: sched: Check for idle Cc: <stable@vger.kernel.org> # 3.3.x: a1f84a3: sched: Check for idle
......
...@@ -237,7 +237,7 @@ kernel.org网站的pub/linux/kernel/v2.6/目录下找到它。它的开发遵循 ...@@ -237,7 +237,7 @@ kernel.org网站的pub/linux/kernel/v2.6/目录下找到它。它的开发遵循
如果没有2.6.x.y版本内核存在,那么最新的2.6.x版本内核就相当于是当前的稳定 如果没有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文件具体描述了可被稳定 内核源码中的Documentation/stable_kernel_rules.txt文件具体描述了可被稳定
......
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 的中文翻译 ...@@ -42,7 +42,7 @@ Documentation/stable_kernel_rules.txt 的中文翻译
向稳定版代码树提交补丁的过程: 向稳定版代码树提交补丁的过程:
- 在确认了补丁符合以上的规则后,将补丁发送到stable@kernel.org。 - 在确认了补丁符合以上的规则后,将补丁发送到stable@vger.kernel.org。
- 如果补丁被接受到队列里,发送者会收到一个ACK回复,如果没有被接受,收 - 如果补丁被接受到队列里,发送者会收到一个ACK回复,如果没有被接受,收
到的是NAK回复。回复需要几天的时间,这取决于开发者的时间安排。 到的是NAK回复。回复需要几天的时间,这取决于开发者的时间安排。
- 被接受的补丁会被加到稳定版本队列里,等待其他开发者的审查。 - 被接受的补丁会被加到稳定版本队列里,等待其他开发者的审查。
......
...@@ -614,39 +614,6 @@ void device_remove_bin_file(struct device *dev, ...@@ -614,39 +614,6 @@ void device_remove_bin_file(struct device *dev,
} }
EXPORT_SYMBOL_GPL(device_remove_bin_file); 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) static void klist_children_get(struct klist_node *n)
{ {
struct device_private *p = to_device_private_parent(n); struct device_private *p = to_device_private_parent(n);
......
...@@ -187,8 +187,8 @@ static void driver_bound(struct device *dev) ...@@ -187,8 +187,8 @@ static void driver_bound(struct device *dev)
return; return;
} }
pr_debug("driver: '%s': %s: bound to device '%s'\n", dev_name(dev), pr_debug("driver: '%s': %s: bound to device '%s'\n", dev->driver->name,
__func__, dev->driver->name); __func__, dev_name(dev));
klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices); klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices);
......
...@@ -39,8 +39,7 @@ ...@@ -39,8 +39,7 @@
static ssize_t show_##name(struct device *dev, \ static ssize_t show_##name(struct device *dev, \
struct device_attribute *attr, char *buf) \ struct device_attribute *attr, char *buf) \
{ \ { \
unsigned int cpu = dev->id; \ return sprintf(buf, "%d\n", topology_##name(dev->id)); \
return sprintf(buf, "%d\n", topology_##name(cpu)); \
} }
#if defined(topology_thread_cpumask) || defined(topology_core_cpumask) || \ #if defined(topology_thread_cpumask) || defined(topology_core_cpumask) || \
......
...@@ -48,14 +48,18 @@ void __init kernfs_inode_init(void) ...@@ -48,14 +48,18 @@ void __init kernfs_inode_init(void)
static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn) static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn)
{ {
static DEFINE_MUTEX(iattr_mutex);
struct kernfs_iattrs *ret;
struct iattr *iattrs; struct iattr *iattrs;
mutex_lock(&iattr_mutex);
if (kn->iattr) if (kn->iattr)
return kn->iattr; goto out_unlock;
kn->iattr = kzalloc(sizeof(struct kernfs_iattrs), GFP_KERNEL); kn->iattr = kzalloc(sizeof(struct kernfs_iattrs), GFP_KERNEL);
if (!kn->iattr) if (!kn->iattr)
return NULL; goto out_unlock;
iattrs = &kn->iattr->ia_iattr; iattrs = &kn->iattr->ia_iattr;
/* assign default attributes */ /* assign default attributes */
...@@ -65,8 +69,10 @@ static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn) ...@@ -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; iattrs->ia_atime = iattrs->ia_mtime = iattrs->ia_ctime = CURRENT_TIME;
simple_xattrs_init(&kn->iattr->xattrs); simple_xattrs_init(&kn->iattr->xattrs);
out_unlock:
return kn->iattr; ret = kn->iattr;
mutex_unlock(&iattr_mutex);
return ret;
} }
static int __kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr) static int __kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr)
......
...@@ -800,7 +800,10 @@ void emergency_remount(void) ...@@ -800,7 +800,10 @@ void emergency_remount(void)
static DEFINE_IDA(unnamed_dev_ida); static DEFINE_IDA(unnamed_dev_ida);
static DEFINE_SPINLOCK(unnamed_dev_lock);/* protects the above */ 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) int get_anon_bdev(dev_t *p)
{ {
......
...@@ -453,95 +453,3 @@ void sysfs_remove_bin_file(struct kobject *kobj, ...@@ -453,95 +453,3 @@ void sysfs_remove_bin_file(struct kobject *kobj,
kernfs_remove_by_name(kobj->sd, attr->attr.name); kernfs_remove_by_name(kobj->sd, attr->attr.name);
} }
EXPORT_SYMBOL_GPL(sysfs_remove_bin_file); 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, ...@@ -566,12 +566,6 @@ extern int __must_check device_create_bin_file(struct device *dev,
const struct bin_attribute *attr); const struct bin_attribute *attr);
extern void device_remove_bin_file(struct device *dev, extern void device_remove_bin_file(struct device *dev,
const struct bin_attribute *attr); 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 */ /* device resource management */
typedef void (*dr_release_t)(struct device *dev, void *res); typedef void (*dr_release_t)(struct device *dev, void *res);
...@@ -932,10 +926,7 @@ extern int device_online(struct device *dev); ...@@ -932,10 +926,7 @@ extern int device_online(struct device *dev);
extern struct device *__root_device_register(const char *name, extern struct device *__root_device_register(const char *name,
struct module *owner); struct module *owner);
/* /* This is a macro to avoid include problems with THIS_MODULE */
* This is a macro to avoid include problems with THIS_MODULE,
* just as per what is done for device_schedule_callback() above.
*/
#define root_device_register(name) \ #define root_device_register(name) \
__root_device_register(name, THIS_MODULE) __root_device_register(name, THIS_MODULE)
......
...@@ -179,9 +179,6 @@ struct sysfs_ops { ...@@ -179,9 +179,6 @@ struct sysfs_ops {
#ifdef CONFIG_SYSFS #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); int __must_check sysfs_create_dir_ns(struct kobject *kobj, const void *ns);
void sysfs_remove_dir(struct kobject *kobj); void sysfs_remove_dir(struct kobject *kobj);
int __must_check sysfs_rename_dir_ns(struct kobject *kobj, const char *new_name, 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) ...@@ -255,12 +252,6 @@ static inline void sysfs_enable_ns(struct kernfs_node *kn)
#else /* CONFIG_SYSFS */ #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) static inline int sysfs_create_dir_ns(struct kobject *kobj, const void *ns)
{ {
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment