Commit ce4f2575 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: asihpi: Replace tasklet with threaded irq

The tasklet is an old API that should be deprecated, usually can be
converted to another decent API.  In ASIHPI driver, a tasklet is
still used for offloading the PCM IRQ handling.  It can be achieved
gracefully with a threaded IRQ, too.

This patch replaces the tasklet usage in asihpi driver with a threaded
IRQ.  It also simplified some call patterns.

Link: https://lore.kernel.org/r/20200903104131.21097-10-tiwai@suse.deSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 2ac55daf
...@@ -117,7 +117,6 @@ struct snd_card_asihpi { ...@@ -117,7 +117,6 @@ struct snd_card_asihpi {
* snd_card_asihpi_timer_function(). * snd_card_asihpi_timer_function().
*/ */
struct snd_card_asihpi_pcm *llmode_streampriv; struct snd_card_asihpi_pcm *llmode_streampriv;
struct tasklet_struct t;
void (*pcm_start)(struct snd_pcm_substream *substream); void (*pcm_start)(struct snd_pcm_substream *substream);
void (*pcm_stop)(struct snd_pcm_substream *substream); void (*pcm_stop)(struct snd_pcm_substream *substream);
...@@ -547,9 +546,7 @@ static void snd_card_asihpi_pcm_int_start(struct snd_pcm_substream *substream) ...@@ -547,9 +546,7 @@ static void snd_card_asihpi_pcm_int_start(struct snd_pcm_substream *substream)
card = snd_pcm_substream_chip(substream); card = snd_pcm_substream_chip(substream);
WARN_ON(in_interrupt()); WARN_ON(in_interrupt());
tasklet_disable(&card->t);
card->llmode_streampriv = dpcm; card->llmode_streampriv = dpcm;
tasklet_enable(&card->t);
hpi_handle_error(hpi_adapter_set_property(card->hpi->adapter->index, hpi_handle_error(hpi_adapter_set_property(card->hpi->adapter->index,
HPI_ADAPTER_PROPERTY_IRQ_RATE, HPI_ADAPTER_PROPERTY_IRQ_RATE,
...@@ -565,13 +562,7 @@ static void snd_card_asihpi_pcm_int_stop(struct snd_pcm_substream *substream) ...@@ -565,13 +562,7 @@ static void snd_card_asihpi_pcm_int_stop(struct snd_pcm_substream *substream)
hpi_handle_error(hpi_adapter_set_property(card->hpi->adapter->index, hpi_handle_error(hpi_adapter_set_property(card->hpi->adapter->index,
HPI_ADAPTER_PROPERTY_IRQ_RATE, 0, 0)); HPI_ADAPTER_PROPERTY_IRQ_RATE, 0, 0));
if (in_interrupt()) card->llmode_streampriv = NULL;
card->llmode_streampriv = NULL;
else {
tasklet_disable(&card->t);
card->llmode_streampriv = NULL;
tasklet_enable(&card->t);
}
} }
static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream, static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream,
...@@ -921,10 +912,9 @@ static void snd_card_asihpi_timer_function(struct timer_list *t) ...@@ -921,10 +912,9 @@ static void snd_card_asihpi_timer_function(struct timer_list *t)
add_timer(&dpcm->timer); add_timer(&dpcm->timer);
} }
static void snd_card_asihpi_int_task(struct tasklet_struct *t) static void snd_card_asihpi_isr(struct hpi_adapter *a)
{ {
struct snd_card_asihpi *asihpi = from_tasklet(asihpi, t, t); struct snd_card_asihpi *asihpi;
struct hpi_adapter *a = asihpi->hpi;
WARN_ON(!a || !a->snd_card || !a->snd_card->private_data); WARN_ON(!a || !a->snd_card || !a->snd_card->private_data);
asihpi = (struct snd_card_asihpi *)a->snd_card->private_data; asihpi = (struct snd_card_asihpi *)a->snd_card->private_data;
...@@ -933,15 +923,6 @@ static void snd_card_asihpi_int_task(struct tasklet_struct *t) ...@@ -933,15 +923,6 @@ static void snd_card_asihpi_int_task(struct tasklet_struct *t)
&asihpi->llmode_streampriv->timer); &asihpi->llmode_streampriv->timer);
} }
static void snd_card_asihpi_isr(struct hpi_adapter *a)
{
struct snd_card_asihpi *asihpi;
WARN_ON(!a || !a->snd_card || !a->snd_card->private_data);
asihpi = (struct snd_card_asihpi *)a->snd_card->private_data;
tasklet_schedule(&asihpi->t);
}
/***************************** PLAYBACK OPS ****************/ /***************************** PLAYBACK OPS ****************/
static int snd_card_asihpi_playback_prepare(struct snd_pcm_substream * static int snd_card_asihpi_playback_prepare(struct snd_pcm_substream *
substream) substream)
...@@ -2871,7 +2852,6 @@ static int snd_asihpi_probe(struct pci_dev *pci_dev, ...@@ -2871,7 +2852,6 @@ static int snd_asihpi_probe(struct pci_dev *pci_dev,
if (hpi->interrupt_mode) { if (hpi->interrupt_mode) {
asihpi->pcm_start = snd_card_asihpi_pcm_int_start; asihpi->pcm_start = snd_card_asihpi_pcm_int_start;
asihpi->pcm_stop = snd_card_asihpi_pcm_int_stop; asihpi->pcm_stop = snd_card_asihpi_pcm_int_stop;
tasklet_setup(&asihpi->t, snd_card_asihpi_int_task);
hpi->interrupt_callback = snd_card_asihpi_isr; hpi->interrupt_callback = snd_card_asihpi_isr;
} else { } else {
asihpi->pcm_start = snd_card_asihpi_pcm_timer_start; asihpi->pcm_start = snd_card_asihpi_pcm_timer_start;
...@@ -2960,14 +2940,12 @@ static int snd_asihpi_probe(struct pci_dev *pci_dev, ...@@ -2960,14 +2940,12 @@ static int snd_asihpi_probe(struct pci_dev *pci_dev,
static void snd_asihpi_remove(struct pci_dev *pci_dev) static void snd_asihpi_remove(struct pci_dev *pci_dev)
{ {
struct hpi_adapter *hpi = pci_get_drvdata(pci_dev); struct hpi_adapter *hpi = pci_get_drvdata(pci_dev);
struct snd_card_asihpi *asihpi = hpi->snd_card->private_data;
/* Stop interrupts */ /* Stop interrupts */
if (hpi->interrupt_mode) { if (hpi->interrupt_mode) {
hpi->interrupt_callback = NULL; hpi->interrupt_callback = NULL;
hpi_handle_error(hpi_adapter_set_property(hpi->adapter->index, hpi_handle_error(hpi_adapter_set_property(hpi->adapter->index,
HPI_ADAPTER_PROPERTY_IRQ_RATE, 0, 0)); HPI_ADAPTER_PROPERTY_IRQ_RATE, 0, 0));
tasklet_kill(&asihpi->t);
} }
snd_card_free(hpi->snd_card); snd_card_free(hpi->snd_card);
......
...@@ -329,11 +329,20 @@ static irqreturn_t asihpi_isr(int irq, void *dev_id) ...@@ -329,11 +329,20 @@ static irqreturn_t asihpi_isr(int irq, void *dev_id)
asihpi_irq_count, a->adapter->type, a->adapter->index); */ asihpi_irq_count, a->adapter->type, a->adapter->index); */
if (a->interrupt_callback) if (a->interrupt_callback)
a->interrupt_callback(a); return IRQ_WAKE_THREAD;
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static irqreturn_t asihpi_isr_thread(int irq, void *dev_id)
{
struct hpi_adapter *a = dev_id;
if (a->interrupt_callback)
a->interrupt_callback(a);
return IRQ_HANDLED;
}
int asihpi_adapter_probe(struct pci_dev *pci_dev, int asihpi_adapter_probe(struct pci_dev *pci_dev,
const struct pci_device_id *pci_id) const struct pci_device_id *pci_id)
{ {
...@@ -478,8 +487,9 @@ int asihpi_adapter_probe(struct pci_dev *pci_dev, ...@@ -478,8 +487,9 @@ int asihpi_adapter_probe(struct pci_dev *pci_dev,
} }
/* Note: request_irq calls asihpi_isr here */ /* Note: request_irq calls asihpi_isr here */
if (request_irq(pci_dev->irq, asihpi_isr, IRQF_SHARED, if (request_threaded_irq(pci_dev->irq, asihpi_isr,
"asihpi", &adapters[adapter_index])) { asihpi_isr_thread, IRQF_SHARED,
"asihpi", &adapters[adapter_index])) {
dev_err(&pci_dev->dev, "request_irq(%d) failed\n", dev_err(&pci_dev->dev, "request_irq(%d) failed\n",
pci_dev->irq); pci_dev->irq);
goto err; goto err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment