On Fri, Nov 12, 2010 at 1:35 PM, Jaroslav Kysela <perex@xxxxxxxx> wrote: > On Fri, 12 Nov 2010, Manu Abraham wrote: > >> On Thu, Nov 11, 2010 at 6:04 PM, Manu Abraham <abraham.manu@xxxxxxxxx> >> wrote: >>> >>> On Thu, Nov 11, 2010 at 4:00 PM, Jaroslav Kysela <perex@xxxxxxxx> wrote: >>>> >>>> On Thu, 11 Nov 2010, Manu Abraham wrote: >>>> >>>>> On Wed, Nov 10, 2010 at 11:35 PM, Jaroslav Kysela <perex@xxxxxxxx> >>>>> wrote: >>> >>>>> >>>>> I adapted the whole thing to make the buffersize divided amongst the >>>>> XS2D_BUFFERS (8): >>>> >>>> Probably yes. >>>> >>>>> I hope the mapping of the buffers is okay ? It looks thus, now .. >>>> >>>> From information you sent me about hw privately, I think that the >>>> period_bytes must be 4096 or multiple of this value with minumum count >>>> of >>>> periods 8 (or multiple of 8). Otherwise you get a non-continuous memory >>>> area >>>> (the hw uses only portion of system memory page, thus there'll be gaps). >>>> The >>>> problem is that we have MMAP_COMPLEX mode, but no application can handle >>>> (does not implement) this mmap mode and I'm not sure, if we can even >>>> describe the DMA buffer size layout for this case for your specific hw. >>>> >>>> I would use: >>>> >>>> Â Â Â Âsnd_pcm_hw_constraint_step(runtime, 0, >>>> SNDRV_PCM_HW_PARAM_PERIOD_BYTES, >>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â4096); >>>> >>>> >>>> Â Â Â Âsnd_pcm_hw_constraint_step(runtime, 0, >>>> SNDRV_PCM_HW_PARAM_PERIODS, >>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 8); >>>> >>>> And define periods_min = 8 (max to multiple 8 - choose your max limit) >>>> and >>>> period_bytes_min to 4096 (max to multiple 4096 - choose your max limit). >>>> >>>> Note that -EIO means that your driver does not called >>>> snd_pcm_period_elapsed() and/or the pointer callback returns wrong >>>> position >>>> to the audio ring buffer. >>> >>> >>> >>> Ok, modified it, also added in code to acquire the stream, It's a bit >>> more complete now. >>> The crazy part that I do see now, is that I see an inconsistent lock >>> state with the hda_intel >>> driver which is the soundcard on my system. But I don't understand why >>> the locking on it >>> has to become inconsistent on loading this driver. >> >> >> Ok, I found the reason: I was passing a single page for the >> page_table, which I guess corrupted the whole stack !! >> >> Eventually, I fixed the same. but ran into another issue ? Should >> trigger not sleep or something that way ? >> Currently, I see the issue as follows in the log, but if the >> ops->run() callback is commented out I don't get that >> weird message/error about lock states. >> >> Now, ops->run(), ie xs2dtl_run() is called with other other streams, >> such as an MPEG stream, where it doesn't >> show any issues. >> >> Any idea, why uncommenting ops->run() produces that message ? Should >> trigger not sleep ? Confused ... > > Trigger must be fast without any sleeping. Only fast spinlocks are allowed. > If you need sleep, just activate a tasklet and do the start job in the > tasklet or a thread. Ok, I have now a tasklet to handle the commands. But still I do have the same issue. if i comment out ops->run() things do look sane. But with the tasklet, also added in, I can see the same error, but almost immediately, the machine freezes completely. I see quite a lot of junk in the syslog, looks like there has been memory corruption. Any idea, what could be going wrong ? static int saa7231_hw_params(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params) { struct saa7231_audio *audio = snd_pcm_substream_chip(pcm); struct saa7231_dev *saa7231 = audio->saa7231; struct snd_pcm_runtime *rt = pcm->runtime; struct saa7231_dmabuf *buffer; struct saa7231_stream *stream; struct saa7231_dmabuf *dmabuf; struct page **ptable; void *mem; void *dma_area; int i, j, pages, bytes, periods, bufsiz, idx; #define MAX_ENTRIES_PER_PAGE (PAGE_SIZE / 8) #define PAGES_PER_XS2D(__pages) (__pages / XS2D_BUFFERS) #define BUFSIZE_PER_XS2D(__size) (__size / XS2D_BUFFERS) dprintk(SAA7231_DEBUG, 1, "DEBUG: ()"); periods = params_periods(params); bytes = params_period_bytes(params); bufsiz = params_buffer_bytes(params); pages = snd_sgbuf_aligned_pages(bufsiz); audio->bufsize = bufsiz; dprintk(SAA7231_DEBUG, 1, "bufsiz=%d periods=%d bytes=%d pages=%d", bufsiz, periods, bytes, pages); /* enable stream */ /* initializing 8 buffer with "pages" pages each .. */ stream = saa7231_stream_init(saa7231, AUDIO_CAPTURE, ADAPTER_INT, 0, (pages / XS2D_BUFFERS)); if (!stream) { dprintk(SAA7231_ERROR, 1, "ERROR: Registering stream"); return -ENOMEM; } audio->stream = stream; buffer = stream->dmabuf; saa7231_add_irqevent(saa7231, 43, SAA7231_EDGE_RISING, saa7231_audio_evhandler, "AS2D_AVIS"); dprintk(SAA7231_DEBUG, 1, "Mapping %d buffers with %d pages each", XS2D_BUFFERS, PAGES_PER_XS2D(pages)); dprintk(SAA7231_DEBUG, 1, "Page Table array size=%d", pages); ptable = kzalloc((sizeof (struct page) * pages), GFP_KERNEL); if (!ptable) { dprintk(SAA7231_ERROR, 1, "ERROR: No memory to allocate virtual map"); return -ENOMEM; } audio->ptable = ptable; idx = 0; for (i = 0; i < XS2D_BUFFERS; i ++) { dmabuf = &buffer[i]; mem = dmabuf->vmalloc; for (j = 0; j < PAGES_PER_XS2D(pages); j++) { BUG_ON(idx > pages); dprintk(SAA7231_DEBUG, 1, "Mapping Page:%d from XS2D_BUFFER:%d to PTA Offset:%d", j, i, idx); ptable[idx] = virt_to_page(mem); mem += PAGE_SIZE; idx += 1; } } dma_area = vmap(ptable, pages, VM_MAP, PAGE_KERNEL); rt->dma_area = dma_area; rt->dma_bytes = pages * PAGE_SIZE; rt->dma_addr = 0; return 0; } static void saa7231_cmd_tasklet(unsigned long data) { struct saa7231_audio *audio = (struct saa7231_audio *) data; struct saa7231_dev *saa7231 = audio->saa7231; struct saa7231_stream *stream = audio->stream; struct stream_ops *ops = &stream->ops; int cmd = audio->cmd; int err = 0; switch (cmd) { case SNDRV_PCM_TRIGGER_START: dprintk(SAA7231_DEBUG, 1, "Trying to START stream, cmd=%d", cmd); if (ops->run) { err = ops->run(stream); if (err) { dprintk(SAA7231_ERROR, 1, "ERROR: starting stream, err=%d", err); // return -EIO; } } break; case SNDRV_PCM_TRIGGER_STOP: dprintk(SAA7231_DEBUG, 1, "Trying to STOP stream, cmd=%d", cmd); if (ops->stop) { err = ops->stop(stream); if (err) { dprintk(SAA7231_ERROR, 1, "ERROR: stopping stream, err=%d", err); // return -EIO; } } break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_SUSPEND: dprintk(SAA7231_DEBUG, 1, "Trying to PAUSE stream, cmd=%d", cmd); if (ops->pause) { err = ops->pause(stream); if (err) { dprintk(SAA7231_ERROR, 1, "ERROR: pausing stream, err=%d", err); // return -EIO; } } break; default: dprintk(SAA7231_DEBUG, 1, "Unknown command, cmd=%d", cmd); snd_BUG(); // return -EINVAL; } } /* * saa7231_capture_trigger() * * This callback is called when the PCM is started, stoppped or paused. */ static int saa7231_capture_trigger(struct snd_pcm_substream *pcm, int cmd) { struct saa7231_audio *audio = snd_pcm_substream_chip(pcm); struct saa7231_dev *saa7231 = audio->saa7231; dprintk(SAA7231_DEBUG, 1, "Scheduling cmd tasklet with cmd=%d", cmd); audio->cmd = cmd; tasklet_schedule(&audio->cmd_tasklet); return 0; } static snd_pcm_uframes_t saa7231_capture_pointer(struct snd_pcm_substream *pcm) { struct saa7231_audio *audio = snd_pcm_substream_chip(pcm); struct saa7231_dev *saa7231 = audio->saa7231; dprintk(SAA7231_DEBUG, 1, "DEBUG:()"); return 0; //bytes_to_frames(rt, played); } int saa7231_alsa_init(struct saa7231_dev *saa7231) { int err; struct snd_card *card; struct saa7231_audio *audio; struct saa7231_config *config = saa7231->config; struct card_desc *desc = config->desc; dprintk(SAA7231_DEBUG, 1, "Initializing Audio .."); audio = kzalloc(sizeof (struct saa7231_audio), GFP_KERNEL); if (!audio) { dprintk(SAA7231_ERROR, 1, "ERROR: Out of memory, audio=NULL"); return -ENOMEM; } err = snd_card_create(index[saa7231->num], id[saa7231->num], THIS_MODULE, 0, &card); if (err < 0) { dprintk(SAA7231_ERROR, 1, "snd_card_create() failed, err=%d", err); return err; } saa7231->audio = audio; audio->saa7231 = saa7231; audio->card = card; err = snd_saa7231_pcm_init(audio); if (err) { dprintk(SAA7231_ERROR, 1, "PCM Initialization failed, err=%d", err); return err; } err = snd_saa7231_mixer_init(audio); if (err) { dprintk(SAA7231_ERROR, 1, "Mixer initialization failed, err=%d", err); return err; } snd_card_set_dev(card, &saa7231->pdev->dev); strcpy(card->driver, "SAA7231"); sprintf(card->shortname, "%s-%d", desc->product, saa7231->num); sprintf(card->mixername, "%s", saa7231->name); sprintf(card->longname, "%s %s (%s) @ 0x%p, irq %i", desc->vendor, desc->product, card->shortname, saa7231->mmio1, saa7231->pdev->irq); err = snd_card_register(card); if (err) { dprintk(SAA7231_ERROR, 1, "Sound Card registration failed, err=%d", err); return err; } tasklet_init(&audio->cmd_tasklet, saa7231_cmd_tasklet, (unsigned long) audio); return 0; } testbox ~ # cat /var/log/messages ginInfo-AllowEmptySettings.X-KDE-PluginInfo-Author 2X-KDE-PluginInfo-Category 0X-KDE-PluginInfo-Depends ,X-KDE-PluginInfo-Email BX-KDE-PluginInfo-EnabledByDefault4X-KDE-PluginInfo-Immutable0X-KDE-PluginInfo-License *X-KDE-PluginInfo-Name 0X-KDE-PluginInfo-Version 0X-KDE-PluginInfo-Website X-KDE-PriorityX-KDE-Protocol X-KDE-Protocols X-KDE-Read(X-KDE-ResourceFamily $X-KDE-ResourceType <X-KDE-SolidBackendInfo-Version &X-KDE-StartupNotify&X-KDE-SubstituteUID<X-KDE-System-Settings-Category JX-KDE-System-Settings-Parent-Category X-KDE-Type ,X-KDE-UA-DYNAMIC-ENTRYâX-KDE-UA-FULL âX-KDE-UA-NAME X-KDE-UA-SYSNAME &X-KDE-UA-SYSRELEASE âX-KDE-UA-TAG X-KDE-UA-VERSION X-KDE-Username âX-KDE-VersionâX-KDE-WMClass âX-KDE-WeightX-KDE-Write,X-KDE-okularAPIVersion>X-KDE-okularHasInternalSettingsX-KIPI-Id "X-KIPI-Interfaces X-KIPI-Mimetypes $X-KIPI-ReqFeatures (X-Kate-MajorProfiles Thanks, Manu _______________________________________________ Alsa-devel mailing list Alsa-devel@xxxxxxxxxxxxxxxx http://mailman.alsa-project.org/mailman/listinfo/alsa-devel