| Index: chromeos/drivers/ath6kl/htc2/AR6000/ar6k.c
|
| diff --git a/chromeos/drivers/ath6kl/htc2/AR6000/ar6k.c b/chromeos/drivers/ath6kl/htc2/AR6000/ar6k.c
|
| index dfcc60b548e43b0743fa9fb126855eb67fb74191..1efc85ce02b28d2e7bd6fa8b9f45d0d989b01001 100644
|
| --- a/chromeos/drivers/ath6kl/htc2/AR6000/ar6k.c
|
| +++ b/chromeos/drivers/ath6kl/htc2/AR6000/ar6k.c
|
| @@ -1,15 +1,19 @@
|
| //------------------------------------------------------------------------------
|
| // <copyright file="ar6k.c" company="Atheros">
|
| -// Copyright (c) 2007-2008 Atheros Corporation. All rights reserved.
|
| +// Copyright (c) 2007-2010 Atheros Corporation. All rights reserved.
|
| //
|
| -// This program is free software; you can redistribute it and/or modify
|
| -// it under the terms of the GNU General Public License version 2 as
|
| -// published by the Free Software Foundation;
|
| //
|
| -// Software distributed under the License is distributed on an "AS
|
| -// IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
| -// implied. See the License for the specific language governing
|
| -// rights and limitations under the License.
|
| +// Permission to use, copy, modify, and/or distribute this software for any
|
| +// purpose with or without fee is hereby granted, provided that the above
|
| +// copyright notice and this permission notice appear in all copies.
|
| +//
|
| +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
| +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
| +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
| +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
| +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
| +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
| +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
| //
|
| //
|
| //------------------------------------------------------------------------------
|
| @@ -57,17 +61,17 @@ HTC_PACKET *AR6KAllocIOPacket(AR6K_DEVICE *pDev)
|
| void DevCleanup(AR6K_DEVICE *pDev)
|
| {
|
| DevCleanupGMbox(pDev);
|
| -
|
| +
|
| if (pDev->HifAttached) {
|
| HIFDetachHTC(pDev->HIFDevice);
|
| pDev->HifAttached = FALSE;
|
| }
|
| -
|
| +
|
| DevCleanupVirtualScatterSupport(pDev);
|
| -
|
| +
|
| if (A_IS_MUTEX_VALID(&pDev->Lock)) {
|
| A_MUTEX_DELETE(&pDev->Lock);
|
| - }
|
| + }
|
| }
|
|
|
| A_STATUS DevSetup(AR6K_DEVICE *pDev)
|
| @@ -76,28 +80,28 @@ A_STATUS DevSetup(AR6K_DEVICE *pDev)
|
| A_STATUS status = A_OK;
|
| int i;
|
| HTC_CALLBACKS htcCallbacks;
|
| -
|
| +
|
| do {
|
| -
|
| +
|
| DL_LIST_INIT(&pDev->ScatterReqHead);
|
| /* initialize our free list of IO packets */
|
| INIT_HTC_PACKET_QUEUE(&pDev->RegisterIOList);
|
| A_MUTEX_INIT(&pDev->Lock);
|
| -
|
| +
|
| A_MEMZERO(&htcCallbacks, sizeof(HTC_CALLBACKS));
|
| /* the device layer handles these */
|
| htcCallbacks.rwCompletionHandler = DevRWCompletionHandler;
|
| htcCallbacks.dsrHandler = DevDsrHandler;
|
| htcCallbacks.context = pDev;
|
| -
|
| +
|
| status = HIFAttachHTC(pDev->HIFDevice, &htcCallbacks);
|
| -
|
| +
|
| if (A_FAILED(status)) {
|
| - break;
|
| + break;
|
| }
|
| -
|
| +
|
| pDev->HifAttached = TRUE;
|
| -
|
| +
|
| /* get the addresses for all 4 mailboxes */
|
| status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_ADDR,
|
| &pDev->MailBoxInfo, sizeof(pDev->MailBoxInfo));
|
| @@ -158,20 +162,20 @@ A_STATUS DevSetup(AR6K_DEVICE *pDev)
|
| sizeof(pDev->HifIRQProcessingMode));
|
|
|
| switch (pDev->HifIRQProcessingMode) {
|
| - case HIF_DEVICE_IRQ_SYNC_ONLY:
|
| + case HIF_DEVICE_IRQ_SYNC_ONLY:
|
| AR_DEBUG_PRINTF(ATH_DEBUG_WARN,("HIF Interrupt processing is SYNC ONLY\n"));
|
| /* see if HIF layer wants HTC to yield */
|
| HIFConfigureDevice(pDev->HIFDevice,
|
| HIF_DEVICE_GET_IRQ_YIELD_PARAMS,
|
| &pDev->HifIRQYieldParams,
|
| sizeof(pDev->HifIRQYieldParams));
|
| -
|
| +
|
| if (pDev->HifIRQYieldParams.RecvPacketYieldCount > 0) {
|
| AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
|
| ("HIF requests that DSR yield per %d RECV packets \n",
|
| - pDev->HifIRQYieldParams.RecvPacketYieldCount));
|
| - pDev->DSRCanYield = TRUE;
|
| - }
|
| + pDev->HifIRQYieldParams.RecvPacketYieldCount));
|
| + pDev->DSRCanYield = TRUE;
|
| + }
|
| break;
|
| case HIF_DEVICE_IRQ_ASYNC_SYNC:
|
| AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("HIF Interrupt processing is ASYNC and SYNC\n"));
|
| @@ -188,15 +192,15 @@ A_STATUS DevSetup(AR6K_DEVICE *pDev)
|
| &pDev->HifMaskUmaskRecvEvent,
|
| sizeof(pDev->HifMaskUmaskRecvEvent));
|
|
|
| - AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("HIF special overrides : 0x%X , 0x%X\n",
|
| - (A_UINT32)pDev->GetPendingEventsFunc, (A_UINT32)pDev->HifMaskUmaskRecvEvent));
|
| + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("HIF special overrides : 0x%lX , 0x%lX\n",
|
| + (unsigned long)pDev->GetPendingEventsFunc, (unsigned long)pDev->HifMaskUmaskRecvEvent));
|
|
|
| status = DevDisableInterrupts(pDev);
|
|
|
| if (A_FAILED(status)) {
|
| - break;
|
| + break;
|
| }
|
| -
|
| +
|
| status = DevSetupGMbox(pDev);
|
|
|
| } while (FALSE);
|
| @@ -299,18 +303,27 @@ A_STATUS DevDisableInterrupts(AR6K_DEVICE *pDev)
|
| /* enable device interrupts */
|
| A_STATUS DevUnmaskInterrupts(AR6K_DEVICE *pDev)
|
| {
|
| - /* for good measure, make sure interrupt are disabled before unmasking at the HIF
|
| - * layer.
|
| - * The rationale here is that between device insertion (where we clear the interrupts the first time)
|
| - * and when HTC is finally ready to handle interrupts, other software can perform target "soft" resets.
|
| - * The AR6K interrupt enables reset back to an "enabled" state when this happens.
|
| - * */
|
| + /* for good measure, make sure interrupt are disabled before unmasking at the HIF
|
| + * layer.
|
| + * The rationale here is that between device insertion (where we clear the interrupts the first time)
|
| + * and when HTC is finally ready to handle interrupts, other software can perform target "soft" resets.
|
| + * The AR6K interrupt enables reset back to an "enabled" state when this happens.
|
| + * */
|
| + A_STATUS IntStatus = A_OK;
|
| DevDisableInterrupts(pDev);
|
|
|
| - /* Unmask the host controller interrupts */
|
| +#ifdef THREAD_X
|
| + // Tobe verified...
|
| + IntStatus = DevEnableInterrupts(pDev);
|
| + /* Unmask the host controller interrupts */
|
| HIFUnMaskInterrupt(pDev->HIFDevice);
|
| +#else
|
| + /* Unmask the host controller interrupts */
|
| + HIFUnMaskInterrupt(pDev->HIFDevice);
|
| + IntStatus = DevEnableInterrupts(pDev);
|
| +#endif
|
|
|
| - return DevEnableInterrupts(pDev);
|
| + return IntStatus;
|
| }
|
|
|
| /* disable all device interrupts */
|
| @@ -328,7 +341,7 @@ static void DevDoEnableDisableRecvAsyncHandler(void *Context, HTC_PACKET *pPacke
|
| {
|
| AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
|
|
|
| - AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevDoEnableDisableRecvAsyncHandler: (dev: 0x%X)\n", (A_UINT32)pDev));
|
| + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevDoEnableDisableRecvAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
|
|
|
| if (A_FAILED(pPacket->Status)) {
|
| AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
|
| @@ -475,6 +488,54 @@ A_STATUS DevEnableRecv(AR6K_DEVICE *pDev, A_BOOL AsyncMode)
|
| }
|
| }
|
|
|
| +A_STATUS DevWaitForPendingRecv(AR6K_DEVICE *pDev,A_UINT32 TimeoutInMs,A_BOOL *pbIsRecvPending)
|
| +{
|
| + A_STATUS status = A_OK;
|
| + A_UCHAR host_int_status = 0x0;
|
| + A_UINT32 counter = 0x0;
|
| +
|
| + if(TimeoutInMs < 100)
|
| + {
|
| + TimeoutInMs = 100;
|
| + }
|
| +
|
| + counter = TimeoutInMs / 100;
|
| +
|
| + do
|
| + {
|
| + //Read the Host Interrupt Status Register
|
| + status = HIFReadWrite(pDev->HIFDevice,
|
| + HOST_INT_STATUS_ADDRESS,
|
| + &host_int_status,
|
| + sizeof(A_UCHAR),
|
| + HIF_RD_SYNC_BYTE_INC,
|
| + NULL);
|
| + if(A_FAILED(status))
|
| + {
|
| + AR_DEBUG_PRINTF(ATH_LOG_ERR,("DevWaitForPendingRecv:Read HOST_INT_STATUS_ADDRESS Failed 0x%X\n",status));
|
| + break;
|
| + }
|
| +
|
| + host_int_status = A_SUCCESS(status) ? (host_int_status & (1 << 0)):0;
|
| + if(!host_int_status)
|
| + {
|
| + status = A_OK;
|
| + *pbIsRecvPending = FALSE;
|
| + break;
|
| + }
|
| + else
|
| + {
|
| + *pbIsRecvPending = TRUE;
|
| + }
|
| +
|
| + A_MDELAY(100);
|
| +
|
| + counter--;
|
| +
|
| + }while(counter);
|
| + return status;
|
| +}
|
| +
|
| void DevDumpRegisters(AR6K_DEVICE *pDev,
|
| AR6K_IRQ_PROC_REGISTERS *pIrqProcRegs,
|
| AR6K_IRQ_ENABLE_REGISTERS *pIrqEnableRegs)
|
| @@ -499,11 +560,11 @@ void DevDumpRegisters(AR6K_DEVICE *pDev,
|
| ("Rx Lookahead 0: 0x%x\n",pIrqProcRegs->rx_lookahead[0]));
|
| AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
|
| ("Rx Lookahead 1: 0x%x\n",pIrqProcRegs->rx_lookahead[1]));
|
| -
|
| +
|
| if (pDev->MailBoxInfo.GMboxAddress != 0) {
|
| /* if the target supports GMBOX hardware, dump some additional state */
|
| AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
|
| - ("GMBOX Host Int Status 2: 0x%x\n",pIrqProcRegs->host_int_status2));
|
| + ("GMBOX Host Int Status 2: 0x%x\n",pIrqProcRegs->host_int_status2));
|
| AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
|
| ("GMBOX RX Avail: 0x%x\n",pIrqProcRegs->gmbox_rx_avail));
|
| AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
|
| @@ -526,9 +587,9 @@ void DevDumpRegisters(AR6K_DEVICE *pDev,
|
|
|
| #define DEV_GET_VIRT_DMA_INFO(p) ((DEV_SCATTER_DMA_VIRTUAL_INFO *)((p)->HIFPrivate[0]))
|
|
|
| -static HIF_SCATTER_REQ *DevAllocScatterReq(HIF_DEVICE *Context)
|
| +static HIF_SCATTER_REQ *DevAllocScatterReq(HIF_DEVICE *Context)
|
| {
|
| - DL_LIST *pItem;
|
| + DL_LIST *pItem;
|
| AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
|
| LOCK_AR6K(pDev);
|
| pItem = DL_ListRemoveItemFromHead(&pDev->ScatterReqHead);
|
| @@ -536,7 +597,7 @@ static HIF_SCATTER_REQ *DevAllocScatterReq(HIF_DEVICE *Context)
|
| if (pItem != NULL) {
|
| return A_CONTAINING_STRUCT(pItem, HIF_SCATTER_REQ, ListLink);
|
| }
|
| - return NULL;
|
| + return NULL;
|
| }
|
|
|
| static void DevFreeScatterReq(HIF_DEVICE *Context, HIF_SCATTER_REQ *pReq)
|
| @@ -544,7 +605,7 @@ static void DevFreeScatterReq(HIF_DEVICE *Context, HIF_SCATTER_REQ *pReq)
|
| AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
|
| LOCK_AR6K(pDev);
|
| DL_ListInsertTail(&pDev->ScatterReqHead, &pReq->ListLink);
|
| - UNLOCK_AR6K(pDev);
|
| + UNLOCK_AR6K(pDev);
|
| }
|
|
|
| A_STATUS DevCopyScatterListToFromDMABuffer(HIF_SCATTER_REQ *pReq, A_BOOL FromDMA)
|
| @@ -552,38 +613,38 @@ A_STATUS DevCopyScatterListToFromDMABuffer(HIF_SCATTER_REQ *pReq, A_BOOL FromDMA
|
| A_UINT8 *pDMABuffer = NULL;
|
| int i, remaining;
|
| A_UINT32 length;
|
| -
|
| +
|
| pDMABuffer = pReq->pScatterBounceBuffer;
|
| -
|
| +
|
| if (pDMABuffer == NULL) {
|
| A_ASSERT(FALSE);
|
| - return A_EINVAL;
|
| + return A_EINVAL;
|
| }
|
| -
|
| +
|
| remaining = (int)pReq->TotalLength;
|
| -
|
| +
|
| for (i = 0; i < pReq->ValidScatterEntries; i++) {
|
| -
|
| +
|
| length = min((int)pReq->ScatterList[i].Length, remaining);
|
| -
|
| +
|
| if (length != (int)pReq->ScatterList[i].Length) {
|
| A_ASSERT(FALSE);
|
| /* there is a problem with the scatter list */
|
| - return A_EINVAL;
|
| + return A_EINVAL;
|
| }
|
| -
|
| +
|
| if (FromDMA) {
|
| /* from DMA buffer */
|
| - A_MEMCPY(pReq->ScatterList[i].pBuffer, pDMABuffer , length);
|
| + A_MEMCPY(pReq->ScatterList[i].pBuffer, pDMABuffer , length);
|
| } else {
|
| /* to DMA buffer */
|
| - A_MEMCPY(pDMABuffer, pReq->ScatterList[i].pBuffer, length);
|
| + A_MEMCPY(pDMABuffer, pReq->ScatterList[i].pBuffer, length);
|
| }
|
| -
|
| +
|
| pDMABuffer += length;
|
| remaining -= length;
|
| }
|
| -
|
| +
|
| return A_OK;
|
| }
|
|
|
| @@ -592,14 +653,14 @@ static void DevReadWriteScatterAsyncHandler(void *Context, HTC_PACKET *pPacket)
|
| AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
|
| HIF_SCATTER_REQ *pReq = (HIF_SCATTER_REQ *)pPacket->pPktContext;
|
|
|
| - AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+DevReadWriteScatterAsyncHandler: (dev: 0x%X)\n", (A_UINT32)pDev));
|
| + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+DevReadWriteScatterAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
|
|
|
| pReq->CompletionStatus = pPacket->Status;
|
| -
|
| +
|
| AR6KFreeIOPacket(pDev,pPacket);
|
| -
|
| +
|
| pReq->CompletionRoutine(pReq);
|
| -
|
| +
|
| AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-DevReadWriteScatterAsyncHandler \n"));
|
| }
|
|
|
| @@ -608,48 +669,48 @@ static A_STATUS DevReadWriteScatter(HIF_DEVICE *Context, HIF_SCATTER_REQ *pReq)
|
| AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
|
| A_STATUS status = A_OK;
|
| HTC_PACKET *pIOPacket = NULL;
|
| - A_UINT32 request = pReq->Request;
|
| -
|
| - do {
|
| -
|
| + A_UINT32 request = pReq->Request;
|
| +
|
| + do {
|
| +
|
| if (pReq->TotalLength > AR6K_MAX_TRANSFER_SIZE_PER_SCATTER) {
|
| AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
|
| ("Invalid length: %d \n", pReq->TotalLength));
|
| - break;
|
| + break;
|
| }
|
| -
|
| +
|
| if (pReq->TotalLength == 0) {
|
| A_ASSERT(FALSE);
|
| - break;
|
| + break;
|
| }
|
| -
|
| - if (request & HIF_ASYNCHRONOUS) {
|
| +
|
| + if (request & HIF_ASYNCHRONOUS) {
|
| /* use an I/O packet to carry this request */
|
| - pIOPacket = AR6KAllocIOPacket(pDev);
|
| + pIOPacket = AR6KAllocIOPacket(pDev);
|
| if (NULL == pIOPacket) {
|
| status = A_NO_MEMORY;
|
| break;
|
| }
|
| -
|
| +
|
| /* save the request */
|
| - pIOPacket->pPktContext = pReq;
|
| + pIOPacket->pPktContext = pReq;
|
| /* stick in our completion routine when the I/O operation completes */
|
| pIOPacket->Completion = DevReadWriteScatterAsyncHandler;
|
| pIOPacket->pContext = pDev;
|
| }
|
|
|
| - if (request & HIF_WRITE) {
|
| + if (request & HIF_WRITE) {
|
| /* in virtual DMA, we are issuing the requests through the legacy HIFReadWrite API
|
| * this API will adjust the address automatically for the last byte to fall on the mailbox
|
| * EOM. */
|
| -
|
| +
|
| /* if the address is an extended address, we can adjust the address here since the extended
|
| - * address will bypass the normal checks in legacy HIF layers */
|
| + * address will bypass the normal checks in legacy HIF layers */
|
| if (pReq->Address == pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedAddress) {
|
| - pReq->Address += pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedSize - pReq->TotalLength;
|
| - }
|
| + pReq->Address += pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedSize - pReq->TotalLength;
|
| + }
|
| }
|
| -
|
| +
|
| /* use legacy readwrite */
|
| status = HIFReadWrite(pDev->HIFDevice,
|
| pReq->Address,
|
| @@ -657,18 +718,18 @@ static A_STATUS DevReadWriteScatter(HIF_DEVICE *Context, HIF_SCATTER_REQ *pReq)
|
| pReq->TotalLength,
|
| request,
|
| (request & HIF_ASYNCHRONOUS) ? pIOPacket : NULL);
|
| -
|
| +
|
| } while (FALSE);
|
| -
|
| +
|
| if ((status != A_PENDING) && A_FAILED(status) && (request & HIF_ASYNCHRONOUS)) {
|
| if (pIOPacket != NULL) {
|
| - AR6KFreeIOPacket(pDev,pIOPacket);
|
| - }
|
| + AR6KFreeIOPacket(pDev,pIOPacket);
|
| + }
|
| pReq->CompletionStatus = status;
|
| pReq->CompletionRoutine(pReq);
|
| status = A_OK;
|
| }
|
| -
|
| +
|
| return status;
|
| }
|
|
|
| @@ -676,17 +737,17 @@ static A_STATUS DevReadWriteScatter(HIF_DEVICE *Context, HIF_SCATTER_REQ *pReq)
|
| static void DevCleanupVirtualScatterSupport(AR6K_DEVICE *pDev)
|
| {
|
| HIF_SCATTER_REQ *pReq;
|
| -
|
| +
|
| while (1) {
|
| pReq = DevAllocScatterReq((HIF_DEVICE *)pDev);
|
| if (NULL == pReq) {
|
| - break;
|
| - }
|
| - A_FREE(pReq);
|
| + break;
|
| + }
|
| + A_FREE(pReq);
|
| }
|
| -
|
| +
|
| }
|
| -
|
| +
|
| /* function to set up virtual scatter support if HIF layer has not implemented the interface */
|
| static A_STATUS DevSetupVirtualScatterSupport(AR6K_DEVICE *pDev)
|
| {
|
| @@ -695,32 +756,32 @@ static A_STATUS DevSetupVirtualScatterSupport(AR6K_DEVICE *pDev)
|
| int i;
|
| DEV_SCATTER_DMA_VIRTUAL_INFO *pVirtualInfo;
|
| HIF_SCATTER_REQ *pReq;
|
| -
|
| - bufferSize = sizeof(DEV_SCATTER_DMA_VIRTUAL_INFO) +
|
| +
|
| + bufferSize = sizeof(DEV_SCATTER_DMA_VIRTUAL_INFO) +
|
| 2 * (A_GET_CACHE_LINE_BYTES()) + AR6K_MAX_TRANSFER_SIZE_PER_SCATTER;
|
| -
|
| - sgreqSize = sizeof(HIF_SCATTER_REQ) +
|
| +
|
| + 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 */
|
| + /* 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;
|
| + 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 */
|
| + /* store the structure in the private area */
|
| pReq->HIFPrivate[0] = pVirtualInfo;
|
| /* we emulate a DMA bounce interface */
|
| pReq->ScatterMethod = HIF_SCATTER_DMA_BOUNCE;
|
| @@ -728,115 +789,126 @@ static A_STATUS DevSetupVirtualScatterSupport(AR6K_DEVICE *pDev)
|
| /* free request to the list */
|
| DevFreeScatterReq((HIF_DEVICE *)pDev,pReq);
|
| }
|
| -
|
| +
|
| if (A_FAILED(status)) {
|
| - DevCleanupVirtualScatterSupport(pDev);
|
| - } else {
|
| + DevCleanupVirtualScatterSupport(pDev);
|
| + } else {
|
| pDev->HifScatterInfo.pAllocateReqFunc = DevAllocScatterReq;
|
| pDev->HifScatterInfo.pFreeReqFunc = DevFreeScatterReq;
|
| - pDev->HifScatterInfo.pReadWriteScatterFunc = DevReadWriteScatter;
|
| - pDev->HifScatterInfo.MaxScatterEntries = AR6K_SCATTER_ENTRIES_PER_REQ;
|
| - pDev->HifScatterInfo.MaxTransferSizePerScatterReq = AR6K_MAX_TRANSFER_SIZE_PER_SCATTER;
|
| - pDev->ScatterIsVirtual = TRUE;
|
| - }
|
| -
|
| - return status;
|
| + 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 DevSetupMsgBundling(AR6K_DEVICE *pDev, int MaxMsgsPerTransfer)
|
| {
|
| - A_STATUS status;
|
| -
|
| + A_STATUS status;
|
| +
|
| if (pDev->MailBoxInfo.Flags & HIF_MBOX_FLAG_NO_BUNDLING) {
|
| - AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("HIF requires bundling disabled\n"));
|
| - return A_ENOTSUP;
|
| + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("HIF requires bundling disabled\n"));
|
| + return A_ENOTSUP;
|
| }
|
| -
|
| - status = HIFConfigureDevice(pDev->HIFDevice,
|
| +
|
| + status = HIFConfigureDevice(pDev->HIFDevice,
|
| HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT,
|
| - &pDev->HifScatterInfo,
|
| + &pDev->HifScatterInfo,
|
| sizeof(pDev->HifScatterInfo));
|
|
|
| if (A_FAILED(status)) {
|
| AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
|
| ("AR6K: ** HIF layer does not support scatter requests (%d) \n",status));
|
| -
|
| +
|
| /* we can try to use a virtual DMA scatter mechanism using legacy HIFReadWrite() */
|
| - status = DevSetupVirtualScatterSupport(pDev);
|
| -
|
| + status = DevSetupVirtualScatterSupport(pDev);
|
| +
|
| if (A_SUCCESS(status)) {
|
| AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
|
| ("AR6K: virtual scatter transfers enabled (max scatter items:%d: maxlen:%d) \n",
|
| - DEV_GET_MAX_MSG_PER_BUNDLE(pDev), DEV_GET_MAX_BUNDLE_LENGTH(pDev)));
|
| - }
|
| -
|
| + DEV_GET_MAX_MSG_PER_BUNDLE(pDev), DEV_GET_MAX_BUNDLE_LENGTH(pDev)));
|
| + }
|
| +
|
| } else {
|
| AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
|
| ("AR6K: HIF layer supports scatter requests (max scatter items:%d: maxlen:%d) \n",
|
| - DEV_GET_MAX_MSG_PER_BUNDLE(pDev), DEV_GET_MAX_BUNDLE_LENGTH(pDev)));
|
| + DEV_GET_MAX_MSG_PER_BUNDLE(pDev), DEV_GET_MAX_BUNDLE_LENGTH(pDev)));
|
| }
|
| -
|
| +
|
| if (A_SUCCESS(status)) {
|
| /* for the recv path, the maximum number of bytes per recv bundle is just limited
|
| * by the maximum transfer size at the HIF layer */
|
| pDev->MaxRecvBundleSize = pDev->HifScatterInfo.MaxTransferSizePerScatterReq;
|
| -
|
| - /* for the send path, the max transfer size is limited by the existence and size of
|
| - * the extended mailbox address range */
|
| - if (pDev->MailBoxInfo.MboxProp[0].ExtendedAddress != 0) {
|
| - pDev->MaxSendBundleSize = pDev->MailBoxInfo.MboxProp[0].ExtendedSize;
|
| +
|
| + if (pDev->MailBoxInfo.MboxBusIFType == MBOX_BUS_IF_SPI) {
|
| + AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6K : SPI bus requires TX bundling disabled\n"));
|
| + pDev->MaxSendBundleSize = 0;
|
| } else {
|
| - /* legacy */
|
| - pDev->MaxSendBundleSize = AR6K_LEGACY_MAX_WRITE_LENGTH;
|
| - }
|
| -
|
| - if (pDev->MaxSendBundleSize > pDev->HifScatterInfo.MaxTransferSizePerScatterReq) {
|
| - /* limit send bundle size to what the HIF can support for scatter requests */
|
| - pDev->MaxSendBundleSize = pDev->HifScatterInfo.MaxTransferSizePerScatterReq;
|
| + /* for the send path, the max transfer size is limited by the existence and size of
|
| + * the extended mailbox address range */
|
| + if (pDev->MailBoxInfo.MboxProp[0].ExtendedAddress != 0) {
|
| + pDev->MaxSendBundleSize = pDev->MailBoxInfo.MboxProp[0].ExtendedSize;
|
| + } else {
|
| + /* legacy */
|
| + pDev->MaxSendBundleSize = AR6K_LEGACY_MAX_WRITE_LENGTH;
|
| + }
|
| +
|
| + if (pDev->MaxSendBundleSize > pDev->HifScatterInfo.MaxTransferSizePerScatterReq) {
|
| + /* limit send bundle size to what the HIF can support for scatter requests */
|
| + pDev->MaxSendBundleSize = pDev->HifScatterInfo.MaxTransferSizePerScatterReq;
|
| + }
|
| }
|
| -
|
| +
|
| AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
|
| ("AR6K: max recv: %d max send: %d \n",
|
| - DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev), DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev)));
|
| -
|
| - }
|
| - return status;
|
| + DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev), DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev)));
|
| +
|
| + }
|
| + return status;
|
| }
|
|
|
| -A_STATUS DevSubmitScatterRequest(AR6K_DEVICE *pDev, HIF_SCATTER_REQ *pScatterReq, A_BOOL Read, A_BOOL Async)
|
| -{
|
| +A_STATUS DevSubmitScatterRequest(AR6K_DEVICE *pDev, HIF_SCATTER_REQ *pScatterReq, A_BOOL Read, A_BOOL Async)
|
| +{
|
| A_STATUS status;
|
| -
|
| +
|
| if (Read) {
|
| /* read operation */
|
| pScatterReq->Request = (Async) ? HIF_RD_ASYNC_BLOCK_FIX : HIF_RD_SYNC_BLOCK_FIX;
|
| - pScatterReq->Address = pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX];
|
| - A_ASSERT(pScatterReq->TotalLength <= (A_UINT32)DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev));
|
| + pScatterReq->Address = pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX];
|
| + A_ASSERT(pScatterReq->TotalLength <= (A_UINT32)DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev));
|
| } else {
|
| A_UINT32 mailboxWidth;
|
| -
|
| +
|
| /* write operation */
|
| pScatterReq->Request = (Async) ? HIF_WR_ASYNC_BLOCK_INC : HIF_WR_SYNC_BLOCK_INC;
|
| - A_ASSERT(pScatterReq->TotalLength <= (A_UINT32)DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev));
|
| + A_ASSERT(pScatterReq->TotalLength <= (A_UINT32)DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev));
|
| if (pScatterReq->TotalLength > AR6K_LEGACY_MAX_WRITE_LENGTH) {
|
| /* for large writes use the extended address */
|
| - pScatterReq->Address = pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedAddress;
|
| + pScatterReq->Address = pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedAddress;
|
| mailboxWidth = pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedSize;
|
| } else {
|
| - pScatterReq->Address = pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX];
|
| - mailboxWidth = AR6K_LEGACY_MAX_WRITE_LENGTH;
|
| + pScatterReq->Address = pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX];
|
| + mailboxWidth = AR6K_LEGACY_MAX_WRITE_LENGTH;
|
| }
|
| -
|
| +
|
| if (!pDev->ScatterIsVirtual) {
|
| /* we are passing this scatter list down to the HIF layer' scatter request handler, fixup the address
|
| * so that the last byte falls on the EOM, we do this for those HIFs that support the
|
| * scatter API */
|
| - pScatterReq->Address += (mailboxWidth - pScatterReq->TotalLength);
|
| + pScatterReq->Address += (mailboxWidth - pScatterReq->TotalLength);
|
| }
|
| -
|
| +
|
| }
|
| -
|
| +
|
| AR_DEBUG_PRINTF(ATH_DEBUG_RECV | ATH_DEBUG_SEND,
|
| ("DevSubmitScatterRequest, Entries: %d, Total Length: %d Mbox:0x%X (mode: %s : %s)\n",
|
| pScatterReq->ValidScatterEntries,
|
| @@ -844,30 +916,30 @@ A_STATUS DevSubmitScatterRequest(AR6K_DEVICE *pDev, HIF_SCATTER_REQ *pScatterReq
|
| pScatterReq->Address,
|
| Async ? "ASYNC" : "SYNC",
|
| (Read) ? "RD" : "WR"));
|
| -
|
| +
|
| status = DEV_PREPARE_SCATTER_OPERATION(pScatterReq);
|
| -
|
| +
|
| if (A_FAILED(status)) {
|
| if (Async) {
|
| pScatterReq->CompletionStatus = status;
|
| pScatterReq->CompletionRoutine(pScatterReq);
|
| - return A_OK;
|
| + return A_OK;
|
| }
|
| - return status;
|
| + return status;
|
| }
|
| -
|
| +
|
| status = pDev->HifScatterInfo.pReadWriteScatterFunc(pDev->ScatterIsVirtual ? pDev : pDev->HIFDevice,
|
| - pScatterReq);
|
| + pScatterReq);
|
| if (!Async) {
|
| /* in sync mode, we can touch the scatter request */
|
| pScatterReq->CompletionStatus = status;
|
| - DEV_FINISH_SCATTER_OPERATION(pScatterReq);
|
| + DEV_FINISH_SCATTER_OPERATION(pScatterReq);
|
| } else {
|
| if (status == A_PENDING) {
|
| - status = A_OK;
|
| - }
|
| + status = A_OK;
|
| + }
|
| }
|
| -
|
| +
|
| return status;
|
| }
|
|
|
|
|