Example #1
0
/**
 * __wcnss_debugfs_open() - open debugfs
 * @inode: inode pointer
 * @file: file pointer
 *
 * Return: 0 on success, error number otherwise
 */
static int __wcnss_debugfs_open(struct inode *inode, struct file *file)
{
	hdd_adapter_t *adapter;
	hdd_context_t *hdd_ctx;
	int ret;

	ENTER();

	if (inode->i_private)
		file->private_data = inode->i_private;

	adapter = (hdd_adapter_t *)file->private_data;
	if ((NULL == adapter) || (WLAN_HDD_ADAPTER_MAGIC != adapter->magic)) {
		VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
			   "%s: Invalid adapter or adapter has invalid magic.",
			   __func__);
		return -EINVAL;
	}

	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
	ret = wlan_hdd_validate_context(hdd_ctx);
	if (0 != ret)
		return ret;

	EXIT();
	return 0;
}
int iw_set_oem_data_req(
        struct net_device *dev, 
        struct iw_request_info *info,
        union iwreq_data *wrqu,
        char *extra)
{
    eHalStatus status = eHAL_STATUS_SUCCESS;
    struct iw_oem_data_req *pOemDataReq = NULL;
    tOemDataReqConfig oemDataReqConfig;

    tANI_U32 oemDataReqID = 0;

    hdd_adapter_t *pAdapter = (netdev_priv(dev));
    hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);

    if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
    {
       VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
                                  "%s:LOGP in Progress. Ignore!!!",__func__);
       return -EBUSY;
    }

    do
    {
        if(NULL != wrqu->data.pointer)
        {
            pOemDataReq = (struct iw_oem_data_req *)wrqu->data.pointer;
        }

        if(pOemDataReq == NULL)
        {
            hddLog(LOGE, "in %s oemDataReq == NULL", __func__);
            status = eHAL_STATUS_FAILURE;
            break;
        }

        vos_mem_zero(&oemDataReqConfig, sizeof(tOemDataReqConfig));

        if (copy_from_user((&oemDataReqConfig)->oemDataReq,
                           pOemDataReq->oemDataReq, OEM_DATA_REQ_SIZE))
        {
            VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
                      "%s: copy_from_user() failed!", __func__);
            return -EFAULT;
        }

        status = sme_OemDataReq(WLAN_HDD_GET_HAL_CTX(pAdapter), 
                                                pAdapter->sessionId,
                                                &oemDataReqConfig, 
                                                &oemDataReqID, 
                                                &hdd_OemDataReqCallback, 
                                                dev);
    
        pwextBuf->oemDataReqID = oemDataReqID;
        pwextBuf->oemDataReqInProgress = TRUE;

    } while(0);
    
    return status;
}
Example #3
0
eHalStatus wlan_hdd_remain_on_channel_callback( tHalHandle hHal, void* pCtx,
                                                eHalStatus status )
{
    hdd_adapter_t *pAdapter = (hdd_adapter_t*) pCtx;
    hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
    hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;

    if( pRemainChanCtx == NULL )
    {
       hddLog( LOGW,
          "%s: No Rem on channel pending for which Rsp is received", __func__);
       return eHAL_STATUS_SUCCESS;
    }

    hddLog( LOG1, "Received remain on channel rsp");

    cfgState->remain_on_chan_ctx = NULL;

    if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
    {
        if( cfgState->buf )
        {
           hddLog( LOGP, 
                   "%s: We need to receive yet an ack from one of tx packet",
                   __func__);
        }
        cfg80211_remain_on_channel_expired( pRemainChanCtx->dev,
                              pRemainChanCtx->cookie,
                              &pRemainChanCtx->chan,
                              pRemainChanCtx->chan_type, GFP_KERNEL );
    }

    vos_mem_free( pRemainChanCtx );

    if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
         ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
         ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
       )
    {
        tANI_U8 sessionId = pAdapter->sessionId;
        sme_DeregisterMgmtFrame(
                   hHal, sessionId,
                   (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
                    NULL, 0 );
    }
    else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
              ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
            )
    {
        WLANSAP_DeRegisterMgmtFrame(
                (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
                (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
                NULL, 0 );
    }

    complete(&pAdapter->cancel_rem_on_chan_var);
    return eHAL_STATUS_SUCCESS;
}
Example #4
0
static void wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter)
{
    hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
    int status = 0;

    if(cfgState->remain_on_chan_ctx != NULL)
    {
        hddLog( LOG1, "Cancel Existing Remain on Channel");

        /* Wait till remain on channel ready indication before issuing cancel 
         * remain on channel request, otherwise if remain on channel not 
         * received and if the driver issues cancel remain on channel then lim 
         * will be in unknown state.
         */
        status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
               msecs_to_jiffies(WAIT_REM_CHAN_READY));
        if (!status)
        {
            hddLog( LOGE, 
                    "%s: timeout waiting for remain on channel ready indication",
                    __func__);
        }

        INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
        
        /* Issue abort remain on chan request to sme.
         * The remain on channel callback will make sure the remain_on_chan
         * expired event is sent.
        */
        if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
             ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
             ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
           )
        {
            sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
                                                     pAdapter->sessionId );
        }
        else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
                  (WLAN_HDD_P2P_GO == pAdapter->device_mode)
                )
        {
            WLANSAP_CancelRemainOnChannel(
                                     (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
        }

        status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
               msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));

        if (!status)
        {
            hddLog( LOGE, 
                    "%s: timeout waiting for cancel remain on channel ready indication",
                    __func__);
        }
    }
}
Example #5
0
/**--------------------------------------------------------------------------------------------

  \brief __iw_get_oem_data_rsp() -

  This function gets the oem data response. This invokes
  the respective sme functionality. Function for handling the oem data rsp 
  IOCTL 

  \param - dev  - Pointer to the net device
         - info - Pointer to the iw_oem_data_req
         - wrqu - Pointer to the iwreq data
         - extra - Pointer to the data

  \return - 0 for success, non zero for failure

-----------------------------------------------------------------------------------------------*/
int __iw_get_oem_data_rsp(
        struct net_device *dev,
        struct iw_request_info *info,
        union iwreq_data *wrqu,
        char *extra)
{
    int                                   rc = 0;
    eHalStatus                            status;
    struct iw_oem_data_rsp*               pHddOemDataRsp;
    tOemDataRsp*                          pSmeOemDataRsp;
    hdd_adapter_t *pAdapter;
    hdd_context_t *pHddCtx;

    ENTER();
    pAdapter = (netdev_priv(dev));
    if (NULL == pAdapter)
    {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                  "%s: Adapter is NULL",__func__);
        return -EINVAL;
    }
    pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
    rc = wlan_hdd_validate_context(pHddCtx);
    if (0 != rc)
    {
        return rc;
    }
    do
    {
        //get the oem data response from sme
        status = sme_getOemDataRsp(WLAN_HDD_GET_HAL_CTX(pAdapter), &pSmeOemDataRsp);
        if (status != eHAL_STATUS_SUCCESS)
        {
            hddLog(LOGE, "%s: failed in sme_getOemDataRsp", __func__);
            rc = -EIO;
            break;
        }
        else
        {
            if (pSmeOemDataRsp != NULL)
            {
                pHddOemDataRsp = (struct iw_oem_data_rsp*)(extra);
                vos_mem_copy(pHddOemDataRsp->oemDataRsp, pSmeOemDataRsp->oemDataRsp, OEM_DATA_RSP_SIZE); 
            }
            else
            {
                hddLog(LOGE, "%s: pSmeOemDataRsp = NULL", __func__);
                rc = -EIO;
                break;
            }
        }
    } while(0);

    EXIT();
    return rc;
}
static eHalStatus hdd_ScanRequestCallback(tHalHandle halHandle, void *pContext,
                         tANI_U32 scanId, eCsrScanStatus status)
{
    struct net_device *dev = (struct net_device *) pContext;
    hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ;
    hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
    union iwreq_data wrqu;
    int we_event;
    char *msg;
    
    ENTER();

    hddLog(LOGW,"%s called with halHandle = %p, pContext = %p, scanID = %d,"
           " returned status = %d", __func__, halHandle, pContext,
           (int) scanId, (int) status);

    /* if there is a scan request pending when the wlan driver is unloaded
       we may be invoked as SME flushes its pending queue.  If that is the
       case, the underlying net_device may have already been destroyed, so
       do some quick sanity before proceeding */
    if (pAdapter->dev != dev)
    {
       hddLog(LOGW, "%s: device mismatch %p vs %p",
               __func__, pAdapter->dev, dev);
        return eHAL_STATUS_SUCCESS;
    }

    /* Check the scanId */
    if (pHddCtx->scan_info.scanId != scanId)
    {
        hddLog(LOGW, "%s called with mismatched scanId pHddCtx->scan_info.scanId = %d "
               "scanId = %d ", __func__, (int) pHddCtx->scan_info.scanId,
                (int) scanId);
    }

    /* Scan is no longer pending */
    pHddCtx->scan_info.mScanPending = VOS_FALSE;

    // notify any applications that may be interested
    memset(&wrqu, '\0', sizeof(wrqu));
    we_event = SIOCGIWSCAN;
    msg = NULL;
    wireless_send_event(dev, we_event, &wrqu, msg);

    EXIT();

    VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit !!!",__func__);

    return eHAL_STATUS_SUCCESS;
}
int iw_get_oem_data_rsp(
        struct net_device *dev, 
        struct iw_request_info *info,
        union iwreq_data *wrqu,
        char *extra)
{
    int                                   rc = 0;
    eHalStatus                            status;
    struct iw_oem_data_rsp*               pHddOemDataRsp;
    tOemDataRsp*                          pSmeOemDataRsp;

    hdd_adapter_t *pAdapter = (netdev_priv(dev));

    if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
    {
       VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
                                  "%s:LOGP in Progress. Ignore!!!",__func__);
       return -EBUSY;
    }

    do
    {
        
        status = sme_getOemDataRsp(WLAN_HDD_GET_HAL_CTX(pAdapter), &pSmeOemDataRsp);
        if (status != eHAL_STATUS_SUCCESS)
        {
            hddLog(LOGE, "%s: failed in sme_getOemDataRsp", __func__);
            rc = -EIO;
            break;
        }
        else
        {
            if (pSmeOemDataRsp != NULL)
            {
                pHddOemDataRsp = (struct iw_oem_data_rsp*)(extra);
                vos_mem_copy(pHddOemDataRsp->oemDataRsp, pSmeOemDataRsp->oemDataRsp, OEM_DATA_RSP_SIZE); 
            }
            else
            {
                hddLog(LOGE, "%s: pSmeOemDataRsp = NULL", __func__);
                rc = -EIO;
                break;
            }
        }
    } while(0);

    return rc;
}
static eHalStatus hdd_ScanRequestCallback(tHalHandle halHandle, void *pContext,
                         tANI_U32 scanId, eCsrScanStatus status)
{
    struct net_device *dev = (struct net_device *) pContext;
    hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ;
    hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
    union iwreq_data wrqu;
    int we_event;
    char *msg;
    
    ENTER();

    hddLog(LOGW,"%s called with halHandle = %p, pContext = %p, scanID = %d,"
           " returned status = %d", __func__, halHandle, pContext,
           (int) scanId, (int) status);

    if (pAdapter->dev != dev)
    {
       hddLog(LOGW, "%s: device mismatch %p vs %p",
               __func__, pAdapter->dev, dev);
        return eHAL_STATUS_SUCCESS;
    }

    
    if (pHddCtx->scan_info.scanId != scanId)
    {
        hddLog(LOGW, "%s called with mismatched scanId pHddCtx->scan_info.scanId = %d "
               "scanId = %d ", __func__, (int) pHddCtx->scan_info.scanId,
                (int) scanId);
    }

    
    pHddCtx->scan_info.mScanPending = VOS_FALSE;

    
    memset(&wrqu, '\0', sizeof(wrqu));
    we_event = SIOCGIWSCAN;
    msg = NULL;
    wireless_send_event(dev, we_event, &wrqu, msg);

    EXIT();

    VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit !!!",__func__);

    return eHAL_STATUS_SUCCESS;
}
Example #9
0
VOS_STATUS hdd_debugfs_init(hdd_adapter_t *pAdapter)
{
    hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
    pHddCtx->debugfs_phy = debugfs_create_dir("wlan_wcnss", 0);

    if (NULL == pHddCtx->debugfs_phy)
        return VOS_STATUS_E_FAILURE;

    if (NULL == debugfs_create_file("wow_pattern", S_IRUSR | S_IWUSR,
        pHddCtx->debugfs_phy, pAdapter, &fops_wowpattern))
        return VOS_STATUS_E_FAILURE;

    if (NULL == debugfs_create_file("pattern_gen", S_IRUSR | S_IWUSR,
        pHddCtx->debugfs_phy, pAdapter, &fops_patterngen))
        return VOS_STATUS_E_FAILURE;

    return VOS_STATUS_SUCCESS;
}
Example #10
0
/**============================================================================
  @brief hdd_tx_low_resource_cbk() - Callback function invoked in the 
  case where VOS packets are not available at the time of the call to get 
  packets. This callback function is invoked by VOS when packets are 
  available.

  @param pVosPacket : [in]  pointer to VOS packet 
  @param userData   : [in]  opaque user data that was passed initially 
  
  @return           : VOS_STATUS_E_FAILURE if any errors encountered, 
                    : VOS_STATUS_SUCCESS otherwise
  =============================================================================*/
VOS_STATUS hdd_tx_low_resource_cbk( vos_pkt_t *pVosPacket, 
                                    v_VOID_t *userData )
{
   VOS_STATUS status;
   v_SINT_t i = 0;
   v_SIZE_t size = 0;
   hdd_adapter_t* pAdapter = (hdd_adapter_t *)userData;
   
   if(pAdapter == NULL)
   {
      VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __FUNCTION__);
      return VOS_STATUS_E_FAILURE;
   }

   //Return the packet to VOS. We just needed to know that VOS is out of low resource
   //situation. Here we will only signal TL that there is a pending data for a STA. 
   //VOS packet will be requested (if needed) when TL comes back to fetch data.
   vos_pkt_return_packet( pVosPacket );

   pAdapter->isVosOutOfResource = VOS_FALSE;

   //Indicate to TL that there is pending data if a queue is non empty
   for( i=NUM_TX_QUEUES-1; i>=0; --i )
   {
      size = 0;
      hdd_list_size( &pAdapter->wmm_tx_queue[i], &size );
      if ( size > 0 )
      {
         status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, 
                                        (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId [0], 
                                        (WLANTL_ACEnumType)i );
         if( !VOS_IS_STATUS_SUCCESS( status ) )
         {
            VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Failure in indicating pkt to TL for ac=%d", __FUNCTION__,i); 
         }
      }
   }

   return VOS_STATUS_SUCCESS;
}
Example #11
0
int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
                                      struct net_device *dev, u64 cookie )
{
    hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
    hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
    int status = 0;

    hddLog( LOG1, "Cancel remain on channel req");

    if (((hdd_context_t*)pAdapter->pHddCtx)->isLogpInProgress)
    {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                "%s:LOGP in Progress. Ignore!!!", __func__);
        return -EAGAIN;
    }
    /* FIXME cancel currently running remain on chan.
     * Need to check cookie and cancel accordingly
     */
    if( (cfgState->remain_on_chan_ctx == NULL) ||
        (cfgState->remain_on_chan_ctx->cookie != cookie) )
    {
        hddLog( LOGE,
            "%s: No Remain on channel pending with specified cookie value",
             __func__);
        return -EINVAL;
    }
    
    /* wait until remain on channel ready event received 
     * for already issued remain on channel request */
    status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
            msecs_to_jiffies(WAIT_REM_CHAN_READY));
    if (!status)
    {
        hddLog( LOGE, 
                "%s: timeout waiting for remain on channel ready indication",
                __func__);
    }
    INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
    /* Issue abort remain on chan request to sme.
     * The remain on channel callback will make sure the remain_on_chan
     * expired event is sent.
     */
    if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
         ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
         ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
       )
    {
        tANI_U8 sessionId = pAdapter->sessionId; 
        sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
                                            sessionId );
    }
    else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
              (WLAN_HDD_P2P_GO == pAdapter->device_mode)
            )
    {
        WLANSAP_CancelRemainOnChannel(
                                (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
    }
    else 
    {
       hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid device_mode = %d",
                            __func__, pAdapter->device_mode);
       return -EIO;
    }
    wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
            msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
    return 0;
}
Example #12
0
static int wlan_hdd_request_remain_on_channel( struct wiphy *wiphy,
                                   struct net_device *dev,
                                   struct ieee80211_channel *chan,
                                   enum nl80211_channel_type channel_type,
                                   unsigned int duration, u64 *cookie,
                                   rem_on_channel_request_type_t request_type )
{
    hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
    hdd_remain_on_chan_ctx_t *pRemainChanCtx;
    hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
    hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
                                 __func__,pAdapter->device_mode);

    hddLog( LOG1,
        "chan(hw_val)0x%x chan(centerfreq) %d chan type 0x%x, duration %d",
        chan->hw_value, chan->center_freq, channel_type, duration );

    //Cancel existing remain On Channel if any
    wlan_hdd_cancel_existing_remain_on_channel(pAdapter);

    /* When P2P-GO and if we are trying to unload the driver then
     * wlan driver is keep on receiving the remain on channel command
     * and which is resulting in crash. So not allowing any remain on
     * channel requets when Load/Unload is in progress*/
    if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
    {
        hddLog( LOGE,
                "%s: Wlan Load/Unload is in progress", __func__);
        return -EBUSY;
    }

    if (((hdd_context_t*)pAdapter->pHddCtx)->isLogpInProgress)
    {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                "%s:LOGP in Progress. Ignore!!!", __func__);
        return -EAGAIN;
    }
    pRemainChanCtx = vos_mem_malloc( sizeof(hdd_remain_on_chan_ctx_t) );
    if( NULL == pRemainChanCtx )
    {
        hddLog(VOS_TRACE_LEVEL_FATAL,
             "%s: Not able to allocate memory for Channel context",
                                         __func__);
        return -ENOMEM;
    }

    vos_mem_copy( &pRemainChanCtx->chan, chan,
                   sizeof(struct ieee80211_channel) );

    pRemainChanCtx->chan_type = channel_type;
    pRemainChanCtx->duration = duration;
    pRemainChanCtx->dev = dev;
    *cookie = (tANI_U32) pRemainChanCtx;
    pRemainChanCtx->cookie = *cookie;
    pRemainChanCtx->rem_on_chan_request = request_type;
    cfgState->remain_on_chan_ctx = pRemainChanCtx;
    cfgState->current_freq = chan->center_freq;
    
    INIT_COMPLETION(pAdapter->rem_on_chan_ready_event);

    //call sme API to start remain on channel.
    if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
         ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
         ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
       )
    {
        tANI_U8 sessionId = pAdapter->sessionId; 
        //call sme API to start remain on channel.
        sme_RemainOnChannel(
                       WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId,
                       chan->hw_value, duration,
                       wlan_hdd_remain_on_channel_callback, pAdapter );

        sme_RegisterMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter),
                              sessionId, (SIR_MAC_MGMT_FRAME << 2) |
                              (SIR_MAC_MGMT_PROBE_REQ << 4), NULL, 0 );

    }
    else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
              ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
            )
    {
        //call sme API to start remain on channel.
        if (VOS_STATUS_SUCCESS != WLANSAP_RemainOnChannel(
                          (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
                          chan->hw_value, duration,
                          wlan_hdd_remain_on_channel_callback, pAdapter ))

        {
           VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                    "%s: WLANSAP_RemainOnChannel returned fail", __func__);
           cfgState->remain_on_chan_ctx = NULL;
           vos_mem_free (pRemainChanCtx);
           return -EINVAL;
        }


        if (VOS_STATUS_SUCCESS != WLANSAP_RegisterMgmtFrame(
                    (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
                    (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
                    NULL, 0 ))
        {
            VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                    "%s: WLANSAP_RegisterMgmtFrame returned fail", __func__);
            WLANSAP_CancelRemainOnChannel(
                    (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
            return -EINVAL;
        }

    }
    return 0;

}
Example #13
0
void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter,
                            tANI_U32 nFrameLength, 
                            tANI_U8* pbFrames,
                            tANI_U8 frameType,
                            tANI_U32 rxChan )
{
    tANI_U16 freq;
    tANI_U8 type = 0;
    tANI_U8 subType = 0; 
    tActionFrmType actionFrmType;
    hdd_cfg80211_state_t *cfgState = NULL;

    hddLog(VOS_TRACE_LEVEL_INFO, "%s: Frame Type = %d Frame Length = %d\n",
            __func__, frameType, nFrameLength);

    if (NULL == pAdapter)
    {
        hddLog( LOGE, FL("pAdapter is NULL"));
        return;
    }

    if (NULL == pAdapter->dev)
    {
        hddLog( LOGE, FL("pAdapter->dev is NULL"));
        return;
    }

    if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
    {
        hddLog( LOGE, FL("pAdapter has invalid magic"));
        return;
    }

    if( !nFrameLength )
    {
        hddLog( LOGE, FL("Frame Length is Invalid ZERO"));
        return;
    }

    if (NULL == pbFrames) {
        hddLog( LOGE, FL("pbFrames is NULL"));
        return;
    }


    if( ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) 
            || ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
      )
    {
        hdd_adapter_t *pMonAdapter =
            hdd_get_mon_adapter( WLAN_HDD_GET_CTX(pAdapter) );

        if( NULL != pMonAdapter )
        {
            hddLog( LOG1, FL("Indicate Frame over Monitor Interface"));
            hdd_sendMgmtFrameOverMonitorIface( pMonAdapter, nFrameLength,
                    pbFrames, frameType);
            return;
        }
    }

    //Channel indicated may be wrong. TODO
    //Indicate an action frame.
    if( rxChan <= MAX_NO_OF_2_4_CHANNELS )
    {
        freq = ieee80211_channel_to_frequency( rxChan,
                IEEE80211_BAND_2GHZ);
    }
    else
    {
        freq = ieee80211_channel_to_frequency( rxChan,
                IEEE80211_BAND_5GHZ);
    }

    type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]);
    subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]);
    cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
    
    if ((type == SIR_MAC_MGMT_FRAME) && 
            (subType == SIR_MAC_MGMT_ACTION) &&
            (pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
    {
        actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
        hddLog(LOG1, "Rx Action Frame %u \n", actionFrmType);
#ifdef WLAN_FEATURE_P2P_DEBUG
        if(actionFrmType > MAX_P2P_ACTION_FRAME_TYPE)
        {
            hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] <--- OTA",
                                                        actionFrmType);
        }
        else
        {
            hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s <--- OTA",
            p2p_action_frame_type[actionFrmType]);
            if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
                (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
            {
                 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
                 hddLog(LOGE,"[P2P State]Inactive state to "
                           "GO negotation progress state");
            }
            else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
                (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
            {
                 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
                 hddLog(LOGE,"[P2P State]GO nego progress to GO nego"
                             " completed state");
            }
            else if( (actionFrmType == WLAN_HDD_INVITATION_REQ) &&
                (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
            {
                 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
                 hddLog(LOGE,"[P2P State]Inactive state to GO nego"
                             " completed state Autonomus GO fromation");
            }
        }
#endif

        if (((actionFrmType == WLAN_HDD_PROV_DIS_RESP) &&
                    (cfgState->actionFrmState == HDD_PD_REQ_ACK_PENDING)) ||
                ((actionFrmType == WLAN_HDD_GO_NEG_RESP) &&
                 (cfgState->actionFrmState == HDD_GO_NEG_REQ_ACK_PENDING)))
        {
            hddLog(LOG1, "%s: ACK_PENDING and But received RESP for Action frame ", 
                    __func__);
            hdd_sendActionCnf(pAdapter, TRUE);
        }
    }

    //Indicate Frame Over Normal Interface
    hddLog( LOG1, FL("Indicate Frame over NL80211 Interface"));

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
    cfg80211_rx_mgmt( pAdapter->dev, freq, 0,
                      pbFrames, nFrameLength,
                      GFP_ATOMIC );
#else
    cfg80211_rx_mgmt( pAdapter->dev, freq,
                      pbFrames, nFrameLength,
                      GFP_ATOMIC );
#endif //LINUX_VERSION_CODE
}
Example #14
0
/**--------------------------------------------------------------------------------------------

  \brief __iw_set_oem_data_req() -

  This function sets the oem data req configuration. This invokes
  the respective sme oem data req functionality. Function for 
  handling the set IOCTL for the oem data req configuration

  \param - dev  - Pointer to the net device
     - info - Pointer to the iw_oem_data_req
     - wrqu - Pointer to the iwreq data
     - extra - Pointer to the data

  \return - 0 for success, non zero for failure

-----------------------------------------------------------------------------------------------*/
int __iw_set_oem_data_req(
        struct net_device *dev,
        struct iw_request_info *info,
        union iwreq_data *wrqu,
        char *extra)
{
    int rc = 0;
    eHalStatus status = eHAL_STATUS_SUCCESS;
    struct iw_oem_data_req *pOemDataReq = NULL;
    tOemDataReqConfig oemDataReqConfig;
    tANI_U32 oemDataReqID = 0;
    hdd_adapter_t *pAdapter;
    hdd_context_t *pHddCtx;
    hdd_wext_state_t *pwextBuf;

    ENTER();
    pAdapter = (netdev_priv(dev));
    if (NULL == pAdapter)
    {
       VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                 "%s: Adapter is NULL",__func__);
       return -EINVAL;
    }
    pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
    rc = wlan_hdd_validate_context(pHddCtx);
    if (0 != rc)
    {
        return rc;
    }

    pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
    if (NULL == pwextBuf)
    {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                  "%s: pwextBuf is NULL",__func__);
        return -EINVAL;
    }

    do
    {
        if (NULL != wrqu->data.pointer)
        {
            pOemDataReq = (struct iw_oem_data_req *)wrqu->data.pointer;
        }

        if (pOemDataReq == NULL)
        {
            hddLog(LOGE, "in %s oemDataReq == NULL", __func__);
            rc = -EIO;
            break;
        }

        vos_mem_zero(&oemDataReqConfig, sizeof(tOemDataReqConfig));

        if (copy_from_user((&oemDataReqConfig)->oemDataReq,
                           pOemDataReq->oemDataReq, OEM_DATA_REQ_SIZE))
        {
            VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
                      "%s: copy_from_user() failed!", __func__);
            rc = -EFAULT;
            break;
        }

        status = sme_OemDataReq(WLAN_HDD_GET_HAL_CTX(pAdapter), 
                                                pAdapter->sessionId,
                                                &oemDataReqConfig, 
                                                &oemDataReqID, 
                                                &hdd_OemDataReqCallback, 
                                                dev);
        if (status != eHAL_STATUS_SUCCESS)
        {
            VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                      "%s: sme_OemDataReq status %d", __func__, status);
            rc = -EFAULT;
            break;
        }
    
        pwextBuf->oemDataReqID = oemDataReqID;
        pwextBuf->oemDataReqInProgress = TRUE;

    } while(0);

    EXIT();
    return rc;
}
Example #15
0
int iw_set_scan(struct net_device *dev, struct iw_request_info *info,
                 union iwreq_data *wrqu, char *extra)
{
   hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ;
   hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
   hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
   tCsrScanRequest scanRequest;
   v_U32_t scanId = 0;
   eHalStatus status = eHAL_STATUS_SUCCESS;
   struct iw_scan_req *scanReq = (struct iw_scan_req *)extra;
   hdd_adapter_t *con_sap_adapter;
   uint16_t con_dfs_ch;

   ENTER();

   VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: enter !!!",__func__);

#ifdef WLAN_BTAMP_FEATURE
   //Scan not supported when AMP traffic is on.
   if( VOS_TRUE == WLANBAP_AmpSessionOn() )
   {
       VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: No scanning when AMP is on",__func__);
       return eHAL_STATUS_SUCCESS;
   }
#endif
    /* Block All Scan during DFS operation and send null scan result */
    con_sap_adapter = hdd_get_con_sap_adapter(pAdapter);
    if (con_sap_adapter) {
        con_dfs_ch = con_sap_adapter->sessionCtx.ap.sapConfig.channel;
        if (con_dfs_ch == AUTO_CHANNEL_SELECT)
            con_dfs_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;

        if (VOS_IS_DFS_CH(con_dfs_ch)) {
            hddLog(LOGW, "%s:##In DFS Master mode. Scan aborted", __func__);
            return -EOPNOTSUPP;
        }
    }


   if(pAdapter->scan_info.mScanPending == TRUE)
   {
       VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:mScanPending is TRUE !!!",__func__);
       return eHAL_STATUS_SUCCESS;
   }

   if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) {
      VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
      return eHAL_STATUS_SUCCESS;
   }
   vos_mem_zero( &scanRequest, sizeof(scanRequest));

   if (NULL != wrqu->data.pointer)
   {
       /* set scanType, active or passive */
       if ((IW_SCAN_TYPE_ACTIVE ==  scanReq->scan_type) ||
           (eSIR_ACTIVE_SCAN == pHddCtx->ioctl_scan_mode))
       {
           scanRequest.scanType = eSIR_ACTIVE_SCAN;
       }
       else
       {
           scanRequest.scanType = eSIR_PASSIVE_SCAN;
       }

       /* set bssid using sockaddr from iw_scan_req */
       vos_mem_copy(scanRequest.bssid,
                       &scanReq->bssid.sa_data, sizeof(scanRequest.bssid) );

      if (wrqu->data.flags & IW_SCAN_THIS_ESSID)  {

          if(scanReq->essid_len) {
              scanRequest.SSIDs.numOfSSIDs = 1;
              scanRequest.SSIDs.SSIDList =( tCsrSSIDInfo *)vos_mem_malloc(sizeof(tCsrSSIDInfo));
              if(scanRequest.SSIDs.SSIDList) {
                 scanRequest.SSIDs.SSIDList->SSID.length =             scanReq->essid_len;
                 vos_mem_copy(scanRequest.SSIDs.SSIDList->  SSID.ssId,scanReq->essid,scanReq->essid_len);
              }
              else
              {
                scanRequest.SSIDs.numOfSSIDs = 0;
                VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Unable to allocate memory",__func__);
                VOS_ASSERT(0);
              }
          }
      }

       /* set min and max channel time */
       scanRequest.minChnTime = scanReq->min_channel_time;
       scanRequest.maxChnTime = scanReq->max_channel_time;

   }
   else
   {
       if (pHddCtx->ioctl_scan_mode == eSIR_ACTIVE_SCAN) {
           /* set the scan type to active */
           scanRequest.scanType = eSIR_ACTIVE_SCAN;
       } else {
           scanRequest.scanType = eSIR_PASSIVE_SCAN;
       }

       vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );

       /* set min and max channel time to zero */
       scanRequest.minChnTime = 0;
       scanRequest.maxChnTime = 0;
   }

   /* set BSSType to default type */
   scanRequest.BSSType = eCSR_BSS_TYPE_ANY;

   /*Scan all the channels */
   scanRequest.ChannelInfo.numOfChannels = 0;

   scanRequest.ChannelInfo.ChannelList = NULL;

   /* set requestType to full scan */
   scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;

   /* if previous genIE is not NULL, update ScanIE */
   if (0 != pwextBuf->genIE.length)
   {
       memset( &pAdapter->scan_info.scanAddIE, 0, sizeof(pAdapter->scan_info.scanAddIE) );
       memcpy( pAdapter->scan_info.scanAddIE.addIEdata, pwextBuf->genIE.addIEdata,
           pwextBuf->genIE.length );
       pAdapter->scan_info.scanAddIE.length = pwextBuf->genIE.length;

       pwextBuf->roamProfile.pAddIEScan = pAdapter->scan_info.scanAddIE.addIEdata;
       pwextBuf->roamProfile.nAddIEScanLength = pAdapter->scan_info.scanAddIE.length;

       /* clear previous genIE after use it */
       memset( &pwextBuf->genIE, 0, sizeof(pwextBuf->genIE) );
   }

   /* push addIEScan in scanRequset if exist */
   if (pAdapter->scan_info.scanAddIE.addIEdata &&
       pAdapter->scan_info.scanAddIE.length)
   {
       scanRequest.uIEFieldLen = pAdapter->scan_info.scanAddIE.length;
       scanRequest.pIEField = pAdapter->scan_info.scanAddIE.addIEdata;
   }

   status = sme_ScanRequest((WLAN_HDD_GET_CTX(pAdapter))->hHal,
                             pAdapter->sessionId, &scanRequest, &scanId,
                             &hdd_ScanRequestCallback, dev);
   if (!HAL_STATUS_SUCCESS(status))
   {
       VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:sme_ScanRequest  fail %d!!!",__func__, status);
       goto error;
   }

   pAdapter->scan_info.mScanPending = TRUE;

   pAdapter->scan_info.scanId = scanId;

error:
   if ((wrqu->data.flags & IW_SCAN_THIS_ESSID) && (scanReq->essid_len))
       vos_mem_free(scanRequest.SSIDs.SSIDList);

   EXIT();

   VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit !!!",__func__);
   return status;
}
Example #16
0
/**============================================================================
  @brief hdd_hard_start_xmit() - Function registered with the Linux OS for 
  transmitting packets. There are 2 versions of this function. One that uses
  locked queue and other that uses lockless queues. Both have been retained to
  do some performance testing

  @param skb      : [in]  pointer to OS packet (sk_buff)
  @param dev      : [in] pointer to Libra network device
  
  @return         : NET_XMIT_DROP if packets are dropped
                  : NET_XMIT_SUCCESS if packet is enqueued succesfully
  ===========================================================================*/
int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
   VOS_STATUS status;
   WLANTL_ACEnumType ac;
   sme_QosWmmUpType up;
   skb_list_node_t *pktNode = NULL;
   hdd_list_node_t *anchor = NULL;
   v_SIZE_t pktListSize = 0;
   hdd_adapter_t *pAdapter =  WLAN_HDD_GET_PRIV_PTR(dev);
   v_BOOL_t granted;

   hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
   
   v_BOOL_t txSuspended = VOS_FALSE;

   ++pAdapter->hdd_stats.hddTxRxStats.txXmitCalled;

   //Get TL AC corresponding to Qdisc queue index/AC.
   ac = hdd_QdiscAcToTlAC[skb->queue_mapping];

   //user priority from IP header, which is already extracted and set from 
   //select_queue call back function
   up = skb->priority;

   ++pAdapter->hdd_stats.hddTxRxStats.txXmitClassifiedAC[ac];

#ifdef HDD_WMM_DEBUG
   VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
              "%s: Classified as ac %d up %d", __FUNCTION__, ac, up);
#endif // HDD_WMM_DEBUG

   spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
   /*For every increment of 10 pkts in the queue, we inform TL about pending pkts.
    * We check for +1 in the logic,to take care of Zero count which 
    * occurs very frequently in low traffic cases */
   if((pAdapter->wmm_tx_queue[ac].count + 1) % 10 == 0)
   {
           VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s:Queue is Filling up.Inform TL again about pending packets", __FUNCTION__);
           WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, pHddStaCtx->conn_info.staId[0], ac );
   }
   //If we have already reached the max queue size, disable the TX queue
   if ( pAdapter->wmm_tx_queue[ac].count == pAdapter->wmm_tx_queue[ac].max_size)
   {
      ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressured;
      ++pAdapter->hdd_stats.hddTxRxStats.txXmitBackPressuredAC[ac];

      netif_tx_stop_queue(netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)));
      pAdapter->isTxSuspended[ac] = VOS_TRUE;
      txSuspended = VOS_TRUE;
   }

   spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);      
   if (VOS_TRUE == txSuspended)
   {
       VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, 
                  "%s: TX queue full for AC=%d Disable OS TX queue", 
                  __FUNCTION__, ac );
      return NETDEV_TX_BUSY;   
   }

   //Use the skb->cb field to hold the list node information
   pktNode = (skb_list_node_t *)&skb->cb;

   //Stick the OS packet inside this node.
   pktNode->skb = skb;

   //Stick the User Priority inside this node 
   pktNode->userPriority = up;


   INIT_LIST_HEAD(&pktNode->anchor);

   //Insert the OS packet into the appropriate AC queue
   spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
   status = hdd_list_insert_back_size( &pAdapter->wmm_tx_queue[ac], &pktNode->anchor, &pktListSize );
   spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);

   if ( !VOS_IS_STATUS_SUCCESS( status ) )
   {
      VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,"%s:Insert Tx queue failed. Pkt dropped", __FUNCTION__);
      ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
      ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
      ++pAdapter->stats.tx_dropped;
      kfree_skb(skb);
      return NETDEV_TX_OK;
   }

   ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued;
   ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac];

   //Make sure we have access to this access category
   if (likely(pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed) || 
           ( pHddStaCtx->conn_info.uIsAuthenticated == VOS_FALSE))
   {
      granted = VOS_TRUE;
   }
   else
   {
      status = hdd_wmm_acquire_access( pAdapter, ac, &granted );
   }

   if ( granted && ( pktListSize == 1 ))
   {
      //Let TL know we have a packet to send for this AC
      //VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s:Indicating Packet to TL", __FUNCTION__);
      status = WLANTL_STAPktPending( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, pHddStaCtx->conn_info.staId[0], ac );      

      if ( !VOS_IS_STATUS_SUCCESS( status ) )
      {
         VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "%s: Failed to signal TL for AC=%d", __FUNCTION__, ac );

         //Remove the packet from queue. It must be at the back of the queue, as TX thread cannot preempt us in the middle
         //as we are in a soft irq context. Also it must be the same packet that we just allocated.
         spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
         status = hdd_list_remove_back( &pAdapter->wmm_tx_queue[ac], &anchor );
         spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
         ++pAdapter->stats.tx_dropped;
         ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped;
         ++pAdapter->hdd_stats.hddTxRxStats.txXmitDroppedAC[ac];
         kfree_skb(skb);
         return NETDEV_TX_OK;
      }
   }

   dev->trans_start = jiffies;

   return NETDEV_TX_OK;
}
int iw_set_scan(struct net_device *dev, struct iw_request_info *info,
                 union iwreq_data *wrqu, char *extra)
{
   hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ;
   hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
   hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
   tCsrScanRequest scanRequest;
   v_U32_t scanId = 0;
   eHalStatus status = eHAL_STATUS_SUCCESS;
   struct iw_scan_req *scanReq = (struct iw_scan_req *)extra;

   ENTER();

   VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: enter !!!",__func__);

#ifdef WLAN_BTAMP_FEATURE
   
   if( VOS_TRUE == WLANBAP_AmpSessionOn() ) 
   {
       VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: No scanning when AMP is on",__func__);
       return eHAL_STATUS_SUCCESS;
   }
#endif
   if(pHddCtx->scan_info.mScanPending == TRUE)
   {
       VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:mScanPending is TRUE !!!",__func__);
       return eHAL_STATUS_SUCCESS;
   }

   if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) {
      VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
      return eHAL_STATUS_SUCCESS;
   }
   vos_mem_zero( &scanRequest, sizeof(scanRequest));

   if (NULL != wrqu->data.pointer)
   {
       
       if ((IW_SCAN_TYPE_ACTIVE ==  scanReq->scan_type) || (eSIR_ACTIVE_SCAN == pHddCtx->scan_info.scan_mode))
       {
           scanRequest.scanType = eSIR_ACTIVE_SCAN;
       }
       else
       {
           scanRequest.scanType = eSIR_PASSIVE_SCAN;
       }

       
       vos_mem_copy(scanRequest.bssid,
                       &scanReq->bssid.sa_data, sizeof(scanRequest.bssid) );

      if (wrqu->data.flags & IW_SCAN_THIS_ESSID)  {

          if(scanReq->essid_len) {
              scanRequest.SSIDs.numOfSSIDs = 1;
              scanRequest.SSIDs.SSIDList =( tCsrSSIDInfo *)vos_mem_malloc(sizeof(tCsrSSIDInfo));
              if(scanRequest.SSIDs.SSIDList) {
                 scanRequest.SSIDs.SSIDList->SSID.length =             scanReq->essid_len;
                 vos_mem_copy(scanRequest.SSIDs.SSIDList->  SSID.ssId,scanReq->essid,scanReq->essid_len);
              }
              else
              {
                scanRequest.SSIDs.numOfSSIDs = 0;
                VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Unable to allocate memory",__func__);
                VOS_ASSERT(0);
              }
          }
      }

       
       scanRequest.minChnTime = scanReq->min_channel_time;
       scanRequest.maxChnTime = scanReq->max_channel_time;

   }
   else
   {
       if(pHddCtx->scan_info.scan_mode == eSIR_ACTIVE_SCAN) {
           
           scanRequest.scanType = eSIR_ACTIVE_SCAN;
       } else {
           scanRequest.scanType = eSIR_PASSIVE_SCAN;
       }

       vos_mem_set( scanRequest.bssid, sizeof( tCsrBssid ), 0xff );

       
       scanRequest.minChnTime = 0;
       scanRequest.maxChnTime = 0;
   }

   
   scanRequest.BSSType = eCSR_BSS_TYPE_ANY;

   
   scanRequest.ChannelInfo.numOfChannels = 0;

   scanRequest.ChannelInfo.ChannelList = NULL;

   
   scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;

   
   if (0 != pwextBuf->genIE.length)
   {
       memset( &pHddCtx->scan_info.scanAddIE, 0, sizeof(pHddCtx->scan_info.scanAddIE) );
       memcpy( pHddCtx->scan_info.scanAddIE.addIEdata, pwextBuf->genIE.addIEdata, 
           pwextBuf->genIE.length );
       pHddCtx->scan_info.scanAddIE.length = pwextBuf->genIE.length;
      
       if (SIR_MAC_MAX_IE_LENGTH  >=  pwextBuf->genIE.length)
       {
           memcpy( pwextBuf->roamProfile.addIEScan,
                       pHddCtx->scan_info.scanAddIE.addIEdata,
                       pHddCtx->scan_info.scanAddIE.length);
           pwextBuf->roamProfile.nAddIEScanLength =
                                pHddCtx->scan_info.scanAddIE.length;
       }
       else
       {
           VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                     "Invalid ScanIE, Length is %d", pwextBuf->genIE.length);
       }
       
       memset( &pwextBuf->genIE, 0, sizeof(pwextBuf->genIE) );
   }

   
   if (pHddCtx->scan_info.scanAddIE.addIEdata && 
       pHddCtx->scan_info.scanAddIE.length)
   { 
       scanRequest.uIEFieldLen = pHddCtx->scan_info.scanAddIE.length;
       scanRequest.pIEField = pHddCtx->scan_info.scanAddIE.addIEdata;
   }

   status = sme_ScanRequest( (WLAN_HDD_GET_CTX(pAdapter))->hHal, pAdapter->sessionId,&scanRequest, &scanId, &hdd_ScanRequestCallback, dev ); 
   if (!HAL_STATUS_SUCCESS(status))
   {
       VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:sme_ScanRequest  fail %d!!!",__func__, status);
       goto error;
   }

   pHddCtx->scan_info.mScanPending = TRUE;

   pHddCtx->scan_info.scanId = scanId;

error:
   if ((wrqu->data.flags & IW_SCAN_THIS_ESSID) && (scanReq->essid_len))
       vos_mem_free(scanRequest.SSIDs.SSIDList);

   EXIT();

   VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit !!!",__func__);
   return status;
}
int iw_set_cscan(struct net_device *dev, struct iw_request_info *info,
                 union iwreq_data *wrqu, char *extra)
{
    hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ;
    hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
    hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
    tCsrScanRequest scanRequest;
    v_U32_t scanId = 0;
    eHalStatus status = eHAL_STATUS_SUCCESS;
    v_U8_t channelIdx;

    ENTER();
    VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: enter !!!",__func__);

#ifdef WLAN_BTAMP_FEATURE
    //Scan not supported when AMP traffic is on.
    if( VOS_TRUE == WLANBAP_AmpSessionOn() )
    {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: No scanning when AMP is on",__func__);
        return eHAL_STATUS_SUCCESS;
    }
#endif

    if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
    {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
        return eHAL_STATUS_SUCCESS;
    }

    vos_mem_zero( &scanRequest, sizeof(scanRequest));
    if (NULL != wrqu->data.pointer)
    {
        char *str_ptr = NULL;
        tCsrSSIDInfo *SsidInfo = NULL;
        int num_ssid = 0;
        int i, j, ssid_start;
        hdd_scan_pending_option_e scanPendingOption = WEXT_SCAN_PENDING_GIVEUP;

        str_ptr = extra;

        i = WEXT_CSCAN_HEADER_SIZE;

        if( WEXT_CSCAN_PENDING_SECTION == str_ptr[i] )
        {
            scanPendingOption = (hdd_scan_pending_option_e)str_ptr[++i];
            ++i;
        }
        pHddCtx->scan_info.scan_pending_option = scanPendingOption;

        if(pHddCtx->scan_info.mScanPending == TRUE)
        {
            hddLog(LOG1,"%s: mScanPending is TRUE",__func__);
            /* If any scan is pending, just giveup this scan request */
            if(WEXT_SCAN_PENDING_GIVEUP == scanPendingOption)
            {
                pHddCtx->scan_info.waitScanResult = FALSE;
                return eHAL_STATUS_SUCCESS; 
            }
            /* If any scan pending, wait till finish current scan,
               and try this scan request when previous scan finish */
            else if(WEXT_SCAN_PENDING_DELAY == scanPendingOption)
            {
                pHddCtx->scan_info.waitScanResult = TRUE;
                vos_event_reset(&pHddCtx->scan_info.scan_finished_event);
                if(vos_wait_single_event(&pHddCtx->scan_info.scan_finished_event,
                                          WEXT_CSCAN_SCAN_DONE_WAIT_TIME))
                {
                    hddLog(LOG1,"%s: Previous SCAN does not finished on time",__func__);
                    return eHAL_STATUS_SUCCESS; 
                }
            }
            /* Piggyback previous scan result */
            else if(WEXT_SCAN_PENDING_PIGGYBACK == scanPendingOption)
            {
                pHddCtx->scan_info.waitScanResult = TRUE;
                return eHAL_STATUS_SUCCESS; 
            }
        }
        pHddCtx->scan_info.waitScanResult = FALSE;

        /* Check for scan IE */
        while( WEXT_CSCAN_SSID_SECTION == str_ptr[i] ) 
        {
            /* ssid_len */
            if(str_ptr[++i] != WEXT_CSCAN_CHANNEL_SECTION) 
            {
                /* total number of ssid's */
                num_ssid++;
                /* increment length filed */
                i += str_ptr[i] + 1;
            }  
            /* i should be saved and it will be pointing to 'C' */
        }

        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: numSsid %d !!!",__func__, num_ssid);
        if( num_ssid ) 
        {
            /* To be fixed in SME and PE: override the number of ssid with 1,
            * as SME and PE does not handle multiple SSID in scan request
            * */
          scanRequest.SSIDs.numOfSSIDs = num_ssid;
          /* Allocate num_ssid tCsrSSIDInfo structure */
          SsidInfo = scanRequest.SSIDs.SSIDList =( tCsrSSIDInfo *)vos_mem_malloc(num_ssid*sizeof(tCsrSSIDInfo));
          if(NULL == scanRequest.SSIDs.SSIDList) {
             hddLog(VOS_TRACE_LEVEL_ERROR, "memory alloc failed SSIDInfo buffer");
             return -ENOMEM;
          }

          /* copy all the ssid's and their length */
          ssid_start = WEXT_CSCAN_HEADER_SIZE + 1;/* skipping 'S' */
          for(j = 0; j < num_ssid; j++) {
             if( SIR_MAC_MAX_SSID_LENGTH < str_ptr[ssid_start]){
                scanRequest.SSIDs.numOfSSIDs -= 1;
             } else{
                /* get the ssid length */
                SsidInfo->SSID.length = str_ptr[ssid_start++];
                vos_mem_copy(SsidInfo->SSID.ssId, &str_ptr[ssid_start], SsidInfo->SSID.length);
                hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d:  %s", j, SsidInfo->SSID.ssId);
             }
                /* skipping length */
             ssid_start += str_ptr[ssid_start - 1] + 1;
             /* Store next ssid info */
             SsidInfo++;
          }
       }

        /* Check for Channel IE */
        if ( WEXT_CSCAN_CHANNEL_SECTION == str_ptr[i]) 
        {
            if( str_ptr[++i] == 0 ) 
            {
                scanRequest.ChannelInfo.numOfChannels = 0;
                scanRequest.ChannelInfo.ChannelList = NULL;
                i++;
            }
            else {

                /* increment the counter */
                scanRequest.ChannelInfo.numOfChannels = str_ptr[i++];
                /* store temp channel list */
                /* SME expects 1 byte channel content */
                scanRequest.ChannelInfo.ChannelList = vos_mem_malloc(scanRequest.ChannelInfo.numOfChannels * sizeof(v_U8_t));
                if(NULL == scanRequest.ChannelInfo.ChannelList) 
                {
                    hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "memory alloc failed for channel list creation");
                    status = -ENOMEM;
                    goto exit_point;
                }

                for(channelIdx = 0; channelIdx < scanRequest.ChannelInfo.numOfChannels; channelIdx++)
                {
                   /* SCAN request from upper layer has 2 bytes channel */
                   scanRequest.ChannelInfo.ChannelList[channelIdx] = (v_U8_t)str_ptr[i];
                   i += sizeof(v_U16_t);
                }
            }
        }

        /* Set default */
        scanRequest.scanType = eSIR_ACTIVE_SCAN;
        scanRequest.minChnTime = 0;
        scanRequest.maxChnTime = 0;

        /* Now i is pointing to passive dwell dwell time */
        /* 'P',min dwell time, max dwell time */
        /* next two offsets contain min and max channel time */
        if( WEXT_CSCAN_PASV_DWELL_SECTION == (str_ptr[i]) ) 
        {
            /* No SSID specified, num_ssid == 0, then start paasive scan */
            if (!num_ssid || (eSIR_PASSIVE_SCAN == pHddCtx->scan_info.scan_mode))
            {
                scanRequest.scanType = eSIR_PASSIVE_SCAN;
                scanRequest.minChnTime = (v_U8_t)str_ptr[++i];//scanReq->min_channel_time;
                scanRequest.maxChnTime = (v_U8_t)str_ptr[++i];//scanReq->max_channel_time;
                i++;
            }
            else
            {
                i += 3;
            }    
        }   

        /* H indicates active channel time */
        if( WEXT_CSCAN_HOME_DWELL_SECTION == (str_ptr[i]) ) 
        {
            if (num_ssid || (eSIR_ACTIVE_SCAN == pHddCtx->scan_info.scan_mode))
            {
                scanRequest.scanType = eSIR_ACTIVE_SCAN;
                scanRequest.minChnTime = str_ptr[++i];//scanReq->min_channel_time;
                scanRequest.maxChnTime = str_ptr[++i];//scanReq->max_channel_time;
                i++;
            }
            else
            {
                i +=3;
            }
        }
        scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
        /* set requestType to full scan */
        scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
        pHddCtx->scan_info.mScanPending = TRUE;

        /* if previous genIE is not NULL, update ScanIE */
        if(0 != pwextBuf->genIE.length)
        {
            memset( &pHddCtx->scan_info.scanAddIE, 0, sizeof(pHddCtx->scan_info.scanAddIE) );
            memcpy( pHddCtx->scan_info.scanAddIE.addIEdata, pwextBuf->genIE.addIEdata, 
                pwextBuf->genIE.length );
            pHddCtx->scan_info.scanAddIE.length = pwextBuf->genIE.length;

            pwextBuf->roamProfile.pAddIEScan = pHddCtx->scan_info.scanAddIE.addIEdata;
            pwextBuf->roamProfile.nAddIEScanLength = pHddCtx->scan_info.scanAddIE.length;

            /* clear previous genIE after use it */
            memset( &pwextBuf->genIE, 0, sizeof(pwextBuf->genIE) );
        }

        /* push addIEScan in scanRequset if exist */
        if (pHddCtx->scan_info.scanAddIE.addIEdata && 
            pHddCtx->scan_info.scanAddIE.length)
        {
            scanRequest.uIEFieldLen = pHddCtx->scan_info.scanAddIE.length;
            scanRequest.pIEField = pHddCtx->scan_info.scanAddIE.addIEdata;
        }

        status = sme_ScanRequest( (WLAN_HDD_GET_CTX(pAdapter))->hHal, 
            pAdapter->sessionId,&scanRequest, &scanId, &hdd_ScanRequestCallback, dev ); 
        if( !HAL_STATUS_SUCCESS(status) )
        {
            VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s: SME scan fail status %d !!!",__func__, status);
            pHddCtx->scan_info.mScanPending = FALSE;
            status = -EINVAL;
            goto exit_point;
        }

        pHddCtx->scan_info.scanId = scanId;

    } //end of data->pointer
    else {
        status = -1;
    }

exit_point:

    /* free ssidlist */
    if (scanRequest.SSIDs.SSIDList) 
    {
        vos_mem_free(scanRequest.SSIDs.SSIDList);
    }
    /* free the channel list */
    if(scanRequest.ChannelInfo.ChannelList)
    {
        vos_mem_free((void*)scanRequest.ChannelInfo.ChannelList);
    }

    EXIT();
    VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit !!!",__func__);
    return status;
}
Example #19
0
int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev,
                     struct ieee80211_channel *chan,
                     enum nl80211_channel_type channel_type,
                     bool channel_type_valid,
                     const u8 *buf, size_t len, u64 *cookie )
#endif //LINUX_VERSION_CODE
{
    hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
    hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
    tANI_U16 extendedWait = 0;
    tANI_U8 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]);
    tANI_U8 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]);
    tActionFrmType actionFrmType;
    bool noack = 0;

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
    hdd_adapter_t *goAdapter;
#endif

#ifdef WLAN_FEATURE_P2P_DEBUG
    if ((type == SIR_MAC_MGMT_FRAME) &&
            (subType == SIR_MAC_MGMT_ACTION) &&
            (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
    {
        actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
        if(actionFrmType > MAX_P2P_ACTION_FRAME_TYPE)
        {
            hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] ---> OTA",
                                   actionFrmType);
        }
        else
        {
            hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s ---> OTA",
            p2p_action_frame_type[actionFrmType]);
            if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
                (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
            {
                 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
                 hddLog(LOGE,"[P2P State]Inactive state to "
                            "GO negotation progress state");
            }
            else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
                (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
            {
                 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
                 hddLog(LOGE,"[P2P State]GO nego progress to GO nego"
                             " completed state");
            }
        }
    }
#endif

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
    noack = dont_wait_for_ack;
#endif

    //If the wait is coming as 0 with off channel set
    //then set the wait to 200 ms
    if (offchan && !wait)
        wait = ACTION_FRAME_DEFAULT_WAIT;

    hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
                            __func__,pAdapter->device_mode);

    //Call sme API to send out a action frame.
    // OR can we send it directly through data path??
    // After tx completion send tx status back.
    if ( ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) ||
         ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
       )
    {
        if (type == SIR_MAC_MGMT_FRAME)
        {
            if (subType == SIR_MAC_MGMT_PROBE_RSP)
            {
                /* Drop Probe response recieved from supplicant, as for GO and 
                   SAP PE itself sends probe response
                   */ 
                goto err_rem_channel;
            }
            else if ((subType == SIR_MAC_MGMT_DISASSOC) ||
                    (subType == SIR_MAC_MGMT_DEAUTH))
            {
                /* During EAP failure or P2P Group Remove supplicant
                 * is sending del_station command to driver. From
                 * del_station function, Driver will send deauth frame to
                 * p2p client. No need to send disassoc frame from here.
                 * so Drop the frame here and send tx indication back to
                 * supplicant.
                 */
                tANI_U8 dstMac[ETH_ALEN] = {0};
                memcpy(&dstMac, &buf[WLAN_HDD_80211_FRM_DA_OFFSET], ETH_ALEN);
                hddLog(VOS_TRACE_LEVEL_INFO,
                        "%s: Deauth/Disassoc received for STA:"
                        "%02x:%02x:%02x:%02x:%02x:%02x",
                        __func__,
                        dstMac[0], dstMac[1], dstMac[2],
                        dstMac[3], dstMac[4], dstMac[5]);
                goto err_rem_channel;
            }
        }
    }

    if( NULL != cfgState->buf )
        return -EBUSY;

    hddLog( LOG1, "Action frame tx request");

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
    goAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_P2P_GO );

    //If GO adapter exists and operating on same frequency
    //then we will not request remain on channel
    if( goAdapter && ( ieee80211_frequency_to_channel(chan->center_freq)
                         == goAdapter->sessionCtx.ap.operatingChannel ) )
    {
        goto send_frame;
    }
#endif

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
    if( offchan && wait)
    {
        int status;

        // In case of P2P Client mode if we are already
        // on the same channel then send the frame directly

        if((cfgState->remain_on_chan_ctx != NULL) &&
           (cfgState->current_freq == chan->center_freq)
          )
        {
            hddLog(LOG1,"action frame: extending the wait time\n");
            extendedWait = (tANI_U16)wait;
            goto send_frame;
        }

        INIT_COMPLETION(pAdapter->offchannel_tx_event);

        status = wlan_hdd_request_remain_on_channel(wiphy, dev,
                                        chan, channel_type, wait, cookie,
                                        OFF_CHANNEL_ACTION_TX);

        if(0 != status)
        {
            if( (-EBUSY == status) &&
                (cfgState->current_freq == chan->center_freq) )
            {
                goto send_frame;
            }
            goto err_rem_channel;
        }

        /* Wait for driver to be ready on the requested channel */
        status = wait_for_completion_interruptible_timeout(
                     &pAdapter->offchannel_tx_event,
                     msecs_to_jiffies(WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX));
        if(!status)
        {
            hddLog( LOGE, "Not able to complete remain on channel request"
                          " within timeout period");
            goto err_rem_channel;
        }
    }
    else if ( offchan )
    {
        /* Check before sending action frame
           whether we already remain on channel */
        if(NULL == cfgState->remain_on_chan_ctx)
        {
            goto err_rem_channel;
        }
    }
    send_frame:
#endif

    if(!noack)
    {
        cfgState->buf = vos_mem_malloc( len ); //buf;
        if( cfgState->buf == NULL )
            return -ENOMEM;

        cfgState->len = len;

        vos_mem_copy( cfgState->buf, buf, len);

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
        if( cfgState->remain_on_chan_ctx )
        {
            cfgState->action_cookie = cfgState->remain_on_chan_ctx->cookie;
            *cookie = cfgState->action_cookie;
        }
        else
        {
#endif
            *cookie = (tANI_U32) cfgState->buf;
            cfgState->action_cookie = *cookie;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
        }
#endif
    } 

    if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
         (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
         ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
       )
    {
        tANI_U8 sessionId = pAdapter->sessionId;         
        
        if ((type == SIR_MAC_MGMT_FRAME) && 
                (subType == SIR_MAC_MGMT_ACTION) &&
                (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
        {
            actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
            hddLog(LOG1, "Tx Action Frame %u \n", actionFrmType);
            if (actionFrmType == WLAN_HDD_PROV_DIS_REQ)
            {
                cfgState->actionFrmState = HDD_PD_REQ_ACK_PENDING;
                hddLog(LOG1, "%s: HDD_PD_REQ_ACK_PENDING \n", __func__);
            }
            else if (actionFrmType == WLAN_HDD_GO_NEG_REQ)
            {
                cfgState->actionFrmState = HDD_GO_NEG_REQ_ACK_PENDING;
                hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING \n", __func__);
            }
        }

        if (eHAL_STATUS_SUCCESS !=
               sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter),
                               sessionId, buf, len, extendedWait, noack))
        {
            VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                     "%s: sme_sendAction returned fail", __func__);
            goto err;
        }
    }
    else if( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
              ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
            )
     {
        if( VOS_STATUS_SUCCESS !=
             WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
                                  buf, len, 0 ) )
        {
            VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                    "%s: WLANSAP_SendAction returned fail", __func__);
            goto err;
        }
    }

    return 0;
err:
    if(!noack)
    {
       hdd_sendActionCnf( pAdapter, FALSE );
    }
    return 0;
err_rem_channel:
    *cookie = (tANI_U32)cfgState;
    cfg80211_mgmt_tx_status( pAdapter->dev, *cookie, buf, len, FALSE, GFP_KERNEL );
    return 0;
}
int iw_get_scan(struct net_device *dev,
                         struct iw_request_info *info,
                         union iwreq_data *wrqu, char *extra)
{
   hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ;
   hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
   tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
   tCsrScanResultInfo *pScanResult;
   eHalStatus status = eHAL_STATUS_SUCCESS;
   hdd_scan_info_t scanInfo;
   tScanResultHandle pResult;
   int i = 0;

   VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: enter buffer length %d!!!",
       __func__, (wrqu->data.length)?wrqu->data.length:IW_SCAN_MAX_DATA);
   ENTER();

   if (TRUE == pHddCtx->scan_info.mScanPending)
   {
       VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:mScanPending is TRUE !!!",__func__);
       return -EAGAIN;
   }

   if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) {
      VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
      return -EAGAIN;
   }

   scanInfo.dev = dev;
   scanInfo.start = extra;
   scanInfo.info = info;

   if (0 == wrqu->data.length)
   {
       scanInfo.end = extra + IW_SCAN_MAX_DATA;
   }
   else
   {
       scanInfo.end = extra + wrqu->data.length;
   }

   status = sme_ScanGetResult(hHal,pAdapter->sessionId,NULL,&pResult);

   if (NULL == pResult)
   {
       
       hddLog(LOG1,"iw_get_scan: NULL Scan Result ");
       return 0;
   }

   pScanResult = sme_ScanResultGetFirst(hHal, pResult);

   while (pScanResult)
   {
       status = hdd_IndicateScanResult(&scanInfo, pScanResult);
       if (0 != status)
       {
           break;
       }
       i++;
       pScanResult = sme_ScanResultGetNext(hHal, pResult);
   }

   sme_ScanResultPurge(hHal, pResult);

   EXIT();
   VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit total %d BSS reported !!!",__func__, i);
   return status;
}
Example #21
0
/**
 * __wcnss_wowenable_write() - write wow enable
 * @file: file pointer
 * @buf: buffer
 * @count: count
 * @ppos: position pointer
 *
 * Return: 0 on success, error number otherwise
 */
static ssize_t __wcnss_wowenable_write(struct file *file,
               const char __user *buf, size_t count, loff_t *ppos)
{

    hdd_adapter_t *pAdapter;
    hdd_context_t *hdd_ctx;
    char cmd[MAX_USER_COMMAND_SIZE_WOWL_ENABLE + 1];
    char *sptr, *token;
    v_U8_t wow_enable = 0;
    v_U8_t wow_mp = 0;
    v_U8_t wow_pbm = 0;
    int ret;

    ENTER();

    pAdapter = (hdd_adapter_t *)file->private_data;
    if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
    {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
                  "%s: Invalid adapter or adapter has invalid magic.",
                  __func__);

        return -EINVAL;
    }

    hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
    ret = wlan_hdd_validate_context(hdd_ctx);
    if (0 != ret)
        return ret;

    if (!sme_IsFeatureSupportedByFW(WOW))
    {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                  "%s: Wake-on-Wireless feature is not supported "
                  "in firmware!", __func__);

        return -EINVAL;
    }

    if (count > MAX_USER_COMMAND_SIZE_WOWL_ENABLE)
    {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                  "%s: Command length is larger than %d bytes.",
                  __func__, MAX_USER_COMMAND_SIZE_WOWL_ENABLE);

        return -EINVAL;
    }

    /* Get command from user */
    if (copy_from_user(cmd, buf, count))
        return -EFAULT;
    cmd[count] = '\0';
    sptr = cmd;

    /* Get enable or disable wow */
    token = strsep(&sptr, " ");
    if (!token)
        return -EINVAL;
    if (kstrtou8(token, 0, &wow_enable))
        return -EINVAL;

    /* Disable wow */
    if (!wow_enable) {
        if (!hdd_exit_wowl(pAdapter))
        {
          VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                    "%s: hdd_exit_wowl failed!", __func__);

          return -EFAULT;
        }

        return count;
    }

    /* Get enable or disable magic packet mode */
    token = strsep(&sptr, " ");
    if (!token)
        return -EINVAL;
    if (kstrtou8(token, 0, &wow_mp))
        return -EINVAL;
    if (wow_mp > 1)
        wow_mp = 1;

    /* Get enable or disable pattern byte matching mode */
    token = strsep(&sptr, " ");
    if (!token)
        return -EINVAL;
    if (kstrtou8(token, 0, &wow_pbm))
        return -EINVAL;
    if (wow_pbm > 1)
        wow_pbm = 1;

    if (!hdd_enter_wowl(pAdapter, wow_mp, wow_pbm))
    {
      VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                "%s: hdd_enter_wowl failed!", __func__);

      return -EFAULT;
    }
    EXIT();
    return count;
}
Example #22
0
void hdd_mon_tx_mgmt_pkt(hdd_adapter_t* pAdapter)
{
   hdd_cfg80211_state_t *cfgState;
   struct sk_buff* skb;
   hdd_adapter_t* pMonAdapter = NULL;
   struct ieee80211_hdr *hdr;

   if (pAdapter == NULL )
   {
      VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
       "%s: pAdapter is NULL", __func__);
      return;
   }

   pMonAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );

   cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );

   if( NULL != cfgState->buf )
   {
      VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
          "%s: Already one MGMT packet Tx going on", __func__);
      return;
   }

   skb = hdd_mon_tx_fetch_pkt(pMonAdapter);

   if (NULL == skb)
   {
      VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
       "%s: No Packet Pending", __func__);
      return;
   }

   cfgState->buf = vos_mem_malloc( skb->len ); //buf;
   if( cfgState->buf == NULL )
   {
      VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
          "%s: Failed to Allocate memory", __func__);
      goto fail;
   }

   cfgState->len = skb->len;

   vos_mem_copy( cfgState->buf, skb->data, skb->len);

   cfgState->skb = skb; //buf;
   cfgState->action_cookie = (tANI_U32)cfgState->buf;

   hdr = (struct ieee80211_hdr *)skb->data;
   if( (hdr->frame_control & HDD_FRAME_TYPE_MASK)
                                       == HDD_FRAME_TYPE_MGMT )
   {
       if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK)
                                       == HDD_FRAME_SUBTYPE_DEAUTH )
       {
          hdd_softap_sta_deauth( pAdapter, hdr->addr1 ); 
          goto mgmt_handled;
       }
       else if( (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK) 
                                      == HDD_FRAME_SUBTYPE_DISASSOC )
       {
          hdd_softap_sta_disassoc( pAdapter, hdr->addr1 ); 
          goto mgmt_handled;
       }
   }
   VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
      "%s: Sending action frame to SAP to TX, Len %d", __func__, skb->len);

   if (VOS_STATUS_SUCCESS != 
      WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
                           skb->data, skb->len, 0) )
   {
      VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
          "%s: WLANSAP_SendAction returned fail", __func__);
      hdd_sendActionCnf( pAdapter, FALSE );
   }
   return;

mgmt_handled:
   hdd_sendActionCnf( pAdapter, TRUE );
   return;
fail:
   kfree_skb(pAdapter->skb_to_tx);
   pAdapter->skb_to_tx = NULL;
   return;
}
int iw_set_cscan(struct net_device *dev, struct iw_request_info *info,
                 union iwreq_data *wrqu, char *extra)
{
    hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ;
    hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
    hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
    tCsrScanRequest scanRequest;
    v_U32_t scanId = 0;
    eHalStatus status = eHAL_STATUS_SUCCESS;
    v_U8_t channelIdx;

    ENTER();
    VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: enter !!!",__func__);

#ifdef WLAN_BTAMP_FEATURE
    
    if( VOS_TRUE == WLANBAP_AmpSessionOn() )
    {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: No scanning when AMP is on",__func__);
        return eHAL_STATUS_SUCCESS;
    }
#endif

    if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
    {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
        return eHAL_STATUS_SUCCESS;
    }

    vos_mem_zero( &scanRequest, sizeof(scanRequest));
    if (NULL != wrqu->data.pointer)
    {
        char *str_ptr = NULL;
        tCsrSSIDInfo *SsidInfo = NULL;
        int num_ssid = 0;
        int i, j, ssid_start;
        hdd_scan_pending_option_e scanPendingOption = WEXT_SCAN_PENDING_GIVEUP;

        str_ptr = extra;

        i = WEXT_CSCAN_HEADER_SIZE;

        if( WEXT_CSCAN_PENDING_SECTION == str_ptr[i] )
        {
            scanPendingOption = (hdd_scan_pending_option_e)str_ptr[++i];
            ++i;
        }
        pHddCtx->scan_info.scan_pending_option = scanPendingOption;

        if(pHddCtx->scan_info.mScanPending == TRUE)
        {
            hddLog(LOG1,"%s: mScanPending is TRUE",__func__);
            
            if(WEXT_SCAN_PENDING_GIVEUP == scanPendingOption)
            {
                pHddCtx->scan_info.waitScanResult = FALSE;
                return eHAL_STATUS_SUCCESS; 
            }
            else if(WEXT_SCAN_PENDING_DELAY == scanPendingOption)
            {
                pHddCtx->scan_info.waitScanResult = TRUE;
                vos_event_reset(&pHddCtx->scan_info.scan_finished_event);
                if(vos_wait_single_event(&pHddCtx->scan_info.scan_finished_event,
                                          WEXT_CSCAN_SCAN_DONE_WAIT_TIME))
                {
                    hddLog(LOG1,"%s: Previous SCAN does not finished on time",__func__);
                    return eHAL_STATUS_SUCCESS; 
                }
            }
            
            else if(WEXT_SCAN_PENDING_PIGGYBACK == scanPendingOption)
            {
                pHddCtx->scan_info.waitScanResult = TRUE;
                return eHAL_STATUS_SUCCESS; 
            }
        }
        pHddCtx->scan_info.waitScanResult = FALSE;

        
        while( WEXT_CSCAN_SSID_SECTION == str_ptr[i] ) 
        {
            
            if(str_ptr[++i] != WEXT_CSCAN_CHANNEL_SECTION) 
            {
                
                num_ssid++;
                
                i += str_ptr[i] + 1;
            }  
            
        }

        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: numSsid %d !!!",__func__, num_ssid);
        if( num_ssid ) 
        {
          scanRequest.SSIDs.numOfSSIDs = num_ssid;
          
          SsidInfo = scanRequest.SSIDs.SSIDList =( tCsrSSIDInfo *)vos_mem_malloc(num_ssid*sizeof(tCsrSSIDInfo));
          if(NULL == scanRequest.SSIDs.SSIDList) {
             hddLog(VOS_TRACE_LEVEL_ERROR, "memory alloc failed SSIDInfo buffer");
             return -ENOMEM;
          }

          
          ssid_start = WEXT_CSCAN_HEADER_SIZE + 1;
          for(j = 0; j < num_ssid; j++) {
             if( SIR_MAC_MAX_SSID_LENGTH < str_ptr[ssid_start]){
                scanRequest.SSIDs.numOfSSIDs -= 1;
             } else{
                
                SsidInfo->SSID.length = str_ptr[ssid_start++];
                vos_mem_copy(SsidInfo->SSID.ssId, &str_ptr[ssid_start], SsidInfo->SSID.length);
                hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "SSID number %d:  %s\n", j, SsidInfo->SSID.ssId);
             }
                
             ssid_start += str_ptr[ssid_start - 1] + 1;
             
             SsidInfo++;
          }
       }

        
        if ( WEXT_CSCAN_CHANNEL_SECTION == str_ptr[i]) 
        {
            if( str_ptr[++i] == 0 ) 
            {
                scanRequest.ChannelInfo.numOfChannels = 0;
                scanRequest.ChannelInfo.ChannelList = NULL;
                i++;
            }
            else {

                
                scanRequest.ChannelInfo.numOfChannels = str_ptr[i++];
                
                
                scanRequest.ChannelInfo.ChannelList = vos_mem_malloc(scanRequest.ChannelInfo.numOfChannels * sizeof(v_U8_t));
                if(NULL == scanRequest.ChannelInfo.ChannelList) 
                {
                    hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "memory alloc failed for channel list creation");
                    status = -ENOMEM;
                    goto exit_point;
                }

                for(channelIdx = 0; channelIdx < scanRequest.ChannelInfo.numOfChannels; channelIdx++)
                {
                   
                   scanRequest.ChannelInfo.ChannelList[channelIdx] = (v_U8_t)str_ptr[i];
                   i += sizeof(v_U16_t);
                }
            }
        }

        
        scanRequest.scanType = eSIR_ACTIVE_SCAN;
        scanRequest.minChnTime = 0;
        scanRequest.maxChnTime = 0;

        
        
        
        if( WEXT_CSCAN_PASV_DWELL_SECTION == (str_ptr[i]) ) 
        {
            
            if (!num_ssid || (eSIR_PASSIVE_SCAN == pHddCtx->scan_info.scan_mode))
            {
                scanRequest.scanType = eSIR_PASSIVE_SCAN;
                scanRequest.minChnTime = (v_U8_t)str_ptr[++i];
                scanRequest.maxChnTime = (v_U8_t)str_ptr[++i];
                i++;
            }
            else
            {
                i += 3;
            }    
        }   

        
        if( WEXT_CSCAN_HOME_DWELL_SECTION == (str_ptr[i]) ) 
        {
            if (num_ssid || (eSIR_ACTIVE_SCAN == pHddCtx->scan_info.scan_mode))
            {
                scanRequest.scanType = eSIR_ACTIVE_SCAN;
                scanRequest.minChnTime = str_ptr[++i];
                scanRequest.maxChnTime = str_ptr[++i];
                i++;
            }
            else
            {
                i +=3;
            }
        }
        scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
        
        scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
        pHddCtx->scan_info.mScanPending = TRUE;

        
        if(0 != pwextBuf->genIE.length)
        {
            memset( &pHddCtx->scan_info.scanAddIE, 0, sizeof(pHddCtx->scan_info.scanAddIE) );
            memcpy( pHddCtx->scan_info.scanAddIE.addIEdata, pwextBuf->genIE.addIEdata, 
                pwextBuf->genIE.length );
            pHddCtx->scan_info.scanAddIE.length = pwextBuf->genIE.length;
            if (SIR_MAC_MAX_IE_LENGTH  >=  pwextBuf->genIE.length)
            {
                memcpy( pwextBuf->roamProfile.addIEScan,
                           pHddCtx->scan_info.scanAddIE.addIEdata,
                           pHddCtx->scan_info.scanAddIE.length);
                pwextBuf->roamProfile.nAddIEScanLength =
                                  pHddCtx->scan_info.scanAddIE.length;
            }
            else
            {
                VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                         "Invalid ScanIE, Length is %d",
                          pwextBuf->genIE.length);
            }
            
            memset( &pwextBuf->genIE, 0, sizeof(pwextBuf->genIE) );
        }

        
        if (pHddCtx->scan_info.scanAddIE.addIEdata && 
            pHddCtx->scan_info.scanAddIE.length)
        {
            scanRequest.uIEFieldLen = pHddCtx->scan_info.scanAddIE.length;
            scanRequest.pIEField = pHddCtx->scan_info.scanAddIE.addIEdata;
        }

        status = sme_ScanRequest( (WLAN_HDD_GET_CTX(pAdapter))->hHal, 
            pAdapter->sessionId,&scanRequest, &scanId, &hdd_ScanRequestCallback, dev ); 
        if( !HAL_STATUS_SUCCESS(status) )
        {
            VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s: SME scan fail status %d !!!",__func__, status);
            pHddCtx->scan_info.mScanPending = FALSE;
            status = -EINVAL;
            goto exit_point;
        }

        pHddCtx->scan_info.scanId = scanId;

    } 
    else {
        status = -1;
    }

exit_point:

    
    if (scanRequest.SSIDs.SSIDList) 
    {
        vos_mem_free(scanRequest.SSIDs.SSIDList);
    }
    
    if(scanRequest.ChannelInfo.ChannelList)
    {
        vos_mem_free((void*)scanRequest.ChannelInfo.ChannelList);
    }

    EXIT();
    VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit !!!",__func__);
    return status;
}
static ssize_t wcnss_patterngen_write(struct file *file,
               const char __user *buf, size_t count, loff_t *ppos)
{
    hdd_adapter_t *pAdapter = (hdd_adapter_t *)file->private_data;
    hdd_context_t *pHddCtx;
    tSirAddPeriodicTxPtrn *addPeriodicTxPtrnParams;
    tSirDelPeriodicTxPtrn *delPeriodicTxPtrnParams;

    char *cmd, *sptr, *token;
    v_U8_t pattern_idx = 0;
    v_U8_t pattern_duration = 0;
    char *pattern_buf;
    v_U16_t pattern_len = 0;
    v_U16_t i = 0;

    if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
    {
        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
                   "%s: Invalid adapter or adapter has invalid magic.",
                   __func__);

        return -EINVAL;
    }

    pHddCtx = WLAN_HDD_GET_CTX(pAdapter);

    if (!sme_IsFeatureSupportedByFW(WLAN_PERIODIC_TX_PTRN))
    {
        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                   "%s: Periodic Tx Pattern Offload feature is not supported "
                   "in firmware!", __func__);

        return -EINVAL;
    }

    
    if (count < MAX_USER_COMMAND_SIZE_FRAME)
        cmd = vos_mem_malloc(count + 1);
    else
    {
        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                   "%s: Command length is larger than d% bytes.",
                   __func__, MAX_USER_COMMAND_SIZE_FRAME);

        return -EINVAL;
    }

    if (!cmd)
    {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                  "%s: Memory allocation for cmd failed!", __func__);

        return -EFAULT;
    }

    if (copy_from_user(cmd, buf, count))
    {
        vos_mem_free(cmd);
        return -EFAULT;
    }
    cmd[count] = '\0';
    sptr = cmd;

    
    token = strsep(&sptr, " ");
    if (!token)
        goto failure;
    if (kstrtou8(token, 0, &pattern_idx))
        goto failure;

    if (pattern_idx > (MAXNUM_PERIODIC_TX_PTRNS - 1))
    {
        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                   "%s: Pattern index %d is not in the range (0 ~ %d).",
                   __func__, pattern_idx, MAXNUM_PERIODIC_TX_PTRNS - 1);

        goto failure;
    }

    
    token = strsep(&sptr, " ");
    if (!token)
        goto failure;
    if (kstrtou8(token, 0, &pattern_duration))
        goto failure;

    
    if (!pattern_duration)
    {
        delPeriodicTxPtrnParams =
            vos_mem_malloc(sizeof(tSirDelPeriodicTxPtrn));
        if (!delPeriodicTxPtrnParams)
        {
            VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                      "%s: Memory allocation for delPeriodicTxPtrnParams "
                      "failed!", __func__);

            vos_mem_free(cmd);
            return -EFAULT;
        }

        delPeriodicTxPtrnParams->ucPatternIdBitmap = 1 << pattern_idx;
        vos_mem_copy(delPeriodicTxPtrnParams->macAddress,
                     pAdapter->macAddressCurrent.bytes, 6);

        
        if (eHAL_STATUS_SUCCESS != sme_DelPeriodicTxPtrn(pHddCtx->hHal,
                                                delPeriodicTxPtrnParams))
        {
            VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                       "%s: sme_DelPeriodicTxPtrn() failed!", __func__);

            vos_mem_free(delPeriodicTxPtrnParams);
            goto failure;
        }

        vos_mem_free(delPeriodicTxPtrnParams);
        vos_mem_free(cmd);
        return count;
    }

    
    if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
    {
        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                   "%s: Not in Connected state!", __func__);

        goto failure;
    }

    
    token = strsep(&sptr, " ");
    if (!token)
        goto failure;

    pattern_buf = token;
    pattern_buf[strlen(pattern_buf) - 1] = '\0';
    pattern_len = strlen(pattern_buf);

    
    if (pattern_len % 2)
    {
        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                   "%s: Malformed pattern!", __func__);

        goto failure;
    }
    else
        pattern_len >>= 1;

    if (pattern_len < 14 || pattern_len > PERIODIC_TX_PTRN_MAX_SIZE)
    {
        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                   "%s: Not an 802.3 frame!", __func__);

        goto failure;
    }

    addPeriodicTxPtrnParams = vos_mem_malloc(sizeof(tSirAddPeriodicTxPtrn));
    if (!addPeriodicTxPtrnParams)
    {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                  "%s: Memory allocation for addPeriodicTxPtrnParams "
                  "failed!", __func__);

        vos_mem_free(cmd);
        return -EFAULT;
    }

    addPeriodicTxPtrnParams->ucPtrnId = pattern_idx;
    addPeriodicTxPtrnParams->usPtrnIntervalMs = pattern_duration * 500;
    addPeriodicTxPtrnParams->ucPtrnSize = pattern_len;
    vos_mem_copy(addPeriodicTxPtrnParams->macAddress,
                 pAdapter->macAddressCurrent.bytes, 6);

    
    for(i = 0; i < addPeriodicTxPtrnParams->ucPtrnSize; i++)
    {
        addPeriodicTxPtrnParams->ucPattern[i] =
        (hdd_parse_hex(pattern_buf[0]) << 4) + hdd_parse_hex(pattern_buf[1]);

        
        pattern_buf += 2;
    }

    
    if (eHAL_STATUS_SUCCESS != sme_AddPeriodicTxPtrn(pHddCtx->hHal,
                                            addPeriodicTxPtrnParams))
    {
        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                   "%s: sme_AddPeriodicTxPtrn() failed!", __func__);

        vos_mem_free(addPeriodicTxPtrnParams);
        goto failure;
    }

    vos_mem_free(addPeriodicTxPtrnParams);
    vos_mem_free(cmd);
    return count;

failure:
    vos_mem_free(cmd);
    return -EINVAL;
}
Example #25
0
/**
 * __wcnss_wowpattern_write() - write wow pattern
 * @file: file pointer
 * @buf: buffer
 * @count: count
 * @ppos: position pointer
 *
 * Return: 0 on success, error number otherwise
 */
static ssize_t __wcnss_wowpattern_write(struct file *file,
               const char __user *buf, size_t count, loff_t *ppos)
{
    hdd_adapter_t *pAdapter = (hdd_adapter_t *)file->private_data;
    hdd_context_t *hdd_ctx;
    char cmd[MAX_USER_COMMAND_SIZE_WOWL_PATTERN + 1];
    char *sptr, *token;
    v_U8_t pattern_idx = 0;
    v_U8_t pattern_offset = 0;
    char *pattern_buf;
    char *pattern_mask;
    int ret;

    if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
    {
        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
                   "%s: Invalid adapter or adapter has invalid magic.",
                   __func__);

        return -EINVAL;
    }

    hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
    ret = wlan_hdd_validate_context(hdd_ctx);
    if (0 != ret)
        return ret;

    if (!sme_IsFeatureSupportedByFW(WOW))
    {
        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                   "%s: Wake-on-Wireless feature is not supported "
                   "in firmware!", __func__);

        return -EINVAL;
    }

    if (count > MAX_USER_COMMAND_SIZE_WOWL_PATTERN)
    {
        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                   "%s: Command length is larger than %d bytes.",
                   __func__, MAX_USER_COMMAND_SIZE_WOWL_PATTERN);

        return -EINVAL;
    }

    /* Get command from user */
    if (copy_from_user(cmd, buf, count))
        return -EFAULT;
    cmd[count] = '\0';
    sptr = cmd;

    /* Get pattern idx */
    token = strsep(&sptr, " ");
    if (!token)
        return -EINVAL;

    if (kstrtou8(token, 0, &pattern_idx))
        return -EINVAL;

    /* Get pattern offset */
    token = strsep(&sptr, " ");

    /* Delete pattern if no further argument */
    if (!token) {
        hdd_del_wowl_ptrn_debugfs(pAdapter, pattern_idx);

        return count;
    }

    if (kstrtou8(token, 0, &pattern_offset))
        return -EINVAL;

    /* Get pattern */
    token = strsep(&sptr, " ");
    if (!token)
        return -EINVAL;

    pattern_buf = token;

    /* Get pattern mask */
    token = strsep(&sptr, " ");
    if (!token)
        return -EINVAL;

    pattern_mask = token;
    pattern_mask[strlen(pattern_mask) - 1] = '\0';

    hdd_add_wowl_ptrn_debugfs(pAdapter, pattern_idx, pattern_offset,
                              pattern_buf, pattern_mask);
    EXIT();
    return count;
}