blob: 509407a24b1ac3ef3d61f1308599e49aa26c1627 [file] [log] [blame]
Andrew Jefferye3e3c972021-05-26 14:37:07 +09301#include "NVMeBasicContext.hpp"
2
Ed Tanouseacbfdd2024-04-04 12:00:24 -07003#include "NVMeContext.hpp"
4#include "NVMeSensor.hpp"
5
Andrew Jefferye3e3c972021-05-26 14:37:07 +09306#include <endian.h>
7#include <sys/ioctl.h>
8#include <unistd.h>
9
Ed Tanous73030632022-01-14 10:09:47 -080010#include <FileHandle.hpp>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070011#include <boost/asio/buffer.hpp>
12#include <boost/asio/error.hpp>
13#include <boost/asio/io_context.hpp>
Andrew Jefferye3e3c972021-05-26 14:37:07 +093014#include <boost/asio/read.hpp>
15#include <boost/asio/streambuf.hpp>
16#include <boost/asio/write.hpp>
George Liu7201be42025-02-20 20:01:54 +080017#include <phosphor-logging/lg2.hpp>
18#include <phosphor-logging/lg2/flags.hpp>
Andrew Jefferye3e3c972021-05-26 14:37:07 +093019
Ed Tanouseacbfdd2024-04-04 12:00:24 -070020#include <array>
Andrew Jefferye3e3c972021-05-26 14:37:07 +093021#include <cerrno>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070022#include <chrono>
23#include <cmath>
24#include <cstdint>
Andrew Jefferye3e3c972021-05-26 14:37:07 +093025#include <cstdio>
26#include <cstring>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070027#include <filesystem>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070028#include <iostream>
29#include <iterator>
30#include <limits>
31#include <memory>
32#include <stdexcept>
33#include <string>
Andrew Jefferye3e3c972021-05-26 14:37:07 +093034#include <system_error>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070035#include <thread>
36#include <utility>
37#include <vector>
Andrew Jefferye3e3c972021-05-26 14:37:07 +093038
39extern "C"
40{
41#include <i2c/smbus.h>
42#include <linux/i2c-dev.h>
43}
44
45/*
46 * NVMe-MI Basic Management Command
47 *
48 * https://nvmexpress.org/wp-content/uploads/NVMe_Management_-_Technical_Note_on_Basic_Management_Command.pdf
49 */
50
Patrick Williams556e04b2025-02-01 08:22:22 -050051static std::shared_ptr<std::array<uint8_t, 6>> encodeBasicQuery(
52 int bus, uint8_t device, uint8_t offset)
Andrew Jefferye3e3c972021-05-26 14:37:07 +093053{
54 if (bus < 0)
55 {
56 throw std::domain_error("Invalid bus argument");
57 }
58
59 /* bus + address + command */
60 uint32_t busle = htole32(static_cast<uint32_t>(bus));
61 auto command =
62 std::make_shared<std::array<uint8_t, sizeof(busle) + 1 + 1>>();
63 memcpy(command->data(), &busle, sizeof(busle));
64 (*command)[sizeof(busle) + 0] = device;
65 (*command)[sizeof(busle) + 1] = offset;
66
67 return command;
68}
69
70static void decodeBasicQuery(const std::array<uint8_t, 6>& req, int& bus,
71 uint8_t& device, uint8_t& offset)
72{
Ed Tanousa771f6a2022-01-14 09:36:51 -080073 uint32_t busle = 0;
Andrew Jefferye3e3c972021-05-26 14:37:07 +093074
75 memcpy(&busle, req.data(), sizeof(busle));
76 bus = le32toh(busle);
77 device = req[sizeof(busle) + 0];
78 offset = req[sizeof(busle) + 1];
79}
80
Andrew Jeffery1a143022022-07-19 14:18:24 +093081static void execBasicQuery(int bus, uint8_t addr, uint8_t cmd,
82 std::vector<uint8_t>& resp)
Andrew Jefferye3e3c972021-05-26 14:37:07 +093083{
Ed Tanousa771f6a2022-01-14 09:36:51 -080084 int32_t size = 0;
Ed Tanous73030632022-01-14 10:09:47 -080085 std::filesystem::path devpath = "/dev/i2c-" + std::to_string(bus);
Andrew Jefferye3e3c972021-05-26 14:37:07 +093086
chaul.ampere0fe02292022-07-21 06:37:39 +000087 try
Andrew Jefferye3e3c972021-05-26 14:37:07 +093088 {
chaul.ampere0fe02292022-07-21 06:37:39 +000089 FileHandle fileHandle(devpath);
90
91 /* Select the target device */
92 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
93 if (::ioctl(fileHandle.handle(), I2C_SLAVE, addr) == -1)
94 {
George Liu7201be42025-02-20 20:01:54 +080095 lg2::error(
96 "Failed to configure device address '{ADDR}' for bus '{BUS}': ERRNO",
97 "ADDR", lg2::hex, addr, "BUS", bus, "ERRNO", lg2::hex, errno);
chaul.ampere0fe02292022-07-21 06:37:39 +000098 resp.resize(0);
99 return;
100 }
101
102 resp.resize(UINT8_MAX + 1);
103
104 /* Issue the NVMe MI basic command */
105 size = i2c_smbus_read_block_data(fileHandle.handle(), cmd, resp.data());
106 if (size < 0)
107 {
George Liu7201be42025-02-20 20:01:54 +0800108 lg2::error(
109 "Failed to read block data from device '{ADDR}' on bus '{BUS}': ERRNO",
110 "ADDR", lg2::hex, addr, "BUS", bus, "ERRNO", lg2::hex, errno);
chaul.ampere0fe02292022-07-21 06:37:39 +0000111 resp.resize(0);
112 }
113 else if (size > UINT8_MAX + 1)
114 {
George Liu7201be42025-02-20 20:01:54 +0800115 lg2::error(
116 "Unexpected message length from device '{ADDR}' on bus '{BUS}': '{SIZE}' ({MAX})",
117 "ADDR", lg2::hex, addr, "BUS", bus, "SIZE", size, "MAX",
118 UINT8_MAX);
chaul.ampere0fe02292022-07-21 06:37:39 +0000119 resp.resize(0);
120 }
121 else
122 {
123 resp.resize(size);
124 }
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930125 }
chaul.ampere0fe02292022-07-21 06:37:39 +0000126 catch (const std::out_of_range& e)
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930127 {
George Liu7201be42025-02-20 20:01:54 +0800128 lg2::error("Failed to create file handle for bus '{BUS}': '{ERR}'",
129 "BUS", bus, "ERR", e);
Andrew Jeffery1a143022022-07-19 14:18:24 +0930130 resp.resize(0);
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930131 }
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930132}
133
Ed Tanous73030632022-01-14 10:09:47 -0800134static ssize_t processBasicQueryStream(FileHandle& in, FileHandle& out)
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930135{
136 std::vector<uint8_t> resp{};
Ed Tanousa771f6a2022-01-14 09:36:51 -0800137 ssize_t rc = 0;
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930138
139 while (true)
140 {
Ed Tanousa771f6a2022-01-14 09:36:51 -0800141 uint8_t device = 0;
142 uint8_t offset = 0;
143 uint8_t len = 0;
144 int bus = 0;
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930145
146 /* bus + address + command */
147 std::array<uint8_t, sizeof(uint32_t) + 1 + 1> req{};
148
149 /* Read the command parameters */
Ed Tanous73030632022-01-14 10:09:47 -0800150 ssize_t rc = ::read(in.handle(), req.data(), req.size());
151 if (rc != static_cast<ssize_t>(req.size()))
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930152 {
George Liu7201be42025-02-20 20:01:54 +0800153 lg2::error(
154 "Failed to read request from in descriptor '{ERROR_MESSAGE}'",
155 "ERROR_MESSAGE", strerror(errno));
Ed Tanous2049bd22022-07-09 07:20:26 -0700156 if (rc != 0)
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930157 {
Ed Tanous73030632022-01-14 10:09:47 -0800158 return -errno;
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930159 }
Ed Tanous73030632022-01-14 10:09:47 -0800160 return -EIO;
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930161 }
162
163 decodeBasicQuery(req, bus, device, offset);
164
165 /* Execute the query */
Andrew Jeffery1a143022022-07-19 14:18:24 +0930166 execBasicQuery(bus, device, offset, resp);
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930167
168 /* Write out the response length */
Andrew Jeffery1a143022022-07-19 14:18:24 +0930169 len = resp.size();
Ed Tanous73030632022-01-14 10:09:47 -0800170 rc = ::write(out.handle(), &len, sizeof(len));
171 if (rc != sizeof(len))
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930172 {
George Liu7201be42025-02-20 20:01:54 +0800173 lg2::error(
174 "Failed to write block ({LEN}) length to out descriptor: '{ERRNO}'",
175 "LEN", len, "ERRNO", strerror(static_cast<int>(-rc)));
Ed Tanous2049bd22022-07-09 07:20:26 -0700176 if (rc != 0)
Ed Tanous73030632022-01-14 10:09:47 -0800177 {
178 return -errno;
179 }
180 return -EIO;
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930181 }
182
183 /* Write out the response data */
Ed Tanous73030632022-01-14 10:09:47 -0800184 std::vector<uint8_t>::iterator cursor = resp.begin();
185 while (cursor != resp.end())
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930186 {
Ed Tanous73030632022-01-14 10:09:47 -0800187 size_t lenRemaining = std::distance(cursor, resp.end());
188 ssize_t egress = ::write(out.handle(), &(*cursor), lenRemaining);
Ed Tanousa771f6a2022-01-14 09:36:51 -0800189 if (egress == -1)
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930190 {
George Liu7201be42025-02-20 20:01:54 +0800191 lg2::error(
192 "Failed to write block data of length '{LEN}' to out pipe: '{ERROR_MESSAGE}'",
193 "LEN", lenRemaining, "ERROR_MESSAGE", strerror(errno));
Ed Tanous2049bd22022-07-09 07:20:26 -0700194 if (rc != 0)
Ed Tanous73030632022-01-14 10:09:47 -0800195 {
196 return -errno;
197 }
198 return -EIO;
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930199 }
200
201 cursor += egress;
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930202 }
203 }
204
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930205 return rc;
206}
207
208/* Throws std::error_code on failure */
209/* FIXME: Probably shouldn't do fallible stuff in a constructor */
Ed Tanous1f978632023-02-28 18:16:39 -0800210NVMeBasicContext::NVMeBasicContext(boost::asio::io_context& io, int rootBus) :
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930211 NVMeContext::NVMeContext(io, rootBus), io(io), reqStream(io), respStream(io)
212{
Ed Tanousa771f6a2022-01-14 09:36:51 -0800213 std::array<int, 2> responsePipe{};
214 std::array<int, 2> requestPipe{};
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930215
216 /* Set up inter-thread communication */
217 if (::pipe(requestPipe.data()) == -1)
218 {
George Liu7201be42025-02-20 20:01:54 +0800219 lg2::error("Failed to create request pipe: '{ERROR}'", "ERROR",
220 strerror(errno));
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930221 throw std::error_code(errno, std::system_category());
222 }
223
224 if (::pipe(responsePipe.data()) == -1)
225 {
George Liu7201be42025-02-20 20:01:54 +0800226 lg2::error("Failed to create response pipe: '{ERROR}'", "ERROR",
227 strerror(errno));
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930228
229 if (::close(requestPipe[0]) == -1)
230 {
George Liu7201be42025-02-20 20:01:54 +0800231 lg2::error("Failed to close write fd of request pipe '{ERROR}'",
232 "ERROR", strerror(errno));
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930233 }
234
235 if (::close(requestPipe[1]) == -1)
236 {
George Liu7201be42025-02-20 20:01:54 +0800237 lg2::error("Failed to close read fd of request pipe '{ERROR}'",
238 "ERROR", strerror(errno));
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930239 }
240
241 throw std::error_code(errno, std::system_category());
242 }
243
244 reqStream.assign(requestPipe[1]);
Ed Tanous73030632022-01-14 10:09:47 -0800245 FileHandle streamIn(requestPipe[0]);
246 FileHandle streamOut(responsePipe[1]);
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930247 respStream.assign(responsePipe[0]);
248
Andrew Jeffery3cbd5a12022-07-18 16:32:11 +0930249 thread = std::jthread([streamIn{std::move(streamIn)},
250 streamOut{std::move(streamOut)}]() mutable {
Ed Tanous72b39112024-04-03 18:35:24 -0700251 ssize_t rc = processBasicQueryStream(streamIn, streamOut);
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930252
Ed Tanous72b39112024-04-03 18:35:24 -0700253 if (rc < 0)
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930254 {
George Liu7201be42025-02-20 20:01:54 +0800255 lg2::error("Failure while processing query stream: '{ERROR}'",
256 "ERROR", strerror(static_cast<int>(-rc)));
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930257 }
258
George Liu7201be42025-02-20 20:01:54 +0800259 lg2::error("Terminating basic query thread");
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930260 });
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930261}
262
Andrew Jefferyb5d7a7f2022-05-02 11:57:03 +0930263void NVMeBasicContext::readAndProcessNVMeSensor()
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930264{
Andrew Jefferyb5d7a7f2022-05-02 11:57:03 +0930265 if (pollCursor == sensors.end())
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930266 {
Andrew Jeffery8c7074e2022-03-21 14:58:13 +1030267 this->pollNVMeDevices();
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930268 return;
269 }
270
Andrew Jefferyb5d7a7f2022-05-02 11:57:03 +0930271 std::shared_ptr<NVMeSensor> sensor = *pollCursor++;
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930272
Andrew Jeffery3859c7f2021-10-29 15:51:16 +1030273 if (!sensor->readingStateGood())
274 {
275 sensor->markAvailable(false);
276 sensor->updateValue(std::numeric_limits<double>::quiet_NaN());
Andrew Jefferyb5d7a7f2022-05-02 11:57:03 +0930277 readAndProcessNVMeSensor();
Andrew Jeffery3859c7f2021-10-29 15:51:16 +1030278 return;
279 }
280
Andrew Jeffery14108bb2022-03-21 15:00:16 +1030281 /* Potentially defer sampling the sensor sensor if it is in error */
282 if (!sensor->sample())
283 {
Andrew Jefferyb5d7a7f2022-05-02 11:57:03 +0930284 readAndProcessNVMeSensor();
Andrew Jeffery14108bb2022-03-21 15:00:16 +1030285 return;
286 }
287
Nnamdi Ajah06cd9882023-02-15 13:21:32 +0100288 auto command = encodeBasicQuery(sensor->bus, sensor->address, 0x00);
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930289
290 /* Issue the request */
291 boost::asio::async_write(
292 reqStream, boost::asio::buffer(command->data(), command->size()),
Ed Tanous76b2bc72022-02-18 09:48:16 -0800293 [command](boost::system::error_code ec, std::size_t) {
Patrick Williams2aaf7172024-08-16 15:20:40 -0400294 if (ec)
295 {
George Liu7201be42025-02-20 20:01:54 +0800296 lg2::error("Got error writing basic query: '{ERROR_MESSAGE}'",
297 "ERROR_MESSAGE", ec.message());
Patrick Williams2aaf7172024-08-16 15:20:40 -0400298 }
299 });
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930300
Andrew Jeffery84c16872022-03-15 21:50:59 +1030301 auto response = std::make_shared<boost::asio::streambuf>();
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930302 response->prepare(1);
303
304 /* Gather the response and dispatch for parsing */
305 boost::asio::async_read(
306 respStream, *response,
307 [response](const boost::system::error_code& ec, std::size_t n) {
Patrick Williams2aaf7172024-08-16 15:20:40 -0400308 if (ec)
309 {
George Liu7201be42025-02-20 20:01:54 +0800310 lg2::error(
311 "Got error completing basic query: '{ERROR_MESSAGE}'",
312 "ERROR_MESSAGE", ec.message());
Patrick Williams2aaf7172024-08-16 15:20:40 -0400313 return static_cast<std::size_t>(0);
314 }
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930315
Patrick Williams2aaf7172024-08-16 15:20:40 -0400316 if (n == 0)
317 {
318 return static_cast<std::size_t>(1);
319 }
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930320
Patrick Williams2aaf7172024-08-16 15:20:40 -0400321 std::istream is(response.get());
322 size_t len = static_cast<std::size_t>(is.peek());
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930323
Patrick Williams2aaf7172024-08-16 15:20:40 -0400324 if (n > len + 1)
325 {
George Liu7201be42025-02-20 20:01:54 +0800326 lg2::error(
327 "Query stream has become unsynchronised: n: {N}, len: {LEN}",
328 "N", n, "LEN", len);
Patrick Williams2aaf7172024-08-16 15:20:40 -0400329 return static_cast<std::size_t>(0);
330 }
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930331
Patrick Williams2aaf7172024-08-16 15:20:40 -0400332 if (n == len + 1)
333 {
334 return static_cast<std::size_t>(0);
335 }
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930336
Patrick Williams2aaf7172024-08-16 15:20:40 -0400337 if (n > 1)
338 {
339 return len + 1 - n;
340 }
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930341
Patrick Williams2aaf7172024-08-16 15:20:40 -0400342 response->prepare(len);
343 return len;
344 },
Andrew Jeffery3cbd5a12022-07-18 16:32:11 +0930345 [weakSelf{weak_from_this()}, sensor, response](
Andrew Jeffery8c7074e2022-03-21 14:58:13 +1030346 const boost::system::error_code& ec, std::size_t length) mutable {
Patrick Williams2aaf7172024-08-16 15:20:40 -0400347 if (ec)
348 {
George Liu7201be42025-02-20 20:01:54 +0800349 lg2::error("Got error reading basic query: '{ERROR_MESSAGE}'",
350 "ERROR_MESSAGE", ec.message());
Patrick Williams2aaf7172024-08-16 15:20:40 -0400351 return;
352 }
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930353
Patrick Williams2aaf7172024-08-16 15:20:40 -0400354 if (length == 0)
355 {
George Liu7201be42025-02-20 20:01:54 +0800356 lg2::error("Invalid message length: '{LEN}'", "LEN", length);
Patrick Williams2aaf7172024-08-16 15:20:40 -0400357 return;
358 }
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930359
Patrick Williams2aaf7172024-08-16 15:20:40 -0400360 if (auto self = weakSelf.lock())
361 {
362 /* Deserialise the response */
363 response->consume(1); /* Drop the length byte */
364 std::istream is(response.get());
365 std::vector<char> data(response->size());
366 is.read(data.data(), response->size());
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930367
Patrick Williams2aaf7172024-08-16 15:20:40 -0400368 /* Update the sensor */
369 self->processResponse(sensor, data.data(), data.size());
Andrew Jeffery8c7074e2022-03-21 14:58:13 +1030370
Patrick Williams2aaf7172024-08-16 15:20:40 -0400371 /* Enqueue processing of the next sensor */
372 self->readAndProcessNVMeSensor();
373 }
374 });
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930375}
376
377void NVMeBasicContext::pollNVMeDevices()
378{
Andrew Jefferyb5d7a7f2022-05-02 11:57:03 +0930379 pollCursor = sensors.begin();
Andrew Jeffery8c7074e2022-03-21 14:58:13 +1030380
Ed Tanous83db50c2023-03-01 10:20:24 -0800381 scanTimer.expires_after(std::chrono::seconds(1));
Andrew Jeffery3cbd5a12022-07-18 16:32:11 +0930382 scanTimer.async_wait([weakSelf{weak_from_this()}](
383 const boost::system::error_code errorCode) {
Ed Tanousbb679322022-05-16 16:10:00 -0700384 if (errorCode == boost::asio::error::operation_aborted)
385 {
386 return;
387 }
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930388
Ed Tanousbb679322022-05-16 16:10:00 -0700389 if (errorCode)
390 {
George Liu7201be42025-02-20 20:01:54 +0800391 lg2::error("error code: '{ERROR_MESSAGE}'", "ERROR_MESSAGE",
392 errorCode.message());
Ed Tanousbb679322022-05-16 16:10:00 -0700393 return;
394 }
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930395
Andrew Jeffery3cbd5a12022-07-18 16:32:11 +0930396 if (auto self = weakSelf.lock())
397 {
398 self->readAndProcessNVMeSensor();
399 }
Ed Tanousbb679322022-05-16 16:10:00 -0700400 });
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930401}
402
403static double getTemperatureReading(int8_t reading)
404{
405 if (reading == static_cast<int8_t>(0x80) ||
406 reading == static_cast<int8_t>(0x81))
407 {
408 // 0x80 = No temperature data or temperature data is more the 5 s
409 // old 0x81 = Temperature sensor failure
410 return std::numeric_limits<double>::quiet_NaN();
411 }
412
413 return reading;
414}
415
Andrew Jeffery8c7074e2022-03-21 14:58:13 +1030416void NVMeBasicContext::processResponse(std::shared_ptr<NVMeSensor>& sensor,
417 void* msg, size_t len)
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930418{
Andrew Jeffery14108bb2022-03-21 15:00:16 +1030419 if (msg == nullptr || len < 6)
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930420 {
Andrew Jeffery14108bb2022-03-21 15:00:16 +1030421 sensor->incrementError();
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930422 return;
423 }
424
425 uint8_t* messageData = static_cast<uint8_t*>(msg);
Andrew Jeffery7aeb1a52022-03-15 22:49:04 +1030426
427 uint8_t status = messageData[0];
Ed Tanous2049bd22022-07-09 07:20:26 -0700428 if (((status & NVME_MI_BASIC_SFLGS_DRIVE_NOT_READY) != 0) ||
429 ((status & NVME_MI_BASIC_SFLGS_DRIVE_FUNCTIONAL) == 0))
Andrew Jeffery7aeb1a52022-03-15 22:49:04 +1030430 {
431 sensor->markFunctional(false);
432 return;
433 }
434
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930435 double value = getTemperatureReading(messageData[2]);
Andrew Jeffery14108bb2022-03-21 15:00:16 +1030436 if (!std::isfinite(value))
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930437 {
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930438 sensor->incrementError();
Andrew Jeffery14108bb2022-03-21 15:00:16 +1030439 return;
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930440 }
Andrew Jeffery14108bb2022-03-21 15:00:16 +1030441
442 sensor->updateValue(value);
Andrew Jefferye3e3c972021-05-26 14:37:07 +0930443}