예제 #1
0
static A_STATUS AllocateDMABounceBuffer(HIF_DEVICE *device, HIF_SCATTER_DMA_BOUNCE_INFO *pBounceInfo)
{
    A_STATUS            status = A_OK;
    A_UINT32            temp;
    SDDMA_DESCRIPTION  *pDescription;
        
    pDescription = SDGET_DMA_DESCRIPTION(device->handle);
    
    do {
        
        pBounceInfo->BufferSize = MAX_SCATTER_REQ_TRANSFER_SIZE + 2*(A_GET_CACHE_LINE_BYTES());
                
            /* allocate the bounce buffer */                 
        pBounceInfo->pBounceBuffer  = (A_UINT8 *)kmalloc(pBounceInfo->BufferSize,
                                                         GFP_KERNEL | GFP_DMA | GFP_ATOMIC);
                                         
        if (NULL == pBounceInfo->pBounceBuffer) {            
            AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,("HIF : *** unable to allocate bounce buffer \n"));      
            status = A_NO_MEMORY;
            break;  
        }   

        temp = (A_UINT32)A_ALIGN_TO_CACHE_LINE(pBounceInfo->pBounceBuffer);
            /* check bounce buffer address alignment */
        if ((temp & pDescription->AddressAlignment) == 0) {
                /* no illegal address bits */
            break;    
        }
                
            /* free the buffer we just allocated, we need to allocate a larger buffer */
        FreeBounceBuffer(device, pBounceInfo);
            /* increase buffer size by padding it by the required alignment */                  
        pBounceInfo->BufferSize = MAX_SCATTER_REQ_TRANSFER_SIZE + 2*(A_GET_CACHE_LINE_BYTES()) + 
                                        (pDescription->AddressAlignment + 1);   
                            
        pBounceInfo->pBounceBuffer  = (A_UINT8 *)kmalloc(pBounceInfo->BufferSize,
                                                         GFP_KERNEL | GFP_DMA | GFP_ATOMIC);
                                                         
        if (NULL == pBounceInfo->pBounceBuffer) {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,("HIF : *** unable to allocate bounce buffer \n"));
            status = A_NO_MEMORY;
            break;  
        }   
        
            /* figure out required alignment */
        temp = (A_UINT32)A_ALIGN_TO_CACHE_LINE(pBounceInfo->pBounceBuffer);
        temp += (pDescription->AddressAlignment + 1);
        temp &= ~pDescription->AddressAlignment;
        
        pBounceInfo->AlignmentOffset = temp - (A_UINT32)pBounceInfo->pBounceBuffer;
        
        AR_DEBUG_PRINTF(ATH_DEBUG_WARN,("HIF : Bounce Buffer (0x%X) will apply alignment: %d \n",
                (A_UINT32)pBounceInfo->pBounceBuffer, pBounceInfo->AlignmentOffset));
                
    } while (FALSE);
    
    return status;
}
예제 #2
0
void *
a_netbuf_alloc(int size)
{
    struct sk_buff *skb;
    size += 2 * (A_GET_CACHE_LINE_BYTES()); /* add some cacheline space at front and back of buffer */
    skb = dev_alloc_skb(AR6000_DATA_OFFSET + sizeof(struct htc_packet) + size);
    skb_reserve(skb, AR6000_DATA_OFFSET + sizeof(struct htc_packet) + A_GET_CACHE_LINE_BYTES());
    return ((void *)skb);
}
예제 #3
0
void *
a_netbuf_alloc(int size)
#endif
{
    struct sk_buff *skb;
    size += 2 * (A_GET_CACHE_LINE_BYTES()); /* add some cacheline space at front and back of buffer */
    skb = dev_alloc_skb(AR6000_DATA_OFFSET + sizeof(HTC_PACKET) + size);
    if (skb) {
        skb_reserve(skb, AR6000_DATA_OFFSET + sizeof(HTC_PACKET) + A_GET_CACHE_LINE_BYTES());    
#ifdef AR6K_ALLOC_DEBUG
        __a_meminfo_add(skb, size, func, lineno);
#endif
    }
    return ((void *)skb);
}
예제 #4
0
파일: ar6k.c 프로젝트: ANFS/ANFS-kernel
    /* function to set up virtual scatter support if HIF layer has not implemented the interface */
static A_STATUS DevSetupVirtualScatterSupport(AR6K_DEVICE *pDev)
{
    A_STATUS                     status = A_OK;
    int                          bufferSize, sgreqSize;
    int                          i;
    DEV_SCATTER_DMA_VIRTUAL_INFO *pVirtualInfo;
    HIF_SCATTER_REQ              *pReq;

    bufferSize = sizeof(DEV_SCATTER_DMA_VIRTUAL_INFO) +
                2 * (A_GET_CACHE_LINE_BYTES()) + AR6K_MAX_TRANSFER_SIZE_PER_SCATTER;

    sgreqSize = sizeof(HIF_SCATTER_REQ) +
                    (AR6K_SCATTER_ENTRIES_PER_REQ - 1) * (sizeof(HIF_SCATTER_ITEM));

    for (i = 0; i < AR6K_SCATTER_REQS; i++) {
            /* allocate the scatter request, buffer info and the actual virtual buffer itself */
        pReq = (HIF_SCATTER_REQ *)A_MALLOC(sgreqSize + bufferSize);

        if (NULL == pReq) {
            status = A_NO_MEMORY;
            break;
        }

        A_MEMZERO(pReq, sgreqSize);

            /* the virtual DMA starts after the scatter request struct */
        pVirtualInfo = (DEV_SCATTER_DMA_VIRTUAL_INFO *)((A_UINT8 *)pReq + sgreqSize);
        A_MEMZERO(pVirtualInfo, sizeof(DEV_SCATTER_DMA_VIRTUAL_INFO));

        pVirtualInfo->pVirtDmaBuffer = &pVirtualInfo->DataArea[0];
            /* align buffer to cache line in case host controller can actually DMA this */
        pVirtualInfo->pVirtDmaBuffer = A_ALIGN_TO_CACHE_LINE(pVirtualInfo->pVirtDmaBuffer);
            /* store the structure in the private area */
        pReq->HIFPrivate[0] = pVirtualInfo;
            /* we emulate a DMA bounce interface */
        pReq->ScatterMethod = HIF_SCATTER_DMA_BOUNCE;
        pReq->pScatterBounceBuffer = pVirtualInfo->pVirtDmaBuffer;
            /* free request to the list */
        DevFreeScatterReq((HIF_DEVICE *)pDev,pReq);
    }

    if (A_FAILED(status)) {
        DevCleanupVirtualScatterSupport(pDev);
    } else {
        pDev->HifScatterInfo.pAllocateReqFunc = DevAllocScatterReq;
        pDev->HifScatterInfo.pFreeReqFunc = DevFreeScatterReq;
        pDev->HifScatterInfo.pReadWriteScatterFunc = DevReadWriteScatter;
        if (pDev->MailBoxInfo.MboxBusIFType == MBOX_BUS_IF_SPI) {
            AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6K: SPI bus requires RX scatter limits\n"));
            pDev->HifScatterInfo.MaxScatterEntries = AR6K_MIN_SCATTER_ENTRIES_PER_REQ;
            pDev->HifScatterInfo.MaxTransferSizePerScatterReq = AR6K_MIN_TRANSFER_SIZE_PER_SCATTER;
        } else {
            pDev->HifScatterInfo.MaxScatterEntries = AR6K_SCATTER_ENTRIES_PER_REQ;
            pDev->HifScatterInfo.MaxTransferSizePerScatterReq = AR6K_MAX_TRANSFER_SIZE_PER_SCATTER;
        }
        pDev->ScatterIsVirtual = TRUE;
    }

    return status;
}
예제 #5
0
A_STATUS SetupHIFScatterSupport(HIF_DEVICE *device, HIF_DEVICE_SCATTER_SUPPORT_INFO *pInfo)
{
    A_STATUS            status = A_ERROR;   
    int                 maxTransferSizePerScatter = MAX_SCATTER_REQ_TRANSFER_SIZE;
    int                 size, i;
    HIF_SCATTER_REQ     *pReq;
    SDREQUEST           *sdrequest;
        
    do {
        
        DetermineScatterMethod(device);
    
        if (device->ScatterMethod == HIF_SCATTER_NONE) {
                /* no scatter support */
            break;    
        }
        
        AR_DEBUG_PRINTF(ATH_DEBUG_INIT,("HIF : Cache Line Size: %d bytes \n",A_GET_CACHE_LINE_BYTES())); 
        
        size = sizeof(HIF_SCATTER_REQ) + 
                    (MAX_SCATTER_ENTRIES_PER_REQ - 1) * (sizeof(HIF_SCATTER_ITEM));
       
        for (i = 0; i < MAX_SCATTER_REQUESTS; i++) {    
            
            pReq = A_MALLOC(size);
            if (NULL == pReq) {
                break;    
            }
            A_MEMZERO(pReq, size);
            
                /* save the device instance */
            SET_DEVICE_INFO_SR(pReq, device);
            
                /* allocate a bus request for this scatter request */
            sdrequest = SDDeviceAllocRequest(device->handle);
            if (NULL == sdrequest) {
                A_FREE(pReq);
                break;    
            }
                /* store bus request into private area */
            SET_SDREQUEST_SR(pReq,sdrequest);
            
            status = SetupScatterResource(device,pReq);
            if (A_FAILED(status)) {
                SDDeviceFreeRequest(device->handle, sdrequest);
                A_FREE(pReq); 
                break;       
            }         
               
                /* add it to the free pool */
            FreeScatterReq(device, pReq);
        }
        
        if (i != MAX_SCATTER_REQUESTS) {
            status = A_NO_MEMORY;
            break;    
        }
        
            /* set function pointers */
        pInfo->pAllocateReqFunc = AllocScatterReq;
        pInfo->pFreeReqFunc = FreeScatterReq;
        pInfo->pReadWriteScatterFunc = HifReadWriteScatter;   
        pInfo->MaxScatterEntries = MAX_SCATTER_ENTRIES_PER_REQ;
        pInfo->MaxTransferSizePerScatterReq = maxTransferSizePerScatter;
     
        status = A_OK;
        
    } while (FALSE);
    
    if (A_FAILED(status)) {
        CleanupHIFScatterResources(device);   
    }
    
    return status;
}