staging: speakup: avoid out-of-range access in synth_add()
[pandora-kernel.git] / drivers / staging / intel_sst / intel_sst_stream.c
1 /*
2  *  intel_sst_stream.c - Intel SST Driver for audio engine
3  *
4  *  Copyright (C) 2008-10 Intel Corp
5  *  Authors:    Vinod Koul <vinod.koul@intel.com>
6  *              Harsha Priya <priya.harsha@intel.com>
7  *              Dharageswari R <dharageswari.r@intel.com>
8  *              KP Jeeja <jeeja.kp@intel.com>
9  *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; version 2 of the License.
14  *
15  *  This program is distributed in the hope that it will be useful, but
16  *  WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  *  General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License along
21  *  with this program; if not, write to the Free Software Foundation, Inc.,
22  *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23  *
24  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25  *
26  *  This file contains the stream operations of SST driver
27  */
28
29 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
30
31 #include <linux/pci.h>
32 #include <linux/firmware.h>
33 #include <linux/sched.h>
34 #include <linux/delay.h>
35 #include "intel_sst_ioctl.h"
36 #include "intel_sst.h"
37 #include "intel_sst_fw_ipc.h"
38 #include "intel_sst_common.h"
39
40 /*
41  * sst_check_device_type - Check the medfield device type
42  *
43  * @device: Device to be checked
44  * @num_ch: Number of channels queried
45  * @pcm_slot: slot to be enabled for this device
46  *
47  * This checks the deivce against the map and calculates pcm_slot value
48  */
49 int sst_check_device_type(u32 device, u32 num_chan, u32 *pcm_slot)
50 {
51         if (device >= MAX_NUM_STREAMS_MFLD) {
52                 pr_debug("device type invalid %d\n", device);
53                 return -EINVAL;
54         }
55         if (sst_drv_ctx->streams[device].status == STREAM_UN_INIT) {
56                 if (device == SND_SST_DEVICE_VIBRA && num_chan == 1)
57                         *pcm_slot = 0x10;
58                 else if (device == SND_SST_DEVICE_HAPTIC && num_chan == 1)
59                         *pcm_slot = 0x20;
60                 else if (device == SND_SST_DEVICE_IHF && num_chan == 1)
61                         *pcm_slot = 0x04;
62                 else if (device == SND_SST_DEVICE_IHF && num_chan == 2)
63                         *pcm_slot = 0x0C;
64                 else if (device == SND_SST_DEVICE_HEADSET && num_chan == 1)
65                         *pcm_slot = 0x01;
66                 else if (device == SND_SST_DEVICE_HEADSET && num_chan == 2)
67                         *pcm_slot = 0x03;
68                 else if (device == SND_SST_DEVICE_CAPTURE && num_chan == 1)
69                         *pcm_slot = 0x01;
70                 else if (device == SND_SST_DEVICE_CAPTURE && num_chan == 2)
71                         *pcm_slot = 0x03;
72                 else if (device == SND_SST_DEVICE_CAPTURE && num_chan == 3)
73                         *pcm_slot = 0x07;
74                 else if (device == SND_SST_DEVICE_CAPTURE && num_chan == 4)
75                         *pcm_slot = 0x0F;
76                 else if (device == SND_SST_DEVICE_CAPTURE && num_chan > 4)
77                         *pcm_slot = 0x1F;
78                 else {
79                         pr_debug("No condition satisfied.. ret err\n");
80                         return -EINVAL;
81                 }
82         } else {
83                 pr_debug("this stream state is not uni-init, is %d\n",
84                                 sst_drv_ctx->streams[device].status);
85                 return -EBADRQC;
86         }
87         pr_debug("returning slot %x\n", *pcm_slot);
88         return 0;
89 }
90 /**
91  * get_mrst_stream_id   -       gets a new stream id for use
92  *
93  * This functions searches the current streams and allocated an empty stream
94  * lock stream_lock required to be held before calling this
95  */
96 static unsigned int get_mrst_stream_id(void)
97 {
98         int i;
99
100         for (i = 1; i <= MAX_NUM_STREAMS_MRST; i++) {
101                 if (sst_drv_ctx->streams[i].status == STREAM_UN_INIT)
102                         return i;
103         }
104         pr_debug("Didn't find empty stream for mrst\n");
105         return -EBUSY;
106 }
107
108 /**
109  * sst_alloc_stream - Send msg for a new stream ID
110  *
111  * @params:     stream params
112  * @stream_ops: operation of stream PB/capture
113  * @codec:      codec for stream
114  * @device:     device stream to be allocated for
115  *
116  * This function is called by any function which wants to start
117  * a new stream. This also check if a stream exists which is idle
118  * it initializes idle stream id to this request
119  */
120 int sst_alloc_stream(char *params, unsigned int stream_ops,
121                u8 codec, unsigned int device)
122 {
123         struct ipc_post *msg = NULL;
124         struct snd_sst_alloc_params alloc_param;
125         unsigned int pcm_slot = 0, num_ch;
126         int str_id;
127         struct snd_sst_stream_params *sparams;
128         struct stream_info *str_info;
129
130         pr_debug("SST DBG:entering sst_alloc_stream\n");
131         pr_debug("SST DBG:%d %d %d\n", stream_ops, codec, device);
132
133         BUG_ON(!params);
134         sparams = (struct snd_sst_stream_params *)params;
135         num_ch = sparams->uc.pcm_params.num_chan;
136         /*check the device type*/
137         if (sst_drv_ctx->pci_id == SST_MFLD_PCI_ID) {
138                 if (sst_check_device_type(device, num_ch, &pcm_slot))
139                         return -EINVAL;
140                 mutex_lock(&sst_drv_ctx->stream_lock);
141                 str_id = device;
142                 mutex_unlock(&sst_drv_ctx->stream_lock);
143                 pr_debug("SST_DBG: slot %x\n", pcm_slot);
144         } else {
145                 mutex_lock(&sst_drv_ctx->stream_lock);
146                 str_id = get_mrst_stream_id();
147                 mutex_unlock(&sst_drv_ctx->stream_lock);
148                 if (str_id <= 0)
149                         return -EBUSY;
150         }
151         /*allocate device type context*/
152         sst_init_stream(&sst_drv_ctx->streams[str_id], codec,
153                         str_id, stream_ops, pcm_slot, device);
154         /* send msg to FW to allocate a stream */
155         if (sst_create_large_msg(&msg))
156                 return -ENOMEM;
157
158         sst_fill_header(&msg->header, IPC_IA_ALLOC_STREAM, 1, str_id);
159         msg->header.part.data = sizeof(alloc_param) + sizeof(u32);
160         alloc_param.str_type.codec_type = codec;
161         alloc_param.str_type.str_type = SST_STREAM_TYPE_MUSIC;
162         alloc_param.str_type.operation = stream_ops;
163         alloc_param.str_type.protected_str = 0; /* non drm */
164         alloc_param.str_type.time_slots = pcm_slot;
165         alloc_param.str_type.result = alloc_param.str_type.reserved = 0;
166         memcpy(&alloc_param.stream_params, params,
167                         sizeof(struct snd_sst_stream_params));
168
169         memcpy(msg->mailbox_data, &msg->header, sizeof(u32));
170         memcpy(msg->mailbox_data + sizeof(u32), &alloc_param,
171                         sizeof(alloc_param));
172         str_info = &sst_drv_ctx->streams[str_id];
173         str_info->ctrl_blk.condition = false;
174         str_info->ctrl_blk.ret_code = 0;
175         str_info->ctrl_blk.on = true;
176         spin_lock(&sst_drv_ctx->list_spin_lock);
177         list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
178         spin_unlock(&sst_drv_ctx->list_spin_lock);
179         sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
180         pr_debug("SST DBG:alloc stream done\n");
181         return str_id;
182 }
183
184
185 /*
186  * sst_alloc_stream_response - process alloc reply
187  *
188  * @str_id:     stream id for which the stream has been allocated
189  * @resp                the stream response from firware
190  *
191  * This function is called by firmware as a response to stream allcoation
192  * request
193  */
194 int sst_alloc_stream_response(unsigned int str_id,
195                                 struct snd_sst_alloc_response *resp)
196 {
197         int retval = 0;
198         struct stream_info *str_info;
199         struct snd_sst_lib_download *lib_dnld;
200
201         pr_debug("SST DEBUG: stream number given = %d\n", str_id);
202         str_info = &sst_drv_ctx->streams[str_id];
203         if (resp->str_type.result == SST_LIB_ERR_LIB_DNLD_REQUIRED) {
204                 lib_dnld = kzalloc(sizeof(*lib_dnld), GFP_KERNEL);
205                 memcpy(lib_dnld, &resp->lib_dnld, sizeof(*lib_dnld));
206         } else
207                 lib_dnld = NULL;
208         if (str_info->ctrl_blk.on == true) {
209                 str_info->ctrl_blk.on = false;
210                 str_info->ctrl_blk.data = lib_dnld;
211                 str_info->ctrl_blk.condition = true;
212                 str_info->ctrl_blk.ret_code = resp->str_type.result;
213                 pr_debug("SST DEBUG: sst_alloc_stream_response: waking up.\n");
214                 wake_up(&sst_drv_ctx->wait_queue);
215         }
216         return retval;
217 }
218
219
220 /**
221 * sst_get_fw_info - Send msg to query for firmware configurations
222 * @info: out param that holds the firmare configurations
223 *
224 * This function is called when the firmware configurations are queiried for
225 */
226 int sst_get_fw_info(struct snd_sst_fw_info *info)
227 {
228         int retval = 0;
229         struct ipc_post *msg = NULL;
230
231         pr_debug("SST DBG:sst_get_fw_info called\n");
232
233         if (sst_create_short_msg(&msg)) {
234                 pr_err("SST ERR: message creation failed\n");
235                 return -ENOMEM;
236         }
237
238         sst_fill_header(&msg->header, IPC_IA_GET_FW_INFO, 0, 0);
239         sst_drv_ctx->fw_info_blk.condition = false;
240         sst_drv_ctx->fw_info_blk.ret_code = 0;
241         sst_drv_ctx->fw_info_blk.on = true;
242         sst_drv_ctx->fw_info_blk.data = info;
243         spin_lock(&sst_drv_ctx->list_spin_lock);
244         list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
245         spin_unlock(&sst_drv_ctx->list_spin_lock);
246         sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
247         retval = sst_wait_interruptible_timeout(sst_drv_ctx,
248                         &sst_drv_ctx->fw_info_blk, SST_BLOCK_TIMEOUT);
249         if (retval) {
250                 pr_err("SST ERR: error in fw_info = %d\n", retval);
251                 retval = -EIO;
252         }
253         return retval;
254 }
255
256
257 /**
258 * sst_pause_stream - Send msg for a pausing stream
259 * @str_id:       stream ID
260 *
261 * This function is called by any function which wants to pause
262 * an already running stream.
263 */
264 int sst_start_stream(int str_id)
265 {
266         int retval = 0;
267         struct ipc_post *msg = NULL;
268         struct stream_info *str_info;
269
270         pr_debug("sst_start_stream for %d\n", str_id);
271         retval = sst_validate_strid(str_id);
272         if (retval)
273                 return retval;
274         str_info = &sst_drv_ctx->streams[str_id];
275         if (str_info->status != STREAM_INIT)
276                 return -EBADRQC;
277         if (sst_create_short_msg(&msg))
278                 return -ENOMEM;
279
280         sst_fill_header(&msg->header, IPC_IA_START_STREAM, 0, str_id);
281         spin_lock(&sst_drv_ctx->list_spin_lock);
282         list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
283         spin_unlock(&sst_drv_ctx->list_spin_lock);
284         sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
285         return retval;
286 }
287
288 /*
289  * sst_pause_stream - Send msg for a pausing stream
290  * @str_id:      stream ID
291  *
292  * This function is called by any function which wants to pause
293  * an already running stream.
294  */
295 int sst_pause_stream(int str_id)
296 {
297         int retval = 0;
298         struct ipc_post *msg = NULL;
299         struct stream_info *str_info;
300
301         pr_debug("SST DBG:sst_pause_stream for %d\n", str_id);
302         retval = sst_validate_strid(str_id);
303         if (retval)
304                 return retval;
305         str_info = &sst_drv_ctx->streams[str_id];
306         if (str_info->status == STREAM_PAUSED)
307                 return 0;
308         if (str_info->status == STREAM_RUNNING ||
309                 str_info->status == STREAM_INIT) {
310                 if (str_info->prev == STREAM_UN_INIT)
311                         return -EBADRQC;
312                 if (str_info->ctrl_blk.on == true) {
313                         pr_err("SST ERR: control path is in use\n");
314                         return -EINVAL;
315                 }
316                 if (sst_create_short_msg(&msg))
317                         return -ENOMEM;
318
319                 sst_fill_header(&msg->header, IPC_IA_PAUSE_STREAM, 0, str_id);
320                 str_info->ctrl_blk.condition = false;
321                 str_info->ctrl_blk.ret_code = 0;
322                 str_info->ctrl_blk.on = true;
323                 spin_lock(&sst_drv_ctx->list_spin_lock);
324                 list_add_tail(&msg->node,
325                                 &sst_drv_ctx->ipc_dispatch_list);
326                 spin_unlock(&sst_drv_ctx->list_spin_lock);
327                 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
328                 retval = sst_wait_interruptible_timeout(sst_drv_ctx,
329                                 &str_info->ctrl_blk, SST_BLOCK_TIMEOUT);
330                 if (retval == 0) {
331                         str_info->prev = str_info->status;
332                         str_info->status = STREAM_PAUSED;
333                 } else if (retval == SST_ERR_INVALID_STREAM_ID) {
334                         retval = -EINVAL;
335                         mutex_lock(&sst_drv_ctx->stream_lock);
336                         sst_clean_stream(str_info);
337                         mutex_unlock(&sst_drv_ctx->stream_lock);
338                 }
339         } else {
340                 retval = -EBADRQC;
341                 pr_err("SST ERR: BADQRC for stream\n");
342         }
343
344         return retval;
345 }
346
347 /**
348  * sst_resume_stream - Send msg for resuming stream
349  * @str_id:             stream ID
350  *
351  * This function is called by any function which wants to resume
352  * an already paused stream.
353  */
354 int sst_resume_stream(int str_id)
355 {
356         int retval = 0;
357         struct ipc_post *msg = NULL;
358         struct stream_info *str_info;
359
360         pr_debug("SST DBG:sst_resume_stream for %d\n", str_id);
361         retval = sst_validate_strid(str_id);
362         if (retval)
363                 return retval;
364         str_info = &sst_drv_ctx->streams[str_id];
365         if (str_info->status == STREAM_RUNNING)
366                         return 0;
367         if (str_info->status == STREAM_PAUSED) {
368                 if (str_info->ctrl_blk.on == true) {
369                         pr_err("SST ERR: control path in use\n");
370                         return -EINVAL;
371                 }
372                 if (sst_create_short_msg(&msg)) {
373                         pr_err("SST ERR: mem allocation failed\n");
374                         return -ENOMEM;
375                 }
376                 sst_fill_header(&msg->header, IPC_IA_RESUME_STREAM, 0, str_id);
377                 str_info->ctrl_blk.condition = false;
378                 str_info->ctrl_blk.ret_code = 0;
379                 str_info->ctrl_blk.on = true;
380                 spin_lock(&sst_drv_ctx->list_spin_lock);
381                 list_add_tail(&msg->node,
382                                 &sst_drv_ctx->ipc_dispatch_list);
383                 spin_unlock(&sst_drv_ctx->list_spin_lock);
384                 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
385                 retval = sst_wait_interruptible_timeout(sst_drv_ctx,
386                                 &str_info->ctrl_blk, SST_BLOCK_TIMEOUT);
387                 if (!retval) {
388                         if (str_info->prev == STREAM_RUNNING)
389                                 str_info->status = STREAM_RUNNING;
390                         else
391                                 str_info->status = STREAM_INIT;
392                         str_info->prev = STREAM_PAUSED;
393                 } else if (retval == -SST_ERR_INVALID_STREAM_ID) {
394                         retval = -EINVAL;
395                         mutex_lock(&sst_drv_ctx->stream_lock);
396                         sst_clean_stream(str_info);
397                         mutex_unlock(&sst_drv_ctx->stream_lock);
398                 }
399         } else {
400                 retval = -EBADRQC;
401                 pr_err("SST ERR: BADQRC for stream\n");
402         }
403
404         return retval;
405 }
406
407
408 /**
409  * sst_drop_stream - Send msg for stopping stream
410  * @str_id:             stream ID
411  *
412  * This function is called by any function which wants to stop
413  * a stream.
414  */
415 int sst_drop_stream(int str_id)
416 {
417         int retval = 0;
418         struct ipc_post *msg = NULL;
419         struct sst_stream_bufs *bufs = NULL, *_bufs;
420         struct stream_info *str_info;
421
422         pr_debug("SST DBG:sst_drop_stream for %d\n", str_id);
423         retval = sst_validate_strid(str_id);
424         if (retval)
425                 return retval;
426         str_info = &sst_drv_ctx->streams[str_id];
427
428         if (str_info->status != STREAM_UN_INIT &&
429                 str_info->status != STREAM_DECODE) {
430                 if (str_info->ctrl_blk.on == true) {
431                         pr_err("SST ERR: control path in use\n");
432                         return -EINVAL;
433                 }
434                 if (sst_create_short_msg(&msg)) {
435                         pr_err("SST ERR: mem allocation failed\n");
436                         return -ENOMEM;
437                 }
438                 sst_fill_header(&msg->header, IPC_IA_DROP_STREAM, 0, str_id);
439                 str_info->ctrl_blk.condition = false;
440                 str_info->ctrl_blk.ret_code = 0;
441                 str_info->ctrl_blk.on = true;
442                 spin_lock(&sst_drv_ctx->list_spin_lock);
443                 list_add_tail(&msg->node,
444                                 &sst_drv_ctx->ipc_dispatch_list);
445                 spin_unlock(&sst_drv_ctx->list_spin_lock);
446                 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
447                 retval = sst_wait_interruptible_timeout(sst_drv_ctx,
448                                 &str_info->ctrl_blk, SST_BLOCK_TIMEOUT);
449                 if (!retval) {
450                         pr_debug("SST DBG:drop success\n");
451                         str_info->prev = STREAM_UN_INIT;
452                         str_info->status = STREAM_INIT;
453                         if (str_info->src != MAD_DRV) {
454                                 mutex_lock(&str_info->lock);
455                                 list_for_each_entry_safe(bufs, _bufs,
456                                                         &str_info->bufs, node) {
457                                         list_del(&bufs->node);
458                                         kfree(bufs);
459                                 }
460                                 mutex_unlock(&str_info->lock);
461                         }
462                         str_info->cumm_bytes += str_info->curr_bytes;
463                 } else if (retval == -SST_ERR_INVALID_STREAM_ID) {
464                         retval = -EINVAL;
465                         mutex_lock(&sst_drv_ctx->stream_lock);
466                         sst_clean_stream(str_info);
467                         mutex_unlock(&sst_drv_ctx->stream_lock);
468                 }
469                 if (str_info->data_blk.on == true) {
470                         str_info->data_blk.condition = true;
471                         str_info->data_blk.ret_code = retval;
472                         wake_up(&sst_drv_ctx->wait_queue);
473                 }
474         } else {
475                 retval = -EBADRQC;
476                 pr_err("SST ERR: BADQRC for stream\n");
477         }
478         return retval;
479 }
480
481 /**
482 * sst_drain_stream - Send msg for draining stream
483 * @str_id:              stream ID
484 *
485 * This function is called by any function which wants to drain
486 * a stream.
487 */
488 int sst_drain_stream(int str_id)
489 {
490         int retval = 0;
491         struct ipc_post *msg = NULL;
492         struct stream_info *str_info;
493
494         pr_debug("SST DBG:sst_drain_stream for %d\n", str_id);
495         retval = sst_validate_strid(str_id);
496         if (retval)
497                 return retval;
498         str_info = &sst_drv_ctx->streams[str_id];
499
500         if (str_info->status != STREAM_RUNNING &&
501                 str_info->status != STREAM_INIT &&
502                 str_info->status != STREAM_PAUSED) {
503                         pr_err("SST ERR: BADQRC for stream = %d\n",
504                                        str_info->status);
505                         return -EBADRQC;
506         }
507
508         if (str_info->status == STREAM_INIT) {
509                 if (sst_create_short_msg(&msg)) {
510                         pr_err("SST ERR: mem allocation failed\n");
511                         return -ENOMEM;
512                 }
513                 sst_fill_header(&msg->header, IPC_IA_DRAIN_STREAM, 0, str_id);
514                 spin_lock(&sst_drv_ctx->list_spin_lock);
515                 list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
516                 spin_unlock(&sst_drv_ctx->list_spin_lock);
517                 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
518         } else
519                 str_info->need_draining = true;
520         str_info->data_blk.condition = false;
521         str_info->data_blk.ret_code = 0;
522         str_info->data_blk.on = true;
523         retval = sst_wait_interruptible(sst_drv_ctx, &str_info->data_blk);
524         str_info->need_draining = false;
525         return retval;
526 }
527
528 /**
529  * sst_free_stream - Frees a stream
530  * @str_id:             stream ID
531  *
532  * This function is called by any function which wants to free
533  * a stream.
534  */
535 int sst_free_stream(int str_id)
536 {
537         int retval = 0;
538         struct ipc_post *msg = NULL;
539         struct stream_info *str_info;
540
541         pr_debug("SST DBG:sst_free_stream for %d\n", str_id);
542
543         retval = sst_validate_strid(str_id);
544         if (retval)
545                 return retval;
546         str_info = &sst_drv_ctx->streams[str_id];
547
548         if (str_info->status != STREAM_UN_INIT) {
549                 if (sst_create_short_msg(&msg)) {
550                         pr_err("SST ERR: mem allocation failed\n");
551                         return -ENOMEM;
552                 }
553                 sst_fill_header(&msg->header, IPC_IA_FREE_STREAM, 0, str_id);
554                 spin_lock(&sst_drv_ctx->list_spin_lock);
555                 list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list);
556                 spin_unlock(&sst_drv_ctx->list_spin_lock);
557                 sst_post_message(&sst_drv_ctx->ipc_post_msg_wq);
558                 str_info->prev =  str_info->status;
559                 str_info->status = STREAM_UN_INIT;
560                 if (str_info->data_blk.on == true) {
561                         str_info->data_blk.condition = true;
562                         str_info->data_blk.ret_code = 0;
563                         wake_up(&sst_drv_ctx->wait_queue);
564                 }
565                 str_info->data_blk.on = true;
566                 str_info->data_blk.condition = false;
567                 retval = sst_wait_interruptible_timeout(sst_drv_ctx,
568                                 &str_info->ctrl_blk, SST_BLOCK_TIMEOUT);
569                 pr_debug("wait for free returned %d\n", retval);
570                 msleep(100);
571                 mutex_lock(&sst_drv_ctx->stream_lock);
572                 sst_clean_stream(str_info);
573                 mutex_unlock(&sst_drv_ctx->stream_lock);
574                 pr_debug("SST DBG:Stream freed\n");
575         } else {
576                 retval = -EBADRQC;
577                 pr_debug("SST DBG:BADQRC for stream\n");
578         }
579
580         return retval;
581 }
582
583