summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2012-01-10 22:09:34 +0000
committerShaun Ruffell <sruffell@digium.com>2012-01-10 22:09:34 +0000
commitb9908040c01908ed27ca21c25e2b46137a294b6e (patch)
treea5f365dcc886e2c62e2eb165d930280a335f91b7
parent90bc4a1a828fb8feeeb3d35e7371ca4f8089f77d (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> Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10410 git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.6@10419 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);