Exemplo n.º 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;
}
Exemplo n.º 2
0
    /* 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;
}