• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "flow_control_task.h"
10 #include "osal_time.h"
11 #include "hdf_log.h"
12 #include "flow_control.h"
13 #define HDF_LOG_TAG HDF_WIFI_CORE
14 #define FLOW_CONTROL_MAP_SIZE 3
15 struct FcPriority {
16     FlowDir dir;
17     FlowControlQueueID id;
18 };
19 
20 static FlowControlQueueID g_staPriorityMapTx[QUEUE_ID_COUNT] = {
21     CTRL_QUEUE_ID, VIP_QUEUE_ID, NORMAL_QUEUE_ID, TCP_ACK_QUEUE_ID, TCP_DATA_QUEUE_ID, VO_QUEUE_ID, VI_QUEUE_ID,
22     BE_QUEUE_ID, BK_QUEUE_ID
23 };
24 
25 static FlowControlQueueID g_staPriorityMapRx[QUEUE_ID_COUNT] = {
26     CTRL_QUEUE_ID, VIP_QUEUE_ID, NORMAL_QUEUE_ID, TCP_DATA_QUEUE_ID, TCP_ACK_QUEUE_ID, VO_QUEUE_ID, VI_QUEUE_ID,
27     BE_QUEUE_ID, BK_QUEUE_ID
28 };
29 
30 static FlowControlQueueID g_priorityMapTx[QUEUE_ID_COUNT] = {
31     CTRL_QUEUE_ID, VIP_QUEUE_ID, NORMAL_QUEUE_ID, TCP_DATA_QUEUE_ID, TCP_ACK_QUEUE_ID, VO_QUEUE_ID, VI_QUEUE_ID,
32     BE_QUEUE_ID, BK_QUEUE_ID
33 };
34 
35 static FlowControlQueueID g_priorityMapRx[QUEUE_ID_COUNT] = {
36     CTRL_QUEUE_ID, VIP_QUEUE_ID, NORMAL_QUEUE_ID, TCP_ACK_QUEUE_ID, TCP_DATA_QUEUE_ID, VO_QUEUE_ID, VI_QUEUE_ID,
37     BE_QUEUE_ID, BK_QUEUE_ID
38 };
39 
IsFcThreadNeedStop(struct FlowControlModule * fcm,FlowDir dir)40 static bool IsFcThreadNeedStop(struct FlowControlModule *fcm, FlowDir dir)
41 {
42     if (fcm->threadStatus[dir] > THREAD_RUNNING) {
43         return true;
44     }
45     return false;
46 }
47 
FlowControlTxTreadProcess(struct FlowControlModule * fcm)48 static void FlowControlTxTreadProcess(struct FlowControlModule *fcm)
49 {
50     bool isSta = false;
51     int i;
52     if (fcm->op != NULL && fcm->op->isDeviceStaOrP2PClient != NULL) {
53         isSta = fcm->op->isDeviceStaOrP2PClient();
54     }
55     if (isSta) {
56         for (i = 0; i < FLOW_CONTROL_MAP_SIZE; i++) {
57             SendFlowControlQueue(fcm, g_staPriorityMapTx[i], FLOW_TX);
58         }
59     } else {
60         for (i = 0; i < FLOW_CONTROL_MAP_SIZE; i++) {
61             SendFlowControlQueue(fcm,  g_priorityMapTx[i], FLOW_TX);
62         }
63     }
64 }
65 
FlowControlRxTreadProcess(struct FlowControlModule * fcm)66 static void FlowControlRxTreadProcess(struct FlowControlModule *fcm)
67 {
68     bool isSta = false;
69     int i;
70     if (fcm->op != NULL && fcm->op->isDeviceStaOrP2PClient != NULL) {
71         isSta = fcm->op->isDeviceStaOrP2PClient();
72     }
73     if (isSta) {
74         for (i = 0; i < QUEUE_ID_COUNT; i++) {
75             SendFlowControlQueue(fcm, g_staPriorityMapRx[i], FLOW_RX);
76         }
77     } else {
78         for (i = 0; i < QUEUE_ID_COUNT; i++) {
79             SendFlowControlQueue(fcm,  g_priorityMapRx[i], FLOW_RX);
80         }
81     }
82 }
83 
RunWiFiFlowControl(void * para,FlowDir dir)84 static int32_t RunWiFiFlowControl(void *para, FlowDir dir)
85 {
86     struct FlowControlModule *fcm = (struct FlowControlModule *)para;
87     if (para == NULL || dir >= FLOW_DIR_COUNT) {
88         HDF_LOGE("%s fail: para = null or dir=%d!", __func__, dir);
89         return HDF_ERR_INVALID_PARAM;
90     }
91     HDF_LOGE("%s Enter flow control dir =%d!", __func__, dir);
92     fcm->threadStatus[dir] = THREAD_STARTING;
93     while (true) {
94         fcm->threadStatus[dir] = THREAD_WAITING;
95         if (OsalSemWait(&fcm->sem[dir], HDF_WAIT_FOREVER) != HDF_SUCCESS) {
96             HDF_LOGE("%s exit: OsalSemWait return false!", __func__);
97             continue;
98         }
99         if (IsFcThreadNeedStop(fcm, dir)) {
100             HDF_LOGE("%s exit: because threadStatus[%d] > THREAD_RUNNING!", __func__, dir);
101             break;
102         }
103         fcm->threadStatus[dir] = THREAD_RUNNING;
104         if (dir == FLOW_TX) {
105             FlowControlTxTreadProcess(fcm);
106         } else if (dir == FLOW_RX) {
107             FlowControlRxTreadProcess(fcm);
108         }
109     }
110     HDF_LOGE("%s Exit!", __func__);
111     fcm->threadStatus[dir] = THREAD_STOPPED;
112     return HDF_SUCCESS;
113 }
114 
RunWiFiTxFlowControl(void * para)115 static int32_t RunWiFiTxFlowControl(void *para)
116 {
117     return RunWiFiFlowControl(para, FLOW_TX);
118 }
119 
RunWiFiRxFlowControl(void * para)120 static int32_t RunWiFiRxFlowControl(void *para)
121 {
122     return RunWiFiFlowControl(para, FLOW_RX);
123 }
124 
CreateTask(struct OsalThread * thread,char * taskName,OsalThreadEntry threadEntry,struct OsalThreadParam * para,void * entryPara)125 static int32_t CreateTask(struct OsalThread *thread, char *taskName, OsalThreadEntry threadEntry,
126     struct OsalThreadParam *para, void *entryPara)
127 {
128     int32_t status = OsalThreadCreate(thread, threadEntry, entryPara);
129     para->name = taskName;
130     if (status != HDF_SUCCESS) {
131         HDF_LOGE("%s:OsalThreadCreate failed!status=%d", __func__, status);
132         return HDF_FAILURE;
133     }
134     status = OsalThreadStart(thread, para);
135     if (status != HDF_SUCCESS) {
136         HDF_LOGE("%s:OsalThreadStart failed!status=%d", __func__, status);
137         OsalThreadDestroy(thread);
138         return HDF_FAILURE;
139     }
140     return HDF_SUCCESS;
141 }
142 
DestroyTask(struct FlowControlModule * fcm,FlowDir dir)143 static void DestroyTask(struct FlowControlModule *fcm, FlowDir dir)
144 {
145     int count = 0;
146     if (fcm == NULL || dir >= FLOW_DIR_COUNT) {
147         HDF_LOGE("%s fail: fcm = null or dir not right!", __func__);
148         return;
149     }
150     if (fcm->threadStatus[dir] == THREAD_INIT_FAIL || fcm->threadStatus[dir] == THREAD_DESTROYED) {
151         HDF_LOGE("%s,delete thread not need!", __func__);
152         return;
153     }
154     fcm->threadStatus[dir] = THREAD_STOPPING;
155     OsalSemPost(&fcm->sem[dir]);
156 
157     /* wait until RunWiFiFlowControl exit */
158     while ((fcm->threadStatus[dir] != THREAD_STOPPED) && (count < MAX_EXIT_THREAD_COUNT)) {
159         OsalMSleep(1);
160         count++;
161     }
162     if (dir == FLOW_TX) {
163         OsalThreadDestroy(&fcm->txTransferThread);
164     } else if (dir == FLOW_RX) {
165         OsalThreadDestroy(&fcm->rxTransferThread);
166     }
167     fcm->threadStatus[dir] = THREAD_DESTROYED;
168     HDF_LOGE("%s delete thread[%d] success!", __func__, dir);
169     return;
170 }
171 
CreateFlowControlTask(struct FlowControlModule * fcm)172 int32_t CreateFlowControlTask(struct FlowControlModule *fcm)
173 {
174     int32_t ret;
175     struct OsalThreadParam config = {
176         .priority = OSAL_THREAD_PRI_HIGHEST,
177         .stackSize = 0,
178     };
179 
180     if (fcm == NULL) {
181         HDF_LOGE("%s fail: fcm = null!", __func__);
182         return HDF_ERR_INVALID_PARAM;
183     }
184     ret = CreateTask(&fcm->txTransferThread, RX_THREAD_NAME, RunWiFiTxFlowControl, &config, fcm);
185     if (ret == HDF_FAILURE) {
186         fcm->threadStatus[FLOW_TX] = THREAD_INIT_FAIL;
187         return HDF_FAILURE;
188     }
189     ret = CreateTask(&fcm->rxTransferThread, TX_THREAD_NAME, RunWiFiRxFlowControl, &config, fcm);
190     if (ret == HDF_FAILURE) {
191         fcm->threadStatus[FLOW_TX] = THREAD_INIT_FAIL;
192         fcm->threadStatus[FLOW_RX] = THREAD_INIT_FAIL;
193         DestroyTask(fcm, FLOW_TX);
194     }
195     fcm->threadStatus[FLOW_TX] = THREAD_INIT_SUCCESS;
196     fcm->threadStatus[FLOW_RX] = THREAD_INIT_SUCCESS;
197     return HDF_SUCCESS;
198 }
199 
DestroyFlowControlTask(struct FlowControlModule * fcm)200 void DestroyFlowControlTask(struct FlowControlModule *fcm)
201 {
202     if (fcm == NULL) {
203         HDF_LOGE("%s fcm = null", __func__);
204         return;
205     }
206     DestroyTask(fcm, FLOW_TX);
207     DestroyTask(fcm, FLOW_RX);
208     return;
209 }