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; }
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); }
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); }
/* 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; }
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; }