]> www.infradead.org Git - users/sagi/libnvme.git/commitdiff
mi: use lpo and numd to chunk big get log page command
authorJinliang Wang <jinliangw@google.com>
Thu, 1 Dec 2022 07:25:05 +0000 (23:25 -0800)
committerJinliang Wang <jinliangw@google.com>
Thu, 1 Dec 2022 07:25:05 +0000 (23:25 -0800)
1) Change log page offset inside `__nvme_mi_admin_get_log`
   We use LPO and NUMD to chunk get log page request whose length
   is greater than 4KB. This method works better for some of current
   devices.
2) Update `test_admin_get_log_split_cb`.

Signed-off-by: Jinliang Wang <jinliangw@google.com>
src/nvme/mi.c
test/mi.c

index 779dbf6d2b7b3364ab0f0b1cc10371cdbdab5708..f55f2d471285e6510ff6fc6ab66bfebb229e5479 100644 (file)
@@ -772,11 +772,19 @@ int nvme_mi_admin_identify_partial(nvme_mi_ctrl_t ctrl,
 }
 
 /* retrieves a MCTP-messsage-sized chunk of log page data. offset and len are
- * specified within the args->data area */
+ * specified within the args->data area. The `offset` parameter is a relative
+ * offset to the args->lpo !
+ *
+ * What's more, we change the LPO of original command to chunk the request
+ * message into proper size which is allowed by MI interface. One reason is that
+ * this option seems to be supported better by devices.  For more information
+ * about this option, please check https://github.com/linux-nvme/libnvme/pull/539
+ * */
 static int __nvme_mi_admin_get_log(nvme_mi_ctrl_t ctrl,
                                   const struct nvme_get_log_args *args,
                                   off_t offset, size_t *lenp, bool final)
 {
+       __u64 log_page_offset = args->lpo + offset;
        struct nvme_mi_admin_resp_hdr resp_hdr;
        struct nvme_mi_admin_req_hdr req_hdr;
        struct nvme_mi_resp resp;
@@ -808,17 +816,13 @@ static int __nvme_mi_admin_get_log(nvme_mi_ctrl_t ctrl,
                                    (args->lid & 0xff));
        req_hdr.cdw11 = cpu_to_le32(args->lsi << 16 |
                                    ndw >> 16);
-       req_hdr.cdw12 = cpu_to_le32(args->lpo & 0xffffffff);
-       req_hdr.cdw13 = cpu_to_le32(args->lpo >> 32);
+       req_hdr.cdw12 = cpu_to_le32(log_page_offset & 0xffffffff);
+       req_hdr.cdw13 = cpu_to_le32(log_page_offset >> 32);
        req_hdr.cdw14 = cpu_to_le32(args->csi << 24 |
                                    (args->ot ? 1 : 0) << 23 |
                                    args->uuidx);
        req_hdr.flags = 0x1;
        req_hdr.dlen = cpu_to_le32(len & 0xffffffff);
-       if (offset) {
-               req_hdr.flags |= 0x2;
-               req_hdr.doff = cpu_to_le32(offset);
-       }
 
        nvme_mi_calc_req_mic(&req);
 
@@ -848,6 +852,11 @@ int nvme_mi_admin_get_log(nvme_mi_ctrl_t ctrl, struct nvme_get_log_args *args)
                return -1;
        }
 
+       if (args->ot && (args->len > max_xfer_size)) {
+               errno = EINVAL;
+               return -1;
+       }
+
        for (xfer_offset = 0; xfer_offset < args->len;) {
                size_t xfered_size, cur_xfer_size = max_xfer_size;
                bool final;
index 4c7f1f250028e0bee40ee45ce48625b42b2962e5..d945bed8994daf56db2f441dcfca68bd0345e1e8 100644 (file)
--- a/test/mi.c
+++ b/test/mi.c
@@ -1776,6 +1776,7 @@ static int test_admin_get_log_split_cb(struct nvme_mi_ep *ep,
                                       struct nvme_mi_resp *resp,
                                       void *data)
 {
+       uint32_t log_page_offset_lower;
        struct log_data *ldata = data;
        uint32_t len, off;
        __u8 *rq_hdr;
@@ -1790,19 +1791,25 @@ static int test_admin_get_log_split_cb(struct nvme_mi_ep *ep,
        off = rq_hdr[31] << 24 | rq_hdr[30] << 16 | rq_hdr[29] << 8 | rq_hdr[28];
        len = rq_hdr[35] << 24 | rq_hdr[34] << 16 | rq_hdr[33] << 8 | rq_hdr[32];
 
+       /* From the MI message's Command Dword 12 */
+       log_page_offset_lower = rq_hdr[55] << 24 | rq_hdr[54] << 16 | rq_hdr[53] << 8 | rq_hdr[52];
+
        /* we should have a full-sized start and middle, and a short end */
        switch (ldata->n) {
        case 0:
+               assert(log_page_offset_lower == 0);
                assert(len == 4096);
                assert(off == 0);
                break;
        case 1:
+               assert(log_page_offset_lower == 4096);
                assert(len == 4096);
-               assert(off == 4096);
+               assert(off == 0);
                break;
        case 2:
+               assert(log_page_offset_lower == 8192);
                assert(len == 4);
-               assert(off == 4096 * 2);
+               assert(off == 0);
                break;
        default:
                assert(0);
@@ -1836,6 +1843,8 @@ static void test_admin_get_log_split(struct nvme_mi_ep *ep)
        args.lid = 1;
        args.log = buf;
        args.len = sizeof(buf);
+       args.lpo = 0;
+       args.ot = false;
 
        rc = nvme_mi_admin_get_log(ctrl, &args);