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
This commit is contained in:
Oron Peled 2012-01-10 22:09:34 +00:00 committed by Shaun Ruffell
parent 17a2ce9421
commit f06c8d50cf

View File

@ -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);