diff options
author | Ezequiel GarcĂa <elezegarcia@gmail.com> | 2012-02-24 09:24:22 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-05-15 08:00:48 -0400 |
commit | 92a0144225fa14e044bdbdaa23e1049ca2047a5c (patch) | |
tree | 26f275ef14ab4fce2d1e5551903646a6dd95283d /drivers/staging | |
parent | df8c4b72322ade883766a9b9311d42ae8a83cf66 (diff) |
[media] staging: easycap: Split easycap_delete() into several pieces
The patch splits easycap_delete(), which is in charge of
buffer deallocation, into smaller functions each
deallocating a specific kind of buffer.
Signed-off-by: Ezequiel Garcia <elezegarcia@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/staging')
-rw-r--r-- | drivers/staging/media/easycap/easycap_main.c | 445 |
1 files changed, 249 insertions, 196 deletions
diff --git a/drivers/staging/media/easycap/easycap_main.c b/drivers/staging/media/easycap/easycap_main.c index 76a2c5b33a91..aed953751a90 100644 --- a/drivers/staging/media/easycap/easycap_main.c +++ b/drivers/staging/media/easycap/easycap_main.c | |||
@@ -701,202 +701,6 @@ static int videodev_release(struct video_device *pvideo_device) | |||
701 | return 0; | 701 | return 0; |
702 | } | 702 | } |
703 | 703 | ||
704 | /* | ||
705 | * This function is called from within easycap_usb_disconnect() and is | ||
706 | * protected by semaphores set and cleared by easycap_usb_disconnect(). | ||
707 | * By this stage the device has already been physically unplugged, | ||
708 | * so peasycap->pusb_device is no longer valid. | ||
709 | */ | ||
710 | static void easycap_delete(struct kref *pkref) | ||
711 | { | ||
712 | struct easycap *peasycap; | ||
713 | struct data_urb *pdata_urb; | ||
714 | struct list_head *plist_head, *plist_next; | ||
715 | int k, m, gone, kd; | ||
716 | int allocation_video_urb; | ||
717 | int allocation_video_page; | ||
718 | int allocation_video_struct; | ||
719 | int allocation_audio_urb; | ||
720 | int allocation_audio_page; | ||
721 | int allocation_audio_struct; | ||
722 | int registered_video, registered_audio; | ||
723 | |||
724 | peasycap = container_of(pkref, struct easycap, kref); | ||
725 | if (!peasycap) { | ||
726 | SAM("ERROR: peasycap is NULL: cannot perform deletions\n"); | ||
727 | return; | ||
728 | } | ||
729 | kd = easycap_isdongle(peasycap); | ||
730 | |||
731 | /* Free video urbs */ | ||
732 | if (peasycap->purb_video_head) { | ||
733 | m = 0; | ||
734 | list_for_each(plist_head, peasycap->purb_video_head) { | ||
735 | pdata_urb = list_entry(plist_head, | ||
736 | struct data_urb, list_head); | ||
737 | if (pdata_urb && pdata_urb->purb) { | ||
738 | usb_free_urb(pdata_urb->purb); | ||
739 | pdata_urb->purb = NULL; | ||
740 | peasycap->allocation_video_urb--; | ||
741 | m++; | ||
742 | } | ||
743 | } | ||
744 | |||
745 | JOM(4, "%i video urbs freed\n", m); | ||
746 | JOM(4, "freeing video data_urb structures.\n"); | ||
747 | m = 0; | ||
748 | list_for_each_safe(plist_head, plist_next, | ||
749 | peasycap->purb_video_head) { | ||
750 | pdata_urb = list_entry(plist_head, | ||
751 | struct data_urb, list_head); | ||
752 | if (pdata_urb) { | ||
753 | peasycap->allocation_video_struct -= | ||
754 | sizeof(struct data_urb); | ||
755 | kfree(pdata_urb); | ||
756 | m++; | ||
757 | } | ||
758 | } | ||
759 | JOM(4, "%i video data_urb structures freed\n", m); | ||
760 | JOM(4, "setting peasycap->purb_video_head=NULL\n"); | ||
761 | peasycap->purb_video_head = NULL; | ||
762 | } | ||
763 | |||
764 | /* Free video isoc buffers */ | ||
765 | JOM(4, "freeing video isoc buffers.\n"); | ||
766 | m = 0; | ||
767 | for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) { | ||
768 | if (peasycap->video_isoc_buffer[k].pgo) { | ||
769 | free_pages((unsigned long) | ||
770 | peasycap->video_isoc_buffer[k].pgo, | ||
771 | VIDEO_ISOC_ORDER); | ||
772 | peasycap->video_isoc_buffer[k].pgo = NULL; | ||
773 | peasycap->allocation_video_page -= | ||
774 | BIT(VIDEO_ISOC_ORDER); | ||
775 | m++; | ||
776 | } | ||
777 | } | ||
778 | JOM(4, "isoc video buffers freed: %i pages\n", | ||
779 | m * (0x01 << VIDEO_ISOC_ORDER)); | ||
780 | /* Free video field buffers */ | ||
781 | JOM(4, "freeing video field buffers.\n"); | ||
782 | gone = 0; | ||
783 | for (k = 0; k < FIELD_BUFFER_MANY; k++) { | ||
784 | for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++) { | ||
785 | if (peasycap->field_buffer[k][m].pgo) { | ||
786 | free_page((unsigned long) | ||
787 | peasycap->field_buffer[k][m].pgo); | ||
788 | peasycap->field_buffer[k][m].pgo = NULL; | ||
789 | peasycap->allocation_video_page -= 1; | ||
790 | gone++; | ||
791 | } | ||
792 | } | ||
793 | } | ||
794 | JOM(4, "video field buffers freed: %i pages\n", gone); | ||
795 | |||
796 | /* Free video frame buffers */ | ||
797 | JOM(4, "freeing video frame buffers.\n"); | ||
798 | gone = 0; | ||
799 | for (k = 0; k < FRAME_BUFFER_MANY; k++) { | ||
800 | for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++) { | ||
801 | if (peasycap->frame_buffer[k][m].pgo) { | ||
802 | free_page((unsigned long) | ||
803 | peasycap->frame_buffer[k][m].pgo); | ||
804 | peasycap->frame_buffer[k][m].pgo = NULL; | ||
805 | peasycap->allocation_video_page -= 1; | ||
806 | gone++; | ||
807 | } | ||
808 | } | ||
809 | } | ||
810 | JOM(4, "video frame buffers freed: %i pages\n", gone); | ||
811 | |||
812 | /* Free audio urbs */ | ||
813 | if (peasycap->purb_audio_head) { | ||
814 | JOM(4, "freeing audio urbs\n"); | ||
815 | m = 0; | ||
816 | list_for_each(plist_head, (peasycap->purb_audio_head)) { | ||
817 | pdata_urb = list_entry(plist_head, | ||
818 | struct data_urb, list_head); | ||
819 | if (pdata_urb && pdata_urb->purb) { | ||
820 | usb_free_urb(pdata_urb->purb); | ||
821 | pdata_urb->purb = NULL; | ||
822 | peasycap->allocation_audio_urb--; | ||
823 | m++; | ||
824 | } | ||
825 | } | ||
826 | JOM(4, "%i audio urbs freed\n", m); | ||
827 | JOM(4, "freeing audio data_urb structures.\n"); | ||
828 | m = 0; | ||
829 | list_for_each_safe(plist_head, plist_next, | ||
830 | peasycap->purb_audio_head) { | ||
831 | pdata_urb = list_entry(plist_head, | ||
832 | struct data_urb, list_head); | ||
833 | if (pdata_urb) { | ||
834 | peasycap->allocation_audio_struct -= | ||
835 | sizeof(struct data_urb); | ||
836 | kfree(pdata_urb); | ||
837 | m++; | ||
838 | } | ||
839 | } | ||
840 | JOM(4, "%i audio data_urb structures freed\n", m); | ||
841 | JOM(4, "setting peasycap->purb_audio_head=NULL\n"); | ||
842 | peasycap->purb_audio_head = NULL; | ||
843 | } | ||
844 | |||
845 | /* Free audio isoc buffers */ | ||
846 | JOM(4, "freeing audio isoc buffers.\n"); | ||
847 | m = 0; | ||
848 | for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) { | ||
849 | if (peasycap->audio_isoc_buffer[k].pgo) { | ||
850 | free_pages((unsigned long) | ||
851 | (peasycap->audio_isoc_buffer[k].pgo), | ||
852 | AUDIO_ISOC_ORDER); | ||
853 | peasycap->audio_isoc_buffer[k].pgo = NULL; | ||
854 | peasycap->allocation_audio_page -= | ||
855 | BIT(AUDIO_ISOC_ORDER); | ||
856 | m++; | ||
857 | } | ||
858 | } | ||
859 | JOM(4, "easyoss_delete(): isoc audio buffers freed: %i pages\n", | ||
860 | m * (0x01 << AUDIO_ISOC_ORDER)); | ||
861 | JOM(4, "freeing easycap structure.\n"); | ||
862 | allocation_video_urb = peasycap->allocation_video_urb; | ||
863 | allocation_video_page = peasycap->allocation_video_page; | ||
864 | allocation_video_struct = peasycap->allocation_video_struct; | ||
865 | registered_video = peasycap->registered_video; | ||
866 | allocation_audio_urb = peasycap->allocation_audio_urb; | ||
867 | allocation_audio_page = peasycap->allocation_audio_page; | ||
868 | allocation_audio_struct = peasycap->allocation_audio_struct; | ||
869 | registered_audio = peasycap->registered_audio; | ||
870 | |||
871 | if (0 <= kd && DONGLE_MANY > kd) { | ||
872 | if (mutex_lock_interruptible(&mutex_dongle)) { | ||
873 | SAY("ERROR: cannot down mutex_dongle\n"); | ||
874 | } else { | ||
875 | JOM(4, "locked mutex_dongle\n"); | ||
876 | easycapdc60_dongle[kd].peasycap = NULL; | ||
877 | mutex_unlock(&mutex_dongle); | ||
878 | JOM(4, "unlocked mutex_dongle\n"); | ||
879 | JOT(4, " null-->dongle[%i].peasycap\n", kd); | ||
880 | allocation_video_struct -= sizeof(struct easycap); | ||
881 | } | ||
882 | } else { | ||
883 | SAY("ERROR: cannot purge dongle[].peasycap"); | ||
884 | } | ||
885 | |||
886 | kfree(peasycap); | ||
887 | |||
888 | SAY("%8i=video urbs after all deletions\n", allocation_video_urb); | ||
889 | SAY("%8i=video pages after all deletions\n", allocation_video_page); | ||
890 | SAY("%8i=video structs after all deletions\n", allocation_video_struct); | ||
891 | SAY("%8i=video devices after all deletions\n", registered_video); | ||
892 | SAY("%8i=audio urbs after all deletions\n", allocation_audio_urb); | ||
893 | SAY("%8i=audio pages after all deletions\n", allocation_audio_page); | ||
894 | SAY("%8i=audio structs after all deletions\n", allocation_audio_struct); | ||
895 | SAY("%8i=audio devices after all deletions\n", registered_audio); | ||
896 | |||
897 | JOT(4, "ending.\n"); | ||
898 | return; | ||
899 | } | ||
900 | /*****************************************************************************/ | 704 | /*****************************************************************************/ |
901 | static unsigned int easycap_poll(struct file *file, poll_table *wait) | 705 | static unsigned int easycap_poll(struct file *file, poll_table *wait) |
902 | { | 706 | { |
@@ -2875,6 +2679,56 @@ static struct easycap *alloc_easycap(u8 bInterfaceNumber) | |||
2875 | return peasycap; | 2679 | return peasycap; |
2876 | } | 2680 | } |
2877 | 2681 | ||
2682 | static void free_easycap(struct easycap *peasycap) | ||
2683 | { | ||
2684 | int allocation_video_urb; | ||
2685 | int allocation_video_page; | ||
2686 | int allocation_video_struct; | ||
2687 | int allocation_audio_urb; | ||
2688 | int allocation_audio_page; | ||
2689 | int allocation_audio_struct; | ||
2690 | int registered_video, registered_audio; | ||
2691 | int kd; | ||
2692 | |||
2693 | JOM(4, "freeing easycap structure.\n"); | ||
2694 | allocation_video_urb = peasycap->allocation_video_urb; | ||
2695 | allocation_video_page = peasycap->allocation_video_page; | ||
2696 | allocation_video_struct = peasycap->allocation_video_struct; | ||
2697 | registered_video = peasycap->registered_video; | ||
2698 | allocation_audio_urb = peasycap->allocation_audio_urb; | ||
2699 | allocation_audio_page = peasycap->allocation_audio_page; | ||
2700 | allocation_audio_struct = peasycap->allocation_audio_struct; | ||
2701 | registered_audio = peasycap->registered_audio; | ||
2702 | |||
2703 | kd = easycap_isdongle(peasycap); | ||
2704 | if (0 <= kd && DONGLE_MANY > kd) { | ||
2705 | if (mutex_lock_interruptible(&mutex_dongle)) { | ||
2706 | SAY("ERROR: cannot down mutex_dongle\n"); | ||
2707 | } else { | ||
2708 | JOM(4, "locked mutex_dongle\n"); | ||
2709 | easycapdc60_dongle[kd].peasycap = NULL; | ||
2710 | mutex_unlock(&mutex_dongle); | ||
2711 | JOM(4, "unlocked mutex_dongle\n"); | ||
2712 | JOT(4, " null-->dongle[%i].peasycap\n", kd); | ||
2713 | allocation_video_struct -= sizeof(struct easycap); | ||
2714 | } | ||
2715 | } else { | ||
2716 | SAY("ERROR: cannot purge dongle[].peasycap"); | ||
2717 | } | ||
2718 | |||
2719 | /* Free device structure */ | ||
2720 | kfree(peasycap); | ||
2721 | |||
2722 | SAY("%8i=video urbs after all deletions\n", allocation_video_urb); | ||
2723 | SAY("%8i=video pages after all deletions\n", allocation_video_page); | ||
2724 | SAY("%8i=video structs after all deletions\n", allocation_video_struct); | ||
2725 | SAY("%8i=video devices after all deletions\n", registered_video); | ||
2726 | SAY("%8i=audio urbs after all deletions\n", allocation_audio_urb); | ||
2727 | SAY("%8i=audio pages after all deletions\n", allocation_audio_page); | ||
2728 | SAY("%8i=audio structs after all deletions\n", allocation_audio_struct); | ||
2729 | SAY("%8i=audio devices after all deletions\n", registered_audio); | ||
2730 | } | ||
2731 | |||
2878 | /* | 2732 | /* |
2879 | * FIXME: Identify the appropriate pointer peasycap for interfaces | 2733 | * FIXME: Identify the appropriate pointer peasycap for interfaces |
2880 | * 1 and 2. The address of peasycap->pusb_device is reluctantly used | 2734 | * 1 and 2. The address of peasycap->pusb_device is reluctantly used |
@@ -3073,6 +2927,26 @@ static int alloc_framebuffers(struct easycap *peasycap) | |||
3073 | return 0; | 2927 | return 0; |
3074 | } | 2928 | } |
3075 | 2929 | ||
2930 | static void free_framebuffers(struct easycap *peasycap) | ||
2931 | { | ||
2932 | int k, m, gone; | ||
2933 | |||
2934 | JOM(4, "freeing video frame buffers.\n"); | ||
2935 | gone = 0; | ||
2936 | for (k = 0; k < FRAME_BUFFER_MANY; k++) { | ||
2937 | for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++) { | ||
2938 | if (peasycap->frame_buffer[k][m].pgo) { | ||
2939 | free_page((unsigned long) | ||
2940 | peasycap->frame_buffer[k][m].pgo); | ||
2941 | peasycap->frame_buffer[k][m].pgo = NULL; | ||
2942 | peasycap->allocation_video_page -= 1; | ||
2943 | gone++; | ||
2944 | } | ||
2945 | } | ||
2946 | } | ||
2947 | JOM(4, "video frame buffers freed: %i pages\n", gone); | ||
2948 | } | ||
2949 | |||
3076 | static int alloc_fieldbuffers(struct easycap *peasycap) | 2950 | static int alloc_fieldbuffers(struct easycap *peasycap) |
3077 | { | 2951 | { |
3078 | int i, j; | 2952 | int i, j; |
@@ -3112,6 +2986,26 @@ static int alloc_fieldbuffers(struct easycap *peasycap) | |||
3112 | return 0; | 2986 | return 0; |
3113 | } | 2987 | } |
3114 | 2988 | ||
2989 | static void free_fieldbuffers(struct easycap *peasycap) | ||
2990 | { | ||
2991 | int k, m, gone; | ||
2992 | |||
2993 | JOM(4, "freeing video field buffers.\n"); | ||
2994 | gone = 0; | ||
2995 | for (k = 0; k < FIELD_BUFFER_MANY; k++) { | ||
2996 | for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++) { | ||
2997 | if (peasycap->field_buffer[k][m].pgo) { | ||
2998 | free_page((unsigned long) | ||
2999 | peasycap->field_buffer[k][m].pgo); | ||
3000 | peasycap->field_buffer[k][m].pgo = NULL; | ||
3001 | peasycap->allocation_video_page -= 1; | ||
3002 | gone++; | ||
3003 | } | ||
3004 | } | ||
3005 | } | ||
3006 | JOM(4, "video field buffers freed: %i pages\n", gone); | ||
3007 | } | ||
3008 | |||
3115 | static int alloc_isocbuffers(struct easycap *peasycap) | 3009 | static int alloc_isocbuffers(struct easycap *peasycap) |
3116 | { | 3010 | { |
3117 | int i; | 3011 | int i; |
@@ -3142,6 +3036,27 @@ static int alloc_isocbuffers(struct easycap *peasycap) | |||
3142 | return 0; | 3036 | return 0; |
3143 | } | 3037 | } |
3144 | 3038 | ||
3039 | static void free_isocbuffers(struct easycap *peasycap) | ||
3040 | { | ||
3041 | int k, m; | ||
3042 | |||
3043 | JOM(4, "freeing video isoc buffers.\n"); | ||
3044 | m = 0; | ||
3045 | for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) { | ||
3046 | if (peasycap->video_isoc_buffer[k].pgo) { | ||
3047 | free_pages((unsigned long) | ||
3048 | peasycap->video_isoc_buffer[k].pgo, | ||
3049 | VIDEO_ISOC_ORDER); | ||
3050 | peasycap->video_isoc_buffer[k].pgo = NULL; | ||
3051 | peasycap->allocation_video_page -= | ||
3052 | BIT(VIDEO_ISOC_ORDER); | ||
3053 | m++; | ||
3054 | } | ||
3055 | } | ||
3056 | JOM(4, "isoc video buffers freed: %i pages\n", | ||
3057 | m * (0x01 << VIDEO_ISOC_ORDER)); | ||
3058 | } | ||
3059 | |||
3145 | static int create_video_urbs(struct easycap *peasycap) | 3060 | static int create_video_urbs(struct easycap *peasycap) |
3146 | { | 3061 | { |
3147 | struct urb *purb; | 3062 | struct urb *purb; |
@@ -3234,6 +3149,45 @@ static int create_video_urbs(struct easycap *peasycap) | |||
3234 | return 0; | 3149 | return 0; |
3235 | } | 3150 | } |
3236 | 3151 | ||
3152 | static void free_video_urbs(struct easycap *peasycap) | ||
3153 | { | ||
3154 | struct list_head *plist_head, *plist_next; | ||
3155 | struct data_urb *pdata_urb; | ||
3156 | int m; | ||
3157 | |||
3158 | if (peasycap->purb_video_head) { | ||
3159 | m = 0; | ||
3160 | list_for_each(plist_head, peasycap->purb_video_head) { | ||
3161 | pdata_urb = list_entry(plist_head, | ||
3162 | struct data_urb, list_head); | ||
3163 | if (pdata_urb && pdata_urb->purb) { | ||
3164 | usb_free_urb(pdata_urb->purb); | ||
3165 | pdata_urb->purb = NULL; | ||
3166 | peasycap->allocation_video_urb--; | ||
3167 | m++; | ||
3168 | } | ||
3169 | } | ||
3170 | |||
3171 | JOM(4, "%i video urbs freed\n", m); | ||
3172 | JOM(4, "freeing video data_urb structures.\n"); | ||
3173 | m = 0; | ||
3174 | list_for_each_safe(plist_head, plist_next, | ||
3175 | peasycap->purb_video_head) { | ||
3176 | pdata_urb = list_entry(plist_head, | ||
3177 | struct data_urb, list_head); | ||
3178 | if (pdata_urb) { | ||
3179 | peasycap->allocation_video_struct -= | ||
3180 | sizeof(struct data_urb); | ||
3181 | kfree(pdata_urb); | ||
3182 | m++; | ||
3183 | } | ||
3184 | } | ||
3185 | JOM(4, "%i video data_urb structures freed\n", m); | ||
3186 | JOM(4, "setting peasycap->purb_video_head=NULL\n"); | ||
3187 | peasycap->purb_video_head = NULL; | ||
3188 | } | ||
3189 | } | ||
3190 | |||
3237 | static int alloc_audio_buffers(struct easycap *peasycap) | 3191 | static int alloc_audio_buffers(struct easycap *peasycap) |
3238 | { | 3192 | { |
3239 | void *pbuf; | 3193 | void *pbuf; |
@@ -3263,6 +3217,27 @@ static int alloc_audio_buffers(struct easycap *peasycap) | |||
3263 | return 0; | 3217 | return 0; |
3264 | } | 3218 | } |
3265 | 3219 | ||
3220 | static void free_audio_buffers(struct easycap *peasycap) | ||
3221 | { | ||
3222 | int k, m; | ||
3223 | |||
3224 | JOM(4, "freeing audio isoc buffers.\n"); | ||
3225 | m = 0; | ||
3226 | for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) { | ||
3227 | if (peasycap->audio_isoc_buffer[k].pgo) { | ||
3228 | free_pages((unsigned long) | ||
3229 | (peasycap->audio_isoc_buffer[k].pgo), | ||
3230 | AUDIO_ISOC_ORDER); | ||
3231 | peasycap->audio_isoc_buffer[k].pgo = NULL; | ||
3232 | peasycap->allocation_audio_page -= | ||
3233 | BIT(AUDIO_ISOC_ORDER); | ||
3234 | m++; | ||
3235 | } | ||
3236 | } | ||
3237 | JOM(4, "easyoss_delete(): isoc audio buffers freed: %i pages\n", | ||
3238 | m * (0x01 << AUDIO_ISOC_ORDER)); | ||
3239 | } | ||
3240 | |||
3266 | static int create_audio_urbs(struct easycap *peasycap) | 3241 | static int create_audio_urbs(struct easycap *peasycap) |
3267 | { | 3242 | { |
3268 | struct urb *purb; | 3243 | struct urb *purb; |
@@ -3351,6 +3326,45 @@ static int create_audio_urbs(struct easycap *peasycap) | |||
3351 | return 0; | 3326 | return 0; |
3352 | } | 3327 | } |
3353 | 3328 | ||
3329 | static void free_audio_urbs(struct easycap *peasycap) | ||
3330 | { | ||
3331 | struct list_head *plist_head, *plist_next; | ||
3332 | struct data_urb *pdata_urb; | ||
3333 | int m; | ||
3334 | |||
3335 | if (peasycap->purb_audio_head) { | ||
3336 | JOM(4, "freeing audio urbs\n"); | ||
3337 | m = 0; | ||
3338 | list_for_each(plist_head, (peasycap->purb_audio_head)) { | ||
3339 | pdata_urb = list_entry(plist_head, | ||
3340 | struct data_urb, list_head); | ||
3341 | if (pdata_urb && pdata_urb->purb) { | ||
3342 | usb_free_urb(pdata_urb->purb); | ||
3343 | pdata_urb->purb = NULL; | ||
3344 | peasycap->allocation_audio_urb--; | ||
3345 | m++; | ||
3346 | } | ||
3347 | } | ||
3348 | JOM(4, "%i audio urbs freed\n", m); | ||
3349 | JOM(4, "freeing audio data_urb structures.\n"); | ||
3350 | m = 0; | ||
3351 | list_for_each_safe(plist_head, plist_next, | ||
3352 | peasycap->purb_audio_head) { | ||
3353 | pdata_urb = list_entry(plist_head, | ||
3354 | struct data_urb, list_head); | ||
3355 | if (pdata_urb) { | ||
3356 | peasycap->allocation_audio_struct -= | ||
3357 | sizeof(struct data_urb); | ||
3358 | kfree(pdata_urb); | ||
3359 | m++; | ||
3360 | } | ||
3361 | } | ||
3362 | JOM(4, "%i audio data_urb structures freed\n", m); | ||
3363 | JOM(4, "setting peasycap->purb_audio_head=NULL\n"); | ||
3364 | peasycap->purb_audio_head = NULL; | ||
3365 | } | ||
3366 | } | ||
3367 | |||
3354 | static void config_easycap(struct easycap *peasycap, | 3368 | static void config_easycap(struct easycap *peasycap, |
3355 | u8 bInterfaceNumber, | 3369 | u8 bInterfaceNumber, |
3356 | u8 bInterfaceClass, | 3370 | u8 bInterfaceClass, |
@@ -3389,6 +3403,45 @@ static void config_easycap(struct easycap *peasycap, | |||
3389 | } | 3403 | } |
3390 | } | 3404 | } |
3391 | 3405 | ||
3406 | /* | ||
3407 | * This function is called from within easycap_usb_disconnect() and is | ||
3408 | * protected by semaphores set and cleared by easycap_usb_disconnect(). | ||
3409 | * By this stage the device has already been physically unplugged, | ||
3410 | * so peasycap->pusb_device is no longer valid. | ||
3411 | */ | ||
3412 | static void easycap_delete(struct kref *pkref) | ||
3413 | { | ||
3414 | struct easycap *peasycap; | ||
3415 | |||
3416 | peasycap = container_of(pkref, struct easycap, kref); | ||
3417 | if (!peasycap) { | ||
3418 | SAM("ERROR: peasycap is NULL: cannot perform deletions\n"); | ||
3419 | return; | ||
3420 | } | ||
3421 | |||
3422 | /* Free video urbs */ | ||
3423 | free_video_urbs(peasycap); | ||
3424 | |||
3425 | /* Free video isoc buffers */ | ||
3426 | free_isocbuffers(peasycap); | ||
3427 | |||
3428 | /* Free video field buffers */ | ||
3429 | free_fieldbuffers(peasycap); | ||
3430 | |||
3431 | /* Free video frame buffers */ | ||
3432 | free_framebuffers(peasycap); | ||
3433 | |||
3434 | /* Free audio urbs */ | ||
3435 | free_audio_urbs(peasycap); | ||
3436 | |||
3437 | /* Free audio isoc buffers */ | ||
3438 | free_audio_buffers(peasycap); | ||
3439 | |||
3440 | free_easycap(peasycap); | ||
3441 | |||
3442 | JOT(4, "ending.\n"); | ||
3443 | } | ||
3444 | |||
3392 | static const struct v4l2_file_operations v4l2_fops = { | 3445 | static const struct v4l2_file_operations v4l2_fops = { |
3393 | .owner = THIS_MODULE, | 3446 | .owner = THIS_MODULE, |
3394 | .open = easycap_open_noinode, | 3447 | .open = easycap_open_noinode, |