static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) { struct rt2x00_dev *rt2x00dev = dev_instance; u32 reg, mask; unsigned long flags; /* Read status and ACK all interrupts */ rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg); if (!reg) return IRQ_NONE; if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) return IRQ_HANDLED; /* * Since INT_MASK_CSR and INT_SOURCE_CSR use the same bits * for interrupts and interrupt masks we can just use the value of * INT_SOURCE_CSR to create the interrupt mask. */ mask = ~reg; if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) { rt2800pci_txstatus_interrupt(rt2x00dev); /* * Never disable the TX_FIFO_STATUS interrupt. */ rt2x00_set_field32(&mask, INT_MASK_CSR_TX_FIFO_STATUS, 1); } if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT)) tasklet_hi_schedule(&rt2x00dev->pretbtt_tasklet); if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT)) tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet); if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE)) tasklet_schedule(&rt2x00dev->rxdone_tasklet); if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) tasklet_schedule(&rt2x00dev->autowake_tasklet); /* * Disable all interrupts for which a tasklet was scheduled right now, * the tasklet will reenable the appropriate interrupts. */ spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); reg &= mask; rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); return IRQ_HANDLED; }
static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) { struct rt2x00_dev *rt2x00dev = dev_instance; u32 reg; irqreturn_t ret = IRQ_HANDLED; /* Read status and ACK all interrupts */ rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg); if (!reg) return IRQ_NONE; if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) return IRQ_HANDLED; if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) rt2800pci_txstatus_interrupt(rt2x00dev); if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT) || rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT) || rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE) || rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) { /* * All other interrupts are handled in the interrupt thread. * Store irqvalue for use in the interrupt thread. */ rt2x00dev->irqvalue[0] = reg; /* * Disable interrupts, will be enabled again in the * interrupt thread. */ rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_IRQ_OFF_ISR); /* * Leave the TX_FIFO_STATUS interrupt enabled to not lose any * tx status reports. */ rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); rt2x00_set_field32(®, INT_MASK_CSR_TX_FIFO_STATUS, 1); rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); ret = IRQ_WAKE_THREAD; } return ret; }