1 /* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
2  *
3  * Permission to use, copy, modify, and/or distribute this software for any
4  * purpose with or without fee is hereby granted, provided that the above
5  * copyright notice and this permission notice appear in all copies.
6  *
7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14  */
15 
16 #ifndef __WLANFW_HEALTH_MON_H__
17 #define __WLANFW_HEALTH_MON_H__
18 
19 #include <a_types.h> /* A_UINT32 */
20 
21 /* WLAN Health monitor data structure shared by host and FW */
22 
23 /*
24  * Version 1 of the upload metric structs (i.e. wlanfw_health_mon_metric_upload_t)
25  * provides a fixed allocation of 8 bytes of scratch space after each metric,
26  * to optionally hold metric-specific data, e.g. from intermediate calculations when computing the score_pct.
27  */
28 #define WLANFW_HEALTH_MON_EXTRA_WORDS32 2
29 
30 /* word0:
31  * Extract bitfields from the A_UINT32 "word" containing them.
32  * The target produces the data in little-endian order.
33  * If the host uses big-endian order, it needs to account for the endianness
34  * difference when reading the data.
35  * Definition of bitfields within 32-bit word:
36  *     bits 7:0   = module ID (M7...M0)
37  *     bits 14:8  = module local ID (m6...m0)
38  *     bits 31:15 = instance ID (I16...I0)
39  *                                bits
40  * |31                           15|14              8|7                 0|
41  * +-------------------------------+-----------------+-------------------+
42  * |         instance ID           | metric local ID |     module ID     |
43  * |I16            ...           I0|m6     ...     m0|M7      ...      M0|
44  *
45  * Layout in memory:
46  *                    bits
47  *        |7  |6                        0|
48  *        +---+--------------------------+
49  * byte 0 |M7  M6  M5  M4  M3  M2  M1  M0|
50  *        +---+--------------------------+
51  * byte 1 |I0 |m6  m5  m4  m3  m2  m1  m0|
52  *        +---+--------------------------+
53  * byte 2 |I8  I7  I6  I5  I4  I3  I2  I1|
54  *        +------------------------------+
55  * byte 3 |I16 I15 I14 I13 I12 I11 I10 I9|
56  */
57 #ifdef LITTLE_ENDIAN
58   /* The little-endian version of the macro to extract the module id and metric id */
59   #define WLANFW_HEALTH_MON_MODULE_ID_GET(word32) \
60       (((word32) & 0x000000ff) >> 0)
61   #define WLANFW_HEALTH_MON_METRIC_LOCAL_ID_GET(word32) \
62       (((word32) & 0x00007f00) >> 8)
63   #define WLANFW_HEALTH_MON_INSTANCE_ID_GET(word32) \
64       (((word32) & 0xffff8000) >> 15)
65 #else
66   /*
67    * When read into a big-endian 32-bit word:
68    *                                bits
69    * |31          24|23|22          16|15               8|7               0|
70    * +--------------+--+--------------+------------------+-----------------+
71    * |M7          M0|I0|m6          m0|I8              I1|I16            I9|
72    *
73    */
74   /*
75    * big-endian macro def to extract module ID = M7:M0 = byte3
76    */
77   #define WLANFW_HEALTH_MON_MODULE_ID_GET(word32) \
78       (((word32) >> 24) && 0xff)
79   /*
80    * big-endian macro def to extract metric local ID = m6:m0 = byte2 & 0x7f
81    */
82   #define WLANFW_HEALTH_MON_METRIC_LOCAL_ID_GET(word32) \
83       (((word32) >> 16) && 0x7f)
84   /*
85    * big-endian macro def to extract instance ID = I16:I0 =
86    *     (I16:I9 << 9) | (I8:I1 << 1) | I0
87    *     (byte0 << 9) | (byte1 << 1) | (byte2 >> 7)
88    */
89   #define WLANFW_HEALTH_MON_INSTANCE_ID_GET(word32) \
90       (((((word32) >> 0)  & 0xff) << 9) | /* I16:I9 */ \
91        ((((word32) >> 8)  & 0xff) << 1) | /* I8:I1 */  \
92        ((((word32) >> 23) & 0x01) << 0))  /* I0 */
93 #endif
94 
95 /* word1:
96  * Extract bitfields from the A_UINT32 "word" containing them.
97  * The target produces the data in little-endian order.
98  * If the host uses big-endian order, it needs to account for the endianness
99  * difference when reading the data.
100  * Definition of bitfields within 32-bit word:
101  *     bits 7:0   = score_pct (S7...S0)
102  *     bits 15:8  = alarm_threshold (A7...A0)
103  *     bit  16    = old_alarm_state (P)
104  *     bits 20:17 = num_extra_bytes (N3..N0)
105  *     bit  21    = valid_data_flag (V)
106  *     bits 31:22 = reserved (R9...R0)
107  *                                bits
108  * |31              22|21|20     17|16|15              8|7              0|
109  * +------------------+--+---------+--+-----------------+----------------+
110  * |     reserved     |V |num bytes|P | alarm threshold |    score_pct   |
111  * |R9              R0|V |N3     N0|P |A7             A0|S7            S0|
112  *
113  * Layout in memory:
114  *                    bits
115  *        |7     6| 5 |4             2|1 0|
116  *        +-------+---+---------------+---+
117  * byte 0 |S7  S6  S5  S4  S3  S2  S1  S0 |
118  *        +-------------------------------+
119  * byte 1 |A7  A6  A5  A4  A3  A2  A1  A0 |
120  *        +-------+---+---------------+---+
121  * byte 2 |R1  R0 | V |N3  N2  N1  N0 | P |
122  *        +-------------------------------+
123  * byte 3 |R9  R8  R7  R6  R5  R4  R3  R2 |
124  *        +-------------------------------+
125  */
126 #ifdef LITTLE_ENDIAN
127   #define WLANFW_HEALTH_MON_SCORE_PCT_GET(word32) \
128       (((word32) & 0x000000ff) >> 0)
129   #define WLANFW_HEALTH_MON_SCORE_ALARM_THRESHOLD_GET(word32) \
130       (((word32) & 0x0000ff00) >> 8)
131   #define WLANFW_HEALTH_MON_SCORE_OLD_ALARM_STATE_GET(word32) \
132       (((word32) & 0x00010000) >> 16)
133   #define WLANFW_HEALTH_MON_SCORE_NUM_EXTRA_BYTES_GET(word32) \
134       (((word32) & 0x001e0000) >> 17)
135   #define WLANFW_HEALTH_MON_SCORE_VALID_DATA_FLAG_GET(word32) \
136       (((word32) & 0x00200000) >> 21)
137 #else
138   /*
139    * When read into a big-endian 32-bit word:
140    *                                bits
141    * |31            24|23          16|15 14|13|12    9|8 |7               0|
142    * +----------------+--------------+-------------------+-----------------+
143    * |S7            S0|A7          A0|R1 R0|V |N3   N0|P |R9             R2|
144    */
145   /*
146    * big-endian macro def to extract score_pct = S7:S0 = byte3
147    */
148   #define WLANFW_HEALTH_MON_SCORE_PCT_GET(word32) \
149       (((word32) >> 24) && 0xff)
150   /*
151    * big-endian macro def to extract alarm_threshold = A7:A0 = byte2
152    */
153   #define WLANFW_HEALTH_MON_SCORE_ALARM_THRESHOLD_GET(word32) \
154       (((word32) >> 16) && 0xff)
155   /*
156    * big-endian macro def to extract old_alarm_state = P = byte1 & 0x1
157    */
158   #define WLANFW_HEALTH_MON_SCORE_OLD_ALARM_STATE_GET(word32) \
159       (((word32) >> 8) && 0x01)
160   /*
161    * big-endian macro def to extract num_extra_bytes = N3:N0 = (byte1>>1) & 0xf
162    */
163   #define WLANFW_HEALTH_MON_SCORE_NUM_EXTRA_BYTES_GET(word32) \
164       (((word32) >> 9) && 0x0f)
165   /*
166    * big-endian macro def to extract valid_data_flag = V = (byte1 >> 5) & 0x1
167    */
168   #define WLANFW_HEALTH_MON_SCORE_VALID_DATA_FLAG_GET(word32) \
169       (((word32) >> 13) && 0x01)
170 #endif
171 
172 
173 typedef struct _wlanfw_health_mon_metric_upload {
174     union {
175         A_UINT32 metric_id;         /* Metric ID
176                                      * Unique ID assigned to every metric registered
177                                      */
178         struct {
179             A_UINT32 module_id:8,       /* module_id:
180                                      * Unique ID assigned to the FW module that owns the metric.
181                                      * Refer to WLAN_MODULE_ID enum.
182                                      */
183                 metric_local_id:7, /* metric_local_id:
184                                      * Unique ID (within the module) assigned to this type of metric by the module that owns the metric.
185                                      */
186                 instance_id:17;    /* instance_id:
187                                      * The ID of the owner of this particular instance of the metric.
188                                      * E.g. for a per-pdev metric, this is the pdev_id, for a per-vdev metric this is the vdev_id, etc.
189                                      */
190         };
191     };
192 
193     union {
194         A_UINT32 word1;
195 
196         struct {
197             A_UINT32 score_pct:8, /* range: 0 (bad) - 100 (perfect) */
198             alarm_threshold:8, /* alarm_threshold:
199                                 * If the metric's score falls below this threshold, the characteristic measured by the metric is a concern.
200                                 * If the score is above this threshold the characteristic in question is behaving normally.
201                                 * Any metrics that are purely for measurement (i.e. not for fault detection) should have alarm_threshold = 0.
202                                 */
203             old_alarm_state:1,  /* old_alarm_state:
204                                 * This flag indicates whether a score_pct below the alarm_threshold is new (old_alarm_state = 0) or ongoing (old_alarm_state = 1).
205                                 */
206             num_extra_bytes:4,  /* num_extra_words32:
207                                  * How many valid extra 4-byte words of metric-specific context follow this struct.
208                                  */
209             valid_data_flag:1,  /* valid_data_flag:
210                                 * Indication of whether this metric is in-use and containing valid data, or unallocated and invalid.
211                                 * Since the target may upload all metric objects, both those that are in use and those that are available but unused, the host must check this flag to see whether the metric object contains valid data.
212                                 */
213             reserved:10;
214         };
215     };
216 
217     /* Extra scratch space for metric specific context data, e.g. the raw data used to compute the score_pct. */
218     A_UINT32 extra_data[WLANFW_HEALTH_MON_EXTRA_WORDS32];
219 } wlanfw_health_mon_metric_upload_t;
220 
221 typedef enum {
222     WLANFW_HEALTH_MON_UPLOAD_FMT_INVALID = 0,
223 
224     /* V1: metrics use the wlanfw_health_mon_metric_upload_t format */
225     WLANFW_HEALTH_MON_UPLOAD_FMT_V1 = 1,
226 } wlanfw_health_mon_upload_fmt;
227 
228 typedef struct _wlanfw_health_mon_upload_ring {
229     wlanfw_health_mon_upload_fmt version_number;    /* version_number:
230                                                      * Specifies the format of the uploaded records.
231                                                      * 0 - unused
232                                                      * 1 - the upload records use the wlanfw_health_mon_metric_upload_t format.
233                                                      *     (WLANFW_HEALTH_MON_UPLOAD_FMT_V1)
234                                                      * All other values are reserved.
235                                                      */
236     /* specifies how large each element within the upload ring is */
237     A_UINT32 ring_element_bytes;
238     /* specifies how many spaces the ring contains */
239     A_UINT32 num_ring_elements;
240     /* specifies which ring element was last written by the target */
241     A_UINT32 write_index;
242 } wlanfw_health_mon_upload_ring_t;
243 
244 typedef struct _wlanfw_health_mon_upload_ring_elem_t {
245     A_UINT32 timestamp;
246     /* how much of the head portion of the ring element contains valid data */
247     A_UINT32 num_valid_bytes;
248 } wlanfw_health_mon_upload_ring_elem_t;
249 
250 
251 #endif /* __WLANFW_HEALTH_MON_H__*/
252