Update of /cvsroot/alsa/alsa-kernel/pci/mixart
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28667/pci/mixart

Modified Files:
        mixart.c mixart.h mixart_core.c 
Log Message:
- fixed the race condition in message flow.
- removed obsolete debug prints.
- make prepare callback non-atomic.
- synchronize with the pending messages in prepare and hw_free callbacks.


Index: mixart.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/mixart/mixart.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- mixart.c    23 Feb 2004 18:18:23 -0000      1.3
+++ mixart.c    24 Feb 2004 12:08:03 -0000      1.4
@@ -123,12 +123,8 @@
        request.size = sizeof(group_state);
 
        err = snd_mixart_send_msg(mgr, &request, sizeof(group_state_resp), 
&group_state_resp);
-       if(err) {
-               snd_printk(KERN_ERR "error MSG_STREAM_ST***_STREAM_GRP_PACKET\n");
-               return err;
-       }
-       if(group_state_resp.txx_status != 0) {
-               snd_printk(KERN_ERR "error status MSG_STREAM_ST***_STREAM_GRP_PACKET 
(%x)!\n", group_state_resp.txx_status);
+       if (err < 0 || group_state_resp.txx_status != 0) {
+               snd_printk(KERN_ERR "error MSG_STREAM_ST***_STREAM_GRP_PACKET err=%x 
stat=%x !\n", err, group_state_resp.txx_status);
                return -EINVAL;
        }
 
@@ -138,13 +134,9 @@
                group_state.pipe_count = 0; /* in case of start same command once 
again with pipe_count=0 */
 
                err = snd_mixart_send_msg(mgr, &request, sizeof(group_state_resp), 
&group_state_resp);
-               if(err) {
-                       snd_printk(KERN_ERR "error MSG_STREAM_START_STREAM_GRP_PACKET 
!\n");
-                       return err;
-               }
-               if(group_state_resp.txx_status != 0) {
-                       snd_printk(KERN_ERR "error status 
MSG_STREAM_START_STREAM_GRP_PACKET (%x)!\n", group_state_resp.txx_status);
-                       return -EINVAL;
+               if (err < 0 || group_state_resp.txx_status != 0) {
+                       snd_printk(KERN_ERR "error MSG_STREAM_START_STREAM_GRP_PACKET 
err=%x stat=%x !\n", err, group_state_resp.txx_status);
+                       return -EINVAL;
                }
 
                /* in case of start send a synchro top */
@@ -155,12 +147,9 @@
                request.size = 0;
 
                err = snd_mixart_send_msg(mgr, &request, sizeof(stat), &stat);
-               if(err) {
-                       snd_printk(KERN_ERR "error MSG_SYSTEM_SEND_SYNCHRO_CMD!\n");
-                       return err;
-               }
-               if(stat) {
-                       snd_printk(KERN_ERR "error MSG_SYSTEM_SEND_SYNCHRO_CMD 
stat=%x!\n", stat);
+               if (err < 0 || stat != 0) {
+                       snd_printk(KERN_ERR "error MSG_SYSTEM_SEND_SYNCHRO_CMD err=%x 
stat=%x !\n", err, stat);
+                       return -EINVAL;
                }
 
                pipe->status = PIPE_RUNNING;
@@ -176,6 +165,8 @@
 {
        mixart_msg_t request;
        mixart_clock_properties_t clock_properties;
+       mixart_clock_properties_resp_t clock_prop_resp;
+       int err;
 
        switch(pipe->status) {
        case PIPE_CLOCK_SET:
@@ -206,13 +197,16 @@
        request.data = &clock_properties;
        request.size = sizeof(clock_properties);
 
-       /* we are not allowed to wait for the response, so simply set rate */
-       /* TODO : error has to be handled later in the tasklet! */
+       err = snd_mixart_send_msg(mgr, &request, sizeof(clock_prop_resp), 
&clock_prop_resp);
+       if (err < 0 || clock_prop_resp.status != 0 || clock_prop_resp.clock_mode != 
CM_STANDALONE) {
+               snd_printk(KERN_ERR "error MSG_CLOCK_SET_PROPERTIES err=%x stat=%x 
mod=%x !\n", err, clock_prop_resp.status, clock_prop_resp.clock_mode);
+               return -EINVAL;
+       }
 
        if(rate)  pipe->status = PIPE_CLOCK_SET;
        else      pipe->status = PIPE_RUNNING;
 
-       return snd_mixart_send_msg_nonblock(mgr, &request);
+       return 0;
 }
 
 
@@ -295,7 +289,7 @@
 
                err = snd_mixart_send_msg(chip->mgr, &request, 
sizeof(streaming_group_resp), &streaming_group_resp);
                if((err < 0) || (streaming_group_resp.status != 0)) {
-                       snd_printk(KERN_ERR "message MSG_STREAM_ADD_**PUT_GROUP return 
error: err(%x) status(%x)!\n", err, streaming_group_resp.status);
+                       snd_printk(KERN_ERR "error MSG_STREAM_ADD_**PUT_GROUP err=%x 
stat=%x !\n", err, streaming_group_resp.status);
                        return NULL;
                }
 
@@ -406,7 +400,6 @@
 
                snd_printdd("SNDRV_PCM_TRIGGER_START\n");
 
-               // snd_printk(KERN_DEBUG "hw_avail = %d\n", 
snd_pcm_playback_hw_avail(subs->runtime));
                /* START_STREAM */
                if( mixart_set_stream_state(stream, 1) )
                        return -EINVAL;
@@ -420,7 +413,6 @@
                if( mixart_set_stream_state(stream, 0) )
                        return -EINVAL;
 
-               /* TODO : mixart drains data transefered in advance -> mute stream ? */
                stream->status = MIXART_STREAM_STATUS_OPEN;
 
                snd_printdd("SNDRV_PCM_TRIGGER_STOP\n");
@@ -443,8 +435,24 @@
        return 0;
 }
 
+static int mixart_sync_nonblock_events(mixart_mgr_t *mgr)
+{
+       int timeout = HZ;
+       while (atomic_read(&mgr->msg_processed) > 0) {
+               if (! timeout--) {
+                       snd_printk(KERN_ERR "mixart: cannot process nonblock 
events!\n");
+                       return -EBUSY;
+               }
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               schedule_timeout(1);
+       }
+       return 0;
+}
+
 /*
  *  prepare callback for all pcms
+ *
+ *  NOTE: this callback is non-atomic (pcm->info_flags |= 
SNDRV_PCM_INFO_NONATOMIC_OPS)
  */
 static int snd_mixart_prepare(snd_pcm_substream_t *subs)
 {
@@ -455,6 +463,8 @@
 
        snd_printdd("snd_mixart_prepare\n");
 
+       mixart_sync_nonblock_events(chip->mgr);
+
        /* only the first stream can choose the sample rate */
        /* the further opened streams will be limited to its frequency (see open) */
        if(chip->mgr->ref_count_rate == 1)
@@ -519,9 +529,8 @@
                stream_param.sample_size = 32;
                break;
        default:
-               snd_printk(KERN_DEBUG "error use default SNDRV_PCM_FORMAT_S16_LE\n");
-               stream_param.sample_type = ST_INTEGER_16LE;
-               stream_param.sample_size = 16;
+               snd_printk(KERN_ERR "error mixart_set_format() : unknown format\n");
+               return -EINVAL;
        }
 
        snd_printdd("set SNDRV_PCM_FORMAT sample_type(%d) sample_size(%d) freq(%d) 
channels(%d)\n",
@@ -544,7 +553,7 @@
 
        err = snd_mixart_send_msg(chip->mgr, &request, sizeof(resp), &resp);
        if((err < 0) || resp.error_code) {
-               snd_printk(KERN_DEBUG "MSG_STREAM_SET_INPUT_STAGE_PARAM err=%x; 
resp=%x\n", err, resp.error_code);
+               snd_printk(KERN_ERR "MSG_STREAM_SET_INPUT_STAGE_PARAM err=%x; 
resp=%x\n", err, resp.error_code);
                return -EINVAL;
        }
        return 0;
@@ -586,7 +595,6 @@
        /* set the format to the board */
        err = mixart_set_format(stream, format);
        if(err < 0) {
-               snd_printk(KERN_DEBUG "mixart_set_format() returned error (%x)\n", 
err);
                return err;
        }
 
@@ -611,7 +619,9 @@
 
 static int snd_mixart_hw_free(snd_pcm_substream_t *subs)
 {
+       mixart_t *chip = snd_pcm_substream_chip(subs);
        snd_pcm_lib_free_pages(subs);
+       mixart_sync_nonblock_events(chip->mgr);
        return 0;
 }
 
@@ -916,7 +926,7 @@
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_mixart_playback_ops);
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops);
 
-       pcm->info_flags = 0;
+       pcm->info_flags = SNDRV_PCM_INFO_NONATOMIC_OPS;
        strcpy(pcm->name, name);
 
        preallocate_buffers(chip, pcm);
@@ -947,7 +957,7 @@
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_mixart_playback_ops);
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops);
 
-       pcm->info_flags = 0;
+       pcm->info_flags = SNDRV_PCM_INFO_NONATOMIC_OPS;
        strcpy(pcm->name, name);
 
        preallocate_buffers(chip, pcm);
@@ -1318,6 +1328,8 @@
 
        mgr->msg_lock = SPIN_LOCK_UNLOCKED;
        init_MUTEX(&mgr->msg_mutex);
+       init_waitqueue_head(&mgr->msg_sleep);
+       atomic_set(&mgr->msg_processed, 0);
 
        /* init setup mutex*/
        init_MUTEX(&mgr->setup_mutex);

Index: mixart.h
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/mixart/mixart.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- mixart.h    9 Feb 2004 17:40:48 -0000       1.1
+++ mixart.h    24 Feb 2004 12:08:03 -0000      1.2
@@ -102,6 +102,7 @@
        u32 msg_fifo[MSG_FIFO_SIZE];
        int msg_fifo_readptr;
        int msg_fifo_writeptr;
+       atomic_t msg_processed;       /* number of messages to be processed in takslet 
*/
 
        spinlock_t lock;              /* interrupt spinlock */
        spinlock_t msg_lock;          /* mailbox spinlock */

Index: mixart_core.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/mixart/mixart_core.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- mixart_core.c       23 Feb 2004 18:18:24 -0000      1.3
+++ mixart_core.c       24 Feb 2004 12:08:03 -0000      1.4
@@ -132,20 +132,19 @@
 /*
  * send a message to miXart. return: the msg_frame used for this message
  */
+/* call with mgr->msg_lock held! */
 static int send_msg( mixart_mgr_t *mgr,
                     mixart_msg_t *msg,
                     int max_answersize,
                     int mark_pending,
                     u32 *msg_event)
 {
-       unsigned long flags;
        u32 headptr, tailptr;
        u32 msg_frame_address;
        int err, i;
 
        snd_assert(msg->size % 4 == 0, return -EINVAL);
 
-       spin_lock_irqsave(&mgr->msg_lock, flags);
        err = 0;
 
        /* get message frame address */
@@ -154,13 +153,11 @@
 
        if (tailptr == headptr) {
                snd_printk(KERN_ERR "error: no message frame available\n");
-               err = -EBUSY;
-               goto _clean_exit;
+               return -EBUSY;
        }
 
        if( (tailptr < MSG_INBOUND_FREE_STACK) || (tailptr >= 
(MSG_INBOUND_FREE_STACK+MSG_BOUND_STACK_SIZE))) {
-               err = -EINVAL;
-               goto _clean_exit;
+               return -EINVAL;
        }
 
        msg_frame_address = readl_be(MIXART_MEM(mgr, tailptr));
@@ -213,8 +210,7 @@
        headptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_POST_HEAD));
 
        if( (headptr < MSG_INBOUND_POST_STACK) || (headptr >= 
(MSG_INBOUND_POST_STACK+MSG_BOUND_STACK_SIZE))) {
-               err = -EINVAL;
-               goto _clean_exit;
+               return -EINVAL;
        }
 
        writel_be(msg_frame_address, MIXART_MEM(mgr, headptr));
@@ -226,8 +222,6 @@
 
        writel_be(headptr, MIXART_MEM(mgr, MSG_INBOUND_POST_HEAD));
 
- _clean_exit:
-       spin_unlock_irqrestore(&mgr->msg_lock, flags);
        return 0;
 }
 
@@ -242,23 +236,21 @@
 
        down(&mgr->msg_mutex);
 
-       init_waitqueue_head(&mgr->msg_sleep);
        init_waitqueue_entry(&wait, current);
 
-       current->state = TASK_UNINTERRUPTIBLE;
-       add_wait_queue(&mgr->msg_sleep, &wait);
-
+       spin_lock_irq(&mgr->msg_lock);
        /* send the message */
        err = send_msg(mgr, request, max_resp_size, 1, &msg_frame);  /* send and mark 
the answer pending */
-       if(err) {
-               current->state = TASK_RUNNING;
-               remove_wait_queue(&mgr->msg_sleep, &wait);
+       if (err) {
+               spin_unlock_irq(&mgr->msg_lock);
                up(&mgr->msg_mutex);
                return err;
        }
 
+       set_current_state(TASK_UNINTERRUPTIBLE);
+       add_wait_queue(&mgr->msg_sleep, &wait);
+       spin_unlock_irq(&mgr->msg_lock);
        timeout = schedule_timeout(MSG_TIMEOUT_JIFFIES);
-       current->state = TASK_RUNNING;
        remove_wait_queue(&mgr->msg_sleep, &wait);
 
        if (! timeout) {
@@ -296,23 +288,21 @@
 
        down(&mgr->msg_mutex);
 
-       init_waitqueue_head(&mgr->msg_sleep);
        init_waitqueue_entry(&wait, current);
 
-       current->state = TASK_UNINTERRUPTIBLE;
-       add_wait_queue(&mgr->msg_sleep, &wait);
-
+       spin_lock_irq(&mgr->msg_lock);
        /* send the message */
        err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 1, &notif_event);  /* send and 
mark the notification event pending */
        if(err) {
-               current->state = TASK_RUNNING;
-               remove_wait_queue(&mgr->msg_sleep, &wait);
+               spin_unlock_irq(&mgr->msg_lock);
                up(&mgr->msg_mutex);
                return err;
        }
 
+       set_current_state(TASK_UNINTERRUPTIBLE);
+       add_wait_queue(&mgr->msg_sleep, &wait);
+       spin_unlock_irq(&mgr->msg_lock);
        timeout = schedule_timeout(MSG_TIMEOUT_JIFFIES);
-       current->state = TASK_RUNNING;
        remove_wait_queue(&mgr->msg_sleep, &wait);
 
        if (! timeout) {
@@ -330,11 +320,18 @@
 int snd_mixart_send_msg_nonblock(mixart_mgr_t *mgr, mixart_msg_t *request)
 {
        u32 message_frame;
+       unsigned long flags;
+       int err;
 
        /* just send the message (do not mark it as a pending one) */
-       return send_msg(mgr, request, MSG_DEFAULT_SIZE, 0, &message_frame);
+       spin_lock_irqsave(&mgr->msg_lock, flags);
+       err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 0, &message_frame);
+       spin_unlock_irqrestore(&mgr->msg_lock, flags);
 
        /* the answer will be handled by snd_mixart_msg_tasklet()  */
+       atomic_inc(&mgr->msg_processed);
+
+       return err;
 }
 
 
@@ -378,16 +375,7 @@
                        case MSG_STREAM_STOP_INPUT_STAGE_PACKET:
                        case MSG_STREAM_STOP_OUTPUT_STAGE_PACKET:
                                if(mixart_msg_data[0])
-                                       snd_printdd("tasklet : 
MSG_STREAM_ST***_***PUT_STAGE_PACKET txx_status(%x)\n", mixart_msg_data[0]);
-                               break;
-                       case MSG_CLOCK_CHECK_PROPERTIES:
-                       case MSG_CLOCK_SET_PROPERTIES:
-                               if(mixart_msg_data[0])
-                                       snd_printdd("tasklet : 
MSG_CLOCK_***_PROPERTIES txx_status(%x) clock_mode(%x)\n", mixart_msg_data[0], 
mixart_msg_data[1]);
-                               break;
-                       case MSG_SYSTEM_WAIT_SYNCHRO_CMD:
-                               if(mixart_msg_data[0])
-                                       snd_printdd("tasklet : 
MSG_SYSTEM_WAIT_SYNCHRO_CMD txx_status(%x)\n", mixart_msg_data[0]);
+                                       snd_printk(KERN_ERR "tasklet : error 
MSG_STREAM_ST***_***PUT_STAGE_PACKET status=%x\n", mixart_msg_data[0]);
                                break;
                        default:
                                snd_printdd("tasklet received mf(%x) : msg_id(%x) 
uid(%x, %x) size(%d)\n",
@@ -395,13 +383,17 @@
                                break;
                        }
                        break;
-               case MSG_TYPE_NOTIFY:
+               case MSG_TYPE_NOTIFY:
                        /* msg contains no address ! do not get_msg() ! */
                case MSG_TYPE_COMMAND:
                        /* get_msg() necessary */
                default:
                        snd_printk(KERN_ERR "tasklet doesn't know what to do with 
message %x\n", msg);
                } /* switch type */
+
+               /* decrement counter */
+               atomic_dec(&mgr->msg_processed);
+
        } /* while there is a msg in fifo */
 
        spin_unlock(&mgr->lock);
@@ -466,7 +458,8 @@
                                        mixart_stream_t *stream;
 
                                        if ((chip_number >= mgr->num_cards) || 
(pcm_number >= MIXART_PCM_TOTAL) || (sub_number >= MIXART_PLAYBACK_STREAMS)) {
-                                               snd_printk(KERN_DEBUG "ERROR buffer_id 
(%x) pos(%d)\n", buffer_id, notify->streams[i].sample_pos_low_part);
+                                               snd_printk(KERN_ERR "error 
MSG_SERVICES_TIMER_NOTIFY buffer_id (%x) pos(%d)\n",
+                                                          buffer_id, 
notify->streams[i].sample_pos_low_part);
                                                break;
                                        }
 
@@ -533,6 +526,7 @@
                        /* no break, continue ! */
                case MSG_TYPE_ANSWER:
                        /* answer or notification to a message we are waiting for*/
+                       spin_lock(&mgr->msg_lock);
                        if( (msg & ~MSG_TYPE_MASK) == mgr->pending_event ) {
                                wake_up(&mgr->msg_sleep);
                                mgr->pending_event = 0;
@@ -544,6 +538,7 @@
                                mgr->msg_fifo_writeptr %= MSG_FIFO_SIZE;
                                tasklet_hi_schedule(&mgr->msg_taskq);
                        }
+                       spin_unlock(&mgr->msg_lock);
                        break;
                case MSG_TYPE_REQUEST:
                default:



-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now.
Build and deploy apps & Web services for Linux with
a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
_______________________________________________
Alsa-cvslog mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-cvslog

Reply via email to