summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTzafrir Cohen <tzafrir.cohen@xorcom.com>2012-01-05 17:35:17 +0000
committerTzafrir Cohen <tzafrir.cohen@xorcom.com>2012-01-05 17:35:17 +0000
commitd790e7ec15490f61afed3b26ca8d8d2d80ca1d01 (patch)
treeadbdb9969b84ecc894430e43eaeea7b76203603d
parent4620300643e819b1bfff9d10a42e985e5e38ece5 (diff)
xpp: handle failures during dahdi_register_device()
* If dahdi_register_device() failed, not all resources were freed. When dahdi_unregister_device() was called later (during driver removal) a panic was caused. * Add proper error handling for possible failures in xbus_register_dahdi_device(): - new xbus_free_ddev() safely free an xbus->ddev - This is called from all failures points. - It is also called from xbus_unregister_dahdi_device() Signed-off-by: Oron Peled <oron.peled@xorcom.com> Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com> git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10410 a0bf4364-ded3-4de4-8d8a-66a801d63aff
-rw-r--r--drivers/dahdi/xpp/xbus-core.c44
1 files changed, 32 insertions, 12 deletions
diff --git a/drivers/dahdi/xpp/xbus-core.c b/drivers/dahdi/xpp/xbus-core.c
index 0226b4c..fc9217f 100644
--- a/drivers/dahdi/xpp/xbus-core.c
+++ b/drivers/dahdi/xpp/xbus-core.c
@@ -900,18 +900,37 @@ int xbus_is_registered(xbus_t *xbus)
return xbus->ddev && xbus->ddev->dev.parent;
}
+static void xbus_free_ddev(xbus_t *xbus)
+{
+ if (!xbus->ddev)
+ return;
+ if (xbus->ddev->devicetype)
+ kfree(xbus->ddev->devicetype);
+ xbus->ddev->devicetype = NULL;
+ xbus->ddev->location = NULL;
+ xbus->ddev->hardware_id = NULL;
+ dahdi_free_device(xbus->ddev);
+ xbus->ddev = NULL;
+}
+
int xbus_register_dahdi_device(xbus_t *xbus)
{
- int i;
- int offset = 0;
+ int i;
+ int offset = 0;
+ int ret;
XBUS_DBG(DEVICES, xbus, "Entering %s\n", __func__);
if (xbus_is_registered(xbus)) {
XBUS_ERR(xbus, "Already registered to DAHDI\n");
WARN_ON(1);
- return -EINVAL;
+ ret = -EINVAL;
+ goto err;
}
xbus->ddev = dahdi_create_device();
+ if (!xbus->ddev) {
+ ret = -ENOMEM;
+ goto err;
+ }
/*
* This actually describe the dahdi_spaninfo version 3
* A bunch of unrelated data exported via a modified ioctl()
@@ -926,8 +945,10 @@ int xbus_register_dahdi_device(xbus_t *xbus)
* OK, let's add to the kernel more useless info.
*/
xbus->ddev->devicetype = kasprintf(GFP_KERNEL, "Astribank2");
- if (!xbus->ddev->devicetype)
- return -ENOMEM;
+ if (!xbus->ddev->devicetype) {
+ ret = -ENOMEM;
+ goto err;
+ }
/*
* location is the only usefull new data item.
@@ -952,7 +973,8 @@ int xbus_register_dahdi_device(xbus_t *xbus)
}
if (dahdi_register_device(xbus->ddev, &xbus->astribank)) {
XBUS_ERR(xbus, "Failed to dahdi_register_device()\n");
- return -ENODEV;
+ ret = -ENODEV;
+ goto err;
}
for (i = 0; i < MAX_XPDS; i++) {
xpd_t *xpd = xpd_of(xbus, i);
@@ -962,6 +984,9 @@ int xbus_register_dahdi_device(xbus_t *xbus)
}
}
return 0;
+err:
+ xbus_free_ddev(xbus);
+ return ret;
}
void xbus_unregister_dahdi_device(xbus_t *xbus)
@@ -976,12 +1001,7 @@ void xbus_unregister_dahdi_device(xbus_t *xbus)
if (xbus->ddev) {
dahdi_unregister_device(xbus->ddev);
XBUS_NOTICE(xbus, "%s: finished dahdi_unregister_device()\n", __func__);
- kfree(xbus->ddev->devicetype);
- xbus->ddev->devicetype = NULL;
- xbus->ddev->location = NULL;
- xbus->ddev->hardware_id = NULL;
- dahdi_free_device(xbus->ddev);
- xbus->ddev = NULL;
+ xbus_free_ddev(xbus);
}
for(i = 0; i < MAX_XPDS; i++) {
xpd_t *xpd = xpd_of(xbus, i);