Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(273)

Side by Side Diff: chromeos/drivers/ath6kl/miscdrv/credit_dist.c

Issue 646055: Atheros AR600x driver + build glue (Closed)
Patch Set: Created 10 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chromeos/drivers/ath6kl/miscdrv/common_drv.c ('k') | chromeos/drivers/ath6kl/miscdrv/makefile » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 //------------------------------------------------------------------------------
2 // <copyright file="credit_dist.c" company="Atheros">
3 // Copyright (c) 2004-2008 Atheros Corporation. All rights reserved.
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License version 2 as
7 // published by the Free Software Foundation;
8 //
9 // Software distributed under the License is distributed on an "AS
10 // IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11 // implied. See the License for the specific language governing
12 // rights and limitations under the License.
13 //
14 //
15 //------------------------------------------------------------------------------
16 //==============================================================================
17 // Author(s): ="Atheros"
18 //==============================================================================
19 #include "a_config.h"
20 #include "athdefs.h"
21 #include "a_types.h"
22 #include "a_osapi.h"
23 #define ATH_MODULE_NAME misc
24 #include "a_debug.h"
25 #include "htc_api.h"
26 #include "common_drv.h"
27
28 /********* CREDIT DISTRIBUTION FUNCTIONS *************************************** ***/
29
30 #define NO_VO_SERVICE 1 /* currently WMI only uses 3 data streams, so we leave V O service inactive */
31
32 #ifdef NO_VO_SERVICE
33 #define DATA_SVCS_USED 3
34 #else
35 #define DATA_SVCS_USED 4
36 #endif
37
38 static void RedistributeCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
39 HTC_ENDPOINT_CREDIT_DIST *pEPDistList);
40
41 static void SeekCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
42 HTC_ENDPOINT_CREDIT_DIST *pEPDistList);
43
44 /* reduce an ep's credits back to a set limit */
45 static INLINE void ReduceCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
46 HTC_ENDPOINT_CREDIT_DIST *pEpDist,
47 int Limit)
48 {
49 int credits;
50
51 /* set the new limit */
52 pEpDist->TxCreditsAssigned = Limit;
53
54 if (pEpDist->TxCredits <= Limit) {
55 return;
56 }
57
58 /* figure out how much to take away */
59 credits = pEpDist->TxCredits - Limit;
60 /* take them away */
61 pEpDist->TxCredits -= credits;
62 pCredInfo->CurrentFreeCredits += credits;
63 }
64
65 /* give an endpoint some credits from the free credit pool */
66 #define GiveCredits(pCredInfo,pEpDist,credits) \
67 { \
68 (pEpDist)->TxCredits += (credits); \
69 (pEpDist)->TxCreditsAssigned += (credits); \
70 (pCredInfo)->CurrentFreeCredits -= (credits); \
71 }
72
73
74 /* default credit init callback.
75 * This function is called in the context of HTCStart() to setup initial (applic ation-specific)
76 * credit distributions */
77 static void ar6000_credit_init(void *Context,
78 HTC_ENDPOINT_CREDIT_DIST *pEPList,
79 int TotalCredits)
80 {
81 HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
82 int count;
83 COMMON_CREDIT_STATE_INFO *pCredInfo = (COMMON_CREDIT_STATE_INFO *)Context;
84
85 pCredInfo->CurrentFreeCredits = TotalCredits;
86 pCredInfo->TotalAvailableCredits = TotalCredits;
87
88 pCurEpDist = pEPList;
89
90 /* run through the list and initialize */
91 while (pCurEpDist != NULL) {
92
93 /* set minimums for each endpoint */
94 pCurEpDist->TxCreditsMin = pCurEpDist->TxCreditsPerMaxMsg;
95
96 if (pCurEpDist->ServiceID == WMI_CONTROL_SVC) {
97 /* give control service some credits */
98 GiveCredits(pCredInfo,pCurEpDist,pCurEpDist->TxCreditsMin);
99 /* control service is always marked active, it never goes inacti ve EVER */
100 SET_EP_ACTIVE(pCurEpDist);
101 } else if (pCurEpDist->ServiceID == WMI_DATA_BK_SVC) {
102 /* this is the lowest priority data endpoint, save this off for easy access */
103 pCredInfo->pLowestPriEpDist = pCurEpDist;
104 }
105
106 /* Streams have to be created (explicit | implicit)for all kinds
107 * of traffic. BE endpoints are also inactive in the beginning.
108 * When BE traffic starts it creates implicit streams that
109 * redistributes credits.
110 */
111
112 /* note, all other endpoints have minimums set but are initially given N O credits.
113 * Credits will be distributed as traffic activity demands */
114 pCurEpDist = pCurEpDist->pNext;
115 }
116
117 if (pCredInfo->CurrentFreeCredits <= 0) {
118 AR_DEBUG_PRINTF(ATH_LOG_INF, ("Not enough credits (%d) to do credit dist ributions \n", TotalCredits));
119 A_ASSERT(FALSE);
120 return;
121 }
122
123 /* reset list */
124 pCurEpDist = pEPList;
125 /* now run through the list and set max operating credit limits for ever yone */
126 while (pCurEpDist != NULL) {
127 if (pCurEpDist->ServiceID == WMI_CONTROL_SVC) {
128 /* control service max is just 1 max message */
129 pCurEpDist->TxCreditsNorm = pCurEpDist->TxCreditsPerMaxMsg;
130 } else {
131 /* for the remaining data endpoints, we assume that each TxCredi tsPerMaxMsg are
132 * the same.
133 * We use a simple calculation here, we take the remaining credi ts and
134 * determine how many max messages this can cover and then set e ach endpoint's
135 * normal value equal to 3/4 this amount.
136 * */
137 count = (pCredInfo->CurrentFreeCredits/pCurEpDist->TxCreditsPerMaxMs g) * pCurEpDist->TxCreditsPerMaxMsg;
138 count = (count * 3) >> 2;
139 count = max(count,pCurEpDist->TxCreditsPerMaxMsg);
140 /* set normal */
141 pCurEpDist->TxCreditsNorm = count;
142
143 }
144 pCurEpDist = pCurEpDist->pNext;
145 }
146
147 }
148
149
150 /* default credit distribution callback
151 * This callback is invoked whenever endpoints require credit distributions.
152 * A lock is held while this function is invoked, this function shall NOT block.
153 * The pEPDistList is a list of distribution structures in prioritized order as
154 * defined by the call to the HTCSetCreditDistribution() api.
155 *
156 */
157 static void ar6000_credit_distribute(void *Context,
158 HTC_ENDPOINT_CREDIT_DIST *pEPDistList,
159 HTC_CREDIT_DIST_REASON Reason)
160 {
161 HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
162 COMMON_CREDIT_STATE_INFO *pCredInfo = (COMMON_CREDIT_STATE_INFO *)Context;
163
164 switch (Reason) {
165 case HTC_CREDIT_DIST_SEND_COMPLETE :
166 pCurEpDist = pEPDistList;
167 /* we are given the start of the endpoint distribution list.
168 * There may be one or more endpoints to service.
169 * Run through the list and distribute credits */
170 while (pCurEpDist != NULL) {
171
172 if (pCurEpDist->TxCreditsToDist > 0) {
173 /* return the credits back to the endpoint */
174 pCurEpDist->TxCredits += pCurEpDist->TxCreditsToDist;
175 /* always zero out when we are done */
176 pCurEpDist->TxCreditsToDist = 0;
177
178 if (pCurEpDist->TxCredits > pCurEpDist->TxCreditsAssigned) {
179 /* reduce to the assigned limit, previous credit red uctions
180 * could have caused the limit to change */
181 ReduceCredits(pCredInfo, pCurEpDist, pCurEpDist->TxCredi tsAssigned);
182 }
183
184 if (pCurEpDist->TxCredits > pCurEpDist->TxCreditsNorm) {
185 /* oversubscribed endpoints need to reduce back to n ormal */
186 ReduceCredits(pCredInfo, pCurEpDist, pCurEpDist->TxCredi tsNorm);
187 }
188
189 if (!IS_EP_ACTIVE(pCurEpDist)) {
190 /* endpoint is inactive, now check for messages wait ing for credits */
191 if (pCurEpDist->TxQueueDepth == 0) {
192 /* EP is inactive and there are no pending messa ges,
193 * reduce credits back to zero to recover credit s */
194 ReduceCredits(pCredInfo, pCurEpDist, 0);
195 }
196 }
197 }
198
199 pCurEpDist = pCurEpDist->pNext;
200 }
201
202 break;
203
204 case HTC_CREDIT_DIST_ACTIVITY_CHANGE :
205 RedistributeCredits(pCredInfo,pEPDistList);
206 break;
207 case HTC_CREDIT_DIST_SEEK_CREDITS :
208 SeekCredits(pCredInfo,pEPDistList);
209 break;
210 case HTC_DUMP_CREDIT_STATE :
211 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Credit Distribution, total : %d, fr ee : %d\n",
212 pCredInf o->TotalAvailableCredits, pCredInfo->CurrentFreeCredits));
213 break;
214 default:
215 break;
216
217 }
218
219 /* sanity checks done after each distribution action */
220 A_ASSERT(pCredInfo->CurrentFreeCredits <= pCredInfo->TotalAvailableCredits);
221 A_ASSERT(pCredInfo->CurrentFreeCredits >= 0);
222
223 }
224
225 /* redistribute credits based on activity change */
226 static void RedistributeCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
227 HTC_ENDPOINT_CREDIT_DIST *pEPDistList)
228 {
229 HTC_ENDPOINT_CREDIT_DIST *pCurEpDist = pEPDistList;
230
231 /* walk through the list and remove credits from inactive endpoints */
232 while (pCurEpDist != NULL) {
233
234 if (pCurEpDist->ServiceID != WMI_CONTROL_SVC) {
235 if (!IS_EP_ACTIVE(pCurEpDist)) {
236 if (pCurEpDist->TxQueueDepth == 0) {
237 /* EP is inactive and there are no pending messages, red uce credits back to zero */
238 ReduceCredits(pCredInfo, pCurEpDist, 0);
239 } else {
240 /* we cannot zero the credits assigned to this EP, but t o keep
241 * the credits available for these leftover packets, red uce to
242 * a minimum */
243 ReduceCredits(pCredInfo, pCurEpDist, pCurEpDist->TxCreditsMi n);
244 }
245 }
246 }
247
248 /* NOTE in the active case, we do not need to do anything further,
249 * when an EP goes active and needs credits, HTC will call into
250 * our distribution function using a reason code of HTC_CREDIT_DIST_SEEK _CREDITS */
251
252 pCurEpDist = pCurEpDist->pNext;
253 }
254
255 }
256
257 /* HTC has an endpoint that needs credits, pEPDist is the endpoint in question * /
258 static void SeekCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
259 HTC_ENDPOINT_CREDIT_DIST *pEPDist)
260 {
261 HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
262 int credits = 0;
263 int need;
264
265 do {
266
267 if (pEPDist->ServiceID == WMI_CONTROL_SVC) {
268 /* we never oversubscribe on the control service, this is not
269 * a high performance path and the target never holds onto contr ol
270 * credits for too long */
271 break;
272 }
273
274 if (pEPDist->ServiceID == WMI_DATA_VI_SVC) {
275 if (pEPDist->TxCreditsAssigned >= pEPDist->TxCreditsNorm) {
276 /* limit VI service from oversubscribing */
277 break;
278 }
279 }
280
281 if (pEPDist->ServiceID == WMI_DATA_VO_SVC) {
282 if (pEPDist->TxCreditsAssigned >= pEPDist->TxCreditsNorm) {
283 /* limit VO service from oversubscribing */
284 break;
285 }
286 }
287
288 /* for all other services, we follow a simple algorithm of
289 * 1. checking the free pool for credits
290 * 2. checking lower priority endpoints for credits to take */
291
292 /* give what we can */
293 credits = min(pCredInfo->CurrentFreeCredits,pEPDist->TxCreditsSeek);
294
295 if (credits >= pEPDist->TxCreditsSeek) {
296 /* we found some to fullfill the seek request */
297 break;
298 }
299
300 /* we don't have enough in the free pool, try taking away from lower pri ority services
301 *
302 * The rule for taking away credits:
303 * 1. Only take from lower priority endpoints
304 * 2. Only take what is allocated above the minimum (never starve an e ndpoint completely)
305 * 3. Only take what you need.
306 *
307 * */
308
309 /* starting at the lowest priority */
310 pCurEpDist = pCredInfo->pLowestPriEpDist;
311
312 /* work backwards until we hit the endpoint again */
313 while (pCurEpDist != pEPDist) {
314 /* calculate how many we need so far */
315 need = pEPDist->TxCreditsSeek - pCredInfo->CurrentFreeCredits;
316
317 if ((pCurEpDist->TxCreditsAssigned - need) >= pCurEpDist->TxCreditsM in) {
318 /* the current one has been allocated more than it's minimum and it
319 * has enough credits assigned above it's minimum to fullfil l our need
320 * try to take away just enough to fullfill our need */
321 ReduceCredits(pCredInfo,
322 pCurEpDist,
323 pCurEpDist->TxCreditsAssigned - need);
324
325 if (pCredInfo->CurrentFreeCredits >= pEPDist->TxCreditsSeek) {
326 /* we have enough */
327 break;
328 }
329 }
330
331 pCurEpDist = pCurEpDist->pPrev;
332 }
333
334 /* return what we can get */
335 credits = min(pCredInfo->CurrentFreeCredits,pEPDist->TxCreditsSeek);
336
337 } while (FALSE);
338
339 /* did we find some credits? */
340 if (credits) {
341 /* give what we can */
342 GiveCredits(pCredInfo, pEPDist, credits);
343 }
344
345 }
346
347 /* initialize and setup credit distribution */
348 A_STATUS ar6000_setup_credit_dist(HTC_HANDLE HTCHandle, COMMON_CREDIT_STATE_INFO *pCredInfo)
349 {
350 HTC_SERVICE_ID servicepriority[5];
351
352 A_MEMZERO(pCredInfo,sizeof(COMMON_CREDIT_STATE_INFO));
353
354 servicepriority[0] = WMI_CONTROL_SVC; /* highest */
355 servicepriority[1] = WMI_DATA_VO_SVC;
356 servicepriority[2] = WMI_DATA_VI_SVC;
357 servicepriority[3] = WMI_DATA_BE_SVC;
358 servicepriority[4] = WMI_DATA_BK_SVC; /* lowest */
359
360 /* set callbacks and priority list */
361 HTCSetCreditDistribution(HTCHandle,
362 pCredInfo,
363 ar6000_credit_distribute,
364 ar6000_credit_init,
365 servicepriority,
366 5);
367
368 return A_OK;
369 }
370
OLDNEW
« no previous file with comments | « chromeos/drivers/ath6kl/miscdrv/common_drv.c ('k') | chromeos/drivers/ath6kl/miscdrv/makefile » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698