[PATCH] ath10k: move irq setup

Kalle Valo kvalo at qca.qualcomm.com
Tue Jul 30 14:35:39 EDT 2013

Michal Kazior <michal.kazior at tieto.com> writes:

> There was a slight race during PCI shutdown. Since
> interrupts weren't really stopped (only Copy
> Engine interrupts were disabled through device hw
> registers) it was possible for a firmware
> indication (crash) interrupt to come in after
> tasklets were synced/killed. This would cause
> memory corruption and a panic in most cases. It
> was also possible for interrupt to come before CE
> was initialized during device probing.
> Interrupts are required for BMI phase so they are enabled as soon as
> power_up() is called but are freed upon both power_down() and stop()
> so there's asymmetry here. As by design stop() cannot be followed by
> start() it is okay. Both power_down() and stop() should be merged
> later on to avoid confusion.

Why are the interrupts freed both in power_down() and stop()? I don't
get that.

What if we call disable_irq() in power_down() instead?

> Before this can be really properly fixed var/hw
> init code split is necessary.
> Signed-off-by: Michal Kazior <michal.kazior at tieto.com>
> ---
> Please note: this is based on my (still under
> review at the time of posting) previous patchests:
> device setup refactor and recovery.
> I'm posting this before those patchsets are merged
> so anyone interested in testing this fix (I can't
> reproduce the problem on my setup) can give it a
> try.

This was reported by Ben, right? So this sould have a Reported-by line
attributing him.

> @@ -1783,16 +1792,24 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
>  	return 0;
>  err_ce:
> +	/* XXX: Until var/hw init is split it's impossible to fix the ordering
> +	 * here so we must call stop_intr() here too to prevent interrupts after
> +	 * CE is teared down. It's okay to double call the stop_intr()
> */


>  exit:
> +	ar_pci->intr_started = ret == 0;

A bit too clever for the sake of readibility for my taste, but I guess
it's ok.

> --- a/drivers/net/wireless/ath/ath10k/pci.h
> +++ b/drivers/net/wireless/ath/ath10k/pci.h
> @@ -198,6 +198,7 @@ struct ath10k_pci {
>  	 * interrupts.
>  	 */
>  	int num_msi_intrs;
> +	bool intr_started;

Adding a new state variable makes me worried. I really would prefer a
solution which would not require that.

Also if we call request_irq() in ath10k_pci_probe() we should also call
free_irq() in ath10k_pci_remove() for symmetry. Just doing a temporary
hack will most likely stay forever :)

Kalle Valo

More information about the ath10k mailing list