chan_freq_power_t *
wlan_get_cfp_by_band_and_channel(pmlan_adapter pmadapter,
				 t_u8 band,
				 t_u16 channel, region_chan_t * region_channel)
{
	region_chan_t *rc;
	chan_freq_power_t *cfp = MNULL;
	int i, j;

	ENTER();

	for (j = 0; !cfp && (j < MAX_REGION_CHANNEL_NUM); j++) {
		rc = &region_channel[j];

		if (!rc->valid || !rc->pcfp)
			continue;
		switch (rc->band) {
		case BAND_A:
			switch (band) {
			case BAND_AN:
			case BAND_A | BAND_AN:
			case BAND_A:	/* Matching BAND_A */
				break;

			default:
				continue;
			}
			break;
		case BAND_B:
		case BAND_G:
			switch (band) {
			case BAND_GN:
			case BAND_B | BAND_G | BAND_GN:
			case BAND_G | BAND_GN:
			case BAND_B | BAND_G:
			case BAND_B:	/* Matching BAND_B/G */
			case BAND_G:
			case 0:
				break;
			default:
				continue;
			}
			break;
		default:
			continue;
		}
		if (channel == FIRST_VALID_CHANNEL)
			cfp = &rc->pcfp[0];
		else {
			for (i = 0; i < rc->num_cfp; i++) {
				if (rc->pcfp[i].channel == channel) {
					cfp = &rc->pcfp[i];
					break;
				}
			}
		}
	}

	if (!cfp && channel)
		PRINTM(MCMND, "wlan_get_cfp_by_band_and_channel(): cannot find "
		       "cfp by band %d & channel %d\n", band, channel);

	LEAVE();
	return cfp;
}
示例#2
0
/** 
 *  @brief configure deep sleep 
 *   
 *  @param dev      A pointer to net_device structure
 *  @param req      A pointer to ifreq structure
 *  @return         0 --success, otherwise fail
 */
static int
woal_uap_deep_sleep(struct net_device *dev, struct ifreq *req)
{
    moal_private *priv = (moal_private *) netdev_priv(dev);
    mlan_ioctl_req *ioctl_req = NULL;
    mlan_ds_pm_cfg *pm = NULL;
    deep_sleep_para param;
    int ret = 0;

    ENTER();
    memset(&param, 0, sizeof(param));

    /* Sanity check */
    if (req->ifr_data == NULL) {
        PRINTM(MERROR, "woal_uap_deep_sleep() corrupt data\n");
        ret = -EFAULT;
        goto done;
    }
    if (copy_from_user(&param, req->ifr_data, sizeof(param))) {
        PRINTM(MERROR, "Copy from user failed\n");
        ret = -EFAULT;
        goto done;
    }
    DBG_HEXDUMP(MCMD_D, "deep_sleep_para", (t_u8 *) & param, sizeof(param));

    ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
    if (ioctl_req == NULL) {
        LEAVE();
        return -ENOMEM;
    }
    pm = (mlan_ds_pm_cfg *) ioctl_req->pbuf;
    pm->sub_command = MLAN_OID_PM_CFG_DEEP_SLEEP;
    ioctl_req->req_id = MLAN_IOCTL_PM_CFG;

    if (!param.action) {
        /* Get deep_sleep status from MLAN */
        ioctl_req->action = MLAN_ACT_GET;
    } else {
        /* Set deep_sleep in MLAN */
        ioctl_req->action = MLAN_ACT_SET;
        if (param.deep_sleep == MTRUE) {
            pm->param.auto_deep_sleep.auto_ds = DEEP_SLEEP_ON;
            pm->param.auto_deep_sleep.idletime = param.idle_time;
        } else {
            pm->param.auto_deep_sleep.auto_ds = DEEP_SLEEP_OFF;
        }
    }
    if (MLAN_STATUS_SUCCESS !=
        woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT)) {
        ret = -EFAULT;
        goto done;
    }
    if (pm->param.auto_deep_sleep.auto_ds == DEEP_SLEEP_ON)
        param.deep_sleep = MTRUE;
    else
        param.deep_sleep = MFALSE;
    param.idle_time = pm->param.auto_deep_sleep.idletime;
    /* Copy to user */
    if (copy_to_user(req->ifr_data, &param, sizeof(param))) {
        PRINTM(MERROR, "Copy to user failed!\n");
        ret = -EFAULT;
        goto done;
    }
  done:
    if (ioctl_req)
        kfree(ioctl_req);
    LEAVE();
    return ret;
}
示例#3
0
/** 
 *  @brief uap power mode ioctl handler
 *   
 *  @param dev      A pointer to net_device structure
 *  @param req      A pointer to ifreq structure
 *  @return         0 --success, otherwise fail
 */
static int
woal_uap_power_mode_ioctl(struct net_device *dev, struct ifreq *req)
{
    moal_private *priv = (moal_private *) netdev_priv(dev);
    mlan_ioctl_req *ioctl_req = NULL;
    mlan_ds_pm_cfg *pm_cfg = NULL;
    mlan_ds_ps_mgmt ps_mgmt;
    int ret = 0;

    ENTER();

    memset(&ps_mgmt, 0, sizeof(mlan_ds_ps_mgmt));

    /* Sanity check */
    if (req->ifr_data == NULL) {
        PRINTM(MERROR, "uap_power_mode_ioctl() corrupt data\n");
        ret = -EFAULT;
        goto done;
    }
    if (copy_from_user(&ps_mgmt, req->ifr_data, sizeof(mlan_ds_ps_mgmt))) {
        PRINTM(MERROR, "Copy from user failed\n");
        ret = -EFAULT;
        goto done;
    }

    PRINTM(MIOCTL,
           "ioctl power: flag=0x%x ps_mode=%d ctrl_bitmap=%d min_sleep=%d max_sleep=%d "
           "inact_to=%d min_awake=%d max_awake=%d\n", ps_mgmt.flags,
           (int) ps_mgmt.ps_mode, (int) ps_mgmt.sleep_param.ctrl_bitmap,
           (int) ps_mgmt.sleep_param.min_sleep,
           (int) ps_mgmt.sleep_param.max_sleep,
           (int) ps_mgmt.inact_param.inactivity_to,
           (int) ps_mgmt.inact_param.min_awake,
           (int) ps_mgmt.inact_param.max_awake);

    if (ps_mgmt.
        flags & ~(PS_FLAG_PS_MODE | PS_FLAG_SLEEP_PARAM |
                  PS_FLAG_INACT_SLEEP_PARAM)) {
        PRINTM(MERROR, "Invalid parameter: flags = 0x%x\n", ps_mgmt.flags);
        ret = -EINVAL;
        goto done;
    }

    if (ps_mgmt.ps_mode > PS_MODE_INACTIVITY) {
        PRINTM(MERROR, "Invalid parameter: ps_mode = %d\n",
               (int) ps_mgmt.flags);
        ret = -EINVAL;
        goto done;
    }

    ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
    if (ioctl_req == NULL) {
        ret = -ENOMEM;
        goto done;
    }
    pm_cfg = (mlan_ds_pm_cfg *) ioctl_req->pbuf;
    pm_cfg->sub_command = MLAN_OID_PM_CFG_PS_MODE;
    ioctl_req->req_id = MLAN_IOCTL_PM_CFG;
    if (ps_mgmt.flags) {
        ioctl_req->action = MLAN_ACT_SET;
        memcpy(&pm_cfg->param.ps_mgmt, &ps_mgmt, sizeof(mlan_ds_ps_mgmt));
    } else {
        ioctl_req->action = MLAN_ACT_GET;
    }

    if (MLAN_STATUS_SUCCESS !=
        woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT)) {
        ret = -EFAULT;
        if (copy_to_user(req->ifr_data, &ioctl_req->status_code, sizeof(t_u32)))
            PRINTM(MERROR, "Copy to user failed!\n");
        goto done;
    }
    if (!ps_mgmt.flags) {
        /* Copy to user */
        if (copy_to_user
            (req->ifr_data, &pm_cfg->param.ps_mgmt, sizeof(mlan_ds_ps_mgmt))) {
            PRINTM(MERROR, "Copy to user failed!\n");
            ret = -EFAULT;
            goto done;
        }
    }
  done:
    if (ioctl_req)
        kfree(ioctl_req);
    LEAVE();
    return ret;
}
/**
 *  @brief This function generates domain_info from parsed_region_chan
 *
 *  @param pmadapter            Pointer to mlan_adapter structure
 *  @param parsed_region_chan   Pointer to parsed_region_chan_11d_t
 *
 *  @return                     MLAN_STATUS_SUCCESS
 */
static mlan_status
wlan_11d_generate_domain_info(pmlan_adapter pmadapter,
			      parsed_region_chan_11d_t *parsed_region_chan)
{
	t_u8 no_of_sub_band = 0;
	t_u8 no_of_chan = parsed_region_chan->no_of_chan;
	t_u8 no_of_parsed_chan = 0;
	t_u8 first_chan = 0, next_chan = 0, max_pwr = 0;
	t_u8 i, flag = MFALSE;
	wlan_802_11d_domain_reg_t *domain_info = &pmadapter->domain_reg;

	ENTER();

	/* Should be only place that clear domain_reg (besides init) */
	memset(pmadapter, domain_info, 0, sizeof(wlan_802_11d_domain_reg_t));

	/* Set country code */
	memcpy(pmadapter, domain_info->country_code,
	       wlan_11d_code_2_region(pmadapter, (t_u8)pmadapter->region_code),
	       COUNTRY_CODE_LEN);

	PRINTM(MINFO, "11D: Number of channel = %d\n", no_of_chan);
	HEXDUMP("11D: parsed_region_chan", (t_u8 *)parsed_region_chan,
		sizeof(parsed_region_chan_11d_t));

	/* Set channel and power */
	for (i = 0; i < no_of_chan; i++) {
		if (!flag) {
			flag = MTRUE;
			next_chan = first_chan =
				parsed_region_chan->chan_pwr[i].chan;
			max_pwr = parsed_region_chan->chan_pwr[i].pwr;
			no_of_parsed_chan = 1;
			continue;
		}

		if (parsed_region_chan->chan_pwr[i].chan == next_chan + 1 &&
		    parsed_region_chan->chan_pwr[i].pwr == max_pwr) {
			next_chan++;
			no_of_parsed_chan++;
		} else {
			domain_info->sub_band[no_of_sub_band].first_chan =
				first_chan;
			domain_info->sub_band[no_of_sub_band].no_of_chan =
				no_of_parsed_chan;
			domain_info->sub_band[no_of_sub_band].max_tx_pwr =
				max_pwr;
			no_of_sub_band++;
			no_of_parsed_chan = 1;
			next_chan = first_chan =
				parsed_region_chan->chan_pwr[i].chan;
			max_pwr = parsed_region_chan->chan_pwr[i].pwr;
		}
	}

	if (flag) {
		domain_info->sub_band[no_of_sub_band].first_chan = first_chan;
		domain_info->sub_band[no_of_sub_band].no_of_chan =
			no_of_parsed_chan;
		domain_info->sub_band[no_of_sub_band].max_tx_pwr = max_pwr;
		no_of_sub_band++;
	}
	domain_info->no_of_sub_band = no_of_sub_band;

	PRINTM(MINFO, "11D: Number of sub-band =0x%x\n",
	       domain_info->no_of_sub_band);
	HEXDUMP("11D: domain_info", (t_u8 *)domain_info,
		COUNTRY_CODE_LEN + 1 +
		sizeof(IEEEtypes_SubbandSet_t) * no_of_sub_band);
	LEAVE();
	return MLAN_STATUS_SUCCESS;
}
示例#5
0
/** 
 *  @brief uap hs_cfg ioctl handler
 *   
 *  @param dev      A pointer to net_device structure
 *  @param req      A pointer to ifreq structure
 *  @return         0 --success, otherwise fail
 */
static int
woal_uap_hs_cfg(struct net_device *dev, struct ifreq *req)
{
    moal_private *priv = (moal_private *) netdev_priv(dev);
    mlan_ds_hs_cfg hscfg;
    ds_hs_cfg hs_cfg;
    t_u16 action;
    int ret = 0;

    ENTER();

    memset(&hscfg, 0, sizeof(mlan_ds_hs_cfg));
    memset(&hs_cfg, 0, sizeof(ds_hs_cfg));

    /* Sanity check */
    if (req->ifr_data == NULL) {
        PRINTM(MERROR, "uap_power_mode_ioctl() corrupt data\n");
        ret = -EFAULT;
        goto done;
    }
    if (copy_from_user(&hs_cfg, req->ifr_data, sizeof(ds_hs_cfg))) {
        PRINTM(MERROR, "Copy from user failed\n");
        ret = -EFAULT;
        goto done;
    }

    PRINTM(MIOCTL,
           "ioctl hscfg: flags=0x%lx condition=0x%lx gpio=%d gap=0x%lx\n",
           hs_cfg.flags, hs_cfg.conditions, (int) hs_cfg.gpio, hs_cfg.gap);

    if (hs_cfg.flags & HS_CFG_FLAG_SET) {
        action = MLAN_ACT_SET;
        if (hs_cfg.flags != HS_CFG_FLAG_ALL) {
            woal_set_get_hs_params(priv, MLAN_ACT_GET, MOAL_IOCTL_WAIT, &hscfg);
        }
        if (hs_cfg.flags & HS_CFG_FLAG_CONDITION)
            hscfg.conditions = hs_cfg.conditions;
        if (hs_cfg.flags & HS_CFG_FLAG_GPIO)
            hscfg.gpio = hs_cfg.gpio;
        if (hs_cfg.flags & HS_CFG_FLAG_GAP)
            hscfg.gap = hs_cfg.gap;

        /* Issue IOCTL to set up parameters */
        hscfg.is_invoke_hostcmd = MFALSE;
        if (MLAN_STATUS_SUCCESS !=
            woal_set_get_hs_params(priv, action, MOAL_IOCTL_WAIT, &hscfg)) {
            ret = -EFAULT;
            goto done;
        }
    } else {
        action = MLAN_ACT_GET;
    }

    /* Issue IOCTL to invoke hostcmd */
    hscfg.is_invoke_hostcmd = MTRUE;
    if (MLAN_STATUS_SUCCESS !=
        woal_set_get_hs_params(priv, action, MOAL_IOCTL_WAIT, &hscfg)) {
        ret = -EFAULT;
        goto done;
    }
    if (!(hs_cfg.flags & HS_CFG_FLAG_SET)) {
        hs_cfg.flags =
            HS_CFG_FLAG_CONDITION | HS_CFG_FLAG_GPIO | HS_CFG_FLAG_GAP;
        hs_cfg.conditions = hscfg.conditions;
        hs_cfg.gpio = hscfg.gpio;
        hs_cfg.gap = hscfg.gap;
        /* Copy to user */
        if (copy_to_user(req->ifr_data, &hs_cfg, sizeof(ds_hs_cfg))) {
            PRINTM(MERROR, "Copy to user failed!\n");
            ret = -EFAULT;
            goto done;
        }
    }

  done:
    LEAVE();
    return ret;
}
/** 
 *  @brief This function handles disconnect event, reports disconnect
 *  		to upper layer, cleans tx/rx packets,
 *  		resets link state etc.
 *  
 *  @param priv            A pointer to mlan_private structure
 *  @param drv_disconnect  Flag indicating the driver should disconnect
 *                         and flush pending packets.
 *
 *  @return        N/A
 */
t_void
wlan_reset_connect_state(pmlan_private priv, t_u8 drv_disconnect)
{
    mlan_adapter *pmadapter = priv->adapter;
    mlan_status ret = MLAN_STATUS_SUCCESS;
    state_11d_t enable;

    ENTER();

    if (priv->media_connected != MTRUE) {
        LEAVE();
        return;
    }

    PRINTM(MINFO, "Handles disconnect event.\n");

    if (drv_disconnect) {
        priv->media_connected = MFALSE;
        wlan_11h_check_update_radar_det_state(priv);
    }

    if (priv->port_ctrl_mode == MTRUE) {
        /* Close the port on Disconnect */
        PRINTM(MINFO, "DISC: port_status = CLOSED\n");
        priv->port_open = MFALSE;
    }
    priv->scan_block = MFALSE;

    /* Reset SNR/NF/RSSI values */
    priv->data_rssi_last = 0;
    priv->data_nf_last = 0;
    priv->data_rssi_avg = 0;
    priv->data_nf_avg = 0;
    priv->bcn_rssi_last = 0;
    priv->bcn_nf_last = 0;
    priv->bcn_rssi_avg = 0;
    priv->bcn_nf_avg = 0;
    priv->rxpd_rate = 0;
    priv->rxpd_htinfo = 0;

    priv->sec_info.ewpa_enabled = MFALSE;
    priv->sec_info.wpa_enabled = MFALSE;
    priv->sec_info.wpa2_enabled = MFALSE;
    priv->wpa_ie_len = 0;

    priv->sec_info.wapi_enabled = MFALSE;
    priv->wapi_ie_len = 0;
    priv->sec_info.wapi_key_on = MFALSE;

    priv->sec_info.encryption_mode = MLAN_ENCRYPTION_MODE_NONE;

    /* Enable auto data rate */
    priv->is_data_rate_auto = MTRUE;
    priv->data_rate = 0;

    if (priv->bss_mode == MLAN_BSS_MODE_IBSS) {
        priv->adhoc_state = ADHOC_IDLE;
        priv->adhoc_is_link_sensed = MFALSE;
        priv->intf_state_11h.adhoc_auto_sel_chan = MTRUE;
    }

    if (drv_disconnect) {
        /* Free Tx and Rx packets, report disconnect to upper layer */
        wlan_clean_txrx(priv);

        /* Need to erase the current SSID and BSSID info */
        memset(pmadapter,
               &priv->curr_bss_params, 0x00, sizeof(priv->curr_bss_params));
    }
    pmadapter->tx_lock_flag = MFALSE;
    pmadapter->pps_uapsd_mode = MFALSE;

    if ((wlan_11d_is_enabled(priv)) &&
        (priv->state_11d.user_enable_11d == DISABLE_11D)) {

        priv->state_11d.enable_11d = DISABLE_11D;
        enable = DISABLE_11D;

        /* Send cmd to FW to enable/disable 11D function */
        ret = wlan_prepare_cmd(priv,
                               HostCmd_CMD_802_11_SNMP_MIB,
                               HostCmd_ACT_GEN_SET, Dot11D_i, MNULL, &enable);
        if (ret)
            PRINTM(MERROR, "11D: Failed to enable 11D\n");
    }
    if (pmadapter->num_cmd_timeout && pmadapter->curr_cmd &&
        (pmadapter->cmd_timer_is_set == MFALSE)) {
        LEAVE();
        return;
    }

    wlan_recv_event(priv, MLAN_EVENT_ID_FW_DISCONNECTED, MNULL);

    LEAVE();
}
/**
 *  @brief This function generates 11D info from user specified regioncode
 *         and download to FW
 *
 *  @param pmpriv       A pointer to mlan_private structure
 *  @param band         Band to create
 *
 *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
 */
mlan_status
wlan_11d_create_dnld_countryinfo(mlan_private *pmpriv, t_u8 band)
{
	mlan_status ret = MLAN_STATUS_SUCCESS;
	mlan_adapter *pmadapter = pmpriv->adapter;
	region_chan_t *region_chan;
	parsed_region_chan_11d_t parsed_region_chan;
	t_u8 j;

	ENTER();

	/* Only valid if 11D is enabled */
	if (wlan_11d_is_enabled(pmpriv)) {

		PRINTM(MINFO, "11D: Band[%d]\n", band);

		/* Update parsed_region_chan; download domain info to FW */

		/* Find region channel */
		for (j = 0; j < MAX_REGION_CHANNEL_NUM; j++) {
			region_chan = &pmadapter->region_channel[j];

			PRINTM(MINFO, "11D: [%d] region_chan->Band[%d]\n", j,
			       region_chan->band);

			if (!region_chan || !region_chan->valid ||
			    !region_chan->pcfp)
				continue;
			switch (region_chan->band) {
			case BAND_A:
				switch (band) {
				case BAND_A:
				case BAND_AN:
				case BAND_A | BAND_AN:
				case BAND_A | BAND_AN | BAND_AAC:
					break;
				default:
					continue;
				}
				break;
			case BAND_B:
			case BAND_G:
				switch (band) {
				case BAND_B:
				case BAND_G:
				case BAND_G | BAND_B:
				case BAND_GN:
				case BAND_G | BAND_GN:
				case BAND_B | BAND_G | BAND_GN:
				case BAND_B | BAND_G | BAND_GN | BAND_GAC:
					break;
				default:
					continue;
				}
				break;
			default:
				continue;
			}
			break;
		}

		/* Check if region channel found */
		if (j >= MAX_REGION_CHANNEL_NUM) {
			PRINTM(MERROR, "11D: region_chan not found. Band[%d]\n",
			       band);
			LEAVE();
			return MLAN_STATUS_FAILURE;
		}

		/* Generate parsed region channel info from region channel */
		memset(pmadapter, &parsed_region_chan, 0,
		       sizeof(parsed_region_chan_11d_t));
		wlan_11d_generate_parsed_region_chan(pmadapter, region_chan,
						     &parsed_region_chan);

		/* Generate domain info from parsed region channel info */
		wlan_11d_generate_domain_info(pmadapter, &parsed_region_chan);

		/* Set domain info */
		ret = wlan_11d_send_domain_info(pmpriv, MNULL);
		if (ret) {
			PRINTM(MERROR,
			       "11D: Error sending domain info to FW\n");
		}
	}

	LEAVE();
	return ret;
}
/**  @brief This function handles client driver suspend
 *  
 *  @param dev	   A pointer to device structure
 *  @return 	   MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
 */
int
woal_sdio_suspend(struct device *dev)
{
    struct sdio_func *func = dev_to_sdio_func(dev);
    mmc_pm_flag_t pm_flags = 0;
    moal_handle *handle = NULL;
    struct sdio_mmc_card *cardp;
    int i;
    int ret = MLAN_STATUS_SUCCESS;
    int hs_actived = 0;
    mlan_ds_ps_info pm_info;

    ENTER();
    PRINTM(MCMND, "<--- Enter woal_sdio_suspend --->\n");
    if (func) {
        pm_flags = sdio_get_host_pm_caps(func);
        PRINTM(MCMND, "%s: suspend: PM flags = 0x%x\n", sdio_func_id(func),
               pm_flags);
        if (!(pm_flags & MMC_PM_KEEP_POWER)) {
            PRINTM(MERROR, "%s: cannot remain alive while host is suspended\n",
                   sdio_func_id(func));
            LEAVE();
            return -ENOSYS;
        }
        cardp = sdio_get_drvdata(func);
        if (!cardp || !cardp->handle) {
            PRINTM(MERROR, "Card or moal_handle structure is not valid\n");
            LEAVE();
            return MLAN_STATUS_SUCCESS;
        }
    } else {
        PRINTM(MERROR, "sdio_func is not specified\n");
        LEAVE();
        return MLAN_STATUS_SUCCESS;
    }

    handle = cardp->handle;
    handle->suspend_fail = MFALSE;
    memset(&pm_info, 0, sizeof(pm_info));
    if (MLAN_STATUS_SUCCESS ==
        woal_get_pm_info(woal_get_priv(handle, MLAN_BSS_ROLE_ANY), &pm_info)) {
        if (pm_info.is_suspend_allowed == MFALSE) {
            PRINTM(MCMND, "suspend not allowed!");
            ret = -EBUSY;
            goto done;
        }
    }
    for (i = 0; i < handle->priv_num; i++)
        netif_device_detach(handle->priv[i]->netdev);

    if (pm_keep_power) {
        /* Enable the Host Sleep */
#ifdef MMC_PM_FUNC_SUSPENDED
        handle->suspend_notify_req = MTRUE;
#endif
        hs_actived = woal_enable_hs(woal_get_priv(handle, MLAN_BSS_ROLE_ANY));
#ifdef MMC_PM_FUNC_SUSPENDED
        handle->suspend_notify_req = MFALSE;
#endif
        if (hs_actived) {
#ifdef MMC_PM_SKIP_RESUME_PROBE
            PRINTM(MCMND, "suspend with MMC_PM_KEEP_POWER and "
                   "MMC_PM_SKIP_RESUME_PROBE\n");
            ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER |
                                         MMC_PM_SKIP_RESUME_PROBE);
#else
            PRINTM(MCMND, "suspend with MMC_PM_KEEP_POWER\n");
            ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
#endif
        } else {
            PRINTM(MCMND, "HS not actived, suspend fail!");
            ret = -EBUSY;
            goto done;
        }
    }

    /* Indicate device suspended */
    handle->is_suspended = MTRUE;
  done:
    PRINTM(MCMND, "<--- Leave woal_sdio_suspend --->\n");
    LEAVE();
    return ret;
}
/**
 *  @brief This function tells firmware to send a NULL data packet.
 *
 *  @param priv     A pointer to mlan_private structure
 *  @param flags    Transmit Pkt Flags
 *
 *  @return 	    MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise failure
 */
mlan_status
wlan_send_null_packet(pmlan_private priv, t_u8 flags)
{
	pmlan_adapter pmadapter = priv->adapter;
	TxPD *ptx_pd;
/* sizeof(TxPD) + Interface specific header */
#define NULL_PACKET_HDR 256
	t_u32 data_len = NULL_PACKET_HDR;
	pmlan_buffer pmbuf = MNULL;
	t_u8 *ptr;
	mlan_status ret = MLAN_STATUS_SUCCESS;
#ifdef DEBUG_LEVEL1
	t_u32 sec, usec;
#endif

	ENTER();

	if (pmadapter->surprise_removed == MTRUE) {
		ret = MLAN_STATUS_FAILURE;
		goto done;
	}

	if (priv->media_connected == MFALSE) {
		ret = MLAN_STATUS_FAILURE;
		goto done;
	}

	if (pmadapter->data_sent == MTRUE) {
		ret = MLAN_STATUS_FAILURE;
		goto done;
	}

	pmbuf = wlan_alloc_mlan_buffer(pmadapter, data_len, 0,
				       MOAL_MALLOC_BUFFER);
	if (!pmbuf) {
		ret = MLAN_STATUS_FAILURE;
		goto done;
	}
	memset(pmadapter, pmbuf->pbuf, 0, data_len);
	pmbuf->bss_index = priv->bss_index;
	pmbuf->buf_type = MLAN_BUF_TYPE_DATA;
	ptr = pmbuf->pbuf + pmbuf->data_offset;
	pmbuf->data_len = sizeof(TxPD) + INTF_HEADER_LEN;
	ptx_pd = (TxPD *) (ptr + INTF_HEADER_LEN);
	ptx_pd->tx_control = priv->pkt_tx_ctrl;
	ptx_pd->flags = flags;
	ptx_pd->priority = WMM_HIGHEST_PRIORITY;
	ptx_pd->tx_pkt_offset = sizeof(TxPD);
	/* Set the BSS number to TxPD */
	ptx_pd->bss_num = GET_BSS_NUM(priv);
	ptx_pd->bss_type = priv->bss_type;

	endian_convert_TxPD(ptx_pd);

	ret = wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_DATA, pmbuf, MNULL);

	switch (ret) {
	case MLAN_STATUS_RESOURCE:
		wlan_free_mlan_buffer(pmadapter, pmbuf);
		PRINTM(MERROR, "STA Tx Error: Failed to send NULL packet!\n");
		pmadapter->dbg.num_tx_host_to_card_failure++;
		goto done;
	case MLAN_STATUS_FAILURE:
		pmadapter->data_sent = MFALSE;
		wlan_free_mlan_buffer(pmadapter, pmbuf);
		PRINTM(MERROR, "STA Tx Error: Failed to send NULL packet!\n");
		pmadapter->dbg.num_tx_host_to_card_failure++;
		goto done;
	case MLAN_STATUS_SUCCESS:
		wlan_free_mlan_buffer(pmadapter, pmbuf);
		PRINTM(MINFO, "STA Tx: Successfully send the NULL packet\n");
		pmadapter->tx_lock_flag = MTRUE;
		break;
	case MLAN_STATUS_PENDING:
		pmadapter->data_sent = MFALSE;
		pmadapter->tx_lock_flag = MTRUE;
		break;
	default:
		break;
	}

	PRINTM_GET_SYS_TIME(MDATA, &sec, &usec);
	PRINTM_NETINTF(MDATA, priv);
	PRINTM(MDATA, "%lu.%06lu : Null data => FW\n", sec, usec);
	DBG_HEXDUMP(MDAT_D, "Null data", ptr, sizeof(TxPD) + INTF_HEADER_LEN);
done:
	LEAVE();
	return ret;
}
示例#10
0
/**
 *  @brief Debug print display of the input measurement report
 *
 *  @param pmeas_rpt  Pointer to measurement report to display
 *
 *  @return          N/A
 */
static
	void
wlan_meas_dump_meas_rpt(const HostCmd_DS_MEASUREMENT_REPORT *pmeas_rpt)
{
	ENTER();

	PRINTM(MINFO, "Meas: Rpt: ------------------------------\n");
	PRINTM(MINFO, "Meas: Rpt: mac_addr: " MACSTR "\n",
	       MAC2STR(pmeas_rpt->mac_addr));

	PRINTM(MINFO, "Meas: Rpt:  dlgTkn: %d\n", pmeas_rpt->dialog_token);

	PRINTM(MINFO, "Meas: Rpt: rptMode: (%x): Rfs[%c] ICp[%c] Lt[%c]\n",
	       *(t_u8 *)&pmeas_rpt->rpt_mode,
	       pmeas_rpt->rpt_mode.refused ? 'X' : ' ',
	       pmeas_rpt->rpt_mode.incapable ? 'X' : ' ',
	       pmeas_rpt->rpt_mode.late ? 'X' : ' ');
#ifdef DEBUG_LEVEL2
	PRINTM(MINFO, "Meas: Rpt: measTyp: %s\n",
	       wlan_meas_get_meas_type_str(pmeas_rpt->meas_type));
#endif

	switch (pmeas_rpt->meas_type) {
	case WLAN_MEAS_BASIC:
		PRINTM(MINFO, "Meas: Rpt: chan: %u\n",
		       pmeas_rpt->rpt.basic.channel);
		PRINTM(MINFO, "Meas: Rpt: strt: %llu\n",
		       wlan_le64_to_cpu(pmeas_rpt->rpt.basic.start_time));
		PRINTM(MINFO, "Meas: Rpt:  dur: %u\n",
		       wlan_le16_to_cpu(pmeas_rpt->rpt.basic.duration));
		PRINTM(MINFO, "Meas: Rpt:  bas: (%x): unmsd[%c], radar[%c]\n",
		       *(t_u8 *)&(pmeas_rpt->rpt.basic.map),
		       pmeas_rpt->rpt.basic.map.unmeasured ? 'X' : ' ',
		       pmeas_rpt->rpt.basic.map.radar ? 'X' : ' ');
		PRINTM(MINFO, "Meas: Rpt:  bas: unidSig[%c] ofdm[%c] bss[%c]\n",
		       pmeas_rpt->rpt.basic.map.unidentified_sig ? 'X' : ' ',
		       pmeas_rpt->rpt.basic.map.ofdm_preamble ? 'X' : ' ',
		       pmeas_rpt->rpt.basic.map.bss ? 'X' : ' ');
		break;
	default:
		PRINTM(MINFO, "Meas: Rpt: <unhandled>\n");
		break;
	}

	PRINTM(MINFO, "Meas: Rpt: ------------------------------\n");
	LEAVE();
}
示例#11
0
/**
 *  @brief Debug print display of the input measurement request
 *
 *  @param pmeas_req  Pointer to the measurement request to display
 *
 *  @return          N/A
 */
static
	void
wlan_meas_dump_meas_req(const HostCmd_DS_MEASUREMENT_REQUEST *pmeas_req)
{
	ENTER();

	PRINTM(MINFO, "Meas: Req: ------------------------------\n");

	PRINTM(MINFO, "Meas: Req: mac_addr: " MACSTR "\n",
	       MAC2STR(pmeas_req->mac_addr));

	PRINTM(MINFO, "Meas: Req:  dlgTkn: %d\n", pmeas_req->dialog_token);
	PRINTM(MINFO, "Meas: Req:    mode: dm[%c] rpt[%c] req[%c]\n",
	       pmeas_req->req_mode.duration_mandatory ? 'X' : ' ',
	       pmeas_req->req_mode.report ? 'X' : ' ',
	       pmeas_req->req_mode.request ? 'X' : ' ');
	PRINTM(MINFO, "Meas: Req:        : en[%c] par[%c]\n",
	       pmeas_req->req_mode.enable ? 'X' : ' ',
	       pmeas_req->req_mode.parallel ? 'X' : ' ');
#ifdef DEBUG_LEVEL2
	PRINTM(MINFO, "Meas: Req: measTyp: %s\n",
	       wlan_meas_get_meas_type_str(pmeas_req->meas_type));
#endif

	switch (pmeas_req->meas_type) {
	case WLAN_MEAS_BASIC:
		/* Lazy cheat, fields of bas, cca, rpi union match on the
		   request */
		PRINTM(MINFO, "Meas: Req: chan: %u\n",
		       pmeas_req->req.basic.channel);
		PRINTM(MINFO, "Meas: Req: strt: %llu\n",
		       wlan_le64_to_cpu(pmeas_req->req.basic.start_time));
		PRINTM(MINFO, "Meas: Req:  dur: %u\n",
		       wlan_le16_to_cpu(pmeas_req->req.basic.duration));
		break;
	default:
		PRINTM(MINFO, "Meas: Req: <unhandled>\n");
		break;
	}

	PRINTM(MINFO, "Meas: Req: ------------------------------\n");
	LEAVE();
}
/**
 *  @brief This function sets region table.
 *
 *  @param pmpriv  A pointer to mlan_private structure
 *  @param region  The region code
 *  @param band    The band
 *
 *  @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
 */
mlan_status
wlan_set_regiontable(mlan_private * pmpriv, t_u8 region, t_u8 band)
{
	mlan_adapter *pmadapter = pmpriv->adapter;
	int i = 0, j;
	chan_freq_power_t *cfp;
	int cfp_no;
	region_chan_t region_chan_old[MAX_REGION_CHANNEL_NUM];

	ENTER();

	memcpy(pmadapter, region_chan_old, pmadapter->region_channel,
	       sizeof(pmadapter->region_channel));
	memset(pmadapter, pmadapter->region_channel, 0,
	       sizeof(pmadapter->region_channel));

	if (band & (BAND_B | BAND_G | BAND_GN)) {
		cfp = wlan_get_region_cfp_table(pmadapter, region,
						BAND_G | BAND_B | BAND_GN,
						&cfp_no);
		if (cfp) {
			pmadapter->region_channel[i].num_cfp = (t_u8) cfp_no;
			pmadapter->region_channel[i].pcfp = cfp;
		} else {
			PRINTM(MERROR, "wrong region code %#x in Band B-G\n",
			       region);
			LEAVE();
			return MLAN_STATUS_FAILURE;
		}
		pmadapter->region_channel[i].valid = MTRUE;
		pmadapter->region_channel[i].region = region;
		if (band & BAND_GN)
			pmadapter->region_channel[i].band = BAND_G;
		else
			pmadapter->region_channel[i].band =
				(band & BAND_G) ? BAND_G : BAND_B;

		for (j = 0; j < MAX_REGION_CHANNEL_NUM; j++) {
			if (region_chan_old[j].band & (BAND_B | BAND_G))
				break;
		}
		if ((j < MAX_REGION_CHANNEL_NUM) && region_chan_old[j].valid)
			wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no,
					      region_chan_old[j].pcfp,
					      region_chan_old[j].num_cfp);
		else
			wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no, MNULL, 0);

		i++;
	}
	if (band & (BAND_A | BAND_AN)) {
		cfp = wlan_get_region_cfp_table(pmadapter, region, BAND_A,
						&cfp_no);
		if (cfp) {
			pmadapter->region_channel[i].num_cfp = (t_u8) cfp_no;
			pmadapter->region_channel[i].pcfp = cfp;
		} else {
			PRINTM(MERROR, "wrong region code %#x in Band A\n",
			       region);
			LEAVE();
			return MLAN_STATUS_FAILURE;
		}
		pmadapter->region_channel[i].valid = MTRUE;
		pmadapter->region_channel[i].region = region;
		pmadapter->region_channel[i].band = BAND_A;

		for (j = 0; j < MAX_REGION_CHANNEL_NUM; j++) {
			if (region_chan_old[j].band & BAND_A)
				break;
		}
		if ((j < MAX_REGION_CHANNEL_NUM) && region_chan_old[j].valid)
			wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no,
					      region_chan_old[j].pcfp,
					      region_chan_old[j].num_cfp);
		else
			wlan_cfp_copy_dynamic(pmadapter, cfp, cfp_no, MNULL, 0);
	}
	LEAVE();
	return MLAN_STATUS_SUCCESS;
}
/**
 *  @brief Get supported data rates
 *
 *  @param pmpriv           A pointer to mlan_private structure
 *  @param bss_mode         The specified BSS mode (Infra/IBSS)
 *  @param config_bands     The specified band configuration
 *  @param rates            The buf to return the supported rates
 *
 *  @return                 The number of Rates
 */
t_u32
wlan_get_supported_rates(mlan_private * pmpriv, t_u32 bss_mode,
			 t_u8 config_bands, WLAN_802_11_RATES rates)
{
	t_u32 k = 0;

	ENTER();

	if (bss_mode == MLAN_BSS_MODE_INFRA) {
		/* Infra. mode */
		switch (config_bands) {
		case BAND_B:
			PRINTM(MINFO, "Infra Band=%d SupportedRates_B\n",
			       config_bands);
			k = wlan_copy_rates(rates, k, SupportedRates_B,
					    sizeof(SupportedRates_B));
			break;
		case BAND_G:
		case BAND_G | BAND_GN:
			PRINTM(MINFO, "Infra band=%d SupportedRates_G\n",
			       config_bands);
			k = wlan_copy_rates(rates, k, SupportedRates_G,
					    sizeof(SupportedRates_G));
			break;
		case BAND_B | BAND_G:
		case BAND_A | BAND_B | BAND_G:
		case BAND_A | BAND_B:
		case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN:
		case BAND_B | BAND_G | BAND_GN:
			PRINTM(MINFO, "Infra band=%d SupportedRates_BG\n",
			       config_bands);
#ifdef WIFI_DIRECT_SUPPORT
			if (pmpriv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
				k = wlan_copy_rates(rates, k, SupportedRates_G,
						    sizeof(SupportedRates_G));
			else
				k = wlan_copy_rates(rates, k, SupportedRates_BG,
						    sizeof(SupportedRates_BG));
#else
			k = wlan_copy_rates(rates, k, SupportedRates_BG,
					    sizeof(SupportedRates_BG));
#endif
			break;
		case BAND_A:
		case BAND_A | BAND_G:
			PRINTM(MINFO, "Infra band=%d SupportedRates_A\n",
			       config_bands);
			k = wlan_copy_rates(rates, k, SupportedRates_A,
					    sizeof(SupportedRates_A));
			break;
		case BAND_AN:
		case BAND_A | BAND_AN:
		case BAND_A | BAND_G | BAND_AN | BAND_GN:
			PRINTM(MINFO, "Infra band=%d SupportedRates_A\n",
			       config_bands);
			k = wlan_copy_rates(rates, k, SupportedRates_A,
					    sizeof(SupportedRates_A));
			break;
		case BAND_GN:
			PRINTM(MINFO, "Infra band=%d SupportedRates_N\n",
			       config_bands);
			k = wlan_copy_rates(rates, k, SupportedRates_N,
					    sizeof(SupportedRates_N));
			break;
		}
	} else {
		/* Ad-hoc mode */
		switch (config_bands) {
		case BAND_B:
			PRINTM(MINFO, "Band: Adhoc B\n");
			k = wlan_copy_rates(rates, k, AdhocRates_B,
					    sizeof(AdhocRates_B));
			break;
		case BAND_G:
		case BAND_G | BAND_GN:
			PRINTM(MINFO, "Band: Adhoc G only\n");
			k = wlan_copy_rates(rates, k, AdhocRates_G,
					    sizeof(AdhocRates_G));
			break;
		case BAND_B | BAND_G:
		case BAND_B | BAND_G | BAND_GN:
			PRINTM(MINFO, "Band: Adhoc BG\n");
			k = wlan_copy_rates(rates, k, AdhocRates_BG,
					    sizeof(AdhocRates_BG));
			break;
		case BAND_A:
		case BAND_AN:
		case BAND_A | BAND_AN:
			PRINTM(MINFO, "Band: Adhoc A\n");
			k = wlan_copy_rates(rates, k, AdhocRates_A,
					    sizeof(AdhocRates_A));
			break;
		}
	}

	LEAVE();
	return k;
}
/**
 *  @brief Find the channel frequency power info for a specific frequency
 *
 *  @param pmadapter    A pointer to mlan_adapter structure
 *  @param band         It can be BAND_A, BAND_G or BAND_B
 *  @param freq         The frequency to search for
 *
 *  @return         Pointer to chan_freq_power_t structure; MNULL if not found
 */
chan_freq_power_t *
wlan_find_cfp_by_band_and_freq(mlan_adapter * pmadapter, t_u8 band, t_u32 freq)
{
	chan_freq_power_t *cfp = MNULL;
	region_chan_t *rc;
	int i, j;

	ENTER();

	for (j = 0; !cfp && (j < MAX_REGION_CHANNEL_NUM); j++) {
		rc = &pmadapter->region_channel[j];

		/* Any station(s) with 11D enabled */
		if (wlan_count_priv_cond(pmadapter, wlan_11d_is_enabled,
					 wlan_is_station) > 0)
			rc = &pmadapter->universal_channel[j];

		if (!rc->valid || !rc->pcfp)
			continue;
		switch (rc->band) {
		case BAND_A:
			switch (band) {
			case BAND_AN:
			case BAND_A | BAND_AN:
			case BAND_A:	/* Matching BAND_A */
				break;
			default:
				continue;
			}
			break;
		case BAND_B:
		case BAND_G:
			switch (band) {
			case BAND_GN:
			case BAND_B | BAND_G | BAND_GN:
			case BAND_G | BAND_GN:
			case BAND_B | BAND_G:
			case BAND_B:
			case BAND_G:
			case 0:
				break;
			default:
				continue;
			}
			break;
		default:
			continue;
		}
		for (i = 0; i < rc->num_cfp; i++) {
			if (rc->pcfp[i].freq == freq) {
				cfp = &rc->pcfp[i];
				break;
			}
		}
	}

	if (!cfp && freq)
		PRINTM(MERROR,
		       "wlan_find_cfp_by_band_and_freq(): cannot find cfp by "
		       "band %d & freq %d\n", band, freq);

	LEAVE();
	return cfp;
}
示例#15
0
/**
 *  @brief The main process
 *
 *  @param pmlan_adapter	A pointer to mlan_adapter structure
 *
 *  @return			MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
 */
mlan_status
mlan_main_process(IN t_void * pmlan_adapter)
{
    mlan_status ret = MLAN_STATUS_SUCCESS;
    mlan_adapter *pmadapter = (mlan_adapter *) pmlan_adapter;
    pmlan_callbacks pcb;

    ENTER();

    MASSERT(pmlan_adapter);

    pcb = &pmadapter->callbacks;

    pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pmain_proc_lock);

    /* Check if already processing */
    if (pmadapter->mlan_processing) {
        pcb->moal_spin_unlock(pmadapter->pmoal_handle,
                              pmadapter->pmain_proc_lock);
        goto exit_main_proc;
    } else {
        pmadapter->mlan_processing = MTRUE;
        pcb->moal_spin_unlock(pmadapter->pmoal_handle,
                              pmadapter->pmain_proc_lock);
    }
  process_start:
    do {
        /* Is MLAN shutting down or not ready? */
        if ((pmadapter->hw_status == WlanHardwareStatusClosing) ||
            (pmadapter->hw_status == WlanHardwareStatusNotReady))
            break;

        /* Handle pending SDIO interrupts if any */
        if (pmadapter->sdio_ireg) {
            if (pmadapter->hs_activated == MTRUE)
                wlan_process_hs_config(pmadapter);
            wlan_process_int_status(pmadapter);
        }

        /* Need to wake up the card ? */
        if ((pmadapter->ps_state == PS_STATE_SLEEP) &&
            (pmadapter->pm_wakeup_card_req &&
             !pmadapter->pm_wakeup_fw_try) &&
            (util_peek_list
             (pmadapter->pmoal_handle, &pmadapter->cmd_pending_q,
              pcb->moal_spin_lock, pcb->moal_spin_unlock)
             || !wlan_bypass_tx_list_empty(pmadapter)
             || !wlan_wmm_lists_empty(pmadapter)
            )) {
            pmadapter->pm_wakeup_fw_try = MTRUE;
            wlan_pm_wakeup_card(pmadapter);
            continue;
        }
        if (IS_CARD_RX_RCVD(pmadapter)) {
            pmadapter->pm_wakeup_fw_try = MFALSE;
            if (pmadapter->ps_state == PS_STATE_SLEEP)
                pmadapter->ps_state = PS_STATE_AWAKE;
        } else {
            /* We have tried to wakeup the card already */
            if (pmadapter->pm_wakeup_fw_try)
                break;
            if (pmadapter->ps_state != PS_STATE_AWAKE ||
                (pmadapter->tx_lock_flag == MTRUE))
                break;

            if (pmadapter->scan_processing || pmadapter->data_sent
                || (wlan_bypass_tx_list_empty(pmadapter) &&
                    wlan_wmm_lists_empty(pmadapter))
                ) {
                if (pmadapter->cmd_sent || pmadapter->curr_cmd ||
                    (!util_peek_list
                     (pmadapter->pmoal_handle, &pmadapter->cmd_pending_q,
                      pcb->moal_spin_lock, pcb->moal_spin_unlock))) {
                    break;
                }
            }
        }

        /* Check for Cmd Resp */
        if (pmadapter->cmd_resp_received) {
            pmadapter->cmd_resp_received = MFALSE;
            wlan_process_cmdresp(pmadapter);

            /* call moal back when init_fw is done */
            if (pmadapter->hw_status == WlanHardwareStatusInitdone) {
                pmadapter->hw_status = WlanHardwareStatusReady;
                wlan_init_fw_complete(pmadapter);
            }
        }

        /* Check for event */
        if (pmadapter->event_received) {
            pmadapter->event_received = MFALSE;
            wlan_process_event(pmadapter);
        }

        /* Check if we need to confirm Sleep Request received previously */
        if (pmadapter->ps_state == PS_STATE_PRE_SLEEP) {
            if (!pmadapter->cmd_sent && !pmadapter->curr_cmd) {
                wlan_check_ps_cond(pmadapter);
            }
        }

        /* 
         * The ps_state may have been changed during processing of
         * Sleep Request event.
         */
        if ((pmadapter->ps_state == PS_STATE_SLEEP)
            || (pmadapter->ps_state == PS_STATE_PRE_SLEEP)
            || (pmadapter->ps_state == PS_STATE_SLEEP_CFM)
            || (pmadapter->tx_lock_flag == MTRUE)
            )
            continue;

        if (!pmadapter->cmd_sent && !pmadapter->curr_cmd) {
            if (wlan_exec_next_cmd(pmadapter) == MLAN_STATUS_FAILURE) {
                ret = MLAN_STATUS_FAILURE;
                break;
            }
        }

        if (!pmadapter->scan_processing && !pmadapter->data_sent &&
            !wlan_bypass_tx_list_empty(pmadapter)) {
            PRINTM(MINFO, "mlan_send_pkt(): deq(bybass_txq)\n");
            wlan_process_bypass_tx(pmadapter);
            if (pmadapter->hs_activated == MTRUE) {
                pmadapter->is_hs_configured = MFALSE;
                wlan_host_sleep_activated_event(wlan_get_priv
                                                (pmadapter, MLAN_BSS_ROLE_ANY),
                                                MFALSE);
            }
        }

        if (!pmadapter->scan_processing && !pmadapter->data_sent &&
            !wlan_wmm_lists_empty(pmadapter)) {
            wlan_wmm_process_tx(pmadapter);
            if (pmadapter->hs_activated == MTRUE) {
                pmadapter->is_hs_configured = MFALSE;
                wlan_host_sleep_activated_event(wlan_get_priv
                                                (pmadapter, MLAN_BSS_ROLE_ANY),
                                                MFALSE);
            }
        }

#ifdef STA_SUPPORT
        if (pmadapter->delay_null_pkt && !pmadapter->cmd_sent &&
            !pmadapter->curr_cmd && !IS_COMMAND_PENDING(pmadapter) &&
            wlan_bypass_tx_list_empty(pmadapter) &&
            wlan_wmm_lists_empty(pmadapter)) {
            if (wlan_send_null_packet
                (wlan_get_priv(pmadapter, MLAN_BSS_ROLE_STA),
                 MRVDRV_TxPD_POWER_MGMT_NULL_PACKET |
                 MRVDRV_TxPD_POWER_MGMT_LAST_PACKET)
                == MLAN_STATUS_SUCCESS) {
                pmadapter->delay_null_pkt = MFALSE;
            }
            break;
        }
#endif

    } while (MTRUE);

    if ((pmadapter->sdio_ireg) || IS_CARD_RX_RCVD(pmadapter)) {
        goto process_start;
    }
    pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pmain_proc_lock);
    pmadapter->mlan_processing = MFALSE;
    pcb->moal_spin_unlock(pmadapter->pmoal_handle, pmadapter->pmain_proc_lock);

  exit_main_proc:
    if (pmadapter->hw_status == WlanHardwareStatusClosing)
        mlan_shutdown_fw(pmadapter);
    LEAVE();
    return ret;
}
/**
 *  @brief This function fill the txpd for tx packet
 *
 *  @param priv	   A pointer to mlan_private structure
 *  @param pmbuf   A pointer to the mlan_buffer for process
 *
 *  @return 	   headptr or MNULL
 */
t_void *
wlan_ops_sta_process_txpd(IN t_void * priv, IN pmlan_buffer pmbuf)
{
	mlan_private *pmpriv = (mlan_private *) priv;
	pmlan_adapter pmadapter = pmpriv->adapter;
	TxPD *plocal_tx_pd;
	t_u8 *head_ptr = MNULL;
	t_u32 pkt_type;
	t_u32 tx_control;

	ENTER();

	if (!pmbuf->data_len) {
		PRINTM(MERROR, "STA Tx Error: Invalid packet length: %d\n",
		       pmbuf->data_len);
		pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
		goto done;
	}
	if (pmbuf->buf_type == MLAN_BUF_TYPE_RAW_DATA) {
		memcpy(pmpriv->adapter, &pkt_type,
		       pmbuf->pbuf + pmbuf->data_offset, sizeof(pkt_type));
		memcpy(pmpriv->adapter, &tx_control,
		       pmbuf->pbuf + pmbuf->data_offset + sizeof(pkt_type),
		       sizeof(tx_control));
		pmbuf->data_offset += sizeof(pkt_type) + sizeof(tx_control);
		pmbuf->data_len -= sizeof(pkt_type) + sizeof(tx_control);
	}

	if (pmbuf->data_offset < (sizeof(TxPD) + INTF_HEADER_LEN +
				  DMA_ALIGNMENT)) {
		PRINTM(MERROR, "not enough space for TxPD: %d\n",
		       pmbuf->data_len);
		pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
		goto done;
	}

	/* head_ptr should be aligned */
	head_ptr =
		pmbuf->pbuf + pmbuf->data_offset - sizeof(TxPD) -
		INTF_HEADER_LEN;
	head_ptr = (t_u8 *) ((t_ptr) head_ptr & ~((t_ptr) (DMA_ALIGNMENT - 1)));

	plocal_tx_pd = (TxPD *) (head_ptr + INTF_HEADER_LEN);
	memset(pmadapter, plocal_tx_pd, 0, sizeof(TxPD));
	/* Set the BSS number to TxPD */
	plocal_tx_pd->bss_num = GET_BSS_NUM(pmpriv);
	plocal_tx_pd->bss_type = pmpriv->bss_type;

	plocal_tx_pd->tx_pkt_length = (t_u16) pmbuf->data_len;

	plocal_tx_pd->priority = (t_u8) pmbuf->priority;
	plocal_tx_pd->pkt_delay_2ms =
		wlan_wmm_compute_driver_packet_delay(pmpriv, pmbuf);

	if (plocal_tx_pd->priority <
	    NELEMENTS(pmpriv->wmm.user_pri_pkt_tx_ctrl))
		/*
		 * Set the priority specific tx_control field, setting of 0 will
		 *   cause the default value to be used later in this function
		 */
		plocal_tx_pd->tx_control
			=
			pmpriv->wmm.user_pri_pkt_tx_ctrl[plocal_tx_pd->
							 priority];
	if (pmadapter->pps_uapsd_mode) {
		if (MTRUE == wlan_check_last_packet_indication(pmpriv)) {
			pmadapter->tx_lock_flag = MTRUE;
			plocal_tx_pd->flags =
				MRVDRV_TxPD_POWER_MGMT_LAST_PACKET;
		}
	}

	/* Offset of actual data */
	plocal_tx_pd->tx_pkt_offset =
		(t_u16) ((t_ptr) pmbuf->pbuf + pmbuf->data_offset -
			 (t_ptr) plocal_tx_pd);

	if (!plocal_tx_pd->tx_control) {
		/* TxCtrl set by user or default */
		plocal_tx_pd->tx_control = pmpriv->pkt_tx_ctrl;
	}

	if (pmbuf->buf_type == MLAN_BUF_TYPE_RAW_DATA) {
		plocal_tx_pd->tx_pkt_type = (t_u16) pkt_type;
		plocal_tx_pd->tx_control = tx_control;
	}

	endian_convert_TxPD(plocal_tx_pd);

	/* Adjust the data offset and length to include TxPD in pmbuf */
	pmbuf->data_len += pmbuf->data_offset;
	pmbuf->data_offset = (t_u32) (head_ptr - pmbuf->pbuf);
	pmbuf->data_len -= pmbuf->data_offset;

done:
	LEAVE();
	return head_ptr;
}
/** 
 *  @brief This function handles events generated by firmware
 *  
 *  @param priv	A pointer to mlan_private structure
 *
 *  @return		MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
 */
mlan_status
wlan_ops_sta_process_event(IN t_void * priv)
{
    pmlan_private pmpriv = (pmlan_private) priv;
    pmlan_adapter pmadapter = pmpriv->adapter;
    mlan_status ret = MLAN_STATUS_SUCCESS;
    t_u32 eventcause = pmadapter->event_cause;
    t_u8 event_buf[100];
    t_u8 *evt_buf = MNULL;
    pmlan_buffer pmbuf = pmadapter->pmlan_buffer_event;
    pmlan_callbacks pcb = &pmadapter->callbacks;
    mlan_event *pevent = (mlan_event *) event_buf;

    ENTER();

    if (eventcause != EVENT_PS_AWAKE && eventcause != EVENT_PS_SLEEP &&
        pmbuf->data_len > sizeof(eventcause))
        DBG_HEXDUMP(MEVT_D, "EVENT", pmbuf->pbuf + pmbuf->data_offset,
                    pmbuf->data_len);

    switch (eventcause) {
    case EVENT_DUMMY_HOST_WAKEUP_SIGNAL:
        PRINTM(MERROR,
               "Invalid EVENT: DUMMY_HOST_WAKEUP_SIGNAL, ignoring it\n");
        break;
    case EVENT_LINK_SENSED:
        PRINTM(MEVENT, "EVENT: LINK_SENSED\n");
        pmpriv->adhoc_is_link_sensed = MTRUE;
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_ADHOC_LINK_SENSED, MNULL);
        break;

    case EVENT_DEAUTHENTICATED:
        PRINTM(MEVENT, "EVENT: Deauthenticated\n");
        pmadapter->dbg.num_event_deauth++;
        wlan_handle_disconnect_event(pmpriv);

        break;

    case EVENT_DISASSOCIATED:
        PRINTM(MEVENT, "EVENT: Disassociated\n");
        pmadapter->dbg.num_event_disassoc++;
        wlan_handle_disconnect_event(pmpriv);
        break;

    case EVENT_LINK_LOST:
        PRINTM(MEVENT, "EVENT: Link lost\n");
        pmadapter->dbg.num_event_link_lost++;
        wlan_handle_disconnect_event(pmpriv);
        break;

    case EVENT_PS_SLEEP:
        PRINTM(MINFO, "EVENT: SLEEP\n");
        PRINTM(MEVENT, "_");

        /* Handle unexpected PS SLEEP event */
        if (pmadapter->ps_state == PS_STATE_SLEEP_CFM)
            break;
        pmadapter->ps_state = PS_STATE_PRE_SLEEP;

        wlan_check_ps_cond(pmadapter);
        break;

    case EVENT_PS_AWAKE:
        PRINTM(MINFO, "EVENT: AWAKE \n");
        PRINTM(MEVENT, "|");
        if (!pmadapter->pps_uapsd_mode &&
            pmpriv->media_connected &&
            (pmpriv->port_open || !pmpriv->port_ctrl_mode) &&
            pmadapter->sleep_period.period) {
            pmadapter->pps_uapsd_mode = MTRUE;
            PRINTM(MEVENT, "PPS/UAPSD mode activated\n");
        }
        /* Handle unexpected PS AWAKE event */
        if (pmadapter->ps_state == PS_STATE_SLEEP_CFM)
            break;
        pmadapter->tx_lock_flag = MFALSE;
        if (pmadapter->pps_uapsd_mode && pmadapter->gen_null_pkt) {
            if (MTRUE == wlan_check_last_packet_indication(pmpriv)) {
                if (!pmadapter->data_sent) {
                    if (wlan_send_null_packet(pmpriv,
                                              MRVDRV_TxPD_POWER_MGMT_NULL_PACKET
                                              |
                                              MRVDRV_TxPD_POWER_MGMT_LAST_PACKET)
                        == MLAN_STATUS_SUCCESS) {
                        return MLAN_STATUS_SUCCESS;
                    }
                }
            }
        }
        pmadapter->ps_state = PS_STATE_AWAKE;
        pmadapter->pm_wakeup_card_req = MFALSE;
        pmadapter->pm_wakeup_fw_try = MFALSE;
        break;

    case EVENT_HS_ACT_REQ:
        PRINTM(MEVENT, "EVENT: HS_ACT_REQ\n");
        ret = wlan_prepare_cmd(priv,
                               HostCmd_CMD_802_11_HS_CFG_ENH,
                               0, 0, MNULL, MNULL);
        break;

    case EVENT_MIC_ERR_UNICAST:
        PRINTM(MEVENT, "EVENT: UNICAST MIC ERROR\n");
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_MIC_ERR_UNI, MNULL);
        break;

    case EVENT_MIC_ERR_MULTICAST:
        PRINTM(MEVENT, "EVENT: MULTICAST MIC ERROR\n");
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_MIC_ERR_MUL, MNULL);
        break;
    case EVENT_MIB_CHANGED:
    case EVENT_INIT_DONE:
        break;

    case EVENT_ADHOC_BCN_LOST:
        PRINTM(MEVENT, "EVENT: ADHOC_BCN_LOST\n");
        pmpriv->adhoc_is_link_sensed = MFALSE;
        wlan_clean_txrx(pmpriv);
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_ADHOC_LINK_LOST, MNULL);
        break;

    case EVENT_BG_SCAN_REPORT:
        PRINTM(MEVENT, "EVENT: BGS_REPORT\n");
        /* Clear the previous scan result */
        memset(pmadapter, pmadapter->pscan_table, 0x00,
               sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST);
        pmadapter->num_in_scan_table = 0;
        pmadapter->pbcn_buf_end = pmadapter->bcn_buf;
        ret = wlan_prepare_cmd(pmpriv,
                               HostCmd_CMD_802_11_BG_SCAN_QUERY,
                               HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
        break;

    case EVENT_PORT_RELEASE:
        PRINTM(MEVENT, "EVENT: PORT RELEASE\n");
        /* Open the port for e-supp mode */
        if (pmpriv->port_ctrl_mode == MTRUE) {
            PRINTM(MINFO, "PORT_REL: port_status = OPEN\n");
            pmpriv->port_open = MTRUE;
        }
        pmpriv->scan_block = MFALSE;
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_PORT_RELEASE, MNULL);
        break;

    case EVENT_STOP_TX:
        PRINTM(MEVENT, "EVENT: Stop Tx (%#x)\n", eventcause);
        wlan_11h_tx_disable(pmpriv);    // this fn will send event up to MOAL
        break;
    case EVENT_START_TX:
        PRINTM(MEVENT, "EVENT: Start Tx (%#x)\n", eventcause);
        wlan_11h_tx_enable(pmpriv);     // this fn will send event up to MOAL
        break;
    case EVENT_CHANNEL_SWITCH:
        PRINTM(MEVENT, "EVENT: Channel Switch (%#x)\n", eventcause);
        /* To be handled for 'chanswann' private command */
        break;
    case EVENT_CHANNEL_SWITCH_ANN:
        PRINTM(MEVENT, "EVENT: Channel Switch Announcement\n");
        /* Here, pass up event first, as handling will send deauth */
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_CHANNEL_SWITCH_ANN, MNULL);
        wlan_11h_handle_event_chanswann(pmpriv);
        break;
    case EVENT_RADAR_DETECTED:
        PRINTM(MEVENT, "EVENT: Radar Detected\n");

        /* Send as passthru first, this event can cause other events */
        memset(pmadapter, pevent, 0x00, sizeof(event_buf));
        pevent->bss_index = pmpriv->bss_index;
        pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
        pevent->event_len = pmbuf->data_len;
        memcpy(pmadapter, (t_u8 *) pevent->event_buf,
               pmbuf->pbuf + pmbuf->data_offset, pevent->event_len);
        wlan_recv_event(pmpriv, pevent->event_id, pevent);

        /* Then handle event */
        if (pmadapter->state_rdh.stage == RDH_OFF) {
            pmadapter->state_rdh.stage = RDH_CHK_INTFS;
            wlan_11h_radar_detected_handling(pmadapter);
        } else {
            PRINTM(MEVENT, "Ignore Event Radar Detected - handling"
                   " already in progress.\n");
        }
        break;

    case EVENT_CHANNEL_REPORT_RDY:
        PRINTM(MEVENT, "EVENT: Channel Report Ready\n");
        /* Allocate memory for event buffer */
        ret = pcb->moal_malloc(pmadapter->pmoal_handle,
                               MAX_EVENT_SIZE, MLAN_MEM_DEF, &evt_buf);
        if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) {
            memset(pmadapter, evt_buf, 0x00, MAX_EVENT_SIZE);
            /* Setup event buffer */
            pevent = (pmlan_event) evt_buf;
            pevent->bss_index = pmpriv->bss_index;
            pevent->event_id = MLAN_EVENT_ID_FW_CHANNEL_REPORT_RDY;
            pevent->event_len = pmbuf->data_len - sizeof(eventcause);
            /* Copy event data */
            memcpy(pmadapter, (t_u8 *) pevent->event_buf,
                   pmbuf->pbuf + pmbuf->data_offset + sizeof(eventcause),
                   pevent->event_len);
            /* Handle / pass event data */
            ret = wlan_11h_handle_event_chanrpt_ready(pmpriv, pevent);

            /* Also send this event as passthru */
            pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
            pevent->event_len = pmbuf->data_len;
            memcpy(pmadapter, (t_u8 *) pevent->event_buf,
                   pmbuf->pbuf + pmbuf->data_offset, pevent->event_len);
            wlan_recv_event(pmpriv, pevent->event_id, pevent);
            /* Now done with buffer */
            pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf);
        }
        /* Send up this Event to unblock MOAL waitqueue */
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_MEAS_REPORT, MNULL);
        break;
    case EVENT_EXT_SCAN_REPORT:
        PRINTM(MEVENT, "EVENT: EXT_SCAN Report (%#x)\n", eventcause);
        ret = wlan_handle_event_ext_scan_report(priv, pmbuf);
        break;
    case EVENT_MEAS_REPORT_RDY:
        PRINTM(MEVENT, "EVENT: Measurement Report Ready (%#x)\n", eventcause);
        wlan_prepare_cmd(priv, HostCmd_CMD_MEASUREMENT_REPORT,
                         HostCmd_ACT_GEN_SET, 0, 0, MNULL);
        break;
    case EVENT_WMM_STATUS_CHANGE:
        if (pmbuf && pmbuf->data_len
            > sizeof(eventcause) + sizeof(MrvlIEtypesHeader_t)) {
            PRINTM(MEVENT, "EVENT: WMM status changed: %d\n", pmbuf->data_len);

            evt_buf = (pmbuf->pbuf + pmbuf->data_offset + sizeof(eventcause));

            wlan_ret_wmm_get_status(pmpriv,
                                    evt_buf,
                                    pmbuf->data_len - sizeof(eventcause));
        } else {
            PRINTM(MEVENT, "EVENT: WMM status changed\n");
            ret = wlan_cmd_wmm_status_change(pmpriv);
        }
        break;

    case EVENT_RSSI_LOW:
        PRINTM(MEVENT, "EVENT: Beacon RSSI_LOW\n");
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BCN_RSSI_LOW, MNULL);
        break;
    case EVENT_SNR_LOW:
        PRINTM(MEVENT, "EVENT: Beacon SNR_LOW\n");
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BCN_SNR_LOW, MNULL);
        break;
    case EVENT_MAX_FAIL:
        PRINTM(MEVENT, "EVENT: MAX_FAIL\n");
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_MAX_FAIL, MNULL);
        break;
    case EVENT_RSSI_HIGH:
        PRINTM(MEVENT, "EVENT: Beacon RSSI_HIGH\n");
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BCN_RSSI_HIGH, MNULL);
        break;
    case EVENT_SNR_HIGH:
        PRINTM(MEVENT, "EVENT: Beacon SNR_HIGH\n");
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BCN_SNR_HIGH, MNULL);
        break;
    case EVENT_DATA_RSSI_LOW:
        PRINTM(MEVENT, "EVENT: Data RSSI_LOW\n");
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_RSSI_LOW, MNULL);
        break;
    case EVENT_DATA_SNR_LOW:
        PRINTM(MEVENT, "EVENT: Data SNR_LOW\n");
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_SNR_LOW, MNULL);
        break;
    case EVENT_DATA_RSSI_HIGH:
        PRINTM(MEVENT, "EVENT: Data RSSI_HIGH\n");
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_RSSI_HIGH, MNULL);
        break;
    case EVENT_DATA_SNR_HIGH:
        PRINTM(MEVENT, "EVENT: Data SNR_HIGH\n");
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_SNR_HIGH, MNULL);
        break;
    case EVENT_LINK_QUALITY:
        PRINTM(MEVENT, "EVENT: Link Quality\n");
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_LINK_QUALITY, MNULL);
        break;
    case EVENT_PRE_BEACON_LOST:
        PRINTM(MEVENT, "EVENT: Pre-Beacon Lost\n");
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_PRE_BCN_LOST, MNULL);
        break;
    case EVENT_IBSS_COALESCED:
        PRINTM(MEVENT, "EVENT: IBSS_COALESCED\n");
        ret = wlan_prepare_cmd(pmpriv,
                               HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,
                               HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
        break;
    case EVENT_ADDBA:
        PRINTM(MEVENT, "EVENT: ADDBA Request\n");
        wlan_prepare_cmd(pmpriv, HostCmd_CMD_11N_ADDBA_RSP,
                         HostCmd_ACT_GEN_SET, 0, MNULL, pmadapter->event_body);
        break;
    case EVENT_DELBA:
        PRINTM(MEVENT, "EVENT: DELBA Request\n");
        wlan_11n_delete_bastream(pmpriv, pmadapter->event_body);
        break;
    case EVENT_BA_STREAM_TIMEOUT:
        PRINTM(MEVENT, "EVENT:  BA Stream timeout\n");
        wlan_11n_ba_stream_timeout(pmpriv,
                                   (HostCmd_DS_11N_BATIMEOUT *) pmadapter->
                                   event_body);
        break;
    case EVENT_RXBA_SYNC:
        PRINTM(MEVENT, "EVENT:  RXBA_SYNC\n");
        wlan_11n_rxba_sync_event(pmpriv, pmadapter->event_body,
                                 pmbuf->data_len - sizeof(eventcause));
        break;
    case EVENT_AMSDU_AGGR_CTRL:
        PRINTM(MEVENT, "EVENT:  AMSDU_AGGR_CTRL %d\n",
               *(t_u16 *) pmadapter->event_body);
        pmadapter->tx_buf_size =
            MIN(pmadapter->curr_tx_buf_size,
                wlan_le16_to_cpu(*(t_u16 *) pmadapter->event_body));
        PRINTM(MEVENT, "tx_buf_size %d\n", pmadapter->tx_buf_size);
        break;

    case EVENT_WEP_ICV_ERR:
        PRINTM(MEVENT, "EVENT: WEP ICV error\n");
        pevent->bss_index = pmpriv->bss_index;
        pevent->event_id = MLAN_EVENT_ID_FW_WEP_ICV_ERR;
        pevent->event_len = sizeof(Event_WEP_ICV_ERR);
        memcpy(pmadapter, (t_u8 *) pevent->event_buf, pmadapter->event_body,
               pevent->event_len);
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_WEP_ICV_ERR, pevent);
        break;

    case EVENT_BW_CHANGE:
        PRINTM(MEVENT, "EVENT: BW Change\n");
        pevent->bss_index = pmpriv->bss_index;
        pevent->event_id = MLAN_EVENT_ID_FW_BW_CHANGED;
        pevent->event_len = sizeof(t_u8);
        /* Copy event body from the event buffer */
        memcpy(pmadapter, (t_u8 *) pevent->event_buf, pmadapter->event_body,
               pevent->event_len);
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BW_CHANGED, pevent);
        break;

#ifdef WFD_SUPPORT
    case EVENT_WFD_GENERIC_EVENT:
    case EVENT_WFD_SERVICE_DISCOVERY:
        PRINTM(MEVENT, "EVENT: WFD event %d\n", eventcause);
        /* Allocate memory for event buffer */
        ret =
            pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE,
                             MLAN_MEM_DEF, &evt_buf);
        if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) {
            pevent = (pmlan_event) evt_buf;
            pevent->bss_index = pmpriv->bss_index;
            pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU;
            pevent->event_len = pmbuf->data_len;
            memcpy(pmadapter, (t_u8 *) pevent->event_buf,
                   pmbuf->pbuf + pmbuf->data_offset, pevent->event_len);
            wlan_recv_event(pmpriv, pevent->event_id, pevent);
            pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf);
        }
        break;
#endif /* WFD_SUPPORT */

    default:
        PRINTM(MEVENT, "EVENT: unknown event id: %#x\n", eventcause);
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_UNKNOWN, MNULL);
        break;
    }

    LEAVE();
    return ret;
}
示例#18
0
/**
 *  @brief Deaggregate the received AMSDU packet 
 *
 *  @param priv		A pointer to mlan_private structure
 *  @param pmbuf	A pointer to aggregated data packet
 *
 *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
 */
mlan_status
wlan_11n_deaggregate_pkt(mlan_private * priv, pmlan_buffer pmbuf)
{
    t_u16 pkt_len;
    int total_pkt_len;
    t_u8 *data;
    int pad;
    mlan_status ret = MLAN_STATUS_FAILURE;
    RxPacketHdr_t *prx_pkt;
    mlan_buffer *daggr_mbuf = MNULL;
    /* mlan_adapter *pmadapter = priv->adapter; */
    t_u8 rfc1042_eth_hdr[MLAN_MAC_ADDR_LENGTH] = { 0xaa, 0xaa, 0x03,
        0x00, 0x00, 0x00
    };

    ENTER();

    data = (t_u8 *) (pmbuf->pbuf + pmbuf->data_offset);
    total_pkt_len = pmbuf->data_len;

    /* Sanity test */
    if (total_pkt_len > MLAN_RX_DATA_BUF_SIZE) {
        PRINTM(MERROR, "Total packet length greater than tx buffer"
               " size %d\n", total_pkt_len);
        goto done;
    }

    pmbuf->use_count = wlan_11n_get_num_aggrpkts(data, total_pkt_len);

    while (total_pkt_len > 0) {
        prx_pkt = (RxPacketHdr_t *) data;
        /* Length will be in network format, change it to host */
        pkt_len = mlan_ntohs((*(t_u16 *) (data + (2 * MLAN_MAC_ADDR_LENGTH))));
        if (pkt_len > total_pkt_len) {
            PRINTM(MERROR,
                   "Error in packet length: total_pkt_len = %d, pkt_len = %d\n",
                   total_pkt_len, pkt_len);
            break;
        }

        pad = (((pkt_len + sizeof(Eth803Hdr_t)) & 3)) ?
            (4 - ((pkt_len + sizeof(Eth803Hdr_t)) & 3)) : 0;

        total_pkt_len -= pkt_len + pad + sizeof(Eth803Hdr_t);

        if (memcmp(pmadapter, &prx_pkt->rfc1042_hdr,
                   rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0) {
            memmove(pmadapter, data + LLC_SNAP_LEN, data, (2 *
                                                           MLAN_MAC_ADDR_LENGTH));
            data += LLC_SNAP_LEN;
            pkt_len += sizeof(Eth803Hdr_t) - LLC_SNAP_LEN;
        } else {
            *(t_u16 *) (data + (2 * MLAN_MAC_ADDR_LENGTH))
                = (t_u16) 0;
            pkt_len += sizeof(Eth803Hdr_t);
        }

#ifndef CONFIG_MLAN_WMSDK
        daggr_mbuf = wlan_alloc_mlan_buffer(pmadapter, pkt_len, 0, MFALSE);
        if (daggr_mbuf == MNULL) {
            PRINTM(MERROR, "Error allocating daggr mlan_buffer\n");
            LEAVE();
            return MLAN_STATUS_FAILURE;
        }
        daggr_mbuf->bss_index = pmbuf->bss_index;
        daggr_mbuf->buf_type = pmbuf->buf_type;
        daggr_mbuf->data_len = pkt_len;
        daggr_mbuf->in_ts_sec = pmbuf->in_ts_sec;
        daggr_mbuf->in_ts_usec = pmbuf->in_ts_usec;
        daggr_mbuf->pparent = pmbuf;
        daggr_mbuf->priority = pmbuf->priority;
        memcpy(pmadapter, daggr_mbuf->pbuf + daggr_mbuf->data_offset, data,
               pkt_len);
#else
	/* This part is customized for WMSDK. We do not need and will not
	   allocate the mlan buffer. */
	wrapper_deliver_amsdu_subframe(pmbuf,  data, pkt_len);
	ret = MLAN_STATUS_SUCCESS;
#endif /* CONFIG_MLAN_WMSDK */

#ifndef CONFIG_MLAN_WMSDK
#ifdef UAP_SUPPORT
        if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)
            ret = wlan_uap_recv_packet(priv, daggr_mbuf);
        else
#endif /* UAP_SUPPORT */
            ret =
                pmadapter->callbacks.moal_recv_packet(pmadapter->pmoal_handle,
                                                      daggr_mbuf);
#endif /* CONFIG_MLAN_WMSDK */

	switch (ret) {
        case MLAN_STATUS_PENDING:
            break;
        case MLAN_STATUS_FAILURE:
            PRINTM(MERROR, "Deaggr, send to moal failed\n");
            daggr_mbuf->status_code = MLAN_ERROR_PKT_INVALID;
        case MLAN_STATUS_SUCCESS:
#ifndef CONFIG_MLAN_WMSDK
		wlan_recv_packet_complete(pmadapter, daggr_mbuf, ret);
#endif /* CONFIG_MLAN_WMSDK */
            break;
        default:
            break;
        }

        data += pkt_len + pad;
    }

  done:
    LEAVE();
    return ret;
}
示例#19
0
/**
 *	@brief read handler for BT char dev
 *
 *	@param filp	pointer to structure file
 *	@param buf		pointer to char buffer
 *	@param count	size of receive buffer
 *	@param f_pos	pointer to loff_t type data
 *	@return			number of bytes read
 */
ssize_t
chardev_read(struct file * filp, char *buf, size_t count, loff_t * f_pos)
{
	struct char_dev *dev = (struct char_dev *)filp->private_data;
	struct m_dev *m_dev = dev->m_dev;
	DECLARE_WAITQUEUE(wait, current);
	ssize_t ret = 0;
	struct sk_buff *skb = NULL;

	ENTER();
	if (!dev || !dev->m_dev) {
		LEAVE();
		return -ENXIO;
	}
	/* Wait for rx data */
	add_wait_queue(&m_dev->req_wait_q, &wait);
	while (1) {
		set_current_state(TASK_INTERRUPTIBLE);
		skb = skb_dequeue(&m_dev->rx_q);
		if (skb)
			break;
		if (!test_bit(HCI_UP, &m_dev->flags)) {
			ret = -EBUSY;
			break;
		}

		if (filp->f_flags & O_NONBLOCK) {
			ret = -EAGAIN;
			break;
		}
		if (signal_pending(current)) {
			ret = -EINTR;
			break;
		}
		schedule();
	}
	set_current_state(TASK_RUNNING);
	remove_wait_queue(&m_dev->req_wait_q, &wait);

	if (!skb)
		goto out;

	if (m_dev->read_continue_flag == 0) {
		/* Put type byte before the data */
		memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
		PRINTM(DATA, "Read: pkt_type: 0x%x, len=%d @%lu\n",
		       bt_cb(skb)->pkt_type, skb->len, jiffies);
	}
	DBG_HEXDUMP(DAT_D, "chardev_read", skb->data, skb->len);
	if (skb->len > count) {
		/* user data length is smaller than the skb length */
		if (copy_to_user(buf, skb->data, count)) {
			ret = -EFAULT;
			goto outf;
		}
		skb_pull(skb, count);
		skb_queue_head(&m_dev->rx_q, skb);
		m_dev->read_continue_flag = 1;
		wake_up_interruptible(&m_dev->req_wait_q);
		ret = count;
		goto out;
	} else {
		if (copy_to_user(buf, skb->data, skb->len)) {
			ret = -EFAULT;
			goto outf;
		}
		m_dev->read_continue_flag = 0;
		ret = skb->len;
	}
outf:
	kfree_skb(skb);
out:
	LEAVE();
	return ret;
}
示例#20
0
/**
 *  @brief Aggregate multiple packets into one single AMSDU packet
 *
 *  @param priv 	A pointer to mlan_private structure
 *  @param pra_list	Pointer to the RA List table containing the pointers
 *  			    to packets.
 *  @param headroom	Any interface specific headroom that may be need. TxPD 
 *  				will be formed leaving this headroom.
 *  @param ptrindex	Pointer index
 *
 *  @return		Final packet size or MLAN_STATUS_FAILURE
 */
int
wlan_11n_aggregate_pkt(mlan_private * priv, raListTbl * pra_list,
                       int headroom, int ptrindex)
{
    int pkt_size = 0;
    pmlan_adapter pmadapter = priv->adapter;
    mlan_buffer *pmbuf_aggr, *pmbuf_src;
    t_u8 *data;
    int pad = 0;
    mlan_status ret = MLAN_STATUS_SUCCESS;
#ifdef DEBUG_LEVEL1
    t_u32 sec, usec;
#endif
    mlan_tx_param tx_param;
#ifdef STA_SUPPORT
    TxPD *ptx_pd = MNULL;
#endif
    t_u32 max_amsdu_size = MIN(pra_list->max_amsdu, pmadapter->tx_buf_size);
    ENTER();

    PRINTM(MDAT_D, "Handling Aggr packet\n");

    if ((pmbuf_src =
         (pmlan_buffer) util_peek_list(pmadapter->pmoal_handle,
                                       &pra_list->buf_head, MNULL, MNULL))) {

        if (!(pmbuf_aggr = wlan_alloc_mlan_buffer(pmadapter,
                                                  pmadapter->tx_buf_size, 0,
                                                  MTRUE))) {
            PRINTM(MERROR, "Error allocating mlan_buffer\n");
            pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
                                                  priv->wmm.ra_list_spinlock);
            LEAVE();
            return MLAN_STATUS_FAILURE;
        }

        data = pmbuf_aggr->pbuf + headroom;
        pmbuf_aggr->bss_index = pmbuf_src->bss_index;
        pmbuf_aggr->buf_type = pmbuf_src->buf_type;
        pmbuf_aggr->priority = pmbuf_src->priority;
        pmbuf_aggr->pbuf = data;
        pmbuf_aggr->data_offset = 0;

        /* Form AMSDU */
        wlan_11n_form_amsdu_txpd(priv, pmbuf_aggr);
        pkt_size = sizeof(TxPD);
#ifdef STA_SUPPORT
        if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA)
            ptx_pd = (TxPD *) pmbuf_aggr->pbuf;
#endif
    } else {
        pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
                                              priv->wmm.ra_list_spinlock);
        goto exit;
    }

    while (pmbuf_src && ((pkt_size + (pmbuf_src->data_len + LLC_SNAP_LEN)
                          + headroom) <= max_amsdu_size)) {

        pmbuf_src = (pmlan_buffer)
            util_dequeue_list(pmadapter->pmoal_handle, &pra_list->buf_head,
                              MNULL, MNULL);

        pra_list->total_pkts--;

        /* decrement for every PDU taken from the list */
        priv->wmm.pkts_queued[ptrindex]--;
        util_scalar_decrement(pmadapter->pmoal_handle,
                              &priv->wmm.tx_pkts_queued, MNULL, MNULL);

        pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
                                              priv->wmm.ra_list_spinlock);

        pkt_size += wlan_11n_form_amsdu_pkt(pmadapter,
                                            (data + pkt_size),
                                            pmbuf_src->pbuf +
                                            pmbuf_src->data_offset,
                                            pmbuf_src->data_len, &pad);

        DBG_HEXDUMP(MDAT_D, "pmbuf_src", pmbuf_src, sizeof(mlan_buffer));
        wlan_write_data_complete(pmadapter, pmbuf_src, MLAN_STATUS_SUCCESS);

        pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
                                            priv->wmm.ra_list_spinlock);

        if (!wlan_is_ralist_valid(priv, pra_list, ptrindex)) {
            pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
                                                  priv->wmm.ra_list_spinlock);
            LEAVE();
            return MLAN_STATUS_FAILURE;
        }

        pmbuf_src =
            (pmlan_buffer) util_peek_list(pmadapter->pmoal_handle,
                                          &pra_list->buf_head, MNULL, MNULL);
    }

    pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
                                          priv->wmm.ra_list_spinlock);

    /* Last AMSDU packet does not need padding */
    pkt_size -= pad;
    pmbuf_aggr->data_len = pkt_size;
    wlan_11n_update_pktlen_amsdu_txpd(priv, pmbuf_aggr);
    pmbuf_aggr->data_len += headroom;
    pmbuf_aggr->pbuf = data - headroom;
    tx_param.next_pkt_len = ((pmbuf_src) ?
                             pmbuf_src->data_len + sizeof(TxPD) : 0);

    ret = wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_DATA,
                                 pmbuf_aggr, &tx_param);
    switch (ret) {
    case MLAN_STATUS_RESOURCE:
        pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
                                            priv->wmm.ra_list_spinlock);

        if (!wlan_is_ralist_valid(priv, pra_list, ptrindex)) {
            pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
                                                  priv->wmm.ra_list_spinlock);
            pmbuf_aggr->status_code = MLAN_ERROR_PKT_INVALID;
            wlan_write_data_complete(pmadapter, pmbuf_aggr,
                                     MLAN_STATUS_FAILURE);
            LEAVE();
            return MLAN_STATUS_FAILURE;
        }
#ifdef STA_SUPPORT
        /* reset tx_lock_flag */
        if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
            pmadapter->pps_uapsd_mode && (pmadapter->tx_lock_flag == MTRUE)) {
            pmadapter->tx_lock_flag = MFALSE;
            ptx_pd->flags = 0;
        }
#endif
        util_enqueue_list_head(pmadapter->pmoal_handle, &pra_list->buf_head,
                               (pmlan_linked_list) pmbuf_aggr, MNULL, MNULL);

        pra_list->total_pkts++;

        /* add back only one: aggregated packet is requeued as one */
        priv->wmm.pkts_queued[ptrindex]++;
        util_scalar_increment(pmadapter->pmoal_handle,
                              &priv->wmm.tx_pkts_queued, MNULL, MNULL);
        pmbuf_aggr->flags |= MLAN_BUF_FLAG_REQUEUED_PKT;
        pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
                                              priv->wmm.ra_list_spinlock);
        PRINTM(MINFO, "MLAN_STATUS_RESOURCE is returned\n");
        pmbuf_aggr->status_code = MLAN_ERROR_PKT_INVALID;
        break;
    case MLAN_STATUS_FAILURE:
        pmadapter->data_sent = MFALSE;
        PRINTM(MERROR, "Error: host_to_card failed: 0x%X\n", ret);
        pmbuf_aggr->status_code = MLAN_ERROR_DATA_TX_FAIL;
        pmadapter->dbg.num_tx_host_to_card_failure++;
        wlan_write_data_complete(pmadapter, pmbuf_aggr, ret);
        goto exit;
    case MLAN_STATUS_PENDING:
        pmadapter->data_sent = MFALSE;
        break;
    case MLAN_STATUS_SUCCESS:
        wlan_write_data_complete(pmadapter, pmbuf_aggr, ret);
        break;
    default:
        break;
    }
    if (ret != MLAN_STATUS_RESOURCE) {
        pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
                                            priv->wmm.ra_list_spinlock);
        if (wlan_is_ralist_valid(priv, pra_list, ptrindex)) {
            priv->wmm.packets_out[ptrindex]++;
            priv->wmm.tid_tbl_ptr[ptrindex].ra_list_curr = pra_list;
        }
        pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur =
            pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur->pnext;
        pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
                                              priv->wmm.ra_list_spinlock);
    }
    PRINTM_GET_SYS_TIME(MDATA, &sec, &usec);
    PRINTM_NETINTF(MDATA, priv);
    PRINTM(MDATA, "%lu.%06lu : Data => FW\n", sec, usec);

  exit:
    LEAVE();
    return (pkt_size + headroom);
}
示例#21
0
/**
 *  @brief This function parses country info from AP and
 *           download country info to FW
 *
 *  @param pmpriv       A pointer to mlan_private structure
 *  @param pbss_desc     A pointer to BSS descriptor
 *
 *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
 */
mlan_status
wlan_11d_parse_dnld_countryinfo(mlan_private *pmpriv,
				BSSDescriptor_t *pbss_desc)
{
	mlan_status ret = MLAN_STATUS_SUCCESS;
	mlan_adapter *pmadapter = pmpriv->adapter;
	parsed_region_chan_11d_t region_chan;
	parsed_region_chan_11d_t bssdesc_region_chan;
	t_u32 i, j;

	ENTER();

	/* Only valid if 11D is enabled */
	if (wlan_11d_is_enabled(pmpriv)) {

		memset(pmadapter, &region_chan, 0,
		       sizeof(parsed_region_chan_11d_t));
		memset(pmadapter, &bssdesc_region_chan, 0,
		       sizeof(parsed_region_chan_11d_t));

		memcpy(pmadapter, &region_chan,
		       &pmadapter->parsed_region_chan,
		       sizeof(parsed_region_chan_11d_t));

		if (pbss_desc) {
			/* Parse domain info if available */
			ret = wlan_11d_parse_domain_info(pmadapter,
							 &pbss_desc->
							 country_info,
							 (t_u8)pbss_desc->
							 bss_band,
							 &bssdesc_region_chan);

			if (ret == MLAN_STATUS_SUCCESS) {
				/* Update the channel-power table */
				for (i = 0;
				     ((i < bssdesc_region_chan.no_of_chan)
				      && (i < MAX_NO_OF_CHAN)); i++) {

					for (j = 0;
					     ((j < region_chan.no_of_chan)
					      && (j < MAX_NO_OF_CHAN)); j++) {
						/*
						 * Channel already exists, use minimum
						 * of existing tx power and tx_power
						 * received from country info of the
						 * current AP
						 */
						if (region_chan.chan_pwr[i].
						    chan ==
						    bssdesc_region_chan.
						    chan_pwr[j].chan &&
						    region_chan.chan_pwr[i].
						    band ==
						    bssdesc_region_chan.
						    chan_pwr[j].band) {
							region_chan.chan_pwr[j].
								pwr =
								MIN(region_chan.
								    chan_pwr[j].
								    pwr,
								    bssdesc_region_chan.
								    chan_pwr[i].
								    pwr);
							break;
						}
					}
				}
			}
		}

		/* Generate domain info */
		wlan_11d_generate_domain_info(pmadapter, &region_chan);

		/* Set domain info */
		ret = wlan_11d_send_domain_info(pmpriv, MNULL);
		if (ret) {
			PRINTM(MERROR,
			       "11D: Error sending domain info to FW\n");
		}
	}

	LEAVE();
	return ret;
}
示例#22
0
/** 
 *  @brief This function handles events generated by firmware
 *  
 *  @param priv	A pointer to mlan_private structure
 *
 *  @return		MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
 */
mlan_status
mlan_process_sta_event(IN t_void * priv)
{
    pmlan_private pmpriv = (pmlan_private) priv;
    pmlan_adapter pmadapter = pmpriv->adapter;
    mlan_status ret = MLAN_STATUS_SUCCESS;
    t_u32 eventcause = pmadapter->event_cause;
    t_u8 event_buf[100];
    mlan_event *pevent = (mlan_event *) event_buf;

    ENTER();

    /* Clear BSS_NO_BITS from event */
    eventcause &= EVENT_ID_MASK;
    switch (eventcause) {
    case EVENT_DUMMY_HOST_WAKEUP_SIGNAL:
        PRINTM(MERROR,
               "Invalid EVENT: DUMMY_HOST_WAKEUP_SIGNAL, ignoring it\n");
        break;
    case EVENT_LINK_SENSED:
        PRINTM(MEVENT, "EVENT: LINK_SENSED\n");
        pmpriv->adhoc_is_link_sensed = MTRUE;
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_ADHOC_LINK_SENSED, MNULL);
        break;

    case EVENT_DEAUTHENTICATED:
        PRINTM(MEVENT, "EVENT: Deauthenticated\n");
        pmadapter->dbg.num_event_deauth++;
        wlan_handle_disconnect_event(pmpriv);
        break;

    case EVENT_DISASSOCIATED:
        PRINTM(MEVENT, "EVENT: Disassociated\n");
        pmadapter->dbg.num_event_disassoc++;
        wlan_handle_disconnect_event(pmpriv);
        break;

    case EVENT_LINK_LOST:
        PRINTM(MEVENT, "EVENT: Link lost\n");
        pmadapter->dbg.num_event_link_lost++;
        wlan_handle_disconnect_event(pmpriv);
        break;

    case EVENT_PS_SLEEP:
        PRINTM(MINFO, "EVENT: SLEEP\n");
        PRINTM(MEVENT, "_");

        pmadapter->ps_state = PS_STATE_PRE_SLEEP;

        wlan_check_ps_cond(pmadapter);
        break;

    case EVENT_PS_AWAKE:
        PRINTM(MINFO, "EVENT: AWAKE \n");
        PRINTM(MEVENT, "|");
        pmadapter->tx_lock_flag = MFALSE;
        if (pmadapter->sleep_period.period) {
            if (MTRUE == wlan_check_last_packet_indication(pmpriv)) {
                if (!pmadapter->data_sent && pmpriv->gen_null_pkg) {
                    wlan_send_null_packet(pmpriv,
                                          MRVDRV_TxPD_POWER_MGMT_NULL_PACKET |
                                          MRVDRV_TxPD_POWER_MGMT_LAST_PACKET);
                    pmadapter->ps_state = PS_STATE_SLEEP;
                    return MLAN_STATUS_SUCCESS;
                }
            }
        }
        pmadapter->ps_state = PS_STATE_AWAKE;
        pmadapter->pm_wakeup_card_req = MFALSE;
        pmadapter->pm_wakeup_fw_try = MFALSE;

        break;

    case EVENT_DEEP_SLEEP_AWAKE:
        wlan_pm_reset_card(pmadapter);
        PRINTM(MEVENT, "EVENT: DS_AWAKE\n");
        if (pmadapter->is_deep_sleep == MTRUE) {
            pmadapter->is_deep_sleep = MFALSE;
        }
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DS_AWAKE, MNULL);
        break;

    case EVENT_HS_ACT_REQ:
        PRINTM(MEVENT, "EVENT: HS_ACT_REQ\n");
        ret = wlan_prepare_cmd(priv,
                               HostCmd_CMD_802_11_HS_CFG_ENH,
                               0, 0, MNULL, MNULL);
        break;

    case EVENT_MIC_ERR_UNICAST:
        PRINTM(MEVENT, "EVENT: UNICAST MIC ERROR\n");
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_MIC_ERR_UNI, MNULL);
        break;

    case EVENT_MIC_ERR_MULTICAST:
        PRINTM(MEVENT, "EVENT: MULTICAST MIC ERROR\n");
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_MIC_ERR_MUL, MNULL);
        break;
    case EVENT_MIB_CHANGED:
    case EVENT_INIT_DONE:
        break;

    case EVENT_ADHOC_BCN_LOST:
        PRINTM(MEVENT, "EVENT: ADHOC_BCN_LOST\n");
        pmpriv->adhoc_is_link_sensed = MFALSE;
        wlan_clean_txrx(pmpriv);
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_ADHOC_LINK_LOST, MNULL);
        break;
    case EVENT_BG_SCAN_REPORT:
        PRINTM(MEVENT, "EVENT: BGS_REPORT\n");
        /* Clear the previous scan result */
        memset(pmadapter->pscan_table, 0x00,
               sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST);
        pmadapter->num_in_scan_table = 0;
        pmadapter->pbcn_buf_end = pmadapter->bcn_buf;
        ret = wlan_prepare_cmd(pmpriv,
                               HostCmd_CMD_802_11_BG_SCAN_QUERY,
                               HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
        break;
    case EVENT_STOP_TX:
        PRINTM(MEVENT, "EVENT: Stop Tx (%#x)\n", eventcause);
        wlan_11h_tx_disable(pmpriv);
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_STOP_TX, MNULL);
        break;
    case EVENT_START_TX:
        PRINTM(MEVENT, "EVENT: Start Tx (%#x)\n", eventcause);
        wlan_11h_tx_enable(pmpriv);
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_START_TX, MNULL);
        break;
    case EVENT_CHANNEL_SWITCH:
        PRINTM(MEVENT, "EVENT: Channel Switch (%#x)\n", eventcause);
        /* To be handled for 'chanswann' private command */
        break;
    case EVENT_MEAS_REPORT_RDY:
        PRINTM(MINFO, "EVENT: Measurement Report Ready (%#x)\n", eventcause);
        /* To be handled for 'measreq' private command */
        break;
    case EVENT_WMM_STATUS_CHANGE:
        PRINTM(MEVENT, "EVENT: WMM status changed\n");
        ret = (mlan_status) wlan_cmd_wmm_status_change(pmpriv);
        break;

    case EVENT_RSSI_LOW:
        PRINTM(MEVENT, "EVENT: Beacon RSSI_LOW\n");
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BCN_RSSI_LOW, MNULL);
        break;
    case EVENT_SNR_LOW:
        PRINTM(MEVENT, "EVENT: Beacon SNR_LOW\n");
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BCN_SNR_LOW, MNULL);
        break;
    case EVENT_MAX_FAIL:
        PRINTM(MEVENT, "EVENT: MAX_FAIL\n");
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_MAX_FAIL, MNULL);
        break;
    case EVENT_RSSI_HIGH:
        PRINTM(MEVENT, "EVENT: Beacon RSSI_HIGH\n");
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BCN_RSSI_HIGH, MNULL);
        break;
    case EVENT_SNR_HIGH:
        PRINTM(MEVENT, "EVENT: Beacon SNR_HIGH\n");
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BCN_SNR_HIGH, MNULL);
        break;
    case EVENT_DATA_RSSI_LOW:
        PRINTM(MEVENT, "EVENT: Data RSSI_LOW\n");
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_RSSI_LOW, MNULL);
        break;
    case EVENT_DATA_SNR_LOW:
        PRINTM(MEVENT, "EVENT: Data SNR_LOW\n");
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_SNR_LOW, MNULL);
        break;
    case EVENT_DATA_RSSI_HIGH:
        PRINTM(MEVENT, "EVENT: Data RSSI_HIGH\n");
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_RSSI_HIGH, MNULL);
        break;
    case EVENT_DATA_SNR_HIGH:
        PRINTM(MEVENT, "EVENT: Data SNR_HIGH\n");
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_DATA_SNR_HIGH, MNULL);
        break;
    case EVENT_LINK_QUALITY:
        PRINTM(MEVENT, "EVENT: Link Quality\n");
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_LINK_QUALITY, MNULL);
        break;
    case EVENT_PRE_BEACON_LOST:
        PRINTM(MEVENT, "EVENT: Pre-Beacon Lost\n");
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_PRE_BCN_LOST, MNULL);
        break;
    case EVENT_IBSS_COALESCED:
        PRINTM(MEVENT, "EVENT: IBSS_COALESCED\n");
        ret = wlan_prepare_cmd(pmpriv,
                               HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,
                               HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
        break;
    case EVENT_PORT_RELEASE:
        PRINTM(MEVENT, "EVENT: PORT RELEASE\n");
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_PORT_RELEASE, MNULL);
        break;
    case EVENT_ADDBA:
        PRINTM(MEVENT, "EVENT: ADDBA Request\n");
        wlan_prepare_cmd(pmpriv, HostCmd_CMD_11N_ADDBA_RSP,
                         HostCmd_ACT_GEN_SET, 0, MNULL, pmadapter->event_body);
        break;
    case EVENT_DELBA:
        PRINTM(MEVENT, "EVENT: DELBA Request\n");
        wlan_11n_delete_bastream(pmpriv, pmadapter->event_body);
        break;
    case EVENT_BA_STREAM_TIEMOUT:
        PRINTM(MEVENT, "EVENT:  BA Stream timeout\n");
        wlan_11n_ba_stream_timeout(pmpriv,
                                   (HostCmd_DS_11N_BATIMEOUT *) pmadapter->
                                   event_body);
        break;
    case EVENT_AMSDU_AGGR_CTRL:
        PRINTM(MEVENT, "EVENT:  AMSDU_AGGR_CTRL %d\n",
               *(t_u16 *) pmadapter->event_body);
        pmpriv->adapter->tx_buf_size =
            MIN(pmpriv->adapter->max_tx_buf_size,
                wlan_le16_to_cpu(*(t_u16 *) pmadapter->event_body));
        PRINTM(MEVENT, "tx_buf_size %d\n", pmpriv->adapter->tx_buf_size);
        break;

    case EVENT_WEP_ICV_ERR:
        PRINTM(MEVENT, "EVENT: WEP ICV error\n");
        pevent->bss_num = pmpriv->bss_num;
        pevent->event_id = MLAN_EVENT_ID_FW_WEP_ICV_ERR;
        pevent->event_len = sizeof(Event_WEP_ICV_ERR);
        memcpy((t_u8 *) pevent->event_buf, pmadapter->event_body,
               pevent->event_len);
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_WEP_ICV_ERR, pevent);
        break;

    case EVENT_BW_CHANGE:
        PRINTM(MEVENT, "EVENT: BW Change\n");
        pevent->bss_num = pmpriv->bss_num;
        pevent->event_id = MLAN_EVENT_ID_FW_BW_CHANGED;
        pevent->event_len = sizeof(t_u8);
        /* Copy event body from the event buffer */
        memcpy((t_u8 *) pevent->event_buf, pmadapter->event_body,
               pevent->event_len);
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BW_CHANGED, pevent);
        break;

    default:
        PRINTM(MEVENT, "EVENT: unknown event id: %#x\n", eventcause);
        wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_UNKNOWN, MNULL);
        break;
    }

    LEAVE();
    return ret;
}
示例#23
0
/**
 *  @brief This function parses country information for region channel
 *
 *  @param pmadapter            Pointer to mlan_adapter structure
 *  @param country_info         Country information
 *  @param band                 Chan band
 *  @param parsed_region_chan   Pointer to parsed_region_chan_11d_t
 *
 *  @return                     MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
 */
mlan_status
wlan_11d_parse_domain_info(pmlan_adapter pmadapter,
			   IEEEtypes_CountryInfoFullSet_t *country_info,
			   t_u8 band,
			   parsed_region_chan_11d_t *parsed_region_chan)
{
	t_u8 no_of_sub_band, no_of_chan;
	t_u8 last_chan, first_chan, cur_chan = 0;
	t_u8 idx = 0;
	t_u8 j, i;

	ENTER();

	/*
	 * Validation Rules:
	 *    1. Valid Region Code
	 *    2. First Chan increment
	 *    3. Channel range no overlap
	 *    4. Channel is valid?
	 *    5. Channel is supported by Region?
	 *    6. Others
	 */

	HEXDUMP("country_info", (t_u8 *)country_info, 30);

	/* Step 1: Check region_code */
	if (!(*(country_info->country_code)) ||
	    (country_info->len <= COUNTRY_CODE_LEN)) {
		/* No region info or wrong region info: treat as no 11D info */
		LEAVE();
		return MLAN_STATUS_FAILURE;
	}

	no_of_sub_band = (country_info->len - COUNTRY_CODE_LEN) /
		sizeof(IEEEtypes_SubbandSet_t);

	for (j = 0, last_chan = 0; j < no_of_sub_band; j++) {

		if (country_info->sub_band[j].first_chan <= last_chan) {
			/* Step2&3: Check First Chan Num increment and no
			   overlap */
			PRINTM(MINFO, "11D: Chan[%d>%d] Overlap\n",
			       country_info->sub_band[j].first_chan, last_chan);
			continue;
		}

		first_chan = country_info->sub_band[j].first_chan;
		no_of_chan = country_info->sub_band[j].no_of_chan;

		for (i = 0; idx < MAX_NO_OF_CHAN && i < no_of_chan; i++) {
			/* Step 4 : Channel is supported? */
			if (wlan_11d_get_chan
			    (pmadapter, band, first_chan, i,
			     &cur_chan) == MFALSE) {
				/* Chan is not found in UN table */
				PRINTM(MWARN,
				       "11D: channel is not supported: %d\n",
				       i);
				break;
			}

			last_chan = cur_chan;

			/* Step 5: We don't need to check if cur_chan is
			   supported by mrvl in region */
			parsed_region_chan->chan_pwr[idx].chan = cur_chan;
			parsed_region_chan->chan_pwr[idx].band = band;
			parsed_region_chan->chan_pwr[idx].pwr =
				country_info->sub_band[j].max_tx_pwr;
			idx++;
		}

		/* Step 6: Add other checking if any */
	}

	parsed_region_chan->no_of_chan = idx;

	PRINTM(MINFO, "11D: number of channel=0x%x\n",
	       parsed_region_chan->no_of_chan);
	HEXDUMP("11D: parsed_region_chan", (t_u8 *)parsed_region_chan->chan_pwr,
		sizeof(chan_power_11d_t) * idx);

	LEAVE();
	return MLAN_STATUS_SUCCESS;
}
示例#24
0
/** 
 *  @brief This function handles disconnect event, reports disconnect
 *  		to upper layer, cleans tx/rx packets,
 *  		resets link state etc.
 *  
 *  @param priv    A pointer to mlan_private structure
 *
 *  @return        N/A
 */
t_void
wlan_reset_connect_state(pmlan_private priv)
{
    mlan_adapter *pmadapter = priv->adapter;
    mlan_status ret = MLAN_STATUS_SUCCESS;
    state_11d_t enable;

    ENTER();

    if (priv->media_connected != MTRUE) {
        LEAVE();
        return;
    }

    PRINTM(MINFO, "Handles disconnect event.\n");

    priv->media_connected = MFALSE;

    /* Free Tx and Rx packets, report disconnect to upper layer */
    wlan_clean_txrx(priv);

    /* Reset SNR/NF/RSSI values */
    priv->data_rssi_last = 0;
    priv->data_nf_last = 0;
    priv->data_rssi_avg = 0;
    priv->data_nf_avg = 0;
    priv->bcn_rssi_last = 0;
    priv->bcn_nf_last = 0;
    priv->bcn_rssi_avg = 0;
    priv->bcn_nf_avg = 0;
    priv->rxpd_rate = 0;
    priv->rxpd_htinfo = 0;

    PRINTM(MINFO, "Current SSID=%s, SSID Length=%u\n",
           priv->curr_bss_params.bss_descriptor.ssid.ssid,
           priv->curr_bss_params.bss_descriptor.ssid.ssid_len);
    PRINTM(MINFO, "Previous SSID=%s, SSID Length=%u\n",
           priv->prev_ssid.ssid, priv->prev_ssid.ssid_len);
    priv->sec_info.ewpa_enabled = MFALSE;
    priv->sec_info.wpa_enabled = MFALSE;
    priv->sec_info.wpa2_enabled = MFALSE;
    priv->wpa_ie_len = 0;

    priv->sec_info.wapi_enabled = MFALSE;
    priv->wapi_ie_len = 0;
    priv->sec_info.wapi_key_on = MFALSE;

    priv->sec_info.encryption_mode = MLAN_ENCRYPTION_MODE_NONE;

    /* Enable auto data rate */
    priv->is_data_rate_auto = MTRUE;
    priv->data_rate = 0;

    if (priv->bss_mode == MLAN_BSS_MODE_IBSS) {
        priv->adhoc_state = ADHOC_IDLE;
        priv->adhoc_is_link_sensed = MFALSE;
        priv->adhoc_auto_sel = MTRUE;
    }

    /* 
     * Memorize the previous SSID and BSSID so
     * it could be used for re-assoc
     */

    memcpy(&priv->prev_ssid,
           &priv->curr_bss_params.bss_descriptor.ssid,
           sizeof(mlan_802_11_ssid));

    memcpy(priv->prev_bssid,
           priv->curr_bss_params.bss_descriptor.mac_address,
           MLAN_MAC_ADDR_LENGTH);

    /* Need to erase the current SSID and BSSID info */
    memset(&priv->curr_bss_params, 0x00, sizeof(priv->curr_bss_params));

    pmadapter->tx_lock_flag = MFALSE;
    pmadapter->ps_state = PS_STATE_AWAKE;
    pmadapter->pm_wakeup_card_req = MFALSE;

    if ((wlan_11d_get_state(priv) == ENABLE_11D) &&
        (pmadapter->state_11d.user_enable_11d == DISABLE_11D)) {

        pmadapter->state_11d.enable_11d = DISABLE_11D;
        enable = DISABLE_11D;

        /* Send cmd to FW to enable/disable 11D function */
        ret = wlan_prepare_cmd(priv,
                               HostCmd_CMD_802_11_SNMP_MIB,
                               HostCmd_ACT_GEN_SET, Dot11D_i, MNULL, &enable);
        if (ret)
            PRINTM(MERROR, "11D: Failed to enable 11D\n");
    }
    if (pmadapter->num_cmd_timeout && pmadapter->curr_cmd &&
        (pmadapter->cmd_timer_is_set == MFALSE)) {
        LEAVE();
        return;
    }
    wlan_recv_event(priv, MLAN_EVENT_ID_FW_DISCONNECTED, MNULL);

    LEAVE();
}
示例#25
0
/** 
 *  @brief uap addba reject tbl 
 *   
 *  @param dev      A pointer to net_device structure
 *  @param req      A pointer to ifreq structure
 *  @return         0 --success, otherwise fail
 */
static int
woal_uap_addba_reject(struct net_device *dev, struct ifreq *req)
{
    moal_private *priv = (moal_private *) netdev_priv(dev);
    mlan_ioctl_req *ioctl_req = NULL;
    mlan_ds_11n_cfg *cfg_11n = NULL;
    addba_reject_para param;
    int ret = 0;
    int i = 0;

    ENTER();
    memset(&param, 0, sizeof(param));

    /* Sanity check */
    if (req->ifr_data == NULL) {
        PRINTM(MERROR, "woal_uap_addba_reject() corrupt data\n");
        ret = -EFAULT;
        goto done;
    }
    if (copy_from_user(&param, req->ifr_data, sizeof(param))) {
        PRINTM(MERROR, "Copy from user failed\n");
        ret = -EFAULT;
        goto done;
    }
    DBG_HEXDUMP(MCMD_D, "addba_reject tbl", (t_u8 *) & param, sizeof(param));

    ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
    if (ioctl_req == NULL) {
        LEAVE();
        return -ENOMEM;
    }
    cfg_11n = (mlan_ds_11n_cfg *) ioctl_req->pbuf;
    cfg_11n->sub_command = MLAN_OID_11N_CFG_ADDBA_REJECT;
    ioctl_req->req_id = MLAN_IOCTL_11N_CFG;

    if (!param.action) {
        /* Get addba_reject tbl from MLAN */
        ioctl_req->action = MLAN_ACT_GET;
    } else {
        /* Set addba_reject tbl in MLAN */
        ioctl_req->action = MLAN_ACT_SET;
        for (i = 0; i < MAX_NUM_TID; i++) {
            cfg_11n->param.addba_reject[i] = param.addba_reject[i];
        }
    }
    if (MLAN_STATUS_SUCCESS !=
        woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT)) {
        ret = -EFAULT;
        goto done;
    }
    for (i = 0; i < MAX_NUM_TID; i++) {
        param.addba_reject[i] = cfg_11n->param.addba_reject[i];
    }
    /* Copy to user */
    if (copy_to_user(req->ifr_data, &param, sizeof(param))) {
        PRINTM(MERROR, "Copy to user failed!\n");
        ret = -EFAULT;
        goto done;
    }
  done:
    if (ioctl_req)
        kfree(ioctl_req);
    LEAVE();
    return ret;
}
示例#26
0
/**
 *  @brief This function registers MOAL to MLAN module.
 *  
 *  @param pmdevice        A pointer to a mlan_device structure
 *                         allocated in MOAL
 *  @param ppmlan_adapter  A pointer to a t_void pointer to store
 *                         mlan_adapter structure pointer as the context
 *
 *  @return                MLAN_STATUS_SUCCESS
 *                             The registration succeeded.
 *                         MLAN_STATUS_FAILURE
 *                             The registration failed.
 *
 * mlan_status mlan_register (
 *   IN pmlan_device     pmdevice,
 *   OUT t_void          **ppmlan_adapter
 * );
 *
 * Comments
 *   MOAL constructs mlan_device data structure to pass moal_handle and
 *   mlan_callback table to MLAN. MLAN returns mlan_adapter pointer to
 *   the ppmlan_adapter buffer provided by MOAL.
 * Headers:
 *   declared in mlan_decl.h
 * See Also
 *   mlan_unregister
 */
mlan_status
mlan_register(IN pmlan_device pmdevice, OUT t_void ** ppmlan_adapter)
{
    mlan_status ret = MLAN_STATUS_SUCCESS;
    pmlan_adapter pmadapter = MNULL;
    pmlan_callbacks pcb = MNULL;
    t_u8 i = 0;
    t_u32 j = 0;

    MASSERT(pmdevice);
    MASSERT(ppmlan_adapter);
    MASSERT(pmdevice->callbacks.moal_print);
#ifdef DEBUG_LEVEL1
    print_callback = pmdevice->callbacks.moal_print;
#endif
    assert_callback = pmdevice->callbacks.moal_assert;

    ENTER();

    MASSERT(pmdevice->callbacks.moal_malloc);
    MASSERT(pmdevice->callbacks.moal_memset);
    MASSERT(pmdevice->callbacks.moal_memmove);

    /* Allocate memory for adapter structure */
    if ((pmdevice->callbacks.
         moal_malloc(pmdevice->pmoal_handle, sizeof(mlan_adapter), MLAN_MEM_DEF,
                     (t_u8 **) & pmadapter) != MLAN_STATUS_SUCCESS)
        || !pmadapter) {
        ret = MLAN_STATUS_FAILURE;
        goto exit_register;
    }

    pmdevice->callbacks.moal_memset(pmadapter, pmadapter,
                                    0, sizeof(mlan_adapter));

    pcb = &pmadapter->callbacks;

    /* Save callback functions */
    pmdevice->callbacks.moal_memmove(pmadapter->pmoal_handle, pcb,
                                     &pmdevice->callbacks,
                                     sizeof(mlan_callbacks));

    /* Assertion for all callback functions */
    MASSERT(pcb->moal_init_fw_complete);
    MASSERT(pcb->moal_shutdown_fw_complete);
    MASSERT(pcb->moal_send_packet_complete);
    MASSERT(pcb->moal_recv_packet);
    MASSERT(pcb->moal_recv_event);
    MASSERT(pcb->moal_ioctl_complete);
    MASSERT(pcb->moal_write_reg);
    MASSERT(pcb->moal_read_reg);
    MASSERT(pcb->moal_alloc_mlan_buffer);
    MASSERT(pcb->moal_free_mlan_buffer);
    MASSERT(pcb->moal_write_data_sync);
    MASSERT(pcb->moal_read_data_sync);
    MASSERT(pcb->moal_mfree);
    MASSERT(pcb->moal_memcpy);
    MASSERT(pcb->moal_memcmp);
    MASSERT(pcb->moal_get_system_time);
    MASSERT(pcb->moal_init_timer);
    MASSERT(pcb->moal_free_timer);
    MASSERT(pcb->moal_start_timer);
    MASSERT(pcb->moal_stop_timer);
    MASSERT(pcb->moal_init_lock);
    MASSERT(pcb->moal_free_lock);
    MASSERT(pcb->moal_spin_lock);
    MASSERT(pcb->moal_spin_unlock);

    /* Save pmoal_handle */
    pmadapter->pmoal_handle = pmdevice->pmoal_handle;
    if ((pmdevice->int_mode == INT_MODE_GPIO) && (pmdevice->gpio_pin == 0)) {
        PRINTM(MERROR, "SDIO_GPIO_INT_CONFIG: Invalid GPIO Pin\n");
        ret = MLAN_STATUS_FAILURE;
        goto error;
    }
    pmadapter->init_para.int_mode = pmdevice->int_mode;
    pmadapter->init_para.gpio_pin = pmdevice->gpio_pin;
    /* card specific probing has been deferred until now .. */
    if (MLAN_STATUS_SUCCESS != (ret = wlan_sdio_probe(pmadapter))) {
        ret = MLAN_STATUS_FAILURE;
        goto error;
    }
#ifdef MFG_CMD_SUPPORT
    pmadapter->init_para.mfg_mode = pmdevice->mfg_mode;
#endif
#ifdef SDIO_MULTI_PORT_TX_AGGR
    pmadapter->init_para.mpa_tx_cfg = pmdevice->mpa_tx_cfg;
#endif
#ifdef SDIO_MULTI_PORT_RX_AGGR
    pmadapter->init_para.mpa_rx_cfg = pmdevice->mpa_rx_cfg;
#endif
    pmadapter->init_para.auto_ds = pmdevice->auto_ds;
    pmadapter->init_para.ps_mode = pmdevice->ps_mode;
    if (pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_2K ||
        pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_4K ||
        pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_8K)
        pmadapter->init_para.max_tx_buf = pmdevice->max_tx_buf;
#if defined(STA_SUPPORT)
    pmadapter->init_para.cfg_11d = pmdevice->cfg_11d;
#endif

    for (i = 0; i < MLAN_MAX_BSS_NUM; i++) {
        pmadapter->priv[i] = MNULL;
        if (pmdevice->bss_attr[i].active == MTRUE) {
            /* For valid bss_attr, allocate memory for private structure */
            if ((pcb->
                 moal_malloc(pmadapter->pmoal_handle, sizeof(mlan_private),
                             MLAN_MEM_DEF,
                             (t_u8 **) & pmadapter->priv[i]) !=
                 MLAN_STATUS_SUCCESS)
                || !pmadapter->priv[i]) {
                ret = MLAN_STATUS_FAILURE;
                goto error;
            }

            memset(pmadapter, pmadapter->priv[i], 0, sizeof(mlan_private));

            pmadapter->priv[i]->adapter = pmadapter;

            /* Save bss_type, frame_type & bss_priority */
            pmadapter->priv[i]->bss_type =
                (t_u8) pmdevice->bss_attr[i].bss_type;
            pmadapter->priv[i]->frame_type =
                (t_u8) pmdevice->bss_attr[i].frame_type;
            pmadapter->priv[i]->bss_priority =
                (t_u8) pmdevice->bss_attr[i].bss_priority;
            if (pmdevice->bss_attr[i].bss_type == MLAN_BSS_TYPE_STA)
                pmadapter->priv[i]->bss_role = MLAN_BSS_ROLE_STA;
            else if (pmdevice->bss_attr[i].bss_type == MLAN_BSS_TYPE_UAP)
                pmadapter->priv[i]->bss_role = MLAN_BSS_ROLE_UAP;

            /* Save bss_index and bss_num */
            pmadapter->priv[i]->bss_index = i;
            pmadapter->priv[i]->bss_num = (t_u8) pmdevice->bss_attr[i].bss_num;

            /* init function table */
            for (j = 0; j < (sizeof(ops) / sizeof(ops[0])); j++) {
                if (ops[j].bss_role == GET_BSS_ROLE(pmadapter->priv[i])) {
                    memcpy(pmadapter, &pmadapter->priv[i]->ops, &ops[j],
                           sizeof(mlan_operations));
                }
            }
        }
    }

    /* Initialize lock variables */
    if (wlan_init_lock_list(pmadapter) != MLAN_STATUS_SUCCESS) {
        ret = MLAN_STATUS_FAILURE;
        goto error;
    }
    /* Initialize timers */
    if (wlan_init_timer(pmadapter) != MLAN_STATUS_SUCCESS) {
        ret = MLAN_STATUS_FAILURE;
        goto error;
    }
    /* Return pointer of mlan_adapter to MOAL */
    *ppmlan_adapter = pmadapter;

    goto exit_register;

  error:
    PRINTM(MINFO, "Leave mlan_register with error\n");
    /* Free timers */
    wlan_free_timer(pmadapter);
    /* Free lock variables */
    wlan_free_lock_list(pmadapter);
    for (i = 0; i < MLAN_MAX_BSS_NUM; i++) {
        if (pmadapter->priv[i])
            pcb->moal_mfree(pmadapter->pmoal_handle,
                            (t_u8 *) pmadapter->priv[i]);
    }
    pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *) pmadapter);

  exit_register:
    LEAVE();
    return ret;
}
示例#27
0
/** 
 *  @brief uap addba parameter handler
 *   
 *  @param dev      A pointer to net_device structure
 *  @param req      A pointer to ifreq structure
 *  @return         0 --success, otherwise fail
 */
static int
woal_uap_addba_param(struct net_device *dev, struct ifreq *req)
{
    moal_private *priv = (moal_private *) netdev_priv(dev);
    mlan_ioctl_req *ioctl_req = NULL;
    mlan_ds_11n_cfg *cfg_11n = NULL;
    addba_param param;
    int ret = 0;

    ENTER();
    memset(&param, 0, sizeof(param));

    /* Sanity check */
    if (req->ifr_data == NULL) {
        PRINTM(MERROR, "uap_addba_param() corrupt data\n");
        ret = -EFAULT;
        goto done;
    }
    if (copy_from_user(&param, req->ifr_data, sizeof(param))) {
        PRINTM(MERROR, "Copy from user failed\n");
        ret = -EFAULT;
        goto done;
    }
    PRINTM(MIOCTL,
           "addba param: action=%d, timeout=%d, txwinsize=%d, rxwinsize=%d\n",
           (int) param.action, (int) param.timeout, (int) param.txwinsize,
           (int) param.rxwinsize);

    ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
    if (ioctl_req == NULL) {
        LEAVE();
        return -ENOMEM;
    }
    cfg_11n = (mlan_ds_11n_cfg *) ioctl_req->pbuf;
    cfg_11n->sub_command = MLAN_OID_11N_CFG_ADDBA_PARAM;
    ioctl_req->req_id = MLAN_IOCTL_11N_CFG;

    if (!param.action) {
        /* Get addba param from MLAN */
        ioctl_req->action = MLAN_ACT_GET;
    } else {
        /* Set addba param in MLAN */
        ioctl_req->action = MLAN_ACT_SET;
        cfg_11n->param.addba_param.timeout = param.timeout;
        cfg_11n->param.addba_param.txwinsize = param.txwinsize;
        cfg_11n->param.addba_param.rxwinsize = param.rxwinsize;
    }
    if (MLAN_STATUS_SUCCESS !=
        woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT)) {
        ret = -EFAULT;
        goto done;
    }
    param.timeout = cfg_11n->param.addba_param.timeout;
    param.txwinsize = cfg_11n->param.addba_param.txwinsize;
    param.rxwinsize = cfg_11n->param.addba_param.rxwinsize;

    /* Copy to user */
    if (copy_to_user(req->ifr_data, &param, sizeof(param))) {
        PRINTM(MERROR, "Copy to user failed!\n");
        ret = -EFAULT;
        goto done;
    }
  done:
    if (ioctl_req)
        kfree(ioctl_req);
    LEAVE();
    return ret;
}
示例#28
0
/**
 *  @brief Shutdown firmware
 *
 *  @param pmlan_adapter	A pointer to mlan_adapter structure
 *
 *  @return			MLAN_STATUS_SUCCESS
 *                      		The firmware shutdown call succeeded.
 *				MLAN_STATUS_PENDING
 *      	                	The firmware shutdown call is pending.
 *				MLAN_STATUS_FAILURE
 *      	                	The firmware shutdown call failed.
 */
mlan_status
mlan_shutdown_fw(IN t_void * pmlan_adapter)
{
    mlan_status ret = MLAN_STATUS_PENDING;
    mlan_adapter *pmadapter = (mlan_adapter *) pmlan_adapter;
    mlan_private *priv = MNULL;
    pmlan_callbacks pcb;
    t_s32 i = 0;

    ENTER();
    MASSERT(pmlan_adapter);
    /* mlan already shutdown */
    if (pmadapter->hw_status == WlanHardwareStatusNotReady)
        return MLAN_STATUS_SUCCESS;

    pmadapter->hw_status = WlanHardwareStatusClosing;
    /* wait for mlan_process to complete */
    if (pmadapter->mlan_processing) {
        PRINTM(MWARN, "mlan main processing is still running\n");
        return ret;
    }

    /* shut down mlan */
    PRINTM(MINFO, "Shutdown mlan...\n");

    pcb = &pmadapter->callbacks;
    /* Clean up Tx/Rx queues and delete BSS priority table */
    for (i = 0; i < MLAN_MAX_BSS_NUM; i++) {
        if (pmadapter->priv[i]) {
            priv = pmadapter->priv[i];

            wlan_clean_txrx(priv);
            wlan_delete_bsspriotbl(priv);
#ifdef UAP_SUPPORT
            if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
                wlan_delete_station_list(priv);
            }
#endif /* UAP_SUPPORT */
        }
    }

    if (pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pmlan_lock)
        != MLAN_STATUS_SUCCESS) {
        ret = MLAN_STATUS_FAILURE;
        goto exit_shutdown_fw;
    }

    /* Free adapter structure */
    wlan_free_adapter(pmadapter);

    if (pcb->moal_spin_unlock(pmadapter->pmoal_handle, pmadapter->pmlan_lock)
        != MLAN_STATUS_SUCCESS) {
        ret = MLAN_STATUS_FAILURE;
        goto exit_shutdown_fw;
    }

    /* Notify completion */
    ret = wlan_shutdown_fw_complete(pmadapter);

  exit_shutdown_fw:
    LEAVE();
    return ret;
}
示例#29
0
/** 
 *  @brief uap BSS config ioctl handler
 *   
 *  @param dev      A pointer to net_device structure
 *  @param req      A pointer to ifreq structure
 *  @return         0 --success, otherwise fail
 */
static int
woal_uap_bss_cfg_ioctl(struct net_device *dev, struct ifreq *req)
{
    moal_private *priv = (moal_private *) netdev_priv(dev);
    int ret = 0;
    mlan_ds_bss *bss = NULL;
    mlan_ioctl_req *ioctl_req = NULL;
    int offset = 0;
    t_u32 action = 0;

    ENTER();

    /* Sanity check */
    if (req->ifr_data == NULL) {
        PRINTM(MERROR, "uap_bss_ioctl() corrupt data\n");
        ret = -EFAULT;
        goto done;
    }

    /* Get action */
    if (copy_from_user(&action, req->ifr_data + offset, sizeof(action))) {
        PRINTM(MERROR, "Copy from user failed\n");
        ret = -EFAULT;
        goto done;
    }
    offset += sizeof(action);

    /* Allocate an IOCTL request buffer */
    ioctl_req =
        (mlan_ioctl_req *) woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
    if (ioctl_req == NULL) {
        ret = -ENOMEM;
        goto done;
    }

    bss = (mlan_ds_bss *) ioctl_req->pbuf;
    bss->sub_command = MLAN_OID_UAP_BSS_CONFIG;
    ioctl_req->req_id = MLAN_IOCTL_BSS;
    if (action == 1) {
        ioctl_req->action = MLAN_ACT_SET;
    } else {
        ioctl_req->action = MLAN_ACT_GET;
    }

    if (ioctl_req->action == MLAN_ACT_SET) {
        /* Get the BSS config from user */
        if (copy_from_user
            (&bss->param.bss_config, req->ifr_data + offset,
             sizeof(mlan_uap_bss_param))) {
            PRINTM(MERROR, "Copy from user failed\n");
            ret = -EFAULT;
            goto done;
        }
    }

    if (MLAN_STATUS_SUCCESS !=
        woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT)) {
        ret = -EFAULT;
        goto done;
    }

    if (ioctl_req->action == MLAN_ACT_GET) {
        offset = sizeof(action);

        /* Copy to user : BSS config */
        if (copy_to_user
            (req->ifr_data + offset, &bss->param.bss_config,
             sizeof(mlan_uap_bss_param))) {
            PRINTM(MERROR, "Copy to user failed!\n");
            ret = -EFAULT;
            goto done;
        }
    }
  done:
    if (ioctl_req)
        kfree(ioctl_req);
    LEAVE();
    return ret;
}
示例#30
0
/**
 *  @brief This function downloads the firmware
 *
 *  @param pmlan_adapter   A pointer to a t_void pointer to store
 *                         mlan_adapter structure pointer
 *  @param pmfw            A pointer to firmware image
 *
 *  @return                MLAN_STATUS_SUCCESS
 *                             The firmware download succeeded.
 *                         MLAN_STATUS_FAILURE
 *                             The firmware download failed.
 */
mlan_status
mlan_dnld_fw(IN t_void * pmlan_adapter, IN pmlan_fw_image pmfw)
{
    mlan_status ret = MLAN_STATUS_SUCCESS;
    mlan_adapter *pmadapter = (mlan_adapter *) pmlan_adapter;
    t_u32 poll_num = 1;
    t_u32 winner = 0;

    ENTER();
    MASSERT(pmlan_adapter);

    /* Card specific probing */
    ret = wlan_sdio_probe(pmadapter);
    if (ret == MLAN_STATUS_FAILURE) {
        PRINTM(MERROR, "WLAN SDIO probe failed\n", ret);
        LEAVE();
        return ret;
    }

    /* Check if firmware is already running */
    ret = wlan_check_fw_status(pmadapter, poll_num);
    if (ret == MLAN_STATUS_SUCCESS) {
        PRINTM(MMSG, "WLAN FW already running! Skip FW download\n");
        goto done;
    }
    poll_num = MAX_FIRMWARE_POLL_TRIES;

    /* Check if other interface is downloading */
    ret = wlan_check_winner_status(pmadapter, &winner);
    if (ret == MLAN_STATUS_FAILURE) {
        PRINTM(MFATAL, "WLAN read winner status failed!\n");
        goto done;
    }
    if (winner) {
        PRINTM(MMSG, "WLAN is not the winner (0x%x). Skip FW download\n",
               winner);
        poll_num = MAX_MULTI_INTERFACE_POLL_TRIES;
        goto poll_fw;
    }

    if (pmfw) {
        /* Download helper/firmware */
        ret = wlan_dnld_fw(pmadapter, pmfw);
        if (ret != MLAN_STATUS_SUCCESS) {
            PRINTM(MERROR, "wlan_dnld_fw fail ret=0x%x\n", ret);
            LEAVE();
            return ret;
        }
    }

  poll_fw:
    /* Check if the firmware is downloaded successfully or not */
    ret = wlan_check_fw_status(pmadapter, poll_num);
    if (ret != MLAN_STATUS_SUCCESS) {
        PRINTM(MFATAL, "FW failed to be active in time!\n");
        ret = MLAN_STATUS_FAILURE;
        LEAVE();
        return ret;
    }
  done:

    /* re-enable host interrupt for mlan after fw dnld is successful */
    wlan_enable_host_int(pmadapter);

    LEAVE();
    return ret;
}