Exemple #1
0
	uint32_t status;
	int basic_ssid =
	    !(sc->sc_capaflags & IWM_UCODE_TLV_FLAGS_NO_BASIC_SSID);

	sc->sc_scanband = flags & (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ);

	IWM_DPRINTF(sc, IWM_DEBUG_SCAN,
	    "Handling ieee80211 scan request\n");
	memset(cmd, 0, sc->sc_scan_cmd_len);

	cmd->quiet_time = htole16(IWM_ACTIVE_QUIET_TIME);
	cmd->quiet_plcp_th = htole16(IWM_PLCP_QUIET_THRESH);
	cmd->rxchain_sel_flags = iwm_mvm_scan_rx_chain(sc);
	cmd->max_out_time = iwm_mvm_scan_max_out_time(sc, 0, is_assoc);
	cmd->suspend_time = iwm_mvm_scan_suspend_time(sc, is_assoc);
	cmd->rxon_flags = iwm_mvm_scan_rxon_flags(sc, flags);
	cmd->filter_flags = htole32(IWM_MAC_FILTER_ACCEPT_GRP |
	    IWM_MAC_FILTER_IN_BEACON);

	cmd->type = htole32(IWM_SCAN_TYPE_FORCED);
	cmd->repeats = htole32(1);

	/*
	 * If the user asked for passive scan, don't change to active scan if
	 * you see any activity on the channel - remain passive.
	 */
	if (n_ssids > 0) {
		cmd->passive2active = htole16(1);
		cmd->scan_flags |= IWM_SCAN_FLAGS_PASSIVE2ACTIVE;
#if 0
		if (basic_ssid) {
Exemple #2
0
int
iwm_mvm_config_umac_scan(struct iwm_softc *sc)
{
	struct ieee80211com *ic = &sc->sc_ic;
	struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);

	struct iwm_scan_config *scan_config;
	int ret, j, nchan;
	size_t cmd_size;
	struct ieee80211_channel *c;
	struct iwm_host_cmd hcmd = {
		.id = iwm_cmd_id(IWM_SCAN_CFG_CMD, IWM_ALWAYS_LONG_GROUP, 0),
		.flags = IWM_CMD_SYNC,
	};
	static const uint32_t rates = (IWM_SCAN_CONFIG_RATE_1M |
	    IWM_SCAN_CONFIG_RATE_2M | IWM_SCAN_CONFIG_RATE_5M |
	    IWM_SCAN_CONFIG_RATE_11M | IWM_SCAN_CONFIG_RATE_6M |
	    IWM_SCAN_CONFIG_RATE_9M | IWM_SCAN_CONFIG_RATE_12M |
	    IWM_SCAN_CONFIG_RATE_18M | IWM_SCAN_CONFIG_RATE_24M |
	    IWM_SCAN_CONFIG_RATE_36M | IWM_SCAN_CONFIG_RATE_48M |
	    IWM_SCAN_CONFIG_RATE_54M);

	cmd_size = sizeof(*scan_config) + sc->ucode_capa.n_scan_channels;

	scan_config = malloc(cmd_size, M_DEVBUF, M_NOWAIT | M_ZERO);
	if (scan_config == NULL)
		return ENOMEM;

	scan_config->tx_chains = htole32(iwm_mvm_get_valid_tx_ant(sc));
	scan_config->rx_chains = htole32(iwm_mvm_get_valid_rx_ant(sc));
	scan_config->legacy_rates = htole32(rates |
	    IWM_SCAN_CONFIG_SUPPORTED_RATE(rates));

	/* These timings correspond to iwlwifi's UNASSOC scan. */
	scan_config->dwell_active = 10;
	scan_config->dwell_passive = 110;
	scan_config->dwell_fragmented = 44;
	scan_config->dwell_extended = 90;
	scan_config->out_of_channel_time = htole32(0);
	scan_config->suspend_time = htole32(0);

	IEEE80211_ADDR_COPY(scan_config->mac_addr,
	    vap ? vap->iv_myaddr : ic->ic_macaddr);

	scan_config->bcast_sta_id = sc->sc_aux_sta.sta_id;
	scan_config->channel_flags = IWM_CHANNEL_FLAG_EBS |
	    IWM_CHANNEL_FLAG_ACCURATE_EBS | IWM_CHANNEL_FLAG_EBS_ADD |
	    IWM_CHANNEL_FLAG_PRE_SCAN_PASSIVE2ACTIVE;

	for (nchan = j = 0;
	    j < ic->ic_nchans && nchan < sc->ucode_capa.n_scan_channels; j++) {
		c = &ic->ic_channels[j];
		/* For 2GHz, only populate 11b channels */
		/* For 5GHz, only populate 11a channels */
		/*
		 * Catch other channels, in case we have 900MHz channels or
		 * something in the chanlist.
		 */
		if (iwm_mvm_scan_skip_channel(c))
			continue;
		scan_config->channel_array[nchan++] =
		    ieee80211_mhz2ieee(c->ic_freq, 0);
	}

	scan_config->flags = htole32(IWM_SCAN_CONFIG_FLAG_ACTIVATE |
	    IWM_SCAN_CONFIG_FLAG_ALLOW_CHUB_REQS |
	    IWM_SCAN_CONFIG_FLAG_SET_TX_CHAINS |
	    IWM_SCAN_CONFIG_FLAG_SET_RX_CHAINS |
	    IWM_SCAN_CONFIG_FLAG_SET_AUX_STA_ID |
	    IWM_SCAN_CONFIG_FLAG_SET_ALL_TIMES |
	    IWM_SCAN_CONFIG_FLAG_SET_LEGACY_RATES |
	    IWM_SCAN_CONFIG_FLAG_SET_MAC_ADDR |
	    IWM_SCAN_CONFIG_FLAG_SET_CHANNEL_FLAGS|
	    IWM_SCAN_CONFIG_N_CHANNELS(nchan) |
	    IWM_SCAN_CONFIG_FLAG_CLEAR_FRAGMENTED);

	hcmd.data[0] = scan_config;
	hcmd.len[0] = cmd_size;

	IWM_DPRINTF(sc, IWM_DEBUG_SCAN, "Sending UMAC scan config\n");

	ret = iwm_send_cmd(sc, &hcmd);
	if (!ret)
		IWM_DPRINTF(sc, IWM_DEBUG_SCAN,
		    "UMAC scan config was sent successfully\n");

	free(scan_config, M_DEVBUF);
	return ret;
}

static boolean_t
iwm_mvm_scan_use_ebs(struct iwm_softc *sc)
{
	const struct iwm_ucode_capabilities *capa = &sc->ucode_capa;

	/* We can only use EBS if:
	 *	1. the feature is supported;
	 *	2. the last EBS was successful;
	 *	3. if only single scan, the single scan EBS API is supported;
	 *	4. it's not a p2p find operation.
	 */
	return ((capa->flags & IWM_UCODE_TLV_FLAGS_EBS_SUPPORT) &&
		sc->last_ebs_successful);
}

int
iwm_mvm_umac_scan(struct iwm_softc *sc)
{
	struct iwm_host_cmd hcmd = {
		.id = iwm_cmd_id(IWM_SCAN_REQ_UMAC, IWM_ALWAYS_LONG_GROUP, 0),
		.len = { 0, },
		.data = { NULL, },
		.flags = IWM_CMD_SYNC,
	};
	struct ieee80211_scan_state *ss = sc->sc_ic.ic_scan;
	struct iwm_scan_req_umac *req;
	struct iwm_scan_req_umac_tail *tail;
	size_t req_len;
	uint8_t i, nssid;
	int ret;

	req_len = sizeof(struct iwm_scan_req_umac) +
	    (sizeof(struct iwm_scan_channel_cfg_umac) *
	    sc->ucode_capa.n_scan_channels) +
	    sizeof(struct iwm_scan_req_umac_tail);
	if (req_len > IWM_MAX_CMD_PAYLOAD_SIZE)
		return ENOMEM;
	req = malloc(req_len, M_DEVBUF, M_NOWAIT | M_ZERO);
	if (req == NULL)
		return ENOMEM;

	hcmd.len[0] = (uint16_t)req_len;
	hcmd.data[0] = (void *)req;

	IWM_DPRINTF(sc, IWM_DEBUG_SCAN, "Handling ieee80211 scan request\n");

	/* These timings correspond to iwlwifi's UNASSOC scan. */
	req->active_dwell = 10;
	req->passive_dwell = 110;
	req->fragmented_dwell = 44;
	req->extended_dwell = 90;
	req->max_out_time = 0;
	req->suspend_time = 0;

	req->scan_priority = htole32(IWM_SCAN_PRIORITY_HIGH);
	req->ooc_priority = htole32(IWM_SCAN_PRIORITY_HIGH);

	nssid = MIN(ss->ss_nssid, IWM_PROBE_OPTION_MAX);
	req->n_channels = iwm_mvm_umac_scan_fill_channels(sc,
	    (struct iwm_scan_channel_cfg_umac *)req->data, nssid);

	req->general_flags = htole32(IWM_UMAC_SCAN_GEN_FLAGS_PASS_ALL |
	    IWM_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE |
	    IWM_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL);

	tail = (void *)((char *)&req->data +
		sizeof(struct iwm_scan_channel_cfg_umac) *
			sc->ucode_capa.n_scan_channels);

	/* Check if we're doing an active directed scan. */
	for (i = 0; i < nssid; i++) {
		tail->direct_scan[i].id = IEEE80211_ELEMID_SSID;
		tail->direct_scan[i].len = MIN(ss->ss_ssid[i].len,
		    IEEE80211_NWID_LEN);
		memcpy(tail->direct_scan[i].ssid, ss->ss_ssid[i].ssid,
		    tail->direct_scan[i].len);
		/* XXX debug */
	}
	if (nssid != 0) {
		req->general_flags |=
		    htole32(IWM_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT);
	} else
		req->general_flags |= htole32(IWM_UMAC_SCAN_GEN_FLAGS_PASSIVE);

	if (iwm_mvm_scan_use_ebs(sc))
		req->channel_flags = IWM_SCAN_CHANNEL_FLAG_EBS |
				     IWM_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
				     IWM_SCAN_CHANNEL_FLAG_CACHE_ADD;

	if (iwm_mvm_rrm_scan_needed(sc))
		req->general_flags |=
		    htole32(IWM_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED);

	ret = iwm_mvm_fill_probe_req(sc, &tail->preq);
	if (ret) {
		free(req, M_DEVBUF);
		return ret;
	}

	/* Specify the scan plan: We'll do one iteration. */
	tail->schedule[0].interval = 0;
	tail->schedule[0].iter_count = 1;

	ret = iwm_send_cmd(sc, &hcmd);
	if (!ret)
		IWM_DPRINTF(sc, IWM_DEBUG_SCAN,
		    "Scan request was sent successfully\n");
	free(req, M_DEVBUF);
	return ret;
}

int
iwm_mvm_lmac_scan(struct iwm_softc *sc)
{
	struct iwm_host_cmd hcmd = {
		.id = IWM_SCAN_OFFLOAD_REQUEST_CMD,
		.len = { 0, },
		.data = { NULL, },
		.flags = IWM_CMD_SYNC,
	};
	struct ieee80211_scan_state *ss = sc->sc_ic.ic_scan;
	struct iwm_scan_req_lmac *req;
	size_t req_len;
	uint8_t i, nssid;
	int ret;

	IWM_DPRINTF(sc, IWM_DEBUG_SCAN,
	    "Handling ieee80211 scan request\n");

	req_len = sizeof(struct iwm_scan_req_lmac) +
	    (sizeof(struct iwm_scan_channel_cfg_lmac) *
	    sc->ucode_capa.n_scan_channels) + sizeof(struct iwm_scan_probe_req);
	if (req_len > IWM_MAX_CMD_PAYLOAD_SIZE)
		return ENOMEM;
	req = malloc(req_len, M_DEVBUF, M_NOWAIT | M_ZERO);
	if (req == NULL)
		return ENOMEM;

	hcmd.len[0] = (uint16_t)req_len;
	hcmd.data[0] = (void *)req;

	/* These timings correspond to iwlwifi's UNASSOC scan. */
	req->active_dwell = 10;
	req->passive_dwell = 110;
	req->fragmented_dwell = 44;
	req->extended_dwell = 90;
	req->max_out_time = 0;
	req->suspend_time = 0;

	req->scan_prio = htole32(IWM_SCAN_PRIORITY_HIGH);
	req->rx_chain_select = iwm_mvm_scan_rx_chain(sc);
	req->iter_num = htole32(1);
	req->delay = 0;

	req->scan_flags = htole32(IWM_MVM_LMAC_SCAN_FLAG_PASS_ALL |
	    IWM_MVM_LMAC_SCAN_FLAG_ITER_COMPLETE |
	    IWM_MVM_LMAC_SCAN_FLAG_EXTENDED_DWELL);
	if (iwm_mvm_rrm_scan_needed(sc))
		req->scan_flags |= htole32(IWM_MVM_LMAC_SCAN_FLAGS_RRM_ENABLED);

	req->flags = iwm_mvm_scan_rxon_flags(sc->sc_ic.ic_scan->ss_chans[0]);

	req->filter_flags =
	    htole32(IWM_MAC_FILTER_ACCEPT_GRP | IWM_MAC_FILTER_IN_BEACON);

	/* Tx flags 2 GHz. */
	req->tx_cmd[0].tx_flags = htole32(IWM_TX_CMD_FLG_SEQ_CTL |
	    IWM_TX_CMD_FLG_BT_DIS);
	req->tx_cmd[0].rate_n_flags =
	    iwm_mvm_scan_rate_n_flags(sc, IEEE80211_CHAN_2GHZ, 1/*XXX*/);
	req->tx_cmd[0].sta_id = sc->sc_aux_sta.sta_id;

	/* Tx flags 5 GHz. */
	req->tx_cmd[1].tx_flags = htole32(IWM_TX_CMD_FLG_SEQ_CTL |
	    IWM_TX_CMD_FLG_BT_DIS);
	req->tx_cmd[1].rate_n_flags =
	    iwm_mvm_scan_rate_n_flags(sc, IEEE80211_CHAN_5GHZ, 1/*XXX*/);
	req->tx_cmd[1].sta_id = sc->sc_aux_sta.sta_id;

	/* Check if we're doing an active directed scan. */
	nssid = MIN(ss->ss_nssid, IWM_PROBE_OPTION_MAX);
	for (i = 0; i < nssid; i++) {
		req->direct_scan[i].id = IEEE80211_ELEMID_SSID;
		req->direct_scan[i].len = MIN(ss->ss_ssid[i].len,
		    IEEE80211_NWID_LEN);
		memcpy(req->direct_scan[i].ssid, ss->ss_ssid[i].ssid,
		    req->direct_scan[i].len);
		/* XXX debug */
	}
	if (nssid != 0) {
		req->scan_flags |=
		    htole32(IWM_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION);
	} else
		req->scan_flags |= htole32(IWM_MVM_LMAC_SCAN_FLAG_PASSIVE);

	req->n_channels = iwm_mvm_lmac_scan_fill_channels(sc,
	    (struct iwm_scan_channel_cfg_lmac *)req->data, nssid);

	ret = iwm_mvm_fill_probe_req(sc,
			    (struct iwm_scan_probe_req *)(req->data +
			    (sizeof(struct iwm_scan_channel_cfg_lmac) *
			    sc->ucode_capa.n_scan_channels)));
	if (ret) {
		free(req, M_DEVBUF);
		return ret;
	}

	/* Specify the scan plan: We'll do one iteration. */
	req->schedule[0].iterations = 1;
	req->schedule[0].full_scan_mul = 1;

	if (iwm_mvm_scan_use_ebs(sc)) {
		req->channel_opt[0].flags =
			htole16(IWM_SCAN_CHANNEL_FLAG_EBS |
				IWM_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
				IWM_SCAN_CHANNEL_FLAG_CACHE_ADD);
		req->channel_opt[0].non_ebs_ratio =
			htole16(IWM_DENSE_EBS_SCAN_RATIO);
		req->channel_opt[1].flags =
			htole16(IWM_SCAN_CHANNEL_FLAG_EBS |
				IWM_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
				IWM_SCAN_CHANNEL_FLAG_CACHE_ADD);
		req->channel_opt[1].non_ebs_ratio =
			htole16(IWM_SPARSE_EBS_SCAN_RATIO);
	}

	ret = iwm_send_cmd(sc, &hcmd);
	if (!ret) {
		IWM_DPRINTF(sc, IWM_DEBUG_SCAN,
		    "Scan request was sent successfully\n");
	}
	free(req, M_DEVBUF);
	return ret;
}