Skip to content

Commit 0d4a1a3

Browse files
committed
mi: Add Admin channel Get Log Page command
This change add support for the Get Log Page command over the MI Admin channel: int nvme_mi_admin_get_log_page(nvme_mi_ctrl_t ctrl, struct nvme_get_log_args *args) Since the log data can be large, we implement this as chunked transfers of >4096 bytes. Signed-off-by: Jeremy Kerr <[email protected]>
1 parent 9237ba8 commit 0d4a1a3

3 files changed

Lines changed: 117 additions & 0 deletions

File tree

src/libnvme-mi.map

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ LIBNVME_MI_1_1 {
1111
nvme_mi_mi_read_mi_data_ctrl;
1212
nvme_mi_mi_subsystem_health_status_poll;
1313
nvme_mi_admin_identify_partial;
14+
nvme_mi_admin_get_log_page;
1415
nvme_mi_open_mctp;
1516
local:
1617
*;

src/nvme/mi.c

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,108 @@ int nvme_mi_admin_identify_partial(nvme_mi_ctrl_t ctrl,
196196
return 0;
197197
}
198198

199+
/* retrieves a MCTP-messsage-sized chunk of log page data. offset and len are
200+
* specified within the args->data area */
201+
static int __nvme_mi_admin_get_log_page(nvme_mi_ctrl_t ctrl,
202+
const struct nvme_get_log_args *args,
203+
off_t offset, size_t *lenp, bool final)
204+
{
205+
struct nvme_mi_admin_resp_hdr resp_hdr;
206+
struct nvme_mi_admin_req_hdr req_hdr;
207+
struct nvme_mi_resp resp;
208+
struct nvme_mi_req req;
209+
size_t len;
210+
__u32 ndw;
211+
int rc;
212+
213+
/* MI spec requires that the data length field is less than or equal
214+
* to 4096 */
215+
len = *lenp;
216+
if (!len || len > 4096 || len < 4)
217+
return -EINVAL;
218+
219+
if (offset < 0 || offset >= len)
220+
return -EINVAL;
221+
222+
ndw = (len >> 2) - 1;
223+
224+
nvme_mi_admin_init_req(&req, &req_hdr, ctrl->id, nvme_admin_get_log_page);
225+
req_hdr.cdw1 = cpu_to_le32(args->nsid);
226+
req_hdr.cdw10 = cpu_to_le32((ndw & 0xffff) << 16 |
227+
((!final || args->rae) ? 1 : 0) << 15 |
228+
args->lsp << 8 |
229+
(args->lid & 0xff));
230+
req_hdr.cdw11 = cpu_to_le32(args->lsi << 16 |
231+
ndw >> 16);
232+
req_hdr.cdw12 = cpu_to_le32(args->lpo & 0xffffffff);
233+
req_hdr.cdw13 = cpu_to_le32(args->lpo >> 32);
234+
req_hdr.cdw14 = cpu_to_le32(args->csi << 24 |
235+
(args->ot ? 1 : 0) << 23 |
236+
args->uuidx);
237+
req_hdr.flags = 0x1;
238+
req_hdr.dlen = cpu_to_le32(len & 0xffffffff);
239+
if (offset) {
240+
req_hdr.flags |= 0x2;
241+
req_hdr.doff = cpu_to_le32(offset);
242+
}
243+
244+
nvme_mi_calc_req_mic(&req);
245+
246+
nvme_mi_admin_init_resp(&resp, &resp_hdr);
247+
resp.data = args->log + offset;
248+
resp.data_len = len;
249+
250+
rc = nvme_mi_submit(ctrl->ep, &req, &resp);
251+
if (rc)
252+
return rc;
253+
254+
if (resp_hdr.status)
255+
return resp_hdr.status;
256+
257+
*lenp = resp.data_len;
258+
259+
return 0;
260+
}
261+
262+
int nvme_mi_admin_get_log_page(nvme_mi_ctrl_t ctrl,
263+
struct nvme_get_log_args *args)
264+
{
265+
const size_t xfer_size = 4096;
266+
off_t xfer_offset;
267+
int rc = 0;
268+
269+
if (args->args_size < sizeof(*args))
270+
return -EINVAL;
271+
272+
for (xfer_offset = 0; xfer_offset < args->len;) {
273+
size_t tmp, cur_xfer_size = xfer_size;
274+
bool final;
275+
276+
if (xfer_offset + cur_xfer_size > args->len)
277+
cur_xfer_size = args->len - xfer_offset;
278+
279+
tmp = cur_xfer_size;
280+
281+
final = xfer_offset + cur_xfer_size >= args->len;
282+
283+
rc = __nvme_mi_admin_get_log_page(ctrl, args, xfer_offset,
284+
&tmp, final);
285+
if (rc)
286+
break;
287+
288+
xfer_offset += tmp;
289+
/* if we returned less data than expected, consider that
290+
* the end of the log page */
291+
if (tmp != cur_xfer_size)
292+
break;
293+
}
294+
295+
if (!rc)
296+
args->len = xfer_offset;
297+
298+
return rc;
299+
}
300+
199301
static int nvme_mi_read_data(nvme_mi_ep_t ep, __u32 cdw0,
200302
void *data, size_t *data_len)
201303
{

src/nvme/mi.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,4 +181,18 @@ static inline int nvme_mi_admin_identify_ctrl_list(nvme_mi_ctrl_t ctrl,
181181
return nvme_mi_admin_identify(ctrl, &args);
182182
}
183183

184+
/**
185+
* Retreives log page data as specified by @args. On return, @args->len is
186+
* updated to the amount of log data written to @args->log.
187+
*
188+
* This request may be implemented as multiple log page commands, in order
189+
* to fit within MI message-size limits.
190+
*
191+
* @ctrl: MI controller
192+
* @args: Log page request parameters
193+
*/
194+
int nvme_mi_admin_get_log_page(nvme_mi_ctrl_t ctrl,
195+
struct nvme_get_log_args *args);
196+
197+
184198
#endif /* _LIBNVME_MI_MI_H */

0 commit comments

Comments
 (0)