Пример #1
0
int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
                       enum wl1271_cmd_ps_mode mode)
{
    int ret;
    u16 timeout = wl->conf.conn.dynamic_ps_timeout;

    switch (mode) {
    case STATION_AUTO_PS_MODE:
    case STATION_POWER_SAVE_MODE:
        wl1271_debug(DEBUG_PSM, "entering psm (mode=%d,timeout=%u)",
                     mode, timeout);

        ret = wl1271_acx_wake_up_conditions(wl, wlvif,
                                            wl->conf.conn.wake_up_event,
                                            wl->conf.conn.listen_interval);
        if (ret < 0) {
            wl1271_error("couldn't set wake up conditions");
            return ret;
        }

        ret = wl1271_cmd_ps_mode(wl, wlvif, mode, timeout);
        if (ret < 0)
            return ret;

        set_bit(WLVIF_FLAG_IN_PS, &wlvif->flags);


        if (wlvif->band == IEEE80211_BAND_2GHZ) {
            ret = wl1271_acx_bet_enable(wl, wlvif, true);
            if (ret < 0)
                return ret;
        }
        break;
    case STATION_ACTIVE_MODE:
        wl1271_debug(DEBUG_PSM, "leaving psm");


        if (wlvif->band == IEEE80211_BAND_2GHZ) {
            ret = wl1271_acx_bet_enable(wl, wlvif, false);
            if (ret < 0)
                return ret;
        }

        ret = wl1271_cmd_ps_mode(wl, wlvif, mode, 0);
        if (ret < 0)
            return ret;

        clear_bit(WLVIF_FLAG_IN_PS, &wlvif->flags);
        break;
    default:
        wl1271_warning("trying to set ps to unsupported mode %d", mode);
        ret = -EINVAL;
    }

    return ret;
}
static int wl1271_event_ps_report(struct wl1271 *wl,
				  struct event_mailbox *mbox,
				  bool *beacon_loss)
{
	int ret = 0;
	u32 total_retries = wl->conf.conn.psm_entry_retries;

	wl1271_debug(DEBUG_EVENT, "ps_status: 0x%x", mbox->ps_status);

	switch (mbox->ps_status) {
	case EVENT_ENTER_POWER_SAVE_FAIL:
		wl1271_debug(DEBUG_PSM, "PSM entry failed");

		if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) {
			/* remain in active mode */
			wl->psm_entry_retry = 0;
			break;
		}

		if (wl->psm_entry_retry < total_retries) {
			wl->psm_entry_retry++;
			ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE,
						 wl->basic_rate, true);
		} else {
			wl1271_info("No ack to nullfunc from AP.");
			wl->psm_entry_retry = 0;
			*beacon_loss = true;
		}
		break;
	case EVENT_ENTER_POWER_SAVE_SUCCESS:
		wl->psm_entry_retry = 0;

		/* enable beacon filtering */
		ret = wl1271_acx_beacon_filter_opt(wl, true);
		if (ret < 0)
			break;

		/*
		 * BET has only a minor effect in 5GHz and masks
		 * channel switch IEs, so we only enable BET on 2.4GHz
		*/
		if (wl->band == IEEE80211_BAND_2GHZ)
			/* enable beacon early termination */
			ret = wl1271_acx_bet_enable(wl, true);

		if (wl->ps_compl) {
			complete(wl->ps_compl);
			wl->ps_compl = NULL;
		}
		break;
	default:
		break;
	}

	return ret;
}
Пример #3
0
int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
		       u32 rates, bool send)
{
	int ret;

	switch (mode) {
	case STATION_POWER_SAVE_MODE:
		wl1271_debug(DEBUG_PSM, "entering psm");

		ret = wl1271_acx_wake_up_conditions(wl,
				    wl->conf.conn.wake_up_event,
				    wl->conf.conn.listen_interval);

		if (ret < 0) {
			wl1271_error("couldn't set wake up conditions");
			return ret;
		}

		ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE);
		if (ret < 0)
			return ret;

		set_bit(WL1271_FLAG_PSM, &wl->flags);
		break;
	case STATION_ACTIVE_MODE:
	default:
		wl1271_debug(DEBUG_PSM, "leaving psm");

		wl->psm_entry_retry = 0;
		cancel_delayed_work(&wl->ps_retry_work);

		/* disable beacon early termination */
		if (wl->band == IEEE80211_BAND_2GHZ) {
			ret = wl1271_acx_bet_enable(wl, false);
			if (ret < 0)
				return ret;
		}

		/* disable beacon filtering */
		ret = wl1271_acx_beacon_filter_opt(wl, false);
		if (ret < 0)
			return ret;

		ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE);
		if (ret < 0)
			return ret;

		clear_bit(WL1271_FLAG_PSM, &wl->flags);
		break;
	}

	return ret;
}
Пример #4
0
int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
		       u32 rates, bool send)
{
	int ret;

	switch (mode) {
	case STATION_POWER_SAVE_MODE:
		wl1271_debug(DEBUG_PSM, "entering psm");

		ret = wl1271_acx_wake_up_conditions(wl);
		if (ret < 0) {
			wl1271_error("couldn't set wake up conditions");
			return ret;
		}

		ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE);
		if (ret < 0)
			return ret;

		set_bit(WL1271_FLAG_PSM, &wl->flags);
		break;
	case STATION_ACTIVE_MODE:
	default:
		wl1271_debug(DEBUG_PSM, "leaving psm");
		ret = wl1271_ps_elp_wakeup(wl, false);
		if (ret < 0)
			return ret;

		/* disable beacon early termination */
		ret = wl1271_acx_bet_enable(wl, false);
		if (ret < 0)
			return ret;

		/* disable beacon filtering */
		ret = wl1271_acx_beacon_filter_opt(wl, false);
		if (ret < 0)
			return ret;

		ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE);
		if (ret < 0)
			return ret;

		clear_bit(WL1271_FLAG_PSM, &wl->flags);
		break;
	}

	return ret;
}
Пример #5
0
static int wl1271_event_ps_report(struct wl1271 *wl,
				  struct event_mailbox *mbox,
				  bool *beacon_loss)
{
	int ret = 0;
	u32 total_retries = wl->conf.conn.psm_entry_retries;

	wl1271_debug(DEBUG_EVENT, "ps_status: 0x%x", mbox->ps_status);

	switch (mbox->ps_status) {
	case EVENT_ENTER_POWER_SAVE_FAIL:
		wl1271_debug(DEBUG_PSM, "PSM entry failed");

		if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) {
			/* remain in active mode */
			wl->psm_entry_retry = 0;
			break;
		}

		if (wl->psm_entry_retry < total_retries) {
			wl->psm_entry_retry++;
			ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE,
						 wl->basic_rate, true);
		} else {
			wl1271_info("No ack to nullfunc from AP.");
			wl->psm_entry_retry = 0;
			*beacon_loss = true;
		}
		break;
	case EVENT_ENTER_POWER_SAVE_SUCCESS:
		wl->psm_entry_retry = 0;

		/* enable beacon filtering */
		ret = wl1271_acx_beacon_filter_opt(wl, true);
		if (ret < 0)
			break;

		/* enable beacon early termination */
		ret = wl1271_acx_bet_enable(wl, true);
		if (ret < 0)
			break;

		/* go to extremely low power mode */
		wl1271_ps_elp_sleep(wl);
		break;
	case EVENT_EXIT_POWER_SAVE_FAIL:
		wl1271_debug(DEBUG_PSM, "PSM exit failed");

		if (test_bit(WL1271_FLAG_PSM, &wl->flags)) {
			wl->psm_entry_retry = 0;
			break;
		}

		/* make sure the firmware goes to active mode - the frame to
		   be sent next will indicate to the AP, that we are active. */
		ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
					 wl->basic_rate, false);
		break;
	case EVENT_EXIT_POWER_SAVE_SUCCESS:
	default:
		break;
	}

	return ret;
}