static void wl1251_filter_work(struct work_struct *work) { struct wl1251 *wl = container_of(work, struct wl1251, filter_work); int ret; mutex_lock(&wl->mutex); if (wl->state == WL1251_STATE_OFF) goto out; ret = wl1251_ps_elp_wakeup(wl); if (ret < 0) goto out; ret = wl1251_join(wl, wl->bss_type, wl->channel, wl->beacon_int, wl->dtim_period); if (ret < 0) goto out_sleep; out_sleep: wl1251_ps_elp_sleep(wl); out: mutex_unlock(&wl->mutex); }
static int wl1251_ps_set_elp(struct wl1251 *wl, bool enable) { int ret; if (enable) { wl1251_debug(DEBUG_PSM, "sleep auth psm/elp"); ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_ELP); if (ret < 0) return ret; wl1251_ps_elp_sleep(wl); } else { wl1251_debug(DEBUG_PSM, "sleep auth cam"); /* * When the target is in ELP, we can only * access the ELP control register. Thus, * we have to wake the target up before * changing the power authorization. */ wl1251_ps_elp_wakeup(wl); ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_CAM); if (ret < 0) return ret; } return 0; }
static int wl1251_ps_set_elp(struct wl1251 *wl, bool enable) { int ret; if (enable) { wl1251_debug(DEBUG_PSM, "sleep auth psm/elp"); ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_ELP); if (ret < 0) return ret; wl1251_ps_elp_sleep(wl); } else { wl1251_debug(DEBUG_PSM, "sleep auth cam"); wl1251_ps_elp_wakeup(wl); ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_CAM); if (ret < 0) return ret; } return 0; }
static void wl1251_debugfs_update_stats(struct wl1251 *wl) { int ret; mutex_lock(&wl->mutex); ret = wl1251_ps_elp_wakeup(wl); if (ret < 0) goto out; if (wl->state == WL1251_STATE_ON && time_after(jiffies, wl->stats.fw_stats_update + msecs_to_jiffies(WL1251_DEBUGFS_STATS_LIFETIME))) { wl1251_acx_statistics(wl, wl->stats.fw_stats); wl->stats.fw_stats_update = jiffies; } wl1251_ps_elp_sleep(wl); out: mutex_unlock(&wl->mutex); }
static void wl1251_irq_work(struct work_struct *work) { u32 intr, ctr = WL1251_IRQ_LOOP_COUNT; struct wl1251 *wl = container_of(work, struct wl1251, irq_work); int ret; mutex_lock(&wl->mutex); wl1251_debug(DEBUG_IRQ, "IRQ work"); if (wl->state == WL1251_STATE_OFF) goto out; ret = wl1251_ps_elp_wakeup(wl); if (ret < 0) goto out; wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1251_ACX_INTR_ALL); intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR); wl1251_debug(DEBUG_IRQ, "intr: 0x%x", intr); do { if (wl->data_path) { wl->rx_counter = wl1251_mem_read32( wl, wl->data_path->rx_control_addr); /* We handle a frmware bug here */ switch ((wl->rx_counter - wl->rx_handled) & 0xf) { case 0: wl1251_debug(DEBUG_IRQ, "RX: FW and host in sync"); intr &= ~WL1251_ACX_INTR_RX0_DATA; intr &= ~WL1251_ACX_INTR_RX1_DATA; break; case 1: wl1251_debug(DEBUG_IRQ, "RX: FW +1"); intr |= WL1251_ACX_INTR_RX0_DATA; intr &= ~WL1251_ACX_INTR_RX1_DATA; break; case 2: wl1251_debug(DEBUG_IRQ, "RX: FW +2"); intr |= WL1251_ACX_INTR_RX0_DATA; intr |= WL1251_ACX_INTR_RX1_DATA; break; default: wl1251_warning( "RX: FW and host out of sync: %d", wl->rx_counter - wl->rx_handled); break; } wl->rx_handled = wl->rx_counter; wl1251_debug(DEBUG_IRQ, "RX counter: %d", wl->rx_counter); } intr &= wl->intr_mask; if (intr == 0) { wl1251_debug(DEBUG_IRQ, "INTR is 0"); goto out_sleep; } if (intr & WL1251_ACX_INTR_RX0_DATA) { wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX0_DATA"); wl1251_rx(wl); } if (intr & WL1251_ACX_INTR_RX1_DATA) { wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX1_DATA"); wl1251_rx(wl); } if (intr & WL1251_ACX_INTR_TX_RESULT) { wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_TX_RESULT"); wl1251_tx_complete(wl); } if (intr & WL1251_ACX_INTR_EVENT_A) { wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT_A"); wl1251_event_handle(wl, 0); } if (intr & WL1251_ACX_INTR_EVENT_B) { wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT_B"); wl1251_event_handle(wl, 1); } if (intr & WL1251_ACX_INTR_INIT_COMPLETE) wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_INIT_COMPLETE"); if (--ctr == 0) break; intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR); } while (intr); out_sleep: wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask)); wl1251_ps_elp_sleep(wl); out: mutex_unlock(&wl->mutex); }