diff options
author | Uri Shkolnik <uris@siano-ms.com> | 2009-05-17 04:59:37 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-06-16 18:14:34 -0400 |
commit | a9349315f65cd6a16e8fab1f6cf0fd40f379c4db (patch) | |
tree | 1aba13508320814d1bdd1d8d4e18a48cb3985608 /drivers/media/dvb | |
parent | 9504ccacd749ad98e1990c35acd94f7fceaa992e (diff) |
V4L/DVB (11819): Siano: smscore - fix get_common_buffer bug
get common buffers() should block operation until valid buffer
is avaliable.
Signed-off-by: Uri Shkolnik <uris@siano-ms.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb')
-rw-r--r-- | drivers/media/dvb/siano/smscoreapi.c | 38 |
1 files changed, 29 insertions, 9 deletions
diff --git a/drivers/media/dvb/siano/smscoreapi.c b/drivers/media/dvb/siano/smscoreapi.c index 040a3ff12068..9a5358caec46 100644 --- a/drivers/media/dvb/siano/smscoreapi.c +++ b/drivers/media/dvb/siano/smscoreapi.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/io.h> | 30 | #include <linux/io.h> |
31 | 31 | ||
32 | #include <linux/firmware.h> | 32 | #include <linux/firmware.h> |
33 | #include <linux/wait.h> | ||
33 | 34 | ||
34 | #include "smscoreapi.h" | 35 | #include "smscoreapi.h" |
35 | #include "sms-cards.h" | 36 | #include "sms-cards.h" |
@@ -352,6 +353,9 @@ int smscore_register_device(struct smsdevice_params_t *params, | |||
352 | init_completion(&dev->resume_done); | 353 | init_completion(&dev->resume_done); |
353 | init_completion(&dev->ir_init_done); | 354 | init_completion(&dev->ir_init_done); |
354 | 355 | ||
356 | /* Buffer management */ | ||
357 | init_waitqueue_head(&dev->buffer_mng_waitq); | ||
358 | |||
355 | /* alloc common buffer */ | 359 | /* alloc common buffer */ |
356 | dev->common_buffer_size = params->buffer_size * params->num_buffers; | 360 | dev->common_buffer_size = params->buffer_size * params->num_buffers; |
357 | dev->common_buffer = dma_alloc_coherent(NULL, dev->common_buffer_size, | 361 | dev->common_buffer = dma_alloc_coherent(NULL, dev->common_buffer_size, |
@@ -686,7 +690,9 @@ void smscore_unregister_device(struct smscore_device_t *coredev) | |||
686 | * onresponse must no longer be called */ | 690 | * onresponse must no longer be called */ |
687 | 691 | ||
688 | while (1) { | 692 | while (1) { |
689 | while ((cb = smscore_getbuffer(coredev))) { | 693 | while (!list_empty(&coredev->buffers)) { |
694 | cb = (struct smscore_buffer_t *) coredev->buffers.next; | ||
695 | list_del(&cb->entry); | ||
690 | kfree(cb); | 696 | kfree(cb); |
691 | num_buffers++; | 697 | num_buffers++; |
692 | } | 698 | } |
@@ -707,8 +713,10 @@ void smscore_unregister_device(struct smscore_device_t *coredev) | |||
707 | 713 | ||
708 | if (coredev->common_buffer) | 714 | if (coredev->common_buffer) |
709 | dma_free_coherent(NULL, coredev->common_buffer_size, | 715 | dma_free_coherent(NULL, coredev->common_buffer_size, |
710 | coredev->common_buffer, | 716 | coredev->common_buffer, coredev->common_buffer_phys); |
711 | coredev->common_buffer_phys); | 717 | |
718 | if (coredev->fw_buf != NULL) | ||
719 | kfree(coredev->fw_buf); | ||
712 | 720 | ||
713 | list_del(&coredev->entry); | 721 | list_del(&coredev->entry); |
714 | kfree(coredev); | 722 | kfree(coredev); |
@@ -1071,12 +1079,24 @@ struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev) | |||
1071 | struct smscore_buffer_t *cb = NULL; | 1079 | struct smscore_buffer_t *cb = NULL; |
1072 | unsigned long flags; | 1080 | unsigned long flags; |
1073 | 1081 | ||
1082 | DEFINE_WAIT(wait); | ||
1083 | |||
1074 | spin_lock_irqsave(&coredev->bufferslock, flags); | 1084 | spin_lock_irqsave(&coredev->bufferslock, flags); |
1075 | 1085 | ||
1076 | if (!list_empty(&coredev->buffers)) { | 1086 | /* This function must return a valid buffer, since the buffer list is |
1077 | cb = (struct smscore_buffer_t *) coredev->buffers.next; | 1087 | * finite, we check that there is an available buffer, if not, we wait |
1078 | list_del(&cb->entry); | 1088 | * until such buffer become available. |
1079 | } | 1089 | */ |
1090 | |||
1091 | prepare_to_wait(&coredev->buffer_mng_waitq, &wait, TASK_INTERRUPTIBLE); | ||
1092 | |||
1093 | if (list_empty(&coredev->buffers)) | ||
1094 | schedule(); | ||
1095 | |||
1096 | finish_wait(&coredev->buffer_mng_waitq, &wait); | ||
1097 | |||
1098 | cb = (struct smscore_buffer_t *) coredev->buffers.next; | ||
1099 | list_del(&cb->entry); | ||
1080 | 1100 | ||
1081 | spin_unlock_irqrestore(&coredev->bufferslock, flags); | 1101 | spin_unlock_irqrestore(&coredev->bufferslock, flags); |
1082 | 1102 | ||
@@ -1093,8 +1113,8 @@ EXPORT_SYMBOL_GPL(smscore_getbuffer); | |||
1093 | * | 1113 | * |
1094 | */ | 1114 | */ |
1095 | void smscore_putbuffer(struct smscore_device_t *coredev, | 1115 | void smscore_putbuffer(struct smscore_device_t *coredev, |
1096 | struct smscore_buffer_t *cb) | 1116 | struct smscore_buffer_t *cb) { |
1097 | { | 1117 | wake_up_interruptible(&coredev->buffer_mng_waitq); |
1098 | list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock); | 1118 | list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock); |
1099 | } | 1119 | } |
1100 | EXPORT_SYMBOL_GPL(smscore_putbuffer); | 1120 | EXPORT_SYMBOL_GPL(smscore_putbuffer); |