Skip to content

Commit

Permalink
Staging: ipack: improve the register of a bus and a device in the bus.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Samuel Iglesias Gonsalvez authored and Greg Kroah-Hartman committed May 19, 2012
1 parent 484ecc9 commit ec44033
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 117 deletions.
63 changes: 16 additions & 47 deletions drivers/staging/ipack/bridges/tpci200.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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);
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/staging/ipack/bridges/tpci200.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
55 changes: 32 additions & 23 deletions drivers/staging/ipack/devices/ipoctal.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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;
}

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -376,26 +378,29 @@ 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;
}

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);
Expand Down Expand Up @@ -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 */

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand All @@ -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)
Expand Down
57 changes: 44 additions & 13 deletions drivers/staging/ipack/ipack.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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);
Expand Down Expand Up @@ -92,16 +99,27 @@ static int ipack_assign_bus_number(void)
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);

Expand All @@ -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);
}
Expand All @@ -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);

Expand Down
Loading

0 comments on commit ec44033

Please sign in to comment.