Using the common protocol helper implementation add support for all new SCMIv3.1 extended names commands related to all protocols with the exception of SENSOR_AXIS_GET_NAME.
Unified · Split
| @@ -16,6 +16,7 @@ enum scmi_clock_protocol_cmd { · 15 unmodified lines | ||
| 16 | 16 | CLOCK_RATE_SET = 0x5, |
| 17 | 17 | CLOCK_RATE_GET = 0x6, |
| 18 | 18 | CLOCK_CONFIG_SET = 0x7, |
| 19 | + CLOCK_NAME_GET = 0x8, | |
| 19 | 20 | }; |
| 20 | 21 | |
| 21 | 22 | struct scmi_msg_resp_clock_protocol_attributes { |
| @@ -27,7 +28,8 @@ struct scmi_msg_resp_clock_protocol_attributes { · 5 unmodified lines | ||
| 27 | 28 | struct scmi_msg_resp_clock_attributes { |
| 28 | 29 | __le32 attributes; |
| 29 | 30 | #define CLOCK_ENABLE BIT(0) |
| 30 | − u8 name[SCMI_MAX_STR_SIZE]; | |
| 31 | +#define SUPPORTS_EXTENDED_NAMES(x) ((x) & BIT(29)) | |
| 32 | + u8 name[SCMI_SHORT_NAME_MAX_SIZE]; | |
| 31 | 33 | __le32 clock_enable_latency; |
| 32 | 34 | }; |
| 33 | 35 | |
| @@ -108,9 +110,11 @@ scmi_clock_protocol_attributes_get(const struct scmi_protocol_handle *ph, · 74 unmodified lines | ||
| 108 | 110 | } |
| 109 | 111 | |
| 110 | 112 | static int scmi_clock_attributes_get(const struct scmi_protocol_handle *ph, |
| 111 | − u32 clk_id, struct scmi_clock_info *clk) | |
| 113 | + u32 clk_id, struct scmi_clock_info *clk, | |
| 114 | + u32 version) | |
| 112 | 115 | { |
| 113 | 116 | int ret; |
| 117 | + u32 attributes; | |
| 114 | 118 | struct scmi_xfer *t; |
| 115 | 119 | struct scmi_msg_resp_clock_attributes *attr; |
| 116 | 120 | |
| @@ -124,6 +128,7 @@ static int scmi_clock_attributes_get(const struct scmi_protocol_handle *ph, · 7 unmodified lines | ||
| 124 | 128 | |
| 125 | 129 | ret = ph->xops->do_xfer(ph, t); |
| 126 | 130 | if (!ret) { |
| 131 | + attributes = le32_to_cpu(attr->attributes); | |
| 127 | 132 | strlcpy(clk->name, attr->name, SCMI_MAX_STR_SIZE); |
| 128 | 133 | /* Is optional field clock_enable_latency provided ? */ |
| 129 | 134 | if (t->rx.len == sizeof(*attr)) |
| @@ -132,6 +137,16 @@ static int scmi_clock_attributes_get(const struct scmi_protocol_handle *ph, · 2 unmodified lines | ||
| 132 | 137 | } |
| 133 | 138 | |
| 134 | 139 | ph->xops->xfer_put(ph, t); |
| 140 | + | |
| 141 | + /* | |
| 142 | + * If supported overwrite short name with the extended one; | |
| 143 | + * on error just carry on and use already provided short name. | |
| 144 | + */ | |
| 145 | + if (!ret && PROTOCOL_REV_MAJOR(version) >= 0x2 && | |
| 146 | + SUPPORTS_EXTENDED_NAMES(attributes)) | |
| 147 | + ph->hops->extended_name_get(ph, CLOCK_NAME_GET, clk_id, | |
| 148 | + clk->name, SCMI_MAX_STR_SIZE); | |
| 149 | + | |
| 135 | 150 | return ret; |
| 136 | 151 | } |
| 137 | 152 | |
| @@ -400,7 +415,7 @@ static int scmi_clock_protocol_init(const struct scmi_protocol_handle *ph) · 262 unmodified lines | ||
| 400 | 415 | for (clkid = 0; clkid < cinfo->num_clocks; clkid++) { |
| 401 | 416 | struct scmi_clock_info *clk = cinfo->clk + clkid; |
| 402 | 417 | |
| 403 | − ret = scmi_clock_attributes_get(ph, clkid, clk); | |
| 418 | + ret = scmi_clock_attributes_get(ph, clkid, clk, version); | |
| 404 | 419 | if (!ret) |
| 405 | 420 | scmi_clock_describe_rates_get(ph, clkid, clk); |
| 406 | 421 | } |
| @@ -32,6 +32,7 @@ enum scmi_performance_protocol_cmd { · 31 unmodified lines | ||
| 32 | 32 | PERF_NOTIFY_LIMITS = 0x9, |
| 33 | 33 | PERF_NOTIFY_LEVEL = 0xa, |
| 34 | 34 | PERF_DESCRIBE_FASTCHANNEL = 0xb, |
| 35 | + PERF_DOMAIN_NAME_GET = 0xc, | |
| 35 | 36 | }; |
| 36 | 37 | |
| 37 | 38 | struct scmi_opp { |
| @@ -56,10 +57,11 @@ struct scmi_msg_resp_perf_domain_attributes { · 18 unmodified lines | ||
| 56 | 57 | #define SUPPORTS_PERF_LIMIT_NOTIFY(x) ((x) & BIT(29)) |
| 57 | 58 | #define SUPPORTS_PERF_LEVEL_NOTIFY(x) ((x) & BIT(28)) |
| 58 | 59 | #define SUPPORTS_PERF_FASTCHANNELS(x) ((x) & BIT(27)) |
| 60 | +#define SUPPORTS_EXTENDED_NAMES(x) ((x) & BIT(26)) | |
| 59 | 61 | __le32 rate_limit_us; |
| 60 | 62 | __le32 sustained_freq_khz; |
| 61 | 63 | __le32 sustained_perf_level; |
| 62 | − u8 name[SCMI_MAX_STR_SIZE]; | |
| 64 | + u8 name[SCMI_SHORT_NAME_MAX_SIZE]; | |
| 63 | 65 | }; |
| 64 | 66 | |
| 65 | 67 | struct scmi_msg_perf_describe_levels { |
| @@ -209,9 +211,11 @@ static int scmi_perf_attributes_get(const struct scmi_protocol_handle *ph, · 143 unmodified lines | ||
| 209 | 211 | |
| 210 | 212 | static int |
| 211 | 213 | scmi_perf_domain_attributes_get(const struct scmi_protocol_handle *ph, |
| 212 | − u32 domain, struct perf_dom_info *dom_info) | |
| 214 | + u32 domain, struct perf_dom_info *dom_info, | |
| 215 | + u32 version) | |
| 213 | 216 | { |
| 214 | 217 | int ret; |
| 218 | + u32 flags; | |
| 215 | 219 | struct scmi_xfer *t; |
| 216 | 220 | struct scmi_msg_resp_perf_domain_attributes *attr; |
| 217 | 221 | |
| @@ -225,7 +229,7 @@ scmi_perf_domain_attributes_get(const struct scmi_protocol_handle *ph, · 7 unmodified lines | ||
| 225 | 229 | |
| 226 | 230 | ret = ph->xops->do_xfer(ph, t); |
| 227 | 231 | if (!ret) { |
| 228 | − u32 flags = le32_to_cpu(attr->flags); | |
| 232 | + flags = le32_to_cpu(attr->flags); | |
| 229 | 233 | |
| 230 | 234 | dom_info->set_limits = SUPPORTS_SET_LIMITS(flags); |
| 231 | 235 | dom_info->set_perf = SUPPORTS_SET_PERF_LVL(flags); |
| @@ -248,6 +252,16 @@ scmi_perf_domain_attributes_get(const struct scmi_protocol_handle *ph, · 16 unmodified lines | ||
| 248 | 252 | } |
| 249 | 253 | |
| 250 | 254 | ph->xops->xfer_put(ph, t); |
| 255 | + | |
| 256 | + /* | |
| 257 | + * If supported overwrite short name with the extended one; | |
| 258 | + * on error just carry on and use already provided short name. | |
| 259 | + */ | |
| 260 | + if (!ret && PROTOCOL_REV_MAJOR(version) >= 0x3 && | |
| 261 | + SUPPORTS_EXTENDED_NAMES(flags)) | |
| 262 | + ph->hops->extended_name_get(ph, PERF_DOMAIN_NAME_GET, domain, | |
| 263 | + dom_info->name, SCMI_MAX_STR_SIZE); | |
| 264 | + | |
| 251 | 265 | return ret; |
| 252 | 266 | } |
| 253 | 267 | |
| @@ -902,7 +916,7 @@ static int scmi_perf_protocol_init(const struct scmi_protocol_handle *ph) · 648 unmodified lines | ||
| 902 | 916 | for (domain = 0; domain < pinfo->num_domains; domain++) { |
| 903 | 917 | struct perf_dom_info *dom = pinfo->dom_info + domain; |
| 904 | 918 | |
| 905 | − scmi_perf_domain_attributes_get(ph, domain, dom); | |
| 919 | + scmi_perf_domain_attributes_get(ph, domain, dom, version); | |
| 906 | 920 | scmi_perf_describe_levels_get(ph, domain, dom); |
| 907 | 921 | |
| 908 | 922 | if (dom->perf_fastchannels) |
| @@ -18,6 +18,7 @@ enum scmi_power_protocol_cmd { · 17 unmodified lines | ||
| 18 | 18 | POWER_STATE_SET = 0x4, |
| 19 | 19 | POWER_STATE_GET = 0x5, |
| 20 | 20 | POWER_STATE_NOTIFY = 0x6, |
| 21 | + POWER_DOMAIN_NAME_GET = 0x8, | |
| 21 | 22 | }; |
| 22 | 23 | |
| 23 | 24 | struct scmi_msg_resp_power_attributes { |
| @@ -33,7 +34,8 @@ struct scmi_msg_resp_power_domain_attributes { · 9 unmodified lines | ||
| 33 | 34 | #define SUPPORTS_STATE_SET_NOTIFY(x) ((x) & BIT(31)) |
| 34 | 35 | #define SUPPORTS_STATE_SET_ASYNC(x) ((x) & BIT(30)) |
| 35 | 36 | #define SUPPORTS_STATE_SET_SYNC(x) ((x) & BIT(29)) |
| 36 | − u8 name[SCMI_MAX_STR_SIZE]; | |
| 37 | +#define SUPPORTS_EXTENDED_NAMES(x) ((x) & BIT(27)) | |
| 38 | + u8 name[SCMI_SHORT_NAME_MAX_SIZE]; | |
| 37 | 39 | }; |
| 38 | 40 | |
| 39 | 41 | struct scmi_power_set_state { |
| @@ -97,9 +99,11 @@ static int scmi_power_attributes_get(const struct scmi_protocol_handle *ph, · 57 unmodified lines | ||
| 97 | 99 | |
| 98 | 100 | static int |
| 99 | 101 | scmi_power_domain_attributes_get(const struct scmi_protocol_handle *ph, |
| 100 | − u32 domain, struct power_dom_info *dom_info) | |
| 102 | + u32 domain, struct power_dom_info *dom_info, | |
| 103 | + u32 version) | |
| 101 | 104 | { |
| 102 | 105 | int ret; |
| 106 | + u32 flags; | |
| 103 | 107 | struct scmi_xfer *t; |
| 104 | 108 | struct scmi_msg_resp_power_domain_attributes *attr; |
| 105 | 109 | |
| @@ -113,15 +117,26 @@ scmi_power_domain_attributes_get(const struct scmi_protocol_handle *ph, · 7 unmodified lines | ||
| 113 | 117 | |
| 114 | 118 | ret = ph->xops->do_xfer(ph, t); |
| 115 | 119 | if (!ret) { |
| 116 | − u32 flags = le32_to_cpu(attr->flags); | |
| 120 | + flags = le32_to_cpu(attr->flags); | |
| 117 | 121 | |
| 118 | 122 | dom_info->state_set_notify = SUPPORTS_STATE_SET_NOTIFY(flags); |
| 119 | 123 | dom_info->state_set_async = SUPPORTS_STATE_SET_ASYNC(flags); |
| 120 | 124 | dom_info->state_set_sync = SUPPORTS_STATE_SET_SYNC(flags); |
| 121 | 125 | strlcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE); |
| 122 | 126 | } |
| 123 | − | |
| 124 | 127 | ph->xops->xfer_put(ph, t); |
| 128 | + | |
| 129 | + /* | |
| 130 | + * If supported overwrite short name with the extended one; | |
| 131 | + * on error just carry on and use already provided short name. | |
| 132 | + */ | |
| 133 | + if (!ret && PROTOCOL_REV_MAJOR(version) >= 0x3 && | |
| 134 | + SUPPORTS_EXTENDED_NAMES(flags)) { | |
| 135 | + ph->hops->extended_name_get(ph, POWER_DOMAIN_NAME_GET, | |
| 136 | + domain, dom_info->name, | |
| 137 | + SCMI_MAX_STR_SIZE); | |
| 138 | + } | |
| 139 | + | |
| 125 | 140 | return ret; |
| 126 | 141 | } |
| 127 | 142 | |
| @@ -308,7 +323,7 @@ static int scmi_power_protocol_init(const struct scmi_protocol_handle *ph) · 180 unmodified lines | ||
| 308 | 323 | for (domain = 0; domain < pinfo->num_domains; domain++) { |
| 309 | 324 | struct power_dom_info *dom = pinfo->dom_info + domain; |
| 310 | 325 | |
| 311 | − scmi_power_domain_attributes_get(ph, domain, dom); | |
| 326 | + scmi_power_domain_attributes_get(ph, domain, dom, version); | |
| 312 | 327 | } |
| 313 | 328 | |
| 314 | 329 | pinfo->version = version; |
| @@ -24,6 +24,8 @@ · 23 unmodified lines | ||
| 24 | 24 | |
| 25 | 25 | #include <asm/unaligned.h> |
| 26 | 26 | |
| 27 | +#define SCMI_SHORT_NAME_MAX_SIZE 16 | |
| 28 | + | |
| 27 | 29 | #define PROTOCOL_REV_MINOR_MASK GENMASK(15, 0) |
| 28 | 30 | #define PROTOCOL_REV_MAJOR_MASK GENMASK(31, 16) |
| 29 | 31 | #define PROTOCOL_REV_MAJOR(x) ((u16)(FIELD_GET(PROTOCOL_REV_MAJOR_MASK, (x)))) |
| @@ -17,6 +17,7 @@ enum scmi_reset_protocol_cmd { · 16 unmodified lines | ||
| 17 | 17 | RESET_DOMAIN_ATTRIBUTES = 0x3, |
| 18 | 18 | RESET = 0x4, |
| 19 | 19 | RESET_NOTIFY = 0x5, |
| 20 | + RESET_DOMAIN_NAME_GET = 0x6, | |
| 20 | 21 | }; |
| 21 | 22 | |
| 22 | 23 | #define NUM_RESET_DOMAIN_MASK 0xffff |
| @@ -26,8 +27,9 @@ struct scmi_msg_resp_reset_domain_attributes { · 3 unmodified lines | ||
| 26 | 27 | __le32 attributes; |
| 27 | 28 | #define SUPPORTS_ASYNC_RESET(x) ((x) & BIT(31)) |
| 28 | 29 | #define SUPPORTS_NOTIFY_RESET(x) ((x) & BIT(30)) |
| 30 | +#define SUPPORTS_EXTENDED_NAMES(x) ((x) & BIT(29)) | |
| 29 | 31 | __le32 latency; |
| 30 | − u8 name[SCMI_MAX_STR_SIZE]; | |
| 32 | + u8 name[SCMI_SHORT_NAME_MAX_SIZE]; | |
| 31 | 33 | }; |
| 32 | 34 | |
| 33 | 35 | struct scmi_msg_reset_domain_reset { |
| @@ -89,9 +91,11 @@ static int scmi_reset_attributes_get(const struct scmi_protocol_handle *ph, · 55 unmodified lines | ||
| 89 | 91 | |
| 90 | 92 | static int |
| 91 | 93 | scmi_reset_domain_attributes_get(const struct scmi_protocol_handle *ph, |
| 92 | − u32 domain, struct reset_dom_info *dom_info) | |
| 94 | + u32 domain, struct reset_dom_info *dom_info, | |
| 95 | + u32 version) | |
| 93 | 96 | { |
| 94 | 97 | int ret; |
| 98 | + u32 attributes; | |
| 95 | 99 | struct scmi_xfer *t; |
| 96 | 100 | struct scmi_msg_resp_reset_domain_attributes *attr; |
| 97 | 101 | |
| @@ -105,7 +109,7 @@ scmi_reset_domain_attributes_get(const struct scmi_protocol_handle *ph, · 7 unmodified lines | ||
| 105 | 109 | |
| 106 | 110 | ret = ph->xops->do_xfer(ph, t); |
| 107 | 111 | if (!ret) { |
| 108 | − u32 attributes = le32_to_cpu(attr->attributes); | |
| 112 | + attributes = le32_to_cpu(attr->attributes); | |
| 109 | 113 | |
| 110 | 114 | dom_info->async_reset = SUPPORTS_ASYNC_RESET(attributes); |
| 111 | 115 | dom_info->reset_notify = SUPPORTS_NOTIFY_RESET(attributes); |
| @@ -116,6 +120,16 @@ scmi_reset_domain_attributes_get(const struct scmi_protocol_handle *ph, · 4 unmodified lines | ||
| 116 | 120 | } |
| 117 | 121 | |
| 118 | 122 | ph->xops->xfer_put(ph, t); |
| 123 | + | |
| 124 | + /* | |
| 125 | + * If supported overwrite short name with the extended one; | |
| 126 | + * on error just carry on and use already provided short name. | |
| 127 | + */ | |
| 128 | + if (!ret && PROTOCOL_REV_MAJOR(version) >= 0x3 && | |
| 129 | + SUPPORTS_EXTENDED_NAMES(attributes)) | |
| 130 | + ph->hops->extended_name_get(ph, RESET_DOMAIN_NAME_GET, domain, | |
| 131 | + dom_info->name, SCMI_MAX_STR_SIZE); | |
| 132 | + | |
| 119 | 133 | return ret; |
| 120 | 134 | } |
| 121 | 135 | |
| @@ -320,7 +334,7 @@ static int scmi_reset_protocol_init(const struct scmi_protocol_handle *ph) · 198 unmodified lines | ||
| 320 | 334 | for (domain = 0; domain < pinfo->num_domains; domain++) { |
| 321 | 335 | struct reset_dom_info *dom = pinfo->dom_info + domain; |
| 322 | 336 | |
| 323 | − scmi_reset_domain_attributes_get(ph, domain, dom); | |
| 337 | + scmi_reset_domain_attributes_get(ph, domain, dom, version); | |
| 324 | 338 | } |
| 325 | 339 | |
| 326 | 340 | pinfo->version = version; |
| @@ -27,6 +27,7 @@ enum scmi_sensor_protocol_cmd { · 26 unmodified lines | ||
| 27 | 27 | SENSOR_CONFIG_GET = 0x9, |
| 28 | 28 | SENSOR_CONFIG_SET = 0xA, |
| 29 | 29 | SENSOR_CONTINUOUS_UPDATE_NOTIFY = 0xB, |
| 30 | + SENSOR_NAME_GET = 0xC, | |
| 30 | 31 | }; |
| 31 | 32 | |
| 32 | 33 | struct scmi_msg_resp_sensor_attributes { |
| @@ -71,6 +72,7 @@ struct scmi_msg_resp_sensor_description { · 38 unmodified lines | ||
| 71 | 72 | __le32 attributes_low; |
| 72 | 73 | /* Common attributes_low macros */ |
| 73 | 74 | #define SUPPORTS_ASYNC_READ(x) FIELD_GET(BIT(31), (x)) |
| 75 | +#define SUPPORTS_EXTENDED_NAMES(x) FIELD_GET(BIT(29), (x)) | |
| 74 | 76 | #define NUM_TRIP_POINTS(x) FIELD_GET(GENMASK(7, 0), (x)) |
| 75 | 77 | __le32 attributes_high; |
| 76 | 78 | /* Common attributes_high macros */ |
| @@ -78,7 +80,7 @@ struct scmi_msg_resp_sensor_description { · 1 unmodified line | ||
| 78 | 80 | #define SENSOR_SCALE_SIGN BIT(4) |
| 79 | 81 | #define SENSOR_SCALE_EXTEND GENMASK(31, 5) |
| 80 | 82 | #define SENSOR_TYPE(x) FIELD_GET(GENMASK(7, 0), (x)) |
| 81 | − u8 name[SCMI_MAX_STR_SIZE]; | |
| 83 | + u8 name[SCMI_SHORT_NAME_MAX_SIZE]; | |
| 82 | 84 | /* only for version > 2.0 */ |
| 83 | 85 | __le32 power; |
| 84 | 86 | __le32 resolution; |
| @@ -519,6 +521,17 @@ static int scmi_sensor_description_get(const struct scmi_protocol_handle *ph, · 434 unmodified lines | ||
| 519 | 521 | SCMI_MAX_NUM_SENSOR_AXIS); |
| 520 | 522 | strlcpy(s->name, sdesc->name, SCMI_MAX_STR_SIZE); |
| 521 | 523 | |
| 524 | + /* | |
| 525 | + * If supported overwrite short name with the extended | |
| 526 | + * one; on error just carry on and use already provided | |
| 527 | + * short name. | |
| 528 | + */ | |
| 529 | + if (PROTOCOL_REV_MAJOR(si->version) >= 0x3 && | |
| 530 | + SUPPORTS_EXTENDED_NAMES(attrl)) | |
| 531 | + ph->hops->extended_name_get(ph, SENSOR_NAME_GET, | |
| 532 | + s->id, s->name, | |
| 533 | + SCMI_MAX_STR_SIZE); | |
| 534 | + | |
| 522 | 535 | if (s->extended_scalar_attrs) { |
| 523 | 536 | s->sensor_power = le32_to_cpu(sdesc->power); |
| 524 | 537 | dsize += sizeof(sdesc->power); |
| @@ -21,13 +21,15 @@ enum scmi_voltage_protocol_cmd { · 20 unmodified lines | ||
| 21 | 21 | VOLTAGE_CONFIG_GET = 0x6, |
| 22 | 22 | VOLTAGE_LEVEL_SET = 0x7, |
| 23 | 23 | VOLTAGE_LEVEL_GET = 0x8, |
| 24 | + VOLTAGE_DOMAIN_NAME_GET = 0x09, | |
| 24 | 25 | }; |
| 25 | 26 | |
| 26 | 27 | #define NUM_VOLTAGE_DOMAINS(x) ((u16)(FIELD_GET(VOLTAGE_DOMS_NUM_MASK, (x)))) |
| 27 | 28 | |
| 28 | 29 | struct scmi_msg_resp_domain_attributes { |
| 29 | 30 | __le32 attr; |
| 30 | − u8 name[SCMI_MAX_STR_SIZE]; | |
| 31 | +#define SUPPORTS_EXTENDED_NAMES(x) ((x) & BIT(30)) | |
| 32 | + u8 name[SCMI_SHORT_NAME_MAX_SIZE]; | |
| 31 | 33 | }; |
| 32 | 34 | |
| 33 | 35 | struct scmi_msg_cmd_describe_levels { |
| @@ -149,6 +151,16 @@ static int scmi_voltage_descriptors_get(const struct scmi_protocol_handle *ph, · 115 unmodified lines | ||
| 149 | 151 | v->attributes = le32_to_cpu(resp_dom->attr); |
| 150 | 152 | strlcpy(v->name, resp_dom->name, SCMI_MAX_STR_SIZE); |
| 151 | 153 | |
| 154 | + /* | |
| 155 | + * If supported overwrite short name with the extended one; | |
| 156 | + * on error just carry on and use already provided short name. | |
| 157 | + */ | |
| 158 | + if (PROTOCOL_REV_MAJOR(vinfo->version) >= 0x2 && | |
| 159 | + SUPPORTS_EXTENDED_NAMES(v->attributes)) | |
| 160 | + ph->hops->extended_name_get(ph, VOLTAGE_DOMAIN_NAME_GET, | |
| 161 | + v->id, v->name, | |
| 162 | + SCMI_MAX_STR_SIZE); | |
| 163 | + | |
| 152 | 164 | cmd = tl->tx.buf; |
| 153 | 165 | /* ...then retrieve domain levels descriptions */ |
| 154 | 166 | do { |
| @@ -13,7 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/notifier.h> |
| 14 | 14 | #include <linux/types.h> |
| 15 | 15 | |
| 16 | −#define SCMI_MAX_STR_SIZE 16 | |
| 16 | +#define SCMI_MAX_STR_SIZE 64 | |
| 17 | 17 | #define SCMI_MAX_NUM_RATES 16 |
| 18 | 18 | |
| 19 | 19 | /** |