Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 57312b75 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-2.6:
  SCSI: fix race in device_create
  USB: Core: fix race in device_create
  USB: Phidget: fix race in device_create
  s390: fix race in device_create
  SOUND: fix race in device_create
  UIO: fix race in device_create
  Power Supply: fix race in device_create
  LEDS: fix race in device_create
  IB: fix race in device_create
  ide: fix race in device_create
  fbdev: fix race in device_create
  mm: bdi: fix race in bdi_class device creation
  Driver core: add device_create_vargs and device_create_drvdata
parents 1b5e2a7e 24b42566
Loading
Loading
Loading
Loading
+79 −6
Original line number Diff line number Diff line
@@ -1084,11 +1084,13 @@ static void device_create_release(struct device *dev)
}

/**
 * device_create - creates a device and registers it with sysfs
 * device_create_vargs - creates a device and registers it with sysfs
 * @class: pointer to the struct class that this device should be registered to
 * @parent: pointer to the parent struct device of this new device, if any
 * @devt: the dev_t for the char device to be added
 * @drvdata: the data to be added to the device for callbacks
 * @fmt: string for the device's name
 * @args: va_list for the device's name
 *
 * This function can be used by char device classes.  A struct device
 * will be created in sysfs, registered to the specified class.
@@ -1104,10 +1106,10 @@ static void device_create_release(struct device *dev)
 * Note: the struct class passed to this function must have previously
 * been created with a call to class_create().
 */
struct device *device_create(struct class *class, struct device *parent,
			     dev_t devt, const char *fmt, ...)
struct device *device_create_vargs(struct class *class, struct device *parent,
				   dev_t devt, void *drvdata, const char *fmt,
				   va_list args)
{
	va_list args;
	struct device *dev = NULL;
	int retval = -ENODEV;

@@ -1124,10 +1126,9 @@ struct device *device_create(struct class *class, struct device *parent,
	dev->class = class;
	dev->parent = parent;
	dev->release = device_create_release;
	dev_set_drvdata(dev, drvdata);

	va_start(args, fmt);
	vsnprintf(dev->bus_id, BUS_ID_SIZE, fmt, args);
	va_end(args);
	retval = device_register(dev);
	if (retval)
		goto error;
@@ -1138,6 +1139,78 @@ struct device *device_create(struct class *class, struct device *parent,
	kfree(dev);
	return ERR_PTR(retval);
}
EXPORT_SYMBOL_GPL(device_create_vargs);

/**
 * device_create_drvdata - creates a device and registers it with sysfs
 * @class: pointer to the struct class that this device should be registered to
 * @parent: pointer to the parent struct device of this new device, if any
 * @devt: the dev_t for the char device to be added
 * @drvdata: the data to be added to the device for callbacks
 * @fmt: string for the device's name
 *
 * This function can be used by char device classes.  A struct device
 * will be created in sysfs, registered to the specified class.
 *
 * A "dev" file will be created, showing the dev_t for the device, if
 * the dev_t is not 0,0.
 * If a pointer to a parent struct device is passed in, the newly created
 * struct device will be a child of that device in sysfs.
 * The pointer to the struct device will be returned from the call.
 * Any further sysfs files that might be required can be created using this
 * pointer.
 *
 * Note: the struct class passed to this function must have previously
 * been created with a call to class_create().
 */
struct device *device_create_drvdata(struct class *class,
				     struct device *parent,
				     dev_t devt,
				     void *drvdata,
				     const char *fmt, ...)
{
	va_list vargs;
	struct device *dev;

	va_start(vargs, fmt);
	dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs);
	va_end(vargs);
	return dev;
}
EXPORT_SYMBOL_GPL(device_create_drvdata);

/**
 * device_create - creates a device and registers it with sysfs
 * @class: pointer to the struct class that this device should be registered to
 * @parent: pointer to the parent struct device of this new device, if any
 * @devt: the dev_t for the char device to be added
 * @fmt: string for the device's name
 *
 * This function can be used by char device classes.  A struct device
 * will be created in sysfs, registered to the specified class.
 *
 * A "dev" file will be created, showing the dev_t for the device, if
 * the dev_t is not 0,0.
 * If a pointer to a parent struct device is passed in, the newly created
 * struct device will be a child of that device in sysfs.
 * The pointer to the struct device will be returned from the call.
 * Any further sysfs files that might be required can be created using this
 * pointer.
 *
 * Note: the struct class passed to this function must have previously
 * been created with a call to class_create().
 */
struct device *device_create(struct class *class, struct device *parent,
			     dev_t devt, const char *fmt, ...)
{
	va_list vargs;
	struct device *dev;

	va_start(vargs, fmt);
	dev = device_create_vargs(class, parent, devt, NULL, fmt, vargs);
	va_end(vargs);
	return dev;
}
EXPORT_SYMBOL_GPL(device_create);

static int __match_devt(struct device *dev, void *data)
+2 −3
Original line number Diff line number Diff line
@@ -648,13 +648,12 @@ static int ide_register_port(ide_hwif_t *hwif)

	get_device(&hwif->gendev);

	hwif->portdev = device_create(ide_port_class, &hwif->gendev,
				      MKDEV(0, 0), hwif->name);
	hwif->portdev = device_create_drvdata(ide_port_class, &hwif->gendev,
					      MKDEV(0, 0), hwif, hwif->name);
	if (IS_ERR(hwif->portdev)) {
		ret = PTR_ERR(hwif->portdev);
		device_unregister(&hwif->gendev);
	}
	dev_set_drvdata(hwif->portdev, hwif);
out:
	return ret;
}
+6 −8
Original line number Diff line number Diff line
@@ -1005,8 +1005,9 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
	if (cdev_add(port->cdev, base_dev + port->dev_num, 1))
		goto err_cdev;

	port->dev = device_create(umad_class, device->dma_device,
				  port->cdev->dev, "umad%d", port->dev_num);
	port->dev = device_create_drvdata(umad_class, device->dma_device,
					  port->cdev->dev, port,
					  "umad%d", port->dev_num);
	if (IS_ERR(port->dev))
		goto err_cdev;

@@ -1024,15 +1025,12 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
	if (cdev_add(port->sm_cdev, base_dev + port->dev_num + IB_UMAD_MAX_PORTS, 1))
		goto err_sm_cdev;

	port->sm_dev = device_create(umad_class, device->dma_device,
				     port->sm_cdev->dev,
	port->sm_dev = device_create_drvdata(umad_class, device->dma_device,
					     port->sm_cdev->dev, port,
					     "issm%d", port->dev_num);
	if (IS_ERR(port->sm_dev))
		goto err_sm_cdev;

	dev_set_drvdata(port->dev,    port);
	dev_set_drvdata(port->sm_dev, port);

	if (device_create_file(port->sm_dev, &dev_attr_ibdev))
		goto err_sm_dev;
	if (device_create_file(port->sm_dev, &dev_attr_port))
+6 −5
Original line number Diff line number Diff line
@@ -755,14 +755,15 @@ static void ib_uverbs_add_one(struct ib_device *device)
	if (cdev_add(uverbs_dev->cdev, IB_UVERBS_BASE_DEV + uverbs_dev->devnum, 1))
		goto err_cdev;

	uverbs_dev->dev = device_create(uverbs_class, device->dma_device,
	uverbs_dev->dev = device_create_drvdata(uverbs_class,
						device->dma_device,
						uverbs_dev->cdev->dev,
					"uverbs%d", uverbs_dev->devnum);
						uverbs_dev,
						"uverbs%d",
						uverbs_dev->devnum);
	if (IS_ERR(uverbs_dev->dev))
		goto err_cdev;

	dev_set_drvdata(uverbs_dev->dev, uverbs_dev);

	if (device_create_file(uverbs_dev->dev, &dev_attr_ibdev))
		goto err_class;
	if (device_create_file(uverbs_dev->dev, &dev_attr_abi_version))
+2 −4
Original line number Diff line number Diff line
@@ -103,13 +103,11 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
{
	int rc;

	led_cdev->dev = device_create(leds_class, parent, 0, "%s",
					    led_cdev->name);
	led_cdev->dev = device_create_drvdata(leds_class, parent, 0, led_cdev,
					      "%s", led_cdev->name);
	if (IS_ERR(led_cdev->dev))
		return PTR_ERR(led_cdev->dev);

	dev_set_drvdata(led_cdev->dev, led_cdev);

	/* register the attributes */
	rc = device_create_file(led_cdev->dev, &dev_attr_brightness);
	if (rc)
Loading