wl->set_power(true);
}
-static void wl1271_fw_status(struct wl1271 *wl, struct wl1271_fw_status *status)
+static void wl1271_fw_status(struct wl1271 *wl,
+ struct wl1271_fw_status *status)
{
u32 total = 0;
int i;
- /*
- * FIXME: Reading the FW status directly from the registers seems to
- * be the right thing to do, but it doesn't work. And in the
- * reference driver, there is a workaround called
- * USE_SDIO_24M_WORKAROUND, which reads the status from memory
- * instead, so we do the same here.
- */
-
- wl1271_spi_mem_read(wl, STATUS_MEM_ADDRESS, status, sizeof(*status));
+ wl1271_spi_reg_read(wl, FW_STATUS_ADDR, status,
+ sizeof(*status), false);
wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
"drv_rx_counter = %d, tx_results_counter = %d)",
wl->time_offset = jiffies_to_usecs(jiffies) - status->fw_localtime;
}
-#define WL1271_IRQ_MAX_LOOPS 10
static void wl1271_irq_work(struct work_struct *work)
{
- u32 intr, ctr = WL1271_IRQ_MAX_LOOPS;
int ret;
+ u32 intr;
struct wl1271 *wl =
container_of(work, struct wl1271, irq_work);
wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
- intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR);
+ wl1271_fw_status(wl, wl->fw_status);
+ intr = wl->fw_status->intr;
if (!intr) {
wl1271_debug(DEBUG_IRQ, "Zero interrupt received.");
goto out_sleep;
intr &= WL1271_INTR_MASK;
- do {
- wl1271_fw_status(wl, wl->fw_status);
-
-
- if (intr & (WL1271_ACX_INTR_EVENT_A |
- WL1271_ACX_INTR_EVENT_B)) {
- wl1271_debug(DEBUG_IRQ,
- "WL1271_ACX_INTR_EVENT (0x%x)", intr);
- if (intr & WL1271_ACX_INTR_EVENT_A)
- wl1271_event_handle(wl, 0);
- else
- wl1271_event_handle(wl, 1);
- }
+ if (intr & (WL1271_ACX_INTR_EVENT_A |
+ WL1271_ACX_INTR_EVENT_B)) {
+ wl1271_debug(DEBUG_IRQ,
+ "WL1271_ACX_INTR_EVENT (0x%x)", intr);
+ if (intr & WL1271_ACX_INTR_EVENT_A)
+ wl1271_event_handle(wl, 0);
+ else
+ wl1271_event_handle(wl, 1);
+ }
- if (intr & WL1271_ACX_INTR_INIT_COMPLETE)
- wl1271_debug(DEBUG_IRQ,
- "WL1271_ACX_INTR_INIT_COMPLETE");
+ if (intr & WL1271_ACX_INTR_INIT_COMPLETE)
+ wl1271_debug(DEBUG_IRQ,
+ "WL1271_ACX_INTR_INIT_COMPLETE");
- if (intr & WL1271_ACX_INTR_HW_AVAILABLE)
- wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE");
+ if (intr & WL1271_ACX_INTR_HW_AVAILABLE)
+ wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE");
- if (intr & WL1271_ACX_INTR_DATA) {
- u8 tx_res_cnt = wl->fw_status->tx_results_counter -
- wl->tx_results_count;
+ if (intr & WL1271_ACX_INTR_DATA) {
+ u8 tx_res_cnt = wl->fw_status->tx_results_counter -
+ wl->tx_results_count;
- wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
+ wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
- /* check for tx results */
- if (tx_res_cnt)
- wl1271_tx_complete(wl, tx_res_cnt);
+ /* check for tx results */
+ if (tx_res_cnt)
+ wl1271_tx_complete(wl, tx_res_cnt);
- wl1271_rx(wl, wl->fw_status);
- }
-
- intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR);
- intr &= WL1271_INTR_MASK;
- } while (intr && --ctr);
+ wl1271_rx(wl, wl->fw_status);
+ }
out_sleep:
wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK,