diff options
author | Samuel Iglesias Gonsalvez <siglesias@igalia.com> | 2013-03-08 09:21:47 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-03-15 12:23:09 -0700 |
commit | e926301b39a07f587ff8c66354a2e2ee4c29162c (patch) | |
tree | 407121dd6ef41bfa48681e2ed4f7f48bf85b5f40 | |
parent | fa882867ae5f8543eb304a1667563f1c99514475 (diff) | |
download | op-kernel-dev-e926301b39a07f587ff8c66354a2e2ee4c29162c.zip op-kernel-dev-e926301b39a07f587ff8c66354a2e2ee4c29162c.tar.gz |
ipack: split ipack_device_register() in several functions
One function is ipack_device_init(). If it fails, the caller should execute
ipack_put_device().
The second function is ipack_device_add that only adds the device. If
it fails, the caller should execute ipack_put_device().
Then the device is removed with refcount = 0, as device_register() kernel
documentation says.
ipack_device_del() is added to remove the device.
Signed-off-by: Samuel Iglesias Gonsalvez <siglesias@igalia.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/ipack/carriers/tpci200.c | 14 | ||||
-rw-r--r-- | drivers/ipack/ipack.c | 24 | ||||
-rw-r--r-- | include/linux/ipack.h | 39 |
3 files changed, 56 insertions, 21 deletions
diff --git a/drivers/ipack/carriers/tpci200.c b/drivers/ipack/carriers/tpci200.c index 0246b1f..c276fde 100644 --- a/drivers/ipack/carriers/tpci200.c +++ b/drivers/ipack/carriers/tpci200.c @@ -480,6 +480,7 @@ static void tpci200_release_device(struct ipack_device *dev) static int tpci200_create_device(struct tpci200_board *tpci200, int i) { + int ret; enum ipack_space space; struct ipack_device *dev = kzalloc(sizeof(struct ipack_device), GFP_KERNEL); @@ -495,7 +496,18 @@ static int tpci200_create_device(struct tpci200_board *tpci200, int i) + tpci200_space_interval[space] * i; dev->region[space].size = tpci200_space_size[space]; } - return ipack_device_register(dev); + + ret = ipack_device_init(dev); + if (ret < 0) { + ipack_put_device(dev); + return ret; + } + + ret = ipack_device_add(dev); + if (ret < 0) + ipack_put_device(dev); + + return ret; } static int tpci200_pci_probe(struct pci_dev *pdev, diff --git a/drivers/ipack/ipack.c b/drivers/ipack/ipack.c index 4f913aa8..6e066c5 100644 --- a/drivers/ipack/ipack.c +++ b/drivers/ipack/ipack.c @@ -227,7 +227,7 @@ static int ipack_unregister_bus_member(struct device *dev, void *data) struct ipack_bus_device *bus = data; if (idev->bus == bus) - ipack_device_unregister(idev); + ipack_device_del(idev); return 1; } @@ -419,7 +419,7 @@ out: return ret; } -int ipack_device_register(struct ipack_device *dev) +int ipack_device_init(struct ipack_device *dev) { int ret; @@ -428,6 +428,7 @@ int ipack_device_register(struct ipack_device *dev) dev->dev.parent = dev->bus->parent; dev_set_name(&dev->dev, "ipack-dev.%u.%u", dev->bus->bus_nr, dev->slot); + device_initialize(&dev->dev); if (dev->bus->ops->set_clockrate(dev, 8)) dev_warn(&dev->dev, "failed to switch to 8 MHz operation for reading of device ID.\n"); @@ -447,19 +448,22 @@ int ipack_device_register(struct ipack_device *dev) dev_err(&dev->dev, "failed to switch to 32 MHz operation.\n"); } - ret = device_register(&dev->dev); - if (ret < 0) - kfree(dev->id); + return 0; +} +EXPORT_SYMBOL_GPL(ipack_device_init); - return ret; +int ipack_device_add(struct ipack_device *dev) +{ + return device_add(&dev->dev); } -EXPORT_SYMBOL_GPL(ipack_device_register); +EXPORT_SYMBOL_GPL(ipack_device_add); -void ipack_device_unregister(struct ipack_device *dev) +void ipack_device_del(struct ipack_device *dev) { - device_unregister(&dev->dev); + device_del(&dev->dev); + ipack_put_device(dev); } -EXPORT_SYMBOL_GPL(ipack_device_unregister); +EXPORT_SYMBOL_GPL(ipack_device_del); void ipack_get_device(struct ipack_device *dev) { diff --git a/include/linux/ipack.h b/include/linux/ipack.h index def91fd..1888e06 100644 --- a/include/linux/ipack.h +++ b/include/linux/ipack.h @@ -207,19 +207,38 @@ int ipack_driver_register(struct ipack_driver *edrv, struct module *owner, void ipack_driver_unregister(struct ipack_driver *edrv); /** - * ipack_device_register -- register an IPack device with the kernel - * @dev: the new device to register. + * ipack_device_init -- initialize an IPack device + * @dev: the new device to initialize. * - * Register a new IPack device ("module" in IndustryPack jargon). The call - * is done by the carrier driver. The carrier should populate the fields - * bus and slot as well as the region array of @dev prior to calling this - * function. The rest of the fields will be allocated and populated - * during registration. + * Initialize a new IPack device ("module" in IndustryPack jargon). The call + * is done by the carrier driver. The carrier should populate the fields + * bus and slot as well as the region array of @dev prior to calling this + * function. The rest of the fields will be allocated and populated + * during initalization. * - * Return zero on success or error code on failure. + * Return zero on success or error code on failure. + * + * NOTE: _Never_ directly free @dev after calling this function, even + * if it returned an error! Always use ipack_put_device() to give up the + * reference initialized in this function instead. + */ +int ipack_device_init(struct ipack_device *dev); + +/** + * ipack_device_add -- Add an IPack device + * @dev: the new device to add. + * + * Add a new IPack device. The call is done by the carrier driver + * after calling ipack_device_init(). + * + * Return zero on success or error code on failure. + * + * NOTE: _Never_ directly free @dev after calling this function, even + * if it returned an error! Always use ipack_put_device() to give up the + * reference initialized in this function instead. */ -int ipack_device_register(struct ipack_device *dev); -void ipack_device_unregister(struct ipack_device *dev); +int ipack_device_add(struct ipack_device *dev); +void ipack_device_del(struct ipack_device *dev); void ipack_get_device(struct ipack_device *dev); void ipack_put_device(struct ipack_device *dev); |