2525#include <stdio.h>
2626#include <unistd.h>
2727#include <inttypes.h>
28+ #include <errno.h>
2829#include "nvme-device.h"
2930#include "switchtec-nvme-device.h"
3031
3132#include <switchtec/switchtec.h>
3233#include <switchtec/fabric.h>
3334#include <switchtec/mrpc.h>
35+ #include <switchtec/errors.h>
36+
37+ #define INVALID_MRPC_CMD (SWITCHTEC_ERRNO_MRPC_FLAG_BIT | ERR_CMD_INVALID)
3438
3539struct switchtec_device_manage_nvme_req
3640{
@@ -48,15 +52,26 @@ struct switchtec_device_manage_nvme_rsp
4852 uint8_t nvme_data [SWITCHTEC_DEVICE_MANAGE_MAX_RESP - (4 * 4 )];
4953};
5054
55+ struct switchtec_admin_passthru_nvme_req {
56+ uint32_t nvme_sqe [16 ];
57+ uint8_t nvme_data [SWITCHTEC_NVME_ADMIN_PASSTHRU_MAX_DATA_LEN -
58+ (16 * 4 )];
59+ };
5160
52- int pax_nvme_submit_admin_passthru (int fd , struct nvme_passthru_cmd * cmd )
61+ struct switchtec_admin_passthru_nvme_rsp {
62+ uint32_t nvme_cqe [4 ];
63+ uint8_t nvme_data [4096 ];
64+ };
65+
66+ int pax_nvme_submit_admin_passthru_1k_rsp (int fd ,
67+ struct nvme_passthru_cmd * cmd )
5368{
5469 int ret ;
5570
5671 struct pax_nvme_device * pax ;
5772 struct switchtec_device_manage_nvme_req req ;
5873 struct switchtec_device_manage_nvme_rsp rsp ;
59- int data_len ;
74+ size_t data_len = 0 ;
6075 int status ;
6176
6277 memset (& req , 0 , sizeof (req ));
@@ -69,23 +84,22 @@ int pax_nvme_submit_admin_passthru(int fd, struct nvme_passthru_cmd *cmd)
6984 /* sqe[9] should be 0 per spec */
7085 req .nvme_sqe [9 ] = 0 ;
7186
72- if (cmd -> data_len > sizeof (req .nvme_data ))
73- data_len = sizeof (req .nvme_data );
74- else
75- data_len = cmd -> data_len ;
87+ if (cmd -> opcode & 0x1 ) {
88+ if (cmd -> data_len > sizeof (req .nvme_data ))
89+ data_len = sizeof (req .nvme_data );
90+ else
91+ data_len = cmd -> data_len ;
7692
77- memcpy (req .nvme_data , (void * )cmd -> addr , data_len );
93+ memcpy (req .nvme_data , (void * )cmd -> addr , data_len );
94+ }
7895
7996 req .hdr .expected_rsp_len = (sizeof (rsp .nvme_cqe ) + sizeof (rsp .nvme_data ));
8097
8198 ret = switchtec_device_manage (pax -> dev ,
8299 (struct switchtec_device_manage_req * )& req ,
83100 (struct switchtec_device_manage_rsp * )& rsp );
84-
85- if (ret ) {
86- switchtec_perror ("device_manage_cmd" );
101+ if (ret )
87102 return ret ;
88- }
89103
90104 status = (rsp .nvme_cqe [3 ] & 0xfffe0000 ) >> 17 ;
91105 if (!status ) {
@@ -100,6 +114,70 @@ int pax_nvme_submit_admin_passthru(int fd, struct nvme_passthru_cmd *cmd)
100114 return status ;
101115}
102116
117+ int pax_nvme_submit_admin_passthru_4k_rsp (int fd ,
118+ struct nvme_passthru_cmd * cmd )
119+ {
120+ int ret ;
121+
122+ struct pax_nvme_device * pax ;
123+ struct switchtec_admin_passthru_nvme_req req ;
124+ struct switchtec_admin_passthru_nvme_rsp rsp ;
125+ size_t data_len = 0 ;
126+ size_t rsp_len ;
127+ int status ;
128+
129+ memset (& req , 0 , sizeof (req ));
130+ memset (& rsp , 0 , sizeof (rsp ));
131+ pax = to_pax_nvme_device (global_device );
132+
133+ memcpy (& req .nvme_sqe , cmd , 16 * 4 );
134+
135+ /* sqe[9] should be 0 per spec */
136+ req .nvme_sqe [9 ] = 0 ;
137+
138+ if (cmd -> opcode & 0x1 ) {
139+ if (cmd -> data_len > sizeof (req .nvme_data ))
140+ data_len = sizeof (req .nvme_data );
141+ else
142+ data_len = cmd -> data_len ;
143+
144+ memcpy (req .nvme_data , (void * )cmd -> addr , data_len );
145+ }
146+
147+ data_len = data_len + 16 * 4 ;
148+
149+ rsp_len = (sizeof (rsp .nvme_cqe ) + cmd -> data_len );
150+
151+ ret = switchtec_nvme_admin_passthru (pax -> dev , pax -> pdfid ,
152+ data_len , & req ,
153+ & rsp_len , & rsp );
154+ if (ret )
155+ return ret ;
156+
157+ status = (rsp .nvme_cqe [3 ] & 0xfffe0000 ) >> 17 ;
158+ if (!status ) {
159+ cmd -> result = rsp .nvme_cqe [0 ];
160+ if (cmd -> addr ) {
161+ memcpy ((uint64_t * )cmd -> addr ,
162+ rsp .nvme_data ,
163+ rsp_len - 4 * 4 );
164+ }
165+ }
166+
167+ return status ;
168+ }
169+
170+ int pax_nvme_submit_admin_passthru (int fd , struct nvme_passthru_cmd * cmd )
171+ {
172+ int ret ;
173+
174+ ret = pax_nvme_submit_admin_passthru_4k_rsp (fd , cmd );
175+ if (ret && errno == INVALID_MRPC_CMD )
176+ ret = pax_nvme_submit_admin_passthru_1k_rsp (fd , cmd );
177+
178+ return ret ;
179+ }
180+
103181int pax_nvme_io (int fd , struct nvme_user_io * io )
104182{
105183 fprintf (stderr , "%s not implemented.\n" , __FUNCTION__ );
@@ -126,8 +204,13 @@ int pax_nvme_ns_rescan(int fd)
126204
127205int pax_nvme_submit_passthru (int fd , int ioctl_cmd , struct nvme_passthru_cmd * cmd )
128206{
129- fprintf (stderr , "%s not implemented.\n" , __FUNCTION__ );
130- return -1 ;
207+ if (ioctl_cmd != (int )NVME_IOCTL_ADMIN_CMD ) {
208+ fprintf (stderr , "%s only supports NVME_IOCTL_ADMIN_CMD.\n" ,
209+ __FUNCTION__ );
210+ return -1 ;
211+ }
212+
213+ return pax_nvme_submit_admin_passthru (fd , cmd );
131214}
132215
133216int pax_nvme_submit_io_passthru (int fd , struct nvme_passthru_cmd * cmd )
0 commit comments