Beispiel #1
0
/* callback when endpoint 0 send buffers are completed */
LOCAL void HTCControlSvcProcessSendComplete(HTC_ENDPOINT_ID EndpointID,
					    adf_nbuf_t pBuffers, void *arg)
{
	HTC_CONTEXT *pHTC = (HTC_CONTEXT *)arg;
	HTC_BUF_CONTEXT *ctx;
	HTC_ENDPOINT_ID creditRptEndpoint;
    
	ctx = (HTC_BUF_CONTEXT *)adf_nbuf_get_priv(pBuffers);       
    
	/* put them back into the pool */
	if ( ctx->htc_flags & HTC_FLAGS_CREDIT_RPT ) {   
		/* extract the endpoint number that requested this credit report */ 
		creditRptEndpoint = ctx->htc_flags & HTC_FLAGS_CRPT_EP_MASK;    
		pHTC->Endpoints[creditRptEndpoint].PendingCreditReports--;  
	}
    
	HTCFreeMsgBuffer(pHTC, pBuffers);
   
	if (pHTC->StateFlags & HTC_SEND_CREDIT_UPDATE_SOON) {
		/* this flag is set when the host could not send a credit report
		 * because we ran out of HTC control buffers */
		pHTC->StateFlags &= ~HTC_SEND_CREDIT_UPDATE_SOON;
		/* send out a report if anything is pending */
		HTCCheckAndSendCreditReport(pHTC, HTC_ANY_ENDPOINT_MASK,NULL,ENDPOINT_MAX);
	}  
}
Beispiel #2
0
void
ieee80211_recv_mgmt_defer(void *arg)
{
    struct ieee80211com *ic = (struct ieee80211com *)arg;
    struct ieee80211_recv_mgt_args *entry = NULL;
    wbuf_t  wbuf = ADF_NBUF_NULL;
    struct ieee80211_rx_status  rs;
     struct ieee80211vap *vap ;
    
    /* Dequeue and process */
    do {

        OS_MGMT_LOCKBH(&ic->ic_mgmt_lock);
        wbuf = adf_nbuf_queue_remove(&ic->ic_mgmt_nbufqueue);
        OS_MGMT_UNLOCKBH(&ic->ic_mgmt_lock);

        if(!wbuf)
            break;
        entry = (struct ieee80211_recv_mgt_args *)adf_nbuf_get_priv(wbuf);
        ieee80211_recv_mgmt( entry->ni, wbuf, entry->subtype, &rs);

        vap = entry->ni->ni_vap;
        if (vap->iv_evtable) {
            vap->iv_evtable->wlan_receive(vap->iv_ifp,wbuf,IEEE80211_FC0_TYPE_MGT,entry->subtype, &rs);
        }

    }while(1);
    atomic_set(&ic->ic_mgmt_deferflags, DEFER_DONE);
    return;
}
/* send completion handler when any HTC buffers are returned */
static void _WMI_SendCompleteHandler(HTC_ENDPOINT_ID Endpt, adf_nbuf_t pHTCBuf, void *arg)
{
	WMI_SVC_CONTEXT *pWMI = (WMI_SVC_CONTEXT *)arg;
	WMI_BUF_CONTEXT *ctx;
	BUF_POOL_ID poolId;

	ctx = (WMI_BUF_CONTEXT *)adf_nbuf_get_priv(pHTCBuf);

	if ( ctx->EventClass == WMI_EVT_CLASS_CMD_EVENT ) {
		poolId = POOL_ID_WMI_SVC_EVENT;
	} else {
		poolId = POOL_ID_WMI_SVC_CMD_REPLY;
	}

	BUF_Pool_free_buf(pWMI->PoolHandle, poolId, pHTCBuf);
}
Beispiel #4
0
LOCAL void HTCSendDoneHandler(adf_nbuf_t buf, void *context)
{
	A_UINT8 current_eid;
	HTC_CONTEXT *pHTC = (HTC_CONTEXT *)context;
	HTC_BUF_CONTEXT *ctx;
      
	ctx = (HTC_BUF_CONTEXT *)adf_nbuf_get_priv(buf);
	current_eid = ctx->end_point;
        
	/* Walk through the buffers and fixup the ones we used for HTC headers.
	 * The buffer list may contain more than one string of HTC buffers comprising of an
	 * HTC message so we need to check every buffer */            
	adf_nbuf_pull_head(buf, HTC_HDR_LENGTH);
                   
	pHTC->Endpoints[current_eid].pService->
		ProcessSendBufferComplete(current_eid, 
					  buf, 
					  pHTC->Endpoints[current_eid].pService->ServiceCtx);
}
static adf_nbuf_t _WMI_AllocEvent(wmi_handle_t handle, WMI_EVT_CLASS EventClass,
				  int Length)
{
	BUF_POOL_ID poolId;
	WMI_SVC_CONTEXT *pWMI = (WMI_SVC_CONTEXT *)handle;
	adf_nbuf_t buf;
	WMI_BUF_CONTEXT *ctx;

	if ( EventClass == WMI_EVT_CLASS_CMD_EVENT ) {
		poolId = POOL_ID_WMI_SVC_EVENT;
	} else {
		poolId = POOL_ID_WMI_SVC_CMD_REPLY;
	}

	buf = BUF_Pool_alloc_buf(pWMI->PoolHandle,
				 poolId,
				 sizeof(WMI_CMD_HDR) + HTC_GetReservedHeadroom(pWMI->HtcHandle));

	if ( buf != NULL ) {
		ctx = (WMI_BUF_CONTEXT *)adf_nbuf_get_priv(buf);
		ctx->EventClass = EventClass;
	}
	return buf;
}
Beispiel #6
0
LOCAL void HTCCheckAndSendCreditReport(HTC_CONTEXT *pHTC, A_UINT32 EpMask,
				       HTC_ENDPOINT *pEndpoint, HTC_ENDPOINT_ID Eid)
{
	adf_nbuf_t pCredBuffer;
	HTC_BUF_CONTEXT *ctx;    
        
	do {
		/* check if host needs credits */
		if (!(pHTC->EpHostNeedsCreditMap & EpMask)) {
			/* host does not need any credits for this set */
			break;    
		}
		/* check if any are pending */
		if (!(pHTC->EpCreditPendingMap & EpMask)) {
			/* nothing to send up */
			break;    
		}  
		/* was an endpoint specified? */
		if (pEndpoint != NULL) {
			/* see if a threshold is in effect for this endpoint */
			if (pEndpoint->CreditReturnThreshhold != 0) {
				if (pEndpoint->CreditsToReturn < pEndpoint->CreditReturnThreshhold) {
					/* this endpoint is using a threshold to prevent credits from dribbling
					 * back to the host */
					break;
				}
			}
         
			if (pEndpoint->PendingCreditReports >= pHTC->MaxEpPendingCreditRpts) {
				/* this endpoint already has some reports outstanding */
				/* flag that as soon as a buffer is reaped, we issue a credit update to
				 * pick up this credit that is being held up because the endpoint has already
				 * exceeded the max outstanding credit report limit */    
				pHTC->StateFlags |= HTC_SEND_CREDIT_UPDATE_SOON;
				break;    
			}                         
		}
        
		/* if we get here we have some credits to send up */
                        
		/* allocate a message buffer for the trailer */
		pCredBuffer = HTCAllocMsgBuffer(pHTC);
		if (NULL == pCredBuffer) {
			/* no buffers left to send an empty message with trailers, host will just
			 * have to wait until we get our endpoint 0 messages back.. */
			/* mark that we need to send an update as soon as we can get a buffer back */
			pHTC->StateFlags |= HTC_SEND_CREDIT_UPDATE_SOON;
			break;    
		}
        
		ctx = (HTC_BUF_CONTEXT *)adf_nbuf_get_priv(pCredBuffer);
		if (pEndpoint != NULL) {
			/* keep track of pending reports */
			pEndpoint->PendingCreditReports++; 
			/* save the endpoint in order to decrement the count when the send completes */
			ctx->htc_flags = Eid | HTC_FLAGS_CREDIT_RPT;
		}   
            
		/* this is an empty message, the HTC_SendMsg will tack on a trailer in the remaining
		 * space, NOTE: no need to flush the cache, the header and trailers are assembled
		 * using uncached addresses */
		HTC_SendMsg(pHTC, ENDPOINT0, pCredBuffer);    
    
	} while (FALSE);      
}
Beispiel #7
0
LOCAL void _HTC_SendMsg(htc_handle_t htcHandle, HTC_ENDPOINT_ID EndpointID,
			adf_nbuf_t pBuffers)
{
	HTC_FRAME_HDR *pHTCHdr;
	int totsz;
	HTC_CONTEXT *pHTC = (HTC_CONTEXT *)htcHandle;  
	HTC_BUF_CONTEXT *ctx;
    
	ctx = (HTC_BUF_CONTEXT *)adf_nbuf_get_priv(pBuffers);
    
	/* init total size (this does not include the space we will put in for the HTC header) */
	totsz = adf_nbuf_len(pBuffers);
    
	/* the first buffer stores the header */
        /* back up buffer by a header size when we pass it down, by agreed upon convention the caller
	 * points the buffer to it's payload and leaves head room for the HTC header  
	 * Note: in HTCSendDoneHandler(), we undo this so that the caller get's it's buffer
	 * back untainted */   
	pHTCHdr = (HTC_FRAME_HDR *)adf_nbuf_push_head(pBuffers, HTC_HDR_LENGTH);
    
	/* flag that this is the header buffer that was modified */
	ctx->htc_flags |= HTC_FLAGS_BUF_HDR;   
	/* mark where this buffer came from */
	ctx->end_point = EndpointID;      
	/* the header start is ALWAYS aligned since we DMA it directly */

        /* set some fields, the rest of them will be filled below when we check for
	 * trailer space */
	pHTCHdr->Flags = 0;
	pHTCHdr->EndpointID = EndpointID;    
       
	/* check opportunistically if we can return any reports via a trailer */
	do {
		int               room,i,totalReportBytes;
		A_UINT32          creditsPendingMap, compareMask;
		HTC_CREDIT_REPORT *pCreditRpt;
		HTC_RECORD_HDR    *pRecHdr;
		int               pipeMaxLen;
		A_UINT32          roomForPipeMaxLen;
                          
		/* figure out how much room the last buffer can spare */
		pipeMaxLen = HIF_get_max_msg_len(pHTC->hifHandle,
						 pHTC->Endpoints[EndpointID].DownLinkPipeID);
		roomForPipeMaxLen = pipeMaxLen - adf_nbuf_headroom(pBuffers) - adf_nbuf_len(pBuffers);
		if ( roomForPipeMaxLen < 0 ) {
			roomForPipeMaxLen = 0;
		}
                        
		room = adf_os_min( adf_nbuf_tailroom(pBuffers), roomForPipeMaxLen);
		if (room < (int)(sizeof(HTC_CREDIT_REPORT) + sizeof(HTC_RECORD_HDR))) {
			/* no room for any reports */
			break;    
		}   
		/* note, a record header only has 8 bit fields, so this is safe.
		 * we need an uncached pointer here too */            
		totalReportBytes = 0;
        
		/* get a copy */        
		creditsPendingMap = pHTC->EpCreditPendingMap;   
                           
		/* test pending map to see if we can send a report , if any
		 * credits are available, we might as well send them on the 
		 * unused space in the buffer */
		if (creditsPendingMap) { 
            
			pRecHdr = (HTC_RECORD_HDR *)adf_nbuf_put_tail(pBuffers,
							      sizeof(HTC_RECORD_HDR));
            
			/* set the ID, the length will be updated with the number of credit reports we
			 * can fit (see below) */
			pRecHdr->RecordID = HTC_RECORD_CREDITS;
			pRecHdr->Length = 0;
			/* the credit report follows the record header */         
			totalReportBytes += sizeof(HTC_RECORD_HDR);
			room -= sizeof(HTC_RECORD_HDR);
            
			/* walkthrough pending credits map and build the records */
			for (i = 0; 
			     (creditsPendingMap != 0) && (room >= (int)sizeof(HTC_CREDIT_REPORT)); 
			     i++) {                
				compareMask = (1 << i);
				if (compareMask & creditsPendingMap) {
                        
					pCreditRpt = (HTC_CREDIT_REPORT *)adf_nbuf_put_tail(pBuffers,
									    sizeof(HTC_CREDIT_REPORT));
                                    
					/* clear pending mask, we are going to return all these credits */
					creditsPendingMap &= ~(compareMask);
					/* add this record */
					pCreditRpt->EndpointID = i;
					pCreditRpt->Credits = (A_UINT8)pHTC->Endpoints[i].CreditsToReturn;
					/* remove pending credits, we always send deltas */
					pHTC->Endpoints[i].CreditsToReturn = 0; 
					/* adjust new threshold for this endpoint if needed */
					CHECK_AND_ADJUST_CREDIT_THRESHOLD(&pHTC->Endpoints[i]);
					/* update this record length */
					pRecHdr->Length += sizeof(HTC_CREDIT_REPORT);
					room -= sizeof(HTC_CREDIT_REPORT);
					totalReportBytes += sizeof(HTC_CREDIT_REPORT);

					if ( room < sizeof(HTC_CREDIT_REPORT) ) {
						break;
					}
				}
			}
            
			/* update new pending credits map */       
			pHTC->EpCreditPendingMap = creditsPendingMap;
		}
        
		if (totalReportBytes <= 0) {
			break;
		}
        
		/* must fit into a byte, this should never actually happen since
		 * the maximum possible number of endpoints is 32. 
		 * The trailer can have at most 1 credit record with up to 32  reports in the record.
		 * The trailer can have at most 1 lookahead record with only 1 lookahead report in the record.
		 */
        
		/* set header option bytes */ 
		pHTCHdr->ControlBytes[0] = totalReportBytes;
		/* HTC frame contains a trailer */
		pHTCHdr->Flags |= HTC_FLAGS_RECV_TRAILER;
		/* increment total size by the reports we added */
		totsz += totalReportBytes;
		/* adjust the last buffer we used for adding on the trailer */                                 
	} while (FALSE);
          
	if (totsz == 0) {
	}
    
	/* set length for message (this includes any reports that were added above) */
	pHTCHdr->PayloadLen = adf_os_htons(totsz);  
	HIF_send_buffer(pHTC->hifHandle, pHTC->Endpoints[EndpointID].DownLinkPipeID, pBuffers);       
}