ipack: split ipack_device_register() in several functions
authorSamuel Iglesias Gonsalvez <siglesias@igalia.com>
Fri, 8 Mar 2013 08:21:47 +0000 (09:21 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 15 Mar 2013 19:23:09 +0000 (12:23 -0700)
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>
drivers/ipack/carriers/tpci200.c
drivers/ipack/ipack.c
include/linux/ipack.h

index 0246b1fddffe5c75516d3885383323e3c9939c6d..c276fde318e547db6e101029b9498cb6d694face 100644 (file)
@@ -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,
index 4f913aa88971b590f8824ff7f7542ddf9ca3ab5d..6e066c53acce7fcd0fc5f36193f8b4c05a25ebb5 100644 (file)
@@ -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)
 {
index def91fd996f47727ab9a5725ce2271b852957384..1888e06ddf64d6f08824c9c4f842f9c884e1e1a4 100644 (file)
@@ -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);