One function is ipack_device_init(). If it fails, it's save to kfree the "dev" reference in the carrier board.
The second function is ipack_device_register that only registers 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. Signed-off-by: Samuel Iglesias Gonsalvez <[email protected]> --- drivers/ipack/carriers/tpci200.c | 14 +++++++++++++- drivers/ipack/ipack.c | 25 ++++++++++++++++++++----- include/linux/ipack.h | 36 +++++++++++++++++++++++++++++------- 3 files changed, 62 insertions(+), 13 deletions(-) diff --git a/drivers/ipack/carriers/tpci200.c b/drivers/ipack/carriers/tpci200.c index 0246b1f..f3734f7 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) { + kfree(dev); + return ret; + } + + ret = ipack_device_register(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 7ec6b20..f148c26 100644 --- a/drivers/ipack/ipack.c +++ b/drivers/ipack/ipack.c @@ -24,6 +24,7 @@ static void ipack_device_release(struct device *dev) { struct ipack_device *device = to_ipack_dev(dev); kfree(device->id); + device->id = NULL; device->release(device); } @@ -419,7 +420,7 @@ out: return ret; } -int ipack_device_register(struct ipack_device *dev) +int ipack_device_init(struct ipack_device *dev) { int ret; @@ -447,12 +448,14 @@ 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 ret; } +EXPORT_SYMBOL_GPL(ipack_device_init); + +int ipack_device_register(struct ipack_device *dev) +{ + return device_register(&dev->dev); +} EXPORT_SYMBOL_GPL(ipack_device_register); void ipack_device_unregister(struct ipack_device *dev) @@ -461,6 +464,18 @@ void ipack_device_unregister(struct ipack_device *dev) } EXPORT_SYMBOL_GPL(ipack_device_unregister); +void ipack_get_device(struct ipack_device *dev) +{ + get_device(&dev->dev); +} +EXPORT_SYMBOL_GPL(ipack_get_device); + +void ipack_put_device(struct ipack_device *dev) +{ + put_device(&dev->dev); +} +EXPORT_SYMBOL_GPL(ipack_put_device); + static int __init ipack_init(void) { ida_init(&ipack_ida); diff --git a/include/linux/ipack.h b/include/linux/ipack.h index fea12cb..9d6d401 100644 --- a/include/linux/ipack.h +++ b/include/linux/ipack.h @@ -206,21 +206,43 @@ int ipack_driver_register(struct ipack_driver *edrv, struct module *owner, const char *name); void ipack_driver_unregister(struct ipack_driver *edrv); + + +/** + * ipack_device_init -- initialize an IPack device + * @dev: the new device to initialize. + * + * 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. + * + * NOTE: in case of failure, you can free @dev. + */ +int ipack_device_init(struct ipack_device *dev); + /** * ipack_device_register -- register an IPack device with the kernel - * @dev: the new device to register. + * @dev: the new device to register. * - * 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. + * Register 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. + * 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); +void ipack_get_device(struct ipack_device *dev); +void ipack_put_device(struct ipack_device *dev); + /** * DEFINE_IPACK_DEVICE_TABLE - macro used to describe a IndustryPack table * @_table: device table name -- 1.7.10.4 ------------------------------------------------------------------------------ Everyone hates slow websites. So do we. Make your web apps faster with AppDynamics Download AppDynamics Lite for free today: http://p.sf.net/sfu/appdyn_d2d_feb _______________________________________________ Industrypack-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/industrypack-devel
