diff options
author | Mike Isely <isely@pobox.com> | 2006-07-22 20:26:30 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-07-29 16:22:37 -0400 |
commit | 08d41808362a3663c0856c9720ad940a61156fb5 (patch) | |
tree | ec0da5edd1cb3351b0dd253baad83aac7f9958a3 | |
parent | d94fc9a08e51432d0d5fc0f74a4f705d7b49c251 (diff) |
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>
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-sysfs.c | 62 |
1 files changed, 50 insertions, 12 deletions
diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index ef46d4f40cff..d1dda5caf406 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c | |||
@@ -44,12 +44,16 @@ struct pvr2_sysfs { | |||
44 | struct kobj_type ktype; | 44 | struct kobj_type ktype; |
45 | struct class_device_attribute attr_v4l_minor_number; | 45 | struct class_device_attribute attr_v4l_minor_number; |
46 | struct class_device_attribute attr_unit_number; | 46 | struct class_device_attribute attr_unit_number; |
47 | int v4l_minor_number_created_ok; | ||
48 | int unit_number_created_ok; | ||
47 | }; | 49 | }; |
48 | 50 | ||
49 | #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC | 51 | #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC |
50 | struct pvr2_sysfs_debugifc { | 52 | struct pvr2_sysfs_debugifc { |
51 | struct class_device_attribute attr_debugcmd; | 53 | struct class_device_attribute attr_debugcmd; |
52 | struct class_device_attribute attr_debuginfo; | 54 | struct class_device_attribute attr_debuginfo; |
55 | int debugcmd_created_ok; | ||
56 | int debuginfo_created_ok; | ||
53 | }; | 57 | }; |
54 | #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ | 58 | #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ |
55 | 59 | ||
@@ -67,6 +71,7 @@ struct pvr2_sysfs_ctl_item { | |||
67 | struct pvr2_sysfs_ctl_item *item_next; | 71 | struct pvr2_sysfs_ctl_item *item_next; |
68 | struct attribute *attr_gen[7]; | 72 | struct attribute *attr_gen[7]; |
69 | struct attribute_group grp; | 73 | struct attribute_group grp; |
74 | int created_ok; | ||
70 | char name[80]; | 75 | char name[80]; |
71 | }; | 76 | }; |
72 | 77 | ||
@@ -487,6 +492,7 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) | |||
487 | struct pvr2_sysfs_func_set *fp; | 492 | struct pvr2_sysfs_func_set *fp; |
488 | struct pvr2_ctrl *cptr; | 493 | struct pvr2_ctrl *cptr; |
489 | unsigned int cnt,acnt; | 494 | unsigned int cnt,acnt; |
495 | int ret; | ||
490 | 496 | ||
491 | if ((ctl_id < 0) || (ctl_id >= (sizeof(funcs)/sizeof(funcs[0])))) { | 497 | if ((ctl_id < 0) || (ctl_id >= (sizeof(funcs)/sizeof(funcs[0])))) { |
492 | return; | 498 | return; |
@@ -589,7 +595,13 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) | |||
589 | cip->grp.name = cip->name; | 595 | cip->grp.name = cip->name; |
590 | cip->grp.attrs = cip->attr_gen; | 596 | cip->grp.attrs = cip->attr_gen; |
591 | 597 | ||
592 | sysfs_create_group(&sfp->class_dev->kobj,&cip->grp); | 598 | ret = sysfs_create_group(&sfp->class_dev->kobj,&cip->grp); |
599 | if (ret) { | ||
600 | printk(KERN_WARNING "%s: sysfs_create_group error: %d\n", | ||
601 | __FUNCTION__, ret); | ||
602 | return; | ||
603 | } | ||
604 | cip->created_ok = !0; | ||
593 | } | 605 | } |
594 | 606 | ||
595 | #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC | 607 | #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC |
@@ -616,22 +628,33 @@ static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp) | |||
616 | dip->attr_debuginfo.show = debuginfo_show; | 628 | dip->attr_debuginfo.show = debuginfo_show; |
617 | sfp->debugifc = dip; | 629 | sfp->debugifc = dip; |
618 | ret = class_device_create_file(sfp->class_dev,&dip->attr_debugcmd); | 630 | ret = class_device_create_file(sfp->class_dev,&dip->attr_debugcmd); |
619 | if (ret < 0) | 631 | if (ret < 0) { |
620 | printk(KERN_WARNING "%s: class_device_create_file error: %d\n", | 632 | printk(KERN_WARNING "%s: class_device_create_file error: %d\n", |
621 | __FUNCTION__, ret); | 633 | __FUNCTION__, ret); |
634 | } else { | ||
635 | dip->debugcmd_created_ok = !0; | ||
636 | } | ||
622 | ret = class_device_create_file(sfp->class_dev,&dip->attr_debuginfo); | 637 | ret = class_device_create_file(sfp->class_dev,&dip->attr_debuginfo); |
623 | if (ret < 0) | 638 | if (ret < 0) { |
624 | printk(KERN_WARNING "%s: class_device_create_file error: %d\n", | 639 | printk(KERN_WARNING "%s: class_device_create_file error: %d\n", |
625 | __FUNCTION__, ret); | 640 | __FUNCTION__, ret); |
641 | } else { | ||
642 | dip->debuginfo_created_ok = !0; | ||
643 | } | ||
626 | } | 644 | } |
627 | 645 | ||
628 | 646 | ||
629 | static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp) | 647 | static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp) |
630 | { | 648 | { |
631 | if (!sfp->debugifc) return; | 649 | if (!sfp->debugifc) return; |
632 | class_device_remove_file(sfp->class_dev, | 650 | if (sfp->debugifc->debuginfo_created_ok) { |
633 | &sfp->debugifc->attr_debuginfo); | 651 | class_device_remove_file(sfp->class_dev, |
634 | class_device_remove_file(sfp->class_dev,&sfp->debugifc->attr_debugcmd); | 652 | &sfp->debugifc->attr_debuginfo); |
653 | } | ||
654 | if (sfp->debugifc->debugcmd_created_ok) { | ||
655 | class_device_remove_file(sfp->class_dev, | ||
656 | &sfp->debugifc->attr_debugcmd); | ||
657 | } | ||
635 | kfree(sfp->debugifc); | 658 | kfree(sfp->debugifc); |
636 | sfp->debugifc = NULL; | 659 | sfp->debugifc = NULL; |
637 | } | 660 | } |
@@ -653,7 +676,9 @@ static void pvr2_sysfs_tear_down_controls(struct pvr2_sysfs *sfp) | |||
653 | struct pvr2_sysfs_ctl_item *cip1,*cip2; | 676 | struct pvr2_sysfs_ctl_item *cip1,*cip2; |
654 | for (cip1 = sfp->item_first; cip1; cip1 = cip2) { | 677 | for (cip1 = sfp->item_first; cip1; cip1 = cip2) { |
655 | cip2 = cip1->item_next; | 678 | cip2 = cip1->item_next; |
656 | sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp); | 679 | if (cip1->created_ok) { |
680 | sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp); | ||
681 | } | ||
657 | pvr2_sysfs_trace("Destroying pvr2_sysfs_ctl_item id=%p",cip1); | 682 | pvr2_sysfs_trace("Destroying pvr2_sysfs_ctl_item id=%p",cip1); |
658 | kfree(cip1); | 683 | kfree(cip1); |
659 | } | 684 | } |
@@ -683,8 +708,14 @@ static void class_dev_destroy(struct pvr2_sysfs *sfp) | |||
683 | pvr2_sysfs_tear_down_debugifc(sfp); | 708 | pvr2_sysfs_tear_down_debugifc(sfp); |
684 | #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ | 709 | #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ |
685 | pvr2_sysfs_tear_down_controls(sfp); | 710 | pvr2_sysfs_tear_down_controls(sfp); |
686 | class_device_remove_file(sfp->class_dev,&sfp->attr_v4l_minor_number); | 711 | if (sfp->v4l_minor_number_created_ok) { |
687 | class_device_remove_file(sfp->class_dev,&sfp->attr_unit_number); | 712 | class_device_remove_file(sfp->class_dev, |
713 | &sfp->attr_v4l_minor_number); | ||
714 | } | ||
715 | if (sfp->unit_number_created_ok) { | ||
716 | class_device_remove_file(sfp->class_dev, | ||
717 | &sfp->attr_unit_number); | ||
718 | } | ||
688 | pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev); | 719 | pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev); |
689 | sfp->class_dev->class_data = NULL; | 720 | sfp->class_dev->class_data = NULL; |
690 | class_device_unregister(sfp->class_dev); | 721 | class_device_unregister(sfp->class_dev); |
@@ -756,10 +787,14 @@ static void class_dev_create(struct pvr2_sysfs *sfp, | |||
756 | sfp->attr_v4l_minor_number.attr.mode = S_IRUGO; | 787 | sfp->attr_v4l_minor_number.attr.mode = S_IRUGO; |
757 | sfp->attr_v4l_minor_number.show = v4l_minor_number_show; | 788 | sfp->attr_v4l_minor_number.show = v4l_minor_number_show; |
758 | sfp->attr_v4l_minor_number.store = NULL; | 789 | sfp->attr_v4l_minor_number.store = NULL; |
759 | ret = class_device_create_file(sfp->class_dev,&sfp->attr_v4l_minor_number); | 790 | ret = class_device_create_file(sfp->class_dev, |
760 | if (ret < 0) | 791 | &sfp->attr_v4l_minor_number); |
792 | if (ret < 0) { | ||
761 | printk(KERN_WARNING "%s: class_device_create_file error: %d\n", | 793 | printk(KERN_WARNING "%s: class_device_create_file error: %d\n", |
762 | __FUNCTION__, ret); | 794 | __FUNCTION__, ret); |
795 | } else { | ||
796 | sfp->v4l_minor_number_created_ok = !0; | ||
797 | } | ||
763 | 798 | ||
764 | sfp->attr_unit_number.attr.owner = THIS_MODULE; | 799 | sfp->attr_unit_number.attr.owner = THIS_MODULE; |
765 | sfp->attr_unit_number.attr.name = "unit_number"; | 800 | sfp->attr_unit_number.attr.name = "unit_number"; |
@@ -767,9 +802,12 @@ static void class_dev_create(struct pvr2_sysfs *sfp, | |||
767 | sfp->attr_unit_number.show = unit_number_show; | 802 | sfp->attr_unit_number.show = unit_number_show; |
768 | sfp->attr_unit_number.store = NULL; | 803 | sfp->attr_unit_number.store = NULL; |
769 | ret = class_device_create_file(sfp->class_dev,&sfp->attr_unit_number); | 804 | ret = class_device_create_file(sfp->class_dev,&sfp->attr_unit_number); |
770 | if (ret < 0) | 805 | if (ret < 0) { |
771 | printk(KERN_WARNING "%s: class_device_create_file error: %d\n", | 806 | printk(KERN_WARNING "%s: class_device_create_file error: %d\n", |
772 | __FUNCTION__, ret); | 807 | __FUNCTION__, ret); |
808 | } else { | ||
809 | sfp->unit_number_created_ok = !0; | ||
810 | } | ||
773 | 811 | ||
774 | pvr2_sysfs_add_controls(sfp); | 812 | pvr2_sysfs_add_controls(sfp); |
775 | #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC | 813 | #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC |