Skip to content

Commit

Permalink
Merge branch 'driver-core-next' into cgroup/for-3.15
Browse files Browse the repository at this point in the history
Pending kernfs conversion depends on kernfs improvements in
driver-core-next.  Pull it into for-3.15.

Signed-off-by: Tejun Heo <tj@kernel.org>
  • Loading branch information
Tejun Heo committed Feb 8, 2014
2 parents 1a698a4 + ba341d5 commit f7cef06
Show file tree
Hide file tree
Showing 27 changed files with 847 additions and 503 deletions.
1 change: 1 addition & 0 deletions arch/s390/include/asm/ccwgroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ struct ccwgroup_device {
unsigned int count;
struct device dev;
struct ccw_device *cdev[0];
struct work_struct ungroup_work;
};

/**
Expand Down
18 changes: 8 additions & 10 deletions arch/s390/pci/pci_sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,29 +48,27 @@ static ssize_t show_pfgid(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR(pfgid, S_IRUGO, show_pfgid, NULL);

static void recover_callback(struct device *dev)
static ssize_t store_recover(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct zpci_dev *zdev = get_zdev(pdev);
int ret;

if (!device_remove_file_self(dev, attr))
return count;

pci_stop_and_remove_bus_device(pdev);
ret = zpci_disable_device(zdev);
if (ret)
return;
return ret;

ret = zpci_enable_device(zdev);
if (ret)
return;
return ret;

pci_rescan_bus(zdev->bus);
}

static ssize_t store_recover(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int rc = device_schedule_callback(dev, recover_callback);
return rc ? rc : count;
return count;
}
static DEVICE_ATTR(recover, S_IWUSR, NULL, store_recover);

Expand Down
50 changes: 17 additions & 33 deletions drivers/base/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,23 @@ void device_remove_file(struct device *dev,
}
EXPORT_SYMBOL_GPL(device_remove_file);

/**
* device_remove_file_self - remove sysfs attribute file from its own method.
* @dev: device.
* @attr: device attribute descriptor.
*
* See kernfs_remove_self() for details.
*/
bool device_remove_file_self(struct device *dev,
const struct device_attribute *attr)
{
if (dev)
return sysfs_remove_file_self(&dev->kobj, &attr->attr);
else
return false;
}
EXPORT_SYMBOL_GPL(device_remove_file_self);

/**
* device_create_bin_file - create sysfs binary attribute file for device.
* @dev: device.
Expand Down Expand Up @@ -598,39 +615,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);
Expand Down
18 changes: 11 additions & 7 deletions drivers/base/dma-buf.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,9 +251,8 @@ EXPORT_SYMBOL_GPL(dma_buf_put);
* @dmabuf: [in] buffer to attach device to.
* @dev: [in] device to be attached.
*
* Returns struct dma_buf_attachment * for this attachment; may return negative
* error codes.
*
* Returns struct dma_buf_attachment * for this attachment; returns ERR_PTR on
* error.
*/
struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
struct device *dev)
Expand Down Expand Up @@ -319,9 +318,8 @@ EXPORT_SYMBOL_GPL(dma_buf_detach);
* @attach: [in] attachment whose scatterlist is to be returned
* @direction: [in] direction of DMA transfer
*
* Returns sg_table containing the scatterlist to be returned; may return NULL
* or ERR_PTR.
*
* Returns sg_table containing the scatterlist to be returned; returns ERR_PTR
* on error.
*/
struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
enum dma_data_direction direction)
Expand All @@ -334,6 +332,8 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
return ERR_PTR(-EINVAL);

sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction);
if (!sg_table)
sg_table = ERR_PTR(-ENOMEM);

return sg_table;
}
Expand Down Expand Up @@ -544,6 +544,8 @@ EXPORT_SYMBOL_GPL(dma_buf_mmap);
* These calls are optional in drivers. The intended use for them
* is for mapping objects linear in kernel space for high use objects.
* Please attempt to use kmap/kunmap before thinking about these interfaces.
*
* Returns NULL on error.
*/
void *dma_buf_vmap(struct dma_buf *dmabuf)
{
Expand All @@ -566,7 +568,9 @@ void *dma_buf_vmap(struct dma_buf *dmabuf)
BUG_ON(dmabuf->vmap_ptr);

ptr = dmabuf->ops->vmap(dmabuf);
if (IS_ERR_OR_NULL(ptr))
if (WARN_ON_ONCE(IS_ERR(ptr)))
ptr = NULL;
if (!ptr)
goto out_unlock;

dmabuf->vmap_ptr = ptr;
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/drm_prime.c
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
get_dma_buf(dma_buf);

sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
if (IS_ERR_OR_NULL(sgt)) {
if (IS_ERR(sgt)) {
ret = PTR_ERR(sgt);
goto fail_detach;
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
get_dma_buf(dma_buf);

sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
if (IS_ERR_OR_NULL(sgt)) {
if (IS_ERR(sgt)) {
ret = PTR_ERR(sgt);
goto err_buf_detach;
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/media/v4l2-core/videobuf2-dma-contig.c
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,7 @@ static int vb2_dc_map_dmabuf(void *mem_priv)

/* get the associated scatterlist for this buffer */
sgt = dma_buf_map_attachment(buf->db_attach, buf->dma_dir);
if (IS_ERR_OR_NULL(sgt)) {
if (IS_ERR(sgt)) {
pr_err("Error getting dmabuf scatterlist\n");
return -EINVAL;
}
Expand Down
17 changes: 3 additions & 14 deletions drivers/pci/pci-sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -351,28 +351,17 @@ static struct device_attribute dev_rescan_attr = __ATTR(rescan,
(S_IWUSR|S_IWGRP),
NULL, dev_rescan_store);

static void remove_callback(struct device *dev)
{
pci_stop_and_remove_bus_device_locked(to_pci_dev(dev));
}

static ssize_t
remove_store(struct device *dev, struct device_attribute *dummy,
remove_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int ret = 0;
unsigned long val;

if (kstrtoul(buf, 0, &val) < 0)
return -EINVAL;

/* An attribute cannot be unregistered by one of its own methods,
* so we have to use this roundabout approach.
*/
if (val)
ret = device_schedule_callback(dev, remove_callback);
if (ret)
count = ret;
if (val && device_remove_file_self(dev, attr))
pci_stop_and_remove_bus_device_locked(to_pci_dev(dev));
return count;
}
static struct device_attribute dev_remove_attr = __ATTR(remove,
Expand Down
14 changes: 7 additions & 7 deletions drivers/s390/block/dcssblk.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,12 +304,6 @@ dcssblk_load_segment(char *name, struct segment_info **seg_info)
return rc;
}

static void dcssblk_unregister_callback(struct device *dev)
{
device_unregister(dev);
put_device(dev);
}

/*
* device attribute for switching shared/nonshared (exclusive)
* operation (show + store)
Expand Down Expand Up @@ -397,7 +391,13 @@ dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const ch
blk_cleanup_queue(dev_info->dcssblk_queue);
dev_info->gd->queue = NULL;
put_disk(dev_info->gd);
rc = device_schedule_callback(dev, dcssblk_unregister_callback);
up_write(&dcssblk_devices_sem);

if (device_remove_file_self(dev, attr)) {
device_unregister(dev);
put_device(dev);
}
return rc;
out:
up_write(&dcssblk_devices_sem);
return rc;
Expand Down
26 changes: 16 additions & 10 deletions drivers/s390/cio/ccwgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,14 +168,12 @@ static ssize_t ccwgroup_online_show(struct device *dev,
* Provide an 'ungroup' attribute so the user can remove group devices no
* longer needed or accidentially created. Saves memory :)
*/
static void ccwgroup_ungroup_callback(struct device *dev)
static void ccwgroup_ungroup(struct ccwgroup_device *gdev)
{
struct ccwgroup_device *gdev = to_ccwgroupdev(dev);

mutex_lock(&gdev->reg_mutex);
if (device_is_registered(&gdev->dev)) {
__ccwgroup_remove_symlinks(gdev);
device_unregister(dev);
device_unregister(&gdev->dev);
__ccwgroup_remove_cdev_refs(gdev);
}
mutex_unlock(&gdev->reg_mutex);
Expand All @@ -195,10 +193,9 @@ static ssize_t ccwgroup_ungroup_store(struct device *dev,
rc = -EINVAL;
goto out;
}
/* Note that we cannot unregister the device from one of its
* attribute methods, so we have to use this roundabout approach.
*/
rc = device_schedule_callback(dev, ccwgroup_ungroup_callback);

if (device_remove_file_self(dev, attr))
ccwgroup_ungroup(gdev);
out:
if (rc) {
if (rc != -EAGAIN)
Expand All @@ -224,6 +221,14 @@ static const struct attribute_group *ccwgroup_attr_groups[] = {
NULL,
};

static void ccwgroup_ungroup_workfn(struct work_struct *work)
{
struct ccwgroup_device *gdev =
container_of(work, struct ccwgroup_device, ungroup_work);

ccwgroup_ungroup(gdev);
}

static void ccwgroup_release(struct device *dev)
{
kfree(to_ccwgroupdev(dev));
Expand Down Expand Up @@ -323,6 +328,7 @@ int ccwgroup_create_dev(struct device *parent, struct ccwgroup_driver *gdrv,
atomic_set(&gdev->onoff, 0);
mutex_init(&gdev->reg_mutex);
mutex_lock(&gdev->reg_mutex);
INIT_WORK(&gdev->ungroup_work, ccwgroup_ungroup_workfn);
gdev->count = num_devices;
gdev->dev.bus = &ccwgroup_bus_type;
gdev->dev.parent = parent;
Expand Down Expand Up @@ -404,10 +410,10 @@ EXPORT_SYMBOL(ccwgroup_create_dev);
static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action,
void *data)
{
struct device *dev = data;
struct ccwgroup_device *gdev = to_ccwgroupdev(data);

if (action == BUS_NOTIFY_UNBIND_DRIVER)
device_schedule_callback(dev, ccwgroup_ungroup_callback);
schedule_work(&gdev->ungroup_work);

return NOTIFY_OK;
}
Expand Down
15 changes: 2 additions & 13 deletions drivers/scsi/scsi_sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -649,23 +649,12 @@ store_rescan_field (struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field);

static void sdev_store_delete_callback(struct device *dev)
{
scsi_remove_device(to_scsi_device(dev));
}

static ssize_t
sdev_store_delete(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int rc;

/* An attribute cannot be unregistered by one of its own methods,
* so we have to use this roundabout approach.
*/
rc = device_schedule_callback(dev, sdev_store_delete_callback);
if (rc)
count = rc;
if (device_remove_file_self(dev, attr))
scsi_remove_device(to_scsi_device(dev));
return count;
};
static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete);
Expand Down
1 change: 1 addition & 0 deletions fs/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ endif # BLOCK
menu "Pseudo filesystems"

source "fs/proc/Kconfig"
source "fs/kernfs/Kconfig"
source "fs/sysfs/Kconfig"

config TMPFS
Expand Down
3 changes: 2 additions & 1 deletion fs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ obj-$(CONFIG_FHANDLE) += fhandle.o
obj-y += quota/

obj-$(CONFIG_PROC_FS) += proc/
obj-$(CONFIG_SYSFS) += sysfs/ kernfs/
obj-$(CONFIG_KERNFS) += kernfs/
obj-$(CONFIG_SYSFS) += sysfs/
obj-$(CONFIG_CONFIGFS_FS) += configfs/
obj-y += devpts/

Expand Down
7 changes: 7 additions & 0 deletions fs/kernfs/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#
# KERNFS should be selected by its users
#

config KERNFS
bool
default n
Loading

0 comments on commit f7cef06

Please sign in to comment.