aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging
diff options
context:
space:
mode:
authorEzequiel GarcĂ­a <elezegarcia@gmail.com>2012-02-24 09:24:22 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-05-15 08:00:48 -0400
commit92a0144225fa14e044bdbdaa23e1049ca2047a5c (patch)
tree26f275ef14ab4fce2d1e5551903646a6dd95283d /drivers/staging
parentdf8c4b72322ade883766a9b9311d42ae8a83cf66 (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.c445
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 */
710static 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/*****************************************************************************/
901static unsigned int easycap_poll(struct file *file, poll_table *wait) 705static 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
2682static 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
2930static 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
3076static int alloc_fieldbuffers(struct easycap *peasycap) 2950static 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
2989static 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
3115static int alloc_isocbuffers(struct easycap *peasycap) 3009static 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
3039static 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
3145static int create_video_urbs(struct easycap *peasycap) 3060static 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
3152static 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
3237static int alloc_audio_buffers(struct easycap *peasycap) 3191static 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
3220static 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
3266static int create_audio_urbs(struct easycap *peasycap) 3241static 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
3329static 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
3354static void config_easycap(struct easycap *peasycap, 3368static 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 */
3412static 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
3392static const struct v4l2_file_operations v4l2_fops = { 3445static 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,