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

Reply via email to