int wlan_queue_fw_log_pkt_for_app(vos_pkt_t *pPacket)
{
	unsigned long flags;
	vos_pkt_t *next_pkt;
	vos_pkt_t *free_pkt;
	VOS_STATUS status = VOS_STATUS_E_FAILURE;

	spin_lock_irqsave(&gwlan_logging.fw_log_pkt_lock, flags);
	if (gwlan_logging.fw_log_pkt_qcnt >= LOGGER_MAX_FW_LOG_PKT_Q_LEN) {
		status = vos_pkt_walk_packet_chain(
			gwlan_logging.fw_log_pkt_queue, &next_pkt, TRUE);
		/*both "success" and "empty" are acceptable results*/
		if (!((status == VOS_STATUS_SUCCESS) ||
				(status == VOS_STATUS_E_EMPTY))) {
			++gwlan_logging.fw_log_pkt_drop_cnt;
			spin_unlock_irqrestore(
				&gwlan_logging.fw_log_pkt_lock, flags);
			pr_err("%s: Failure walking packet chain", __func__);
			/*keep returning pkts to avoid low resource cond*/
			vos_pkt_return_packet(pPacket);
			return VOS_STATUS_E_FAILURE;
		}

		free_pkt = gwlan_logging.fw_log_pkt_queue;
		gwlan_logging.fw_log_pkt_queue = next_pkt;
		/*returning head of pkt queue. latest pkts are important*/
		--gwlan_logging.fw_log_pkt_qcnt;
		spin_unlock_irqrestore(&gwlan_logging.fw_log_pkt_lock,
					flags);
		vos_pkt_return_packet(free_pkt);
	} else {
		spin_unlock_irqrestore(&gwlan_logging.fw_log_pkt_lock,
					flags);
	}

	spin_lock_irqsave(&gwlan_logging.fw_log_pkt_lock, flags);

	if (gwlan_logging.fw_log_pkt_queue) {
		vos_pkt_chain_packet(gwlan_logging.fw_log_pkt_queue,
					pPacket, TRUE);
	} else {
		gwlan_logging.fw_log_pkt_queue = pPacket;
	}
	++gwlan_logging.fw_log_pkt_qcnt;

	spin_unlock_irqrestore(&gwlan_logging.fw_log_pkt_lock, flags);

	set_bit(LOGGER_FW_LOG_PKT_POST, &gwlan_logging.event_flag);
	wake_up_interruptible(&gwlan_logging.wait_queue);

	return VOS_STATUS_SUCCESS;
}
VOS_STATUS
WDA_DS_TxFrames
( 
  v_PVOID_t pvosGCtx 
)
{
  VOS_STATUS vosStatus;
  vos_pkt_t  *pTxMgmtChain = NULL;
  vos_pkt_t  *pTxDataChain = NULL;
  vos_pkt_t  *pTxPacket = NULL;
  v_BOOL_t   bUrgent;
  wpt_uint32  ucTxResReq;
  WDI_Status wdiStatus;
  tWDA_CbContext *wdaContext = NULL;
  v_U32_t     uMgmtAvailRes;
  v_U32_t     uDataAvailRes;
  WLANTL_TxCompCBType  pfnTxComp = NULL;
  v_U32_t     uTxFailCount = 0;

  wdaContext = (tWDA_CbContext *)vos_get_context(VOS_MODULE_ID_WDA, pvosGCtx);
  if ( NULL == wdaContext )
  {
    VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
               "WDA:Invalid wda context pointer from pvosGCtx on WDA_DS_TxFrames" );
    return VOS_STATUS_E_FAULT;
  }

  /*-------------------------------------------------------------------------
     Need to fetch separatelly for Mgmt and Data frames because TL is not
     aware of separate resource management at the lower levels 
  -------------------------------------------------------------------------*/
  /*Mgmt tx*/
  uMgmtAvailRes = WDI_GetAvailableResCount(wdaContext->pWdiContext, 
                                           WDI_MGMT_POOL_ID);
  
  ucTxResReq = WLANTL_GetFrames( pvosGCtx, 
                              &pTxMgmtChain, 
                               uMgmtAvailRes, 
                              (wdaContext->uTxFlowMask & WDA_HI_FLOW_MASK),
                              &bUrgent );

  // We need to initialize vsoStatus in case we don't enter the "while"
  // loop.  If we don't enter the loop, it means that there are no packets,
  // available, and that is considered success.  If we enter the loop,
  // vosStatus will be set appropriately inside the loop
  vosStatus = VOS_STATUS_SUCCESS;
      
  while ( NULL != pTxMgmtChain )
  {
    /* Walk the chain and unchain the packet */
    pTxPacket = pTxMgmtChain;
    vosStatus = vos_pkt_walk_packet_chain( pTxMgmtChain, &pTxMgmtChain, VOS_TRUE );

    if( (VOS_STATUS_SUCCESS != vosStatus) &&
        (VOS_STATUS_E_EMPTY != vosStatus) )
    {
      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
                 "WDA Walking packet chain returned status : %d", vosStatus );
      VOS_ASSERT( 0 );
      vosStatus = VOS_STATUS_E_FAILURE;
      break;
    }

    if ( VOS_STATUS_E_EMPTY == vosStatus )
    {
       vosStatus = VOS_STATUS_SUCCESS;
    }

    wdiStatus = WDI_DS_TxPacket( wdaContext->pWdiContext, 
                                 (wpt_packet*)pTxPacket, 
                                 0 /* more */ );
    if ( WDI_STATUS_SUCCESS != wdiStatus )
    {
      VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
                  "WDA : Pushing a packet to WDI failed." );
      if ( WDI_STATUS_E_NOT_ALLOWED != wdiStatus )
      {
        uTxFailCount++;
      }
      VOS_ASSERT( wdiStatus == WDI_STATUS_E_NOT_ALLOWED );
      //We need to free the packet here
      vos_pkt_get_user_data_ptr(pTxPacket, VOS_PKT_USER_DATA_ID_TL, (void **)&pfnTxComp);
      if(pfnTxComp)
      {
         pfnTxComp(pvosGCtx, pTxPacket, VOS_STATUS_E_FAILURE);
      }
    }

  };

  if ( uTxFailCount )
  {
    VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                 "WDA : Tx fail count for mgmt pkts: %d.", uTxFailCount);
    uTxFailCount = 0;
  }

  /*Data tx*/
  uDataAvailRes = WDI_GetAvailableResCount(wdaContext->pWdiContext, 
                                           WDI_DATA_POOL_ID);

  ucTxResReq = WLANTL_GetFrames( pvosGCtx, 
                              &pTxDataChain, 
                              /*WDA_DS_DXE_RES_COUNT*/ uDataAvailRes, 
                              (wdaContext->uTxFlowMask & WDA_LO_FLOW_MASK),
                              &bUrgent );

  // We need to initialize vsoStatus in case we don't enter the "while"
  // loop.  If we don't enter the loop, it means that there are no packets,
  // available, and that is considered success.  If we enter the loop,
  // vosStatus will be set appropriately inside the loop
  vosStatus = VOS_STATUS_SUCCESS;

  while ( NULL != pTxDataChain )
  {
    /* Walk the chain and unchain the packet */
    pTxPacket = pTxDataChain;
    vosStatus = vos_pkt_walk_packet_chain( pTxDataChain, &pTxDataChain, VOS_TRUE );

    if( (VOS_STATUS_SUCCESS != vosStatus) &&
        (VOS_STATUS_E_EMPTY != vosStatus) )
    {
      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
                 "WDA Walking packet chain returned status : %d", vosStatus );
      VOS_ASSERT( 0 );
      vosStatus = VOS_STATUS_E_FAILURE;
      break;
    }

    if ( VOS_STATUS_E_EMPTY == vosStatus )
    {
       vosStatus = VOS_STATUS_SUCCESS;
    }

    wdiStatus = WDI_DS_TxPacket( wdaContext->pWdiContext, 
                                 (wpt_packet*)pTxPacket, 
                                 0 /* more */ );
    if ( WDI_STATUS_SUCCESS != wdiStatus )
    {
      VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
                  "WDA : Pushing a packet to WDI failed." );
      if ( WDI_STATUS_E_NOT_ALLOWED != wdiStatus )
      {
        uTxFailCount++;
      }
      VOS_ASSERT( wdiStatus == WDI_STATUS_E_NOT_ALLOWED );
      //We need to free the packet here
      vos_pkt_get_user_data_ptr(pTxPacket, VOS_PKT_USER_DATA_ID_TL, (void **)&pfnTxComp);
      if(pfnTxComp)
      {
         pfnTxComp(pvosGCtx, pTxPacket, VOS_STATUS_E_FAILURE);
      }
    }

  };

  if ( uTxFailCount )
  {
    VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                 "WDA : Tx fail count for data pkts: %d.", uTxFailCount);
  }


  WDI_DS_TxComplete(wdaContext->pWdiContext, ucTxResReq);

  return vosStatus;
}
Beispiel #3
0
/**============================================================================
  @brief hdd_rx_packet_cbk() - Receive callback registered with TL.
  TL will call this to notify the HDD when one or more packets were
  received for a registered STA.

  @param vosContext      : [in] pointer to VOS context  
  @param pVosPacketChain : [in] pointer to VOS packet chain
  @param staId           : [in] Station Id
  @param pRxMetaInfo     : [in] pointer to meta info for the received pkt(s) 

  @return                : VOS_STATUS_E_FAILURE if any errors encountered, 
                         : VOS_STATUS_SUCCESS otherwise
  ===========================================================================*/
VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext, 
                              vos_pkt_t *pVosPacketChain,
                              v_U8_t staId,
                              WLANTL_RxMetaInfoType* pRxMetaInfo )
{
   hdd_adapter_t *pAdapter = NULL;
   hdd_context_t *pHddCtx = NULL;
   VOS_STATUS status = VOS_STATUS_E_FAILURE;
   int rxstat;
   struct sk_buff *skb = NULL;
   vos_pkt_t* pVosPacket;
   vos_pkt_t* pNextVosPacket;

   //Sanity check on inputs
   if ( ( NULL == vosContext ) || 
        ( NULL == pVosPacketChain ) ||
        ( NULL == pRxMetaInfo ) )
   {
      VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Null params being passed", __FUNCTION__);
      return VOS_STATUS_E_FAILURE;
   }

   pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
   if ( NULL == pHddCtx )
   {
      VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __FUNCTION__);
      return VOS_STATUS_E_FAILURE;
   }

   pAdapter = pHddCtx->sta_to_adapter[staId];
   if( NULL == pAdapter )
   {
      VOS_ASSERT(0);
      return VOS_STATUS_E_FAILURE;
   }

   ++pAdapter->hdd_stats.hddTxRxStats.rxChains;

   // walk the chain until all are processed
   pVosPacket = pVosPacketChain;
   do
   {
      // get the pointer to the next packet in the chain
      // (but don't unlink the packet since we free the entire chain later)
      status = vos_pkt_walk_packet_chain( pVosPacket, &pNextVosPacket, VOS_FALSE);

      // both "success" and "empty" are acceptable results
      if (!((status == VOS_STATUS_SUCCESS) || (status == VOS_STATUS_E_EMPTY)))
      {
         ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
         VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Failure walking packet chain", __FUNCTION__);
         return VOS_STATUS_E_FAILURE;
      }

      // Extract the OS packet (skb).
      // Tell VOS to detach the OS packet from the VOS packet
      status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_TRUE );
      if(!VOS_IS_STATUS_SUCCESS( status ))
      {
         ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
         VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Failure extracting skb from vos pkt", __FUNCTION__);
         return VOS_STATUS_E_FAILURE;
      }

      if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
      {
         VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
           "Magic cookie(%x) for adapter sanity verification is invalid", pAdapter->magic);
         return eHAL_STATUS_FAILURE;
      }

      skb->dev = pAdapter->dev;
      skb->protocol = eth_type_trans(skb, skb->dev);
      skb->ip_summed = CHECKSUM_NONE;
      ++pAdapter->hdd_stats.hddTxRxStats.rxPackets;
      ++pAdapter->stats.rx_packets;
      pAdapter->stats.rx_bytes += skb->len;
#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
      wake_lock_timeout(&pHddCtx->rx_wake_lock, HDD_WAKE_LOCK_DURATION);
#endif
      rxstat = netif_rx_ni(skb);
      if (NET_RX_SUCCESS == rxstat)
      {
         ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
      }
      else
      {
         ++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
      }
      // now process the next packet in the chain
      pVosPacket = pNextVosPacket;

   } while (pVosPacket);

   //Return the entire VOS packet chain to the resource pool
   status = vos_pkt_return_packet( pVosPacketChain );
   if(!VOS_IS_STATUS_SUCCESS( status ))
   {
      VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: Failure returning vos pkt", __FUNCTION__);
   }
   
   pAdapter->dev->last_rx = jiffies;

   return status;   
}
static int send_data_mgmt_log_pkt_to_user(void)
{
	int ret = -1;
	int extra_header_len, nl_payload_len;
	struct sk_buff *skb = NULL;
	static int nlmsg_seq;
	vos_pkt_t *current_pkt;
	vos_pkt_t *next_pkt;
	VOS_STATUS status = VOS_STATUS_E_FAILURE;
	unsigned long flags;

	tAniNlLogHdr msg_header;

	do {
		spin_lock_irqsave(&gwlan_logging.data_mgmt_pkt_lock, flags);

		if (!gwlan_logging.data_mgmt_pkt_queue) {
			spin_unlock_irqrestore(
				&gwlan_logging.data_mgmt_pkt_lock, flags);
			return -EIO;
		}

		/* pick first pkt from queued chain */
		current_pkt = gwlan_logging.data_mgmt_pkt_queue;

		/* get the pointer to the next packet in the chain */
		status = vos_pkt_walk_packet_chain(current_pkt, &next_pkt,
							TRUE);

		/* both "success" and "empty" are acceptable results */
		if (!((status == VOS_STATUS_SUCCESS) ||
					(status == VOS_STATUS_E_EMPTY))) {
			++gwlan_logging.pkt_drop_cnt;
			spin_unlock_irqrestore(
				&gwlan_logging.data_mgmt_pkt_lock, flags);
			pr_err("%s: Failure walking packet chain", __func__);
			return -EIO;
		}

		/* update queue head with next pkt ptr which could be NULL */
		gwlan_logging.data_mgmt_pkt_queue = next_pkt;
		--gwlan_logging.data_mgmt_pkt_qcnt;
		spin_unlock_irqrestore(&gwlan_logging.data_mgmt_pkt_lock, flags);

		status = vos_pkt_get_os_packet(current_pkt, (v_VOID_t **)&skb,
						TRUE);
		if (!VOS_IS_STATUS_SUCCESS(status)) {
			++gwlan_logging.pkt_drop_cnt;
			pr_err("%s: Failure extracting skb from vos pkt",
				__func__);
			return -EIO;
		}

		/*return vos pkt since skb is already detached */
		vos_pkt_return_packet(current_pkt);

		extra_header_len = sizeof(msg_header.radio) + sizeof(tAniHdr) +
						sizeof(msg_header.frameSize);
		nl_payload_len = NLMSG_ALIGN(extra_header_len + skb->len);

		msg_header.nlh.nlmsg_type = ANI_NL_MSG_LOG;
		msg_header.nlh.nlmsg_len = nl_payload_len;
		msg_header.nlh.nlmsg_flags = NLM_F_REQUEST;
		msg_header.nlh.nlmsg_pid = 0;
		msg_header.nlh.nlmsg_seq = nlmsg_seq++;

		msg_header.radio = 0;

		msg_header.wmsg.type = ANI_NL_MSG_LOG_PKT_TYPE;
		msg_header.wmsg.length = skb->len + sizeof(uint32);

		msg_header.frameSize = WLAN_MGMT_LOGGING_FRAMESIZE_128BYTES;

		if (unlikely(skb_headroom(skb) < sizeof(msg_header))) {
			pr_err("VPKT [%d]: Insufficient headroom, head[%p],"
				" data[%p], req[%zu]", __LINE__, skb->head,
				skb->data, sizeof(msg_header));
			return -EIO;
		}

		vos_mem_copy(skb_push(skb, sizeof(msg_header)), &msg_header,
							sizeof(msg_header));

		ret =  nl_srv_bcast(skb);
		if (ret < 0) {
			pr_info("%s: Send Failed %d drop_count = %u\n",
				__func__, ret, ++gwlan_logging.pkt_drop_cnt);
		} else {
			ret = 0;
		}

	} while (next_pkt);

	return ret;
}