Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions sound/soc/sof/intel/byt.c
Original file line number Diff line number Diff line change
Expand Up @@ -689,8 +689,22 @@ static int byt_pci_probe(struct snd_sof_dev *sdev)
dev_dbg(sdev->dev, "IMR VADDR %p\n", sdev->bar[BYT_IMR_BAR]);

irq:
/* register our IRQ */
sdev->ipc_irq = pci->irq;
/*
* register our IRQ
* let's try to enable msi firstly
* if it fails, use legacy interrupt mode
* TODO: support interrupt mode selection with kernel parameter
* support msi multiple vectors
*/
ret = pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_MSI);
if (ret < 0) {
dev_info(sdev->dev, "use legacy interrupt mode\n");
sdev->ipc_irq = pci->irq;
} else {
dev_info(sdev->dev, "use msi interrupt mode\n");
sdev->ipc_irq = pci_irq_vector(pci, 0);
}

dev_dbg(sdev->dev, "using IRQ %d\n", sdev->ipc_irq);
ret = request_threaded_irq(sdev->ipc_irq, byt_irq_handler,
byt_irq_thread, 0, "AudioDSP", sdev);
Expand All @@ -714,6 +728,7 @@ static int byt_pci_probe(struct snd_sof_dev *sdev)

irq_err:
iounmap(sdev->bar[BYT_IMR_BAR]);
pci_free_irq_vectors(pci);
imr_err:
iounmap(sdev->bar[BYT_DSP_BAR]);
return ret;
Expand All @@ -738,7 +753,10 @@ static int byt_acpi_remove(struct snd_sof_dev *sdev)

static int byt_pci_remove(struct snd_sof_dev *sdev)
{
struct pci_dev *pci = sdev->pci;

free_irq(sdev->ipc_irq, sdev);
pci_free_irq_vectors(pci);
return 0;
}

Expand Down
33 changes: 25 additions & 8 deletions sound/soc/sof/intel/hda.c
Original file line number Diff line number Diff line change
Expand Up @@ -446,20 +446,34 @@ int hda_dsp_probe(struct snd_sof_dev *sdev)
SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN,
SOF_HDA_INT_CTRL_EN | SOF_HDA_INT_GLOBAL_EN);

dev_dbg(sdev->dev, "using PCI IRQ %d\n", pci->irq);
/*
* register our IRQ
* let's try to enable msi firstly
* if it fails, use legacy interrupt mode
* TODO: support interrupt mode selection with kernel parameter
Copy link
Member

Choose a reason for hiding this comment

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

what does it take to add this? the kernel parameter doesn't seem very complicated, but I don't know what the multiple vectors mean in terms of functionality/schedule?

Copy link
Author

Choose a reason for hiding this comment

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

kernel parameter is not a must feature. It offers a choice to user to change the default behavior. There is no requirement so far and I didn't implement it. I think we can implement it only when we have such requirement, such as MSI is supported but doesn't work. In this case we need a quirk to let user set the default mode is legacy interrupt mode.
Multiple vectors is a feature of MSI, with this feature, device can offer multiple irq number. I checked on apl, and it only uses 1. To enable multiple msi vectors, the code will be a little complicated. I don't have platform to test multiple msi vectors, so I enable the single multiple currently.

* support msi multiple vectors
*/
ret = pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_MSI);
if (ret < 0) {
dev_info(sdev->dev, "use legacy interrupt mode\n");
sdev->hda->irq = pci->irq;
sdev->ipc_irq = pci->irq;
} else {
dev_info(sdev->dev, "use msi interrupt mode\n");
sdev->hda->irq = pci_irq_vector(pci, 0);
Copy link
Member

Choose a reason for hiding this comment

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

can you change this to avoid two calls, pci_irq_vector isn't a small function:

int pci_irq_vector(struct pci_dev *dev, unsigned int nr)
{
if (dev->msix_enabled) {
struct msi_desc *entry;
int i = 0;

	for_each_pci_msi_entry(entry, dev) {
		if (i == nr)
			return entry->irq;
		i++;
	}
	WARN_ON_ONCE(1);
	return -EINVAL;
}

if (dev->msi_enabled) {
	struct msi_desc *entry = first_pci_msi_entry(dev);

	if (WARN_ON_ONCE(nr >= entry->nvec_used))
		return -EINVAL;
} else {
	if (WARN_ON_ONCE(nr > 0))
		return -EINVAL;
}

return dev->irq + nr;

}
EXPORT_SYMBOL(pci_irq_vector);

Copy link
Author

Choose a reason for hiding this comment

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

It makes sense. I will do it :)

sdev->ipc_irq = pci_irq_vector(pci, 0);
}

/* register our IRQ */
ret = request_threaded_irq(pci->irq, hda_dsp_stream_interrupt,
dev_dbg(sdev->dev, "using HDA IRQ %d\n", sdev->hda->irq);
ret = request_threaded_irq(sdev->hda->irq, hda_dsp_stream_interrupt,
hda_dsp_stream_threaded_handler,
IRQF_SHARED, "AudioHDA", sdev);
IRQF_SHARED, "AudioHDA", sdev);
if (ret < 0) {
dev_err(sdev->dev, "error: failed to register HDA IRQ %d\n",
sdev->ipc_irq);
sdev->hda->irq);
goto stream_err;
}
sdev->hda->irq = pci->irq;

sdev->ipc_irq = pci->irq;
dev_dbg(sdev->dev, "using IPC IRQ %d\n", sdev->ipc_irq);
ret = request_threaded_irq(sdev->ipc_irq, hda_dsp_ipc_irq_handler,
chip->ops->irq_thread, IRQF_SHARED,
Expand Down Expand Up @@ -494,8 +508,9 @@ int hda_dsp_probe(struct snd_sof_dev *sdev)
return 0;

irq_err:
free_irq(pci->irq, sdev);
free_irq(sdev->hda->irq, sdev);
stream_err:
pci_free_irq_vectors(pci);
hda_dsp_stream_free(sdev);
err:
/* disable DSP */
Expand All @@ -506,6 +521,7 @@ int hda_dsp_probe(struct snd_sof_dev *sdev)

int hda_dsp_remove(struct snd_sof_dev *sdev)
{
struct pci_dev *pci = sdev->pci;
const struct sof_intel_dsp_desc *chip = sdev->hda->desc;

/* disable DSP IRQ */
Expand All @@ -526,6 +542,7 @@ int hda_dsp_remove(struct snd_sof_dev *sdev)

free_irq(sdev->ipc_irq, sdev);
free_irq(sdev->pci->irq, sdev);
pci_free_irq_vectors(pci);

hda_dsp_stream_free(sdev);
return 0;
Expand Down