V4L/DVB (4373): Correctly handle sysfs error leg file removal in pvrusb2

Take note of which sysfs files / groups that the pvrusb2 successfully
creates and only delete those specific items when tearing things
down.  (Previously we just blindly tore everything down every time.)

Signed-off-by: Mike Isely <isely@pobox.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
Mike Isely 2006-07-22 21:26:30 -03:00 committed by Mauro Carvalho Chehab
parent d94fc9a08e
commit 08d4180836
1 changed files with 50 additions and 12 deletions

View File

@ -44,12 +44,16 @@ struct pvr2_sysfs {
struct kobj_type ktype; struct kobj_type ktype;
struct class_device_attribute attr_v4l_minor_number; struct class_device_attribute attr_v4l_minor_number;
struct class_device_attribute attr_unit_number; struct class_device_attribute attr_unit_number;
int v4l_minor_number_created_ok;
int unit_number_created_ok;
}; };
#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
struct pvr2_sysfs_debugifc { struct pvr2_sysfs_debugifc {
struct class_device_attribute attr_debugcmd; struct class_device_attribute attr_debugcmd;
struct class_device_attribute attr_debuginfo; struct class_device_attribute attr_debuginfo;
int debugcmd_created_ok;
int debuginfo_created_ok;
}; };
#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
@ -67,6 +71,7 @@ struct pvr2_sysfs_ctl_item {
struct pvr2_sysfs_ctl_item *item_next; struct pvr2_sysfs_ctl_item *item_next;
struct attribute *attr_gen[7]; struct attribute *attr_gen[7];
struct attribute_group grp; struct attribute_group grp;
int created_ok;
char name[80]; char name[80];
}; };
@ -487,6 +492,7 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
struct pvr2_sysfs_func_set *fp; struct pvr2_sysfs_func_set *fp;
struct pvr2_ctrl *cptr; struct pvr2_ctrl *cptr;
unsigned int cnt,acnt; unsigned int cnt,acnt;
int ret;
if ((ctl_id < 0) || (ctl_id >= (sizeof(funcs)/sizeof(funcs[0])))) { if ((ctl_id < 0) || (ctl_id >= (sizeof(funcs)/sizeof(funcs[0])))) {
return; return;
@ -589,7 +595,13 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
cip->grp.name = cip->name; cip->grp.name = cip->name;
cip->grp.attrs = cip->attr_gen; cip->grp.attrs = cip->attr_gen;
sysfs_create_group(&sfp->class_dev->kobj,&cip->grp); ret = sysfs_create_group(&sfp->class_dev->kobj,&cip->grp);
if (ret) {
printk(KERN_WARNING "%s: sysfs_create_group error: %d\n",
__FUNCTION__, ret);
return;
}
cip->created_ok = !0;
} }
#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
@ -616,22 +628,33 @@ static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp)
dip->attr_debuginfo.show = debuginfo_show; dip->attr_debuginfo.show = debuginfo_show;
sfp->debugifc = dip; sfp->debugifc = dip;
ret = class_device_create_file(sfp->class_dev,&dip->attr_debugcmd); ret = class_device_create_file(sfp->class_dev,&dip->attr_debugcmd);
if (ret < 0) if (ret < 0) {
printk(KERN_WARNING "%s: class_device_create_file error: %d\n", printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
__FUNCTION__, ret); __FUNCTION__, ret);
} else {
dip->debugcmd_created_ok = !0;
}
ret = class_device_create_file(sfp->class_dev,&dip->attr_debuginfo); ret = class_device_create_file(sfp->class_dev,&dip->attr_debuginfo);
if (ret < 0) if (ret < 0) {
printk(KERN_WARNING "%s: class_device_create_file error: %d\n", printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
__FUNCTION__, ret); __FUNCTION__, ret);
} else {
dip->debuginfo_created_ok = !0;
}
} }
static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp) static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp)
{ {
if (!sfp->debugifc) return; if (!sfp->debugifc) return;
class_device_remove_file(sfp->class_dev, if (sfp->debugifc->debuginfo_created_ok) {
&sfp->debugifc->attr_debuginfo); class_device_remove_file(sfp->class_dev,
class_device_remove_file(sfp->class_dev,&sfp->debugifc->attr_debugcmd); &sfp->debugifc->attr_debuginfo);
}
if (sfp->debugifc->debugcmd_created_ok) {
class_device_remove_file(sfp->class_dev,
&sfp->debugifc->attr_debugcmd);
}
kfree(sfp->debugifc); kfree(sfp->debugifc);
sfp->debugifc = NULL; sfp->debugifc = NULL;
} }
@ -653,7 +676,9 @@ static void pvr2_sysfs_tear_down_controls(struct pvr2_sysfs *sfp)
struct pvr2_sysfs_ctl_item *cip1,*cip2; struct pvr2_sysfs_ctl_item *cip1,*cip2;
for (cip1 = sfp->item_first; cip1; cip1 = cip2) { for (cip1 = sfp->item_first; cip1; cip1 = cip2) {
cip2 = cip1->item_next; cip2 = cip1->item_next;
sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp); if (cip1->created_ok) {
sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp);
}
pvr2_sysfs_trace("Destroying pvr2_sysfs_ctl_item id=%p",cip1); pvr2_sysfs_trace("Destroying pvr2_sysfs_ctl_item id=%p",cip1);
kfree(cip1); kfree(cip1);
} }
@ -683,8 +708,14 @@ static void class_dev_destroy(struct pvr2_sysfs *sfp)
pvr2_sysfs_tear_down_debugifc(sfp); pvr2_sysfs_tear_down_debugifc(sfp);
#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
pvr2_sysfs_tear_down_controls(sfp); pvr2_sysfs_tear_down_controls(sfp);
class_device_remove_file(sfp->class_dev,&sfp->attr_v4l_minor_number); if (sfp->v4l_minor_number_created_ok) {
class_device_remove_file(sfp->class_dev,&sfp->attr_unit_number); class_device_remove_file(sfp->class_dev,
&sfp->attr_v4l_minor_number);
}
if (sfp->unit_number_created_ok) {
class_device_remove_file(sfp->class_dev,
&sfp->attr_unit_number);
}
pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev); pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev);
sfp->class_dev->class_data = NULL; sfp->class_dev->class_data = NULL;
class_device_unregister(sfp->class_dev); class_device_unregister(sfp->class_dev);
@ -756,10 +787,14 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
sfp->attr_v4l_minor_number.attr.mode = S_IRUGO; sfp->attr_v4l_minor_number.attr.mode = S_IRUGO;
sfp->attr_v4l_minor_number.show = v4l_minor_number_show; sfp->attr_v4l_minor_number.show = v4l_minor_number_show;
sfp->attr_v4l_minor_number.store = NULL; sfp->attr_v4l_minor_number.store = NULL;
ret = class_device_create_file(sfp->class_dev,&sfp->attr_v4l_minor_number); ret = class_device_create_file(sfp->class_dev,
if (ret < 0) &sfp->attr_v4l_minor_number);
if (ret < 0) {
printk(KERN_WARNING "%s: class_device_create_file error: %d\n", printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
__FUNCTION__, ret); __FUNCTION__, ret);
} else {
sfp->v4l_minor_number_created_ok = !0;
}
sfp->attr_unit_number.attr.owner = THIS_MODULE; sfp->attr_unit_number.attr.owner = THIS_MODULE;
sfp->attr_unit_number.attr.name = "unit_number"; sfp->attr_unit_number.attr.name = "unit_number";
@ -767,9 +802,12 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
sfp->attr_unit_number.show = unit_number_show; sfp->attr_unit_number.show = unit_number_show;
sfp->attr_unit_number.store = NULL; sfp->attr_unit_number.store = NULL;
ret = class_device_create_file(sfp->class_dev,&sfp->attr_unit_number); ret = class_device_create_file(sfp->class_dev,&sfp->attr_unit_number);
if (ret < 0) if (ret < 0) {
printk(KERN_WARNING "%s: class_device_create_file error: %d\n", printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
__FUNCTION__, ret); __FUNCTION__, ret);
} else {
sfp->unit_number_created_ok = !0;
}
pvr2_sysfs_add_controls(sfp); pvr2_sysfs_add_controls(sfp);
#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC