Skip to content

dmic: write back OUTSTATx in irq handler - #4287

Closed
kv2019i wants to merge 1 commit into
thesofproject:mainfrom
kv2019i:topic/dmic-outstat-ack
Closed

kv2019i wants to merge 1 commit into
thesofproject:mainfrom
kv2019i:topic/dmic-outstat-ack

Conversation

@kv2019i

@kv2019i kv2019i commented Jun 3, 2021

Copy link
Copy Markdown
Collaborator

Write back OUTSTATx bits whenever interrupt is raised and
not just when ROR_BIT is set.

Signed-off-by: Kai Vehmanen kai.vehmanen@linux.intel.com

Write back OUTSTATx bits whenever interrupt is raised and
not just when ROR_BIT is set.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
@kv2019i
kv2019i requested review from lgirdwood and singalsu June 3, 2021 15:03
@kv2019i

kv2019i commented Jun 3, 2021

Copy link
Copy Markdown
Collaborator Author

Not sure this is correct thing to do, but this avoids the IRQ floods I get with multiple-pause-resume.sh sof-test on Zephyr builds.

@kv2019i
kv2019i requested a review from keyonjie June 3, 2021 15:05

@lgirdwood lgirdwood left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kv2019i this look right to me as a "Read to Clear" and should be in rc3/final. @keyonjie fyi.
@singalsu any comments ?

@singalsu singalsu left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice finding! Thanks!

Comment thread src/drivers/intel/dmic.c
dmic_stop(dai, dmic->state == COMP_STATE_ACTIVE);
dmic->state = COMP_STATE_PREPARE;
}
dai_write(dai, OUTSTAT0, val0);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this changes the sequence for error handling, should you move the two writes before the tests and factor the two dmic_stop?

e.g.

needs_stop = false;
val0 = dai_read(dai, OUTSTAT0);
val1 = dai_read(dai, OUTSTAT1);

dai_write(dai, OUTSTAT0, val0);
dai_write(dai, OUTSTAT1, val1);

if (val0 & OUTSTAT0_ROR_BIT) {
    dai_err(dai, "dmic_irq_handler(): full fifo A or PDM overrun");
    needs_stop = true;
}

if (val1 & OUTSTAT1_ROR_BIT) {
    dai_err(dai, "dmic_irq_handler(): full fifo B or PDM overrun");
    needs_stop = true;
}

if (needs_stop) {
    dmic_stop(dai, dmic->state == COMP_STATE_ACTIVE);
    dmic->state = COMP_STATE_PREPARE;
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack, thanks @plbossart . I'll do a non-draft cleanup version. I'm also not 100% sure calling dmic_stop() is safe here. To me it seems possible that a dmic interrupt is raised while a DSP core is already running dmic_stop() (for normal pipeline stop).

I think the primary reason to stop the dmic here (rather than relying on pipeline xrun handling) is to avoid spamming the trace log when a xrun happens.

@keyonjie

keyonjie commented Jun 4, 2021

Copy link
Copy Markdown
Contributor

@kv2019i @singalsu sorry I don't understand the logic here, only the xrun bit of the whole register is writable, if the xrun bit is not set which means there is no this kind of xrun actually, why we should write back it? and write back bit 0 actually won't clear any interrupts for us no?

@keyonjie

keyonjie commented Jun 4, 2021 •

Copy link
Copy Markdown
Contributor

if we do hit interrupt storm, I would suspect if the previous interrupt clearing or dmic_stop() work actually correctly, e.g. add a polling to the xrun bit or the SIP/FINIT bits to double confirm the clearing and stopping do success.

@singalsu one more point is that we should check (and clear) the OUTSTAT for the corresponding dai only, e.g.

static void dmic_irq_handler(void *data)
{
	struct dai *dai = data;
        uint32_t reg = dai->index ? OUTSTAT1 : OUTSTAT0;
	uint32_t val;

	/* Trace OUTSTAT register */
	val= dai_read(dai, reg);
	dai_info(dai, "dmic_irq_handler(), OUTSTAT = 0x%x",
		 val);

	if (val & BIT(27)) {
		dai_err(dai, "dmic_irq_handler(): full fifo or PDM xrun for dai %d", index);
		dai_write(dai, reg, val);
		dmic_stop(dai);
	}
}

@kv2019i

kv2019i commented Jun 4, 2021

Copy link
Copy Markdown
Collaborator Author

Cross-checked with hw spec and this change is not needed. ROR is the only writable bit, so original logic is correct.

The problem I was seeing is fixed by #4297 instead. Closing this one.

@kv2019i kv2019i closed this Jun 4, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants