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);
}
Example #2
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");

        /*
         * 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;
}
Example #3
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;
}
Example #4
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);
}
Example #5
0
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);
}