summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_mu_group.h
blob: fb83ce77c8a68042d8cc2febe538b196cbf02933 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// SPDX-License-Identifier: GPL-2.0-or-later
/**
 ******************************************************************************
 *
 * @file rwnx_mu_group.h
 *
 * Copyright (C) RivieraWaves 2016-2019
 *
 ******************************************************************************
 */
#ifndef _RWNX_MU_GROUP_H_
#define _RWNX_MU_GROUP_H_

#include <linux/workqueue.h>
#include <linux/semaphore.h>

struct rwnx_hw;
struct rwnx_sta;

#ifdef CONFIG_RWNX_MUMIMO_TX

/**
 * struct rwnx_sta_group_info - Group Information for a STA
 *
 * @active: node for @mu->active_sta list
 * @update: node for @mu->update_sta list
 * @cnt: Number of groups the STA belongs to
 * @map: Bitfield of groups the sta belongs to
 * @traffic: Number of buffers sent since previous group selection
 * @group: Id of the group selected by previous group selection
 *         (cf @rwnx_mu_group_sta_select)
 */
struct rwnx_sta_group_info {
    struct list_head active;
    struct list_head update;
    u16 last_update;
    int cnt;
    u64 map;
    int traffic;
    u8  group;
};

/**
 * struct mu_group_info - Information about the users of a group
 *
 * @list: node for mu->active_groups
 * @group_id: Group identifier
 * @user_cnt: Number of the users in the group
 * @users: Pointer to the sta, ordered by user position
 */
struct rwnx_mu_group {
    struct list_head list;
    int group_id;
    int user_cnt;
    struct rwnx_sta *users[CONFIG_USER_MAX];
};

/**
 * struct rwnx_mu_info - Information about all MU group
 *
 * @active_groups: List of all possible groups. Ordered from the most recently
 *                 used one to the least one (and possibly never used)
 * @active_sta: List of MU beamformee sta that have been active (since previous
 *              group update). Ordered from the most recently active.
 * @update_sta: List of sta whose group information has changed and need to be
 *              updated at fw level
 * @groups: Table of all groups
 * @group_work: Work item used to schedule group update
 * @update_count: Counter used to identify the last group formation update.
 *                (cf rwnx_sta_group_info.last_update)
 * @lock: Lock taken during group update. If tx happens lock is taken, then tx
 *        will not used MU.
 * @next_group_assign: Next time the group selection should be run
 *                     (ref @rwnx_mu_group_sta_select)
 * @group_cnt: Number of group created
 */
struct rwnx_mu_info {
    struct list_head active_groups;
    struct list_head active_sta;
    struct list_head update_sta;
    struct rwnx_mu_group groups[NX_MU_GROUP_MAX];
    struct delayed_work group_work;
    u16 update_count;
    struct semaphore lock;
    unsigned long next_group_select;
    u8 group_cnt;
};

#define RWNX_SU_GROUP BIT_ULL(0)
#define RWNX_MU_GROUP_MASK 0x7ffffffffffffffeULL
#define RWNX_MU_GROUP_INTERVAL 200 /* in ms */
#define RWNX_MU_GROUP_SELECT_INTERVAL 100 /* in ms */
// minimum traffic in a RWNX_MU_GROUP_SELECT_INTERVAL to consider the sta
#define RWNX_MU_GROUP_MIN_TRAFFIC 50 /* in number of packet */


#define RWNX_GET_FIRST_GROUP_ID(map) (fls64(map) - 1)

#define group_sta_for_each(sta, id, map)                                \
    map = sta->group_info.map & RWNX_MU_GROUP_MASK;                     \
    for (id = (fls64(map) - 1) ; id > 0 ;                               \
         map &= ~(u64)BIT_ULL(id), id = (fls64(map) - 1))

#define group_for_each(id, map)                                         \
    for (id = (fls64(map) - 1) ; id > 0 ;                               \
         map &= ~(u64)BIT_ULL(id), id = (fls64(map) - 1))

#define RWNX_MUMIMO_INFO_POS_ID(info) (((info) >> 6) & 0x3)
#define RWNX_MUMIMO_INFO_GROUP_ID(info) ((info) & 0x3f)

static inline
struct rwnx_mu_group *rwnx_mu_group_from_id(struct rwnx_mu_info *mu, int id)
{
    if (id > NX_MU_GROUP_MAX)
        return NULL;

    return &mu->groups[id - 1];
}


void rwnx_mu_group_sta_init(struct rwnx_sta *sta,
                            const struct ieee80211_vht_cap *vht_cap);
void rwnx_mu_group_sta_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta);
u64 rwnx_mu_group_sta_get_map(struct rwnx_sta *sta);
int rwnx_mu_group_sta_get_pos(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta,
                              int group_id);

void rwnx_mu_group_init(struct rwnx_hw *rwnx_hw);

void rwnx_mu_set_active_sta(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta,
                            int traffic);
void rwnx_mu_set_active_group(struct rwnx_hw *rwnx_hw, int group_id);
void rwnx_mu_group_sta_select(struct rwnx_hw *rwnx_hw);


#else /* ! CONFIG_RWNX_MUMIMO_TX */

static inline
void rwnx_mu_group_sta_init(struct rwnx_sta *sta,
                            const struct ieee80211_vht_cap *vht_cap)
{}

static inline
void rwnx_mu_group_sta_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta)
{}

static inline
u64 rwnx_mu_group_sta_get_map(struct rwnx_sta *sta)
{
    return 0;
}

static inline
int rwnx_mu_group_sta_get_pos(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta,
                              int group_id)
{
    return 0;
}

static inline
void rwnx_mu_group_init(struct rwnx_hw *rwnx_hw)
{}

static inline
void rwnx_mu_set_active_sta(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta,
                            int traffic)
{}

static inline
void rwnx_mu_set_active_group(struct rwnx_hw *rwnx_hw, int group_id)
{}

static inline
void rwnx_mu_group_sta_select(struct rwnx_hw *rwnx_hw)
{}

#endif /* CONFIG_RWNX_MUMIMO_TX */

#endif /* _RWNX_MU_GROUP_H_ */