diff options
Diffstat (limited to 'drivers/mcb')
-rw-r--r-- | drivers/mcb/mcb-core.c | 116 | ||||
-rw-r--r-- | drivers/mcb/mcb-internal.h | 1 | ||||
-rw-r--r-- | drivers/mcb/mcb-parse.c | 15 | ||||
-rw-r--r-- | drivers/mcb/mcb-pci.c | 23 |
4 files changed, 119 insertions, 36 deletions
diff --git a/drivers/mcb/mcb-core.c b/drivers/mcb/mcb-core.c index a4be45107..6f2c8522e 100644 --- a/drivers/mcb/mcb-core.c +++ b/drivers/mcb/mcb-core.c @@ -61,21 +61,36 @@ static int mcb_probe(struct device *dev) struct mcb_driver *mdrv = to_mcb_driver(dev->driver); struct mcb_device *mdev = to_mcb_device(dev); const struct mcb_device_id *found_id; + struct module *carrier_mod; + int ret; found_id = mcb_match_id(mdrv->id_table, mdev); if (!found_id) return -ENODEV; - return mdrv->probe(mdev, found_id); + carrier_mod = mdev->dev.parent->driver->owner; + if (!try_module_get(carrier_mod)) + return -EINVAL; + + get_device(dev); + ret = mdrv->probe(mdev, found_id); + if (ret) + module_put(carrier_mod); + + return ret; } static int mcb_remove(struct device *dev) { struct mcb_driver *mdrv = to_mcb_driver(dev->driver); struct mcb_device *mdev = to_mcb_device(dev); + struct module *carrier_mod; mdrv->remove(mdev); + carrier_mod = mdev->dev.parent->driver->owner; + module_put(carrier_mod); + put_device(&mdev->dev); return 0; @@ -83,13 +98,67 @@ static int mcb_remove(struct device *dev) static void mcb_shutdown(struct device *dev) { + struct mcb_driver *mdrv = to_mcb_driver(dev->driver); struct mcb_device *mdev = to_mcb_device(dev); - struct mcb_driver *mdrv = mdev->driver; if (mdrv && mdrv->shutdown) mdrv->shutdown(mdev); } +static ssize_t revision_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct mcb_bus *bus = to_mcb_bus(dev); + + return scnprintf(buf, PAGE_SIZE, "%d\n", bus->revision); +} +static DEVICE_ATTR_RO(revision); + +static ssize_t model_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct mcb_bus *bus = to_mcb_bus(dev); + + return scnprintf(buf, PAGE_SIZE, "%c\n", bus->model); +} +static DEVICE_ATTR_RO(model); + +static ssize_t minor_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct mcb_bus *bus = to_mcb_bus(dev); + + return scnprintf(buf, PAGE_SIZE, "%d\n", bus->minor); +} +static DEVICE_ATTR_RO(minor); + +static ssize_t name_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct mcb_bus *bus = to_mcb_bus(dev); + + return scnprintf(buf, PAGE_SIZE, "%s\n", bus->name); +} +static DEVICE_ATTR_RO(name); + +static struct attribute *mcb_bus_attrs[] = { + &dev_attr_revision.attr, + &dev_attr_model.attr, + &dev_attr_minor.attr, + &dev_attr_name.attr, + NULL, +}; + +static const struct attribute_group mcb_carrier_group = { + .attrs = mcb_bus_attrs, +}; + +static const struct attribute_group *mcb_carrier_groups[] = { + &mcb_carrier_group, + NULL, +}; + + static struct bus_type mcb_bus_type = { .name = "mcb", .match = mcb_match, @@ -99,6 +168,11 @@ static struct bus_type mcb_bus_type = { .shutdown = mcb_shutdown, }; +static struct device_type mcb_carrier_device_type = { + .name = "mcb-carrier", + .groups = mcb_carrier_groups, +}; + /** * __mcb_register_driver() - Register a @mcb_driver at the system * @drv: The @mcb_driver @@ -155,6 +229,7 @@ int mcb_device_register(struct mcb_bus *bus, struct mcb_device *dev) int device_id; device_initialize(&dev->dev); + mcb_bus_get(bus); dev->dev.bus = &mcb_bus_type; dev->dev.parent = bus->dev.parent; dev->dev.release = mcb_release_dev; @@ -178,6 +253,15 @@ out: } EXPORT_SYMBOL_GPL(mcb_device_register); +static void mcb_free_bus(struct device *dev) +{ + struct mcb_bus *bus = to_mcb_bus(dev); + + put_device(bus->carrier); + ida_simple_remove(&mcb_ida, bus->bus_nr); + kfree(bus); +} + /** * mcb_alloc_bus() - Allocate a new @mcb_bus * @@ -187,6 +271,7 @@ struct mcb_bus *mcb_alloc_bus(struct device *carrier) { struct mcb_bus *bus; int bus_nr; + int rc; bus = kzalloc(sizeof(struct mcb_bus), GFP_KERNEL); if (!bus) @@ -194,14 +279,29 @@ struct mcb_bus *mcb_alloc_bus(struct device *carrier) bus_nr = ida_simple_get(&mcb_ida, 0, 0, GFP_KERNEL); if (bus_nr < 0) { - kfree(bus); - return ERR_PTR(bus_nr); + rc = bus_nr; + goto err_free; } - INIT_LIST_HEAD(&bus->children); bus->bus_nr = bus_nr; - bus->carrier = carrier; + bus->carrier = get_device(carrier); + + device_initialize(&bus->dev); + bus->dev.parent = carrier; + bus->dev.bus = &mcb_bus_type; + bus->dev.type = &mcb_carrier_device_type; + bus->dev.release = &mcb_free_bus; + + dev_set_name(&bus->dev, "mcb:%d", bus_nr); + rc = device_add(&bus->dev); + if (rc) + goto err_free; + return bus; +err_free: + put_device(carrier); + kfree(bus); + return ERR_PTR(rc); } EXPORT_SYMBOL_GPL(mcb_alloc_bus); @@ -224,10 +324,6 @@ static void mcb_devices_unregister(struct mcb_bus *bus) void mcb_release_bus(struct mcb_bus *bus) { mcb_devices_unregister(bus); - - ida_simple_remove(&mcb_ida, bus->bus_nr); - - kfree(bus); } EXPORT_SYMBOL_GPL(mcb_release_bus); diff --git a/drivers/mcb/mcb-internal.h b/drivers/mcb/mcb-internal.h index fb7493dcf..5254e0285 100644 --- a/drivers/mcb/mcb-internal.h +++ b/drivers/mcb/mcb-internal.h @@ -5,7 +5,6 @@ #define PCI_VENDOR_ID_MEN 0x1a88 #define PCI_DEVICE_ID_MEN_CHAMELEON 0x4d45 -#define CHAMELEON_FILENAME_LEN 12 #define CHAMELEONV2_MAGIC 0xabce #define CHAM_HEADER_SIZE 0x200 diff --git a/drivers/mcb/mcb-parse.c b/drivers/mcb/mcb-parse.c index b0155b05c..dbecbed0d 100644 --- a/drivers/mcb/mcb-parse.c +++ b/drivers/mcb/mcb-parse.c @@ -113,16 +113,11 @@ int chameleon_parse_cells(struct mcb_bus *bus, phys_addr_t mapbase, } p += hsize; - pr_debug("header->revision = %d\n", header->revision); - pr_debug("header->model = 0x%x ('%c')\n", header->model, - header->model); - pr_debug("header->minor = %d\n", header->minor); - pr_debug("header->bus_type = 0x%x\n", header->bus_type); - - - pr_debug("header->magic = 0x%x\n", header->magic); - pr_debug("header->filename = \"%.*s\"\n", CHAMELEON_FILENAME_LEN, - header->filename); + bus->revision = header->revision; + bus->model = header->model; + bus->minor = header->minor; + snprintf(bus->name, CHAMELEON_FILENAME_LEN + 1, "%s", + header->filename); for_each_chameleon_cell(dtype, p) { switch (dtype) { diff --git a/drivers/mcb/mcb-pci.c b/drivers/mcb/mcb-pci.c index 67d5e7d08..b15a0349c 100644 --- a/drivers/mcb/mcb-pci.c +++ b/drivers/mcb/mcb-pci.c @@ -35,7 +35,6 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) struct resource *res; struct priv *priv; int ret; - int num_cells; unsigned long flags; priv = devm_kzalloc(&pdev->dev, sizeof(struct priv), GFP_KERNEL); @@ -55,19 +54,20 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto out_disable; } - res = request_mem_region(priv->mapbase, CHAM_HEADER_SIZE, - KBUILD_MODNAME); + res = devm_request_mem_region(&pdev->dev, priv->mapbase, + CHAM_HEADER_SIZE, + KBUILD_MODNAME); if (!res) { dev_err(&pdev->dev, "Failed to request PCI memory\n"); ret = -EBUSY; goto out_disable; } - priv->base = ioremap(priv->mapbase, CHAM_HEADER_SIZE); + priv->base = devm_ioremap(&pdev->dev, priv->mapbase, CHAM_HEADER_SIZE); if (!priv->base) { dev_err(&pdev->dev, "Cannot ioremap\n"); ret = -ENOMEM; - goto out_release; + goto out_disable; } flags = pci_resource_flags(pdev, 0); @@ -75,7 +75,7 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) ret = -ENOTSUPP; dev_err(&pdev->dev, "IO mapped PCI devices are not supported\n"); - goto out_iounmap; + goto out_disable; } pci_set_drvdata(pdev, priv); @@ -83,7 +83,7 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) priv->bus = mcb_alloc_bus(&pdev->dev); if (IS_ERR(priv->bus)) { ret = PTR_ERR(priv->bus); - goto out_iounmap; + goto out_disable; } priv->bus->get_irq = mcb_pci_get_irq; @@ -91,9 +91,8 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) ret = chameleon_parse_cells(priv->bus, priv->mapbase, priv->base); if (ret < 0) goto out_mcb_bus; - num_cells = ret; - dev_dbg(&pdev->dev, "Found %d cells\n", num_cells); + dev_dbg(&pdev->dev, "Found %d cells\n", ret); mcb_bus_add_devices(priv->bus); @@ -101,10 +100,6 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) out_mcb_bus: mcb_release_bus(priv->bus); -out_iounmap: - iounmap(priv->base); -out_release: - pci_release_region(pdev, 0); out_disable: pci_disable_device(pdev); return ret; @@ -116,8 +111,6 @@ static void mcb_pci_remove(struct pci_dev *pdev) mcb_release_bus(priv->bus); - iounmap(priv->base); - release_region(priv->mapbase, CHAM_HEADER_SIZE); pci_disable_device(pdev); } |