Coverage Report

Created: 2026-07-25 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/nsmd/libnsm/platform-environmental.c
Line
Count
Source
1
/*
2
 * SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION &
3
 * AFFILIATES. All rights reserved. SPDX-License-Identifier: Apache-2.0
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 * http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
#include "platform-environmental.h"
19
#include "base.h"
20
21
#include <endian.h>
22
#include <stdio.h>
23
#include <string.h>
24
25
#ifdef ENABLE_GRACE_SPI_OPERATIONS
26
int encode_send_spi_command_req(uint8_t instance_id, struct nsm_msg *msg,
27
        enum nsm_spi_command command)
28
{
29
  if (msg == NULL) {
30
    return NSM_SW_ERROR_NULL;
31
  }
32
33
  struct nsm_header_info header = {0};
34
  header.nsm_msg_type = NSM_REQUEST;
35
  header.instance_id = instance_id;
36
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
37
38
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
39
  if (rc != NSM_SW_SUCCESS) {
40
    return rc;
41
  }
42
43
  struct nsm_send_spi_command_req *request =
44
      (struct nsm_send_spi_command_req *)msg->payload;
45
46
  request->hdr.command = NSM_SET_SPI;
47
  request->hdr.data_size = 3;
48
  request->nsm_spi_command = NSM_WRITE_SPI_DATA;
49
  request->spi_data_select = 0x00;
50
  request->spi_command = command;
51
52
  return NSM_SW_SUCCESS;
53
}
54
55
int decode_send_spi_command_resp(const struct nsm_msg *msg, size_t msg_len,
56
         uint8_t *cc, uint16_t *reason_code)
57
{
58
  // NOTE: Decode reason code function checks pointers passed in
59
  // (msg, msg_len, cc, and reason_code)
60
  // so they are not checked here before use
61
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
62
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
63
    return rc;
64
  }
65
66
  if (msg_len < sizeof(struct nsm_msg_hdr) +
67
        sizeof(struct nsm_send_spi_command_resp)) {
68
    return NSM_SW_ERROR_LENGTH;
69
  }
70
71
  return NSM_SW_SUCCESS;
72
}
73
74
int encode_send_spi_transaction_req(uint8_t instance_id, struct nsm_msg *msg,
75
            uint16_t write_bytes, uint16_t read_bytes)
76
{
77
  if (msg == NULL) {
78
    return NSM_SW_ERROR_NULL;
79
  }
80
81
  // The max number of bytes that can be written or read is 256, so check
82
  // sizes
83
  if (write_bytes > 256) {
84
    return NSM_SW_ERROR_DATA;
85
  }
86
87
  if (read_bytes > 256) {
88
    return NSM_SW_ERROR_DATA;
89
  }
90
91
  struct nsm_header_info header = {0};
92
  header.nsm_msg_type = NSM_REQUEST;
93
  header.instance_id = instance_id;
94
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
95
96
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
97
  if (rc != NSM_SW_SUCCESS) {
98
    return rc;
99
  }
100
101
  struct nsm_send_spi_transaction_req *request =
102
      (struct nsm_send_spi_transaction_req *)msg->payload;
103
104
  request->hdr.command = NSM_SET_SPI;
105
  request->hdr.data_size = 0x0c;
106
  request->command_byte = NSM_CONFIGURE_SPI_TRANSACTION;
107
  request->unused = 0x00;
108
  request->bytes_to_write_lsb = write_bytes & 0xff;
109
  request->bytes_to_write_msb = write_bytes >> 8;
110
  request->bytes_to_read_lsb = read_bytes & 0xff;
111
  request->bytes_to_read_msb = read_bytes >> 8;
112
  request->mode = 0x00;
113
  request->target = 0x00;
114
  request->bus = 0x00;
115
  request->reserved = 0x00;
116
  request->turnaround_cycles = 0x00;
117
  request->command_bytes = 0x01;
118
119
  return NSM_SW_SUCCESS;
120
}
121
122
int decode_send_spi_transaction_resp(const struct nsm_msg *msg, size_t msg_len,
123
             uint8_t *cc, uint16_t *reason_code)
124
{
125
  // NOTE: Decode reason code function checks pointers passed in
126
  // (msg, msg_len, cc, and reason_code)
127
  // so they are not checked here before use
128
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
129
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
130
    return rc;
131
  }
132
133
  if (msg_len < sizeof(struct nsm_msg_hdr) +
134
        sizeof(struct nsm_send_spi_transaction_resp)) {
135
    return NSM_SW_ERROR_LENGTH;
136
  }
137
138
  // struct nsm_send_spi_command_resp *resp =
139
  //     (struct nsm_send_spi_command_resp*)msg->payload;
140
141
  return NSM_SW_SUCCESS;
142
}
143
144
int encode_send_spi_operation_req(uint8_t instance_id, struct nsm_msg *msg,
145
          uint32_t address,
146
          enum nsm_spi_command command)
147
{
148
  if (msg == NULL) {
149
    return NSM_SW_ERROR_NULL;
150
  }
151
152
  struct nsm_header_info header = {0};
153
  header.nsm_msg_type = NSM_REQUEST;
154
  header.instance_id = instance_id;
155
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
156
157
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
158
  if (rc != NSM_SW_SUCCESS) {
159
    return rc;
160
  }
161
162
  struct nsm_send_spi_operation_req *request =
163
      (struct nsm_send_spi_operation_req *)msg->payload;
164
165
  request->hdr.command = NSM_SET_SPI;
166
  request->hdr.data_size = 7;
167
  request->command_byte = NSM_WRITE_SPI_DATA;
168
  request->block = 0x00;
169
  request->spi_command = command;
170
  // The address passed in is a 4byte address in a uint32_t
171
  // Split the address out to individual bytes (uin8_t)
172
  request->addr_byte_3 = (address & 0xff000000) >> 24;
173
  request->addr_byte_2 = (address & 0x00ff0000) >> 16;
174
  request->addr_byte_1 = (address & 0x0000ff00) >> 8;
175
  request->addr_byte_0 = (address & 0x000000ff);
176
177
  return NSM_SW_SUCCESS;
178
}
179
180
int decode_send_spi_operation_resp(const struct nsm_msg *msg, size_t msg_len,
181
           uint8_t *cc, uint16_t *reason_code)
182
{
183
  // NOTE: Decode reason code function checks pointers passed in
184
  // (msg, msg_len, cc, and reason_code)
185
  // so they are not checked here before use
186
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
187
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
188
    return rc;
189
  }
190
191
  if (msg_len < (sizeof(struct nsm_msg_hdr) +
192
           sizeof(struct nsm_send_spi_operation_resp))) {
193
    return NSM_SW_ERROR_LENGTH;
194
  }
195
196
  return NSM_SW_SUCCESS;
197
}
198
199
int encode_read_spi_status_req(uint8_t instance_id, struct nsm_msg *msg)
200
{
201
  if (msg == NULL) {
202
    return NSM_SW_ERROR_NULL;
203
  }
204
205
  struct nsm_header_info header = {0};
206
  header.nsm_msg_type = NSM_REQUEST;
207
  header.instance_id = instance_id;
208
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
209
210
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
211
  if (rc != NSM_SW_SUCCESS) {
212
    return rc;
213
  }
214
215
  struct nsm_read_spi_status_req *request =
216
      (struct nsm_read_spi_status_req *)msg->payload;
217
218
  request->hdr.command = NSM_GET_SPI;
219
  request->hdr.data_size = 1;
220
  request->nsm_spi_command = NSM_GET_SPI_TRANSACTION_STATUS;
221
222
  return NSM_SW_SUCCESS;
223
}
224
225
int decode_read_spi_status_resp(const struct nsm_msg *msg, size_t msg_len,
226
        uint8_t *cc, uint16_t *reason_code,
227
        enum nsm_spi_status *spiStatus)
228
{
229
  // NOTE: Decode reason code function checks pointers passed in
230
  // (msg, msg_len, cc, and reason_code)
231
  // so they are not checked here before use
232
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
233
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
234
    return rc;
235
  }
236
237
  if (spiStatus == NULL) {
238
    return NSM_SW_ERROR_NULL;
239
  }
240
241
  if (msg_len < (sizeof(struct nsm_msg_hdr) +
242
           sizeof(struct nsm_read_spi_status_resp))) {
243
    return NSM_SW_ERROR_LENGTH;
244
  }
245
246
  struct nsm_read_spi_status_resp *resp =
247
      (struct nsm_read_spi_status_resp *)msg->payload;
248
249
  if ((resp->spi_status & 0x03) == 0x00) {
250
    *spiStatus = NSM_SPI_READY;
251
  } else if ((resp->spi_status & 0x01) == 0x01) {
252
    *spiStatus = NSM_SPI_BUSY;
253
  } else if (((resp->spi_status & 0x02) >> 1) == 0x01) {
254
    *spiStatus = NSM_SPI_ERROR;
255
  }
256
257
  return NSM_SW_SUCCESS;
258
}
259
260
int encode_read_spi_block_req(uint8_t instance_id, struct nsm_msg *msg,
261
            uint8_t block)
262
{
263
  if (msg == NULL) {
264
    return NSM_SW_ERROR_NULL;
265
  }
266
267
  struct nsm_header_info header = {0};
268
  header.nsm_msg_type = NSM_REQUEST;
269
  header.instance_id = instance_id;
270
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
271
272
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
273
  if (rc != NSM_SW_SUCCESS) {
274
    return rc;
275
  }
276
277
  struct nsm_read_spi_block_req *request =
278
      (struct nsm_read_spi_block_req *)msg->payload;
279
280
  request->hdr.command = NSM_GET_SPI;
281
  request->hdr.data_size = 2;
282
  request->nsm_spi_command = NSM_READ_SPI_DATA;
283
  request->spi_data_select = block;
284
285
  return NSM_SW_SUCCESS;
286
}
287
288
int decode_read_spi_block_resp(const struct nsm_msg *msg, size_t msg_len,
289
             uint8_t *cc, uint16_t *reason_code,
290
             uint8_t *data, uint8_t data_size)
291
{
292
  // NOTE: Decode reason code function checks pointers passed in
293
  // (msg, msg_len, cc, and reason_code)
294
  // so they are not checked here before use
295
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
296
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
297
    return rc;
298
  }
299
300
  if (data == NULL) {
301
    return NSM_SW_ERROR_NULL;
302
  }
303
304
  if (msg_len < (sizeof(struct nsm_msg_hdr) +
305
           sizeof(struct nsm_read_spi_block_resp))) {
306
    return NSM_SW_ERROR_LENGTH;
307
  }
308
309
  if (data_size < 30) {
310
    return NSM_SW_ERROR_LENGTH;
311
  }
312
313
  struct nsm_read_spi_block_resp *resp =
314
      (struct nsm_read_spi_block_resp *)msg->payload;
315
316
  for (uint8_t i = 0; i < 30; i++) {
317
    data[i] = resp->data[i];
318
  }
319
320
  return NSM_SW_SUCCESS;
321
}
322
323
int decode_read_spi_last_block_resp(const struct nsm_msg *msg, size_t msg_len,
324
            uint8_t *cc, uint16_t *reason_code,
325
            uint8_t *data, uint8_t data_size)
326
{
327
  // NOTE: Decode reason code function checks pointers passed in
328
  // (msg, msg_len, cc, and reason_code)
329
  // so they are not checked here before use
330
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
331
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
332
    return rc;
333
  }
334
335
  if (data == NULL) {
336
    return NSM_SW_ERROR_NULL;
337
  }
338
339
  if (msg_len < (sizeof(struct nsm_msg_hdr) +
340
           sizeof(struct nsm_read_spi_last_block_resp))) {
341
    return NSM_SW_ERROR_LENGTH;
342
  }
343
344
  if (data_size < 16) {
345
    return NSM_SW_ERROR_LENGTH;
346
  }
347
348
  struct nsm_read_spi_block_resp *resp =
349
      (struct nsm_read_spi_block_resp *)msg->payload;
350
351
  for (uint8_t i = 0; i < 16; i++) {
352
    data[i] = resp->data[i];
353
  }
354
355
  return NSM_SW_SUCCESS;
356
}
357
#endif
358
359
int encode_get_inventory_information_req(uint8_t instance_id,
360
           uint8_t property_identifier,
361
           struct nsm_msg *msg)
362
0
{
363
0
  if (msg == NULL) {
364
0
    return NSM_SW_ERROR_NULL;
365
0
  }
366
367
0
  struct nsm_header_info header = {0};
368
0
  header.nsm_msg_type = NSM_REQUEST;
369
0
  header.instance_id = instance_id;
370
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
371
372
0
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
373
0
  if (rc != NSM_SW_SUCCESS) {
374
0
    return rc;
375
0
  }
376
377
0
  struct nsm_get_inventory_information_req *request =
378
0
      (struct nsm_get_inventory_information_req *)msg->payload;
379
380
0
  request->hdr.command = NSM_GET_INVENTORY_INFORMATION;
381
0
  request->hdr.data_size = 1;
382
0
  request->property_identifier = property_identifier;
383
384
0
  return NSM_SW_SUCCESS;
385
0
}
386
387
int decode_get_inventory_information_req(const struct nsm_msg *msg,
388
           size_t msg_len,
389
           uint8_t *property_identifier)
390
0
{
391
0
  if (msg == NULL || property_identifier == NULL) {
392
0
    return NSM_SW_ERROR_NULL;
393
0
  }
394
395
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
396
0
        sizeof(struct nsm_get_inventory_information_req)) {
397
0
    return NSM_SW_ERROR_LENGTH;
398
0
  }
399
400
0
  struct nsm_get_inventory_information_req *request =
401
0
      (struct nsm_get_inventory_information_req *)msg->payload;
402
403
0
  if (request->hdr.data_size <
404
0
      sizeof(struct nsm_get_inventory_information_req) -
405
0
    NSM_REQUEST_CONVENTION_LEN) {
406
0
    return NSM_SW_ERROR_DATA;
407
0
  }
408
409
0
  *property_identifier = request->property_identifier;
410
411
0
  return NSM_SW_SUCCESS;
412
0
}
413
414
int encode_get_inventory_information_resp(uint8_t instance_id, uint8_t cc,
415
            uint16_t reason_code,
416
            const uint16_t data_size,
417
            const uint8_t *inventory_information,
418
            struct nsm_msg *msg)
419
0
{
420
0
  if (msg == NULL) {
421
0
    return NSM_SW_ERROR_NULL;
422
0
  }
423
424
0
  struct nsm_header_info header = {0};
425
0
  header.nsm_msg_type = NSM_RESPONSE;
426
0
  header.instance_id = instance_id & INSTANCEID_MASK;
427
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
428
429
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
430
0
  if (rc != NSM_SW_SUCCESS) {
431
0
    return rc;
432
0
  }
433
434
0
  if (cc != NSM_SUCCESS) {
435
0
    return encode_reason_code(cc, reason_code,
436
0
            NSM_GET_INVENTORY_INFORMATION, msg);
437
0
  }
438
439
0
  struct nsm_get_inventory_information_resp *resp =
440
0
      (struct nsm_get_inventory_information_resp *)msg->payload;
441
442
0
  resp->hdr.command = NSM_GET_INVENTORY_INFORMATION;
443
0
  resp->hdr.completion_code = cc;
444
0
  resp->hdr.data_size = htole16(data_size);
445
446
0
  if (cc == NSM_SUCCESS) {
447
0
    {
448
0
      if (inventory_information == NULL) {
449
0
        return NSM_SW_ERROR_NULL;
450
0
      }
451
0
    }
452
0
    memcpy(resp->inventory_information, inventory_information,
453
0
           data_size);
454
0
  }
455
456
0
  return NSM_SW_SUCCESS;
457
0
}
458
459
int decode_get_inventory_information_resp(const struct nsm_msg *msg,
460
            size_t msg_len, uint8_t *cc,
461
            uint16_t *reason_code,
462
            uint16_t *data_size,
463
            uint8_t *inventory_information)
464
0
{
465
0
  if (data_size == NULL || inventory_information == NULL) {
466
0
    return NSM_SW_ERROR_NULL;
467
0
  }
468
469
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
470
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
471
0
    return rc;
472
0
  }
473
474
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
475
0
        sizeof(struct nsm_get_inventory_information_resp)) {
476
0
    return NSM_SW_ERROR_LENGTH;
477
0
  }
478
479
0
  struct nsm_get_inventory_information_resp *resp =
480
0
      (struct nsm_get_inventory_information_resp *)msg->payload;
481
482
0
  *data_size = le16toh(resp->hdr.data_size);
483
0
  memcpy(inventory_information, resp->inventory_information, *data_size);
484
485
0
  return NSM_SW_SUCCESS;
486
0
}
487
488
int encode_get_platform_env_command_no_payload_req(
489
    uint8_t instance_id, struct nsm_msg *msg,
490
    enum nsm_platform_environmental_commands command)
491
0
{
492
0
  if (msg == NULL) {
493
0
    return NSM_SW_ERROR_NULL;
494
0
  }
495
496
0
  struct nsm_header_info header = {0};
497
0
  header.nsm_msg_type = NSM_REQUEST;
498
0
  header.instance_id = instance_id;
499
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
500
501
0
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
502
0
  if (rc != NSM_SW_SUCCESS) {
503
0
    return rc;
504
0
  }
505
506
0
  struct nsm_common_req *request = (struct nsm_common_req *)msg->payload;
507
508
0
  request->command = command;
509
0
  request->data_size = 0;
510
0
  return NSM_SW_SUCCESS;
511
0
}
512
513
int decode_get_platform_env_command_no_payload_req(
514
    const struct nsm_msg *msg, size_t msg_len,
515
    __attribute__((unused)) enum nsm_platform_environmental_commands command)
516
0
{
517
0
  if (msg == NULL) {
518
0
    return NSM_SW_ERROR_NULL;
519
0
  }
520
521
0
  if (msg_len <
522
0
      sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_common_req)) {
523
0
    return NSM_SW_ERROR_LENGTH;
524
0
  }
525
0
  return NSM_SW_SUCCESS;
526
0
}
527
528
uint32_t
529
decode_inventory_information_as_uint32(const uint8_t *inventory_information,
530
               const uint16_t data_size)
531
0
{
532
0
  if (data_size < sizeof(uint32_t))
533
0
    return UINT32_MAX;
534
0
  return le32toh(*(uint32_t *)inventory_information);
535
0
}
536
537
int encode_get_temperature_reading_req(uint8_t instance_id, uint8_t sensor_id,
538
               struct nsm_msg *msg)
539
0
{
540
0
  if (msg == NULL) {
541
0
    return NSM_SW_ERROR_NULL;
542
0
  }
543
544
0
  struct nsm_header_info header = {0};
545
0
  header.nsm_msg_type = NSM_REQUEST;
546
0
  header.instance_id = instance_id;
547
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
548
549
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
550
0
  if (rc != NSM_SW_SUCCESS) {
551
0
    return rc;
552
0
  }
553
554
0
  nsm_get_temperature_reading_req *request =
555
0
      (nsm_get_temperature_reading_req *)msg->payload;
556
557
0
  request->hdr.command = NSM_GET_TEMPERATURE_READING;
558
0
  request->hdr.data_size = sizeof(sensor_id);
559
0
  request->sensor_id = sensor_id;
560
561
0
  return NSM_SW_SUCCESS;
562
0
}
563
564
int decode_get_temperature_reading_req(const struct nsm_msg *msg,
565
               size_t msg_len, uint8_t *sensor_id)
566
0
{
567
0
  if (msg == NULL || sensor_id == NULL) {
568
0
    return NSM_SW_ERROR_NULL;
569
0
  }
570
571
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
572
0
        sizeof(nsm_get_temperature_reading_req)) {
573
0
    return NSM_SW_ERROR_LENGTH;
574
0
  }
575
576
0
  nsm_get_temperature_reading_req *request =
577
0
      (nsm_get_temperature_reading_req *)msg->payload;
578
579
0
  if (request->hdr.data_size < sizeof(request->sensor_id)) {
580
0
    return NSM_SW_ERROR_DATA;
581
0
  }
582
583
0
  *sensor_id = request->sensor_id;
584
585
0
  return NSM_SW_SUCCESS;
586
0
}
587
588
int encode_get_temperature_reading_resp(uint8_t instance_id, uint8_t cc,
589
          uint16_t reason_code,
590
          double temperature_reading,
591
          struct nsm_msg *msg)
592
0
{
593
0
  if (msg == NULL) {
594
0
    return NSM_SW_ERROR_NULL;
595
0
  }
596
597
0
  struct nsm_header_info header = {0};
598
0
  header.nsm_msg_type = NSM_RESPONSE;
599
0
  header.instance_id = instance_id & INSTANCEID_MASK;
600
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
601
602
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
603
0
  if (rc != NSM_SW_SUCCESS) {
604
0
    return rc;
605
0
  }
606
607
0
  if (cc != NSM_SUCCESS) {
608
0
    return encode_reason_code(cc, reason_code,
609
0
            NSM_GET_TEMPERATURE_READING, msg);
610
0
  }
611
612
0
  struct nsm_get_temperature_reading_resp *response =
613
0
      (struct nsm_get_temperature_reading_resp *)msg->payload;
614
615
0
  response->hdr.command = NSM_GET_TEMPERATURE_READING;
616
0
  response->hdr.completion_code = cc;
617
0
  response->hdr.data_size = htole16(sizeof(uint32_t));
618
619
0
  int32_t reading = temperature_reading * (1 << 8);
620
0
  response->reading = htole32(reading);
621
622
0
  return NSM_SW_SUCCESS;
623
0
}
624
625
int decode_get_temperature_reading_resp(const struct nsm_msg *msg,
626
          size_t msg_len, uint8_t *cc,
627
          uint16_t *reason_code,
628
          double *temperature_reading)
629
0
{
630
0
  if (temperature_reading == NULL) {
631
0
    return NSM_SW_ERROR_NULL;
632
0
  }
633
634
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
635
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
636
0
    return rc;
637
0
  }
638
639
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
640
0
        sizeof(struct nsm_get_temperature_reading_resp)) {
641
0
    return NSM_SW_ERROR_LENGTH;
642
0
  }
643
644
0
  struct nsm_get_temperature_reading_resp *response =
645
0
      (struct nsm_get_temperature_reading_resp *)msg->payload;
646
647
0
  uint16_t data_size = le16toh(response->hdr.data_size);
648
0
  if (data_size != sizeof(int32_t)) {
649
0
    return NSM_SW_ERROR_DATA;
650
0
  }
651
652
0
  int32_t reading = le32toh(response->reading);
653
0
  *temperature_reading = reading / (double)(1 << 8);
654
655
0
  return NSM_SW_SUCCESS;
656
0
}
657
658
int encode_read_thermal_parameter_req(uint8_t instance, uint8_t parameter_id,
659
              struct nsm_msg *msg)
660
0
{
661
0
  if (msg == NULL) {
662
0
    return NSM_SW_ERROR_NULL;
663
0
  }
664
665
0
  struct nsm_header_info header = {0};
666
0
  header.nsm_msg_type = NSM_REQUEST;
667
0
  header.instance_id = instance;
668
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
669
670
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
671
0
  if (rc != NSM_SW_SUCCESS) {
672
0
    return rc;
673
0
  }
674
675
0
  struct nsm_read_thermal_parameter_req *request =
676
0
      (struct nsm_read_thermal_parameter_req *)msg->payload;
677
678
0
  request->hdr.command = NSM_READ_THERMAL_PARAMETER;
679
0
  request->hdr.data_size = sizeof(parameter_id);
680
0
  request->parameter_id = parameter_id;
681
682
0
  return NSM_SW_SUCCESS;
683
0
}
684
685
int decode_read_thermal_parameter_req(const struct nsm_msg *msg, size_t msg_len,
686
              uint8_t *parameter_id)
687
0
{
688
0
  if (msg == NULL || parameter_id == NULL) {
689
0
    return NSM_SW_ERROR_NULL;
690
0
  }
691
692
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
693
0
        sizeof(struct nsm_read_thermal_parameter_req)) {
694
0
    return NSM_SW_ERROR_LENGTH;
695
0
  }
696
697
0
  struct nsm_read_thermal_parameter_req *request =
698
0
      (struct nsm_read_thermal_parameter_req *)msg->payload;
699
700
0
  if (request->hdr.data_size < sizeof(request->parameter_id)) {
701
0
    return NSM_SW_ERROR_DATA;
702
0
  }
703
704
0
  *parameter_id = request->parameter_id;
705
706
0
  return NSM_SW_SUCCESS;
707
0
}
708
709
int encode_read_thermal_parameter_resp(uint8_t instance_id, uint8_t cc,
710
               uint16_t reason_code, int32_t threshold,
711
               struct nsm_msg *msg)
712
0
{
713
0
  if (msg == NULL) {
714
0
    return NSM_SW_ERROR_NULL;
715
0
  }
716
717
0
  struct nsm_header_info header = {0};
718
0
  header.nsm_msg_type = NSM_RESPONSE;
719
0
  header.instance_id = instance_id & 0x1f;
720
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
721
722
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
723
0
  if (rc != NSM_SW_SUCCESS) {
724
0
    return rc;
725
0
  }
726
727
0
  if (cc != NSM_SUCCESS) {
728
0
    return encode_reason_code(cc, reason_code,
729
0
            NSM_READ_THERMAL_PARAMETER, msg);
730
0
  }
731
732
0
  struct nsm_read_thermal_parameter_resp *response =
733
0
      (struct nsm_read_thermal_parameter_resp *)msg->payload;
734
735
0
  response->hdr.command = NSM_READ_THERMAL_PARAMETER;
736
0
  response->hdr.completion_code = cc;
737
0
  response->hdr.data_size = htole16(sizeof(threshold));
738
0
  response->threshold = htole32(threshold);
739
740
0
  return NSM_SW_SUCCESS;
741
0
}
742
743
int decode_read_thermal_parameter_resp(const struct nsm_msg *msg,
744
               size_t msg_len, uint8_t *cc,
745
               uint16_t *reason_code,
746
               int32_t *threshold)
747
0
{
748
0
  if (threshold == NULL) {
749
0
    return NSM_SW_ERROR_NULL;
750
0
  }
751
752
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
753
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
754
0
    return rc;
755
0
  }
756
757
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
758
0
        sizeof(struct nsm_read_thermal_parameter_resp)) {
759
0
    return NSM_SW_ERROR_LENGTH;
760
0
  }
761
762
0
  struct nsm_read_thermal_parameter_resp *response =
763
0
      (struct nsm_read_thermal_parameter_resp *)msg->payload;
764
765
0
  uint16_t data_size = le16toh(response->hdr.data_size);
766
0
  if (data_size != sizeof(*threshold)) {
767
0
    return NSM_SW_ERROR_DATA;
768
0
  }
769
770
0
  *threshold = le32toh(response->threshold);
771
0
  return NSM_SW_SUCCESS;
772
0
}
773
774
int encode_aggregate_thermal_parameter_data(int32_t threshold, uint8_t *data,
775
              size_t *data_len)
776
0
{
777
0
  if (data == NULL || data_len == NULL) {
778
0
    return NSM_SW_ERROR_NULL;
779
0
  }
780
781
0
  int32_t le_reading = htole32(threshold);
782
783
0
  memcpy(data, &le_reading, sizeof(int32_t));
784
0
  *data_len = sizeof(int32_t);
785
786
0
  return NSM_SW_SUCCESS;
787
0
}
788
789
int decode_aggregate_thermal_parameter_data(const uint8_t *data,
790
              size_t data_len, int32_t *threshold)
791
0
{
792
0
  if (data == NULL || threshold == NULL) {
793
0
    return NSM_SW_ERROR_NULL;
794
0
  }
795
796
0
  if (data_len != sizeof(int32_t)) {
797
0
    return NSM_SW_ERROR_LENGTH;
798
0
  }
799
800
0
  int32_t le_reading;
801
0
  memcpy(&le_reading, data, sizeof(int32_t));
802
803
0
  *threshold = le32toh(le_reading);
804
805
0
  return NSM_SW_SUCCESS;
806
0
}
807
808
int encode_get_current_power_draw_req(uint8_t instance_id, uint8_t sensor_id,
809
              uint8_t averaging_interval,
810
              struct nsm_msg *msg)
811
0
{
812
0
  if (msg == NULL) {
813
0
    return NSM_SW_ERROR_NULL;
814
0
  }
815
816
0
  struct nsm_header_info header = {0};
817
0
  header.nsm_msg_type = NSM_REQUEST;
818
0
  header.instance_id = instance_id;
819
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
820
821
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
822
0
  if (rc != NSM_SW_SUCCESS) {
823
0
    return rc;
824
0
  }
825
826
0
  struct nsm_get_current_power_draw_req *request =
827
0
      (struct nsm_get_current_power_draw_req *)msg->payload;
828
829
0
  request->hdr.command = NSM_GET_POWER;
830
0
  request->hdr.data_size = sizeof(sensor_id) + sizeof(averaging_interval);
831
0
  request->sensor_id = sensor_id;
832
0
  request->averaging_interval = averaging_interval;
833
834
0
  return NSM_SW_SUCCESS;
835
0
}
836
837
int decode_get_current_power_draw_req(const struct nsm_msg *msg, size_t msg_len,
838
              uint8_t *sensor_id,
839
              uint8_t *averaging_interval)
840
0
{
841
0
  if (msg == NULL || sensor_id == NULL || averaging_interval == NULL) {
842
0
    return NSM_SW_ERROR_NULL;
843
0
  }
844
845
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
846
0
        sizeof(struct nsm_get_current_power_draw_req)) {
847
0
    return NSM_SW_ERROR_LENGTH;
848
0
  }
849
850
0
  struct nsm_get_current_power_draw_req *request =
851
0
      (struct nsm_get_current_power_draw_req *)msg->payload;
852
853
0
  if (request->hdr.data_size <
854
0
      sizeof(request->sensor_id) + sizeof(request->averaging_interval)) {
855
0
    return NSM_SW_ERROR_DATA;
856
0
  }
857
858
0
  *sensor_id = request->sensor_id;
859
0
  *averaging_interval = request->averaging_interval;
860
861
0
  return NSM_SW_SUCCESS;
862
0
}
863
864
int encode_get_current_power_draw_resp(uint8_t instance_id, uint8_t cc,
865
               uint16_t reason_code, uint32_t reading,
866
               struct nsm_msg *msg)
867
0
{
868
0
  if (msg == NULL) {
869
0
    return NSM_SW_ERROR_NULL;
870
0
  }
871
872
0
  struct nsm_header_info header = {0};
873
0
  header.nsm_msg_type = NSM_RESPONSE;
874
0
  header.instance_id = instance_id & 0x1f;
875
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
876
877
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
878
0
  if (rc != NSM_SW_SUCCESS) {
879
0
    return rc;
880
0
  }
881
882
0
  if (cc != NSM_SUCCESS) {
883
0
    return encode_reason_code(cc, reason_code, NSM_GET_POWER, msg);
884
0
  }
885
886
0
  nsm_get_current_power_draw_resp *response =
887
0
      (nsm_get_current_power_draw_resp *)msg->payload;
888
889
0
  response->hdr.command = NSM_GET_POWER;
890
0
  response->hdr.completion_code = cc;
891
0
  response->hdr.data_size = htole16(sizeof(reading));
892
0
  response->reading = htole32(reading);
893
894
0
  return NSM_SW_SUCCESS;
895
0
}
896
897
int decode_get_current_power_draw_resp(const struct nsm_msg *msg,
898
               size_t msg_len, uint8_t *cc,
899
               uint16_t *reason_code, uint32_t *reading)
900
0
{
901
0
  if (reading == NULL) {
902
0
    return NSM_SW_ERROR_NULL;
903
0
  }
904
905
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
906
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
907
0
    return rc;
908
0
  }
909
910
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
911
0
        sizeof(nsm_get_current_power_draw_resp)) {
912
0
    return NSM_SW_ERROR_LENGTH;
913
0
  }
914
915
0
  nsm_get_current_power_draw_resp *response =
916
0
      (nsm_get_current_power_draw_resp *)msg->payload;
917
918
0
  uint16_t data_size = le16toh(response->hdr.data_size);
919
0
  if (data_size != sizeof(*reading)) {
920
0
    return NSM_SW_ERROR_DATA;
921
0
  }
922
923
0
  *reading = le32toh(response->reading);
924
0
  return NSM_SW_SUCCESS;
925
0
}
926
927
int encode_get_max_observed_power_req(uint8_t instance_id, uint8_t sensor_id,
928
              uint8_t averaging_interval,
929
              struct nsm_msg *msg)
930
0
{
931
0
  if (msg == NULL) {
932
0
    return NSM_SW_ERROR_NULL;
933
0
  }
934
935
0
  struct nsm_header_info header = {0};
936
0
  header.nsm_msg_type = NSM_REQUEST;
937
0
  header.instance_id = instance_id;
938
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
939
940
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
941
0
  if (rc != NSM_SW_SUCCESS) {
942
0
    return rc;
943
0
  }
944
945
0
  nsm_get_max_observed_power_req *request =
946
0
      (nsm_get_max_observed_power_req *)msg->payload;
947
948
0
  request->hdr.command = NSM_GET_MAX_OBSERVED_POWER;
949
0
  request->hdr.data_size = sizeof(sensor_id) + sizeof(averaging_interval);
950
0
  request->sensor_id = sensor_id;
951
0
  request->averaging_interval = averaging_interval;
952
953
0
  return NSM_SW_SUCCESS;
954
0
}
955
956
int decode_get_max_observed_power_req(const struct nsm_msg *msg, size_t msg_len,
957
              uint8_t *sensor_id,
958
              uint8_t *averaging_interval)
959
0
{
960
0
  if (msg == NULL || sensor_id == NULL || averaging_interval == NULL) {
961
0
    return NSM_SW_ERROR_NULL;
962
0
  }
963
964
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
965
0
        sizeof(nsm_get_max_observed_power_req)) {
966
0
    return NSM_SW_ERROR_LENGTH;
967
0
  }
968
969
0
  nsm_get_max_observed_power_req *request =
970
0
      (nsm_get_max_observed_power_req *)msg->payload;
971
972
0
  if (request->hdr.data_size <
973
0
      sizeof(request->sensor_id) + sizeof(request->averaging_interval)) {
974
0
    return NSM_SW_ERROR_DATA;
975
0
  }
976
977
0
  *sensor_id = request->sensor_id;
978
0
  *averaging_interval = request->averaging_interval;
979
980
0
  return NSM_SW_SUCCESS;
981
0
}
982
983
int encode_get_max_observed_power_resp(uint8_t instance_id, uint8_t cc,
984
               uint16_t reason_code, uint32_t reading,
985
               struct nsm_msg *msg)
986
0
{
987
0
  if (msg == NULL) {
988
0
    return NSM_SW_ERROR_NULL;
989
0
  }
990
991
0
  struct nsm_header_info header = {0};
992
0
  header.nsm_msg_type = NSM_RESPONSE;
993
0
  header.instance_id = instance_id & 0x1f;
994
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
995
996
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
997
0
  if (rc != NSM_SW_SUCCESS) {
998
0
    return rc;
999
0
  }
1000
1001
0
  if (cc != NSM_SUCCESS) {
1002
0
    return encode_reason_code(cc, reason_code, NSM_GET_POWER, msg);
1003
0
  }
1004
1005
0
  nsm_get_max_observed_power_resp *response =
1006
0
      (nsm_get_max_observed_power_resp *)msg->payload;
1007
1008
0
  response->hdr.command = NSM_GET_MAX_OBSERVED_POWER;
1009
0
  response->hdr.completion_code = cc;
1010
0
  response->hdr.data_size = htole16(sizeof(reading));
1011
0
  response->reading = htole32(reading);
1012
1013
0
  return NSM_SW_SUCCESS;
1014
0
}
1015
1016
int decode_get_max_observed_power_resp(const struct nsm_msg *msg,
1017
               size_t msg_len, uint8_t *cc,
1018
               uint16_t *reason_code, uint32_t *reading)
1019
0
{
1020
0
  if (reading == NULL) {
1021
0
    return NSM_SW_ERROR_NULL;
1022
0
  }
1023
1024
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
1025
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
1026
0
    return rc;
1027
0
  }
1028
1029
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
1030
0
        sizeof(nsm_get_max_observed_power_resp)) {
1031
0
    return NSM_SW_ERROR_LENGTH;
1032
0
  }
1033
1034
0
  nsm_get_max_observed_power_resp *response =
1035
0
      (nsm_get_max_observed_power_resp *)msg->payload;
1036
1037
0
  uint16_t data_size = le16toh(response->hdr.data_size);
1038
0
  if (data_size != sizeof(*reading)) {
1039
0
    return NSM_SW_ERROR_DATA;
1040
0
  }
1041
1042
0
  *reading = le32toh(response->reading);
1043
0
  return NSM_SW_SUCCESS;
1044
0
}
1045
1046
int encode_get_driver_info_req(uint8_t instance_id, struct nsm_msg *msg)
1047
0
{
1048
0
  if (msg == NULL) {
1049
0
    return NSM_SW_ERROR_NULL;
1050
0
  }
1051
1052
0
  struct nsm_header_info header = {0};
1053
0
  header.nsm_msg_type = NSM_REQUEST;
1054
0
  header.instance_id = instance_id;
1055
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
1056
1057
0
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
1058
0
  if (rc != NSM_SW_SUCCESS) {
1059
0
    return rc;
1060
0
  }
1061
1062
  // Since there's no payload, we just set the command and data size
1063
0
  struct nsm_common_req *request = (struct nsm_common_req *)msg->payload;
1064
1065
0
  request->command = NSM_GET_DRIVER_INFO;
1066
0
  request->data_size = 0;
1067
0
  return NSM_SW_SUCCESS;
1068
0
}
1069
1070
int decode_get_driver_info_req(const struct nsm_msg *msg, size_t msg_len)
1071
0
{
1072
0
  if (msg == NULL) {
1073
0
    return NSM_SW_ERROR_NULL;
1074
0
  }
1075
1076
0
  if (msg_len <
1077
0
      sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_common_req)) {
1078
0
    return NSM_SW_ERROR_LENGTH;
1079
0
  }
1080
1081
0
  struct nsm_common_req *request = (struct nsm_common_req *)msg->payload;
1082
1083
0
  if (request->data_size != 0) {
1084
0
    return NSM_SW_ERROR_DATA;
1085
0
  }
1086
0
  return NSM_SW_SUCCESS;
1087
0
}
1088
1089
int encode_get_driver_info_resp(uint8_t instance_id, uint8_t cc,
1090
        uint16_t reason_code, const uint16_t data_size,
1091
        const uint8_t *driver_info_data,
1092
        struct nsm_msg *msg)
1093
0
{
1094
0
  if (msg == NULL) {
1095
0
    return NSM_SW_ERROR_NULL;
1096
0
  }
1097
1098
0
  struct nsm_header_info header = {0};
1099
0
  header.nsm_msg_type = NSM_RESPONSE;
1100
0
  header.instance_id = instance_id & INSTANCEID_MASK;
1101
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
1102
1103
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
1104
0
  if (rc != NSM_SUCCESS) {
1105
0
    return rc;
1106
0
  }
1107
0
  if (cc != NSM_SUCCESS) {
1108
0
    return encode_reason_code(cc, reason_code, NSM_GET_DRIVER_INFO,
1109
0
            msg);
1110
0
  }
1111
1112
0
  struct nsm_get_driver_info_resp *response =
1113
0
      (struct nsm_get_driver_info_resp *)msg->payload;
1114
1115
0
  response->hdr.command = NSM_GET_DRIVER_INFO;
1116
0
  response->hdr.completion_code = cc;
1117
0
  response->hdr.data_size = htole16(data_size);
1118
1119
0
  if (driver_info_data == NULL) {
1120
0
    return NSM_SW_ERROR_NULL;
1121
0
  }
1122
0
  response->driver_state = driver_info_data[0];
1123
0
  memcpy(response->driver_version,
1124
0
         driver_info_data + sizeof(response->driver_state),
1125
0
         data_size - sizeof(response->driver_state));
1126
1127
0
  return NSM_SUCCESS;
1128
0
}
1129
1130
int decode_get_driver_info_resp(const struct nsm_msg *msg, size_t msg_len,
1131
        uint8_t *cc, uint16_t *reason_code,
1132
        enum8 *driver_state, char *driver_version)
1133
0
{
1134
0
  if (driver_state == NULL || driver_version == NULL) {
1135
0
    return NSM_SW_ERROR_NULL;
1136
0
  }
1137
1138
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
1139
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
1140
0
    return rc;
1141
0
  }
1142
1143
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
1144
0
        sizeof(struct nsm_get_driver_info_resp)) {
1145
0
    return NSM_SW_ERROR_LENGTH;
1146
0
  }
1147
1148
0
  struct nsm_get_driver_info_resp *response =
1149
0
      (struct nsm_get_driver_info_resp *)msg->payload;
1150
0
  size_t data_size = le16toh(response->hdr.data_size);
1151
0
  *driver_state = response->driver_state;
1152
0
  size_t driver_version_length =
1153
0
      data_size - sizeof(response->driver_state);
1154
1155
0
  if (driver_version_length > MAX_VERSION_STRING_SIZE ||
1156
0
      response->driver_version[driver_version_length - 1] != '\0') {
1157
0
    return NSM_SW_ERROR_LENGTH;
1158
0
  }
1159
1160
0
  memcpy(driver_version, response->driver_version, driver_version_length);
1161
1162
0
  return NSM_SUCCESS;
1163
0
}
1164
1165
int encode_aggregate_get_current_power_draw_reading(uint32_t reading,
1166
                uint8_t *data,
1167
                size_t *data_len)
1168
0
{
1169
0
  if (data == NULL || data_len == NULL) {
1170
0
    return NSM_SW_ERROR_NULL;
1171
0
  }
1172
1173
0
  uint32_t le_reading = htole32(reading);
1174
1175
0
  memcpy(data, &le_reading, sizeof(uint32_t));
1176
0
  *data_len = sizeof(uint32_t);
1177
1178
0
  return NSM_SW_SUCCESS;
1179
0
}
1180
1181
int decode_aggregate_get_current_power_draw_reading(const uint8_t *data,
1182
                size_t data_len,
1183
                uint32_t *reading)
1184
0
{
1185
0
  if (data == NULL || reading == NULL) {
1186
0
    return NSM_SW_ERROR_NULL;
1187
0
  }
1188
1189
0
  if (data_len != sizeof(uint32_t)) {
1190
0
    return NSM_SW_ERROR_LENGTH;
1191
0
  }
1192
1193
0
  uint32_t le_reading;
1194
0
  memcpy(&le_reading, data, sizeof(uint32_t));
1195
1196
0
  *reading = le32toh(le_reading);
1197
1198
0
  return NSM_SW_SUCCESS;
1199
0
}
1200
1201
int encode_get_current_energy_count_req(uint8_t instance, uint8_t sensor_id,
1202
          struct nsm_msg *msg)
1203
0
{
1204
0
  if (msg == NULL) {
1205
0
    return NSM_SW_ERROR_NULL;
1206
0
  }
1207
1208
0
  struct nsm_header_info header = {0};
1209
0
  header.nsm_msg_type = NSM_REQUEST;
1210
0
  header.instance_id = instance;
1211
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
1212
1213
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
1214
0
  if (rc != NSM_SW_SUCCESS) {
1215
0
    return rc;
1216
0
  }
1217
1218
0
  nsm_get_current_energy_count_req *request =
1219
0
      (nsm_get_current_energy_count_req *)msg->payload;
1220
1221
0
  request->hdr.command = NSM_GET_ENERGY_COUNT;
1222
0
  request->hdr.data_size = sizeof(sensor_id);
1223
0
  request->sensor_id = sensor_id;
1224
1225
0
  return NSM_SW_SUCCESS;
1226
0
}
1227
1228
int decode_get_current_energy_count_req(const struct nsm_msg *msg,
1229
          size_t msg_len, uint8_t *sensor_id)
1230
0
{
1231
0
  if (msg == NULL || sensor_id == NULL) {
1232
0
    return NSM_SW_ERROR_NULL;
1233
0
  }
1234
1235
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
1236
0
        sizeof(nsm_get_current_energy_count_req)) {
1237
0
    return NSM_SW_ERROR_LENGTH;
1238
0
  }
1239
1240
0
  nsm_get_current_energy_count_req *request =
1241
0
      (nsm_get_current_energy_count_req *)msg->payload;
1242
1243
0
  if (request->hdr.data_size < sizeof(request->sensor_id)) {
1244
0
    return NSM_SW_ERROR_DATA;
1245
0
  }
1246
1247
0
  *sensor_id = request->sensor_id;
1248
1249
0
  return NSM_SW_SUCCESS;
1250
0
}
1251
1252
int encode_get_current_energy_count_resp(uint8_t instance_id, uint8_t cc,
1253
           uint16_t reason_code,
1254
           uint64_t energy_reading,
1255
           struct nsm_msg *msg)
1256
0
{
1257
0
  if (msg == NULL) {
1258
0
    return NSM_SW_ERROR_NULL;
1259
0
  }
1260
1261
0
  struct nsm_header_info header = {0};
1262
0
  header.nsm_msg_type = NSM_RESPONSE;
1263
0
  header.instance_id = instance_id & 0x1f;
1264
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
1265
1266
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
1267
0
  if (rc != NSM_SW_SUCCESS) {
1268
0
    return rc;
1269
0
  }
1270
1271
0
  if (cc != NSM_SUCCESS) {
1272
0
    return encode_reason_code(cc, reason_code, NSM_GET_ENERGY_COUNT,
1273
0
            msg);
1274
0
  }
1275
1276
0
  struct nsm_get_current_energy_count_resp *response =
1277
0
      (struct nsm_get_current_energy_count_resp *)msg->payload;
1278
1279
0
  response->hdr.command = NSM_GET_ENERGY_COUNT;
1280
0
  response->hdr.completion_code = cc;
1281
0
  response->hdr.data_size = htole16(sizeof(energy_reading));
1282
0
  response->reading = htole64(energy_reading);
1283
1284
0
  return NSM_SW_SUCCESS;
1285
0
}
1286
1287
int decode_get_current_energy_count_resp(const struct nsm_msg *msg,
1288
           size_t msg_len, uint8_t *cc,
1289
           uint16_t *reason_code,
1290
           uint64_t *energy_reading)
1291
0
{
1292
0
  if (energy_reading == NULL) {
1293
0
    return NSM_SW_ERROR_NULL;
1294
0
  }
1295
1296
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
1297
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
1298
0
    return rc;
1299
0
  }
1300
1301
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
1302
0
        sizeof(struct nsm_get_current_energy_count_resp)) {
1303
0
    return NSM_SW_ERROR_LENGTH;
1304
0
  }
1305
1306
0
  struct nsm_get_current_energy_count_resp *response =
1307
0
      (struct nsm_get_current_energy_count_resp *)msg->payload;
1308
1309
0
  uint16_t data_size = le16toh(response->hdr.data_size);
1310
0
  if (data_size != sizeof(*energy_reading)) {
1311
0
    return NSM_SW_ERROR_DATA;
1312
0
  }
1313
1314
0
  *energy_reading = le64toh(response->reading);
1315
1316
0
  return NSM_SW_SUCCESS;
1317
0
}
1318
1319
int encode_get_voltage_req(uint8_t instance, uint8_t sensor_id,
1320
         struct nsm_msg *msg)
1321
0
{
1322
0
  if (msg == NULL) {
1323
0
    return NSM_SW_ERROR_NULL;
1324
0
  }
1325
1326
0
  struct nsm_header_info header = {0};
1327
0
  header.nsm_msg_type = NSM_REQUEST;
1328
0
  header.instance_id = instance;
1329
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
1330
1331
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
1332
0
  if (rc != NSM_SW_SUCCESS) {
1333
0
    return rc;
1334
0
  }
1335
1336
0
  nsm_get_voltage_req *request = (nsm_get_voltage_req *)msg->payload;
1337
1338
0
  request->hdr.command = NSM_GET_VOLTAGE;
1339
0
  request->hdr.data_size = sizeof(sensor_id);
1340
0
  request->sensor_id = sensor_id;
1341
1342
0
  return NSM_SW_SUCCESS;
1343
0
}
1344
1345
int decode_get_voltage_req(const struct nsm_msg *msg, size_t msg_len,
1346
         uint8_t *sensor_id)
1347
0
{
1348
0
  if (msg == NULL || sensor_id == NULL) {
1349
0
    return NSM_SW_ERROR_NULL;
1350
0
  }
1351
1352
0
  if (msg_len <
1353
0
      sizeof(struct nsm_msg_hdr) + sizeof(nsm_get_voltage_req)) {
1354
0
    return NSM_SW_ERROR_LENGTH;
1355
0
  }
1356
1357
0
  nsm_get_voltage_req *request = (nsm_get_voltage_req *)msg->payload;
1358
1359
0
  if (request->hdr.data_size < sizeof(request->sensor_id)) {
1360
0
    return NSM_SW_ERROR_DATA;
1361
0
  }
1362
1363
0
  *sensor_id = request->sensor_id;
1364
1365
0
  return NSM_SW_SUCCESS;
1366
0
}
1367
1368
int encode_get_voltage_resp(uint8_t instance_id, uint8_t cc,
1369
          uint16_t reason_code, uint32_t voltage,
1370
          struct nsm_msg *msg)
1371
0
{
1372
0
  if (msg == NULL) {
1373
0
    return NSM_SW_ERROR_NULL;
1374
0
  }
1375
1376
0
  struct nsm_header_info header = {0};
1377
0
  header.nsm_msg_type = NSM_RESPONSE;
1378
0
  header.instance_id = instance_id & 0x1f;
1379
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
1380
1381
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
1382
0
  if (rc != NSM_SW_SUCCESS) {
1383
0
    return rc;
1384
0
  }
1385
1386
0
  if (cc != NSM_SUCCESS) {
1387
0
    return encode_reason_code(cc, reason_code, NSM_GET_VOLTAGE,
1388
0
            msg);
1389
0
  }
1390
1391
0
  nsm_get_voltage_resp *response = (nsm_get_voltage_resp *)msg->payload;
1392
1393
0
  response->hdr.command = NSM_GET_VOLTAGE;
1394
0
  response->hdr.completion_code = cc;
1395
0
  response->hdr.data_size = htole16(sizeof(voltage));
1396
0
  response->reading = htole32(voltage);
1397
1398
0
  return NSM_SW_SUCCESS;
1399
0
}
1400
1401
int decode_get_voltage_resp(const struct nsm_msg *msg, size_t msg_len,
1402
          uint8_t *cc, uint16_t *reason_code,
1403
          uint32_t *voltage)
1404
0
{
1405
0
  if (voltage == NULL) {
1406
0
    return NSM_SW_ERROR_NULL;
1407
0
  }
1408
1409
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
1410
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
1411
0
    return rc;
1412
0
  }
1413
1414
0
  if (msg_len <
1415
0
      sizeof(struct nsm_msg_hdr) + sizeof(nsm_get_voltage_resp)) {
1416
0
    return NSM_SW_ERROR_LENGTH;
1417
0
  }
1418
1419
0
  nsm_get_voltage_resp *response = (nsm_get_voltage_resp *)msg->payload;
1420
1421
0
  uint16_t data_size = le16toh(response->hdr.data_size);
1422
0
  if (data_size != sizeof(*voltage)) {
1423
0
    return NSM_SW_ERROR_DATA;
1424
0
  }
1425
1426
0
  *voltage = le64toh(response->reading);
1427
1428
0
  return NSM_SW_SUCCESS;
1429
0
}
1430
1431
int encode_get_altitude_pressure_req(uint8_t instance_id, struct nsm_msg *msg)
1432
0
{
1433
0
  if (msg == NULL) {
1434
0
    return NSM_SW_ERROR_NULL;
1435
0
  }
1436
1437
0
  struct nsm_header_info header = {0};
1438
0
  header.nsm_msg_type = NSM_REQUEST;
1439
0
  header.instance_id = instance_id;
1440
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
1441
1442
0
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
1443
0
  if (rc != NSM_SW_SUCCESS) {
1444
0
    return rc;
1445
0
  }
1446
1447
0
  struct nsm_common_req *request = (struct nsm_common_req *)msg->payload;
1448
1449
0
  request->command = NSM_GET_ALTITUDE_PRESSURE;
1450
0
  request->data_size = 0;
1451
1452
0
  return NSM_SW_SUCCESS;
1453
0
}
1454
1455
int encode_get_altitude_pressure_resp(uint8_t instance_id, uint8_t cc,
1456
              uint16_t reason_code, uint32_t reading,
1457
              struct nsm_msg *msg)
1458
0
{
1459
0
  if (msg == NULL) {
1460
0
    return NSM_SW_ERROR_NULL;
1461
0
  }
1462
1463
0
  struct nsm_header_info header = {0};
1464
0
  header.nsm_msg_type = NSM_RESPONSE;
1465
0
  header.instance_id = instance_id & 0x1f;
1466
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
1467
1468
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
1469
0
  if (rc != NSM_SW_SUCCESS) {
1470
0
    return rc;
1471
0
  }
1472
1473
0
  if (cc != NSM_SUCCESS) {
1474
0
    return encode_reason_code(cc, reason_code,
1475
0
            NSM_GET_ALTITUDE_PRESSURE, msg);
1476
0
  }
1477
1478
0
  nsm_get_altitude_pressure_resp *response =
1479
0
      (nsm_get_altitude_pressure_resp *)msg->payload;
1480
1481
0
  response->hdr.command = NSM_GET_ALTITUDE_PRESSURE;
1482
0
  response->hdr.completion_code = cc;
1483
0
  response->hdr.data_size = htole16(sizeof(reading));
1484
0
  response->reading = htole32(reading);
1485
1486
0
  return NSM_SW_SUCCESS;
1487
0
}
1488
1489
int decode_get_altitude_pressure_resp(const struct nsm_msg *msg, size_t msg_len,
1490
              uint8_t *cc, uint16_t *reason_code,
1491
              uint32_t *reading)
1492
0
{
1493
0
  if (reading == NULL) {
1494
0
    return NSM_SW_ERROR_NULL;
1495
0
  }
1496
1497
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
1498
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
1499
0
    return rc;
1500
0
  }
1501
1502
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
1503
0
        sizeof(nsm_get_altitude_pressure_resp)) {
1504
0
    return NSM_SW_ERROR_LENGTH;
1505
0
  }
1506
1507
0
  nsm_get_altitude_pressure_resp *response =
1508
0
      (nsm_get_altitude_pressure_resp *)msg->payload;
1509
1510
0
  uint16_t data_size = le16toh(response->hdr.data_size);
1511
0
  if (data_size != sizeof(*reading)) {
1512
0
    return NSM_SW_ERROR_DATA;
1513
0
  }
1514
1515
0
  *reading = le32toh(response->reading);
1516
0
  return NSM_SW_SUCCESS;
1517
0
}
1518
1519
int encode_aggregate_timestamp_data(uint64_t timestamp, uint8_t *data,
1520
            size_t *data_len)
1521
0
{
1522
0
  if (data == NULL || data_len == NULL) {
1523
0
    return NSM_SW_ERROR_NULL;
1524
0
  }
1525
1526
0
  uint64_t le_reading = htole64(timestamp);
1527
1528
0
  memcpy(data, &le_reading, sizeof(uint64_t));
1529
0
  *data_len = sizeof(uint64_t);
1530
1531
0
  return NSM_SW_SUCCESS;
1532
0
}
1533
1534
int decode_aggregate_timestamp_data(const uint8_t *data, size_t data_len,
1535
            uint64_t *timestamp)
1536
0
{
1537
0
  if (data == NULL || timestamp == NULL) {
1538
0
    return NSM_SW_ERROR_NULL;
1539
0
  }
1540
1541
0
  if (data_len != sizeof(uint64_t)) {
1542
0
    return NSM_SW_ERROR_LENGTH;
1543
0
  }
1544
1545
0
  uint64_t le_timestamp;
1546
0
  memcpy(&le_timestamp, data, sizeof(uint64_t));
1547
1548
0
  *timestamp = le64toh(le_timestamp);
1549
1550
0
  return NSM_SW_SUCCESS;
1551
0
}
1552
1553
int encode_aggregate_resp(uint8_t instance_id, uint8_t command, uint8_t cc,
1554
        uint16_t telemetry_count, struct nsm_msg *msg)
1555
0
{
1556
0
  if (msg == NULL) {
1557
0
    return NSM_SW_ERROR_NULL;
1558
0
  }
1559
1560
0
  struct nsm_header_info header = {0};
1561
0
  header.nsm_msg_type = NSM_RESPONSE;
1562
0
  header.instance_id = instance_id & 0x1f;
1563
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
1564
1565
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
1566
0
  if (rc != NSM_SW_SUCCESS) {
1567
0
    return rc;
1568
0
  }
1569
1570
0
  struct nsm_aggregate_resp *response =
1571
0
      (struct nsm_aggregate_resp *)msg->payload;
1572
1573
0
  response->command = command;
1574
0
  response->telemetry_count = htole16(telemetry_count);
1575
0
  response->completion_code = cc;
1576
1577
0
  return NSM_SW_SUCCESS;
1578
0
}
1579
1580
int decode_aggregate_resp(const struct nsm_msg *msg, size_t msg_len,
1581
        size_t *consumed_len, uint8_t *cc,
1582
        uint16_t *telemetry_count)
1583
0
{
1584
0
  if (msg == NULL || cc == NULL || telemetry_count == NULL) {
1585
0
    return NSM_SW_ERROR_NULL;
1586
0
  }
1587
1588
0
  if (msg_len <
1589
0
      sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_aggregate_resp)) {
1590
0
    return NSM_SW_ERROR_LENGTH;
1591
0
  }
1592
1593
0
  struct nsm_aggregate_resp *response =
1594
0
      (struct nsm_aggregate_resp *)msg->payload;
1595
1596
0
  *consumed_len =
1597
0
      sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_aggregate_resp);
1598
0
  *cc = response->completion_code;
1599
0
  *telemetry_count = le16toh(response->telemetry_count);
1600
1601
0
  return NSM_SW_SUCCESS;
1602
0
}
1603
1604
int encode_aggregate_resp_sample(uint8_t tag, bool valid, const uint8_t *data,
1605
         size_t data_len,
1606
         struct nsm_aggregate_resp_sample *sample,
1607
         size_t *sample_len)
1608
0
{
1609
0
  if (data == NULL || sample == NULL || sample_len == NULL) {
1610
0
    return NSM_SW_ERROR_NULL;
1611
0
  }
1612
1613
0
  sample->tag = tag;
1614
0
  sample->reserved = 0;
1615
0
  sample->valid = valid;
1616
1617
0
  for (int i = 0; i <= NSM_AGGREGATE_MAX_SAMPLE_SIZE_AS_POWER_OF_2; ++i) {
1618
0
    size_t valid_size = 1 << i;
1619
0
    if (data_len == valid_size) {
1620
0
      sample->length = i;
1621
1622
0
      memcpy(sample->data, data, data_len);
1623
0
      *sample_len = data_len +
1624
0
              sizeof(struct nsm_aggregate_resp_sample) -
1625
0
              1;
1626
1627
0
      return NSM_SW_SUCCESS;
1628
0
    }
1629
0
  }
1630
1631
0
  return NSM_SW_ERROR_DATA;
1632
0
}
1633
1634
int decode_aggregate_resp_sample(const struct nsm_aggregate_resp_sample *sample,
1635
         size_t msg_len, size_t *consumed_len,
1636
         uint8_t *tag, bool *valid,
1637
         const uint8_t **data, size_t *data_len)
1638
0
{
1639
0
  if (sample == NULL || consumed_len == NULL || tag == NULL ||
1640
0
      data == NULL || data_len == NULL) {
1641
0
    return NSM_SW_ERROR_NULL;
1642
0
  }
1643
1644
0
  if (msg_len < sizeof(struct nsm_aggregate_resp_sample)) {
1645
0
    return NSM_SW_ERROR_LENGTH;
1646
0
  }
1647
1648
0
  *data_len = 1 << sample->length;
1649
0
  *consumed_len =
1650
0
      *data_len + sizeof(struct nsm_aggregate_resp_sample) - 1;
1651
1652
0
  *valid = sample->valid;
1653
0
  *tag = sample->tag;
1654
0
  *data = sample->data;
1655
1656
0
  if (msg_len < *consumed_len) {
1657
0
    return NSM_SW_ERROR_DATA;
1658
0
  }
1659
1660
0
  return NSM_SW_SUCCESS;
1661
0
}
1662
1663
int encode_aggregate_temperature_reading_data(double temperature_reading,
1664
                uint8_t *data, size_t *data_len)
1665
0
{
1666
0
  if (data == NULL || data_len == NULL) {
1667
0
    return NSM_SW_ERROR_NULL;
1668
0
  }
1669
1670
0
  int32_t reading = temperature_reading * (1 << 8);
1671
0
  reading = htole32(reading);
1672
1673
0
  memcpy(data, &reading, sizeof(int32_t));
1674
0
  *data_len = sizeof(int32_t);
1675
1676
0
  return NSM_SW_SUCCESS;
1677
0
}
1678
1679
int decode_aggregate_temperature_reading_data(const uint8_t *data,
1680
                size_t data_len,
1681
                double *temperature_reading)
1682
0
{
1683
0
  if (data == NULL || temperature_reading == NULL) {
1684
0
    return NSM_SW_ERROR_NULL;
1685
0
  }
1686
1687
0
  if (data_len != sizeof(uint32_t)) {
1688
0
    return NSM_SW_ERROR_LENGTH;
1689
0
  }
1690
1691
0
  uint32_t reading = 0;
1692
0
  memcpy(&reading, data, sizeof(uint32_t));
1693
0
  *temperature_reading = (int32_t)le32toh(reading) / (double)(1 << 8);
1694
1695
0
  return NSM_SW_SUCCESS;
1696
0
}
1697
1698
int encode_aggregate_energy_count_data(uint64_t energy_count, uint8_t *data,
1699
               size_t *data_len)
1700
0
{
1701
0
  if (data == NULL || data_len == NULL) {
1702
0
    return NSM_SW_ERROR_NULL;
1703
0
  }
1704
1705
0
  uint64_t le_reading = htole64(energy_count);
1706
1707
0
  memcpy(data, &le_reading, sizeof(uint64_t));
1708
0
  *data_len = sizeof(uint64_t);
1709
1710
0
  return NSM_SW_SUCCESS;
1711
0
}
1712
1713
int decode_aggregate_energy_count_data(const uint8_t *data, size_t data_len,
1714
               uint64_t *energy_count)
1715
0
{
1716
0
  if (data == NULL || energy_count == NULL) {
1717
0
    return NSM_SW_ERROR_NULL;
1718
0
  }
1719
1720
0
  if (data_len != sizeof(uint64_t)) {
1721
0
    return NSM_SW_ERROR_LENGTH;
1722
0
  }
1723
1724
0
  uint64_t le_reading;
1725
0
  memcpy(&le_reading, data, sizeof(uint64_t));
1726
1727
0
  *energy_count = le64toh(le_reading);
1728
1729
0
  return NSM_SW_SUCCESS;
1730
0
}
1731
1732
int encode_aggregate_voltage_data(uint32_t voltage, uint8_t *data,
1733
          size_t *data_len)
1734
0
{
1735
0
  if (data == NULL || data_len == NULL) {
1736
0
    return NSM_SW_ERROR_NULL;
1737
0
  }
1738
1739
0
  uint32_t le_reading = htole32(voltage);
1740
1741
0
  memcpy(data, &le_reading, sizeof(uint32_t));
1742
0
  *data_len = sizeof(uint32_t);
1743
1744
0
  return NSM_SW_SUCCESS;
1745
0
}
1746
1747
int decode_aggregate_voltage_data(const uint8_t *data, size_t data_len,
1748
          uint32_t *voltage)
1749
0
{
1750
0
  if (data == NULL || voltage == NULL) {
1751
0
    return NSM_SW_ERROR_NULL;
1752
0
  }
1753
1754
0
  if (data_len != sizeof(uint32_t)) {
1755
0
    return NSM_SW_ERROR_LENGTH;
1756
0
  }
1757
1758
0
  uint32_t le_reading;
1759
0
  memcpy(&le_reading, data, sizeof(uint32_t));
1760
1761
0
  *voltage = le32toh(le_reading);
1762
1763
0
  return NSM_SW_SUCCESS;
1764
0
}
1765
1766
// Get Mig Mode Command, NSM T3 spec
1767
int encode_get_MIG_mode_req(uint8_t instance_id, struct nsm_msg *msg)
1768
0
{
1769
0
  if (msg == NULL) {
1770
0
    return NSM_SW_ERROR_NULL;
1771
0
  }
1772
1773
0
  struct nsm_header_info header = {0};
1774
0
  header.nsm_msg_type = NSM_REQUEST;
1775
0
  header.instance_id = instance_id;
1776
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
1777
1778
0
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
1779
0
  if (rc != NSM_SW_SUCCESS) {
1780
0
    return rc;
1781
0
  }
1782
1783
0
  struct nsm_common_req *request = (struct nsm_common_req *)msg->payload;
1784
1785
0
  request->command = NSM_GET_MIG_MODE;
1786
0
  request->data_size = 0;
1787
0
  return NSM_SW_SUCCESS;
1788
0
}
1789
1790
// Get Mig Mode Command, NSM T3 spec
1791
int encode_get_MIG_mode_resp(uint8_t instance_id, uint8_t cc,
1792
           uint16_t reason_code, bitfield8_t *flags,
1793
           struct nsm_msg *msg)
1794
0
{
1795
0
  if (msg == NULL || flags == NULL) {
1796
0
    return NSM_SW_ERROR_NULL;
1797
0
  }
1798
1799
0
  struct nsm_header_info header = {0};
1800
0
  header.nsm_msg_type = NSM_RESPONSE;
1801
0
  header.instance_id = instance_id & 0x1f;
1802
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
1803
1804
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
1805
0
  if (rc != NSM_SUCCESS) {
1806
0
    return rc;
1807
0
  }
1808
0
  if (cc != NSM_SUCCESS) {
1809
0
    return encode_reason_code(cc, reason_code, NSM_GET_MIG_MODE,
1810
0
            msg);
1811
0
  }
1812
1813
0
  struct nsm_get_MIG_mode_resp *resp =
1814
0
      (struct nsm_get_MIG_mode_resp *)msg->payload;
1815
0
  resp->hdr.command = NSM_GET_MIG_MODE;
1816
0
  resp->hdr.completion_code = cc;
1817
0
  uint16_t data_size = sizeof(bitfield8_t);
1818
0
  resp->hdr.data_size = htole16(data_size);
1819
0
  memcpy(&(resp->flags), flags, data_size);
1820
1821
0
  return NSM_SW_SUCCESS;
1822
0
}
1823
1824
// Get Mig Mode Command, NSM T3 spec
1825
int decode_get_MIG_mode_resp(const struct nsm_msg *msg, size_t msg_len,
1826
           uint8_t *cc, uint16_t *data_size,
1827
           uint16_t *reason_code, bitfield8_t *flags)
1828
0
{
1829
0
  if (msg == NULL || cc == NULL || data_size == NULL || flags == NULL) {
1830
0
    return NSM_SW_ERROR_NULL;
1831
0
  }
1832
1833
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
1834
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
1835
0
    return rc;
1836
0
  }
1837
1838
0
  if (msg_len != (sizeof(struct nsm_msg_hdr)) +
1839
0
         sizeof(struct nsm_get_MIG_mode_resp)) {
1840
0
    return NSM_SW_ERROR_LENGTH;
1841
0
  }
1842
1843
0
  struct nsm_get_MIG_mode_resp *resp =
1844
0
      (struct nsm_get_MIG_mode_resp *)msg->payload;
1845
1846
0
  if (resp->hdr.command != NSM_GET_MIG_MODE) {
1847
0
    return NSM_SW_ERROR_DATA;
1848
0
  }
1849
0
  *data_size = le16toh(resp->hdr.data_size);
1850
1851
0
  if ((*data_size) < sizeof(bitfield8_t)) {
1852
0
    return NSM_SW_ERROR_DATA;
1853
0
  }
1854
0
  memcpy(flags, &(resp->flags), sizeof(bitfield8_t));
1855
1856
0
  return NSM_SW_SUCCESS;
1857
0
}
1858
1859
int encode_get_MIG_mode_event_resp(uint8_t instance_id, uint8_t cc,
1860
           uint16_t reason_code,
1861
           const bitfield8_t *flags,
1862
           struct nsm_msg *msg)
1863
0
{
1864
0
  return encode_long_running_resp(
1865
0
      instance_id, cc, reason_code, NSM_TYPE_PLATFORM_ENVIRONMENTAL,
1866
0
      NSM_GET_MIG_MODE, (const uint8_t *)flags, sizeof(bitfield8_t), msg);
1867
0
}
1868
1869
int decode_get_MIG_mode_event_resp(const struct nsm_msg *msg, size_t msg_len,
1870
           uint8_t *cc, uint16_t *reason_code,
1871
           bitfield8_t *flags)
1872
0
{
1873
0
  return decode_long_running_resp_with_data(
1874
0
      msg, msg_len, NSM_TYPE_PLATFORM_ENVIRONMENTAL, NSM_GET_MIG_MODE, cc,
1875
0
      reason_code, (uint8_t *)flags, sizeof(bitfield8_t));
1876
0
}
1877
1878
// Set Mig Mode Command, NSM T3 spec
1879
int encode_set_MIG_mode_req(uint8_t instance_id, uint8_t requested_mode,
1880
          struct nsm_msg *msg)
1881
0
{
1882
0
  if (msg == NULL) {
1883
0
    return NSM_SW_ERROR_NULL;
1884
0
  }
1885
1886
0
  struct nsm_header_info header = {0};
1887
0
  header.nsm_msg_type = NSM_REQUEST;
1888
0
  header.instance_id = instance_id;
1889
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
1890
1891
0
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
1892
0
  if (rc != NSM_SW_SUCCESS) {
1893
0
    return rc;
1894
0
  }
1895
1896
0
  struct nsm_set_MIG_mode_req *request =
1897
0
      (struct nsm_set_MIG_mode_req *)msg->payload;
1898
1899
0
  request->hdr.command = NSM_SET_MIG_MODE;
1900
0
  request->hdr.data_size = sizeof(uint8_t);
1901
0
  request->requested_mode = requested_mode;
1902
0
  return NSM_SW_SUCCESS;
1903
0
}
1904
1905
// Set Mig Mode Command, NSM T3 spec
1906
int decode_set_MIG_mode_req(const struct nsm_msg *msg, size_t msg_len,
1907
          uint8_t *requested_mode)
1908
0
{
1909
0
  if (msg == NULL || requested_mode == NULL) {
1910
0
    return NSM_SW_ERROR_NULL;
1911
0
  }
1912
1913
0
  struct nsm_header_info header = {0};
1914
0
  uint8_t rc = unpack_nsm_header(&msg->hdr, &header);
1915
0
  if (rc != NSM_SW_SUCCESS) {
1916
0
    return rc;
1917
0
  }
1918
1919
0
  if (msg_len !=
1920
0
      sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_set_MIG_mode_req)) {
1921
0
    return NSM_SW_ERROR_LENGTH;
1922
0
  }
1923
1924
0
  struct nsm_set_MIG_mode_req *request =
1925
0
      (struct nsm_set_MIG_mode_req *)msg->payload;
1926
1927
0
  if (request->hdr.data_size != sizeof(uint8_t)) {
1928
0
    return NSM_SW_ERROR_DATA;
1929
0
  }
1930
1931
0
  *requested_mode = request->requested_mode;
1932
0
  return NSM_SW_SUCCESS;
1933
0
}
1934
1935
int encode_set_MIG_mode_resp(uint8_t instance_id, uint8_t cc,
1936
           uint16_t reason_code, struct nsm_msg *msg)
1937
0
{
1938
0
  return encode_common_resp(instance_id, cc, reason_code,
1939
0
          NSM_TYPE_PLATFORM_ENVIRONMENTAL,
1940
0
          NSM_SET_MIG_MODE, msg);
1941
0
}
1942
1943
int decode_set_MIG_mode_resp(const struct nsm_msg *msg, size_t msg_len,
1944
           uint8_t *cc, uint16_t *data_size,
1945
           uint16_t *reason_code)
1946
0
{
1947
0
  return decode_common_resp(msg, msg_len, cc, data_size, reason_code);
1948
0
}
1949
1950
int encode_set_MIG_mode_event_resp(uint8_t instance_id, uint8_t cc,
1951
           uint16_t reason_code, struct nsm_msg *msg)
1952
0
{
1953
0
  return encode_long_running_resp(instance_id, cc, reason_code,
1954
0
          NSM_TYPE_PLATFORM_ENVIRONMENTAL,
1955
0
          NSM_SET_MIG_MODE, NULL, 0, msg);
1956
0
}
1957
1958
int decode_set_MIG_mode_event_resp(const struct nsm_msg *msg, size_t msg_len,
1959
           uint8_t *cc, uint16_t *reason_code)
1960
0
{
1961
0
  return decode_long_running_resp(msg, msg_len,
1962
0
          NSM_TYPE_PLATFORM_ENVIRONMENTAL,
1963
0
          NSM_SET_MIG_MODE, cc, reason_code);
1964
0
}
1965
1966
// Get ECC Mode Command, NSM T3 spec
1967
int encode_get_ECC_mode_req(uint8_t instance_id, struct nsm_msg *msg)
1968
0
{
1969
0
  if (msg == NULL) {
1970
0
    return NSM_SW_ERROR_NULL;
1971
0
  }
1972
1973
0
  struct nsm_header_info header = {0};
1974
0
  header.nsm_msg_type = NSM_REQUEST;
1975
0
  header.instance_id = instance_id;
1976
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
1977
1978
0
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
1979
0
  if (rc != NSM_SW_SUCCESS) {
1980
0
    return rc;
1981
0
  }
1982
1983
0
  struct nsm_common_req *request = (struct nsm_common_req *)msg->payload;
1984
1985
0
  request->command = NSM_GET_ECC_MODE;
1986
0
  request->data_size = 0;
1987
1988
0
  return NSM_SW_SUCCESS;
1989
0
}
1990
1991
// Get ECC Mode Command, NSM T3 spec
1992
int encode_get_ECC_mode_resp(uint8_t instance_id, uint8_t cc,
1993
           uint16_t reason_code, bitfield8_t *flags,
1994
           struct nsm_msg *msg)
1995
0
{
1996
0
  if (msg == NULL || flags == NULL) {
1997
0
    return NSM_SW_ERROR_NULL;
1998
0
  }
1999
0
  struct nsm_header_info header = {0};
2000
0
  header.nsm_msg_type = NSM_RESPONSE;
2001
0
  header.instance_id = instance_id & 0x1f;
2002
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
2003
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
2004
0
  if (rc != NSM_SW_SUCCESS) {
2005
0
    return rc;
2006
0
  }
2007
0
  if (cc != NSM_SUCCESS) {
2008
0
    return encode_reason_code(cc, reason_code, NSM_GET_ECC_MODE,
2009
0
            msg);
2010
0
  }
2011
0
  struct nsm_get_ECC_mode_resp *resp =
2012
0
      (struct nsm_get_ECC_mode_resp *)msg->payload;
2013
0
  resp->hdr.command = NSM_GET_ECC_MODE;
2014
0
  resp->hdr.completion_code = cc;
2015
0
  uint16_t data_size = sizeof(bitfield8_t);
2016
0
  resp->hdr.data_size = htole16(data_size);
2017
0
  memcpy(&(resp->flags), flags, data_size);
2018
2019
0
  return NSM_SW_SUCCESS;
2020
0
}
2021
2022
// Get ECC Mode Command, NSM T3 spec
2023
int decode_get_ECC_mode_resp(const struct nsm_msg *msg, size_t msg_len,
2024
           uint8_t *cc, uint16_t *data_size,
2025
           uint16_t *reason_code, bitfield8_t *flags)
2026
0
{
2027
0
  if (msg == NULL || cc == NULL || data_size == NULL || flags == NULL) {
2028
0
    return NSM_SW_ERROR_NULL;
2029
0
  }
2030
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
2031
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
2032
0
    return rc;
2033
0
  }
2034
2035
0
  if (msg_len != (sizeof(struct nsm_msg_hdr)) +
2036
0
         sizeof(struct nsm_get_ECC_mode_resp)) {
2037
0
    return NSM_SW_ERROR_LENGTH;
2038
0
  }
2039
2040
0
  struct nsm_get_ECC_mode_resp *resp =
2041
0
      (struct nsm_get_ECC_mode_resp *)msg->payload;
2042
2043
0
  *data_size = le16toh(resp->hdr.data_size);
2044
2045
0
  if ((*data_size) < sizeof(bitfield8_t)) {
2046
0
    return NSM_SW_ERROR_DATA;
2047
0
  }
2048
0
  memcpy(flags, &(resp->flags), sizeof(bitfield8_t));
2049
2050
0
  return NSM_SW_SUCCESS;
2051
0
}
2052
2053
int encode_get_ECC_mode_event_resp(uint8_t instance_id, uint8_t cc,
2054
           uint16_t reason_code,
2055
           const bitfield8_t *flags,
2056
           struct nsm_msg *msg)
2057
0
{
2058
0
  return encode_long_running_resp(
2059
0
      instance_id, cc, reason_code, NSM_TYPE_PLATFORM_ENVIRONMENTAL,
2060
0
      NSM_GET_ECC_MODE, (const uint8_t *)flags, sizeof(bitfield8_t), msg);
2061
0
}
2062
2063
int decode_get_ECC_mode_event_resp(const struct nsm_msg *msg, size_t msg_len,
2064
           uint8_t *cc, uint16_t *reason_code,
2065
           bitfield8_t *flags)
2066
0
{
2067
0
  return decode_long_running_resp_with_data(
2068
0
      msg, msg_len, NSM_TYPE_PLATFORM_ENVIRONMENTAL, NSM_GET_ECC_MODE, cc,
2069
0
      reason_code, (uint8_t *)flags, sizeof(bitfield8_t));
2070
0
}
2071
2072
// Set ECC Mode Command, NSM T3 spec
2073
int encode_set_ECC_mode_req(uint8_t instance_id, uint8_t requested_mode,
2074
          struct nsm_msg *msg)
2075
0
{
2076
0
  if (msg == NULL) {
2077
0
    return NSM_SW_ERROR_NULL;
2078
0
  }
2079
2080
0
  struct nsm_header_info header = {0};
2081
0
  header.nsm_msg_type = NSM_REQUEST;
2082
0
  header.instance_id = instance_id;
2083
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
2084
2085
0
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
2086
0
  if (rc != NSM_SW_SUCCESS) {
2087
0
    return rc;
2088
0
  }
2089
2090
0
  struct nsm_set_ECC_mode_req *request =
2091
0
      (struct nsm_set_ECC_mode_req *)msg->payload;
2092
2093
0
  request->hdr.command = NSM_SET_ECC_MODE;
2094
0
  request->hdr.data_size = sizeof(uint8_t);
2095
0
  request->requested_mode = requested_mode;
2096
0
  return NSM_SW_SUCCESS;
2097
0
}
2098
2099
// Set ECC Mode Command, NSM T3 spec
2100
int decode_set_ECC_mode_req(const struct nsm_msg *msg, size_t msg_len,
2101
          uint8_t *requested_mode)
2102
0
{
2103
0
  if (msg == NULL || requested_mode == NULL) {
2104
0
    return NSM_SW_ERROR_NULL;
2105
0
  }
2106
2107
0
  struct nsm_header_info header = {0};
2108
0
  uint8_t rc = unpack_nsm_header(&msg->hdr, &header);
2109
0
  if (rc != NSM_SW_SUCCESS) {
2110
0
    return rc;
2111
0
  }
2112
2113
0
  if (msg_len !=
2114
0
      sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_set_ECC_mode_req)) {
2115
0
    return NSM_SW_ERROR_LENGTH;
2116
0
  }
2117
2118
0
  struct nsm_set_ECC_mode_req *request =
2119
0
      (struct nsm_set_ECC_mode_req *)msg->payload;
2120
2121
0
  if (request->hdr.data_size != sizeof(uint8_t)) {
2122
0
    return NSM_SW_ERROR_DATA;
2123
0
  }
2124
2125
0
  *requested_mode = request->requested_mode;
2126
0
  return NSM_SW_SUCCESS;
2127
0
}
2128
2129
int encode_set_ECC_mode_resp(uint8_t instance_id, uint8_t cc,
2130
           uint16_t reason_code, struct nsm_msg *msg)
2131
0
{
2132
0
  return encode_common_resp(instance_id, cc, reason_code,
2133
0
          NSM_TYPE_PLATFORM_ENVIRONMENTAL,
2134
0
          NSM_SET_ECC_MODE, msg);
2135
0
}
2136
2137
int decode_set_ECC_mode_resp(const struct nsm_msg *msg, size_t msg_len,
2138
           uint8_t *cc, uint16_t *data_size,
2139
           uint16_t *reason_code)
2140
0
{
2141
0
  return decode_common_resp(msg, msg_len, cc, data_size, reason_code);
2142
0
}
2143
2144
int encode_set_ECC_mode_event_resp(uint8_t instance_id, uint8_t cc,
2145
           uint16_t reason_code, struct nsm_msg *msg)
2146
0
{
2147
0
  return encode_long_running_resp(instance_id, cc, reason_code,
2148
0
          NSM_TYPE_PLATFORM_ENVIRONMENTAL,
2149
0
          NSM_SET_ECC_MODE, NULL, 0, msg);
2150
0
}
2151
int decode_set_ECC_mode_event_resp(const struct nsm_msg *msg, size_t msg_len,
2152
           uint8_t *cc, uint16_t *reason_code)
2153
0
{
2154
0
  return decode_long_running_resp(msg, msg_len,
2155
0
          NSM_TYPE_PLATFORM_ENVIRONMENTAL,
2156
0
          NSM_SET_ECC_MODE, cc, reason_code);
2157
0
}
2158
2159
static void htoleEccErrorCounts(struct nsm_ECC_error_counts *errorCounts)
2160
0
{
2161
0
  errorCounts->flags.byte = htole16(errorCounts->flags.byte);
2162
0
  errorCounts->dram_corrected = htole32(errorCounts->dram_corrected);
2163
0
  errorCounts->dram_uncorrected = htole32(errorCounts->dram_uncorrected);
2164
0
  errorCounts->sram_corrected = htole32(errorCounts->sram_corrected);
2165
0
  errorCounts->sram_uncorrected_parity =
2166
0
      htole32(errorCounts->sram_uncorrected_parity);
2167
0
  errorCounts->sram_uncorrected_secded =
2168
0
      htole32(errorCounts->sram_uncorrected_secded);
2169
0
}
2170
2171
static void letohEccErrorCounts(struct nsm_ECC_error_counts *errorCounts)
2172
0
{
2173
0
  errorCounts->flags.byte = le16toh(errorCounts->flags.byte);
2174
0
  errorCounts->dram_corrected = le32toh(errorCounts->dram_corrected);
2175
0
  errorCounts->dram_uncorrected = le32toh(errorCounts->dram_uncorrected);
2176
0
  errorCounts->sram_corrected = le32toh(errorCounts->sram_corrected);
2177
0
  errorCounts->sram_uncorrected_parity =
2178
0
      le32toh(errorCounts->sram_uncorrected_parity);
2179
0
  errorCounts->sram_uncorrected_secded =
2180
0
      le32toh(errorCounts->sram_uncorrected_secded);
2181
0
}
2182
2183
// Get ECC Error Counts command, NSM T3 spec
2184
int encode_get_ECC_error_counts_req(uint8_t instance_id, struct nsm_msg *msg)
2185
0
{
2186
0
  if (msg == NULL) {
2187
0
    return NSM_SW_ERROR_NULL;
2188
0
  }
2189
2190
0
  struct nsm_header_info header = {0};
2191
0
  header.nsm_msg_type = NSM_REQUEST;
2192
0
  header.instance_id = instance_id;
2193
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
2194
2195
0
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
2196
0
  if (rc != NSM_SW_SUCCESS) {
2197
0
    return rc;
2198
0
  }
2199
2200
0
  struct nsm_common_req *request = (struct nsm_common_req *)msg->payload;
2201
2202
0
  request->command = NSM_GET_ECC_ERROR_COUNTS;
2203
0
  request->data_size = 0;
2204
2205
0
  return NSM_SW_SUCCESS;
2206
0
}
2207
2208
// Get ECC Error Counts command, NSM T3 spec
2209
int encode_get_ECC_error_counts_resp(uint8_t instance_id, uint8_t cc,
2210
             uint16_t reason_code,
2211
             struct nsm_ECC_error_counts *errorCounts,
2212
             struct nsm_msg *msg)
2213
0
{
2214
0
  if (msg == NULL || errorCounts == NULL) {
2215
0
    return NSM_SW_ERROR_NULL;
2216
0
  }
2217
0
  struct nsm_header_info header = {0};
2218
0
  header.nsm_msg_type = NSM_RESPONSE;
2219
0
  header.instance_id = instance_id & 0x1f;
2220
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
2221
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
2222
0
  if (rc != NSM_SW_SUCCESS) {
2223
0
    return rc;
2224
0
  }
2225
0
  if (cc != NSM_SUCCESS) {
2226
0
    return encode_reason_code(cc, reason_code,
2227
0
            NSM_GET_ECC_ERROR_COUNTS, msg);
2228
0
  }
2229
0
  struct nsm_get_ECC_error_counts_resp *resp =
2230
0
      (struct nsm_get_ECC_error_counts_resp *)msg->payload;
2231
0
  resp->hdr.command = NSM_GET_ECC_ERROR_COUNTS;
2232
0
  resp->hdr.completion_code = cc;
2233
0
  uint16_t data_size = sizeof(struct nsm_ECC_error_counts);
2234
0
  resp->hdr.data_size = htole16(data_size);
2235
2236
0
  htoleEccErrorCounts(errorCounts);
2237
0
  memcpy(&(resp->errorCounts), errorCounts,
2238
0
         sizeof(struct nsm_ECC_error_counts));
2239
2240
0
  return NSM_SW_SUCCESS;
2241
0
}
2242
2243
// Get ECC Error Counts command, NSM T3 spec
2244
int decode_get_ECC_error_counts_resp(const struct nsm_msg *msg, size_t msg_len,
2245
             uint8_t *cc, uint16_t *data_size,
2246
             uint16_t *reason_code,
2247
             struct nsm_ECC_error_counts *errorCounts)
2248
0
{
2249
0
  if (msg == NULL || cc == NULL || data_size == NULL ||
2250
0
      errorCounts == NULL) {
2251
0
    return NSM_SW_ERROR_NULL;
2252
0
  }
2253
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
2254
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
2255
0
    return rc;
2256
0
  }
2257
2258
0
  if (msg_len != (sizeof(struct nsm_msg_hdr)) +
2259
0
         sizeof(struct nsm_get_ECC_error_counts_resp)) {
2260
0
    return NSM_SW_ERROR_LENGTH;
2261
0
  }
2262
2263
0
  struct nsm_get_ECC_error_counts_resp *resp =
2264
0
      (struct nsm_get_ECC_error_counts_resp *)msg->payload;
2265
2266
0
  *data_size = le16toh(resp->hdr.data_size);
2267
0
  letohEccErrorCounts(&(resp->errorCounts));
2268
2269
0
  if ((*data_size) < sizeof(struct nsm_ECC_error_counts)) {
2270
0
    return NSM_SW_ERROR_DATA;
2271
0
  }
2272
0
  memcpy(errorCounts, &(resp->errorCounts),
2273
0
         sizeof(struct nsm_ECC_error_counts));
2274
2275
0
  return NSM_SW_SUCCESS;
2276
0
}
2277
2278
// Get Programmable EDPp Scaling factor, NSM T3 spec
2279
int encode_get_programmable_EDPp_scaling_factor_req(uint8_t instance_id,
2280
                struct nsm_msg *msg)
2281
0
{
2282
0
  if (msg == NULL) {
2283
0
    return NSM_SW_ERROR_NULL;
2284
0
  }
2285
2286
0
  struct nsm_header_info header = {0};
2287
0
  header.nsm_msg_type = NSM_REQUEST;
2288
0
  header.instance_id = instance_id;
2289
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
2290
2291
0
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
2292
0
  if (rc != NSM_SW_SUCCESS) {
2293
0
    return rc;
2294
0
  }
2295
2296
0
  struct nsm_common_req *request = (struct nsm_common_req *)msg->payload;
2297
2298
0
  request->command = NSM_GET_PROGRAMMABLE_EDPP_SCALING_FACTOR;
2299
0
  request->data_size = 0;
2300
0
  return NSM_SW_SUCCESS;
2301
0
}
2302
2303
// Get Programmable EDPp Scaling factor, NSM T3 spec
2304
int encode_get_programmable_EDPp_scaling_factor_resp(
2305
    uint8_t instance_id, uint8_t cc, uint16_t reason_code,
2306
    struct nsm_EDPp_scaling_factors *scaling_factors, struct nsm_msg *msg)
2307
0
{
2308
0
  if (msg == NULL || scaling_factors == NULL) {
2309
0
    return NSM_SW_ERROR_NULL;
2310
0
  }
2311
0
  struct nsm_header_info header = {0};
2312
0
  header.nsm_msg_type = NSM_RESPONSE;
2313
0
  header.instance_id = instance_id & 0x1f;
2314
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
2315
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
2316
0
  if (rc != NSM_SUCCESS) {
2317
0
    return rc;
2318
0
  }
2319
0
  if (cc != NSM_SUCCESS) {
2320
0
    return encode_reason_code(
2321
0
        cc, reason_code, NSM_GET_PROGRAMMABLE_EDPP_SCALING_FACTOR,
2322
0
        msg);
2323
0
  }
2324
2325
0
  struct nsm_get_programmable_EDPp_scaling_factor_resp *resp =
2326
0
      (struct nsm_get_programmable_EDPp_scaling_factor_resp *)
2327
0
    msg->payload;
2328
0
  resp->hdr.command = NSM_GET_PROGRAMMABLE_EDPP_SCALING_FACTOR;
2329
0
  resp->hdr.completion_code = cc;
2330
0
  uint16_t data_size = sizeof(struct nsm_EDPp_scaling_factors);
2331
0
  resp->hdr.data_size = htole16(data_size);
2332
0
  resp->scaling_factors = *scaling_factors;
2333
2334
0
  return NSM_SW_SUCCESS;
2335
0
}
2336
2337
// Get Programmable EDPp Scaling factor, NSM T3 spec
2338
int decode_get_programmable_EDPp_scaling_factor_resp(
2339
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc, uint16_t *data_size,
2340
    uint16_t *reason_code, struct nsm_EDPp_scaling_factors *scaling_factors)
2341
0
{
2342
0
  if (msg == NULL || cc == NULL || data_size == NULL ||
2343
0
      scaling_factors == NULL) {
2344
0
    return NSM_SW_ERROR_NULL;
2345
0
  }
2346
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
2347
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
2348
0
    return rc;
2349
0
  }
2350
2351
0
  if (msg_len !=
2352
0
      (sizeof(struct nsm_msg_hdr)) +
2353
0
    sizeof(struct nsm_get_programmable_EDPp_scaling_factor_resp)) {
2354
0
    return NSM_SW_ERROR_LENGTH;
2355
0
  }
2356
2357
0
  struct nsm_get_programmable_EDPp_scaling_factor_resp *resp =
2358
0
      (struct nsm_get_programmable_EDPp_scaling_factor_resp *)
2359
0
    msg->payload;
2360
0
  *cc = resp->hdr.completion_code;
2361
0
  if (NSM_SUCCESS != *cc) {
2362
0
    return NSM_SUCCESS;
2363
0
  }
2364
0
  *data_size = le16toh(resp->hdr.data_size);
2365
2366
0
  if ((*data_size) < sizeof(struct nsm_EDPp_scaling_factors)) {
2367
0
    return NSM_SW_ERROR_DATA;
2368
0
  }
2369
0
  *scaling_factors = resp->scaling_factors;
2370
2371
0
  return NSM_SW_SUCCESS;
2372
0
}
2373
2374
int encode_set_programmable_EDPp_scaling_factor_req(uint8_t instance_id,
2375
                uint8_t action,
2376
                uint8_t persistence,
2377
                uint8_t scaling_factor,
2378
                struct nsm_msg *msg)
2379
0
{
2380
0
  if (msg == NULL) {
2381
0
    return NSM_SW_ERROR_NULL;
2382
0
  }
2383
2384
0
  struct nsm_header_info header = {0};
2385
0
  header.nsm_msg_type = NSM_REQUEST;
2386
0
  header.instance_id = instance_id;
2387
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
2388
2389
0
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
2390
0
  if (rc != NSM_SW_SUCCESS) {
2391
0
    return rc;
2392
0
  }
2393
2394
0
  struct nsm_set_programmable_EDPp_scaling_factor_req *request =
2395
0
      (struct nsm_set_programmable_EDPp_scaling_factor_req *)msg->payload;
2396
2397
0
  request->hdr.command = NSM_SET_PROGRAMMABLE_EDPP_SCALING_FACTOR;
2398
0
  request->hdr.data_size =
2399
0
      sizeof(struct nsm_set_programmable_EDPp_scaling_factor_req) -
2400
0
      sizeof(struct nsm_common_req);
2401
0
  request->action = action;
2402
0
  request->persistence = persistence;
2403
0
  request->scaling_factor = scaling_factor;
2404
0
  return NSM_SW_SUCCESS;
2405
0
}
2406
2407
int decode_set_programmable_EDPp_scaling_factor_req(const struct nsm_msg *msg,
2408
                size_t msg_len,
2409
                uint8_t *action,
2410
                uint8_t *persistence,
2411
                uint8_t *scaling_factor)
2412
0
{
2413
0
  if (msg == NULL || action == NULL || persistence == NULL ||
2414
0
      scaling_factor == NULL) {
2415
0
    return NSM_SW_ERROR_NULL;
2416
0
  }
2417
2418
0
  if (msg_len !=
2419
0
      sizeof(struct nsm_msg_hdr) +
2420
0
    sizeof(struct nsm_set_programmable_EDPp_scaling_factor_req)) {
2421
0
    return NSM_SW_ERROR_LENGTH;
2422
0
  }
2423
2424
0
  struct nsm_set_programmable_EDPp_scaling_factor_req *request =
2425
0
      (struct nsm_set_programmable_EDPp_scaling_factor_req *)msg->payload;
2426
2427
0
  if (request->hdr.data_size !=
2428
0
      sizeof(struct nsm_set_programmable_EDPp_scaling_factor_req) -
2429
0
    sizeof(struct nsm_common_req)) {
2430
0
    return NSM_SW_ERROR_DATA;
2431
0
  }
2432
2433
0
  *action = request->action;
2434
0
  *persistence = request->persistence;
2435
0
  *scaling_factor = request->scaling_factor;
2436
2437
0
  return NSM_SW_SUCCESS;
2438
0
}
2439
2440
int encode_set_programmable_EDPp_scaling_factor_resp(uint8_t instance_id,
2441
                 uint8_t cc,
2442
                 uint16_t reason_code,
2443
                 struct nsm_msg *msg)
2444
0
{
2445
0
  if (msg == NULL) {
2446
0
    return NSM_SW_ERROR_NULL;
2447
0
  }
2448
2449
0
  struct nsm_header_info header = {0};
2450
0
  header.nsm_msg_type = NSM_RESPONSE;
2451
0
  header.instance_id = instance_id & 0x1f;
2452
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
2453
2454
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
2455
0
  if (rc != NSM_SUCCESS) {
2456
0
    return rc;
2457
0
  }
2458
0
  if (cc != NSM_SUCCESS) {
2459
0
    return encode_reason_code(
2460
0
        cc, reason_code, NSM_SET_PROGRAMMABLE_EDPP_SCALING_FACTOR,
2461
0
        msg);
2462
0
  }
2463
2464
0
  struct nsm_common_resp *resp = (struct nsm_common_resp *)msg->payload;
2465
0
  resp->command = NSM_SET_PROGRAMMABLE_EDPP_SCALING_FACTOR;
2466
0
  resp->completion_code = cc;
2467
0
  resp->data_size = 0;
2468
2469
0
  return NSM_SW_SUCCESS;
2470
0
}
2471
2472
int decode_set_programmable_EDPp_scaling_factor_resp(const struct nsm_msg *msg,
2473
                 size_t msg_len,
2474
                 uint8_t *cc,
2475
                 uint16_t *data_size,
2476
                 uint16_t *reason_code)
2477
0
{
2478
0
  return decode_common_resp(msg, msg_len, cc, data_size, reason_code);
2479
0
}
2480
2481
int encode_set_power_limit_req(uint8_t instance_id, uint32_t id, uint8_t action,
2482
             uint8_t persistence, uint32_t power_limit,
2483
             struct nsm_msg *msg)
2484
0
{
2485
0
  if (msg == NULL) {
2486
0
    return NSM_SW_ERROR_NULL;
2487
0
  }
2488
2489
0
  struct nsm_header_info header = {0};
2490
0
  header.nsm_msg_type = NSM_REQUEST;
2491
0
  header.instance_id = instance_id;
2492
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
2493
2494
0
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
2495
0
  if (rc != NSM_SW_SUCCESS) {
2496
0
    return rc;
2497
0
  }
2498
2499
0
  struct nsm_set_power_limit_req *request =
2500
0
      (struct nsm_set_power_limit_req *)msg->payload;
2501
2502
0
  request->hdr.command = NSM_SET_POWER_LIMITS;
2503
0
  request->hdr.data_size = 2 * sizeof(uint8_t) + 2 * sizeof(uint32_t);
2504
0
  request->action = action;
2505
0
  request->persistance = persistence;
2506
0
  request->power_limit = htole32(power_limit);
2507
0
  request->id = htole32(id);
2508
0
  return NSM_SW_SUCCESS;
2509
0
}
2510
2511
int encode_set_device_power_limit_req(uint8_t instance, uint8_t action,
2512
              uint8_t persistence, uint32_t power_limit,
2513
              struct nsm_msg *msg)
2514
0
{
2515
0
  return encode_set_power_limit_req(instance, DEVICE, action, persistence,
2516
0
            power_limit, msg);
2517
0
}
2518
2519
int encode_set_module_power_limit_req(uint8_t instance, uint8_t action,
2520
              uint8_t persistence, uint32_t power_limit,
2521
              struct nsm_msg *msg)
2522
0
{
2523
0
  return encode_set_power_limit_req(instance, MODULE, action, persistence,
2524
0
            power_limit, msg);
2525
0
}
2526
2527
int decode_set_power_limit_req(const struct nsm_msg *msg, size_t msg_len,
2528
             uint32_t *id, uint8_t *action,
2529
             uint8_t *persistence, uint32_t *power_limit)
2530
0
{
2531
0
  if (msg == NULL || id == NULL || action == NULL ||
2532
0
      persistence == NULL || power_limit == NULL) {
2533
0
    return NSM_SW_ERROR_NULL;
2534
0
  }
2535
2536
0
  if (msg_len != sizeof(struct nsm_msg_hdr) +
2537
0
         sizeof(struct nsm_set_power_limit_req)) {
2538
0
    return NSM_SW_ERROR_LENGTH;
2539
0
  }
2540
2541
0
  struct nsm_set_power_limit_req *request =
2542
0
      (struct nsm_set_power_limit_req *)msg->payload;
2543
2544
0
  if (request->hdr.data_size !=
2545
0
      2 * sizeof(uint8_t) + 2 * sizeof(uint32_t)) {
2546
0
    return NSM_SW_ERROR_DATA;
2547
0
  }
2548
2549
0
  *action = request->action;
2550
0
  *persistence = request->persistance;
2551
0
  *power_limit = le32toh(request->power_limit);
2552
0
  *id = le32toh(request->id);
2553
0
  return NSM_SW_SUCCESS;
2554
0
}
2555
2556
int encode_set_power_limit_resp(uint8_t instance_id, uint8_t cc,
2557
        uint16_t reason_code, struct nsm_msg *msg)
2558
0
{
2559
0
  if (msg == NULL) {
2560
0
    return NSM_SW_ERROR_NULL;
2561
0
  }
2562
2563
0
  struct nsm_header_info header = {0};
2564
0
  header.nsm_msg_type = NSM_RESPONSE;
2565
0
  header.instance_id = instance_id & INSTANCEID_MASK;
2566
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
2567
2568
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
2569
0
  if (rc != NSM_SUCCESS) {
2570
0
    return rc;
2571
0
  }
2572
0
  if (cc != NSM_SUCCESS) {
2573
0
    return encode_reason_code(cc, reason_code, NSM_SET_POWER_LIMITS,
2574
0
            msg);
2575
0
  }
2576
2577
0
  struct nsm_common_resp *resp = (struct nsm_common_resp *)msg->payload;
2578
0
  resp->command = NSM_SET_POWER_LIMITS;
2579
0
  resp->completion_code = cc;
2580
0
  resp->data_size = 0;
2581
2582
0
  return NSM_SW_SUCCESS;
2583
0
}
2584
2585
int decode_set_power_limit_resp(const struct nsm_msg *msg, size_t msg_len,
2586
        uint8_t *cc, uint16_t *data_size,
2587
        uint16_t *reason_code)
2588
0
{
2589
0
  return decode_common_resp(msg, msg_len, cc, data_size, reason_code);
2590
0
}
2591
2592
int encode_get_power_limit_req(uint8_t instance_id, uint32_t id,
2593
             struct nsm_msg *msg)
2594
0
{
2595
0
  if (msg == NULL) {
2596
0
    return NSM_SW_ERROR_NULL;
2597
0
  }
2598
2599
0
  struct nsm_header_info header = {0};
2600
0
  header.nsm_msg_type = NSM_REQUEST;
2601
0
  header.instance_id = instance_id;
2602
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
2603
2604
0
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
2605
0
  if (rc != NSM_SW_SUCCESS) {
2606
0
    return rc;
2607
0
  }
2608
2609
0
  struct nsm_get_power_limit_req *request =
2610
0
      (struct nsm_get_power_limit_req *)msg->payload;
2611
2612
0
  request->hdr.command = NSM_GET_POWER_LIMITS;
2613
0
  request->hdr.data_size = sizeof(id);
2614
0
  request->id = htole32(id);
2615
0
  return NSM_SW_SUCCESS;
2616
0
}
2617
2618
int encode_get_device_power_limit_req(uint8_t instance, struct nsm_msg *msg)
2619
0
{
2620
0
  return encode_get_power_limit_req(instance, DEVICE, msg);
2621
0
}
2622
2623
int encode_get_module_power_limit_req(uint8_t instance, struct nsm_msg *msg)
2624
0
{
2625
0
  return encode_get_power_limit_req(instance, MODULE, msg);
2626
0
}
2627
2628
int decode_get_power_limit_req(const struct nsm_msg *msg, size_t msg_len,
2629
             uint32_t *id)
2630
0
{
2631
0
  if (msg == NULL || id == NULL) {
2632
0
    return NSM_SW_ERROR_NULL;
2633
0
  }
2634
2635
0
  if (msg_len != sizeof(struct nsm_msg_hdr) +
2636
0
         sizeof(struct nsm_get_power_limit_req)) {
2637
0
    return NSM_SW_ERROR_LENGTH;
2638
0
  }
2639
2640
0
  struct nsm_get_power_limit_req *request =
2641
0
      (struct nsm_get_power_limit_req *)msg->payload;
2642
2643
0
  if (request->hdr.data_size != sizeof(uint32_t)) {
2644
0
    return NSM_SW_ERROR_DATA;
2645
0
  }
2646
0
  *id = le32toh(request->id);
2647
0
  return NSM_SW_SUCCESS;
2648
0
}
2649
2650
int encode_get_power_limit_resp(uint8_t instance_id, uint8_t cc,
2651
        uint16_t reason_code,
2652
        uint32_t requested_persistent_limit,
2653
        uint32_t requested_oneshot_limit,
2654
        uint32_t enforced_limit, struct nsm_msg *msg)
2655
0
{
2656
0
  if (msg == NULL) {
2657
0
    return NSM_SW_ERROR_NULL;
2658
0
  }
2659
2660
0
  struct nsm_header_info header = {0};
2661
0
  header.nsm_msg_type = NSM_RESPONSE;
2662
0
  header.instance_id = instance_id & 0x1f;
2663
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
2664
2665
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
2666
0
  if (rc != NSM_SUCCESS) {
2667
0
    return rc;
2668
0
  }
2669
0
  if (cc != NSM_SUCCESS) {
2670
0
    return encode_reason_code(cc, reason_code, NSM_GET_POWER_LIMITS,
2671
0
            msg);
2672
0
  }
2673
2674
0
  struct nsm_get_power_limit_resp *resp =
2675
0
      (struct nsm_get_power_limit_resp *)msg->payload;
2676
2677
0
  resp->hdr.command = NSM_GET_POWER_LIMITS;
2678
0
  resp->hdr.completion_code = cc;
2679
0
  uint16_t data_size = 3 * sizeof(uint32_t);
2680
0
  resp->hdr.data_size = htole16(data_size);
2681
0
  resp->requested_persistent_limit = htole32(requested_persistent_limit);
2682
0
  resp->requested_oneshot_limit = htole32(requested_oneshot_limit);
2683
0
  resp->enforced_limit = htole32(enforced_limit);
2684
2685
0
  return NSM_SW_SUCCESS;
2686
0
}
2687
2688
int decode_get_power_limit_resp(const struct nsm_msg *msg, size_t msg_len,
2689
        uint8_t *cc, uint16_t *data_size,
2690
        uint16_t *reason_code,
2691
        uint32_t *requested_persistent_limit,
2692
        uint32_t *requested_oneshot_limit,
2693
        uint32_t *enforced_limit)
2694
0
{
2695
0
  if (msg == NULL || cc == NULL || data_size == NULL ||
2696
0
      requested_persistent_limit == NULL ||
2697
0
      requested_oneshot_limit == NULL || enforced_limit == NULL) {
2698
0
    return NSM_SW_ERROR_NULL;
2699
0
  }
2700
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
2701
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
2702
0
    return rc;
2703
0
  }
2704
2705
0
  if (msg_len != (sizeof(struct nsm_msg_hdr)) +
2706
0
         sizeof(struct nsm_get_power_limit_resp)) {
2707
0
    return NSM_SW_ERROR_LENGTH;
2708
0
  }
2709
2710
0
  struct nsm_get_power_limit_resp *resp =
2711
0
      (struct nsm_get_power_limit_resp *)msg->payload;
2712
2713
0
  *data_size = le16toh(resp->hdr.data_size);
2714
2715
0
  if ((*data_size) != 3 * sizeof(uint32_t)) {
2716
0
    return NSM_SW_ERROR_DATA;
2717
0
  }
2718
0
  *requested_persistent_limit = le32toh(resp->requested_persistent_limit);
2719
0
  *requested_oneshot_limit = le32toh(resp->requested_oneshot_limit);
2720
0
  *enforced_limit = le32toh(resp->enforced_limit);
2721
2722
0
  return NSM_SW_SUCCESS;
2723
0
}
2724
2725
static void htoleClockLimit(struct nsm_clock_limit *clock_limit)
2726
0
{
2727
0
  clock_limit->present_limit_max =
2728
0
      htole32(clock_limit->present_limit_max);
2729
0
  clock_limit->present_limit_min =
2730
0
      htole32(clock_limit->present_limit_min);
2731
0
  clock_limit->requested_limit_max =
2732
0
      htole32(clock_limit->requested_limit_max);
2733
0
  clock_limit->requested_limit_min =
2734
0
      htole32(clock_limit->requested_limit_min);
2735
0
}
2736
2737
static void letohClockLimit(struct nsm_clock_limit *clock_limit)
2738
0
{
2739
0
  clock_limit->present_limit_max =
2740
0
      le32toh(clock_limit->present_limit_max);
2741
0
  clock_limit->present_limit_min =
2742
0
      le32toh(clock_limit->present_limit_min);
2743
0
  clock_limit->requested_limit_max =
2744
0
      le32toh(clock_limit->requested_limit_max);
2745
0
  clock_limit->requested_limit_min =
2746
0
      le32toh(clock_limit->requested_limit_min);
2747
0
}
2748
2749
// Get Clock Limit, NSM T3 spec
2750
int encode_get_clock_limit_req(uint8_t instance_id, uint8_t clock_id,
2751
             struct nsm_msg *msg)
2752
0
{
2753
0
  if (msg == NULL) {
2754
0
    return NSM_SW_ERROR_NULL;
2755
0
  }
2756
2757
0
  struct nsm_header_info header = {0};
2758
0
  header.nsm_msg_type = NSM_REQUEST;
2759
0
  header.instance_id = instance_id;
2760
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
2761
2762
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
2763
0
  if (rc != NSM_SW_SUCCESS) {
2764
0
    return rc;
2765
0
  }
2766
2767
0
  struct nsm_get_clock_limit_req *request =
2768
0
      (struct nsm_get_clock_limit_req *)msg->payload;
2769
2770
0
  request->hdr.command = NSM_GET_CLOCK_LIMIT;
2771
0
  request->hdr.data_size = sizeof(clock_id);
2772
0
  request->clock_id = clock_id;
2773
2774
0
  return NSM_SW_SUCCESS;
2775
0
}
2776
2777
// Get Clock Limit, NSM T3 spec
2778
int decode_get_clock_limit_req(const struct nsm_msg *msg, size_t msg_len,
2779
             uint8_t *clock_id)
2780
0
{
2781
0
  if (msg == NULL || clock_id == NULL) {
2782
0
    return NSM_SW_ERROR_NULL;
2783
0
  }
2784
2785
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
2786
0
        sizeof(struct nsm_get_clock_limit_req)) {
2787
0
    return NSM_SW_ERROR_LENGTH;
2788
0
  }
2789
2790
0
  struct nsm_get_clock_limit_req *request =
2791
0
      (struct nsm_get_clock_limit_req *)msg->payload;
2792
2793
0
  if (request->hdr.data_size < sizeof(request->clock_id)) {
2794
0
    return NSM_SW_ERROR_DATA;
2795
0
  }
2796
2797
0
  *clock_id = request->clock_id;
2798
2799
0
  return NSM_SW_SUCCESS;
2800
0
}
2801
2802
// Get Clock Limit, NSM T3 spec
2803
int encode_get_clock_limit_resp(uint8_t instance_id, uint8_t cc,
2804
        uint16_t reason_code,
2805
        struct nsm_clock_limit *clock_limit,
2806
        struct nsm_msg *msg)
2807
0
{
2808
0
  if (msg == NULL || clock_limit == NULL) {
2809
0
    return NSM_SW_ERROR_NULL;
2810
0
  }
2811
0
  struct nsm_header_info header = {0};
2812
0
  header.nsm_msg_type = NSM_RESPONSE;
2813
0
  header.instance_id = instance_id & 0x1f;
2814
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
2815
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
2816
0
  if (rc != NSM_SUCCESS) {
2817
0
    return rc;
2818
0
  }
2819
0
  if (cc != NSM_SUCCESS) {
2820
0
    return encode_reason_code(cc, reason_code, NSM_GET_CLOCK_LIMIT,
2821
0
            msg);
2822
0
  }
2823
2824
0
  struct nsm_get_clock_limit_resp *resp =
2825
0
      (struct nsm_get_clock_limit_resp *)msg->payload;
2826
0
  resp->hdr.command = NSM_GET_CLOCK_LIMIT;
2827
0
  resp->hdr.completion_code = cc;
2828
0
  uint16_t data_size = sizeof(struct nsm_clock_limit);
2829
0
  resp->hdr.data_size = htole16(data_size);
2830
2831
0
  htoleClockLimit(clock_limit);
2832
0
  memcpy(&(resp->clock_limit), clock_limit,
2833
0
         sizeof(struct nsm_clock_limit));
2834
2835
0
  return NSM_SW_SUCCESS;
2836
0
}
2837
2838
// Get Clock Limit, NSM T3 spec
2839
int decode_get_clock_limit_resp(const struct nsm_msg *msg, size_t msg_len,
2840
        uint8_t *cc, uint16_t *data_size,
2841
        uint16_t *reason_code,
2842
        struct nsm_clock_limit *clock_limit)
2843
0
{
2844
0
  if (msg == NULL || cc == NULL || data_size == NULL ||
2845
0
      clock_limit == NULL) {
2846
0
    return NSM_SW_ERROR_NULL;
2847
0
  }
2848
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
2849
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
2850
0
    return rc;
2851
0
  }
2852
2853
0
  if (msg_len != (sizeof(struct nsm_msg_hdr)) +
2854
0
         sizeof(struct nsm_get_clock_limit_resp)) {
2855
0
    return NSM_SW_ERROR_LENGTH;
2856
0
  }
2857
2858
0
  struct nsm_get_clock_limit_resp *resp =
2859
0
      (struct nsm_get_clock_limit_resp *)msg->payload;
2860
2861
0
  *data_size = le16toh(resp->hdr.data_size);
2862
0
  letohClockLimit(&(resp->clock_limit));
2863
2864
0
  if ((*data_size) < sizeof(struct nsm_clock_limit)) {
2865
0
    return NSM_SW_ERROR_DATA;
2866
0
  }
2867
2868
0
  memcpy(clock_limit, &(resp->clock_limit),
2869
0
         sizeof(struct nsm_clock_limit));
2870
2871
0
  return NSM_SW_SUCCESS;
2872
0
}
2873
2874
// Get Current Clock Frequency command, NSM T3 spec
2875
int encode_get_curr_clock_freq_req(uint8_t instance_id, uint8_t clock_id,
2876
           struct nsm_msg *msg)
2877
0
{
2878
0
  if (msg == NULL) {
2879
0
    return NSM_SW_ERROR_NULL;
2880
0
  }
2881
2882
0
  struct nsm_header_info header = {0};
2883
0
  header.nsm_msg_type = NSM_REQUEST;
2884
0
  header.instance_id = instance_id;
2885
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
2886
2887
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
2888
0
  if (rc != NSM_SW_SUCCESS) {
2889
0
    return rc;
2890
0
  }
2891
2892
0
  struct nsm_get_curr_clock_freq_req *request =
2893
0
      (struct nsm_get_curr_clock_freq_req *)msg->payload;
2894
2895
0
  request->hdr.command = NSM_GET_CURRENT_CLOCK_FREQUENCY;
2896
0
  request->hdr.data_size = sizeof(clock_id);
2897
0
  request->clock_id = clock_id;
2898
2899
0
  return NSM_SW_SUCCESS;
2900
0
}
2901
2902
int decode_get_curr_clock_freq_req(const struct nsm_msg *msg, size_t msg_len,
2903
           uint8_t *clock_id)
2904
0
{
2905
0
  if (msg == NULL || clock_id == NULL) {
2906
0
    return NSM_SW_ERROR_NULL;
2907
0
  }
2908
2909
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
2910
0
        sizeof(struct nsm_get_curr_clock_freq_req)) {
2911
0
    return NSM_SW_ERROR_LENGTH;
2912
0
  }
2913
2914
0
  struct nsm_get_curr_clock_freq_req *request =
2915
0
      (struct nsm_get_curr_clock_freq_req *)msg->payload;
2916
2917
0
  if (request->hdr.data_size < sizeof(request->clock_id)) {
2918
0
    return NSM_SW_ERROR_DATA;
2919
0
  }
2920
2921
0
  *clock_id = request->clock_id;
2922
2923
0
  return NSM_SW_SUCCESS;
2924
0
}
2925
2926
// Get Current Clock Frequency command, NSM T3 spec
2927
int encode_get_curr_clock_freq_resp(uint8_t instance_id, uint8_t cc,
2928
            uint16_t reason_code, uint32_t *clockFreq,
2929
            struct nsm_msg *msg)
2930
0
{
2931
0
  if (msg == NULL || clockFreq == NULL) {
2932
0
    return NSM_SW_ERROR_NULL;
2933
0
  }
2934
0
  struct nsm_header_info header = {0};
2935
0
  header.nsm_msg_type = NSM_RESPONSE;
2936
0
  header.instance_id = instance_id & 0x1f;
2937
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
2938
2939
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
2940
0
  if (rc != NSM_SW_SUCCESS) {
2941
0
    return rc;
2942
0
  }
2943
0
  if (cc != NSM_SUCCESS) {
2944
0
    return encode_reason_code(cc, reason_code,
2945
0
            NSM_GET_CURRENT_CLOCK_FREQUENCY, msg);
2946
0
  }
2947
2948
0
  struct nsm_get_curr_clock_freq_resp *resp =
2949
0
      (struct nsm_get_curr_clock_freq_resp *)msg->payload;
2950
0
  resp->hdr.command = NSM_GET_CURRENT_CLOCK_FREQUENCY;
2951
0
  resp->hdr.completion_code = cc;
2952
0
  uint16_t data_size = sizeof(uint32_t);
2953
0
  resp->hdr.data_size = htole16(data_size);
2954
0
  *clockFreq = htole32(*clockFreq);
2955
0
  memcpy(&(resp->clockFreq), clockFreq, data_size);
2956
2957
0
  return NSM_SW_SUCCESS;
2958
0
}
2959
2960
// Get Current Clock Frequency command, NSM T3 spec
2961
int decode_get_curr_clock_freq_resp(const struct nsm_msg *msg, size_t msg_len,
2962
            uint8_t *cc, uint16_t *data_size,
2963
            uint16_t *reason_code, uint32_t *clockFreq)
2964
0
{
2965
0
  if (msg == NULL || cc == NULL || data_size == NULL ||
2966
0
      clockFreq == NULL) {
2967
0
    return NSM_SW_ERROR_NULL;
2968
0
  }
2969
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
2970
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
2971
0
    return rc;
2972
0
  }
2973
2974
0
  if (msg_len != (sizeof(struct nsm_msg_hdr)) +
2975
0
         sizeof(struct nsm_get_curr_clock_freq_resp)) {
2976
0
    return NSM_SW_ERROR_LENGTH;
2977
0
  }
2978
2979
0
  struct nsm_get_curr_clock_freq_resp *resp =
2980
0
      (struct nsm_get_curr_clock_freq_resp *)msg->payload;
2981
2982
0
  if (resp->hdr.command != NSM_GET_CURRENT_CLOCK_FREQUENCY) {
2983
0
    return NSM_SW_ERROR_DATA;
2984
0
  }
2985
2986
0
  *data_size = le16toh(resp->hdr.data_size);
2987
2988
0
  if ((*data_size) < sizeof(uint32_t)) {
2989
0
    return NSM_SW_ERROR_DATA;
2990
0
  }
2991
0
  *clockFreq = le32toh(resp->clockFreq);
2992
2993
0
  return NSM_SW_SUCCESS;
2994
0
}
2995
2996
int encode_get_current_clock_event_reason_code_req(uint8_t instance_id,
2997
               struct nsm_msg *msg)
2998
0
{
2999
0
  if (msg == NULL) {
3000
0
    return NSM_SW_ERROR_NULL;
3001
0
  }
3002
3003
0
  struct nsm_header_info header = {0};
3004
0
  header.nsm_msg_type = NSM_REQUEST;
3005
0
  header.instance_id = instance_id;
3006
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
3007
3008
0
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
3009
0
  if (rc != NSM_SW_SUCCESS) {
3010
0
    return rc;
3011
0
  }
3012
3013
0
  struct nsm_common_req *request = (struct nsm_common_req *)msg->payload;
3014
3015
0
  request->command = NSM_GET_CLOCK_EVENT_REASON_CODES;
3016
0
  request->data_size = 0;
3017
3018
0
  return NSM_SW_SUCCESS;
3019
0
}
3020
3021
int decode_get_current_clock_event_reason_code_req(const struct nsm_msg *msg,
3022
               size_t msg_len)
3023
0
{
3024
0
  return decode_common_req(msg, msg_len);
3025
0
}
3026
3027
int encode_get_current_clock_event_reason_code_resp(uint8_t instance_id,
3028
                uint8_t cc,
3029
                uint16_t reason_code,
3030
                bitfield32_t *flags,
3031
                struct nsm_msg *msg)
3032
0
{
3033
0
  if (msg == NULL) {
3034
0
    return NSM_SW_ERROR_NULL;
3035
0
  }
3036
3037
0
  struct nsm_header_info header = {0};
3038
0
  header.nsm_msg_type = NSM_RESPONSE;
3039
0
  header.instance_id = instance_id & 0x1f;
3040
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
3041
3042
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
3043
0
  if (rc != NSM_SW_SUCCESS) {
3044
0
    return rc;
3045
0
  }
3046
3047
0
  if (cc != NSM_SUCCESS) {
3048
0
    return encode_reason_code(
3049
0
        cc, reason_code, NSM_GET_CLOCK_EVENT_REASON_CODES, msg);
3050
0
  }
3051
3052
0
  struct nsm_get_current_clock_event_reason_code_resp *resp =
3053
0
      (struct nsm_get_current_clock_event_reason_code_resp *)msg->payload;
3054
3055
0
  resp->hdr.command = NSM_GET_CLOCK_EVENT_REASON_CODES;
3056
0
  resp->hdr.completion_code = cc;
3057
0
  resp->hdr.data_size = htole16(sizeof(bitfield32_t));
3058
3059
0
  resp->flags.byte = htole32(flags->byte);
3060
0
  return NSM_SW_SUCCESS;
3061
0
}
3062
3063
int decode_get_current_clock_event_reason_code_resp(const struct nsm_msg *msg,
3064
                size_t msg_len, uint8_t *cc,
3065
                uint16_t *data_size,
3066
                uint16_t *reason_code,
3067
                bitfield32_t *flags)
3068
0
{
3069
0
  if (data_size == NULL || flags == NULL) {
3070
0
    return NSM_SW_ERROR_NULL;
3071
0
  }
3072
3073
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
3074
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
3075
0
    return rc;
3076
0
  }
3077
3078
0
  if (msg_len !=
3079
0
      sizeof(struct nsm_msg_hdr) +
3080
0
    sizeof(struct nsm_get_current_clock_event_reason_code_resp)) {
3081
0
    return NSM_SW_ERROR_LENGTH;
3082
0
  }
3083
3084
0
  struct nsm_get_current_clock_event_reason_code_resp *resp =
3085
0
      (struct nsm_get_current_clock_event_reason_code_resp *)msg->payload;
3086
3087
0
  *data_size = le16toh(resp->hdr.data_size);
3088
0
  if ((*data_size) < sizeof(bitfield32_t)) {
3089
0
    return NSM_SW_ERROR_DATA;
3090
0
  }
3091
0
  flags->byte = (resp->flags.byte);
3092
0
  return NSM_SW_SUCCESS;
3093
0
}
3094
3095
// Get Accumulated GPU Utilization Command, NSM T3 spec
3096
int encode_get_accum_GPU_util_time_req(uint8_t instance, struct nsm_msg *msg)
3097
0
{
3098
0
  if (msg == NULL) {
3099
0
    return NSM_SW_ERROR_NULL;
3100
0
  }
3101
3102
0
  struct nsm_header_info header = {0};
3103
0
  header.nsm_msg_type = NSM_REQUEST;
3104
0
  header.instance_id = instance;
3105
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
3106
3107
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
3108
0
  if (rc != NSM_SW_SUCCESS) {
3109
0
    return rc;
3110
0
  }
3111
3112
0
  struct nsm_common_req *request = (struct nsm_common_req *)msg->payload;
3113
3114
0
  request->command = NSM_GET_ACCUMULATED_GPU_UTILIZATION_TIME;
3115
0
  request->data_size = 0;
3116
3117
0
  return NSM_SW_SUCCESS;
3118
0
}
3119
3120
// Get Accumulated GPU Utilization Command, NSM T3 spec
3121
int encode_get_accum_GPU_util_time_resp(uint8_t instance_id, uint8_t cc,
3122
          uint16_t reason_code,
3123
          uint32_t *context_util_time,
3124
          uint32_t *SM_util_time,
3125
          struct nsm_msg *msg)
3126
0
{
3127
0
  if (msg == NULL) {
3128
0
    return NSM_SW_ERROR_NULL;
3129
0
  }
3130
0
  struct nsm_header_info header = {0};
3131
0
  header.nsm_msg_type = NSM_RESPONSE;
3132
0
  header.instance_id = instance_id & 0x1f;
3133
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
3134
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
3135
0
  if (rc != NSM_SW_SUCCESS) {
3136
0
    return rc;
3137
0
  }
3138
0
  if (cc != NSM_SUCCESS) {
3139
0
    return encode_reason_code(
3140
0
        cc, reason_code, NSM_GET_ACCUMULATED_GPU_UTILIZATION_TIME,
3141
0
        msg);
3142
0
  }
3143
3144
0
  struct nsm_get_accum_GPU_util_time_resp *resp =
3145
0
      (struct nsm_get_accum_GPU_util_time_resp *)msg->payload;
3146
0
  resp->hdr.command = NSM_GET_ACCUMULATED_GPU_UTILIZATION_TIME;
3147
0
  resp->hdr.completion_code = cc;
3148
0
  uint16_t data_size = 2 * sizeof(uint32_t);
3149
0
  resp->hdr.data_size = htole16(data_size);
3150
3151
0
  resp->context_util_time = htole32(*context_util_time);
3152
0
  resp->SM_util_time = htole32(*SM_util_time);
3153
3154
0
  return NSM_SW_SUCCESS;
3155
0
}
3156
3157
// Get Accumulated GPU Utilization Command, NSM T3 spec
3158
int decode_get_accum_GPU_util_time_resp(
3159
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc, uint16_t *data_size,
3160
    uint16_t *reason_code, uint32_t *context_util_time, uint32_t *SM_util_time)
3161
0
{
3162
0
  if (msg == NULL || cc == NULL || data_size == NULL ||
3163
0
      context_util_time == NULL || SM_util_time == NULL) {
3164
0
    return NSM_SW_ERROR_NULL;
3165
0
  }
3166
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
3167
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
3168
0
    return rc;
3169
0
  }
3170
3171
0
  if (msg_len != (sizeof(struct nsm_msg_hdr)) +
3172
0
         sizeof(struct nsm_get_accum_GPU_util_time_resp)) {
3173
0
    return NSM_SW_ERROR_LENGTH;
3174
0
  }
3175
3176
0
  struct nsm_get_accum_GPU_util_time_resp *resp =
3177
0
      (struct nsm_get_accum_GPU_util_time_resp *)msg->payload;
3178
3179
0
  *data_size = le16toh(resp->hdr.data_size);
3180
3181
0
  if ((*data_size) < 2 * sizeof(uint32_t)) {
3182
0
    return NSM_SW_ERROR_DATA;
3183
0
  }
3184
0
  *context_util_time = le32toh(resp->context_util_time);
3185
0
  *SM_util_time = le32toh(resp->SM_util_time);
3186
3187
0
  return NSM_SW_SUCCESS;
3188
0
}
3189
3190
int encode_get_current_utilization_req(uint8_t instance, struct nsm_msg *msg)
3191
0
{
3192
0
  if (msg == NULL) {
3193
0
    return NSM_SW_ERROR_NULL;
3194
0
  }
3195
3196
0
  struct nsm_header_info header = {0};
3197
0
  header.nsm_msg_type = NSM_REQUEST;
3198
0
  header.instance_id = instance;
3199
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
3200
3201
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
3202
0
  if (rc != NSM_SW_SUCCESS) {
3203
0
    return rc;
3204
0
  }
3205
3206
0
  struct nsm_common_req *request = (struct nsm_common_req *)msg->payload;
3207
3208
0
  request->command = NSM_GET_CURRENT_UTILIZATION;
3209
0
  request->data_size = 0;
3210
3211
0
  return NSM_SW_SUCCESS;
3212
0
}
3213
3214
int encode_get_current_utilization_resp(
3215
    uint8_t instance_id, uint8_t cc, uint16_t reason_code,
3216
    const struct nsm_get_current_utilization_data *data, struct nsm_msg *msg)
3217
0
{
3218
0
  if (msg == NULL || data == NULL) {
3219
0
    return NSM_SW_ERROR_NULL;
3220
0
  }
3221
3222
0
  struct nsm_header_info header = {0};
3223
0
  header.nsm_msg_type = NSM_RESPONSE;
3224
0
  header.instance_id = instance_id & 0x1f;
3225
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
3226
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
3227
0
  if (rc != NSM_SW_SUCCESS) {
3228
0
    return rc;
3229
0
  }
3230
3231
0
  if (cc != NSM_SUCCESS) {
3232
0
    return encode_reason_code(cc, reason_code,
3233
0
            NSM_GET_CURRENT_UTILIZATION, msg);
3234
0
  }
3235
3236
0
  struct nsm_get_current_utilization_resp *resp =
3237
0
      (struct nsm_get_current_utilization_resp *)msg->payload;
3238
0
  resp->hdr.command = NSM_GET_CURRENT_UTILIZATION;
3239
0
  resp->hdr.completion_code = cc;
3240
0
  uint16_t data_size = sizeof(struct nsm_get_current_utilization_data);
3241
0
  resp->hdr.data_size = htole16(data_size);
3242
3243
0
  resp->data.gpu_utilization = htole32(data->gpu_utilization);
3244
0
  resp->data.memory_utilization = htole32(data->memory_utilization);
3245
3246
0
  return NSM_SW_SUCCESS;
3247
0
}
3248
3249
int decode_get_current_utilization_resp(
3250
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc, uint16_t *data_size,
3251
    uint16_t *reason_code, struct nsm_get_current_utilization_data *data)
3252
0
{
3253
0
  if (msg == NULL || cc == NULL || data_size == NULL || data == NULL) {
3254
0
    return NSM_SW_ERROR_NULL;
3255
0
  }
3256
3257
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
3258
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
3259
0
    return rc;
3260
0
  }
3261
3262
0
  if (msg_len < (sizeof(struct nsm_msg_hdr)) +
3263
0
        sizeof(struct nsm_get_current_utilization_resp)) {
3264
0
    return NSM_SW_ERROR_LENGTH;
3265
0
  }
3266
3267
0
  struct nsm_get_current_utilization_resp *resp =
3268
0
      (struct nsm_get_current_utilization_resp *)msg->payload;
3269
3270
0
  *data_size = le16toh(resp->hdr.data_size);
3271
3272
0
  if ((*data_size) < sizeof(struct nsm_get_current_utilization_data)) {
3273
0
    return NSM_SW_ERROR_DATA;
3274
0
  }
3275
0
  data->gpu_utilization = le32toh(resp->data.gpu_utilization);
3276
0
  data->memory_utilization = le32toh(resp->data.memory_utilization);
3277
3278
0
  return NSM_SW_SUCCESS;
3279
0
}
3280
int encode_get_current_utilization_event_resp(
3281
    uint8_t instance_id, uint8_t cc, uint16_t reason_code,
3282
    struct nsm_get_current_utilization_data *data, struct nsm_msg *msg)
3283
0
{
3284
0
  if (data != NULL) {
3285
0
    data->gpu_utilization = htole32(data->gpu_utilization);
3286
0
    data->memory_utilization = htole32(data->memory_utilization);
3287
0
  }
3288
0
  return encode_long_running_resp(
3289
0
      instance_id, cc, reason_code, NSM_TYPE_PLATFORM_ENVIRONMENTAL,
3290
0
      NSM_GET_CURRENT_UTILIZATION, (const uint8_t *)data,
3291
0
      sizeof(struct nsm_get_current_utilization_data), msg);
3292
0
}
3293
3294
int decode_get_current_utilization_event_resp(
3295
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
3296
    uint16_t *reason_code, struct nsm_get_current_utilization_data *data)
3297
0
{
3298
0
  int rc = decode_long_running_resp_with_data(
3299
0
      msg, msg_len, NSM_TYPE_PLATFORM_ENVIRONMENTAL,
3300
0
      NSM_GET_CURRENT_UTILIZATION, cc, reason_code, (uint8_t *)data,
3301
0
      sizeof(struct nsm_get_current_utilization_data));
3302
0
  if (rc == NSM_SW_SUCCESS && data != NULL) {
3303
0
    data->gpu_utilization = le32toh(data->gpu_utilization);
3304
0
    data->memory_utilization = le32toh(data->memory_utilization);
3305
0
  }
3306
0
  return rc;
3307
0
}
3308
3309
// Get Row Remap State command, NSM T3 spec
3310
int encode_get_row_remap_state_req(uint8_t instance_id, struct nsm_msg *msg)
3311
0
{
3312
0
  if (msg == NULL) {
3313
0
    return NSM_SW_ERROR_NULL;
3314
0
  }
3315
3316
0
  struct nsm_header_info header = {0};
3317
0
  header.nsm_msg_type = NSM_REQUEST;
3318
0
  header.instance_id = instance_id;
3319
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
3320
3321
0
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
3322
0
  if (rc != NSM_SW_SUCCESS) {
3323
0
    return rc;
3324
0
  }
3325
3326
0
  struct nsm_common_req *request = (struct nsm_common_req *)msg->payload;
3327
3328
0
  request->command = NSM_GET_ROW_REMAP_STATE_FLAGS;
3329
0
  request->data_size = 0;
3330
0
  return NSM_SW_SUCCESS;
3331
0
}
3332
3333
// Get Row Remap State command, NSM T3 spec
3334
int decode_get_row_remap_state_req(const struct nsm_msg *msg, size_t msg_len)
3335
0
{
3336
0
  return decode_common_req(msg, msg_len);
3337
0
}
3338
3339
// Get Row Remap State command, NSM T3 spec
3340
int encode_get_row_remap_state_resp(uint8_t instance_id, uint8_t cc,
3341
            uint16_t reason_code, bitfield8_t *flags,
3342
            struct nsm_msg *msg)
3343
0
{
3344
0
  if (msg == NULL || flags == NULL) {
3345
0
    return NSM_SW_ERROR_NULL;
3346
0
  }
3347
3348
0
  struct nsm_header_info header = {0};
3349
0
  header.nsm_msg_type = NSM_RESPONSE;
3350
0
  header.instance_id = instance_id & 0x1f;
3351
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
3352
3353
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
3354
0
  if (rc != NSM_SW_SUCCESS) {
3355
0
    return rc;
3356
0
  }
3357
0
  if (cc != NSM_SUCCESS) {
3358
0
    return encode_reason_code(cc, reason_code,
3359
0
            NSM_GET_ROW_REMAP_STATE_FLAGS, msg);
3360
0
  }
3361
3362
0
  struct nsm_get_row_remap_state_resp *resp =
3363
0
      (struct nsm_get_row_remap_state_resp *)msg->payload;
3364
0
  resp->hdr.command = NSM_GET_ROW_REMAP_STATE_FLAGS;
3365
0
  resp->hdr.completion_code = cc;
3366
0
  uint16_t data_size = sizeof(bitfield8_t);
3367
0
  resp->hdr.data_size = htole16(data_size);
3368
3369
0
  memcpy(&(resp->flags), flags, data_size);
3370
3371
0
  return NSM_SW_SUCCESS;
3372
0
}
3373
3374
// Get Row Remap State command, NSM T3 spec
3375
int decode_get_row_remap_state_resp(const struct nsm_msg *msg, size_t msg_len,
3376
            uint8_t *cc, uint16_t *data_size,
3377
            uint16_t *reason_code, bitfield8_t *flags)
3378
0
{
3379
0
  if (msg == NULL || cc == NULL || data_size == NULL || flags == NULL) {
3380
0
    return NSM_SW_ERROR_NULL;
3381
0
  }
3382
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
3383
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
3384
0
    return rc;
3385
0
  }
3386
3387
0
  if (msg_len != (sizeof(struct nsm_msg_hdr)) +
3388
0
         sizeof(struct nsm_get_row_remap_state_resp)) {
3389
0
    return NSM_SW_ERROR_LENGTH;
3390
0
  }
3391
3392
0
  struct nsm_get_row_remap_state_resp *resp =
3393
0
      (struct nsm_get_row_remap_state_resp *)msg->payload;
3394
3395
0
  *data_size = le16toh(resp->hdr.data_size);
3396
3397
0
  if ((*data_size) < sizeof(bitfield8_t)) {
3398
0
    return NSM_SW_ERROR_DATA;
3399
0
  }
3400
0
  memcpy(flags, &(resp->flags), sizeof(bitfield8_t));
3401
3402
0
  return NSM_SW_SUCCESS;
3403
0
}
3404
3405
// Get Row Remapping Counts, NSM T3 spec
3406
int encode_get_row_remapping_counts_req(uint8_t instance_id,
3407
          struct nsm_msg *msg)
3408
0
{
3409
0
  if (msg == NULL) {
3410
0
    return NSM_SW_ERROR_NULL;
3411
0
  }
3412
3413
0
  struct nsm_header_info header = {0};
3414
0
  header.nsm_msg_type = NSM_REQUEST;
3415
0
  header.instance_id = instance_id;
3416
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
3417
3418
0
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
3419
0
  if (rc != NSM_SW_SUCCESS) {
3420
0
    return rc;
3421
0
  }
3422
3423
0
  struct nsm_common_req *request = (struct nsm_common_req *)msg->payload;
3424
3425
0
  request->command = NSM_GET_ROW_REMAPPING_COUNTS;
3426
0
  request->data_size = 0;
3427
0
  return NSM_SW_SUCCESS;
3428
0
}
3429
3430
// Get Row Remapping Counts, NSM T3 spec
3431
int decode_get_row_remapping_counts_req(const struct nsm_msg *msg,
3432
          size_t msg_len)
3433
0
{
3434
0
  return decode_common_req(msg, msg_len);
3435
0
}
3436
3437
// Get Row Remapping Counts, NSM T3 spec
3438
int encode_get_row_remapping_counts_resp(uint8_t instance_id, uint8_t cc,
3439
           uint16_t reason_code,
3440
           uint32_t correctable_error,
3441
           uint32_t uncorrectable_error,
3442
           struct nsm_msg *msg)
3443
0
{
3444
0
  if (msg == NULL) {
3445
0
    return NSM_SW_ERROR_NULL;
3446
0
  }
3447
0
  struct nsm_header_info header = {0};
3448
0
  header.nsm_msg_type = NSM_RESPONSE;
3449
0
  header.instance_id = instance_id & 0x1f;
3450
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
3451
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
3452
0
  if (rc != NSM_SW_SUCCESS) {
3453
0
    return rc;
3454
0
  }
3455
0
  if (cc != NSM_SUCCESS) {
3456
0
    return encode_reason_code(cc, reason_code,
3457
0
            NSM_GET_ROW_REMAPPING_COUNTS, msg);
3458
0
  }
3459
3460
0
  struct nsm_get_row_remapping_counts_resp *resp =
3461
0
      (struct nsm_get_row_remapping_counts_resp *)msg->payload;
3462
0
  resp->hdr.command = NSM_GET_ROW_REMAPPING_COUNTS;
3463
0
  resp->hdr.completion_code = cc;
3464
0
  uint16_t data_size = 2 * sizeof(uint32_t);
3465
0
  resp->hdr.data_size = htole16(data_size);
3466
3467
0
  resp->correctable_error = htole32(correctable_error);
3468
0
  resp->uncorrectable_error = htole32(uncorrectable_error);
3469
3470
0
  return NSM_SW_SUCCESS;
3471
0
}
3472
3473
// Get Row Remapping Counts, NSM T3 spec
3474
int decode_get_row_remapping_counts_resp(const struct nsm_msg *msg,
3475
           size_t msg_len, uint8_t *cc,
3476
           uint16_t *data_size,
3477
           uint16_t *reason_code,
3478
           uint32_t *correctable_error,
3479
           uint32_t *uncorrectable_error)
3480
0
{
3481
0
  if (msg == NULL || cc == NULL || data_size == NULL ||
3482
0
      correctable_error == NULL || uncorrectable_error == NULL) {
3483
0
    return NSM_SW_ERROR_NULL;
3484
0
  }
3485
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
3486
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
3487
0
    return rc;
3488
0
  }
3489
3490
0
  if (msg_len != (sizeof(struct nsm_msg_hdr)) +
3491
0
         sizeof(struct nsm_get_row_remapping_counts_resp)) {
3492
0
    return NSM_SW_ERROR_LENGTH;
3493
0
  }
3494
3495
0
  struct nsm_get_row_remapping_counts_resp *resp =
3496
0
      (struct nsm_get_row_remapping_counts_resp *)msg->payload;
3497
3498
0
  *data_size = le16toh(resp->hdr.data_size);
3499
3500
0
  if ((*data_size) < 2 * sizeof(uint32_t)) {
3501
0
    return NSM_SW_ERROR_DATA;
3502
0
  }
3503
3504
0
  *correctable_error = le16toh(resp->correctable_error);
3505
0
  *uncorrectable_error = le16toh(resp->uncorrectable_error);
3506
3507
0
  return NSM_SW_SUCCESS;
3508
0
}
3509
3510
int encode_get_row_remap_availability_req(uint8_t instance_id,
3511
            struct nsm_msg *msg)
3512
0
{
3513
0
  if (msg == NULL) {
3514
0
    return NSM_SW_ERROR_NULL;
3515
0
  }
3516
3517
0
  struct nsm_header_info header = {0};
3518
0
  header.nsm_msg_type = NSM_REQUEST;
3519
0
  header.instance_id = instance_id;
3520
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
3521
3522
0
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
3523
0
  if (rc != NSM_SW_SUCCESS) {
3524
0
    return rc;
3525
0
  }
3526
3527
0
  struct nsm_common_req *request = (struct nsm_common_req *)msg->payload;
3528
3529
0
  request->command = NSM_GET_ROW_REMAP_AVAILABILITY;
3530
0
  request->data_size = 0;
3531
0
  return NSM_SW_SUCCESS;
3532
0
}
3533
3534
int decode_get_row_remap_availability_req(const struct nsm_msg *msg,
3535
            size_t msg_len)
3536
0
{
3537
0
  return decode_common_req(msg, msg_len);
3538
0
}
3539
3540
int encode_get_row_remap_availability_resp(
3541
    uint8_t instance_id, uint8_t cc, uint16_t reason_code,
3542
    struct nsm_row_remap_availability *data, struct nsm_msg *msg)
3543
0
{
3544
0
  if (msg == NULL || data == NULL) {
3545
0
    return NSM_SW_ERROR_NULL;
3546
0
  }
3547
3548
0
  struct nsm_header_info header = {0};
3549
0
  header.nsm_msg_type = NSM_RESPONSE;
3550
0
  header.instance_id = instance_id & 0x1f;
3551
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
3552
3553
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
3554
0
  if (rc != NSM_SW_SUCCESS) {
3555
0
    return rc;
3556
0
  }
3557
0
  if (cc != NSM_SUCCESS) {
3558
0
    return encode_reason_code(cc, reason_code,
3559
0
            NSM_GET_ROW_REMAP_AVAILABILITY, msg);
3560
0
  }
3561
3562
0
  struct nsm_get_row_remap_availability_resp *resp =
3563
0
      (struct nsm_get_row_remap_availability_resp *)msg->payload;
3564
0
  resp->hdr.command = NSM_GET_ROW_REMAP_AVAILABILITY;
3565
0
  resp->hdr.completion_code = cc;
3566
0
  uint16_t data_size = sizeof(struct nsm_row_remap_availability);
3567
0
  resp->hdr.data_size = htole16(data_size);
3568
0
  resp->data.high_remapping = htole16(data->high_remapping);
3569
0
  resp->data.low_remapping = htole16(data->low_remapping);
3570
0
  resp->data.max_remapping = htole16(data->max_remapping);
3571
0
  resp->data.no_remapping = htole16(data->no_remapping);
3572
0
  resp->data.partial_remapping = htole16(data->partial_remapping);
3573
0
  return NSM_SW_SUCCESS;
3574
0
}
3575
3576
int decode_get_row_remap_availability_resp(
3577
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc, uint16_t *data_size,
3578
    uint16_t *reason_code, struct nsm_row_remap_availability *data)
3579
0
{
3580
0
  if (data_size == NULL || data == NULL) {
3581
0
    return NSM_SW_ERROR_NULL;
3582
0
  }
3583
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
3584
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
3585
0
    return rc;
3586
0
  }
3587
3588
0
  if (msg_len != (sizeof(struct nsm_msg_hdr)) +
3589
0
         sizeof(struct nsm_get_row_remap_availability_resp)) {
3590
0
    return NSM_SW_ERROR_LENGTH;
3591
0
  }
3592
3593
0
  struct nsm_get_row_remap_availability_resp *resp =
3594
0
      (struct nsm_get_row_remap_availability_resp *)msg->payload;
3595
3596
0
  *data_size = le16toh(resp->hdr.data_size);
3597
3598
0
  if ((*data_size) < sizeof(struct nsm_row_remap_availability)) {
3599
0
    return NSM_SW_ERROR_DATA;
3600
0
  }
3601
3602
0
  data->high_remapping = le16toh(resp->data.high_remapping);
3603
0
  data->low_remapping = le16toh(resp->data.low_remapping);
3604
0
  data->max_remapping = le16toh(resp->data.max_remapping);
3605
0
  data->no_remapping = le16toh(resp->data.no_remapping);
3606
0
  data->partial_remapping = le16toh(resp->data.partial_remapping);
3607
3608
0
  return NSM_SW_SUCCESS;
3609
0
}
3610
3611
int encode_get_memory_capacity_util_req(uint8_t instance_id,
3612
          struct nsm_msg *msg)
3613
0
{
3614
0
  if (msg == NULL) {
3615
0
    return NSM_SW_ERROR_NULL;
3616
0
  }
3617
3618
0
  struct nsm_header_info header = {0};
3619
0
  header.nsm_msg_type = NSM_REQUEST;
3620
0
  header.instance_id = instance_id;
3621
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
3622
3623
0
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
3624
0
  if (rc != NSM_SW_SUCCESS) {
3625
0
    return rc;
3626
0
  }
3627
3628
0
  struct nsm_common_req *request = (struct nsm_common_req *)msg->payload;
3629
3630
0
  request->command = NSM_GET_MEMORY_CAPACITY_UTILIZATION;
3631
0
  request->data_size = 0;
3632
3633
0
  return NSM_SW_SUCCESS;
3634
0
}
3635
3636
int decode_get_memory_capacity_util_req(const struct nsm_msg *msg,
3637
          size_t msg_len)
3638
0
{
3639
0
  return decode_common_req(msg, msg_len);
3640
0
}
3641
3642
int encode_get_memory_capacity_util_resp(
3643
    uint8_t instance_id, uint8_t cc, uint16_t reason_code,
3644
    struct nsm_memory_capacity_utilization *data, struct nsm_msg *msg)
3645
0
{
3646
0
  if (msg == NULL) {
3647
0
    return NSM_SW_ERROR_NULL;
3648
0
  }
3649
3650
0
  struct nsm_header_info header = {0};
3651
0
  header.nsm_msg_type = NSM_RESPONSE;
3652
0
  header.instance_id = instance_id & 0x1f;
3653
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
3654
3655
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
3656
0
  if (rc != NSM_SW_SUCCESS) {
3657
0
    return rc;
3658
0
  }
3659
3660
0
  if (cc != NSM_SUCCESS) {
3661
0
    return encode_reason_code(
3662
0
        cc, reason_code, NSM_GET_MEMORY_CAPACITY_UTILIZATION, msg);
3663
0
  }
3664
3665
0
  struct nsm_get_memory_capacity_util_resp *resp =
3666
0
      (struct nsm_get_memory_capacity_util_resp *)msg->payload;
3667
3668
0
  resp->hdr.command = NSM_GET_MEMORY_CAPACITY_UTILIZATION;
3669
0
  resp->hdr.completion_code = cc;
3670
0
  resp->hdr.data_size =
3671
0
      htole16(sizeof(struct nsm_memory_capacity_utilization));
3672
3673
0
  resp->data.reserved_memory = htole32(data->reserved_memory);
3674
0
  resp->data.used_memory = htole32(data->used_memory);
3675
3676
0
  return NSM_SW_SUCCESS;
3677
0
}
3678
3679
int decode_get_memory_capacity_util_resp(
3680
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc, uint16_t *data_size,
3681
    uint16_t *reason_code, struct nsm_memory_capacity_utilization *data)
3682
0
{
3683
0
  if (data_size == NULL || data == NULL) {
3684
0
    return NSM_SW_ERROR_NULL;
3685
0
  }
3686
3687
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
3688
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
3689
0
    return rc;
3690
0
  }
3691
3692
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
3693
0
        sizeof(struct nsm_get_memory_capacity_util_resp)) {
3694
0
    return NSM_SW_ERROR_LENGTH;
3695
0
  }
3696
3697
0
  struct nsm_get_memory_capacity_util_resp *resp =
3698
0
      (struct nsm_get_memory_capacity_util_resp *)msg->payload;
3699
3700
0
  *data_size = le16toh(resp->hdr.data_size);
3701
3702
0
  if (*data_size != sizeof(struct nsm_memory_capacity_utilization)) {
3703
0
    return NSM_SW_ERROR_DATA;
3704
0
  }
3705
0
  data->reserved_memory = le32toh(resp->data.reserved_memory);
3706
0
  data->used_memory = le32toh(resp->data.used_memory);
3707
3708
0
  return NSM_SW_SUCCESS;
3709
0
}
3710
3711
int encode_get_memory_capacity_util_event_resp(
3712
    uint8_t instance_id, uint8_t cc, uint16_t reason_code,
3713
    struct nsm_memory_capacity_utilization *data, struct nsm_msg *msg)
3714
0
{
3715
0
  if (data != NULL) {
3716
0
    data->reserved_memory = htole32(data->reserved_memory);
3717
0
    data->used_memory = htole32(data->used_memory);
3718
0
  }
3719
0
  return encode_long_running_resp(
3720
0
      instance_id, cc, reason_code, NSM_TYPE_PLATFORM_ENVIRONMENTAL,
3721
0
      NSM_GET_MEMORY_CAPACITY_UTILIZATION, (const uint8_t *)data,
3722
0
      sizeof(struct nsm_memory_capacity_utilization), msg);
3723
0
}
3724
3725
int decode_get_memory_capacity_util_event_resp(
3726
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
3727
    uint16_t *reason_code, struct nsm_memory_capacity_utilization *data)
3728
0
{
3729
0
  int rc = decode_long_running_resp_with_data(
3730
0
      msg, msg_len, NSM_TYPE_PLATFORM_ENVIRONMENTAL,
3731
0
      NSM_GET_MEMORY_CAPACITY_UTILIZATION, cc, reason_code,
3732
0
      (uint8_t *)data, sizeof(struct nsm_memory_capacity_utilization));
3733
0
  if (rc == NSM_SW_SUCCESS && data != NULL) {
3734
0
    data->reserved_memory = le32toh(data->reserved_memory);
3735
0
    data->used_memory = le32toh(data->used_memory);
3736
0
  }
3737
0
  return rc;
3738
0
}
3739
3740
int encode_get_clock_output_enable_state_req(uint8_t instance_id, uint8_t index,
3741
               struct nsm_msg *msg)
3742
0
{
3743
0
  if (msg == NULL) {
3744
0
    return NSM_SW_ERROR_NULL;
3745
0
  }
3746
3747
0
  struct nsm_header_info header = {0};
3748
0
  header.nsm_msg_type = NSM_REQUEST;
3749
0
  header.instance_id = instance_id;
3750
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
3751
3752
0
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
3753
0
  if (rc != NSM_SW_SUCCESS) {
3754
0
    return rc;
3755
0
  }
3756
3757
0
  struct nsm_get_clock_output_enabled_state_req *request =
3758
0
      (struct nsm_get_clock_output_enabled_state_req *)msg->payload;
3759
3760
0
  request->hdr.command = NSM_GET_CLOCK_OUTPUT_ENABLE_STATE;
3761
0
  request->hdr.data_size = sizeof(index);
3762
0
  request->index = index;
3763
3764
0
  return NSM_SW_SUCCESS;
3765
0
}
3766
3767
int decode_get_clock_output_enable_state_req(const struct nsm_msg *msg,
3768
               size_t msg_len, uint8_t *index)
3769
0
{
3770
0
  if (msg == NULL || index == NULL) {
3771
0
    return NSM_SW_ERROR_NULL;
3772
0
  }
3773
3774
0
  if (msg_len <
3775
0
      sizeof(struct nsm_msg_hdr) +
3776
0
    sizeof(struct nsm_get_clock_output_enabled_state_req)) {
3777
0
    return NSM_SW_ERROR_LENGTH;
3778
0
  }
3779
3780
0
  struct nsm_get_clock_output_enabled_state_req *request =
3781
0
      (struct nsm_get_clock_output_enabled_state_req *)msg->payload;
3782
3783
0
  if (request->hdr.data_size < sizeof(request->index)) {
3784
0
    return NSM_SW_ERROR_DATA;
3785
0
  }
3786
3787
0
  *index = request->index;
3788
3789
0
  return NSM_SW_SUCCESS;
3790
0
}
3791
3792
int encode_get_clock_output_enable_state_resp(uint8_t instance_id, uint8_t cc,
3793
                uint16_t reason_code,
3794
                uint32_t clk_buf,
3795
                struct nsm_msg *msg)
3796
0
{
3797
0
  if (msg == NULL) {
3798
0
    return NSM_SW_ERROR_NULL;
3799
0
  }
3800
3801
0
  struct nsm_header_info header = {0};
3802
0
  header.nsm_msg_type = NSM_RESPONSE;
3803
0
  header.instance_id = instance_id & INSTANCEID_MASK;
3804
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
3805
3806
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
3807
0
  if (rc != NSM_SW_SUCCESS) {
3808
0
    return rc;
3809
0
  }
3810
3811
0
  if (cc != NSM_SUCCESS) {
3812
0
    return encode_reason_code(
3813
0
        cc, reason_code, NSM_GET_CLOCK_OUTPUT_ENABLE_STATE, msg);
3814
0
  }
3815
3816
0
  struct nsm_get_clock_output_enabled_state_resp *response =
3817
0
      (struct nsm_get_clock_output_enabled_state_resp *)msg->payload;
3818
3819
0
  response->hdr.command = NSM_GET_CLOCK_OUTPUT_ENABLE_STATE;
3820
0
  response->hdr.completion_code = cc;
3821
0
  response->hdr.data_size = htole16(sizeof(clk_buf));
3822
0
  response->clk_buf_data = htole32(clk_buf);
3823
3824
0
  return NSM_SW_SUCCESS;
3825
0
}
3826
3827
int decode_get_clock_output_enable_state_resp(const struct nsm_msg *msg,
3828
                size_t msg_len, uint8_t *cc,
3829
                uint16_t *reason_code,
3830
                uint16_t *data_size,
3831
                uint32_t *clk_buf)
3832
0
{
3833
0
  if (data_size == NULL || clk_buf == NULL) {
3834
0
    return NSM_SW_ERROR_NULL;
3835
0
  }
3836
3837
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
3838
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
3839
0
    return rc;
3840
0
  }
3841
3842
0
  if (msg_len !=
3843
0
      (sizeof(struct nsm_msg_hdr) +
3844
0
       sizeof(struct nsm_get_clock_output_enabled_state_resp))) {
3845
0
    return NSM_SW_ERROR_LENGTH;
3846
0
  }
3847
3848
0
  struct nsm_get_clock_output_enabled_state_resp *resp =
3849
0
      (struct nsm_get_clock_output_enabled_state_resp *)msg->payload;
3850
3851
0
  *data_size = le16toh(resp->hdr.data_size);
3852
0
  if (*data_size < sizeof(*clk_buf)) {
3853
0
    return NSM_SW_ERROR_DATA;
3854
0
  }
3855
3856
0
  *clk_buf = le32toh(resp->clk_buf_data);
3857
3858
0
  return NSM_SW_SUCCESS;
3859
0
}
3860
3861
// Set Clock Limit Command, NSM T3 spec
3862
int encode_set_clock_limit_req(uint8_t instance_id, uint8_t clock_id,
3863
             uint8_t flags, uint32_t limit_min,
3864
             uint32_t limit_max, struct nsm_msg *msg)
3865
0
{
3866
0
  if (msg == NULL) {
3867
0
    return NSM_SW_ERROR_NULL;
3868
0
  }
3869
3870
0
  struct nsm_header_info header = {0};
3871
0
  header.nsm_msg_type = NSM_REQUEST;
3872
0
  header.instance_id = instance_id;
3873
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
3874
3875
0
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
3876
0
  if (rc != NSM_SW_SUCCESS) {
3877
0
    return rc;
3878
0
  }
3879
3880
0
  struct nsm_set_clock_limit_req *request =
3881
0
      (struct nsm_set_clock_limit_req *)msg->payload;
3882
3883
0
  request->hdr.command = NSM_SET_CLOCK_LIMIT;
3884
0
  request->hdr.data_size = sizeof(struct nsm_set_clock_limit_req) -
3885
0
         sizeof(struct nsm_common_req);
3886
0
  request->flags = flags;
3887
0
  request->clock_id = clock_id;
3888
0
  request->limit_max = htole32(limit_max);
3889
0
  request->limit_min = htole32(limit_min);
3890
0
  return NSM_SW_SUCCESS;
3891
0
}
3892
3893
// Set Clock Limit Command, NSM T3 spec
3894
int decode_set_clock_limit_req(const struct nsm_msg *msg, size_t msg_len,
3895
             uint8_t *clock_id, uint8_t *flags,
3896
             uint32_t *limit_min, uint32_t *limit_max)
3897
0
{
3898
0
  if (msg == NULL || clock_id == NULL || flags == NULL ||
3899
0
      limit_min == NULL || limit_max == NULL) {
3900
0
    return NSM_SW_ERROR_NULL;
3901
0
  }
3902
3903
0
  if (msg_len != sizeof(struct nsm_msg_hdr) +
3904
0
         sizeof(struct nsm_set_clock_limit_req)) {
3905
0
    return NSM_SW_ERROR_LENGTH;
3906
0
  }
3907
3908
0
  struct nsm_set_clock_limit_req *request =
3909
0
      (struct nsm_set_clock_limit_req *)msg->payload;
3910
3911
0
  if (request->hdr.data_size != sizeof(struct nsm_set_clock_limit_req) -
3912
0
            sizeof(struct nsm_common_req)) {
3913
0
    return NSM_SW_ERROR_DATA;
3914
0
  }
3915
3916
0
  *clock_id = request->clock_id;
3917
0
  *flags = request->flags;
3918
0
  *limit_max = le32toh(request->limit_max);
3919
0
  *limit_min = le32toh(request->limit_min);
3920
0
  return NSM_SW_SUCCESS;
3921
0
}
3922
3923
int encode_set_clock_limit_resp(uint8_t instance_id, uint8_t cc,
3924
        uint16_t reason_code, struct nsm_msg *msg)
3925
0
{
3926
0
  if (msg == NULL) {
3927
0
    return NSM_SW_ERROR_NULL;
3928
0
  }
3929
3930
0
  struct nsm_header_info header = {0};
3931
0
  header.nsm_msg_type = NSM_RESPONSE;
3932
0
  header.instance_id = instance_id & 0x1f;
3933
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
3934
3935
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
3936
0
  if (rc != NSM_SUCCESS) {
3937
0
    return rc;
3938
0
  }
3939
0
  if (cc != NSM_SUCCESS) {
3940
0
    return encode_reason_code(cc, reason_code, NSM_SET_CLOCK_LIMIT,
3941
0
            msg);
3942
0
  }
3943
3944
0
  struct nsm_common_resp *resp = (struct nsm_common_resp *)msg->payload;
3945
0
  resp->command = NSM_SET_CLOCK_LIMIT;
3946
0
  resp->completion_code = cc;
3947
0
  resp->data_size = 0;
3948
3949
0
  return NSM_SW_SUCCESS;
3950
0
}
3951
3952
int decode_set_clock_limit_resp(const struct nsm_msg *msg, size_t msg_len,
3953
        uint8_t *cc, uint16_t *data_size,
3954
        uint16_t *reason_code)
3955
0
{
3956
0
  return decode_common_resp(msg, msg_len, cc, data_size, reason_code);
3957
0
}
3958
3959
int encode_nsm_xid_event(uint8_t instance_id, bool ackr,
3960
       struct nsm_xid_event_payload payload,
3961
       const char *message_text, size_t message_text_size,
3962
       struct nsm_msg *msg)
3963
0
{
3964
0
  payload.reason = htole32(payload.reason);
3965
0
  payload.sequence_number = htole32(payload.sequence_number);
3966
0
  payload.timestamp = htole64(payload.timestamp);
3967
3968
0
  uint8_t event_data[NSM_EVENT_DATA_MAX_LEN];
3969
0
  memcpy(event_data, &payload, sizeof(payload));
3970
0
  memcpy(&event_data[sizeof(payload)], message_text, message_text_size);
3971
3972
0
  return encode_nsm_event(
3973
0
      instance_id, NSM_TYPE_PLATFORM_ENVIRONMENTAL, ackr,
3974
0
      NSM_EVENT_VERSION, NSM_XID_EVENT, NSM_GENERAL_EVENT_CLASS, 0,
3975
0
      sizeof(payload) + message_text_size, event_data, msg);
3976
0
}
3977
3978
int decode_nsm_xid_event(const struct nsm_msg *msg, size_t msg_len,
3979
       uint8_t *event_class, uint16_t *event_state,
3980
       struct nsm_xid_event_payload *payload,
3981
       char *message_text, size_t *message_text_size)
3982
0
{
3983
0
  if (msg == NULL || event_class == NULL || event_state == NULL ||
3984
0
      payload == NULL || message_text == NULL ||
3985
0
      message_text_size == NULL) {
3986
0
    return NSM_SW_ERROR_NULL;
3987
0
  }
3988
3989
0
  if (msg_len < sizeof(struct nsm_msg_hdr) + NSM_EVENT_MIN_LEN) {
3990
0
    return NSM_SW_ERROR_LENGTH;
3991
0
  }
3992
3993
0
  struct nsm_event *event = (struct nsm_event *)msg->payload;
3994
3995
0
  if (event->data_size >
3996
0
      msg_len - sizeof(struct nsm_msg_hdr) - NSM_EVENT_MIN_LEN) {
3997
0
    return NSM_SW_ERROR_DATA;
3998
0
  }
3999
4000
0
  *event_class = event->event_class;
4001
0
  *event_state = le16toh(event->event_state);
4002
4003
0
  if (event->data_size < sizeof(*payload)) {
4004
0
    return NSM_SW_ERROR_DATA;
4005
0
  } else if (event->data_size == sizeof(*payload)) {
4006
0
    *message_text_size = 0;
4007
0
  } else {
4008
0
    *message_text_size = event->data_size - sizeof(*payload);
4009
4010
0
    const uint8_t *text = &event->data[0] + sizeof(*payload);
4011
0
    memcpy(message_text, text, *message_text_size);
4012
0
  }
4013
4014
0
  memcpy(payload, event->data, sizeof(*payload));
4015
4016
0
  payload->reason = le32toh(payload->reason);
4017
0
  payload->sequence_number = le32toh(payload->sequence_number);
4018
0
  payload->timestamp = le64toh(payload->timestamp);
4019
4020
0
  return NSM_SW_SUCCESS;
4021
0
}
4022
4023
int encode_query_aggregate_gpm_metrics_req(
4024
    uint8_t instance, uint8_t retrieval_source, uint8_t gpu_instance,
4025
    uint8_t compute_instance, const uint8_t *metrics_bitfield,
4026
    size_t metrics_bitfield_length, struct nsm_msg *msg)
4027
0
{
4028
0
  if (msg == NULL) {
4029
0
    return NSM_SW_ERROR_NULL;
4030
0
  }
4031
4032
0
  struct nsm_header_info header = {0};
4033
0
  header.nsm_msg_type = NSM_REQUEST;
4034
0
  header.instance_id = instance;
4035
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
4036
4037
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
4038
0
  if (rc != NSM_SW_SUCCESS) {
4039
0
    return rc;
4040
0
  }
4041
4042
0
  struct nsm_query_aggregate_gpm_metrics_req *request =
4043
0
      (struct nsm_query_aggregate_gpm_metrics_req *)msg->payload;
4044
4045
0
  request->hdr.command = NSM_QUERY_AGGREGATE_GPM_METRICS;
4046
0
  request->hdr.data_size =
4047
0
      sizeof(struct nsm_query_aggregate_gpm_metrics_req) -
4048
0
      sizeof(struct nsm_common_req) - 1 + metrics_bitfield_length;
4049
0
  request->retrieval_source = retrieval_source;
4050
0
  request->gpu_instance = gpu_instance;
4051
0
  request->compute_instance = compute_instance;
4052
0
  memcpy(request->metrics_bitfield, metrics_bitfield,
4053
0
         metrics_bitfield_length);
4054
4055
0
  return NSM_SW_SUCCESS;
4056
0
}
4057
4058
int encode_nsm_reset_required_event(uint8_t instance_id, bool ackr,
4059
            struct nsm_msg *msg)
4060
0
{
4061
0
  return encode_nsm_event(instance_id, NSM_TYPE_PLATFORM_ENVIRONMENTAL,
4062
0
        ackr, NSM_EVENT_VERSION,
4063
0
        NSM_RESET_REQUIRED_EVENT,
4064
0
        NSM_GENERAL_EVENT_CLASS, 0, 0, NULL, msg);
4065
0
}
4066
4067
int decode_nsm_reset_required_event(const struct nsm_msg *msg, size_t msg_len,
4068
            uint8_t *event_class, uint16_t *event_state)
4069
0
{
4070
0
  uint8_t data_size = 0;
4071
0
  int result =
4072
0
      decode_nsm_event(msg, msg_len, NSM_RESET_REQUIRED_EVENT,
4073
0
           NSM_GENERAL_EVENT_CLASS, event_state, &data_size);
4074
0
  if (data_size > 0) {
4075
0
    return NSM_SW_ERROR_DATA;
4076
0
  }
4077
0
  if (event_class != NULL) {
4078
0
    *event_class = NSM_GENERAL_EVENT_CLASS;
4079
0
  }
4080
0
  return result;
4081
0
}
4082
4083
int decode_query_aggregate_gpm_metrics_req(
4084
    const struct nsm_msg *msg, size_t msg_len, uint8_t *retrieval_source,
4085
    uint8_t *gpu_instance, uint8_t *compute_instance,
4086
    const uint8_t **metrics_bitfield, size_t *metrics_bitfield_length)
4087
0
{
4088
0
  if (msg == NULL || retrieval_source == NULL || gpu_instance == NULL ||
4089
0
      compute_instance == NULL || metrics_bitfield == NULL ||
4090
0
      metrics_bitfield_length == NULL) {
4091
0
    return NSM_SW_ERROR_NULL;
4092
0
  }
4093
4094
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
4095
0
        sizeof(struct nsm_query_aggregate_gpm_metrics_req)) {
4096
0
    return NSM_SW_ERROR_LENGTH;
4097
0
  }
4098
4099
0
  struct nsm_query_aggregate_gpm_metrics_req *request =
4100
0
      (struct nsm_query_aggregate_gpm_metrics_req *)msg->payload;
4101
4102
0
  if (request->hdr.data_size <
4103
0
      (sizeof(struct nsm_query_aggregate_gpm_metrics_req) -
4104
0
       sizeof(struct nsm_common_req))) {
4105
0
    return NSM_SW_ERROR_DATA;
4106
0
  }
4107
4108
0
  *retrieval_source = request->retrieval_source;
4109
0
  *gpu_instance = request->gpu_instance;
4110
0
  *compute_instance = request->compute_instance;
4111
0
  *metrics_bitfield = request->metrics_bitfield;
4112
0
  *metrics_bitfield_length =
4113
0
      request->hdr.data_size -
4114
0
      (sizeof(struct nsm_query_aggregate_gpm_metrics_req) -
4115
0
       sizeof(struct nsm_common_req) - 1);
4116
4117
0
  return NSM_SW_SUCCESS;
4118
0
}
4119
4120
int encode_query_per_instance_gpm_metrics_req(
4121
    uint8_t instance, uint8_t retrieval_source, uint8_t gpu_instance,
4122
    uint8_t compute_instance, uint8_t metric_id, uint32_t instance_bitmask,
4123
    struct nsm_msg *msg)
4124
0
{
4125
0
  if (msg == NULL) {
4126
0
    return NSM_SW_ERROR_NULL;
4127
0
  }
4128
4129
0
  struct nsm_header_info header = {0};
4130
0
  header.nsm_msg_type = NSM_REQUEST;
4131
0
  header.instance_id = instance;
4132
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
4133
4134
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
4135
0
  if (rc != NSM_SW_SUCCESS) {
4136
0
    return rc;
4137
0
  }
4138
4139
0
  struct nsm_query_per_instance_gpm_metrics_req *request =
4140
0
      (struct nsm_query_per_instance_gpm_metrics_req *)msg->payload;
4141
4142
0
  request->hdr.command = NSM_QUERY_PER_INSTANCE_GPM_METRICS;
4143
0
  request->hdr.data_size =
4144
0
      sizeof(struct nsm_query_per_instance_gpm_metrics_req) -
4145
0
      sizeof(struct nsm_common_req);
4146
0
  request->retrieval_source = retrieval_source;
4147
0
  request->gpu_instance = gpu_instance;
4148
0
  request->compute_instance = compute_instance;
4149
0
  request->metric_id = metric_id;
4150
0
  request->instance_bitmask = htole32(instance_bitmask);
4151
4152
0
  return NSM_SW_SUCCESS;
4153
0
}
4154
4155
int decode_query_per_instance_gpm_metrics_req(
4156
    const struct nsm_msg *msg, size_t msg_len, uint8_t *retrieval_source,
4157
    uint8_t *gpu_instance, uint8_t *compute_instance, uint8_t *metric_id,
4158
    uint32_t *instance_bitmask)
4159
0
{
4160
0
  if (msg == NULL || retrieval_source == NULL || gpu_instance == NULL ||
4161
0
      compute_instance == NULL || metric_id == NULL ||
4162
0
      instance_bitmask == NULL) {
4163
0
    return NSM_SW_ERROR_NULL;
4164
0
  }
4165
4166
0
  if (msg_len <
4167
0
      sizeof(struct nsm_msg_hdr) +
4168
0
    sizeof(struct nsm_query_per_instance_gpm_metrics_req)) {
4169
0
    return NSM_SW_ERROR_LENGTH;
4170
0
  }
4171
4172
0
  struct nsm_query_per_instance_gpm_metrics_req *request =
4173
0
      (struct nsm_query_per_instance_gpm_metrics_req *)msg->payload;
4174
4175
0
  if (request->hdr.data_size <
4176
0
      (sizeof(struct nsm_query_per_instance_gpm_metrics_req) -
4177
0
       sizeof(struct nsm_common_req))) {
4178
0
    return NSM_SW_ERROR_DATA;
4179
0
  }
4180
4181
0
  *retrieval_source = request->retrieval_source;
4182
0
  *gpu_instance = request->gpu_instance;
4183
0
  *compute_instance = request->compute_instance;
4184
0
  *metric_id = request->metric_id;
4185
0
  *instance_bitmask = le32toh(request->instance_bitmask);
4186
4187
0
  return NSM_SW_SUCCESS;
4188
0
}
4189
4190
int encode_aggregate_gpm_metric_percentage_data(double percentage,
4191
            uint8_t *data, size_t *data_len)
4192
0
{
4193
0
  if (data == NULL || data_len == NULL) {
4194
0
    return NSM_SW_ERROR_NULL;
4195
0
  }
4196
4197
0
  if (percentage < 0) {
4198
0
    return NSM_SW_ERROR_DATA;
4199
0
  }
4200
4201
  // Data type of the percentage in NSM Response is NvS24.8 which is 32
4202
  // bit fixed point signed number with 8 fraction bits. And hence the
4203
  // floating point value value is multiplied by 256 (1 << 8 fraction
4204
  // bits) and converted into integer value.
4205
0
  uint32_t reading = percentage * (1 << 8);
4206
0
  reading = htole32(reading);
4207
4208
0
  memcpy(data, &reading, sizeof(uint32_t));
4209
0
  *data_len = sizeof(uint32_t);
4210
4211
0
  return NSM_SW_SUCCESS;
4212
0
}
4213
4214
int decode_aggregate_gpm_metric_percentage_data(const uint8_t *data,
4215
            size_t data_len,
4216
            double *percentage)
4217
0
{
4218
0
  if (data == NULL || percentage == NULL) {
4219
0
    return NSM_SW_ERROR_NULL;
4220
0
  }
4221
4222
0
  if (data_len != sizeof(uint32_t)) {
4223
0
    return NSM_SW_ERROR_LENGTH;
4224
0
  }
4225
4226
0
  uint32_t reading = 0;
4227
0
  memcpy(&reading, data, sizeof(uint32_t));
4228
4229
  // Data type of the percentage in NSM Response is NvS24.8 which is 32
4230
  // bit fixed point signed number with 8 fraction bits. And hence the
4231
  // value is divided by 256 (1 << 8 fraction bits) in its integer form to
4232
  // obtain a floating point value.
4233
0
  *percentage = (uint32_t)le32toh(reading) / (double)(1 << 8);
4234
4235
0
  return NSM_SW_SUCCESS;
4236
0
}
4237
4238
int encode_aggregate_gpm_metric_bandwidth_data(uint64_t bandwidth,
4239
                 uint8_t *data, size_t *data_len)
4240
0
{
4241
0
  if (data == NULL || data_len == NULL) {
4242
0
    return NSM_SW_ERROR_NULL;
4243
0
  }
4244
4245
0
  uint64_t le_reading = htole64(bandwidth);
4246
4247
0
  memcpy(data, &le_reading, sizeof(uint64_t));
4248
0
  *data_len = sizeof(uint64_t);
4249
4250
0
  return NSM_SW_SUCCESS;
4251
0
}
4252
4253
int decode_aggregate_gpm_metric_bandwidth_data(const uint8_t *data,
4254
                 size_t data_len,
4255
                 uint64_t *bandwidth)
4256
0
{
4257
0
  if (data == NULL || bandwidth == NULL) {
4258
0
    return NSM_SW_ERROR_NULL;
4259
0
  }
4260
4261
0
  if (data_len != sizeof(uint64_t)) {
4262
0
    return NSM_SW_ERROR_LENGTH;
4263
0
  }
4264
4265
0
  uint64_t le_reading;
4266
0
  memcpy(&le_reading, data, sizeof(uint64_t));
4267
4268
0
  *bandwidth = le64toh(le_reading);
4269
4270
0
  return NSM_SW_SUCCESS;
4271
0
}
4272
4273
int encode_get_violation_duration_req(uint8_t instance_id, struct nsm_msg *msg)
4274
0
{
4275
0
  if (msg == NULL) {
4276
0
    return NSM_SW_ERROR_NULL;
4277
0
  }
4278
4279
0
  struct nsm_header_info header = {0};
4280
0
  header.nsm_msg_type = NSM_REQUEST;
4281
0
  header.instance_id = instance_id;
4282
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
4283
4284
0
  uint8_t rc = pack_nsm_header(&header, &(msg->hdr));
4285
0
  if (rc != NSM_SW_SUCCESS) {
4286
0
    return rc;
4287
0
  }
4288
4289
0
  struct nsm_common_req *request = (struct nsm_common_req *)msg->payload;
4290
4291
0
  request->command = NSM_GET_VIOLATION_DURATION;
4292
0
  request->data_size = 0;
4293
4294
0
  return NSM_SW_SUCCESS;
4295
0
}
4296
4297
int decode_get_violation_duration_req(const struct nsm_msg *msg, size_t msg_len)
4298
0
{
4299
0
  return decode_common_req(msg, msg_len);
4300
0
}
4301
4302
int encode_get_violation_duration_resp(uint8_t instance_id, uint8_t cc,
4303
               uint16_t reason_code,
4304
               struct nsm_violation_duration *data,
4305
               struct nsm_msg *msg)
4306
0
{
4307
0
  if (msg == NULL || data == NULL) {
4308
0
    return NSM_SW_ERROR_NULL;
4309
0
  }
4310
4311
0
  struct nsm_header_info header = {0};
4312
0
  header.nsm_msg_type = NSM_RESPONSE;
4313
0
  header.instance_id = instance_id & 0x1f;
4314
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
4315
4316
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
4317
0
  if (rc != NSM_SW_SUCCESS) {
4318
0
    return rc;
4319
0
  }
4320
4321
0
  if (cc != NSM_SUCCESS) {
4322
0
    return encode_reason_code(cc, reason_code,
4323
0
            NSM_GET_VIOLATION_DURATION, msg);
4324
0
  }
4325
4326
0
  struct nsm_get_violation_duration_resp *resp =
4327
0
      (struct nsm_get_violation_duration_resp *)msg->payload;
4328
4329
0
  resp->hdr.command = NSM_GET_VIOLATION_DURATION;
4330
0
  resp->hdr.completion_code = cc;
4331
0
  resp->hdr.data_size = htole16(sizeof(struct nsm_violation_duration));
4332
4333
0
  resp->data.supported_counter.byte =
4334
0
      htole64(data->supported_counter.byte);
4335
0
  resp->data.hw_violation_duration = htole64(data->hw_violation_duration);
4336
0
  resp->data.global_sw_violation_duration =
4337
0
      htole64(data->global_sw_violation_duration);
4338
0
  resp->data.power_violation_duration =
4339
0
      htole64(data->power_violation_duration);
4340
0
  resp->data.thermal_violation_duration =
4341
0
      htole64(data->thermal_violation_duration);
4342
0
  resp->data.counter4 = htole64(data->counter4);
4343
0
  resp->data.counter5 = htole64(data->counter5);
4344
0
  resp->data.counter6 = htole64(data->counter6);
4345
0
  resp->data.counter7 = htole64(data->counter7);
4346
4347
0
  return NSM_SW_SUCCESS;
4348
0
}
4349
4350
int decode_get_violation_duration_resp(const struct nsm_msg *msg,
4351
               size_t msg_len, uint8_t *cc,
4352
               uint16_t *data_size,
4353
               uint16_t *reason_code,
4354
               struct nsm_violation_duration *data)
4355
0
{
4356
0
  if (data_size == NULL || data == NULL) {
4357
0
    return NSM_SW_ERROR_NULL;
4358
0
  }
4359
4360
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
4361
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
4362
0
    return rc;
4363
0
  }
4364
4365
0
  if (msg_len != sizeof(struct nsm_msg_hdr) +
4366
0
         sizeof(struct nsm_get_violation_duration_resp)) {
4367
0
    return NSM_SW_ERROR_LENGTH;
4368
0
  }
4369
4370
0
  struct nsm_get_violation_duration_resp *resp =
4371
0
      (struct nsm_get_violation_duration_resp *)msg->payload;
4372
4373
0
  *data_size = le16toh(resp->hdr.data_size);
4374
4375
0
  if (*data_size != sizeof(struct nsm_violation_duration)) {
4376
0
    return NSM_SW_ERROR_DATA;
4377
0
  }
4378
0
  data->supported_counter.byte =
4379
0
      le64toh(resp->data.supported_counter.byte);
4380
0
  data->hw_violation_duration = le64toh(resp->data.hw_violation_duration);
4381
0
  data->global_sw_violation_duration =
4382
0
      le64toh(resp->data.global_sw_violation_duration);
4383
0
  data->power_violation_duration =
4384
0
      le64toh(resp->data.power_violation_duration);
4385
0
  data->thermal_violation_duration =
4386
0
      le64toh(resp->data.thermal_violation_duration);
4387
0
  data->counter4 = le64toh(resp->data.counter4);
4388
0
  data->counter5 = le64toh(resp->data.counter5);
4389
0
  data->counter6 = le64toh(resp->data.counter6);
4390
0
  data->counter7 = le64toh(resp->data.counter7);
4391
4392
0
  return NSM_SW_SUCCESS;
4393
0
}
4394
4395
int encode_get_violation_duration_event_resp(
4396
    uint8_t instance_id, uint8_t cc, uint16_t reason_code,
4397
    struct nsm_violation_duration *data, struct nsm_msg *msg)
4398
0
{
4399
0
  if (data != NULL) {
4400
0
    data->supported_counter.byte =
4401
0
        htole64(data->supported_counter.byte);
4402
0
    data->hw_violation_duration =
4403
0
        htole64(data->hw_violation_duration);
4404
0
    data->global_sw_violation_duration =
4405
0
        htole64(data->global_sw_violation_duration);
4406
0
    data->power_violation_duration =
4407
0
        htole64(data->power_violation_duration);
4408
0
    data->thermal_violation_duration =
4409
0
        htole64(data->thermal_violation_duration);
4410
0
    data->counter4 = htole64(data->counter4);
4411
0
    data->counter5 = htole64(data->counter5);
4412
0
    data->counter6 = htole64(data->counter6);
4413
0
    data->counter7 = htole64(data->counter7);
4414
0
  }
4415
0
  return encode_long_running_resp(
4416
0
      instance_id, cc, reason_code, NSM_TYPE_PLATFORM_ENVIRONMENTAL,
4417
0
      NSM_GET_VIOLATION_DURATION, (const uint8_t *)data,
4418
0
      sizeof(struct nsm_violation_duration), msg);
4419
0
}
4420
4421
int decode_get_violation_duration_event_resp(
4422
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
4423
    uint16_t *reason_code, struct nsm_violation_duration *data)
4424
0
{
4425
0
  int rc = decode_long_running_resp_with_data(
4426
0
      msg, msg_len, NSM_TYPE_PLATFORM_ENVIRONMENTAL,
4427
0
      NSM_GET_VIOLATION_DURATION, cc, reason_code, (uint8_t *)data,
4428
0
      sizeof(struct nsm_violation_duration));
4429
0
  if (rc == NSM_SW_SUCCESS && data != NULL) {
4430
0
    data->supported_counter.byte =
4431
0
        le64toh(data->supported_counter.byte);
4432
0
    data->hw_violation_duration =
4433
0
        le64toh(data->hw_violation_duration);
4434
0
    data->global_sw_violation_duration =
4435
0
        le64toh(data->global_sw_violation_duration);
4436
0
    data->power_violation_duration =
4437
0
        le64toh(data->power_violation_duration);
4438
0
    data->thermal_violation_duration =
4439
0
        le64toh(data->thermal_violation_duration);
4440
0
    data->counter4 = le64toh(data->counter4);
4441
0
    data->counter5 = le64toh(data->counter5);
4442
0
    data->counter6 = le64toh(data->counter6);
4443
0
    data->counter7 = le64toh(data->counter7);
4444
0
  }
4445
0
  return rc;
4446
0
}
4447
4448
static void
4449
htolePowerSmoothingFeat(struct nsm_pwr_smoothing_featureinfo_data *data)
4450
0
{
4451
0
  data->feature_flag = htole32(data->feature_flag);
4452
0
  data->currentTmpSetting = htole32(data->currentTmpSetting);
4453
0
  data->currentTmpFloorSetting = htole32(data->currentTmpFloorSetting);
4454
0
  data->maxTmpFloorSettingInPercent =
4455
0
      htole16(data->maxTmpFloorSettingInPercent);
4456
0
  data->minTmpFloorSettingInPercent =
4457
0
      htole16(data->minTmpFloorSettingInPercent);
4458
0
}
4459
4460
static void
4461
letohPowerSmoothingFeat(struct nsm_pwr_smoothing_featureinfo_data *data)
4462
0
{
4463
0
  data->feature_flag = le32toh(data->feature_flag);
4464
0
  data->currentTmpSetting = le32toh(data->currentTmpSetting);
4465
0
  data->currentTmpFloorSetting = le32toh(data->currentTmpFloorSetting);
4466
0
  data->maxTmpFloorSettingInPercent =
4467
0
      le16toh(data->maxTmpFloorSettingInPercent);
4468
0
  data->minTmpFloorSettingInPercent =
4469
0
      le16toh(data->minTmpFloorSettingInPercent);
4470
0
}
4471
4472
int encode_get_powersmoothing_featinfo_req(uint8_t instance_id,
4473
             struct nsm_msg *msg)
4474
0
{
4475
0
  return encode_get_platform_env_command_no_payload_req(
4476
0
      instance_id, msg, NSM_PWR_SMOOTHING_GET_FEATURE_INFO);
4477
0
}
4478
4479
int decode_get_powersmoothing_featinfo_req(const struct nsm_msg *msg,
4480
             size_t msg_len)
4481
0
{
4482
0
  return decode_get_platform_env_command_no_payload_req(
4483
0
      msg, msg_len, NSM_PWR_SMOOTHING_GET_FEATURE_INFO);
4484
0
}
4485
4486
int encode_get_powersmoothing_featinfo_resp(
4487
    uint8_t instance_id, uint8_t cc, uint16_t reason_code,
4488
    struct nsm_pwr_smoothing_featureinfo_data *data, struct nsm_msg *msg)
4489
0
{
4490
0
  if (msg == NULL || data == NULL) {
4491
0
    return NSM_SW_ERROR_NULL;
4492
0
  }
4493
4494
0
  struct nsm_header_info header = {0};
4495
0
  header.nsm_msg_type = NSM_RESPONSE;
4496
0
  header.instance_id = instance_id & 0x1f;
4497
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
4498
4499
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
4500
0
  if (rc != NSM_SW_SUCCESS) {
4501
0
    return rc;
4502
0
  }
4503
4504
0
  if (cc != NSM_SUCCESS) {
4505
0
    return encode_reason_code(
4506
0
        cc, reason_code, NSM_PWR_SMOOTHING_GET_FEATURE_INFO, msg);
4507
0
  }
4508
4509
0
  struct nsm_get_power_smoothing_feat_resp *response =
4510
0
      (struct nsm_get_power_smoothing_feat_resp *)msg->payload;
4511
0
  response->hdr.command = NSM_PWR_SMOOTHING_GET_FEATURE_INFO;
4512
0
  response->hdr.completion_code = cc;
4513
0
  response->hdr.data_size =
4514
0
      htole16(sizeof(struct nsm_pwr_smoothing_featureinfo_data));
4515
4516
0
  htolePowerSmoothingFeat(data);
4517
0
  memcpy(&(response->data), data,
4518
0
         sizeof(struct nsm_pwr_smoothing_featureinfo_data));
4519
4520
0
  return NSM_SW_SUCCESS;
4521
0
}
4522
4523
int decode_get_powersmoothing_featinfo_resp(
4524
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
4525
    uint16_t *reason_code, uint16_t *data_size,
4526
    struct nsm_pwr_smoothing_featureinfo_data *data)
4527
0
{
4528
0
  if (msg == NULL || cc == NULL || data_size == NULL || data == NULL) {
4529
0
    return NSM_SW_ERROR_NULL;
4530
0
  }
4531
4532
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
4533
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
4534
0
    return rc;
4535
0
  }
4536
4537
0
  if (msg_len != (sizeof(struct nsm_msg_hdr)) +
4538
0
         sizeof(struct nsm_get_power_smoothing_feat_resp)) {
4539
0
    return NSM_SW_ERROR_LENGTH;
4540
0
  }
4541
4542
0
  struct nsm_get_power_smoothing_feat_resp *resp =
4543
0
      (struct nsm_get_power_smoothing_feat_resp *)msg->payload;
4544
0
  *data_size = le16toh(resp->hdr.data_size);
4545
4546
0
  if (resp->hdr.command != NSM_PWR_SMOOTHING_GET_FEATURE_INFO) {
4547
0
    return NSM_ERR_INVALID_DATA;
4548
0
  }
4549
4550
0
  size_t nsm_featureinfo_data_length =
4551
0
      sizeof(struct nsm_pwr_smoothing_featureinfo_data);
4552
0
  if (*data_size < nsm_featureinfo_data_length) {
4553
0
    return NSM_ERR_INVALID_DATA_LENGTH;
4554
0
  }
4555
4556
0
  memcpy(data, &(resp->data), nsm_featureinfo_data_length);
4557
0
  *cc = resp->hdr.completion_code;
4558
4559
0
  letohPowerSmoothingFeat(data);
4560
0
  return NSM_SUCCESS;
4561
0
}
4562
4563
int encode_get_hardware_lifetime_cricuitry_req(uint8_t instance_id,
4564
                 struct nsm_msg *msg)
4565
0
{
4566
0
  return encode_get_platform_env_command_no_payload_req(
4567
0
      instance_id, msg,
4568
0
      NSM_PWR_SMOOTHING_GET_HARDWARE_CIRCUITRY_LIFETIME_USAGE);
4569
0
}
4570
4571
int decode_get_hardware_lifetime_cricuitry_req(const struct nsm_msg *msg,
4572
                 size_t msg_len)
4573
0
{
4574
0
  return decode_get_platform_env_command_no_payload_req(
4575
0
      msg, msg_len,
4576
0
      NSM_PWR_SMOOTHING_GET_HARDWARE_CIRCUITRY_LIFETIME_USAGE);
4577
0
}
4578
4579
int encode_get_hardware_lifetime_cricuitry_resp(
4580
    uint8_t instance_id, uint8_t cc, uint16_t reason_code,
4581
    struct nsm_hardwarecircuitry_data *data, struct nsm_msg *msg)
4582
0
{
4583
0
  if (msg == NULL || data == NULL) {
4584
0
    return NSM_SW_ERROR_NULL;
4585
0
  }
4586
4587
0
  struct nsm_header_info header = {0};
4588
0
  header.nsm_msg_type = NSM_RESPONSE;
4589
0
  header.instance_id = instance_id & 0x1f;
4590
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
4591
4592
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
4593
0
  if (rc != NSM_SW_SUCCESS) {
4594
0
    return rc;
4595
0
  }
4596
4597
0
  if (cc != NSM_SUCCESS) {
4598
0
    return encode_reason_code(
4599
0
        cc, reason_code,
4600
0
        NSM_PWR_SMOOTHING_GET_HARDWARE_CIRCUITRY_LIFETIME_USAGE,
4601
0
        msg);
4602
0
  }
4603
4604
0
  struct nsm_hardwareciruitry_resp *response =
4605
0
      (struct nsm_hardwareciruitry_resp *)msg->payload;
4606
0
  response->hdr.command =
4607
0
      NSM_PWR_SMOOTHING_GET_HARDWARE_CIRCUITRY_LIFETIME_USAGE;
4608
0
  response->hdr.completion_code = cc;
4609
0
  uint16_t data_size = htole16(sizeof(struct nsm_hardwarecircuitry_data));
4610
0
  response->hdr.data_size = htole16(data_size);
4611
0
  memcpy(&(response->data), data,
4612
0
         sizeof(struct nsm_hardwarecircuitry_data));
4613
0
  response->data.reading = htole32(response->data.reading);
4614
0
  return NSM_SW_SUCCESS;
4615
0
}
4616
4617
int decode_get_hardware_lifetime_cricuitry_resp(
4618
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
4619
    uint16_t *reason_code, uint16_t *data_size,
4620
    struct nsm_hardwarecircuitry_data *data)
4621
0
{
4622
0
  if (msg == NULL || cc == NULL || data_size == NULL || data == NULL) {
4623
0
    return NSM_SW_ERROR_NULL;
4624
0
  }
4625
4626
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
4627
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
4628
0
    return rc;
4629
0
  }
4630
4631
0
  if (msg_len != sizeof(struct nsm_msg_hdr) +
4632
0
         sizeof(struct nsm_hardwareciruitry_resp)) {
4633
0
    return NSM_SW_ERROR_LENGTH;
4634
0
  }
4635
4636
0
  struct nsm_hardwareciruitry_resp *resp =
4637
0
      (struct nsm_hardwareciruitry_resp *)msg->payload;
4638
0
  *data_size = le16toh(resp->hdr.data_size);
4639
4640
0
  if (resp->hdr.command !=
4641
0
      NSM_PWR_SMOOTHING_GET_HARDWARE_CIRCUITRY_LIFETIME_USAGE) {
4642
0
    return NSM_ERR_INVALID_DATA;
4643
0
  }
4644
4645
0
  size_t nsm_hardwarecircuitry_data_length =
4646
0
      sizeof(struct nsm_hardwarecircuitry_data);
4647
0
  if (*data_size < nsm_hardwarecircuitry_data_length) {
4648
0
    return NSM_ERR_INVALID_DATA_LENGTH;
4649
0
  }
4650
4651
0
  memcpy(data, &(resp->data), nsm_hardwarecircuitry_data_length);
4652
0
  data->reading = le32toh(data->reading);
4653
0
  *cc = resp->hdr.completion_code;
4654
4655
0
  return NSM_SUCCESS;
4656
0
}
4657
4658
int encode_get_current_profile_info_req(uint8_t instance_id,
4659
          struct nsm_msg *msg)
4660
0
{
4661
0
  return encode_get_platform_env_command_no_payload_req(
4662
0
      instance_id, msg,
4663
0
      NSM_PWR_SMOOTHING_GET_CURRENT_PROFILE_INFORMATION);
4664
0
}
4665
4666
int decode_get_current_profile_info_req(const struct nsm_msg *msg,
4667
          size_t msg_len)
4668
0
{
4669
0
  return decode_get_platform_env_command_no_payload_req(
4670
0
      msg, msg_len, NSM_PWR_SMOOTHING_GET_CURRENT_PROFILE_INFORMATION);
4671
0
}
4672
4673
static void
4674
htole32CurrentProfileInfoResp(struct nsm_get_current_profile_data *profileInfo)
4675
0
{
4676
0
  profileInfo->current_percent_tmp_floor =
4677
0
      htole16(profileInfo->current_percent_tmp_floor);
4678
0
  profileInfo->current_rampup_rate_in_miliwatts_per_second =
4679
0
      htole32(profileInfo->current_rampup_rate_in_miliwatts_per_second);
4680
0
  profileInfo->current_rampdown_rate_in_miliwatts_per_second =
4681
0
      htole32(profileInfo->current_rampdown_rate_in_miliwatts_per_second);
4682
0
  profileInfo->current_rampdown_hysteresis_value_in_milisec =
4683
0
      htole32(profileInfo->current_rampdown_hysteresis_value_in_milisec);
4684
0
}
4685
4686
static void
4687
le32tohCurrentProfileInfoResp(struct nsm_get_current_profile_data *profileInfo)
4688
0
{
4689
0
  profileInfo->current_percent_tmp_floor =
4690
0
      le16toh(profileInfo->current_percent_tmp_floor);
4691
0
  profileInfo->current_rampup_rate_in_miliwatts_per_second =
4692
0
      le32toh(profileInfo->current_rampup_rate_in_miliwatts_per_second);
4693
0
  profileInfo->current_rampdown_rate_in_miliwatts_per_second =
4694
0
      le32toh(profileInfo->current_rampdown_rate_in_miliwatts_per_second);
4695
0
  profileInfo->current_rampdown_hysteresis_value_in_milisec =
4696
0
      le32toh(profileInfo->current_rampdown_hysteresis_value_in_milisec);
4697
0
}
4698
4699
int encode_get_current_profile_info_resp(
4700
    uint8_t instance_id, uint8_t cc, uint16_t reason_code,
4701
    struct nsm_get_current_profile_data *data, struct nsm_msg *msg)
4702
0
{
4703
0
  if (msg == NULL || data == NULL) {
4704
0
    return NSM_SW_ERROR_NULL;
4705
0
  }
4706
4707
0
  struct nsm_header_info header = {0};
4708
0
  header.nsm_msg_type = NSM_RESPONSE;
4709
0
  header.instance_id = instance_id & 0x1f;
4710
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
4711
4712
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
4713
0
  if (rc != NSM_SW_SUCCESS) {
4714
0
    return rc;
4715
0
  }
4716
4717
0
  if (cc != NSM_SUCCESS) {
4718
0
    return encode_reason_code(
4719
0
        cc, reason_code,
4720
0
        NSM_PWR_SMOOTHING_GET_CURRENT_PROFILE_INFORMATION, msg);
4721
0
  }
4722
4723
0
  struct nsm_get_current_profile_info_resp *response =
4724
0
      (struct nsm_get_current_profile_info_resp *)msg->payload;
4725
4726
0
  response->hdr.command =
4727
0
      NSM_PWR_SMOOTHING_GET_CURRENT_PROFILE_INFORMATION;
4728
0
  response->hdr.completion_code = cc;
4729
0
  response->hdr.data_size =
4730
0
      htole16(sizeof(struct nsm_pwr_smoothing_featureinfo_data));
4731
4732
0
  htole32CurrentProfileInfoResp(data);
4733
4734
0
  memcpy(&(response->data), data,
4735
0
         sizeof(struct nsm_get_current_profile_data));
4736
4737
0
  return NSM_SW_SUCCESS;
4738
0
}
4739
4740
int decode_get_current_profile_info_resp(
4741
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
4742
    uint16_t *reason_code, uint16_t *data_size,
4743
    struct nsm_get_current_profile_data *data)
4744
0
{
4745
0
  if (data == NULL || data_size == NULL) {
4746
0
    return NSM_SW_ERROR_NULL;
4747
0
  }
4748
4749
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
4750
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
4751
0
    return rc;
4752
0
  }
4753
4754
0
  if (msg_len != (sizeof(struct nsm_msg_hdr) +
4755
0
      sizeof(struct nsm_get_current_profile_info_resp))) {
4756
0
    return NSM_SW_ERROR_LENGTH;
4757
0
  }
4758
0
  struct nsm_get_current_profile_info_resp *resp_payload =
4759
0
      (struct nsm_get_current_profile_info_resp *)msg->payload;
4760
4761
0
  *data_size = le16toh(resp_payload->hdr.data_size);
4762
0
  size_t response_data_len = sizeof(struct nsm_get_current_profile_data);
4763
0
  memcpy(data, &(resp_payload->data), response_data_len);
4764
4765
  // conversion le32toh for each counter data
4766
0
  le32tohCurrentProfileInfoResp(data);
4767
4768
0
  return NSM_SW_SUCCESS;
4769
0
}
4770
4771
int encode_query_admin_override_req(uint8_t instance_id, struct nsm_msg *msg)
4772
0
{
4773
0
  return encode_get_platform_env_command_no_payload_req(
4774
0
      instance_id, msg, NSM_PWR_SMOOTHING_QUERY_ADMIN_OVERRIDE);
4775
0
}
4776
4777
int decode_query_admin_override_req(const struct nsm_msg *msg, size_t msg_len)
4778
0
{
4779
0
  return decode_get_platform_env_command_no_payload_req(
4780
0
      msg, msg_len, NSM_PWR_SMOOTHING_QUERY_ADMIN_OVERRIDE);
4781
0
}
4782
4783
static void htoleAdminOverrideData(struct nsm_admin_override_data *adminData)
4784
0
{
4785
0
  adminData->admin_override_percent_tmp_floor =
4786
0
      htole16(adminData->admin_override_percent_tmp_floor);
4787
0
  adminData->admin_override_ramup_rate_in_miliwatts_per_second = htole32(
4788
0
      adminData->admin_override_ramup_rate_in_miliwatts_per_second);
4789
0
  adminData->admin_override_rampdown_rate_in_miliwatts_per_second =
4790
0
      htole32(adminData
4791
0
      ->admin_override_rampdown_rate_in_miliwatts_per_second);
4792
0
  adminData->admin_override_rampdown_hysteresis_value_in_milisec =
4793
0
      htole32(
4794
0
    adminData->admin_override_rampdown_hysteresis_value_in_milisec);
4795
0
}
4796
4797
static void letohAdminOverrideData(struct nsm_admin_override_data *adminData)
4798
0
{
4799
0
  adminData->admin_override_percent_tmp_floor =
4800
0
      le16toh(adminData->admin_override_percent_tmp_floor);
4801
0
  adminData->admin_override_ramup_rate_in_miliwatts_per_second = le32toh(
4802
0
      adminData->admin_override_ramup_rate_in_miliwatts_per_second);
4803
0
  adminData->admin_override_rampdown_rate_in_miliwatts_per_second =
4804
0
      le32toh(adminData
4805
0
      ->admin_override_rampdown_rate_in_miliwatts_per_second);
4806
0
  adminData->admin_override_rampdown_hysteresis_value_in_milisec =
4807
0
      le32toh(
4808
0
    adminData->admin_override_rampdown_hysteresis_value_in_milisec);
4809
0
}
4810
4811
int encode_query_admin_override_resp(uint8_t instance_id, uint8_t cc,
4812
             uint16_t reason_code,
4813
             struct nsm_admin_override_data *data,
4814
             struct nsm_msg *msg)
4815
0
{
4816
0
  if (msg == NULL || data == NULL) {
4817
0
    return NSM_SW_ERROR_NULL;
4818
0
  }
4819
4820
0
  struct nsm_header_info header = {0};
4821
0
  header.nsm_msg_type = NSM_RESPONSE;
4822
0
  header.instance_id = instance_id & 0x1f;
4823
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
4824
4825
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
4826
0
  if (rc != NSM_SW_SUCCESS) {
4827
0
    return rc;
4828
0
  }
4829
4830
0
  if (cc != NSM_SUCCESS) {
4831
0
    return encode_reason_code(
4832
0
        cc, reason_code, NSM_PWR_SMOOTHING_QUERY_ADMIN_OVERRIDE,
4833
0
        msg);
4834
0
  }
4835
4836
0
  struct nsm_query_admin_override_resp *response =
4837
0
      (struct nsm_query_admin_override_resp *)msg->payload;
4838
4839
0
  response->hdr.command = NSM_PWR_SMOOTHING_QUERY_ADMIN_OVERRIDE;
4840
0
  response->hdr.completion_code = cc;
4841
0
  response->hdr.data_size =
4842
0
      htole16(sizeof(struct nsm_admin_override_data));
4843
4844
  // conversion htole32 for each admin override data
4845
0
  htoleAdminOverrideData(data);
4846
4847
0
  memcpy(&(response->data), data, sizeof(struct nsm_admin_override_data));
4848
4849
0
  return NSM_SW_SUCCESS;
4850
0
}
4851
4852
int decode_query_admin_override_resp(const struct nsm_msg *msg, size_t msg_len,
4853
             uint8_t *cc, uint16_t *reason_code,
4854
             uint16_t *data_size,
4855
             struct nsm_admin_override_data *data)
4856
0
{
4857
0
  if (data_size == NULL || data == NULL) {
4858
0
    return NSM_SW_ERROR_NULL;
4859
0
  }
4860
4861
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
4862
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
4863
0
    return rc;
4864
0
  }
4865
4866
0
  if (msg_len != (sizeof(struct nsm_msg_hdr) +
4867
0
      sizeof(struct nsm_query_admin_override_resp))) {
4868
0
    return NSM_SW_ERROR_LENGTH;
4869
0
  }
4870
4871
0
  struct nsm_query_admin_override_resp *resp =
4872
0
      (struct nsm_query_admin_override_resp *)msg->payload;
4873
0
  size_t admin_data_len = sizeof(struct nsm_admin_override_data);
4874
4875
0
  *data_size = le16toh(resp->hdr.data_size);
4876
0
  if (*data_size < admin_data_len) {
4877
0
    return NSM_SW_ERROR_DATA;
4878
0
  }
4879
4880
0
  memcpy(data, &(resp->data), admin_data_len);
4881
4882
  // conversion le32toh for each admin override data
4883
0
  letohAdminOverrideData(data);
4884
4885
0
  return NSM_SW_SUCCESS;
4886
0
}
4887
4888
int encode_set_active_preset_profile_req(uint8_t instance_id,
4889
           uint8_t profile_id,
4890
           struct nsm_msg *msg)
4891
0
{
4892
0
  if (msg == NULL) {
4893
0
    return NSM_SW_ERROR_NULL;
4894
0
  }
4895
4896
0
  struct nsm_header_info header = {0};
4897
0
  header.nsm_msg_type = NSM_REQUEST;
4898
0
  header.instance_id = instance_id;
4899
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
4900
4901
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
4902
0
  if (rc != NSM_SW_SUCCESS) {
4903
0
    return rc;
4904
0
  }
4905
4906
0
  struct nsm_set_active_preset_profile_req *request =
4907
0
      (struct nsm_set_active_preset_profile_req *)msg->payload;
4908
4909
0
  request->hdr.command = NSM_PWR_SMOOTHING_SET_ACTIVE_PRESET_PROFILE;
4910
0
  request->hdr.data_size = sizeof(profile_id);
4911
0
  request->profile_id = profile_id;
4912
0
  return NSM_SW_SUCCESS;
4913
0
}
4914
4915
int decode_set_active_preset_profile_req(const struct nsm_msg *msg,
4916
           size_t msg_len, uint8_t *profile_id)
4917
0
{
4918
0
  if (msg == NULL || profile_id == NULL) {
4919
0
    return NSM_SW_ERROR_NULL;
4920
0
  }
4921
4922
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
4923
0
        sizeof(struct nsm_set_active_preset_profile_req)) {
4924
0
    return NSM_SW_ERROR_LENGTH;
4925
0
  }
4926
4927
0
  struct nsm_set_active_preset_profile_req *request =
4928
0
      (struct nsm_set_active_preset_profile_req *)msg->payload;
4929
4930
0
  if (request->hdr.data_size < sizeof(request->profile_id)) {
4931
0
    return NSM_SW_ERROR_DATA;
4932
0
  }
4933
4934
0
  *profile_id = request->profile_id;
4935
4936
0
  return NSM_SW_SUCCESS;
4937
0
}
4938
4939
int encode_set_active_preset_profile_resp(uint8_t instance_id, uint8_t cc,
4940
            uint16_t reason_code,
4941
            struct nsm_msg *msg)
4942
0
{
4943
0
  if (msg == NULL) {
4944
0
    return NSM_SW_ERROR_NULL;
4945
0
  }
4946
4947
0
  struct nsm_header_info header = {0};
4948
0
  header.nsm_msg_type = NSM_RESPONSE;
4949
0
  header.instance_id = instance_id & 0x1f;
4950
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
4951
4952
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
4953
0
  if (rc != NSM_SW_SUCCESS) {
4954
0
    return rc;
4955
0
  }
4956
4957
0
  if (cc != NSM_SUCCESS) {
4958
0
    return encode_reason_code(
4959
0
        cc, reason_code,
4960
0
        NSM_PWR_SMOOTHING_SET_ACTIVE_PRESET_PROFILE, msg);
4961
0
  }
4962
0
  struct nsm_common_resp *response =
4963
0
      (struct nsm_common_resp *)msg->payload;
4964
4965
0
  response->command = NSM_PWR_SMOOTHING_SET_ACTIVE_PRESET_PROFILE;
4966
0
  response->completion_code = cc;
4967
0
  response->data_size = 0;
4968
4969
0
  return NSM_SW_SUCCESS;
4970
0
}
4971
4972
int decode_set_active_preset_profile_resp(const struct nsm_msg *msg,
4973
            size_t msg_len, uint8_t *cc,
4974
            uint16_t *reason_code)
4975
0
{
4976
0
  if (msg == NULL || cc == NULL) {
4977
0
    return NSM_ERR_INVALID_DATA;
4978
0
  }
4979
4980
0
  if (msg_len <
4981
0
      sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_common_resp)) {
4982
0
    return NSM_SW_ERROR_LENGTH;
4983
0
  }
4984
4985
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
4986
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
4987
0
    return rc;
4988
0
  }
4989
4990
0
  struct nsm_common_resp *resp = (struct nsm_common_resp *)msg->payload;
4991
4992
0
  uint16_t data_size = le16toh(resp->data_size);
4993
0
  if (data_size != 0) {
4994
0
    return NSM_SW_ERROR_DATA;
4995
0
  }
4996
4997
0
  return NSM_SUCCESS;
4998
0
}
4999
5000
int encode_setup_admin_override_req(uint8_t instance_id, uint8_t parameter_id,
5001
            uint32_t param_value, struct nsm_msg *msg)
5002
0
{
5003
0
  if (msg == NULL) {
5004
0
    return NSM_SW_ERROR_NULL;
5005
0
  }
5006
5007
0
  struct nsm_header_info header = {0};
5008
0
  header.nsm_msg_type = NSM_REQUEST;
5009
0
  header.instance_id = instance_id;
5010
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
5011
5012
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
5013
0
  if (rc != NSM_SW_SUCCESS) {
5014
0
    return rc;
5015
0
  }
5016
5017
0
  struct nsm_setup_admin_override_req *request =
5018
0
      (struct nsm_setup_admin_override_req *)msg->payload;
5019
5020
0
  request->hdr.command = NSM_PWR_SMOOTHING_SETUP_ADMIN_OVERRIDE;
5021
0
  request->hdr.data_size = sizeof(struct nsm_setup_admin_override_req) -
5022
0
         sizeof(struct nsm_common_req);
5023
0
  request->parameter_id = parameter_id;
5024
0
  request->param_value = htole32(param_value);
5025
0
  return NSM_SW_SUCCESS;
5026
0
}
5027
5028
int decode_setup_admin_override_req(const struct nsm_msg *msg, size_t msg_len,
5029
            uint8_t *parameter_id,
5030
            uint32_t *param_value)
5031
0
{
5032
0
  if (msg == NULL || parameter_id == NULL || param_value == NULL) {
5033
0
    return NSM_SW_ERROR_NULL;
5034
0
  }
5035
5036
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
5037
0
        sizeof(struct nsm_setup_admin_override_req)) {
5038
0
    return NSM_SW_ERROR_LENGTH;
5039
0
  }
5040
5041
0
  struct nsm_setup_admin_override_req *request =
5042
0
      (struct nsm_setup_admin_override_req *)msg->payload;
5043
5044
0
  if (request->hdr.data_size <
5045
0
      sizeof(request->parameter_id) + sizeof(request->param_value)) {
5046
0
    return NSM_SW_ERROR_DATA;
5047
0
  }
5048
5049
0
  *parameter_id = request->parameter_id;
5050
0
  *param_value = le32toh(request->param_value);
5051
5052
0
  return NSM_SW_SUCCESS;
5053
0
}
5054
5055
int encode_setup_admin_override_resp(uint8_t instance_id, uint8_t cc,
5056
             uint16_t reason_code, struct nsm_msg *msg)
5057
0
{
5058
0
  if (msg == NULL) {
5059
0
    return NSM_SW_ERROR_NULL;
5060
0
  }
5061
5062
0
  struct nsm_header_info header = {0};
5063
0
  header.nsm_msg_type = NSM_RESPONSE;
5064
0
  header.instance_id = instance_id & 0x1f;
5065
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
5066
5067
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
5068
0
  if (rc != NSM_SW_SUCCESS) {
5069
0
    return rc;
5070
0
  }
5071
5072
0
  if (cc != NSM_SUCCESS) {
5073
0
    return encode_reason_code(
5074
0
        cc, reason_code, NSM_PWR_SMOOTHING_SETUP_ADMIN_OVERRIDE,
5075
0
        msg);
5076
0
  }
5077
0
  struct nsm_common_resp *response =
5078
0
      (struct nsm_common_resp *)msg->payload;
5079
5080
0
  response->command = NSM_PWR_SMOOTHING_SETUP_ADMIN_OVERRIDE;
5081
0
  response->completion_code = cc;
5082
0
  response->data_size = 0;
5083
5084
0
  return NSM_SW_SUCCESS;
5085
0
}
5086
5087
int decode_setup_admin_override_resp(const struct nsm_msg *msg, size_t msg_len,
5088
             uint8_t *cc, uint16_t *reason_code)
5089
0
{
5090
0
  if (msg == NULL || cc == NULL) {
5091
0
    return NSM_ERR_INVALID_DATA;
5092
0
  }
5093
5094
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
5095
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
5096
0
    return rc;
5097
0
  }
5098
5099
0
  if (msg_len <
5100
0
      sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_common_resp)) {
5101
0
    return NSM_SW_ERROR_LENGTH;
5102
0
  }
5103
5104
0
  struct nsm_common_resp *resp = (struct nsm_common_resp *)msg->payload;
5105
5106
0
  uint16_t data_size = le16toh(resp->data_size);
5107
0
  if (data_size != 0) {
5108
0
    return NSM_SW_ERROR_DATA;
5109
0
  }
5110
5111
0
  return NSM_SUCCESS;
5112
0
}
5113
5114
int encode_apply_admin_override_req(uint8_t instance_id, struct nsm_msg *msg)
5115
0
{
5116
0
  return encode_get_platform_env_command_no_payload_req(
5117
0
      instance_id, msg, NSM_PWR_SMOOTHING_APPLY_ADMIN_OVERRIDE);
5118
0
}
5119
5120
int decode_apply_admin_override_req(const struct nsm_msg *msg, size_t msg_len)
5121
0
{
5122
0
  return decode_get_platform_env_command_no_payload_req(
5123
0
      msg, msg_len, NSM_PWR_SMOOTHING_APPLY_ADMIN_OVERRIDE);
5124
0
}
5125
5126
int encode_apply_admin_override_resp(uint8_t instance_id, uint8_t cc,
5127
             uint16_t reason_code, struct nsm_msg *msg)
5128
0
{
5129
0
  if (msg == NULL) {
5130
0
    return NSM_SW_ERROR_NULL;
5131
0
  }
5132
5133
0
  struct nsm_header_info header = {0};
5134
0
  header.nsm_msg_type = NSM_RESPONSE;
5135
0
  header.instance_id = instance_id & 0x1f;
5136
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
5137
5138
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
5139
0
  if (rc != NSM_SW_SUCCESS) {
5140
0
    return rc;
5141
0
  }
5142
5143
0
  if (cc != NSM_SUCCESS) {
5144
0
    return encode_reason_code(
5145
0
        cc, reason_code, NSM_PWR_SMOOTHING_APPLY_ADMIN_OVERRIDE,
5146
0
        msg);
5147
0
  }
5148
0
  struct nsm_common_resp *response =
5149
0
      (struct nsm_common_resp *)msg->payload;
5150
5151
0
  response->command = NSM_PWR_SMOOTHING_APPLY_ADMIN_OVERRIDE;
5152
0
  response->completion_code = cc;
5153
0
  response->data_size = 0;
5154
5155
0
  return NSM_SW_SUCCESS;
5156
0
}
5157
5158
int decode_apply_admin_override_resp(const struct nsm_msg *msg, size_t msg_len,
5159
             uint8_t *cc, uint16_t *reason_code)
5160
0
{
5161
0
  if (msg == NULL || cc == NULL) {
5162
0
    return NSM_ERR_INVALID_DATA;
5163
0
  }
5164
5165
0
  if (msg_len <
5166
0
      sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_common_resp)) {
5167
0
    return NSM_SW_ERROR_LENGTH;
5168
0
  }
5169
5170
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
5171
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
5172
0
    return rc;
5173
0
  }
5174
5175
0
  struct nsm_common_resp *resp = (struct nsm_common_resp *)msg->payload;
5176
5177
0
  uint16_t data_size = le16toh(resp->data_size);
5178
0
  if (data_size != 0) {
5179
0
    return NSM_SW_ERROR_DATA;
5180
0
  }
5181
5182
0
  return NSM_SUCCESS;
5183
0
}
5184
5185
int encode_toggle_immediate_rampdown_req(uint8_t instance_id,
5186
           uint8_t ramp_down_toggle,
5187
           struct nsm_msg *msg)
5188
0
{
5189
0
  if (msg == NULL) {
5190
0
    return NSM_SW_ERROR_NULL;
5191
0
  }
5192
5193
0
  struct nsm_header_info header = {0};
5194
0
  header.nsm_msg_type = NSM_REQUEST;
5195
0
  header.instance_id = instance_id;
5196
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
5197
5198
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
5199
0
  if (rc != NSM_SW_SUCCESS) {
5200
0
    return rc;
5201
0
  }
5202
5203
0
  struct nsm_toggle_immediate_rampdown_req *request =
5204
0
      (struct nsm_toggle_immediate_rampdown_req *)msg->payload;
5205
5206
0
  request->hdr.command = NSM_PWR_SMOOTHING_TOGGLE_IMMEDIATE_RAMP_DOWN;
5207
0
  request->hdr.data_size = sizeof(ramp_down_toggle);
5208
0
  request->ramp_down_toggle = ramp_down_toggle;
5209
0
  return NSM_SW_SUCCESS;
5210
0
}
5211
5212
int decode_toggle_immediate_rampdown_req(const struct nsm_msg *msg,
5213
           size_t msg_len,
5214
           uint8_t *ramp_down_toggle)
5215
0
{
5216
0
  if (msg == NULL || ramp_down_toggle == NULL) {
5217
0
    return NSM_SW_ERROR_NULL;
5218
0
  }
5219
5220
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
5221
0
        sizeof(struct nsm_toggle_immediate_rampdown_req)) {
5222
0
    return NSM_SW_ERROR_LENGTH;
5223
0
  }
5224
5225
0
  struct nsm_toggle_immediate_rampdown_req *request =
5226
0
      (struct nsm_toggle_immediate_rampdown_req *)msg->payload;
5227
5228
0
  if (request->hdr.data_size < sizeof(request->ramp_down_toggle)) {
5229
0
    return NSM_SW_ERROR_DATA;
5230
0
  }
5231
5232
0
  *ramp_down_toggle = request->ramp_down_toggle;
5233
5234
0
  return NSM_SW_SUCCESS;
5235
0
}
5236
5237
int encode_toggle_immediate_rampdown_resp(uint8_t instance_id, uint8_t cc,
5238
            uint16_t reason_code,
5239
            struct nsm_msg *msg)
5240
0
{
5241
0
  if (msg == NULL) {
5242
0
    return NSM_SW_ERROR_NULL;
5243
0
  }
5244
5245
0
  struct nsm_header_info header = {0};
5246
0
  header.nsm_msg_type = NSM_RESPONSE;
5247
0
  header.instance_id = instance_id & 0x1f;
5248
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
5249
5250
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
5251
0
  if (rc != NSM_SW_SUCCESS) {
5252
0
    return rc;
5253
0
  }
5254
5255
0
  if (cc != NSM_SUCCESS) {
5256
0
    return encode_reason_code(
5257
0
        cc, reason_code,
5258
0
        NSM_PWR_SMOOTHING_TOGGLE_IMMEDIATE_RAMP_DOWN, msg);
5259
0
  }
5260
0
  struct nsm_common_resp *response =
5261
0
      (struct nsm_common_resp *)msg->payload;
5262
5263
0
  response->command = NSM_PWR_SMOOTHING_TOGGLE_IMMEDIATE_RAMP_DOWN;
5264
0
  response->completion_code = cc;
5265
0
  response->data_size = 0;
5266
5267
0
  return NSM_SW_SUCCESS;
5268
0
}
5269
5270
int decode_toggle_immediate_rampdown_resp(const struct nsm_msg *msg,
5271
            size_t msg_len, uint8_t *cc,
5272
            uint16_t *reason_code)
5273
0
{
5274
0
  if (msg == NULL || cc == NULL) {
5275
0
    return NSM_ERR_INVALID_DATA;
5276
0
  }
5277
5278
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
5279
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
5280
0
    return rc;
5281
0
  }
5282
5283
0
  if (msg_len <
5284
0
      sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_common_resp)) {
5285
0
    return NSM_SW_ERROR_LENGTH;
5286
0
  }
5287
5288
0
  struct nsm_common_resp *resp = (struct nsm_common_resp *)msg->payload;
5289
5290
0
  uint16_t data_size = le16toh(resp->data_size);
5291
0
  if (data_size != 0) {
5292
0
    return NSM_SW_ERROR_DATA;
5293
0
  }
5294
0
  return NSM_SUCCESS;
5295
0
}
5296
5297
int encode_toggle_feature_state_req(uint8_t instance_id, uint8_t feature_state,
5298
            struct nsm_msg *msg)
5299
0
{
5300
0
  if (msg == NULL) {
5301
0
    return NSM_SW_ERROR_NULL;
5302
0
  }
5303
5304
0
  struct nsm_header_info header = {0};
5305
0
  header.nsm_msg_type = NSM_REQUEST;
5306
0
  header.instance_id = instance_id;
5307
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
5308
5309
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
5310
0
  if (rc != NSM_SW_SUCCESS) {
5311
0
    return rc;
5312
0
  }
5313
5314
0
  struct nsm_toggle_feature_state_req *request =
5315
0
      (struct nsm_toggle_feature_state_req *)msg->payload;
5316
5317
0
  request->hdr.command = NSM_PWR_SMOOTHING_TOGGLE_FEATURESTATE;
5318
0
  request->hdr.data_size = sizeof(feature_state);
5319
0
  request->feature_state = feature_state;
5320
0
  return NSM_SW_SUCCESS;
5321
0
}
5322
5323
int decode_toggle_feature_state_req(const struct nsm_msg *msg, size_t msg_len,
5324
            uint8_t *feature_state)
5325
0
{
5326
0
  if (msg == NULL || feature_state == NULL) {
5327
0
    return NSM_SW_ERROR_NULL;
5328
0
  }
5329
5330
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
5331
0
        sizeof(struct nsm_toggle_feature_state_req)) {
5332
0
    return NSM_SW_ERROR_LENGTH;
5333
0
  }
5334
5335
0
  struct nsm_toggle_feature_state_req *request =
5336
0
      (struct nsm_toggle_feature_state_req *)msg->payload;
5337
5338
0
  if (request->hdr.data_size < sizeof(request->feature_state)) {
5339
0
    return NSM_SW_ERROR_DATA;
5340
0
  }
5341
5342
0
  *feature_state = request->feature_state;
5343
5344
0
  return NSM_SW_SUCCESS;
5345
0
}
5346
5347
int encode_toggle_feature_state_resp(uint8_t instance_id, uint8_t cc,
5348
             uint16_t reason_code, struct nsm_msg *msg)
5349
0
{
5350
0
  if (msg == NULL) {
5351
0
    return NSM_SW_ERROR_NULL;
5352
0
  }
5353
5354
0
  struct nsm_header_info header = {0};
5355
0
  header.nsm_msg_type = NSM_RESPONSE;
5356
0
  header.instance_id = instance_id & 0x1f;
5357
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
5358
5359
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
5360
0
  if (rc != NSM_SW_SUCCESS) {
5361
0
    return rc;
5362
0
  }
5363
5364
0
  if (cc != NSM_SUCCESS) {
5365
0
    return encode_reason_code(cc, reason_code,
5366
0
            NSM_PWR_SMOOTHING_TOGGLE_FEATURESTATE,
5367
0
            msg);
5368
0
  }
5369
0
  struct nsm_common_resp *response =
5370
0
      (struct nsm_common_resp *)msg->payload;
5371
5372
0
  response->command = NSM_PWR_SMOOTHING_TOGGLE_FEATURESTATE;
5373
0
  response->completion_code = cc;
5374
0
  response->data_size = 0;
5375
5376
0
  return NSM_SW_SUCCESS;
5377
0
}
5378
5379
int decode_toggle_feature_state_resp(const struct nsm_msg *msg, size_t msg_len,
5380
             uint8_t *cc, uint16_t *reason_code)
5381
0
{
5382
0
  if (msg == NULL || cc == NULL) {
5383
0
    return NSM_ERR_INVALID_DATA;
5384
0
  }
5385
5386
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
5387
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
5388
0
    return rc;
5389
0
  }
5390
5391
0
  if (msg_len <
5392
0
      sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_common_resp)) {
5393
0
    return NSM_SW_ERROR_LENGTH;
5394
0
  }
5395
5396
0
  struct nsm_common_resp *resp = (struct nsm_common_resp *)msg->payload;
5397
5398
0
  uint16_t data_size = le16toh(resp->data_size);
5399
0
  if (data_size != 0) {
5400
0
    return NSM_SW_ERROR_DATA;
5401
0
  }
5402
5403
0
  return NSM_SUCCESS;
5404
0
}
5405
5406
static void letohgetPresetProfiledata(struct nsm_preset_profile_data *data)
5407
0
{
5408
0
  data->tmp_floor_setting_in_percent =
5409
0
      le16toh(data->tmp_floor_setting_in_percent);
5410
0
  data->ramp_up_rate_in_miliwattspersec =
5411
0
      le32toh(data->ramp_up_rate_in_miliwattspersec);
5412
0
  data->ramp_down_rate_in_miliwattspersec =
5413
0
      le32toh(data->ramp_down_rate_in_miliwattspersec);
5414
0
  data->ramp_hysterisis_rate_in_milisec =
5415
0
      le32toh(data->ramp_hysterisis_rate_in_milisec);
5416
0
}
5417
5418
static void htolegetPresetProfiledata(struct nsm_preset_profile_data *data)
5419
0
{
5420
0
  data->tmp_floor_setting_in_percent =
5421
0
      htole16(data->tmp_floor_setting_in_percent);
5422
0
  data->ramp_up_rate_in_miliwattspersec =
5423
0
      htole32(data->ramp_up_rate_in_miliwattspersec);
5424
0
  data->ramp_down_rate_in_miliwattspersec =
5425
0
      htole32(data->ramp_down_rate_in_miliwattspersec);
5426
0
  data->ramp_hysterisis_rate_in_milisec =
5427
0
      htole32(data->ramp_hysterisis_rate_in_milisec);
5428
0
}
5429
5430
int encode_get_preset_profile_req(uint8_t instance_id, struct nsm_msg *msg)
5431
0
{
5432
0
  return encode_get_platform_env_command_no_payload_req(
5433
0
      instance_id, msg, NSM_PWR_SMOOTHING_GET_PRESET_PROFILE_INFORMATION);
5434
0
}
5435
5436
int decode_get_preset_profile_req(const struct nsm_msg *msg, size_t msg_len)
5437
0
{
5438
0
  return decode_get_platform_env_command_no_payload_req(
5439
0
      msg, msg_len, NSM_PWR_SMOOTHING_GET_PRESET_PROFILE_INFORMATION);
5440
0
}
5441
5442
int encode_get_preset_profile_resp(
5443
    uint8_t instance_id, uint8_t cc, uint16_t reason_code,
5444
    struct nsm_get_all_preset_profile_meta_data *meta_data,
5445
    struct nsm_preset_profile_data *profile_data,
5446
    uint8_t max_number_of_profiles, struct nsm_msg *msg)
5447
0
{
5448
0
  if (msg == NULL || profile_data == NULL || meta_data == NULL) {
5449
0
    return NSM_SW_ERROR_NULL;
5450
0
  }
5451
5452
0
  struct nsm_header_info header = {0};
5453
0
  header.nsm_msg_type = NSM_RESPONSE;
5454
0
  header.instance_id = instance_id & 0x1f;
5455
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
5456
5457
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
5458
0
  if (rc != NSM_SW_SUCCESS) {
5459
0
    return rc;
5460
0
  }
5461
5462
0
  if (cc != NSM_SUCCESS) {
5463
0
    return encode_reason_code(
5464
0
        cc, reason_code,
5465
0
        NSM_PWR_SMOOTHING_GET_PRESET_PROFILE_INFORMATION, msg);
5466
0
  }
5467
5468
0
  struct nsm_get_all_preset_profile_resp *response =
5469
0
      (struct nsm_get_all_preset_profile_resp *)msg->payload;
5470
5471
0
  uint16_t meta_data_size =
5472
0
      sizeof(struct nsm_get_all_preset_profile_meta_data);
5473
0
  uint16_t profile_data_size = sizeof(struct nsm_preset_profile_data);
5474
  // data size is sum of metadata + number of profiles * size of one
5475
  // profile
5476
0
  uint16_t data_size =
5477
0
      meta_data_size + max_number_of_profiles * profile_data_size;
5478
5479
0
  response->hdr.command =
5480
0
      NSM_PWR_SMOOTHING_GET_PRESET_PROFILE_INFORMATION;
5481
0
  response->hdr.completion_code = cc;
5482
0
  response->hdr.data_size = htole16(data_size);
5483
5484
0
  response->data.max_profiles_supported = max_number_of_profiles;
5485
0
  for (int i = 0; i < max_number_of_profiles; i++) {
5486
0
    htolegetPresetProfiledata(profile_data + i);
5487
0
  }
5488
0
  memcpy(&(response->data.profiles), profile_data,
5489
0
         profile_data_size * max_number_of_profiles);
5490
0
  return NSM_SW_SUCCESS;
5491
0
}
5492
5493
int decode_get_preset_profile_metadata_resp(
5494
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
5495
    uint16_t *reason_code, struct nsm_get_all_preset_profile_meta_data *data,
5496
    uint8_t *number_of_profiles)
5497
0
{
5498
0
  if (data == NULL) {
5499
0
    return NSM_SW_ERROR_NULL;
5500
0
  }
5501
5502
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
5503
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
5504
0
    return rc;
5505
0
  }
5506
5507
0
  if (msg_len < (sizeof(struct nsm_msg_hdr) +
5508
0
           sizeof(struct nsm_get_all_preset_profile_resp))) {
5509
0
    return NSM_SW_ERROR_LENGTH;
5510
0
  }
5511
5512
0
  struct nsm_get_all_preset_profile_resp *resp =
5513
0
      (struct nsm_get_all_preset_profile_resp *)msg->payload;
5514
0
  size_t meta_data_len =
5515
0
      sizeof(struct nsm_get_all_preset_profile_meta_data);
5516
5517
0
  uint16_t preset_profile_size = sizeof(struct nsm_preset_profile_data);
5518
0
  uint16_t expected_data_size =
5519
0
      preset_profile_size * (data->max_profiles_supported);
5520
5521
0
  if (le16toh(resp->hdr.data_size) < expected_data_size) {
5522
0
    return NSM_SW_ERROR_DATA;
5523
0
  }
5524
5525
0
  memcpy(data, &(resp->data), meta_data_len);
5526
0
  *number_of_profiles = data->max_profiles_supported;
5527
5528
0
  return NSM_SW_SUCCESS;
5529
0
}
5530
5531
int decode_get_preset_profile_data_from_resp(
5532
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
5533
    uint16_t *reason_code, uint8_t max_profiles_supported, uint8_t profile_id,
5534
    struct nsm_preset_profile_data *profile_data)
5535
0
{
5536
0
  if (profile_data == NULL) {
5537
0
    return NSM_SW_ERROR_NULL;
5538
0
  }
5539
5540
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
5541
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
5542
0
    return rc;
5543
0
  }
5544
5545
0
  if (msg_len < (sizeof(struct nsm_msg_hdr) +
5546
0
           sizeof(struct nsm_get_all_preset_profile_resp))) {
5547
0
    return NSM_SW_ERROR_LENGTH;
5548
0
  }
5549
5550
0
  struct nsm_get_all_preset_profile_resp *resp =
5551
0
      (struct nsm_get_all_preset_profile_resp *)msg->payload;
5552
5553
0
  uint16_t preset_profile_size = sizeof(struct nsm_preset_profile_data);
5554
0
  uint16_t expected_data_size =
5555
0
      preset_profile_size * (max_profiles_supported);
5556
5557
0
  if (le16toh(resp->hdr.data_size) < expected_data_size) {
5558
0
    return NSM_SW_ERROR_DATA;
5559
0
  }
5560
0
  uint8_t profile_data_size = sizeof(struct nsm_preset_profile_data);
5561
5562
0
  memcpy(profile_data,
5563
0
         &(resp->data.profiles) + profile_id * profile_data_size,
5564
0
         profile_data_size);
5565
5566
  // conversion le to he
5567
0
  letohgetPresetProfiledata(profile_data);
5568
5569
0
  return NSM_SW_SUCCESS;
5570
0
}
5571
int encode_update_preset_profile_param_req(uint8_t instance_id,
5572
             uint8_t profile_id,
5573
             uint8_t parameter_id,
5574
             uint32_t param_value,
5575
             struct nsm_msg *msg)
5576
0
{
5577
0
  if (msg == NULL) {
5578
0
    return NSM_SW_ERROR_NULL;
5579
0
  }
5580
5581
0
  struct nsm_header_info header = {0};
5582
0
  header.nsm_msg_type = NSM_REQUEST;
5583
0
  header.instance_id = instance_id;
5584
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
5585
5586
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
5587
0
  if (rc != NSM_SW_SUCCESS) {
5588
0
    return rc;
5589
0
  }
5590
5591
0
  struct nsm_update_preset_profile_req *request =
5592
0
      (struct nsm_update_preset_profile_req *)msg->payload;
5593
5594
0
  request->hdr.command =
5595
0
      NSM_PWR_SMOOTHING_UPDATE_PRESET_PROFILE_PARAMETERS;
5596
0
  request->hdr.data_size = sizeof(struct nsm_update_preset_profile_req) -
5597
0
         sizeof(struct nsm_common_req);
5598
0
  request->profile_id = profile_id;
5599
0
  request->parameter_id = parameter_id;
5600
0
  request->param_value = htole32(param_value);
5601
0
  return NSM_SW_SUCCESS;
5602
0
}
5603
5604
int decode_update_preset_profile_param_req(const struct nsm_msg *msg,
5605
             size_t msg_len, uint8_t *profile_id,
5606
             uint8_t *parameter_id,
5607
             uint32_t *param_value)
5608
0
{
5609
0
  if (msg == NULL || parameter_id == NULL || param_value == NULL) {
5610
0
    return NSM_SW_ERROR_NULL;
5611
0
  }
5612
5613
0
  if (msg_len < sizeof(struct nsm_msg_hdr) +
5614
0
        sizeof(struct nsm_update_preset_profile_req)) {
5615
0
    return NSM_SW_ERROR_LENGTH;
5616
0
  }
5617
5618
0
  struct nsm_update_preset_profile_req *request =
5619
0
      (struct nsm_update_preset_profile_req *)msg->payload;
5620
5621
0
  if (request->hdr.data_size <
5622
0
      sizeof(request->parameter_id) + sizeof(request->param_value)) {
5623
0
    return NSM_SW_ERROR_DATA;
5624
0
  }
5625
0
  *profile_id = request->profile_id;
5626
0
  *parameter_id = request->parameter_id;
5627
0
  *param_value = le32toh(request->param_value);
5628
5629
0
  return NSM_SW_SUCCESS;
5630
0
}
5631
5632
int encode_update_preset_profile_param_resp(uint8_t instance_id, uint8_t cc,
5633
              uint16_t reason_code,
5634
              struct nsm_msg *msg)
5635
0
{
5636
0
  if (msg == NULL) {
5637
0
    return NSM_SW_ERROR_NULL;
5638
0
  }
5639
5640
0
  struct nsm_header_info header = {0};
5641
0
  header.nsm_msg_type = NSM_RESPONSE;
5642
0
  header.instance_id = instance_id & 0x1f;
5643
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
5644
5645
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
5646
0
  if (rc != NSM_SW_SUCCESS) {
5647
0
    return rc;
5648
0
  }
5649
5650
0
  if (cc != NSM_SUCCESS) {
5651
0
    return encode_reason_code(
5652
0
        cc, reason_code,
5653
0
        NSM_PWR_SMOOTHING_UPDATE_PRESET_PROFILE_PARAMETERS, msg);
5654
0
  }
5655
0
  struct nsm_common_resp *response =
5656
0
      (struct nsm_common_resp *)msg->payload;
5657
5658
0
  response->command = NSM_PWR_SMOOTHING_UPDATE_PRESET_PROFILE_PARAMETERS;
5659
0
  response->completion_code = cc;
5660
0
  response->data_size = 0;
5661
5662
0
  return NSM_SW_SUCCESS;
5663
0
}
5664
5665
int decode_update_preset_profile_param_resp(const struct nsm_msg *msg,
5666
              size_t msg_len, uint8_t *cc,
5667
              uint16_t *reason_code)
5668
0
{
5669
0
  if (msg == NULL || cc == NULL) {
5670
0
    return NSM_ERR_INVALID_DATA;
5671
0
  }
5672
5673
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
5674
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
5675
0
    return rc;
5676
0
  }
5677
5678
0
  if (msg_len <
5679
0
      sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_common_resp)) {
5680
0
    return NSM_SW_ERROR_LENGTH;
5681
0
  }
5682
5683
0
  struct nsm_common_resp *resp = (struct nsm_common_resp *)msg->payload;
5684
5685
0
  uint16_t data_size = le16toh(resp->data_size);
5686
0
  if (data_size != 0) {
5687
0
    return NSM_SW_ERROR_DATA;
5688
0
  }
5689
5690
0
  return NSM_SUCCESS;
5691
0
}
5692
5693
double NvUFXP4_12ToDouble(uint16_t reading)
5694
0
{
5695
0
  double value = reading / (double)(1 << 12);
5696
0
  return value;
5697
0
}
5698
// reading should be between 0 - 1
5699
uint16_t doubleToNvUFXP4_12(double reading)
5700
0
{
5701
0
  if (reading > 1)
5702
0
    return 0;
5703
  // Separate integer and fractional parts
5704
0
  int integerPart = (int)(reading);
5705
0
  double fractionalPart = reading - integerPart;
5706
5707
  // Convert integer part to 4-bit representation
5708
0
  uint16_t result = (integerPart & 0xF) << 12;
5709
5710
  // Convert fractional part to 12-bit representation
5711
0
  uint16_t fractionalBits = (uint16_t)(fractionalPart * 4096);
5712
5713
  // Combine integer and fractional parts
5714
0
  result |= (fractionalBits & 0xFFF);
5715
0
  return result;
5716
0
}
5717
5718
double NvUFXP8_24ToDouble(uint32_t reading)
5719
0
{
5720
  // Extract the MSB (8 bits)
5721
0
  int32_t msb = (reading >> 24) & 0xFF;
5722
  // Extract the LSB (24 bits)
5723
0
  uint32_t lsb = reading & 0xFFFFFF;
5724
  // Combine MSB and LSB
5725
0
  double result = (double)msb + (double)lsb / (1 << 24);
5726
0
  return result;
5727
0
}
5728
5729
uint32_t doubleToNvUFXP8_24(double reading)
5730
0
{
5731
0
  uint32_t value = reading * (1 << 24);
5732
0
  return value;
5733
0
}
5734
5735
//  Enable Workload Power Profiles
5736
int encode_enable_workload_power_profile_req(uint8_t instance_id,
5737
               bitfield256_t *profile_mask,
5738
               struct nsm_msg *msg)
5739
0
{
5740
0
  if (msg == NULL) {
5741
0
    return NSM_SW_ERROR_NULL;
5742
0
  }
5743
5744
0
  struct nsm_header_info header = {0};
5745
0
  header.nsm_msg_type = NSM_REQUEST;
5746
0
  header.instance_id = instance_id;
5747
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
5748
5749
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
5750
0
  if (rc != NSM_SW_SUCCESS) {
5751
0
    return rc;
5752
0
  }
5753
5754
0
  struct nsm_enable_workload_power_profile_req *request =
5755
0
      (struct nsm_enable_workload_power_profile_req *)msg->payload;
5756
5757
0
  request->hdr.command = NSM_ENABLE_WORKLOAD_POWER_PROFILE;
5758
0
  request->hdr.data_size = sizeof(bitfield256_t);
5759
5760
  // htole
5761
0
  size_t length = 8;
5762
0
  for (size_t i = 0; i < length; i++) {
5763
0
    request->profile_mask.fields[length - 1 - i].byte =
5764
0
        profile_mask->fields[i].byte;
5765
0
  }
5766
5767
0
  for (size_t i = 0; i < length; i++) {
5768
0
    request->profile_mask.fields[i].byte =
5769
0
        htole32(request->profile_mask.fields[i].byte);
5770
0
  }
5771
5772
0
  return NSM_SW_SUCCESS;
5773
0
}
5774
5775
int decode_enable_workload_power_profile_req(const struct nsm_msg *msg,
5776
               size_t msg_len,
5777
               bitfield256_t *profile_mask)
5778
0
{
5779
0
  if (msg == NULL || profile_mask == NULL) {
5780
0
    return NSM_SW_ERROR_NULL;
5781
0
  }
5782
5783
0
  if (msg_len < sizeof(struct nsm_msg_hdr) + sizeof(bitfield256_t)) {
5784
0
    return NSM_SW_ERROR_LENGTH;
5785
0
  }
5786
5787
0
  struct nsm_enable_workload_power_profile_req *request =
5788
0
      (struct nsm_enable_workload_power_profile_req *)msg->payload;
5789
5790
0
  if (request->hdr.data_size < sizeof(request->profile_mask)) {
5791
0
    return NSM_SW_ERROR_DATA;
5792
0
  }
5793
5794
0
  memcpy(profile_mask, &(request->profile_mask), sizeof(bitfield256_t));
5795
0
  for (int i = 0; i < 8; i++) {
5796
0
    profile_mask->fields[i].byte =
5797
0
        le32toh(profile_mask->fields[i].byte);
5798
0
  }
5799
0
  return NSM_SW_SUCCESS;
5800
0
}
5801
5802
int encode_enable_workload_power_profile_resp(uint8_t instance_id, uint8_t cc,
5803
                uint16_t reason_code,
5804
                struct nsm_msg *msg)
5805
0
{
5806
0
  if (msg == NULL) {
5807
0
    return NSM_SW_ERROR_NULL;
5808
0
  }
5809
5810
0
  struct nsm_header_info header = {0};
5811
0
  header.nsm_msg_type = NSM_RESPONSE;
5812
0
  header.instance_id = instance_id & 0x1f;
5813
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
5814
5815
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
5816
0
  if (rc != NSM_SW_SUCCESS) {
5817
0
    return rc;
5818
0
  }
5819
5820
0
  if (cc != NSM_SUCCESS) {
5821
0
    return encode_reason_code(
5822
0
        cc, reason_code, NSM_ENABLE_WORKLOAD_POWER_PROFILE, msg);
5823
0
  }
5824
0
  struct nsm_common_resp *response =
5825
0
      (struct nsm_common_resp *)msg->payload;
5826
5827
0
  response->command = NSM_ENABLE_WORKLOAD_POWER_PROFILE;
5828
0
  response->completion_code = cc;
5829
0
  response->data_size = 0;
5830
5831
0
  return NSM_SW_SUCCESS;
5832
0
}
5833
5834
int decode_enable_workload_power_profile_resp(const struct nsm_msg *msg,
5835
                size_t msg_len, uint8_t *cc,
5836
                uint16_t *reason_code)
5837
0
{
5838
0
  if (msg == NULL || cc == NULL) {
5839
0
    return NSM_ERR_INVALID_DATA;
5840
0
  }
5841
5842
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
5843
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
5844
0
    return rc;
5845
0
  }
5846
5847
0
  if (msg_len <
5848
0
      sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_common_resp)) {
5849
0
    return NSM_SW_ERROR_LENGTH;
5850
0
  }
5851
5852
0
  struct nsm_common_resp *resp = (struct nsm_common_resp *)msg->payload;
5853
5854
0
  uint16_t data_size = le16toh(resp->data_size);
5855
0
  if (data_size != 0) {
5856
0
    return NSM_SW_ERROR_DATA;
5857
0
  }
5858
5859
0
  return NSM_SUCCESS;
5860
0
}
5861
5862
//  Enable Workload Power Profiles
5863
int encode_disable_workload_power_profile_req(uint8_t instance_id,
5864
                bitfield256_t *profile_mask,
5865
                struct nsm_msg *msg)
5866
0
{
5867
0
  if (msg == NULL) {
5868
0
    return NSM_SW_ERROR_NULL;
5869
0
  }
5870
5871
0
  struct nsm_header_info header = {0};
5872
0
  header.nsm_msg_type = NSM_REQUEST;
5873
0
  header.instance_id = instance_id;
5874
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
5875
5876
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
5877
0
  if (rc != NSM_SW_SUCCESS) {
5878
0
    return rc;
5879
0
  }
5880
5881
0
  struct nsm_disable_workload_power_profile_req *request =
5882
0
      (struct nsm_disable_workload_power_profile_req *)msg->payload;
5883
5884
0
  request->hdr.command = NSM_DISABLE_WORKLOAD_POWER_PROFILE;
5885
0
  request->hdr.data_size = sizeof(bitfield256_t);
5886
5887
  // htole
5888
0
  size_t length = 8;
5889
0
  for (size_t i = 0; i < length; i++) {
5890
0
    request->profile_mask.fields[length - 1 - i].byte =
5891
0
        profile_mask->fields[i].byte;
5892
0
  }
5893
5894
0
  for (size_t i = 0; i < length; i++) {
5895
0
    request->profile_mask.fields[i].byte =
5896
0
        htole32(request->profile_mask.fields[i].byte);
5897
0
  }
5898
5899
0
  return NSM_SW_SUCCESS;
5900
0
}
5901
5902
int decode_disable_workload_power_profile_req(const struct nsm_msg *msg,
5903
                size_t msg_len,
5904
                bitfield256_t *profile_mask)
5905
0
{
5906
0
  if (msg == NULL || profile_mask == NULL) {
5907
0
    return NSM_SW_ERROR_NULL;
5908
0
  }
5909
5910
0
  if (msg_len < sizeof(struct nsm_msg_hdr) + sizeof(bitfield256_t)) {
5911
0
    return NSM_SW_ERROR_LENGTH;
5912
0
  }
5913
5914
0
  struct nsm_disable_workload_power_profile_req *request =
5915
0
      (struct nsm_disable_workload_power_profile_req *)msg->payload;
5916
5917
0
  if (request->hdr.data_size < sizeof(request->profile_mask)) {
5918
0
    return NSM_SW_ERROR_DATA;
5919
0
  }
5920
5921
0
  memcpy(profile_mask, &(request->profile_mask), sizeof(bitfield32_t[8]));
5922
0
  for (int i = 0; i < 8; i++) {
5923
0
    profile_mask->fields[i].byte =
5924
0
        le32toh(profile_mask->fields[i].byte);
5925
0
  }
5926
0
  return NSM_SW_SUCCESS;
5927
0
}
5928
5929
int encode_disable_workload_power_profile_resp(uint8_t instance_id, uint8_t cc,
5930
                 uint16_t reason_code,
5931
                 struct nsm_msg *msg)
5932
0
{
5933
0
  if (msg == NULL) {
5934
0
    return NSM_SW_ERROR_NULL;
5935
0
  }
5936
5937
0
  struct nsm_header_info header = {0};
5938
0
  header.nsm_msg_type = NSM_RESPONSE;
5939
0
  header.instance_id = instance_id & 0x1f;
5940
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
5941
5942
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
5943
0
  if (rc != NSM_SW_SUCCESS) {
5944
0
    return rc;
5945
0
  }
5946
5947
0
  if (cc != NSM_SUCCESS) {
5948
0
    return encode_reason_code(
5949
0
        cc, reason_code, NSM_DISABLE_WORKLOAD_POWER_PROFILE, msg);
5950
0
  }
5951
0
  struct nsm_common_resp *response =
5952
0
      (struct nsm_common_resp *)msg->payload;
5953
5954
0
  response->command = NSM_ENABLE_WORKLOAD_POWER_PROFILE;
5955
0
  response->completion_code = cc;
5956
0
  response->data_size = 0;
5957
5958
0
  return NSM_SW_SUCCESS;
5959
0
}
5960
5961
int decode_disable_workload_power_profile_resp(const struct nsm_msg *msg,
5962
                 size_t msg_len, uint8_t *cc,
5963
                 uint16_t *reason_code)
5964
0
{
5965
0
  if (msg == NULL || cc == NULL) {
5966
0
    return NSM_ERR_INVALID_DATA;
5967
0
  }
5968
5969
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
5970
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
5971
0
    return rc;
5972
0
  }
5973
5974
0
  if (msg_len <
5975
0
      sizeof(struct nsm_msg_hdr) + sizeof(struct nsm_common_resp)) {
5976
0
    return NSM_SW_ERROR_LENGTH;
5977
0
  }
5978
5979
0
  struct nsm_common_resp *resp = (struct nsm_common_resp *)msg->payload;
5980
5981
0
  uint16_t data_size = le16toh(resp->data_size);
5982
0
  if (data_size != 0) {
5983
0
    return NSM_SW_ERROR_DATA;
5984
0
  }
5985
5986
0
  return NSM_SUCCESS;
5987
0
}
5988
5989
int encode_get_workload_power_profile_status_req(uint8_t instance_id,
5990
             struct nsm_msg *msg)
5991
0
{
5992
0
  return encode_get_platform_env_command_no_payload_req(
5993
0
      instance_id, msg, NSM_GET_WORKLOAD_POWER_PROFILE_STATUS_INFO);
5994
0
}
5995
5996
int decode_get_workload_power_profile_status_req(const struct nsm_msg *msg,
5997
             size_t msg_len)
5998
0
{
5999
0
  return decode_get_platform_env_command_no_payload_req(
6000
0
      msg, msg_len, NSM_GET_WORKLOAD_POWER_PROFILE_STATUS_INFO);
6001
0
}
6002
6003
static void
6004
htole32PresetProfileResp(struct workload_power_profile_status *profileInfo)
6005
0
{
6006
0
  size_t length = 8 / 2;
6007
0
  for (size_t i = 0; i < length; i++) {
6008
0
    uint32_t temp =
6009
0
        htole32(profileInfo->supported_profile_mask.fields[i].byte);
6010
0
    profileInfo->supported_profile_mask.fields[i].byte = htole32(
6011
0
        profileInfo->supported_profile_mask.fields[length - 1 - i]
6012
0
      .byte);
6013
0
    profileInfo->supported_profile_mask.fields[length - 1 - i]
6014
0
        .byte = temp;
6015
0
  }
6016
6017
0
  for (size_t i = 0; i < length; i++) {
6018
0
    uint32_t temp =
6019
0
        htole32(profileInfo->requested_profile_maks.fields[i].byte);
6020
0
    profileInfo->requested_profile_maks.fields[i].byte = htole32(
6021
0
        profileInfo->requested_profile_maks.fields[length - 1 - i]
6022
0
      .byte);
6023
0
    profileInfo->requested_profile_maks.fields[length - 1 - i]
6024
0
        .byte = temp;
6025
0
  }
6026
6027
0
  for (size_t i = 0; i < length; i++) {
6028
0
    uint32_t temp =
6029
0
        htole32(profileInfo->enforced_profile_mask.fields[i].byte);
6030
0
    profileInfo->enforced_profile_mask.fields[i].byte = htole32(
6031
0
        profileInfo->enforced_profile_mask.fields[length - 1 - i]
6032
0
      .byte);
6033
0
    profileInfo->enforced_profile_mask.fields[length - 1 - i].byte =
6034
0
        temp;
6035
0
  }
6036
0
}
6037
6038
static void
6039
le32tohPresetProfileResp(struct workload_power_profile_status *profileInfo)
6040
0
{
6041
0
  size_t length = 8;
6042
0
  for (size_t i = 0; i < length / 2; i++) {
6043
0
    uint32_t temp =
6044
0
        profileInfo->supported_profile_mask.fields[i].byte;
6045
0
    profileInfo->supported_profile_mask.fields[i].byte =
6046
0
        profileInfo->supported_profile_mask.fields[length - 1 - i]
6047
0
      .byte;
6048
0
    profileInfo->supported_profile_mask.fields[length - 1 - i]
6049
0
        .byte = temp;
6050
0
  }
6051
6052
0
  for (size_t i = 0; i < length / 2; i++) {
6053
0
    uint32_t temp =
6054
0
        profileInfo->requested_profile_maks.fields[i].byte;
6055
0
    profileInfo->requested_profile_maks.fields[i].byte =
6056
0
        profileInfo->requested_profile_maks.fields[length - 1 - i]
6057
0
      .byte;
6058
0
    profileInfo->requested_profile_maks.fields[length - 1 - i]
6059
0
        .byte = temp;
6060
0
  }
6061
6062
0
  for (size_t i = 0; i < length / 2; i++) {
6063
0
    uint32_t temp =
6064
0
        profileInfo->enforced_profile_mask.fields[i].byte;
6065
0
    profileInfo->enforced_profile_mask.fields[i].byte =
6066
0
        profileInfo->enforced_profile_mask.fields[length - 1 - i]
6067
0
      .byte;
6068
0
    profileInfo->enforced_profile_mask.fields[length - 1 - i].byte =
6069
0
        temp;
6070
0
  }
6071
0
  for (size_t i = 0; i < length; i++) {
6072
0
    profileInfo->supported_profile_mask.fields[i].byte =
6073
0
        le32toh(profileInfo->supported_profile_mask.fields[i].byte);
6074
0
    profileInfo->requested_profile_maks.fields[i].byte =
6075
0
        le32toh(profileInfo->requested_profile_maks.fields[i].byte);
6076
0
    profileInfo->enforced_profile_mask.fields[i].byte =
6077
0
        le32toh(profileInfo->enforced_profile_mask.fields[i].byte);
6078
0
  }
6079
0
}
6080
6081
int encode_get_workload_power_profile_status_resp(
6082
    uint8_t instance_id, uint8_t cc, uint16_t reason_code,
6083
    struct workload_power_profile_status *data, struct nsm_msg *msg)
6084
0
{
6085
0
  if (msg == NULL || data == NULL) {
6086
0
    return NSM_SW_ERROR_NULL;
6087
0
  }
6088
6089
0
  struct nsm_header_info header = {0};
6090
0
  header.nsm_msg_type = NSM_RESPONSE;
6091
0
  header.instance_id = instance_id & 0x1f;
6092
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
6093
6094
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
6095
0
  if (rc != NSM_SW_SUCCESS) {
6096
0
    return rc;
6097
0
  }
6098
6099
0
  if (cc != NSM_SUCCESS) {
6100
0
    return encode_reason_code(
6101
0
        cc, reason_code, NSM_GET_WORKLOAD_POWER_PROFILE_STATUS_INFO,
6102
0
        msg);
6103
0
  }
6104
6105
0
  struct nsm_get_workload_power_profile_status_info_resp *response =
6106
0
      (struct nsm_get_workload_power_profile_status_info_resp *)
6107
0
    msg->payload;
6108
6109
0
  response->hdr.command = NSM_GET_WORKLOAD_POWER_PROFILE_STATUS_INFO;
6110
0
  response->hdr.completion_code = cc;
6111
0
  response->hdr.data_size =
6112
0
      htole16(sizeof(struct workload_power_profile_status));
6113
6114
0
  memcpy(&(response->data), data,
6115
0
         sizeof(struct workload_power_profile_status));
6116
0
  htole32PresetProfileResp(data);
6117
6118
0
  return NSM_SW_SUCCESS;
6119
0
}
6120
6121
int decode_get_workload_power_profile_status_resp(
6122
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
6123
    uint16_t *reason_code, uint16_t *data_size,
6124
    struct workload_power_profile_status *data)
6125
0
{
6126
0
  if (data == NULL || data_size == NULL) {
6127
0
    return NSM_SW_ERROR_NULL;
6128
0
  }
6129
6130
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
6131
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
6132
0
    return rc;
6133
0
  }
6134
6135
0
  if (msg_len <
6136
0
      (sizeof(struct nsm_msg_hdr) +
6137
0
       sizeof(struct nsm_get_workload_power_profile_status_info_resp))) {
6138
0
    return NSM_SW_ERROR_LENGTH;
6139
0
  }
6140
0
  struct nsm_get_workload_power_profile_status_info_resp *resp_payload =
6141
0
      (struct nsm_get_workload_power_profile_status_info_resp *)
6142
0
    msg->payload;
6143
6144
0
  *data_size = le16toh(resp_payload->hdr.data_size);
6145
0
  size_t response_data_len = sizeof(struct workload_power_profile_status);
6146
0
  memcpy(data, &(resp_payload->data), response_data_len);
6147
6148
  // conversion le32toh
6149
0
  le32tohPresetProfileResp(data);
6150
6151
0
  return NSM_SW_SUCCESS;
6152
0
}
6153
6154
static void
6155
letohgetWorkloadPresetProfiledata(struct nsm_workload_power_profile_data *data)
6156
0
{
6157
0
  data->profile_id = le16toh(data->profile_id);
6158
0
  data->priority = le16toh(data->priority);
6159
0
  size_t length = 8;
6160
0
  for (int i = 0; i < 8; i++) {
6161
0
    data->conflict_mask.fields[i].byte =
6162
0
        le32toh(data->conflict_mask.fields[i].byte);
6163
0
  }
6164
6165
0
  for (size_t i = 0; i < length / 2; i++) {
6166
0
    uint32_t temp = data->conflict_mask.fields[i].byte;
6167
0
    data->conflict_mask.fields[i].byte =
6168
0
        data->conflict_mask.fields[length - 1 - i].byte;
6169
0
    data->conflict_mask.fields[length - 1 - i].byte = temp;
6170
0
  }
6171
6172
0
  for (size_t i = 0; i < length; i++) {
6173
0
    data->conflict_mask.fields[i].byte =
6174
0
        le32toh(data->conflict_mask.fields[i].byte);
6175
0
  }
6176
0
}
6177
6178
static void
6179
htolegetWorkloadPresetProfiledata(struct nsm_workload_power_profile_data *data)
6180
0
{
6181
0
  data->profile_id = htole16(data->profile_id);
6182
0
  data->priority = htole16(data->priority);
6183
0
  for (int i = 0; i < 8; i++) {
6184
0
    data->conflict_mask.fields[i].byte =
6185
0
        htole32(data->conflict_mask.fields[i].byte);
6186
0
  }
6187
0
}
6188
6189
int encode_get_workload_power_profile_info_req(uint8_t instance_id,
6190
                 uint16_t identifier,
6191
                 struct nsm_msg *msg)
6192
0
{
6193
0
  if (msg == NULL) {
6194
0
    return NSM_SW_ERROR_NULL;
6195
0
  }
6196
6197
0
  struct nsm_header_info header = {0};
6198
0
  header.nsm_msg_type = NSM_REQUEST;
6199
0
  header.instance_id = instance_id;
6200
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
6201
6202
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
6203
0
  if (rc != NSM_SW_SUCCESS) {
6204
0
    return rc;
6205
0
  }
6206
6207
0
  struct nsm_get_workload_power_profile_info_req *request =
6208
0
      (struct nsm_get_workload_power_profile_info_req *)msg->payload;
6209
6210
0
  request->hdr.command = NSM_GET_WORKLOAD_POWER_PROFILE_INFO;
6211
0
  request->hdr.data_size = sizeof(identifier);
6212
0
  request->identifier = identifier;
6213
0
  return NSM_SW_SUCCESS;
6214
0
}
6215
6216
int decode_get_workload_power_profile_info_req(const struct nsm_msg *msg,
6217
                 size_t msg_len,
6218
                 uint16_t *identifier)
6219
0
{
6220
0
  if (msg == NULL || identifier == NULL) {
6221
0
    return NSM_SW_ERROR_NULL;
6222
0
  }
6223
6224
0
  if (msg_len <
6225
0
      sizeof(struct nsm_msg_hdr) +
6226
0
    sizeof(struct nsm_get_workload_power_profile_info_req)) {
6227
0
    return NSM_SW_ERROR_LENGTH;
6228
0
  }
6229
6230
0
  struct nsm_get_workload_power_profile_info_req *request =
6231
0
      (struct nsm_get_workload_power_profile_info_req *)msg->payload;
6232
6233
0
  if (request->hdr.data_size < sizeof(request->identifier)) {
6234
0
    return NSM_SW_ERROR_DATA;
6235
0
  }
6236
6237
0
  *identifier = request->identifier;
6238
6239
0
  return NSM_SW_SUCCESS;
6240
0
}
6241
6242
int encode_get_workload_power_profile_info_resp(
6243
    uint8_t instance_id, uint8_t cc, uint16_t reason_code,
6244
    struct nsm_all_workload_power_profile_meta_data *meta_data,
6245
    struct nsm_workload_power_profile_data *profile_data,
6246
    uint8_t number_of_profiles, struct nsm_msg *msg)
6247
0
{
6248
0
  if (msg == NULL || profile_data == NULL || meta_data == NULL) {
6249
0
    return NSM_SW_ERROR_NULL;
6250
0
  }
6251
6252
0
  struct nsm_header_info header = {0};
6253
0
  header.nsm_msg_type = NSM_RESPONSE;
6254
0
  header.instance_id = instance_id & 0x1f;
6255
0
  header.nvidia_msg_type = NSM_TYPE_PLATFORM_ENVIRONMENTAL;
6256
6257
0
  uint8_t rc = pack_nsm_header(&header, &msg->hdr);
6258
0
  if (rc != NSM_SW_SUCCESS) {
6259
0
    return rc;
6260
0
  }
6261
6262
0
  if (cc != NSM_SUCCESS) {
6263
0
    return encode_reason_code(
6264
0
        cc, reason_code, NSM_GET_WORKLOAD_POWER_PROFILE_INFO, msg);
6265
0
  }
6266
6267
0
  struct nsm_workload_power_profile_get_all_preset_profile_resp
6268
0
      *response =
6269
0
    (struct nsm_workload_power_profile_get_all_preset_profile_resp
6270
0
         *)msg->payload;
6271
6272
0
  uint16_t meta_data_size =
6273
0
      sizeof(struct nsm_all_workload_power_profile_meta_data);
6274
0
  uint16_t profile_data_size =
6275
0
      sizeof(struct nsm_workload_power_profile_data);
6276
  // data size is sum of metadata + number of profiles * size of one
6277
  // profile
6278
0
  uint16_t data_size =
6279
0
      meta_data_size + number_of_profiles * profile_data_size;
6280
6281
0
  response->hdr.command = NSM_GET_WORKLOAD_POWER_PROFILE_INFO;
6282
0
  response->hdr.completion_code = cc;
6283
0
  response->hdr.data_size = htole16(data_size);
6284
0
  response->data.next_identifier = htole16(meta_data->next_identifier);
6285
0
  response->data.number_of_profiles = number_of_profiles;
6286
0
  for (int i = 0; i < number_of_profiles; i++) {
6287
0
    htolegetWorkloadPresetProfiledata(profile_data + i);
6288
0
  }
6289
0
  memcpy(&(response->data.profiles), profile_data,
6290
0
         profile_data_size * number_of_profiles);
6291
0
  return NSM_SW_SUCCESS;
6292
0
}
6293
6294
int decode_get_workload_power_profile_info_metadata_resp(
6295
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
6296
    uint16_t *reason_code,
6297
    struct nsm_all_workload_power_profile_meta_data *data,
6298
    uint8_t *number_of_profiles)
6299
0
{
6300
0
  if (data == NULL) {
6301
0
    return NSM_SW_ERROR_NULL;
6302
0
  }
6303
6304
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
6305
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
6306
0
    return rc;
6307
0
  }
6308
6309
0
  if (msg_len <
6310
0
      (sizeof(struct nsm_msg_hdr) +
6311
0
       sizeof(struct nsm_all_workload_power_profile_resp_meta_data))) {
6312
0
    return NSM_SW_ERROR_LENGTH;
6313
0
  }
6314
6315
0
  struct nsm_workload_power_profile_get_all_preset_profile_resp *resp =
6316
0
      (struct nsm_workload_power_profile_get_all_preset_profile_resp *)
6317
0
    msg->payload;
6318
0
  size_t meta_data_len =
6319
0
      sizeof(struct nsm_all_workload_power_profile_meta_data);
6320
6321
0
  uint16_t preset_profile_size =
6322
0
      sizeof(struct nsm_workload_power_profile_data);
6323
0
  uint16_t expected_data_size =
6324
0
      preset_profile_size * (resp->data.number_of_profiles);
6325
6326
0
  if (le16toh(resp->hdr.data_size) < expected_data_size) {
6327
0
    return NSM_SW_ERROR_DATA;
6328
0
  }
6329
6330
0
  memcpy(data, &(resp->data), meta_data_len);
6331
0
  *number_of_profiles = data->number_of_profiles;
6332
0
  data->next_identifier = le16toh(data->next_identifier);
6333
6334
0
  return NSM_SW_SUCCESS;
6335
0
}
6336
6337
int decode_get_workload_power_profile_info_data_resp(
6338
    const struct nsm_msg *msg, size_t msg_len, uint8_t *cc,
6339
    uint16_t *reason_code, uint8_t max_profiles_supported, uint8_t offset,
6340
    struct nsm_workload_power_profile_data *profile_data)
6341
0
{
6342
0
  if (profile_data == NULL) {
6343
0
    return NSM_SW_ERROR_NULL;
6344
0
  }
6345
6346
0
  int rc = decode_reason_code_and_cc(msg, msg_len, cc, reason_code);
6347
0
  if (rc != NSM_SW_SUCCESS || *cc != NSM_SUCCESS) {
6348
0
    return rc;
6349
0
  }
6350
6351
0
  if (msg_len < (sizeof(struct nsm_msg_hdr) +
6352
0
           sizeof(struct nsm_get_all_preset_profile_resp))) {
6353
0
    return NSM_SW_ERROR_LENGTH;
6354
0
  }
6355
6356
0
  struct nsm_workload_power_profile_get_all_preset_profile_resp *resp =
6357
0
      (struct nsm_workload_power_profile_get_all_preset_profile_resp *)
6358
0
    msg->payload;
6359
6360
0
  uint16_t preset_profile_size =
6361
0
      sizeof(struct nsm_workload_power_profile_data);
6362
0
  uint16_t expected_data_size =
6363
0
      preset_profile_size * (max_profiles_supported);
6364
6365
0
  if (le16toh(resp->hdr.data_size) < expected_data_size) {
6366
0
    return NSM_SW_ERROR_DATA;
6367
0
  }
6368
0
  uint8_t profile_data_size =
6369
0
      sizeof(struct nsm_workload_power_profile_data);
6370
6371
0
  memcpy(profile_data,
6372
0
         &(resp->data.profiles) + offset * profile_data_size,
6373
0
         profile_data_size);
6374
6375
  // conversion le to he
6376
0
  letohgetWorkloadPresetProfiledata(profile_data);
6377
6378
0
  return NSM_SW_SUCCESS;
6379
0
}