net:wireless:Support eswin usb wifi ECR6600U
[platform/kernel/linux-starfive.git] / drivers / net / wireless / eswin / ecrnx_mu_group.c
1 /**
2  ******************************************************************************
3  *
4  * @file ecrnx_mu_group.c
5  *
6  * Copyright (C) ESWIN 2015-2020
7  *
8  ******************************************************************************
9  */
10
11 #include "ecrnx_defs.h"
12 #include "ecrnx_msg_tx.h"
13 #include "ecrnx_events.h"
14
15
16 /**
17  * ecrnx_mu_group_sta_init - Initialize group information for a STA
18  *
19  * @sta: Sta to initialize
20  */
21 void ecrnx_mu_group_sta_init(struct ecrnx_sta *sta,
22                             const struct ieee80211_vht_cap *vht_cap)
23 {
24     sta->group_info.map = 0;
25     sta->group_info.cnt = 0;
26     sta->group_info.active.next = LIST_POISON1;
27     sta->group_info.update.next = LIST_POISON1;
28     sta->group_info.last_update = 0;
29     sta->group_info.traffic = 0;
30     sta->group_info.group = 0;
31
32     if (!vht_cap ||
33         !(vht_cap->vht_cap_info & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) {
34             sta->group_info.map = ECRNX_SU_GROUP;
35     }
36 }
37
38 /**
39  * ecrnx_mu_group_sta_del - Remove a sta from all MU group
40  *
41  * @ecrnx_hw: main driver data
42  * @sta: STA to remove
43  *
44  * Remove one sta from all the MU groups it belongs to.
45  */
46 void ecrnx_mu_group_sta_del(struct ecrnx_hw *ecrnx_hw, struct ecrnx_sta *sta)
47 {
48     struct ecrnx_mu_info *mu = &ecrnx_hw->mu;
49     int i, j, group_id;
50     bool lock_taken;
51     u64 map;
52
53     lock_taken = (down_interruptible(&mu->lock) == 0);
54
55     group_sta_for_each(sta, group_id, map) {
56         struct ecrnx_mu_group *group = ecrnx_mu_group_from_id(mu, group_id);
57
58         for (i = 0; i < CONFIG_USER_MAX; i++) {
59             if (group->users[i] == sta) {
60                 group->users[i] = NULL;
61                 group->user_cnt --;
62                 /* Don't keep group with only one user */
63                 if (group->user_cnt == 1) {
64                     for (j = 0; j < CONFIG_USER_MAX; j++) {
65                         if (group->users[j]) {
66                             group->users[j]->group_info.cnt--;
67                             group->users[j]->group_info.map &= ~BIT_ULL(group->group_id);
68                             if (group->users[j]->group_info.group == group_id)
69                                 group->users[j]->group_info.group = 0;
70                             group->user_cnt --;
71                             break;
72                         }
73                     }
74                     mu->group_cnt--;
75                     trace_mu_group_delete(group->group_id);
76                 } else {
77                     trace_mu_group_update(group);
78                 }
79                 break;
80             }
81         }
82
83         WARN((i == CONFIG_USER_MAX), "sta %d doesn't belongs to group %d",
84             sta->sta_idx, group_id);
85     }
86
87     sta->group_info.map = 0;
88     sta->group_info.cnt = 0;
89     sta->group_info.traffic = 0;
90
91     if (sta->group_info.active.next != LIST_POISON1)
92         list_del(&sta->group_info.active);
93
94     if (sta->group_info.update.next != LIST_POISON1)
95         list_del(&sta->group_info.update);
96
97     if (lock_taken)
98         up(&mu->lock);
99 }
100
101 /**
102  * ecrnx_mu_group_sta_get_map - Get the list of group a STA belongs to
103  *
104  * @sta: pointer to the sta
105  *
106  * @return the list of group a STA belongs to as a bitfield
107  */
108 u64 ecrnx_mu_group_sta_get_map(struct ecrnx_sta *sta)
109 {
110     if (sta)
111         return sta->group_info.map;
112     return 0;
113 }
114
115 /**
116  * ecrnx_mu_group_sta_get_pos - Get sta position in a group
117  *
118  * @ecrnx_hw: main driver data
119  * @sta: pointer to the sta
120  * @group_id: Group id
121  *
122  * @return the positon of @sta in group @group_id or -1 if the sta
123  * doesn't belongs to the group (or group id is invalid)
124  */
125 int ecrnx_mu_group_sta_get_pos(struct ecrnx_hw *ecrnx_hw, struct ecrnx_sta *sta,
126                               int group_id)
127 {
128     struct ecrnx_mu_group *group;
129     int i;
130
131     group = ecrnx_mu_group_from_id(&ecrnx_hw->mu, group_id);
132     if (!group)
133         return -1;
134
135     for (i = 0; i < CONFIG_USER_MAX; i++) {
136         if (group->users[i] == sta)
137             return i;
138     }
139
140     WARN(1, "sta %d doesn't belongs to group %d",
141          sta->sta_idx, group_id);
142     return -1;
143 }
144
145 /**
146  * ecrnx_mu_group_move_head - Move (or add) one element at the top of a list
147  *
148  * @list: list pointer
149  * @elem: element to move (or add) at the top of @list
150  *
151  */
152 static inline
153 void ecrnx_mu_group_move_head(struct list_head *list, struct list_head *elem)
154 {
155     if (elem->next != LIST_POISON1) {
156         __list_del_entry(elem);
157     }
158     list_add(elem, list);
159 }
160
161 /**
162  * ecrnx_mu_group_remove_users - Remove all the users of a group
163  *
164  * @mu: pointer on MU info
165  * @group: pointer on group to remove users from
166  *
167  * Loop over all users one one group and remove this group from their
168  * map (and count).
169  * Each users is also added to the update_sta list, so that group info
170  * will be resent to fw for this user.
171  */
172 static inline
173 void ecrnx_mu_group_remove_users(struct ecrnx_mu_info *mu,
174                                 struct ecrnx_mu_group *group)
175 {
176     struct ecrnx_sta *sta;
177     int i, group_id = group->group_id;
178
179     for (i = 0; i < CONFIG_USER_MAX; i++) {
180         if (group->users[i]) {
181             sta = group->users[i];
182             group->users[i] = NULL;
183             sta->group_info.cnt--;
184             sta->group_info.map &= ~BIT_ULL(group_id);
185             ecrnx_mu_group_move_head(&mu->update_sta,
186                                     &sta->group_info.update);
187         }
188     }
189
190     if (group->user_cnt)
191         mu->group_cnt--;
192     group->user_cnt = 0;
193     trace_mu_group_delete(group_id);
194 }
195
196 /**
197  * ecrnx_mu_group_add_users - Add users to a group
198  *
199  * @mu: pointer on MU info
200  * @group: pointer on group to add users in
201  * @nb_user: number of users to ad
202  * @users: table of user to add
203  *
204  * Add @nb_users to @group (which may already have users)
205  * Each new users is added to the first free position.
206  * It is assume that @group has at least @nb_user free position. If it is not
207  * case it only add the number of users needed to complete the group.
208  * Each users (effectively added to @group) is also added to the update_sta
209  * list, so that group info will be resent to fw for this user.
210  */
211 static inline
212 void ecrnx_mu_group_add_users(struct ecrnx_mu_info *mu,
213                              struct ecrnx_mu_group *group,
214                              int nb_user, struct ecrnx_sta **users)
215 {
216     int i, j, group_id = group->group_id;
217
218     if (!group->user_cnt)
219         mu->group_cnt++;
220
221     j = 0;
222     for (i = 0; i < nb_user ; i++) {
223         for (; j < CONFIG_USER_MAX ; j++) {
224             if (group->users[j] == NULL) {
225                 group->users[j] = users[i];
226                 users[i]->group_info.cnt ++;
227                 users[i]->group_info.map |= BIT_ULL(group_id);
228
229                 ecrnx_mu_group_move_head(&(mu->update_sta),
230                                         &(users[i]->group_info.update));
231                 group->user_cnt ++;
232                 j ++;
233                 break;
234             }
235
236             WARN(j == (CONFIG_USER_MAX - 1),
237                  "Too many user for group %d (nb_user=%d)",
238                  group_id, group->user_cnt + nb_user - i);
239         }
240     }
241
242     trace_mu_group_update(group);
243 }
244
245
246 /**
247  * ecrnx_mu_group_create_one - create on group with a specific group of user
248  *
249  * @mu: pointer on MU info
250  * @nb_user: number of user to include in the group (<= CONFIG_USER_MAX)
251  * @users: table of users
252  *
253  * Try to create a new group with a specific group of users.
254  * 1- First it checks if a group containing all this users already exists.
255  *
256  * 2- Then it checks if it is possible to complete a group which already
257  *    contains at least one user.
258  *
259  * 3- Finally it create a new group. To do so, it take take the last group of
260  *    the active_groups list, remove all its current users and add the new ones
261  *
262  * In all cases, the group selected is moved at the top of the active_groups
263  * list
264  *
265  * @return 1 if a new group has been created and 0 otherwise
266  */
267 static
268 int ecrnx_mu_group_create_one(struct ecrnx_mu_info *mu, int nb_user,
269                              struct ecrnx_sta **users, int *nb_group_left)
270 {
271     int i, group_id;
272     struct ecrnx_mu_group *group;
273     u64 group_match;
274     u64 group_avail;
275
276     group_match = users[0]->group_info.map;
277     group_avail = users[0]->group_info.map;
278     for (i = 1; i < nb_user ; i++) {
279         group_match &= users[i]->group_info.map;
280         group_avail |= users[i]->group_info.map;
281
282     }
283
284     if (group_match) {
285         /* a group (or more) with all the users already exist */
286         group_id = ECRNX_GET_FIRST_GROUP_ID(group_match);
287         group = ecrnx_mu_group_from_id(mu, group_id);
288         ecrnx_mu_group_move_head(&mu->active_groups, &group->list);
289         return 0;
290     }
291
292 #if CONFIG_USER_MAX > 2
293     if (group_avail) {
294         /* check if we can complete a group */
295         struct ecrnx_sta *users2[CONFIG_USER_MAX];
296         int nb_user2;
297
298         group_for_each(group_id, group_avail) {
299             group = ecrnx_mu_group_from_id(mu, group_id);
300             if (group->user_cnt == CONFIG_USER_MAX)
301                 continue;
302
303             nb_user2 = 0;
304             for (i = 0; i < nb_user ; i++) {
305                 if (!(users[i]->group_info.map & BIT_ULL(group_id))) {
306                     users2[nb_user2] = users[i];
307                     nb_user2++;
308                 }
309             }
310
311             if ((group->user_cnt + nb_user2) <= CONFIG_USER_MAX) {
312                 ecrnx_mu_group_add_users(mu, group, nb_user2, users2);
313                 ecrnx_mu_group_move_head(&mu->active_groups, &group->list);
314                 return 0;
315             }
316         }
317     }
318 #endif /* CONFIG_USER_MAX > 2*/
319
320     /* create a new group */
321     group = list_last_entry(&mu->active_groups, struct ecrnx_mu_group, list);
322     ecrnx_mu_group_remove_users(mu, group);
323     ecrnx_mu_group_add_users(mu, group, nb_user, users);
324     ecrnx_mu_group_move_head(&mu->active_groups, &group->list);
325     (*nb_group_left)--;
326
327     return 1;
328 }
329
330 /**
331  * ecrnx_mu_group_create - Create new groups containing one specific sta
332  *
333  * @mu: pointer on MU info
334  * @sta: sta to add in each group
335  * @nb_group_left: maximum number to new group allowed. (updated on exit)
336  *
337  * This will try to create "all the possible" group with a specific sta being
338  * a member of all these group.
339  * The function simply loops over the @active_sta list (starting from @sta).
340  * When it has (CONFIG_USER_MAX - 1) users it try to create a new group with
341  * these users (plus @sta).
342  * Loops end when there is no more users, or no more new group is allowed
343  *
344  */
345 static
346 void ecrnx_mu_group_create(struct ecrnx_mu_info *mu, struct ecrnx_sta *sta,
347                           int *nb_group_left)
348 {
349     struct ecrnx_sta *user_sta = sta;
350     struct ecrnx_sta *users[CONFIG_USER_MAX];
351     int nb_user = 1;
352
353     users[0] = sta;
354     while (*nb_group_left) {
355
356         list_for_each_entry_continue(user_sta, &mu->active_sta, group_info.active) {
357             users[nb_user] = user_sta;
358             if (++nb_user == CONFIG_USER_MAX) {
359                 break;
360             }
361         }
362
363         if (nb_user > 1) {
364             if (ecrnx_mu_group_create_one(mu, nb_user, users, nb_group_left))
365                 (*nb_group_left)--;
366
367             if (nb_user < CONFIG_USER_MAX)
368                 break;
369             else
370                 nb_user = 1;
371         } else
372             break;
373     }
374 }
375
376 /**
377  * ecrnx_mu_group_work - process function of the "group_work"
378  *
379  * The work is scheduled when several sta (MU beamformee capable) are active.
380  * When called, the @active_sta contains the list of the active sta (starting
381  * from the most recent one), and @active_groups is the list of all possible
382  * groups ordered so that the first one is the most recently used.
383  *
384  * This function will create new groups, starting from group containing the
385  * most "active" sta.
386  * For example if the list of sta is :
387  * sta8 -> sta3 -> sta4 -> sta7 -> sta1
388  * and the number of user per group is 3, it will create grooups :
389  * - sta8 / sta3 / sta4
390  * - sta8 / sta7 / sta1
391  * - sta3 / sta4 / sta7
392  * - sta3 / sta1
393  * - sta4 / sta7 / sta1
394  * - sta7 / sta1
395  *
396  * To create new group, the least used group are first selected.
397  * It is only allowed to create NX_MU_GROUP_MAX per iteration.
398  *
399  * Once groups have been updated, mu group information is update to the fw.
400  * To do so it use the @update_sta list to know which sta has been affected.
401  * As it is necessary to wait for fw confirmation before using this new group
402  * MU is temporarily disabled during group update
403  *
404  * Work is then rescheduled.
405  *
406  * At the end of the function, both @active_sta and @update_sta list are empty.
407  *
408  * Note:
409  * - This is still a WIP, and will require more tuning
410  * - not all combinations are created, to avoid to much processing.
411  * - reschedule delay should be adaptative
412  */
413 void ecrnx_mu_group_work(struct work_struct *ws)
414 {
415     struct delayed_work *dw = container_of(ws, struct delayed_work, work);
416     struct ecrnx_mu_info *mu = container_of(dw, struct ecrnx_mu_info, group_work);
417     struct ecrnx_hw *ecrnx_hw = container_of(mu, struct ecrnx_hw, mu);
418     struct ecrnx_sta *sta, *next;
419     int nb_group_left = NX_MU_GROUP_MAX;
420
421     if (WARN(!ecrnx_hw->mod_params->mutx,
422              "In group formation work, but mutx disabled"))
423         return;
424
425     if (down_interruptible(&mu->lock) != 0)
426         return;
427
428     mu->update_count++;
429     if (!mu->update_count)
430         mu->update_count++;
431
432     list_for_each_entry_safe(sta, next, &mu->active_sta, group_info.active) {
433         if (nb_group_left)
434             ecrnx_mu_group_create(mu, sta, &nb_group_left);
435
436         sta->group_info.last_update = mu->update_count;
437         list_del(&sta->group_info.active);
438     }
439
440     if (! list_empty(&mu->update_sta)) {
441         list_for_each_entry_safe(sta, next, &mu->update_sta, group_info.update) {
442             ecrnx_send_mu_group_update_req(ecrnx_hw, sta);
443             list_del(&sta->group_info.update);
444         }
445     }
446
447     mu->next_group_select = jiffies;
448     ecrnx_mu_group_sta_select(ecrnx_hw);
449     up(&mu->lock);
450
451     return;
452 }
453
454 /**
455  * ecrnx_mu_group_init - Initialize MU groups
456  *
457  * @ecrnx_hw: main driver data
458  *
459  * Initialize all MU group
460  */
461 void ecrnx_mu_group_init(struct ecrnx_hw *ecrnx_hw)
462 {
463     struct ecrnx_mu_info *mu = &ecrnx_hw->mu;
464     int i;
465
466     INIT_LIST_HEAD(&mu->active_groups);
467     INIT_LIST_HEAD(&mu->active_sta);
468     INIT_LIST_HEAD(&mu->update_sta);
469
470     for (i = 0; i < NX_MU_GROUP_MAX; i++) {
471         int j;
472         mu->groups[i].user_cnt = 0;
473         mu->groups[i].group_id = i + 1;
474         for (j = 0; j < CONFIG_USER_MAX; j++) {
475             mu->groups[i].users[j] = NULL;
476         }
477         list_add(&mu->groups[i].list, &mu->active_groups);
478     }
479
480     mu->update_count = 1;
481     mu->group_cnt = 0;
482     mu->next_group_select = jiffies;
483     INIT_DELAYED_WORK(&mu->group_work, ecrnx_mu_group_work);
484     sema_init(&mu->lock, 1);
485 }
486
487 /**
488  * ecrnx_mu_set_active_sta - mark a STA as active
489  *
490  * @ecrnx_hw: main driver data
491  * @sta: pointer to the sta
492  * @traffic: Number of buffers to add in the sta's traffic counter
493  *
494  * If @sta is MU beamformee capable (and MU-MIMO tx is enabled) move the
495  * sta at the top of the @active_sta list.
496  * It also schedule the group_work if not already scheduled and the list
497  * contains more than one sta.
498  *
499  * If a STA was already in the list during the last group update
500  * (i.e. sta->group_info.last_update == mu->update_count) it is not added
501  * back to the list until a sta that wasn't active during the last update is
502  * added. This is to avoid scheduling group update with a list of sta that
503  * were all already in the list during previous update.
504  *
505  * It is called with mu->lock taken.
506  */
507 void ecrnx_mu_set_active_sta(struct ecrnx_hw *ecrnx_hw, struct ecrnx_sta *sta,
508                             int traffic)
509 {
510     struct ecrnx_mu_info *mu = &ecrnx_hw->mu;
511
512     if (!sta || (sta->group_info.map & ECRNX_SU_GROUP))
513         return;
514
515     sta->group_info.traffic += traffic;
516
517     if ((sta->group_info.last_update != mu->update_count) ||
518         !list_empty(&mu->active_sta)) {
519
520         ecrnx_mu_group_move_head(&mu->active_sta, &sta->group_info.active);
521
522         if (!delayed_work_pending(&mu->group_work) &&
523             !list_is_singular(&mu->active_sta)) {
524             schedule_delayed_work(&mu->group_work,
525                                   msecs_to_jiffies(ECRNX_MU_GROUP_INTERVAL));
526         }
527     }
528 }
529
530 /**
531  * ecrnx_mu_set_active_group - mark a MU group as active
532  *
533  * @ecrnx_hw: main driver data
534  * @group_id: Group id
535  *
536  * move a group at the top of the @active_groups list
537  */
538 void ecrnx_mu_set_active_group(struct ecrnx_hw *ecrnx_hw, int group_id)
539 {
540     struct ecrnx_mu_info *mu = &ecrnx_hw->mu;
541     struct ecrnx_mu_group *group = ecrnx_mu_group_from_id(mu, group_id);
542
543     ecrnx_mu_group_move_head(&mu->active_groups, &group->list);
544 }
545
546
547 /**
548  * ecrnx_mu_group_sta_select - Select the best group for MU stas
549  *
550  * @ecrnx_hw: main driver data
551  *
552  * For each MU capable client of AP interfaces this function tries to select
553  * the best group to use.
554  *
555  * In first pass, gather information from all stations to form statistics
556  * for each group for the previous @ECRNX_MU_GROUP_SELECT_INTERVAL interval:
557  * - number of buffers transmitted
558  * - number of user
559  *
560  * Then groups with more than 2 active users, are assigned after being ordered
561  * by traffic :
562  * - group with highest traffic is selected: set this group for all its users
563  * - update nb_users for all others group (as one sta may be in several groups)
564  * - select the next group that have still mor than 2 users and assign it.
565  * - continue until all group are processed
566  *
567  */
568 void ecrnx_mu_group_sta_select(struct ecrnx_hw *ecrnx_hw)
569 {
570     struct ecrnx_mu_info *mu = &ecrnx_hw->mu;
571     int nb_users[NX_MU_GROUP_MAX + 1];
572     int traffic[NX_MU_GROUP_MAX + 1];
573     int order[NX_MU_GROUP_MAX + 1];
574     struct ecrnx_sta *sta;
575     struct ecrnx_vif *vif;
576     struct list_head *head;
577     u64 map;
578     int i, j, update, group_id, tmp, cnt = 0;
579
580     if (!mu->group_cnt || time_before(jiffies, mu->next_group_select))
581         return;
582
583     list_for_each_entry(vif, &ecrnx_hw->vifs, list) {
584
585         if (ECRNX_VIF_TYPE(vif) != NL80211_IFTYPE_AP)
586             continue;
587
588 #ifdef CONFIG_ECRNX_FULLMAC
589         head = &vif->ap.sta_list;
590 #else
591         head = &vif->stations;
592 #endif /* CONFIG_ECRNX_FULLMAC */
593
594         memset(nb_users, 0, sizeof(nb_users));
595         memset(traffic, 0, sizeof(traffic));
596         list_for_each_entry(sta, head, list) {
597             int sta_traffic = sta->group_info.traffic;
598
599             /* reset statistics for next selection */
600             sta->group_info.traffic = 0;
601             if (sta->group_info.group)
602                 trace_mu_group_selection(sta, 0);
603             sta->group_info.group = 0;
604
605             if (sta->group_info.cnt == 0 ||
606                 sta_traffic < ECRNX_MU_GROUP_MIN_TRAFFIC)
607                 continue;
608
609             group_sta_for_each(sta, group_id, map) {
610                 nb_users[group_id]++;
611                 traffic[group_id] += sta_traffic;
612
613                 /* list group with 2 users or more */
614                 if (nb_users[group_id] == 2)
615                     order[cnt++] = group_id;
616             }
617         }
618
619         /* reorder list of group with more that 2 users */
620         update = 1;
621         while(update) {
622             update = 0;
623             for (i = 0; i < cnt - 1; i++) {
624                 if (traffic[order[i]] < traffic[order[i + 1]]) {
625                     tmp = order[i];
626                     order[i] = order[i + 1];
627                     order[i + 1] = tmp;
628                     update = 1;
629                 }
630             }
631         }
632
633         /* now assign group in traffic order */
634         for (i = 0; i < cnt ; i ++) {
635             struct ecrnx_mu_group *group;
636             group_id = order[i];
637
638             if (nb_users[group_id] < 2)
639                 continue;
640
641             group = ecrnx_mu_group_from_id(mu, group_id);
642             for (j = 0; j < CONFIG_USER_MAX ; j++) {
643                 if (group->users[j]) {
644                     trace_mu_group_selection(group->users[j], group_id);
645                     group->users[j]->group_info.group = group_id;
646
647                     group_sta_for_each(group->users[j], tmp, map) {
648                         if (group_id != tmp)
649                             nb_users[tmp]--;
650                     }
651                 }
652             }
653         }
654     }
655
656     mu->next_group_select = jiffies +
657         msecs_to_jiffies(ECRNX_MU_GROUP_SELECT_INTERVAL);
658     mu->next_group_select |= 1;
659 }