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 |
