bcma: use (get|put)_device when probing/removing device driver
[pandora-kernel.git] / drivers / bcma / main.c
index 73b7b1a..94dd240 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include "bcma_private.h"
+#include <linux/module.h>
 #include <linux/bcma/bcma.h>
 #include <linux/slab.h>
 
@@ -68,6 +69,10 @@ static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
 static void bcma_release_core_dev(struct device *dev)
 {
        struct bcma_device *core = container_of(dev, struct bcma_device, dev);
+       if (core->io_addr)
+               iounmap(core->io_addr);
+       if (core->io_wrap)
+               iounmap(core->io_wrap);
        kfree(core);
 }
 
@@ -82,6 +87,7 @@ static int bcma_register_cores(struct bcma_bus *bus)
                case BCMA_CORE_CHIPCOMMON:
                case BCMA_CORE_PCI:
                case BCMA_CORE_PCIE:
+               case BCMA_CORE_MIPS_74K:
                        continue;
                }
 
@@ -95,7 +101,10 @@ static int bcma_register_cores(struct bcma_bus *bus)
                        core->dma_dev = &bus->host_pci->dev;
                        core->irq = bus->host_pci->irq;
                        break;
-               case BCMA_HOSTTYPE_NONE:
+               case BCMA_HOSTTYPE_SOC:
+                       core->dev.dma_mask = &core->dev.coherent_dma_mask;
+                       core->dma_dev = &core->dev;
+                       break;
                case BCMA_HOSTTYPE_SDIO:
                        break;
                }
@@ -115,9 +124,10 @@ static int bcma_register_cores(struct bcma_bus *bus)
 
 static void bcma_unregister_cores(struct bcma_bus *bus)
 {
-       struct bcma_device *core;
+       struct bcma_device *core, *tmp;
 
-       list_for_each_entry(core, &bus->cores, list) {
+       list_for_each_entry_safe(core, tmp, &bus->cores, list) {
+               list_del(&core->list);
                if (core->dev_registered)
                        device_unregister(&core->dev);
        }
@@ -142,6 +152,13 @@ int bcma_bus_register(struct bcma_bus *bus)
                bcma_core_chipcommon_init(&bus->drv_cc);
        }
 
+       /* Init MIPS core */
+       core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
+       if (core) {
+               bus->drv_mips.core = core;
+               bcma_core_mips_init(&bus->drv_mips);
+       }
+
        /* Init PCIE core */
        core = bcma_find_core(bus, BCMA_CORE_PCIE);
        if (core) {
@@ -171,6 +188,75 @@ void bcma_bus_unregister(struct bcma_bus *bus)
        bcma_unregister_cores(bus);
 }
 
+int __init bcma_bus_early_register(struct bcma_bus *bus,
+                                  struct bcma_device *core_cc,
+                                  struct bcma_device *core_mips)
+{
+       int err;
+       struct bcma_device *core;
+       struct bcma_device_id match;
+
+       bcma_init_bus(bus);
+
+       match.manuf = BCMA_MANUF_BCM;
+       match.id = BCMA_CORE_CHIPCOMMON;
+       match.class = BCMA_CL_SIM;
+       match.rev = BCMA_ANY_REV;
+
+       /* Scan for chip common core */
+       err = bcma_bus_scan_early(bus, &match, core_cc);
+       if (err) {
+               pr_err("Failed to scan for common core: %d\n", err);
+               return -1;
+       }
+
+       match.manuf = BCMA_MANUF_MIPS;
+       match.id = BCMA_CORE_MIPS_74K;
+       match.class = BCMA_CL_SIM;
+       match.rev = BCMA_ANY_REV;
+
+       /* Scan for mips core */
+       err = bcma_bus_scan_early(bus, &match, core_mips);
+       if (err) {
+               pr_err("Failed to scan for mips core: %d\n", err);
+               return -1;
+       }
+
+       /* Init CC core */
+       core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
+       if (core) {
+               bus->drv_cc.core = core;
+               bcma_core_chipcommon_init(&bus->drv_cc);
+       }
+
+       /* Init MIPS core */
+       core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
+       if (core) {
+               bus->drv_mips.core = core;
+               bcma_core_mips_init(&bus->drv_mips);
+       }
+
+       pr_info("Early bus registered\n");
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+int bcma_bus_resume(struct bcma_bus *bus)
+{
+       struct bcma_device *core;
+
+       /* Init CC core */
+       core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
+       if (core) {
+               bus->drv_cc.setup_done = false;
+               bcma_core_chipcommon_init(&bus->drv_cc);
+       }
+
+       return 0;
+}
+#endif
+
 int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
 {
        drv->drv.name = drv->name;
@@ -211,8 +297,11 @@ static int bcma_device_probe(struct device *dev)
                                               drv);
        int err = 0;
 
+       get_device(dev);
        if (adrv->probe)
                err = adrv->probe(core);
+       if (err)
+               put_device(dev);
 
        return err;
 }
@@ -225,6 +314,7 @@ static int bcma_device_remove(struct device *dev)
 
        if (adrv->remove)
                adrv->remove(core);
+       put_device(dev);
 
        return 0;
 }