/**
 *  @brief Callback to finish 11H channel check handling.
 *  Not to be called directly to initiate channel check.
 *
 *  @param priv A pointer to mlan_private structure (cast from t_void*)
 *
 *  @return     MLAN_STATUS_SUCCESS/PENDING --success, otherwise fail
 *  @sa         wlan_uap_11h_channel_check_req
 */
static mlan_status
wlan_uap_callback_11h_channel_check_req(IN t_void * priv)
{
	mlan_status ret = MLAN_STATUS_FAILURE;
	mlan_private *pmpriv = (mlan_private *) priv;
	mlan_callbacks *pcb = (mlan_callbacks *) & pmpriv->adapter->callbacks;
	wlan_uap_get_info_cb_t *puap_state_chan_cb = &pmpriv->uap_state_chan_cb;
	/* keep copy as local variable */
	pmlan_ioctl_req pioctl = puap_state_chan_cb->pioctl_req_curr;

	ENTER();
	/* clear callback now that we're here */
	puap_state_chan_cb->get_chan_callback = MNULL;
	/* clear early to avoid race condition */
	puap_state_chan_cb->pioctl_req_curr = MNULL;

	/*
	 * Check if the region and channel requires a channel availability
	 * check.
	 */
	if ((puap_state_chan_cb->band_config & BAND_CONFIG_5GHZ) &&
	    wlan_11h_radar_detect_required(pmpriv, puap_state_chan_cb->channel)
	    && !wlan_11h_is_channel_under_nop(pmpriv->adapter,
					      puap_state_chan_cb->channel)) {

		/*
		 * Radar detection is required for this channel, make sure
		 * 11h is activated in the firmware
		 */
		ret = wlan_11h_activate(pmpriv, MNULL, MTRUE);
		ret = wlan_11h_config_master_radar_det(pmpriv, MTRUE);
		ret = wlan_11h_check_update_radar_det_state(pmpriv);

		/* Check for radar on the channel */
		ret = wlan_11h_issue_radar_detect(pmpriv,
						  pioctl,
						  puap_state_chan_cb->channel);
		if (ret == MLAN_STATUS_SUCCESS)
			ret = MLAN_STATUS_PENDING;
	} else {
		/* No command sent with the ioctl, need manually signal
		   completion */
		pcb->moal_ioctl_complete(pmpriv->adapter->pmoal_handle,
					 pioctl, MLAN_STATUS_FAILURE);
	}

	LEAVE();
	return ret;
}
Esempio n. 2
0
/**
 *  @brief Callback to finish BSS IOCTL START
 *  Not to be called directly to initiate bss_start
 *
 *  @param priv A pointer to mlan_private structure (cast from t_void*)
 *
 *  @return     MLAN_STATUS_PENDING --success, otherwise fail
 *  @sa         wlan_uap_bss_ioctl_start
 */
static mlan_status
wlan_uap_callback_bss_ioctl_start(IN t_void * priv)
{
    mlan_status ret = MLAN_STATUS_SUCCESS;
    mlan_private *pmpriv = (mlan_private *) priv;
    mlan_callbacks *pcb = (mlan_callbacks *) & pmpriv->adapter->callbacks;
    wlan_uap_get_info_cb_t *puap_state_chan_cb = &pmpriv->uap_state_chan_cb;
    t_u8 old_channel;

    ENTER();
    /* clear callback now that we're here */
    puap_state_chan_cb->get_chan_callback = MNULL;

    /*
     * Check if the region and channel requires we check for radar.
     */
    if ((puap_state_chan_cb->band_config & BAND_CONFIG_5GHZ) &&
        wlan_11h_radar_detect_required(pmpriv, puap_state_chan_cb->channel)) {
        /* first check if channel is under NOP */
        if (wlan_11h_is_channel_under_nop(pmpriv->adapter,
                                          puap_state_chan_cb->channel)) {
            /* recently we've seen radar on this channel */
            ret = MLAN_STATUS_FAILURE;
        }

        /* Check cached radar check on the channel */
        if (ret == MLAN_STATUS_SUCCESS)
            ret =
                wlan_11h_check_chan_report(pmpriv, puap_state_chan_cb->channel);

        /* Found radar: try to switch to a non-dfs channel */
        if (ret != MLAN_STATUS_SUCCESS) {
            old_channel = puap_state_chan_cb->channel;
            ret =
                wlan_11h_switch_non_dfs_chan(pmpriv,
                                             &puap_state_chan_cb->channel);

            if (ret == MLAN_STATUS_SUCCESS) {
                ret = wlan_uap_set_channel(pmpriv,
                                           pmpriv->uap_state_chan_cb.
                                           band_config,
                                           puap_state_chan_cb->channel);
                if (ret == MLAN_STATUS_SUCCESS) {
                    PRINTM(MMSG, "Radar found on channel %d,"
                           "switch to new channel %d.\n",
                           old_channel, puap_state_chan_cb->channel);
                } else {
                    PRINTM(MMSG, "Radar found on channel %d,"
                           " switch to new channel %d failed.\n",
                           old_channel, puap_state_chan_cb->channel);
                    pcb->moal_ioctl_complete(pmpriv->adapter->pmoal_handle,
                                             puap_state_chan_cb->
                                             pioctl_req_curr,
                                             MLAN_STATUS_FAILURE);
                    goto done;
                }
            } else {
                PRINTM(MMSG,
                       "Radar found on channel %d, no switch channel available.\n",
                       old_channel);
                /* No command sent with the ioctl, need manually signal
                   completion */
                pcb->moal_ioctl_complete(pmpriv->adapter->pmoal_handle,
                                         puap_state_chan_cb->pioctl_req_curr,
                                         MLAN_STATUS_FAILURE);
                goto done;
            }
        } else {
            PRINTM(MINFO, "No Radar found on channel %d\n",
                   puap_state_chan_cb->channel);
        }
    }

    /* else okay to send command: not DFS channel or no radar */
    ret = wlan_prepare_cmd(pmpriv,
                           HOST_CMD_APCMD_BSS_START,
                           HostCmd_ACT_GEN_SET,
                           0,
                           (t_void *) puap_state_chan_cb->pioctl_req_curr,
                           MNULL);
    if (ret == MLAN_STATUS_SUCCESS)
        ret = MLAN_STATUS_PENDING;

  done:
    puap_state_chan_cb->pioctl_req_curr = MNULL;        // prevent re-use
    LEAVE();
    return ret;
}