summaryrefslogtreecommitdiffstats
path: root/target/linux/s3c24xx/files-2.6.30/drivers/ar6000/miscdrv
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/s3c24xx/files-2.6.30/drivers/ar6000/miscdrv')
-rw-r--r--target/linux/s3c24xx/files-2.6.30/drivers/ar6000/miscdrv/common_drv.c467
-rw-r--r--target/linux/s3c24xx/files-2.6.30/drivers/ar6000/miscdrv/credit_dist.c346
2 files changed, 0 insertions, 813 deletions
diff --git a/target/linux/s3c24xx/files-2.6.30/drivers/ar6000/miscdrv/common_drv.c b/target/linux/s3c24xx/files-2.6.30/drivers/ar6000/miscdrv/common_drv.c
deleted file mode 100644
index 4f12734666..0000000000
--- a/target/linux/s3c24xx/files-2.6.30/drivers/ar6000/miscdrv/common_drv.c
+++ /dev/null
@@ -1,467 +0,0 @@
-
-/*
- *
- * Copyright (c) 2004-2007 Atheros Communications Inc.
- * 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.
- *
- *
- *
- */
-
-#include "a_config.h"
-#include "athdefs.h"
-#include "a_types.h"
-#include "AR6Khwreg.h"
-#include "targaddrs.h"
-#include "a_osapi.h"
-#include "hif.h"
-#include "htc_api.h"
-#include "bmi.h"
-#include "bmi_msg.h"
-#include "common_drv.h"
-#include "a_debug.h"
-#include "targaddrs.h"
-
-#define HOST_INTEREST_ITEM_ADDRESS(target, item) \
-(((TargetType) == TARGET_TYPE_AR6001) ? \
- AR6001_HOST_INTEREST_ITEM_ADDRESS(item) : \
- AR6002_HOST_INTEREST_ITEM_ADDRESS(item))
-
-
-/* Compile the 4BYTE version of the window register setup routine,
- * This mitigates host interconnect issues with non-4byte aligned bus requests, some
- * interconnects use bus adapters that impose strict limitations.
- * Since diag window access is not intended for performance critical operations, the 4byte mode should
- * be satisfactory even though it generates 4X the bus activity. */
-
-#ifdef USE_4BYTE_REGISTER_ACCESS
-
- /* set the window address register (using 4-byte register access ). */
-A_STATUS ar6000_SetAddressWindowRegister(HIF_DEVICE *hifDevice, A_UINT32 RegisterAddr, A_UINT32 Address)
-{
- A_STATUS status;
- A_UINT8 addrValue[4];
- int i;
-
- /* write bytes 1,2,3 of the register to set the upper address bytes, the LSB is written
- * last to initiate the access cycle */
-
- for (i = 1; i <= 3; i++) {
- /* fill the buffer with the address byte value we want to hit 4 times*/
- addrValue[0] = ((A_UINT8 *)&Address)[i];
- addrValue[1] = addrValue[0];
- addrValue[2] = addrValue[0];
- addrValue[3] = addrValue[0];
-
- /* hit each byte of the register address with a 4-byte write operation to the same address,
- * this is a harmless operation */
- status = HIFReadWrite(hifDevice,
- RegisterAddr+i,
- addrValue,
- 4,
- HIF_WR_SYNC_BYTE_FIX,
- NULL);
- if (status != A_OK) {
- break;
- }
- }
-
- if (status != A_OK) {
- AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write initial bytes of 0x%x to window reg: 0x%X \n",
- RegisterAddr, Address));
- return status;
- }
-
- /* write the address register again, this time write the whole 4-byte value.
- * The effect here is that the LSB write causes the cycle to start, the extra
- * 3 byte write to bytes 1,2,3 has no effect since we are writing the same values again */
- status = HIFReadWrite(hifDevice,
- RegisterAddr,
- (A_UCHAR *)(&Address),
- 4,
- HIF_WR_SYNC_BYTE_INC,
- NULL);
-
- if (status != A_OK) {
- AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to window reg: 0x%X \n",
- RegisterAddr, Address));
- return status;
- }
-
- return A_OK;
-
-
-
-}
-
-
-#else
-
- /* set the window address register */
-A_STATUS ar6000_SetAddressWindowRegister(HIF_DEVICE *hifDevice, A_UINT32 RegisterAddr, A_UINT32 Address)
-{
- A_STATUS status;
-
- /* write bytes 1,2,3 of the register to set the upper address bytes, the LSB is written
- * last to initiate the access cycle */
- status = HIFReadWrite(hifDevice,
- RegisterAddr+1, /* write upper 3 bytes */
- ((A_UCHAR *)(&Address))+1,
- sizeof(A_UINT32)-1,
- HIF_WR_SYNC_BYTE_INC,
- NULL);
-
- if (status != A_OK) {
- AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write initial bytes of 0x%x to window reg: 0x%X \n",
- RegisterAddr, Address));
- return status;
- }
-
- /* write the LSB of the register, this initiates the operation */
- status = HIFReadWrite(hifDevice,
- RegisterAddr,
- (A_UCHAR *)(&Address),
- sizeof(A_UINT8),
- HIF_WR_SYNC_BYTE_INC,
- NULL);
-
- if (status != A_OK) {
- AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to window reg: 0x%X \n",
- RegisterAddr, Address));
- return status;
- }
-
- return A_OK;
-}
-
-#endif
-
-/*
- * Read from the AR6000 through its diagnostic window.
- * No cooperation from the Target is required for this.
- */
-A_STATUS
-ar6000_ReadRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data)
-{
- A_STATUS status;
-
- /* set window register to start read cycle */
- status = ar6000_SetAddressWindowRegister(hifDevice,
- WINDOW_READ_ADDR_ADDRESS,
- *address);
-
- if (status != A_OK) {
- return status;
- }
-
- /* read the data */
- status = HIFReadWrite(hifDevice,
- WINDOW_DATA_ADDRESS,
- (A_UCHAR *)data,
- sizeof(A_UINT32),
- HIF_RD_SYNC_BYTE_INC,
- NULL);
- if (status != A_OK) {
- AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot read from WINDOW_DATA_ADDRESS\n"));
- return status;
- }
-
- return status;
-}
-
-
-/*
- * Write to the AR6000 through its diagnostic window.
- * No cooperation from the Target is required for this.
- */
-A_STATUS
-ar6000_WriteRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data)
-{
- A_STATUS status;
-
- /* set write data */
- status = HIFReadWrite(hifDevice,
- WINDOW_DATA_ADDRESS,
- (A_UCHAR *)data,
- sizeof(A_UINT32),
- HIF_WR_SYNC_BYTE_INC,
- NULL);
- if (status != A_OK) {
- AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to WINDOW_DATA_ADDRESS\n", *data));
- return status;
- }
-
- /* set window register, which starts the write cycle */
- return ar6000_SetAddressWindowRegister(hifDevice,
- WINDOW_WRITE_ADDR_ADDRESS,
- *address);
-}
-
-A_STATUS
-ar6000_ReadDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,
- A_UCHAR *data, A_UINT32 length)
-{
- A_UINT32 count;
- A_STATUS status = A_OK;
-
- for (count = 0; count < length; count += 4, address += 4) {
- if ((status = ar6000_ReadRegDiag(hifDevice, &address,
- (A_UINT32 *)&data[count])) != A_OK)
- {
- break;
- }
- }
-
- return status;
-}
-
-A_STATUS
-ar6000_WriteDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,
- A_UCHAR *data, A_UINT32 length)
-{
- A_UINT32 count;
- A_STATUS status = A_OK;
-
- for (count = 0; count < length; count += 4, address += 4) {
- if ((status = ar6000_WriteRegDiag(hifDevice, &address,
- (A_UINT32 *)&data[count])) != A_OK)
- {
- break;
- }
- }
-
- return status;
-}
-
-A_STATUS
-ar6000_reset_device_skipflash(HIF_DEVICE *hifDevice)
-{
- int i;
- struct forceROM_s {
- A_UINT32 addr;
- A_UINT32 data;
- };
- struct forceROM_s *ForceROM;
- int szForceROM;
- A_UINT32 instruction;
-
- static struct forceROM_s ForceROM_REV2[] = {
- /* NB: This works for old REV2 ROM (old). */
- {0x00001ff0, 0x175b0027}, /* jump instruction at 0xa0001ff0 */
- {0x00001ff4, 0x00000000}, /* nop instruction at 0xa0001ff4 */
-
- {MC_REMAP_TARGET_ADDRESS, 0x00001ff0}, /* remap to 0xa0001ff0 */
- {MC_REMAP_COMPARE_ADDRESS, 0x01000040},/* ...from 0xbfc00040 */
- {MC_REMAP_SIZE_ADDRESS, 0x00000000}, /* ...1 cache line */
- {MC_REMAP_VALID_ADDRESS, 0x00000001}, /* ...remap is valid */
-
- {LOCAL_COUNT_ADDRESS+0x10, 0}, /* clear BMI credit counter */
-
- {RESET_CONTROL_ADDRESS, RESET_CONTROL_WARM_RST_MASK},
- };
-
- static struct forceROM_s ForceROM_NEW[] = {
- /* NB: This works for AR6000 ROM REV3 and beyond. */
- {LOCAL_SCRATCH_ADDRESS, AR6K_OPTION_IGNORE_FLASH},
- {LOCAL_COUNT_ADDRESS+0x10, 0}, /* clear BMI credit counter */
- {RESET_CONTROL_ADDRESS, RESET_CONTROL_WARM_RST_MASK},
- };
-
- /*
- * Examine a semi-arbitrary instruction that's different
- * in REV2 and other revisions.
- * NB: If a Host port does not require simultaneous support
- * for multiple revisions of Target ROM, this code can be elided.
- */
- (void)ar6000_ReadDataDiag(hifDevice, 0x01000040,
- (A_UCHAR *)&instruction, 4);
-
- AR_DEBUG_PRINTF(ATH_LOG_ERR, ("instruction=0x%x\n", instruction));
-
- if (instruction == 0x3c1aa200) {
- /* It's an old ROM */
- ForceROM = ForceROM_REV2;
- szForceROM = sizeof(ForceROM_REV2)/sizeof(*ForceROM);
- AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Using OLD method\n"));
- } else {
- ForceROM = ForceROM_NEW;
- szForceROM = sizeof(ForceROM_NEW)/sizeof(*ForceROM);
- AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Using NEW method\n"));
- }
-
- AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Force Target to execute from ROM....\n"));
- for (i = 0; i < szForceROM; i++)
- {
- if (ar6000_WriteRegDiag(hifDevice,
- &ForceROM[i].addr,
- &ForceROM[i].data) != A_OK)
- {
- AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot force Target to execute ROM!\n"));
- return A_ERROR;
- }
- }
-
- msleep(50); /* delay to allow dragon to come to BMI phase */
- return A_OK;
-}
-
-/* reset device */
-A_STATUS ar6000_reset_device(HIF_DEVICE *hifDevice, A_UINT32 TargetType)
-{
-
-#if !defined(DWSIM)
- A_STATUS status = A_OK;
- A_UINT32 address;
- A_UINT32 data;
-
- do {
-
- // address = RESET_CONTROL_ADDRESS;
- data = RESET_CONTROL_COLD_RST_MASK;
-
- /* Hardcode the address of RESET_CONTROL_ADDRESS based on the target type */
- if (TargetType == TARGET_TYPE_AR6001) {
- address = 0x0C000000;
- } else {
- if (TargetType == TARGET_TYPE_AR6002) {
- address = 0x00004000;
- } else {
- A_ASSERT(0);
- }
- }
-
- status = ar6000_WriteRegDiag(hifDevice, &address, &data);
-
- if (A_FAILED(status)) {
- break;
- }
-
- /*
- * Read back the RESET CAUSE register to ensure that the cold reset
- * went through.
- */
- msleep(2000); /* 2 second delay to allow things to settle down */
-
-
- // address = RESET_CAUSE_ADDRESS;
- /* Hardcode the address of RESET_CAUSE_ADDRESS based on the target type */
- if (TargetType == TARGET_TYPE_AR6001) {
- address = 0x0C0000CC;
- } else {
- if (TargetType == TARGET_TYPE_AR6002) {
- address = 0x000040C0;
- } else {
- A_ASSERT(0);
- }
- }
-
- data = 0;
- status = ar6000_ReadRegDiag(hifDevice, &address, &data);
-
- if (A_FAILED(status)) {
- break;
- }
-
- AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Reset Cause readback: 0x%X \n",data));
- data &= RESET_CAUSE_LAST_MASK;
- if (data != 2) {
- AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Unable to cold reset the target \n"));
- }
-
- } while (FALSE);
-
- if (A_FAILED(status)) {
- AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Failed to reset target \n"));
- }
-#endif
- return A_OK;
-}
-
-#define REG_DUMP_COUNT_AR6001 38 /* WORDs, derived from AR6001_regdump.h */
-#define REG_DUMP_COUNT_AR6002 32 /* WORDs, derived from AR6002_regdump.h */
-
-
-#if REG_DUMP_COUNT_AR6001 <= REG_DUMP_COUNT_AR6002
-#define REGISTER_DUMP_LEN_MAX REG_DUMP_COUNT_AR6002
-#else
-#define REGISTER_DUMP_LEN_MAX REG_DUMP_COUNT_AR6001
-#endif
-
-void ar6000_dump_target_assert_info(HIF_DEVICE *hifDevice, A_UINT32 TargetType)
-{
- A_UINT32 address;
- A_UINT32 regDumpArea = 0;
- A_STATUS status;
- A_UINT32 regDumpValues[REGISTER_DUMP_LEN_MAX];
- A_UINT32 regDumpCount = 0;
- A_UINT32 i;
-
- do {
-
- /* the reg dump pointer is copied to the host interest area */
- address = HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_failure_state);
-
- if (TargetType == TARGET_TYPE_AR6001) {
- /* for AR6001, this is a fixed location because the ptr is actually stuck in cache,
- * this may be fixed in later firmware versions */
- address = 0x18a0;
- regDumpCount = REG_DUMP_COUNT_AR6001;
-
- } else if (TargetType == TARGET_TYPE_AR6002) {
-
- regDumpCount = REG_DUMP_COUNT_AR6002;
-
- } else {
- A_ASSERT(0);
- }
-
- /* read RAM location through diagnostic window */
- status = ar6000_ReadRegDiag(hifDevice, &address, &regDumpArea);
-
- if (A_FAILED(status)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get ptr to register dump area \n"));
- break;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Location of register dump data: 0x%X \n",regDumpArea));
-
- if (regDumpArea == 0) {
- /* no reg dump */
- break;
- }
-
- if (TargetType == TARGET_TYPE_AR6001) {
- regDumpArea &= 0x0FFFFFFF; /* convert to physical address in target memory */
- }
-
- /* fetch register dump data */
- status = ar6000_ReadDataDiag(hifDevice,
- regDumpArea,
- (A_UCHAR *)&regDumpValues[0],
- regDumpCount * (sizeof(A_UINT32)));
-
- if (A_FAILED(status)) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get register dump \n"));
- break;
- }
-
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Register Dump: \n"));
-
- for (i = 0; i < regDumpCount; i++) {
- AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" %d : 0x%8.8X \n",i, regDumpValues[i]));
- }
-
- } while (FALSE);
-
-}
-
diff --git a/target/linux/s3c24xx/files-2.6.30/drivers/ar6000/miscdrv/credit_dist.c b/target/linux/s3c24xx/files-2.6.30/drivers/ar6000/miscdrv/credit_dist.c
deleted file mode 100644
index 8d37d62720..0000000000
--- a/target/linux/s3c24xx/files-2.6.30/drivers/ar6000/miscdrv/credit_dist.c
+++ /dev/null
@@ -1,346 +0,0 @@
-
-/*
- *
- * Copyright (c) 2004-2007 Atheros Communications Inc.
- * 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.
- *
- *
- *
- */
-
-#include "a_config.h"
-#include "athdefs.h"
-#include "a_types.h"
-#include "a_osapi.h"
-#include "a_debug.h"
-#include "htc_api.h"
-#include "common_drv.h"
-
-/********* CREDIT DISTRIBUTION FUNCTIONS ******************************************/
-
-#define NO_VO_SERVICE 1 /* currently WMI only uses 3 data streams, so we leave VO service inactive */
-
-#ifdef NO_VO_SERVICE
-#define DATA_SVCS_USED 3
-#else
-#define DATA_SVCS_USED 4
-#endif
-
-static void RedistributeCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
- HTC_ENDPOINT_CREDIT_DIST *pEPDistList);
-
-static void SeekCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
- HTC_ENDPOINT_CREDIT_DIST *pEPDistList);
-
-/* reduce an ep's credits back to a set limit */
-static INLINE void ReduceCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
- HTC_ENDPOINT_CREDIT_DIST *pEpDist,
- int Limit)
-{
- int credits;
-
- /* set the new limit */
- pEpDist->TxCreditsAssigned = Limit;
-
- if (pEpDist->TxCredits <= Limit) {
- return;
- }
-
- /* figure out how much to take away */
- credits = pEpDist->TxCredits - Limit;
- /* take them away */
- pEpDist->TxCredits -= credits;
- pCredInfo->CurrentFreeCredits += credits;
-}
-
-/* give an endpoint some credits from the free credit pool */
-#define GiveCredits(pCredInfo,pEpDist,credits) \
-{ \
- (pEpDist)->TxCredits += (credits); \
- (pEpDist)->TxCreditsAssigned += (credits); \
- (pCredInfo)->CurrentFreeCredits -= (credits); \
-}
-
-
-/* default credit init callback.
- * This function is called in the context of HTCStart() to setup initial (application-specific)
- * credit distributions */
-static void ar6000_credit_init(void *Context,
- HTC_ENDPOINT_CREDIT_DIST *pEPList,
- int TotalCredits)
-{
- HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
- int count;
- COMMON_CREDIT_STATE_INFO *pCredInfo = (COMMON_CREDIT_STATE_INFO *)Context;
-
- pCredInfo->CurrentFreeCredits = TotalCredits;
- pCredInfo->TotalAvailableCredits = TotalCredits;
-
- pCurEpDist = pEPList;
-
- /* run through the list and initialize */
- while (pCurEpDist != NULL) {
-
- /* set minimums for each endpoint */
- pCurEpDist->TxCreditsMin = pCurEpDist->TxCreditsPerMaxMsg;
-
- if (pCurEpDist->ServiceID == WMI_CONTROL_SVC) {
- /* give control service some credits */
- GiveCredits(pCredInfo,pCurEpDist,pCurEpDist->TxCreditsMin);
- /* control service is always marked active, it never goes inactive EVER */
- SET_EP_ACTIVE(pCurEpDist);
- } else if (pCurEpDist->ServiceID == WMI_DATA_BK_SVC) {
- /* this is the lowest priority data endpoint, save this off for easy access */
- pCredInfo->pLowestPriEpDist = pCurEpDist;
- }
-
- /* Streams have to be created (explicit | implicit)for all kinds
- * of traffic. BE endpoints are also inactive in the beginning.
- * When BE traffic starts it creates implicit streams that
- * redistributes credits.
- */
-
- /* note, all other endpoints have minimums set but are initially given NO credits.
- * Credits will be distributed as traffic activity demands */
- pCurEpDist = pCurEpDist->pNext;
- }
-
- if (pCredInfo->CurrentFreeCredits <= 0) {
- AR_DEBUG_PRINTF(ATH_LOG_INF, ("Not enough credits (%d) to do credit distributions \n", TotalCredits));
- A_ASSERT(FALSE);
- return;
- }
-
- /* reset list */
- pCurEpDist = pEPList;
- /* now run through the list and set max operating credit limits for everyone */
- while (pCurEpDist != NULL) {
- if (pCurEpDist->ServiceID == WMI_CONTROL_SVC) {
- /* control service max is just 1 max message */
- pCurEpDist->TxCreditsNorm = pCurEpDist->TxCreditsPerMaxMsg;
- } else {
- /* for the remaining data endpoints, we assume that each TxCreditsPerMaxMsg are
- * the same.
- * We use a simple calculation here, we take the remaining credits and
- * determine how many max messages this can cover and then set each endpoint's
- * normal value equal to half this amount.
- * */
- count = (pCredInfo->CurrentFreeCredits/pCurEpDist->TxCreditsPerMaxMsg) * pCurEpDist->TxCreditsPerMaxMsg;
- count = count >> 1;
- count = max(count,pCurEpDist->TxCreditsPerMaxMsg);
- /* set normal */
- pCurEpDist->TxCreditsNorm = count;
-
- }
- pCurEpDist = pCurEpDist->pNext;
- }
-
-}
-
-
-/* default credit distribution callback
- * This callback is invoked whenever endpoints require credit distributions.
- * A lock is held while this function is invoked, this function shall NOT block.
- * The pEPDistList is a list of distribution structures in prioritized order as
- * defined by the call to the HTCSetCreditDistribution() api.
- *
- */
-static void ar6000_credit_distribute(void *Context,
- HTC_ENDPOINT_CREDIT_DIST *pEPDistList,
- HTC_CREDIT_DIST_REASON Reason)
-{
- HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
- COMMON_CREDIT_STATE_INFO *pCredInfo = (COMMON_CREDIT_STATE_INFO *)Context;
-
- switch (Reason) {
- case HTC_CREDIT_DIST_SEND_COMPLETE :
- pCurEpDist = pEPDistList;
- /* we are given the start of the endpoint distribution list.
- * There may be one or more endpoints to service.
- * Run through the list and distribute credits */
- while (pCurEpDist != NULL) {
-
- if (pCurEpDist->TxCreditsToDist > 0) {
- /* return the credits back to the endpoint */
- pCurEpDist->TxCredits += pCurEpDist->TxCreditsToDist;
- /* always zero out when we are done */
- pCurEpDist->TxCreditsToDist = 0;
-
- if (pCurEpDist->TxCredits > pCurEpDist->TxCreditsAssigned) {
- /* reduce to the assigned limit, previous credit reductions
- * could have caused the limit to change */
- ReduceCredits(pCredInfo, pCurEpDist, pCurEpDist->TxCreditsAssigned);
- }
-
- if (pCurEpDist->TxCredits > pCurEpDist->TxCreditsNorm) {
- /* oversubscribed endpoints need to reduce back to normal */
- ReduceCredits(pCredInfo, pCurEpDist, pCurEpDist->TxCreditsNorm);
- }
- }
-
- pCurEpDist = pCurEpDist->pNext;
- }
-
- A_ASSERT(pCredInfo->CurrentFreeCredits <= pCredInfo->TotalAvailableCredits);
-
- break;
-
- case HTC_CREDIT_DIST_ACTIVITY_CHANGE :
- RedistributeCredits(pCredInfo,pEPDistList);
- break;
- case HTC_CREDIT_DIST_SEEK_CREDITS :
- SeekCredits(pCredInfo,pEPDistList);
- break;
- case HTC_DUMP_CREDIT_STATE :
- AR_DEBUG_PRINTF(ATH_LOG_INF, ("Credit Distribution, total : %d, free : %d\n",
- pCredInfo->TotalAvailableCredits, pCredInfo->CurrentFreeCredits));
- break;
- default:
- break;
-
- }
-
-}
-
-/* redistribute credits based on activity change */
-static void RedistributeCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
- HTC_ENDPOINT_CREDIT_DIST *pEPDistList)
-{
- HTC_ENDPOINT_CREDIT_DIST *pCurEpDist = pEPDistList;
-
- /* walk through the list and remove credits from inactive endpoints */
- while (pCurEpDist != NULL) {
-
- if (pCurEpDist->ServiceID != WMI_CONTROL_SVC) {
- if (!IS_EP_ACTIVE(pCurEpDist)) {
- /* EP is inactive, reduce credits back to zero */
- ReduceCredits(pCredInfo, pCurEpDist, 0);
- }
- }
-
- /* NOTE in the active case, we do not need to do anything further,
- * when an EP goes active and needs credits, HTC will call into
- * our distribution function using a reason code of HTC_CREDIT_DIST_SEEK_CREDITS */
-
- pCurEpDist = pCurEpDist->pNext;
- }
-
- A_ASSERT(pCredInfo->CurrentFreeCredits <= pCredInfo->TotalAvailableCredits);
-
-}
-
-/* HTC has an endpoint that needs credits, pEPDist is the endpoint in question */
-static void SeekCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
- HTC_ENDPOINT_CREDIT_DIST *pEPDist)
-{
- HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
- int credits = 0;
- int need;
-
- do {
-
- if (pEPDist->ServiceID == WMI_CONTROL_SVC) {
- /* we never oversubscribe on the control service, this is not
- * a high performance path and the target never holds onto control
- * credits for too long */
- break;
- }
-
- /* for all other services, we follow a simple algorithm of
- * 1. checking the free pool for credits
- * 2. checking lower priority endpoints for credits to take */
-
- if (pCredInfo->CurrentFreeCredits >= 2 * pEPDist->TxCreditsSeek) {
- /* try to give more credits than it needs */
- credits = 2 * pEPDist->TxCreditsSeek;
- } else {
- /* give what we can */
- credits = min(pCredInfo->CurrentFreeCredits,pEPDist->TxCreditsSeek);
- }
-
- if (credits >= pEPDist->TxCreditsSeek) {
- /* we found some to fullfill the seek request */
- break;
- }
-
- /* we don't have enough in the free pool, try taking away from lower priority services
- *
- * The rule for taking away credits:
- * 1. Only take from lower priority endpoints
- * 2. Only take what is allocated above the minimum (never starve an endpoint completely)
- * 3. Only take what you need.
- *
- * */
-
- /* starting at the lowest priority */
- pCurEpDist = pCredInfo->pLowestPriEpDist;
-
- /* work backwards until we hit the endpoint again */
- while (pCurEpDist != pEPDist) {
- /* calculate how many we need so far */
- need = pEPDist->TxCreditsSeek - pCredInfo->CurrentFreeCredits;
-
- if ((pCurEpDist->TxCreditsAssigned - need) > pCurEpDist->TxCreditsMin) {
- /* the current one has been allocated more than it's minimum and it
- * has enough credits assigned above it's minimum to fullfill our need
- * try to take away just enough to fullfill our need */
- ReduceCredits(pCredInfo,
- pCurEpDist,
- pCurEpDist->TxCreditsAssigned - need);
-
- if (pCredInfo->CurrentFreeCredits >= pEPDist->TxCreditsSeek) {
- /* we have enough */
- break;
- }
- }
-
- pCurEpDist = pCurEpDist->pPrev;
- }
-
- /* return what we can get */
- credits = min(pCredInfo->CurrentFreeCredits,pEPDist->TxCreditsSeek);
-
- } while (FALSE);
-
- /* did we find some credits? */
- if (credits) {
- /* give what we can */
- GiveCredits(pCredInfo, pEPDist, credits);
- }
-
-}
-
-/* initialize and setup credit distribution */
-A_STATUS ar6000_setup_credit_dist(HTC_HANDLE HTCHandle, COMMON_CREDIT_STATE_INFO *pCredInfo)
-{
- HTC_SERVICE_ID servicepriority[5];
-
- A_MEMZERO(pCredInfo,sizeof(COMMON_CREDIT_STATE_INFO));
-
- servicepriority[0] = WMI_CONTROL_SVC; /* highest */
- servicepriority[1] = WMI_DATA_VO_SVC;
- servicepriority[2] = WMI_DATA_VI_SVC;
- servicepriority[3] = WMI_DATA_BE_SVC;
- servicepriority[4] = WMI_DATA_BK_SVC; /* lowest */
-
- /* set callbacks and priority list */
- HTCSetCreditDistribution(HTCHandle,
- pCredInfo,
- ar6000_credit_distribute,
- ar6000_credit_init,
- servicepriority,
- 5);
-
- return A_OK;
-}
-