source: ReferenceDesigns/w3_802.11/c/wlan_mac_high_framework/wlan_mac_ltg.c

Last change on this file was 6319, checked in by chunter, 5 years ago

1.8.0 release wlan-mac-se

File size: 23.2 KB
Line 
1/** @file wlan_mac_ltg.c
2 *  @brief Local Traffic Generator
3 *
4 *  This contains code for scheduling local traffic directly from the
5 *  board.
6 *
7 *  @copyright Copyright 2013-2019, Mango Communications. All rights reserved.
8 *          Distributed under the Mango Communications Reference Design License
9 *              See LICENSE.txt included in the design archive or
10 *              at http://mangocomm.com/802.11/license
11 *
12 *  This file is part of the Mango 802.11 Reference Design (https://mangocomm.com/802.11)
13 */
14
15/***************************** Include Files *********************************/
16#include "wlan_mac_high_sw_config.h"
17
18#include "xil_types.h"
19#include "stdlib.h"
20#include "stdio.h"
21#include "string.h"
22#include "wlan_mac_dl_list.h"
23
24#include "wlan_exp_common.h"
25
26#include "wlan_mac_common.h"
27#include "wlan_mac_802_11_defs.h"
28#include "wlan_mac_eth_util.h"
29#include "wlan_mac_high.h"
30#include "wlan_mac_ltg.h"
31#include "wlan_mac_schedule.h"
32#include "wlan_platform_common.h"
33#include "wlan_platform_high.h"
34#include "wlan_mac_packet_types.h"
35#include "wlan_platform_intc.h"
36
37#if WLAN_SW_CONFIG_ENABLE_LTG
38
39/*************************** Constant Definitions ****************************/
40
41platform_high_dev_info_t platform_high_dev_info;
42
43/*************************** Variable Definitions ****************************/
44
45static dl_list tg_list;
46static function_ptr_t ltg_callback;
47static volatile u64 num_ltg_checks;
48static volatile u32 schedule_id;
49static volatile u8 schedule_running;
50
51
52/*************************** Functions Prototypes ****************************/
53
54void ltg_sched_check();
55int ltg_sched_start_l(dl_entry* curr_tg_dl_entry);
56int ltg_sched_stop_l(dl_entry* curr_tg_dl_entry);
57dl_entry* ltg_sched_create_l();
58void ltg_sched_destroy_l(dl_entry* tg_dl_entry);
59void ltg_sched_destroy_params(tg_schedule* tg);
60
61
62/******************************** Functions **********************************/
63
64/*****************************************************************************/
65/**
66 * @brief Initialize the LTG Framework
67 *
68 * This function is called by the High Framework when first starting up
69 * @return  None
70 */
71int  wlan_mac_ltg_sched_init(){
72
73    platform_high_dev_info = wlan_platform_high_get_dev_info();
74
75    int return_value = 0;
76
77    schedule_running = 0;
78    schedule_id      = SCHEDULE_FAILURE;
79    num_ltg_checks   = 0;
80    ltg_sched_remove(LTG_REMOVE_ALL);
81    dl_list_init(&tg_list);
82    ltg_callback = (function_ptr_t)wlan_null_callback;
83
84    return return_value;
85}
86
87/*****************************************************************************/
88/**
89 * @brief Set LTG event callback
90 *
91 * This function should be called by user application to configure a callback
92 * that will be called according to an LTG schedule.
93 *
94 * @param   callback            - function pointer
95 * @return  None
96 */
97void wlan_mac_ltg_sched_set_callback(void(*callback)()){
98    ltg_callback = (function_ptr_t)callback;
99}
100
101/*****************************************************************************/
102/**
103 * @brief Create an LTG schedule
104 *
105 * This function will set up (but not start) an LTG.
106 *
107 * @param   type - LTG_SCHED_TYPE_PERIODIC or LTG_SCHED_TYPE_UNIFORM_RAND
108 * @param   params - pointer to ltg_sched_periodic_params_t or ltg_sched_uniform_rand_params_t
109 * @param   callback_arg - pointer to ltg_pyld_fixed_t, ltg_pyld_all_assoc_fixed_t, or ltg_pyld_uniform_rand_t
110 * @param   cleanup_callback - optional function pointer to be called upon destruction of LTG. NULL if not needed.
111 * @return  ltg_id - ID of LTG that is created. Used as argument to stop, stop, and remove functions
112 */
113u32 ltg_sched_create(u32 type, void* params, void* callback_arg, void(*cleanup_callback)()){
114
115    static u32 id = 0;
116    u32 return_value;
117
118    tg_schedule* curr_tg;
119    dl_entry* curr_tg_dl_entry;
120
121    //Create a new tg for this id
122    curr_tg_dl_entry = ltg_sched_create_l();
123
124    if(curr_tg_dl_entry == NULL){
125        return_value = LTG_ID_INVALID;
126        return return_value;
127    }
128
129    curr_tg = (tg_schedule*)(curr_tg_dl_entry->data);
130
131    curr_tg->id  = id;
132    return_value = id;
133
134    // Increment LTG ID so that it is unique per LTG
135    id++;
136    if(id == LTG_ID_INVALID){ id++; }
137
138    curr_tg->type = type;
139    curr_tg->cleanup_callback = (function_ptr_t)cleanup_callback;
140
141    switch(type){
142        case LTG_SCHED_TYPE_PERIODIC:
143            curr_tg->params = wlan_mac_high_malloc(sizeof(ltg_sched_periodic_params_t));
144            curr_tg->state  = wlan_mac_high_malloc(sizeof(ltg_sched_periodic_state_t));
145
146            if(curr_tg->params != NULL && curr_tg->state != NULL){
147                bzero(curr_tg->state, sizeof(ltg_sched_periodic_state_t));
148                memcpy(curr_tg->params, params, sizeof(ltg_sched_periodic_params_t));
149                curr_tg->callback_arg = callback_arg;
150            } else {
151                xil_printf("LTG: ERROR: Failed to initialize LTG structs\n");
152                ltg_sched_destroy_l(curr_tg_dl_entry);
153                return LTG_ID_INVALID;
154            }
155        break;
156
157        case LTG_SCHED_TYPE_UNIFORM_RAND:
158            curr_tg->params = wlan_mac_high_malloc(sizeof(ltg_sched_uniform_rand_params_t));
159            curr_tg->state  = wlan_mac_high_malloc(sizeof(ltg_sched_uniform_rand_state_t));
160
161            if(curr_tg->params != NULL && curr_tg->state != NULL){
162                bzero(curr_tg->state, sizeof(ltg_sched_uniform_rand_state_t));
163                memcpy(curr_tg->params, params, sizeof(ltg_sched_uniform_rand_params_t));
164                curr_tg->callback_arg = callback_arg;
165            } else {
166                xil_printf("LTG: ERROR: Failed to initialize LTG structs\n");
167                ltg_sched_destroy_l(curr_tg_dl_entry);
168                return LTG_ID_INVALID;
169            }
170        break;
171
172        default:
173            xil_printf("LTG: ERROR: Unknown type %d\n", type);
174            ltg_sched_destroy_l(curr_tg_dl_entry);
175            return LTG_ID_INVALID;
176        break;
177    }
178
179    dl_entry_insertEnd(&tg_list,curr_tg_dl_entry);
180
181    return return_value;
182}
183
184/*****************************************************************************/
185/**
186 * @brief Create an LTG schedule (low-level)
187 *
188 * Internal function. Not intended to be called by user code.
189 *
190 */
191dl_entry* ltg_sched_create_l(){
192    dl_entry* curr_tg_dl_entry;
193    tg_schedule* curr_tg;
194
195    curr_tg_dl_entry = (dl_entry*)wlan_mac_high_malloc(sizeof(dl_entry));
196
197    if(curr_tg_dl_entry == NULL){
198        return NULL;
199    }
200
201    curr_tg = (tg_schedule*)wlan_mac_high_malloc(sizeof(tg_schedule));
202
203    if(curr_tg == NULL){
204        wlan_mac_high_free(curr_tg_dl_entry);
205        return NULL;
206    }
207
208    curr_tg_dl_entry->data = (void*)curr_tg;
209
210    return curr_tg_dl_entry;
211}
212
213/*****************************************************************************/
214/**
215 * @brief Start an existing LTG (low-lever)
216 *
217 * Internal function. Not intended to be called by user code.
218 *
219 */
220int ltg_sched_start(u32 id){
221    dl_entry* curr_tg_dl_entry;
222
223    if (id == LTG_START_ALL) {
224        return ltg_sched_start_all();
225    } else {
226        // Single ID case
227        curr_tg_dl_entry = ltg_sched_find_tg_schedule(id);
228
229        if(curr_tg_dl_entry != NULL){
230            return ltg_sched_start_l(curr_tg_dl_entry);
231        } else {
232            xil_printf("LTG: ERROR: Failed to start: %d. Please ensure LTG is configured before starting\n", id);
233            return WLAN_FAILURE;
234        }
235    }
236}
237
238/*****************************************************************************/
239/**
240 * @brief Start all existing LTGs
241 * This function will start all previously created schedules that have no been removed
242 *
243 * @return  0 if success, -1 if error
244 */
245int ltg_sched_start_all(){
246
247    int ret_val = 0;
248    tg_schedule* curr_tg;
249    dl_entry* next_tg_dl_entry;
250    dl_entry* curr_tg_dl_entry;
251
252    next_tg_dl_entry = tg_list.first;
253    interrupt_state_t prev_interrupt_state;
254
255    prev_interrupt_state = wlan_platform_intc_stop();
256
257    while(next_tg_dl_entry != NULL){
258        curr_tg_dl_entry = next_tg_dl_entry;
259        next_tg_dl_entry = dl_entry_next(next_tg_dl_entry);
260
261        curr_tg = (tg_schedule*)(curr_tg_dl_entry->data);
262
263        if(ltg_sched_start_l(curr_tg_dl_entry) == -1) {
264            xil_printf("LTG: ERROR: Failed to start: %d. Please ensure LTG is configured before starting\n", (curr_tg->id));
265            ret_val = -1;
266        }
267    }
268
269    wlan_platform_intc_set_state(prev_interrupt_state);
270
271    return ret_val;
272}
273
274/*****************************************************************************/
275/**
276 * @brief Start an existing LTG
277 *
278 * Internal function, not intended to be called by user code.
279 *
280 */
281int ltg_sched_start_l(dl_entry* curr_tg_dl_entry){
282    tg_schedule* curr_tg = (tg_schedule*)(curr_tg_dl_entry->data);
283    u64 timestamp = get_system_time_usec();
284    u64 random_timestamp;
285
286    switch(curr_tg->type){
287        case LTG_SCHED_TYPE_PERIODIC:
288
289            curr_tg->target = num_ltg_checks + (((ltg_sched_periodic_params_t*)(curr_tg->params))->interval_count);
290
291            if(((ltg_sched_periodic_params_t*)(curr_tg->params))->duration_count != LTG_DURATION_FOREVER){
292                curr_tg->stop_target = num_ltg_checks + ((ltg_sched_periodic_params_t*)(curr_tg->params))->duration_count;
293            } else {
294                curr_tg->stop_target = LTG_DURATION_FOREVER;
295            }
296
297            ((ltg_sched_state_hdr_t*)(curr_tg->state))->start_timestamp = timestamp;
298            ((ltg_sched_state_hdr_t*)(curr_tg->state))->enabled = 1;
299        break;
300
301        case LTG_SCHED_TYPE_UNIFORM_RAND:
302            random_timestamp = (rand()%(((ltg_sched_uniform_rand_params_t*)(curr_tg->params))->max_interval_count - ((ltg_sched_uniform_rand_params_t*)(curr_tg->params))->min_interval_count))+((ltg_sched_uniform_rand_params_t*)(curr_tg->params))->min_interval_count;
303            curr_tg->target = num_ltg_checks + random_timestamp;
304
305            if(((ltg_sched_uniform_rand_params_t*)(curr_tg->params))->duration_count != LTG_DURATION_FOREVER){
306                curr_tg->stop_target = num_ltg_checks + ((ltg_sched_uniform_rand_params_t*)(curr_tg->params))->duration_count;
307            } else {
308                curr_tg->stop_target = LTG_DURATION_FOREVER;
309            }
310
311            ((ltg_sched_state_hdr_t*)(curr_tg->state))->start_timestamp = timestamp;
312            ((ltg_sched_state_hdr_t*)(curr_tg->state))->enabled = 1;
313        break;
314
315        default:
316            xil_printf("LTG: ERROR: Unknown type %d\n", curr_tg->type);
317            dl_entry_remove(&tg_list,curr_tg_dl_entry);
318            ltg_sched_destroy_l(curr_tg_dl_entry);
319            return WLAN_FAILURE;
320        break;
321    }
322
323    if(schedule_running == 0){
324        schedule_running = 1;
325
326        // A value of 0 here reflects that the LTG's minimum interval is whatever the scheduler's minimum interval is.
327        //  This assumption is shared among all calling contexts who set _count parameters in an LTG schedule.
328        schedule_id = wlan_mac_schedule_add_event(SCHEDULE_ID_FINE, 0, SCHEDULE_REPEAT_FOREVER, (void*)ltg_sched_check);
329    }
330
331    //u64 start_time = ((ltg_sched_state_hdr_t*)(curr_tg->state))->start_timestamp;
332    //xil_printf("LTG Start @ 0x%08x 0x%08x\n", (u32)(start_time >> 32), (u32)start_time );
333
334    return WLAN_SUCCESS;
335}
336
337/*****************************************************************************/
338/**
339 * @brief Start an existing LTG
340 *
341 * Internal function. Not intended to be called by user code.
342 *
343 */
344void ltg_sched_check(){
345    tg_schedule* curr_tg;
346    dl_entry* curr_tg_dl_entry;
347    u64 random_timestamp;
348
349    num_ltg_checks++;
350    if(tg_list.length > 0){
351
352        curr_tg_dl_entry = tg_list.first;
353
354        while(curr_tg_dl_entry != NULL){
355            curr_tg = (tg_schedule*)(curr_tg_dl_entry->data);
356
357            if(((ltg_sched_state_hdr_t*)(curr_tg->state))->enabled){
358
359                if( num_ltg_checks >= ( curr_tg->target ) ){
360                    switch(curr_tg->type){
361                        case LTG_SCHED_TYPE_PERIODIC:
362                            curr_tg->target = num_ltg_checks + (((ltg_sched_periodic_params_t*)(curr_tg->params))->interval_count);
363                        break;
364                        case LTG_SCHED_TYPE_UNIFORM_RAND:
365                            random_timestamp = (rand()%(((ltg_sched_uniform_rand_params_t*)(curr_tg->params))->max_interval_count - ((ltg_sched_uniform_rand_params_t*)(curr_tg->params))->min_interval_count))+((ltg_sched_uniform_rand_params_t*)(curr_tg->params))->min_interval_count;
366                            curr_tg->target = num_ltg_checks + random_timestamp;
367                        break;
368                        default:
369                            ltg_sched_stop_l(curr_tg_dl_entry);
370                            return;
371                        break;
372                    }
373                    ltg_callback(curr_tg->id, curr_tg->callback_arg);
374                }
375
376                if( curr_tg->stop_target != LTG_DURATION_FOREVER && num_ltg_checks >= ( curr_tg->stop_target )){
377                    ltg_sched_stop_l(curr_tg_dl_entry);
378                }
379
380            }
381
382            curr_tg_dl_entry = dl_entry_next(curr_tg_dl_entry);
383        }
384    }
385}
386
387/*****************************************************************************/
388/**
389 * @brief Stop an existing LTG
390 *
391 * This function will stop executing callbacks for a currently-running LTG.
392 *
393 * @param   id - ID of LTG event (provided by ltg_sched_create)
394 * @return  0 if success, -1 if error
395 */
396int ltg_sched_stop(u32 id){
397    dl_entry* curr_tg_dl_entry;
398
399    if (id == LTG_STOP_ALL) {
400        return ltg_sched_stop_all();
401    } else {
402        // Single ID case
403        curr_tg_dl_entry = ltg_sched_find_tg_schedule(id);
404
405        if(curr_tg_dl_entry != NULL){
406            return ltg_sched_stop_l(curr_tg_dl_entry);
407        } else {
408            xil_printf("LTG: ERROR: Failed to stop: %d. Please ensure LTG is configured before stopping\n", id);
409            return WLAN_FAILURE;
410        }
411    }
412}
413
414/*****************************************************************************/
415/**
416 * @brief Stop all existing LTGs
417 *
418 * This function will stop executing callbacks for all currently-running LTGs.
419 * Note: this does not remove the LTG schedules. They can be started again.
420 *
421 * @return  WLAN_SUCCESS or WLAN_FAILURE
422 */
423int ltg_sched_stop_all(){
424    dl_entry* next_tg_dl_entry;
425    dl_entry* curr_tg_dl_entry;
426    interrupt_state_t prev_interrupt_state;
427
428    next_tg_dl_entry = tg_list.first;
429
430    prev_interrupt_state = wlan_platform_intc_stop();
431
432    while(next_tg_dl_entry != NULL){
433        curr_tg_dl_entry = next_tg_dl_entry;
434        next_tg_dl_entry = dl_entry_next(curr_tg_dl_entry);
435        ltg_sched_stop_l(curr_tg_dl_entry);
436    }
437
438    wlan_platform_intc_set_state(prev_interrupt_state);
439
440    return WLAN_SUCCESS;
441}
442
443/*****************************************************************************/
444/**
445 * @brief Stop existing LTG (low-level)
446 *
447 * Internal function. Not intended to be called by user code.
448 *
449 */
450int ltg_sched_stop_l(dl_entry* curr_tg_dl_entry){
451    tg_schedule* curr_tg = (tg_schedule*)(curr_tg_dl_entry->data);
452
453    u64 timestamp = get_system_time_usec();
454
455    if ( ((ltg_sched_state_hdr_t*)(curr_tg->state))->enabled == 1 ) {
456        ((ltg_sched_state_hdr_t*)(curr_tg->state))->enabled = 0;
457        ((ltg_sched_state_hdr_t*)(curr_tg->state))->stop_timestamp = timestamp;
458        //xil_printf("LTG Stop  @ 0x%08x 0x%08x\n", (u32)(timestamp >> 32), (u32)timestamp );
459    }
460
461    if(tg_list.length == 0 && schedule_running == 1){
462        wlan_mac_schedule_remove_event(schedule_id);
463        schedule_running = 0;
464    }
465
466    return WLAN_SUCCESS;
467}
468
469/*****************************************************************************/
470/**
471 * @brief Get the current state of an LTG
472 *
473 * This function will allows user code to inspect the current state of an existing LTG. This function
474 * returns the state by filling in pointers provided by arguments.
475 *
476 * @param   id - ID of LTG event (provided by ltg_sched_create)
477 * @param   type - pointer to a u32 that will be filled in with LTG_SCHED_TYPE_PERIODIC or LTG_SCHED_TYPE_UNIFORM_RAND
478 * @param   state - double pointer that will be filled in with a pointer to ltg_sched_periodic_state_t or ltg_sched_uniform_rand_state_t
479 * @return  WLAN_SUCCESS or WLAN_FAILURE
480 */
481int ltg_sched_get_state(u32 id, u32* type, void** state){
482    //This function returns the type of schedule corresponding to the id argument
483    //It fills in the state argument with the state of the schedule
484
485    tg_schedule* curr_tg;
486    dl_entry* curr_tg_dl_entry;
487
488    curr_tg_dl_entry = ltg_sched_find_tg_schedule(id);
489    if(curr_tg_dl_entry == NULL){
490        return WLAN_FAILURE;
491    }
492
493    curr_tg = (tg_schedule*)(curr_tg_dl_entry->data);
494
495    if(type != NULL) *type = curr_tg->type;
496    if(state != NULL) *state = curr_tg->state;
497
498    switch(curr_tg->type){
499        case LTG_SCHED_TYPE_PERIODIC:
500            if(num_ltg_checks < (curr_tg->target) ){
501                ((ltg_sched_periodic_state_t*)(curr_tg->state))->time_to_next_count = (u32)(curr_tg->target - num_ltg_checks);
502            } else {
503                ((ltg_sched_periodic_state_t*)(curr_tg->state))->time_to_next_count = 0;
504            }
505        break;
506
507        case LTG_SCHED_TYPE_UNIFORM_RAND:
508            if(num_ltg_checks < (curr_tg->target) ){
509                ((ltg_sched_uniform_rand_state_t*)(curr_tg->state))->time_to_next_count = (u32)(curr_tg->target - num_ltg_checks);
510            } else {
511                ((ltg_sched_uniform_rand_state_t*)(curr_tg->state))->time_to_next_count = 0;
512            }
513        break;
514
515        default:
516            xil_printf("LTG: ERROR: Unknown type %d\n", curr_tg->type);
517            return WLAN_FAILURE;
518        break;
519    }
520
521    return WLAN_SUCCESS;
522}
523
524/*****************************************************************************/
525/**
526 * @brief Get the current params of an LTG
527 *
528 * This function will allows user code to inspect the current parameters of an existing LTG. This function
529 * returns the state by filling in pointers provided by arguments.
530 *
531 * @param   id - ID of LTG event (provided by ltg_sched_create)
532 * @param   params - double pointer that will be filled in with a pointer to ltg_sched_periodic_params_t or ltg_sched_uniform_rand_params_t
533 * @return  WLAN_SUCCESS or WLAN_FAILURE
534 */
535int ltg_sched_get_params(u32 id, void** params){
536    //This function returns the type of the schedule corresponding to the id argument
537    //It fills in the current parameters of the schedule into the params argument
538    tg_schedule* curr_tg;
539    dl_entry* curr_tg_dl_entry;
540
541    curr_tg_dl_entry = ltg_sched_find_tg_schedule(id);
542    if(curr_tg_dl_entry == NULL){
543        return WLAN_FAILURE;
544    }
545
546    curr_tg = (tg_schedule*)(curr_tg_dl_entry->data);
547
548    *params = curr_tg->params;
549
550    return WLAN_SUCCESS;
551}
552
553/*****************************************************************************/
554/**
555 * @brief Get the current callback argument of an LTG
556 *
557 * This function will allows user code to inspect the current callback argument of an existing LTG.
558 *
559 * @param   id - ID of LTG event (provided by ltg_sched_create)
560 * @param   params - double pointer that will be filled in with a function pointer that is the current callback
561 * @return  WLAN_SUCCESS
562 */
563int ltg_sched_get_callback_arg(u32 id, void** callback_arg){
564    tg_schedule* curr_tg;
565    dl_entry* curr_tg_dl_entry;
566
567    curr_tg_dl_entry = ltg_sched_find_tg_schedule(id);
568    if(curr_tg_dl_entry == NULL){
569        return WLAN_FAILURE;
570    }
571
572    curr_tg = (tg_schedule*)(curr_tg_dl_entry->data);
573
574    *callback_arg = curr_tg->callback_arg;
575
576    return WLAN_SUCCESS;
577}
578
579/*****************************************************************************/
580/**
581 * @brief Remove an existing LTG
582 *
583 * This function will remove an existing LTG. If that LTG is currently running, it will first be stopped.
584 *
585 * @param   id - ID of LTG event (provided by ltg_sched_create)
586 * @return  WLAN_SUCCESS or WLAN_FAILURE
587 */
588int ltg_sched_remove(u32 id){
589    tg_schedule* curr_tg;
590    dl_entry* curr_tg_dl_entry;
591
592    if (id == LTG_REMOVE_ALL) {
593        return ltg_sched_remove_all();
594    } else {
595        // Single ID case
596        curr_tg_dl_entry = ltg_sched_find_tg_schedule(id);
597
598        if(curr_tg_dl_entry != NULL){
599            curr_tg = (tg_schedule*)(curr_tg_dl_entry->data);
600
601            ltg_sched_stop_l(curr_tg_dl_entry);
602            dl_entry_remove(&tg_list, curr_tg_dl_entry);
603            if(curr_tg->cleanup_callback != NULL){
604                curr_tg->cleanup_callback(curr_tg->id, curr_tg->callback_arg);
605            }
606            ltg_sched_destroy_l(curr_tg_dl_entry);
607
608            return WLAN_SUCCESS;
609        } else {
610            xil_printf("LTG: ERROR: Failed to remove: %d. Please ensure LTG is configured before removing\n", id);
611            return WLAN_FAILURE;
612        }
613    }
614}
615
616/*****************************************************************************/
617/**
618 * @brief Remove all existing LTGs
619 *
620 * This function will remove all existing LTGs. The end result will be idential to a just-booted node where no LTG has been configured.
621 *
622 * @return  WLAN_SUCCESS
623 */
624int ltg_sched_remove_all(){
625    tg_schedule* curr_tg;
626    dl_entry* next_tg_dl_entry;
627    dl_entry* curr_tg_dl_entry;
628    interrupt_state_t prev_interrupt_state;
629
630    next_tg_dl_entry = tg_list.first;
631
632    prev_interrupt_state = wlan_platform_intc_stop();
633
634    // NOTE:  Cannot use a for loop for this iteration b/c we are removing
635    //   elements from the list.
636    while(next_tg_dl_entry != NULL){
637        curr_tg_dl_entry = next_tg_dl_entry;
638        next_tg_dl_entry = dl_entry_next(curr_tg_dl_entry);
639
640        curr_tg = (tg_schedule*)(curr_tg_dl_entry->data);
641
642        ltg_sched_stop_l(curr_tg_dl_entry);
643        dl_entry_remove(&tg_list, curr_tg_dl_entry);
644        if(curr_tg->cleanup_callback != NULL){
645            curr_tg->cleanup_callback(curr_tg->id, curr_tg->callback_arg);
646        }
647        ltg_sched_destroy_l(curr_tg_dl_entry);
648    }
649
650    wlan_platform_intc_set_state(prev_interrupt_state);
651
652    return WLAN_SUCCESS;
653}
654
655/*****************************************************************************/
656/**
657 * @brief Destroy LTG parameters
658 *
659 * Internal function. Not intended to be called by user code.
660 *
661 */
662void ltg_sched_destroy_params(tg_schedule* tg){
663    switch(tg->type){
664        case LTG_SCHED_TYPE_PERIODIC:
665        case LTG_SCHED_TYPE_UNIFORM_RAND:
666            wlan_mac_high_free(tg->params);
667            wlan_mac_high_free(tg->state);
668        break;
669    }
670}
671
672/*****************************************************************************/
673/**
674 * @brief Destroy LTG parameters (low-level)
675 *
676 * Internal function. Not intended to be called by user code.
677 *
678 */
679void ltg_sched_destroy_l(dl_entry* tg_dl_entry){
680    tg_schedule* curr_tg;
681
682    curr_tg = (tg_schedule*)(tg_dl_entry->data);
683
684    ltg_sched_destroy_params(curr_tg);
685    wlan_mac_high_free(tg_dl_entry);
686    wlan_mac_high_free(curr_tg);
687    return;
688}
689
690/*****************************************************************************/
691/**
692 * @brief Find LTG given id
693 *
694 * Internal function. Not intended to be called by user code.
695 *
696 */
697dl_entry* ltg_sched_find_tg_schedule(u32 id){
698    dl_entry* curr_tg_dl_entry;
699    tg_schedule* curr_tg;
700    int iter;
701
702    curr_tg_dl_entry = tg_list.first;
703
704
705    iter = tg_list.length;
706
707    while((curr_tg_dl_entry != NULL) && (iter-- > 0)){
708        curr_tg = (tg_schedule*)(curr_tg_dl_entry->data);
709        if( (curr_tg->id)==id){
710            return curr_tg_dl_entry;
711        }
712        curr_tg_dl_entry = dl_entry_next(curr_tg_dl_entry);
713    }
714    return NULL;
715}
716
717/*****************************************************************************/
718/**
719 * @brief Create LTG frame
720 *
721 * Function is typically called in the context of the LTG event callback. It creates a complete
722 * 802.11 data frame with the extra LTG metadata in the payload.
723 *
724 */
725
726int wlan_create_ltg_frame(u8* pkt,
727                          u8* addr1,
728                          u8* addr2,
729                          u8* addr3,
730                          u8 frame_control_2,
731                          u32 ltg_id){
732    u32 tx_length;
733    ltg_packet_id_t* pkt_id;
734
735    if( pkt == NULL ) return WLAN_FAILURE;
736
737    tx_length = wlan_create_data_frame_header(pkt,
738                                              addr1,
739                                              addr2,
740                                              addr3,
741                                              frame_control_2);
742
743    // Prepare the MPDU LLC header
744    pkt_id = (ltg_packet_id_t*)(pkt + sizeof(mac_header_80211));
745
746    (pkt_id->llc_hdr).dsap = LLC_SNAP;
747    (pkt_id->llc_hdr).ssap = LLC_SNAP;
748    (pkt_id->llc_hdr).control_field = LLC_CNTRL_UNNUMBERED;
749    bzero((void *)((pkt_id->llc_hdr).org_code), 3);             // Org Code 0x000000: Encapsulated Ethernet
750    (pkt_id->llc_hdr).type = LLC_TYPE_WLAN_LTG;
751
752    pkt_id->unique_seq     = 0; //make sure this is filled in via the dequeue callback
753    pkt_id->ltg_id         = ltg_id;
754
755    // LTG packets always have LLC header, LTG payload id, plus any extra payload requested by user
756    tx_length += ((sizeof(ltg_packet_id_t)));
757
758    return tx_length;
759}
760
761#endif //WLAN_SW_CONFIG_ENABLE_LTG
Note: See TracBrowser for help on using the repository browser.