summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2009-12-01 14:36:26 +0000
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2009-12-08 16:02:51 +1100
commit7fb19ea054a0cdf1a4d935e68d51bde4d3725414 (patch)
treeec4882255440c93c8104e59efaceffae98f379d3
parente15a113700324f7fdcee95589875daed2b98a2fe (diff)
downloadlinux-3.10-7fb19ea054a0cdf1a4d935e68d51bde4d3725414.tar.gz
linux-3.10-7fb19ea054a0cdf1a4d935e68d51bde4d3725414.tar.bz2
linux-3.10-7fb19ea054a0cdf1a4d935e68d51bde4d3725414.zip
powerpc/macio: Add devres support to macio_device
This adds some basic devres support. When enabled via macio_enable_devres() resources requested by drivers will be automatically released. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--arch/powerpc/include/asm/macio.h2
-rw-r--r--drivers/macintosh/macio_asic.c47
2 files changed, 49 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/macio.h b/arch/powerpc/include/asm/macio.h
index 079c06eae44..2b7b39294a6 100644
--- a/arch/powerpc/include/asm/macio.h
+++ b/arch/powerpc/include/asm/macio.h
@@ -78,6 +78,8 @@ static inline unsigned long macio_resource_len(struct macio_dev *dev, int resour
return res->end - res->start + 1;
}
+extern int macio_enable_devres(struct macio_dev *dev);
+
extern int macio_request_resource(struct macio_dev *dev, int resource_no, const char *name);
extern void macio_release_resource(struct macio_dev *dev, int resource_no);
extern int macio_request_resources(struct macio_dev *dev, const char *name);
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c
index 588a5b0bc4b..5200acfc9d3 100644
--- a/drivers/macintosh/macio_asic.c
+++ b/drivers/macintosh/macio_asic.c
@@ -538,6 +538,42 @@ void macio_unregister_driver(struct macio_driver *drv)
driver_unregister(&drv->driver);
}
+/* Managed MacIO resources */
+struct macio_devres {
+ u32 res_mask;
+};
+
+static void maciom_release(struct device *gendev, void *res)
+{
+ struct macio_dev *dev = to_macio_device(gendev);
+ struct macio_devres *dr = res;
+ int i, max;
+
+ max = min(dev->n_resources, 32);
+ for (i = 0; i < max; i++) {
+ if (dr->res_mask & (1 << i))
+ macio_release_resource(dev, i);
+ }
+}
+
+int macio_enable_devres(struct macio_dev *dev)
+{
+ struct macio_devres *dr;
+
+ dr = devres_find(&dev->ofdev.dev, maciom_release, NULL, NULL);
+ if (!dr) {
+ dr = devres_alloc(maciom_release, sizeof(*dr), GFP_KERNEL);
+ if (!dr)
+ return -ENOMEM;
+ }
+ return devres_get(&dev->ofdev.dev, dr, NULL, NULL) != NULL;
+}
+
+static struct macio_devres * find_macio_dr(struct macio_dev *dev)
+{
+ return devres_find(&dev->ofdev.dev, maciom_release, NULL, NULL);
+}
+
/**
* macio_request_resource - Request an MMIO resource
* @dev: pointer to the device holding the resource
@@ -555,6 +591,8 @@ void macio_unregister_driver(struct macio_driver *drv)
int macio_request_resource(struct macio_dev *dev, int resource_no,
const char *name)
{
+ struct macio_devres *dr = find_macio_dr(dev);
+
if (macio_resource_len(dev, resource_no) == 0)
return 0;
@@ -562,6 +600,9 @@ int macio_request_resource(struct macio_dev *dev, int resource_no,
macio_resource_len(dev, resource_no),
name))
goto err_out;
+
+ if (dr && resource_no < 32)
+ dr->res_mask |= 1 << resource_no;
return 0;
@@ -582,10 +623,14 @@ err_out:
*/
void macio_release_resource(struct macio_dev *dev, int resource_no)
{
+ struct macio_devres *dr = find_macio_dr(dev);
+
if (macio_resource_len(dev, resource_no) == 0)
return;
release_mem_region(macio_resource_start(dev, resource_no),
macio_resource_len(dev, resource_no));
+ if (dr && resource_no < 32)
+ dr->res_mask &= ~(1 << resource_no);
}
/**
@@ -744,3 +789,5 @@ EXPORT_SYMBOL(macio_request_resource);
EXPORT_SYMBOL(macio_release_resource);
EXPORT_SYMBOL(macio_request_resources);
EXPORT_SYMBOL(macio_release_resources);
+EXPORT_SYMBOL(macio_enable_devres);
+