Skip to content

Commit 178fdf6

Browse files
committed
mi: Add initial Admin channel commands
This change adds Admin Channel commands, and the first admin channel command to the MI transport: Identify. The admin functions have the nvme_mi_admin_ prefix. For this, we need a couple of definitions for Admin-Channel-over-MI serialisation, and add individual admin commands using those. Signed-off-by: Jeremy Kerr <[email protected]>
1 parent 31ddc5a commit 178fdf6

3 files changed

Lines changed: 130 additions & 0 deletions

File tree

src/libnvme-mi.map

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ LIBNVME_MI_1_1 {
1010
nvme_mi_mi_read_mi_data_ctrl_list;
1111
nvme_mi_mi_read_mi_data_ctrl;
1212
nvme_mi_mi_subsystem_health_status_poll;
13+
nvme_mi_admin_identify_ctrl;
14+
nvme_mi_admin_identify_ctrl_partial;
15+
nvme_mi_admin_identify_ctrl_list;
1316
nvme_mi_open_mctp;
1417
local:
1518
*;

src/nvme/mi.c

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,104 @@ int nvme_mi_submit(nvme_mi_ep_t ep, struct nvme_mi_req *req,
121121
return 0;
122122
}
123123

124+
static void nvme_mi_admin_init_req(struct nvme_mi_req *req,
125+
struct nvme_mi_admin_req_hdr *hdr,
126+
__u16 ctrl_id, __u8 opcode)
127+
{
128+
memset(req, 0, sizeof(*req));
129+
memset(hdr, 0, sizeof(*hdr));
130+
131+
hdr->hdr.type = NVME_MI_MSGTYPE_NVME;
132+
hdr->hdr.nmp = (NVME_MI_ROR_REQ << 7) |
133+
(NVME_MI_MT_ADMIN << 3); /* we always use command slot 0 */
134+
hdr->opcode = opcode;
135+
hdr->ctrl_id = cpu_to_le16(ctrl_id);
136+
137+
req->hdr = &hdr->hdr;
138+
req->hdr_len = sizeof(*hdr);
139+
}
140+
141+
static void nvme_mi_admin_init_resp(struct nvme_mi_resp *resp,
142+
struct nvme_mi_admin_resp_hdr *hdr)
143+
{
144+
memset(resp, 0, sizeof(*resp));
145+
resp->hdr = &hdr->hdr;
146+
resp->hdr_len = sizeof(*hdr);
147+
}
148+
149+
static int nvme_mi_admin_identify(nvme_mi_ctrl_t ctrl,
150+
enum nvme_identify_cns cns,
151+
__u16 cid, __u16 nsid, void *id,
152+
off_t offset, size_t size)
153+
{
154+
struct nvme_mi_admin_resp_hdr resp_hdr;
155+
struct nvme_mi_admin_req_hdr req_hdr;
156+
struct nvme_mi_resp resp;
157+
struct nvme_mi_req req;
158+
int rc;
159+
160+
if (!size || size > 0xffffffff)
161+
return -EINVAL;
162+
163+
nvme_mi_admin_init_req(&req, &req_hdr, ctrl->id, nvme_admin_identify);
164+
req_hdr.cdw10 = cpu_to_le16(cid) << 16 | cpu_to_le16(cns);
165+
req_hdr.cdw11 = cpu_to_le16(nsid);
166+
req_hdr.dlen = cpu_to_le32(size & 0xffffffff);
167+
req_hdr.flags = 0x1;
168+
if (offset) {
169+
req_hdr.flags |= 0x2;
170+
req_hdr.doff = offset;
171+
}
172+
173+
nvme_mi_calc_req_mic(&req);
174+
175+
nvme_mi_admin_init_resp(&resp, &resp_hdr);
176+
resp.data = id;
177+
resp.data_len = size;
178+
179+
rc = nvme_mi_submit(ctrl->ep, &req, &resp);
180+
if (rc)
181+
return rc;
182+
183+
/* check status, map to return value */
184+
185+
return 0;
186+
}
187+
188+
int nvme_mi_admin_identify_ctrl(nvme_mi_ctrl_t ctrl,
189+
struct nvme_id_ctrl *id)
190+
{
191+
return nvme_mi_admin_identify(ctrl, NVME_IDENTIFY_CNS_CTRL,
192+
0, 0, id, 0, sizeof(*id));
193+
}
194+
195+
int nvme_mi_admin_identify_ctrl_partial(nvme_mi_ctrl_t ctrl,
196+
struct nvme_id_ctrl *id,
197+
off_t offset, size_t size)
198+
{
199+
void *buf;
200+
201+
if (offset > sizeof(*id))
202+
return -EINVAL;
203+
if (size > sizeof(*id))
204+
return -EINVAL;
205+
if (offset + size > sizeof(*id))
206+
return -EINVAL;
207+
208+
buf = id;
209+
buf += offset;
210+
211+
return nvme_mi_admin_identify(ctrl, NVME_IDENTIFY_CNS_CTRL,
212+
0, 0, buf, offset, size);
213+
}
214+
215+
int nvme_mi_admin_identify_ctrl_list(nvme_mi_ctrl_t ctrl,
216+
struct nvme_ctrl_list *ctrllist)
217+
{
218+
return nvme_mi_admin_identify(ctrl, NVME_IDENTIFY_CNS_CTRL_LIST,
219+
0, 0, ctrllist, 0, sizeof(*ctrllist));
220+
}
221+
124222
static int nvme_mi_read_data(nvme_mi_ep_t ep, __u32 cdw0,
125223
void *data, size_t *data_len)
126224
{

src/nvme/mi.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,27 @@ enum nvme_mi_dtyp {
6868
nvme_mi_dtyp_meb_support = 0x05,
6969
};
7070

71+
/* Admin command definitions */
72+
73+
struct nvme_mi_admin_req_hdr {
74+
struct nvme_mi_msg_hdr hdr;
75+
__u8 opcode;
76+
__u8 flags;
77+
__le16 ctrl_id;
78+
__le32 cdw1, cdw2, cdw3, cdw4, cdw5;
79+
__le32 doff;
80+
__le32 dlen;
81+
__le32 rsvd0, rsvd1;
82+
__le32 cdw10, cdw11, cdw12, cdw13, cdw14, cdw15;
83+
} __attribute((packed));
84+
85+
struct nvme_mi_admin_resp_hdr {
86+
struct nvme_mi_msg_hdr hdr;
87+
__u8 status;
88+
__u8 rsvd0[3];
89+
__le32 cdw0, cdw1, cdw3;
90+
} __attribute__((packed));
91+
7192
/* MI Command API */
7293

7394
/* library-level API object */
@@ -102,5 +123,13 @@ int nvme_mi_mi_read_mi_data_ctrl(nvme_mi_ep_t ep, __u16 ctrl_id,
102123
int nvme_mi_mi_subsystem_health_status_poll(nvme_mi_ep_t ep, bool clear,
103124
struct nvme_mi_nvm_ss_health_status *nshds);
104125

126+
/* Admin channel functions */
127+
int nvme_mi_admin_identify_ctrl(nvme_mi_ctrl_t ctrl,
128+
struct nvme_id_ctrl *id);
129+
int nvme_mi_admin_identify_ctrl_partial(nvme_mi_ctrl_t ctrl,
130+
struct nvme_id_ctrl *id,
131+
off_t offset, size_t size);
132+
int nvme_mi_admin_identify_ctrl_list(nvme_mi_ctrl_t ctrl,
133+
struct nvme_ctrl_list *ctrllist);
105134

106135
#endif /* _LIBNVME_MI_MI_H */

0 commit comments

Comments
 (0)