diff options
Diffstat (limited to 'sound/pci/hda/hda_controller.c')
-rw-r--r-- | sound/pci/hda/hda_controller.c | 47 |
1 files changed, 26 insertions, 21 deletions
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 37cf9cee9835..27de8015717d 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c | |||
@@ -930,6 +930,8 @@ irqreturn_t azx_interrupt(int irq, void *dev_id) | |||
930 | struct azx *chip = dev_id; | 930 | struct azx *chip = dev_id; |
931 | struct hdac_bus *bus = azx_bus(chip); | 931 | struct hdac_bus *bus = azx_bus(chip); |
932 | u32 status; | 932 | u32 status; |
933 | bool active, handled = false; | ||
934 | int repeat = 0; /* count for avoiding endless loop */ | ||
933 | 935 | ||
934 | #ifdef CONFIG_PM | 936 | #ifdef CONFIG_PM |
935 | if (azx_has_pm_runtime(chip)) | 937 | if (azx_has_pm_runtime(chip)) |
@@ -939,33 +941,36 @@ irqreturn_t azx_interrupt(int irq, void *dev_id) | |||
939 | 941 | ||
940 | spin_lock(&bus->reg_lock); | 942 | spin_lock(&bus->reg_lock); |
941 | 943 | ||
942 | if (chip->disabled) { | 944 | if (chip->disabled) |
943 | spin_unlock(&bus->reg_lock); | 945 | goto unlock; |
944 | return IRQ_NONE; | ||
945 | } | ||
946 | |||
947 | status = azx_readl(chip, INTSTS); | ||
948 | if (status == 0 || status == 0xffffffff) { | ||
949 | spin_unlock(&bus->reg_lock); | ||
950 | return IRQ_NONE; | ||
951 | } | ||
952 | 946 | ||
953 | snd_hdac_bus_handle_stream_irq(bus, status, stream_update); | 947 | do { |
948 | status = azx_readl(chip, INTSTS); | ||
949 | if (status == 0 || status == 0xffffffff) | ||
950 | break; | ||
954 | 951 | ||
955 | /* clear rirb int */ | 952 | handled = true; |
956 | status = azx_readb(chip, RIRBSTS); | 953 | active = false; |
957 | if (status & RIRB_INT_MASK) { | 954 | if (snd_hdac_bus_handle_stream_irq(bus, status, stream_update)) |
958 | if (status & RIRB_INT_RESPONSE) { | 955 | active = true; |
959 | if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) | 956 | |
960 | udelay(80); | 957 | /* clear rirb int */ |
961 | snd_hdac_bus_update_rirb(bus); | 958 | status = azx_readb(chip, RIRBSTS); |
959 | if (status & RIRB_INT_MASK) { | ||
960 | active = true; | ||
961 | if (status & RIRB_INT_RESPONSE) { | ||
962 | if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) | ||
963 | udelay(80); | ||
964 | snd_hdac_bus_update_rirb(bus); | ||
965 | } | ||
966 | azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); | ||
962 | } | 967 | } |
963 | azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); | 968 | } while (active && ++repeat < 10); |
964 | } | ||
965 | 969 | ||
970 | unlock: | ||
966 | spin_unlock(&bus->reg_lock); | 971 | spin_unlock(&bus->reg_lock); |
967 | 972 | ||
968 | return IRQ_HANDLED; | 973 | return IRQ_RETVAL(handled); |
969 | } | 974 | } |
970 | EXPORT_SYMBOL_GPL(azx_interrupt); | 975 | EXPORT_SYMBOL_GPL(azx_interrupt); |
971 | 976 | ||