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:
parent
17a2ce9421
commit
f06c8d50cf
@ -900,18 +900,37 @@ int xbus_is_registered(xbus_t *xbus)
|
|||||||
return xbus->ddev && xbus->ddev->dev.parent;
|
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 xbus_register_dahdi_device(xbus_t *xbus)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
XBUS_DBG(DEVICES, xbus, "Entering %s\n", __func__);
|
XBUS_DBG(DEVICES, xbus, "Entering %s\n", __func__);
|
||||||
if (xbus_is_registered(xbus)) {
|
if (xbus_is_registered(xbus)) {
|
||||||
XBUS_ERR(xbus, "Already registered to DAHDI\n");
|
XBUS_ERR(xbus, "Already registered to DAHDI\n");
|
||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
return -EINVAL;
|
ret = -EINVAL;
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
xbus->ddev = dahdi_create_device();
|
xbus->ddev = dahdi_create_device();
|
||||||
|
if (!xbus->ddev) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* This actually describe the dahdi_spaninfo version 3
|
* This actually describe the dahdi_spaninfo version 3
|
||||||
* A bunch of unrelated data exported via a modified ioctl()
|
* 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.
|
* OK, let's add to the kernel more useless info.
|
||||||
*/
|
*/
|
||||||
xbus->ddev->devicetype = kasprintf(GFP_KERNEL, "Astribank2");
|
xbus->ddev->devicetype = kasprintf(GFP_KERNEL, "Astribank2");
|
||||||
if (!xbus->ddev->devicetype)
|
if (!xbus->ddev->devicetype) {
|
||||||
return -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* location is the only usefull new data item.
|
* 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)) {
|
if (dahdi_register_device(xbus->ddev, &xbus->astribank)) {
|
||||||
XBUS_ERR(xbus, "Failed to dahdi_register_device()\n");
|
XBUS_ERR(xbus, "Failed to dahdi_register_device()\n");
|
||||||
return -ENODEV;
|
ret = -ENODEV;
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
for (i = 0; i < MAX_XPDS; i++) {
|
for (i = 0; i < MAX_XPDS; i++) {
|
||||||
xpd_t *xpd = xpd_of(xbus, i);
|
xpd_t *xpd = xpd_of(xbus, i);
|
||||||
@ -962,6 +984,9 @@ int xbus_register_dahdi_device(xbus_t *xbus)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
err:
|
||||||
|
xbus_free_ddev(xbus);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void xbus_unregister_dahdi_device(xbus_t *xbus)
|
void xbus_unregister_dahdi_device(xbus_t *xbus)
|
||||||
@ -976,12 +1001,7 @@ void xbus_unregister_dahdi_device(xbus_t *xbus)
|
|||||||
if (xbus->ddev) {
|
if (xbus->ddev) {
|
||||||
dahdi_unregister_device(xbus->ddev);
|
dahdi_unregister_device(xbus->ddev);
|
||||||
XBUS_NOTICE(xbus, "%s: finished dahdi_unregister_device()\n", __func__);
|
XBUS_NOTICE(xbus, "%s: finished dahdi_unregister_device()\n", __func__);
|
||||||
kfree(xbus->ddev->devicetype);
|
xbus_free_ddev(xbus);
|
||||||
xbus->ddev->devicetype = NULL;
|
|
||||||
xbus->ddev->location = NULL;
|
|
||||||
xbus->ddev->hardware_id = NULL;
|
|
||||||
dahdi_free_device(xbus->ddev);
|
|
||||||
xbus->ddev = NULL;
|
|
||||||
}
|
}
|
||||||
for(i = 0; i < MAX_XPDS; i++) {
|
for(i = 0; i < MAX_XPDS; i++) {
|
||||||
xpd_t *xpd = xpd_of(xbus, i);
|
xpd_t *xpd = xpd_of(xbus, i);
|
||||||
|
Loading…
Reference in New Issue
Block a user