Staging: ipack: improve the register of a bus and a device in the bus.
authorSamuel Iglesias Gonsalvez <siglesias@igalia.com>
Fri, 18 May 2012 09:10:05 +0000 (11:10 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 19 May 2012 00:36:01 +0000 (17:36 -0700)
It adds and removes some fields in the struct ipack_device and
ipack_bus_device to make it cleaner.

The API has change to group all the operations on these structures inside
of the ipack driver.

Signed-off-by: Samuel Iglesias Gonsalvez <siglesias@igalia.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/ipack/bridges/tpci200.c
drivers/staging/ipack/bridges/tpci200.h
drivers/staging/ipack/devices/ipoctal.c
drivers/staging/ipack/ipack.c
drivers/staging/ipack/ipack.h

index 4e812a79b3d1e1c1d202b66958e6f8beb25eaf2c..392aec0666c6e6e93f05f34f5287ca3de9923c54 100644 (file)
@@ -407,53 +407,22 @@ static struct ipack_device *tpci200_slot_register(const char *board_name,
                goto err_unlock;
        }
 
-       dev = kzalloc(sizeof(struct ipack_device), GFP_KERNEL);
-       if (dev == NULL) {
-               pr_info("Slot [%s %d:%d] Unable to allocate memory for new slot !\n",
-                       TPCI200_SHORTNAME,
-                       tpci200_number, slot_position);
-               goto err_unlock;
-       }
-
-       if (size > IPACK_BOARD_NAME_SIZE) {
-               pr_warning("Slot [%s %d:%d] name (%s) too long (%d > %d). Will be truncated!\n",
-                          TPCI200_SHORTNAME, tpci200_number, slot_position,
-                          board_name, (int)strlen(board_name),
-                          IPACK_BOARD_NAME_SIZE);
-
-               size = IPACK_BOARD_NAME_SIZE;
-       }
-
-       strncpy(dev->board_name, board_name, size-1);
-       dev->board_name[size-1] = '\0';
-       dev->bus_nr = tpci200->info->drv.bus_nr;
-       dev->slot = slot_position;
        /*
         * Give the same IRQ number as the slot number.
         * The TPCI200 has assigned his own two IRQ by PCI bus driver
         */
-       dev->irq = slot_position;
-
-       dev->id_space.address = NULL;
-       dev->id_space.size = 0;
-       dev->io_space.address = NULL;
-       dev->io_space.size = 0;
-       dev->mem_space.address = NULL;
-       dev->mem_space.size = 0;
+       dev = ipack_device_register(tpci200->info->ipack_bus,
+                                   slot_position, slot_position);
+       if (dev == NULL) {
+               pr_info("Slot [%d:%d] Unable to register an ipack device\n",
+                       tpci200_number, slot_position);
+               goto err_unlock;
+       }
 
-       /* Give the operations structure */
-       dev->ops = &tpci200_bus_ops;
        tpci200->slots[slot_position].dev = dev;
-
-       if (ipack_device_register(dev) < 0)
-               goto err_unregister;
-
        mutex_unlock(&tpci200->mutex);
        return dev;
 
-err_unregister:
-       tpci200_slot_unregister(dev);
-       kfree(dev);
 err_unlock:
        mutex_unlock(&tpci200->mutex);
        return NULL;
@@ -874,7 +843,6 @@ static int tpci200_slot_unregister(struct ipack_device *dev)
 
        ipack_device_unregister(dev);
        tpci200->slots[dev->slot].dev = NULL;
-       kfree(dev);
        mutex_unlock(&tpci200->mutex);
 
        return 0;
@@ -1116,20 +1084,20 @@ static int tpci200_pciprobe(struct pci_dev *pdev,
                return -ENODEV;
        }
 
-       tpci200->info->drv.dev = &pdev->dev;
-       tpci200->info->drv.slots = TPCI200_NB_SLOT;
-
-       /* Register the bus in the industry pack driver */
-       ret = ipack_bus_register(&tpci200->info->drv);
-       if (ret < 0) {
+       /* Register the carrier in the industry pack bus driver */
+       tpci200->info->ipack_bus = ipack_bus_register(&pdev->dev,
+                                                     TPCI200_NB_SLOT,
+                                                     &tpci200_bus_ops);
+       if (!tpci200->info->ipack_bus) {
                pr_err("error registering the carrier on ipack driver\n");
                tpci200_uninstall(tpci200);
                kfree(tpci200->info);
                kfree(tpci200);
                return -EFAULT;
        }
+
        /* save the bus number given by ipack to logging purpose */
-       tpci200->number = tpci200->info->drv.bus_nr;
+       tpci200->number = tpci200->info->ipack_bus->bus_nr;
        dev_set_drvdata(&pdev->dev, tpci200);
        /* add the registered device in an internal linked list */
        list_add_tail(&tpci200->list, &tpci200_list);
@@ -1141,7 +1109,8 @@ static void __tpci200_pci_remove(struct tpci200_board *tpci200)
        tpci200_uninstall(tpci200);
        tpci200_remove_sysfs_files(tpci200);
        list_del(&tpci200->list);
-       ipack_bus_unregister(&tpci200->info->drv);
+       ipack_bus_unregister(tpci200->info->ipack_bus);
+       kfree(tpci200->info);
        kfree(tpci200);
 }
 
index c05210792e9d9c3618abdaf8eb8c0f736ab1d876..e3a7e5d1cfeb012f7b4b505142d8321a4d61e3be 100644 (file)
@@ -151,7 +151,7 @@ struct tpci200_infos {
        void __iomem                    *ioidint_space;
        void __iomem                    *mem8_space;
        spinlock_t                      access_lock;
-       struct ipack_bus_device         drv;
+       struct ipack_bus_device         *ipack_bus;
 };
 struct tpci200_board {
        struct list_head        list;
index c88f391ca62cf8dd7c92c8d6dad06078e7ec8e94..29f6fa841d2327f1781981543a863e8613708c22 100644 (file)
@@ -73,7 +73,8 @@ static inline void ipoctal_write_io_reg(struct ipoctal *ipoctal,
        unsigned long offset;
 
        offset = ((void __iomem *) dest) - ipoctal->dev->io_space.address;
-       ipoctal->dev->ops->write8(ipoctal->dev, IPACK_IO_SPACE, offset, value);
+       ipoctal->dev->bus->ops->write8(ipoctal->dev, IPACK_IO_SPACE, offset,
+                                      value);
 }
 
 static inline void ipoctal_write_cr_cmd(struct ipoctal *ipoctal,
@@ -90,7 +91,8 @@ static inline unsigned char ipoctal_read_io_reg(struct ipoctal *ipoctal,
        unsigned char value;
 
        offset = ((void __iomem *) src) - ipoctal->dev->io_space.address;
-       ipoctal->dev->ops->read8(ipoctal->dev, IPACK_IO_SPACE, offset, &value);
+       ipoctal->dev->bus->ops->read8(ipoctal->dev, IPACK_IO_SPACE, offset,
+                                     &value);
        return value;
 }
 
@@ -341,12 +343,12 @@ static int ipoctal_check_model(struct ipack_device *dev, unsigned char *id)
        unsigned char manufacturerID;
        unsigned char board_id;
 
-       dev->ops->read8(dev, IPACK_ID_SPACE,
+       dev->bus->ops->read8(dev, IPACK_ID_SPACE,
                        IPACK_IDPROM_OFFSET_MANUFACTURER_ID, &manufacturerID);
        if (manufacturerID != IP_OCTAL_MANUFACTURER_ID)
                return -ENODEV;
 
-       dev->ops->read8(dev, IPACK_ID_SPACE,
+       dev->bus->ops->read8(dev, IPACK_ID_SPACE,
                        IPACK_IDPROM_OFFSET_MODEL, (unsigned char *)&board_id);
 
        switch (board_id) {
@@ -376,7 +378,8 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
        char name[20];
        unsigned char board_id;
 
-       res = ipoctal->dev->ops->map_space(ipoctal->dev, 0, IPACK_ID_SPACE);
+       res = ipoctal->dev->bus->ops->map_space(ipoctal->dev, 0,
+                                               IPACK_ID_SPACE);
        if (res) {
                pr_err("Unable to map slot [%d:%d] ID space!\n", bus_nr, slot);
                return res;
@@ -384,18 +387,20 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
 
        res = ipoctal_check_model(ipoctal->dev, &board_id);
        if (res) {
-               ipoctal->dev->ops->unmap_space(ipoctal->dev, IPACK_ID_SPACE);
+               ipoctal->dev->bus->ops->unmap_space(ipoctal->dev,
+                                                   IPACK_ID_SPACE);
                goto out_unregister_id_space;
        }
        ipoctal->board_id = board_id;
 
-       res = ipoctal->dev->ops->map_space(ipoctal->dev, 0, IPACK_IO_SPACE);
+       res = ipoctal->dev->bus->ops->map_space(ipoctal->dev, 0,
+                                               IPACK_IO_SPACE);
        if (res) {
                pr_err("Unable to map slot [%d:%d] IO space!\n", bus_nr, slot);
                goto out_unregister_id_space;
        }
 
-       res = ipoctal->dev->ops->map_space(ipoctal->dev,
+       res = ipoctal->dev->bus->ops->map_space(ipoctal->dev,
                                           0x8000, IPACK_MEM_SPACE);
        if (res) {
                pr_err("Unable to map slot [%d:%d] MEM space!\n", bus_nr, slot);
@@ -434,9 +439,9 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
         * Depending of the carrier these addresses are accesible or not.
         * More info in the datasheet.
         */
-       ipoctal->dev->ops->request_irq(ipoctal->dev, vector,
+       ipoctal->dev->bus->ops->request_irq(ipoctal->dev, vector,
                                       ipoctal_irq_handler, ipoctal);
-       ipoctal->dev->ops->write8(ipoctal->dev, IPACK_ID_SPACE, 0, vector);
+       ipoctal->dev->bus->ops->write8(ipoctal->dev, IPACK_ID_SPACE, 0, vector);
 
        /* Register the TTY device */
 
@@ -502,11 +507,11 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
        return 0;
 
 out_unregister_slot_unmap:
-       ipoctal->dev->ops->unmap_space(ipoctal->dev, IPACK_ID_SPACE);
+       ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_ID_SPACE);
 out_unregister_io_space:
-       ipoctal->dev->ops->unmap_space(ipoctal->dev, IPACK_IO_SPACE);
+       ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_IO_SPACE);
 out_unregister_id_space:
-       ipoctal->dev->ops->unmap_space(ipoctal->dev, IPACK_MEM_SPACE);
+       ipoctal->dev->bus->ops->unmap_space(ipoctal->dev, IPACK_MEM_SPACE);
        return res;
 }
 
@@ -799,13 +804,20 @@ static int ipoctal_match(struct ipack_device *dev)
        int res;
        unsigned char board_id;
 
-       res = dev->ops->map_space(dev, 0, IPACK_ID_SPACE);
+       if ((!dev->bus->ops) || (!dev->bus->ops->map_space) ||
+           (!dev->bus->ops->unmap_space))
+               return 0;
+
+       res = dev->bus->ops->map_space(dev, 0, IPACK_ID_SPACE);
        if (res)
-               return res;
+               return 0;
 
        res = ipoctal_check_model(dev, &board_id);
-       dev->ops->unmap_space(dev, IPACK_ID_SPACE);
-       return res;
+       dev->bus->ops->unmap_space(dev, IPACK_ID_SPACE);
+       if (!res)
+               return 1;
+
+       return 0;
 }
 
 static int ipoctal_probe(struct ipack_device *dev)
@@ -843,8 +855,8 @@ static void __ipoctal_remove(struct ipoctal *ipoctal)
        put_tty_driver(ipoctal->tty_drv);
 
        /* Tell the carrier board to free all the resources for this device */
-       if (ipoctal->dev->ops->remove_device != NULL)
-               ipoctal->dev->ops->remove_device(ipoctal->dev);
+       if (ipoctal->dev->bus->ops->remove_device != NULL)
+               ipoctal->dev->bus->ops->remove_device(ipoctal->dev);
 
        list_del(&ipoctal->list);
        kfree(ipoctal);
@@ -868,11 +880,8 @@ static struct ipack_driver_ops ipoctal_drv_ops = {
 
 static int __init ipoctal_init(void)
 {
-       driver.owner = THIS_MODULE;
        driver.ops = &ipoctal_drv_ops;
-       driver.driver.name = KBUILD_MODNAME;
-       ipack_driver_register(&driver);
-       return 0;
+       return ipack_driver_register(&driver, THIS_MODULE, KBUILD_MODNAME);
 }
 
 static void __exit ipoctal_exit(void)
index ad06e06bdc743644b301ce1bcbde63d5de10b55d..2b4fa51bf167a81d67ec59a719dd5e2bd906d564 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/slab.h>
 #include "ipack.h"
 
 #define to_ipack_dev(device) container_of(device, struct ipack_device, dev)
@@ -28,13 +29,19 @@ struct ipack_busmap {
 };
 static struct ipack_busmap busmap;
 
+static void ipack_device_release(struct device *dev)
+{
+       struct ipack_device *device = to_ipack_dev(dev);
+       kfree(device);
+}
+
 static int ipack_bus_match(struct device *device, struct device_driver *driver)
 {
        int ret;
        struct ipack_device *dev = to_ipack_dev(device);
        struct ipack_driver *drv = to_ipack_driver(driver);
 
-       if (!drv->ops->match)
+       if ((!drv->ops) || (!drv->ops->match))
                return -EINVAL;
 
        ret = drv->ops->match(dev);
@@ -92,16 +99,27 @@ error_find_busnum:
        return busnum;
 }
 
-int ipack_bus_register(struct ipack_bus_device *bus)
+struct ipack_bus_device *ipack_bus_register(struct device *parent, int slots,
+                                           struct ipack_bus_ops *ops)
 {
        int bus_nr;
+       struct ipack_bus_device *bus;
+
+       bus = kzalloc(sizeof(struct ipack_bus_device), GFP_KERNEL);
+       if (!bus)
+               return NULL;
 
        bus_nr = ipack_assign_bus_number();
-       if (bus_nr < 0)
-               return -1;
+       if (bus_nr < 0) {
+               kfree(bus);
+               return NULL;
+       }
 
        bus->bus_nr = bus_nr;
-       return 0;
+       bus->parent = parent;
+       bus->slots = slots;
+       bus->ops = ops;
+       return bus;
 }
 EXPORT_SYMBOL_GPL(ipack_bus_register);
 
@@ -110,12 +128,16 @@ int ipack_bus_unregister(struct ipack_bus_device *bus)
        mutex_lock(&ipack_mutex);
        clear_bit(bus->bus_nr, busmap.busmap);
        mutex_unlock(&ipack_mutex);
+       kfree(bus);
        return 0;
 }
 EXPORT_SYMBOL_GPL(ipack_bus_unregister);
 
-int ipack_driver_register(struct ipack_driver *edrv)
+int ipack_driver_register(struct ipack_driver *edrv, struct module *owner,
+                         char *name)
 {
+       edrv->driver.owner = owner;
+       edrv->driver.name = name;
        edrv->driver.bus = &ipack_bus_type;
        return driver_register(&edrv->driver);
 }
@@ -127,26 +149,35 @@ void ipack_driver_unregister(struct ipack_driver *edrv)
 }
 EXPORT_SYMBOL_GPL(ipack_driver_unregister);
 
-static void ipack_device_release(struct device *dev)
-{
-}
-
-int ipack_device_register(struct ipack_device *dev)
+struct ipack_device *ipack_device_register(struct ipack_bus_device *bus,
+                                          int slot, int irqv)
 {
        int ret;
+       struct ipack_device *dev;
+
+       dev = kzalloc(sizeof(struct ipack_device), GFP_KERNEL);
+       if (!dev)
+               return NULL;
 
        dev->dev.bus = &ipack_bus_type;
        dev->dev.release = ipack_device_release;
+       dev->dev.parent = bus->parent;
+       dev->slot = slot;
+       dev->bus_nr = bus->bus_nr;
+       dev->irq = irqv;
+       dev->bus = bus;
        dev_set_name(&dev->dev,
-                    "%s.%u.%u", dev->board_name, dev->bus_nr, dev->slot);
+                    "ipack-dev.%u.%u", dev->bus_nr, dev->slot);
 
        ret = device_register(&dev->dev);
        if (ret < 0) {
                pr_err("error registering the device.\n");
                dev->driver->ops->remove(dev);
+               kfree(dev);
+               return NULL;
        }
 
-       return ret;
+       return dev;
 }
 EXPORT_SYMBOL_GPL(ipack_device_register);
 
index 7f408adc14bc6543efae8d780c06d68c88032ee2..d50af713956975b1032822c5cecfed9f05a4789a 100644 (file)
@@ -49,13 +49,11 @@ struct ipack_addr_space {
 /**
  *     struct ipack_device
  *
- *     @board_name: IP mezzanine board name
- *     @bus_name: IP carrier board name
  *     @bus_nr: IP bus number where the device is plugged
  *     @slot: Slot where the device is plugged in the carrier board
  *     @irq: IRQ vector
  *     @driver: Pointer to the ipack_driver that manages the device
- *     @ops: Carrier board operations to access the device
+ *     @bus: ipack_bus_device where the device is plugged to.
  *     @id_space: Virtual address to ID space.
  *     @io_space: Virtual address to IO space.
  *     @mem_space: Virtual address to MEM space.
@@ -63,7 +61,7 @@ struct ipack_addr_space {
  *
  * Warning: Direct access to mapped memory is possible but the endianness
  * is not the same with PCI carrier or VME carrier. The endianness is managed
- * by the carrier board throught @ops.
+ * by the carrier board throught bus->ops.
  */
 struct ipack_device {
        char board_name[IPACK_BOARD_NAME_SIZE];
@@ -72,14 +70,14 @@ struct ipack_device {
        unsigned int slot;
        unsigned int irq;
        struct ipack_driver *driver;
-       struct ipack_bus_ops *ops;
+       struct ipack_bus_device *bus;
        struct ipack_addr_space id_space;
        struct ipack_addr_space io_space;
        struct ipack_addr_space mem_space;
        struct device dev;
 };
 
-/*
+/**
  *     struct ipack_driver_ops -- callbacks to mezzanine driver for installing/removing one device
  *
  *     @match: Match function
@@ -94,36 +92,16 @@ struct ipack_driver_ops {
 };
 
 /**
- *     struct ipack_driver -- Specific data to each mezzanine board driver
+ *     struct ipack_driver -- Specific data to each ipack board driver
  *
  *     @driver: Device driver kernel representation
  *     @ops: Mezzanine driver operations specific for the ipack bus.
  */
 struct ipack_driver {
-       struct module *owner;
        struct device_driver driver;
        struct ipack_driver_ops *ops;
 };
 
-/*
- *     ipack_driver_register -- Register a new mezzanine driver
- *
- * Called by the mezzanine driver to register itself as a driver
- * that can manage ipack devices.
- */
-
-int ipack_driver_register(struct ipack_driver *edrv);
-void ipack_driver_unregister(struct ipack_driver *edrv);
-
-/*
- *     ipack_device_register -- register a new mezzanine device
- *
- * Register a new ipack device (mezzanine device). The call is done by
- * the carrier device driver.
- */
-int ipack_device_register(struct ipack_device *dev);
-void ipack_device_unregister(struct ipack_device *dev);
-
 /**
  *     struct ipack_bus_ops - available operations on a bridge module
  *
@@ -159,24 +137,51 @@ struct ipack_bus_ops {
  *     @dev: pointer to carrier device
  *     @slots: number of slots available
  *     @bus_nr: ipack bus number
- *     @vector: IRQ base vector. IRQ vectors are $vector + $slot_number
+ *     @ops: bus operations for the mezzanine drivers
  */
 struct ipack_bus_device {
-       struct device *dev;
+       struct device *parent;
        int slots;
        int bus_nr;
-       int vector;
+       struct ipack_bus_ops *ops;
 };
 
 /**
  *     ipack_bus_register -- register a new ipack bus
  *
- * The carrier board device driver should call this function to register itself
- * as available bus in ipack.
+ * @parent: pointer to the parent device, if any.
+ * @slots: number of slots available in the bus device.
+ * @ops: bus operations for the mezzanine drivers.
+ *
+ * The carrier board device should call this function to register itself as
+ * available bus device in ipack.
  */
-int ipack_bus_register(struct ipack_bus_device *bus);
+struct ipack_bus_device *ipack_bus_register(struct device *parent, int slots,
+                                           struct ipack_bus_ops *ops);
 
 /**
  *     ipack_bus_unregister -- unregister an ipack bus
  */
 int ipack_bus_unregister(struct ipack_bus_device *bus);
+
+/**
+ *     ipack_driver_register -- Register a new driver
+ *
+ * Called by a ipack driver to register itself as a driver
+ * that can manage ipack devices.
+ */
+int ipack_driver_register(struct ipack_driver *edrv, struct module *owner, char *name);
+void ipack_driver_unregister(struct ipack_driver *edrv);
+
+/**
+ *     ipack_device_register -- register a new mezzanine device
+ *
+ * @bus: ipack bus device it is plugged to.
+ * @slot: slot position in the bus device.
+ * @irqv: IRQ vector for the mezzanine.
+ *
+ * Register a new ipack device (mezzanine device). The call is done by
+ * the carrier device driver.
+ */
+struct ipack_device *ipack_device_register(struct ipack_bus_device *bus, int slot, int irqv);
+void ipack_device_unregister(struct ipack_device *dev);