nvme.h 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /* SPDX-License-Identifier: MIT */
  2. /*
  3. * Description: Helpers for NVMe uring passthrough commands
  4. */
  5. #ifndef LIBURING_NVME_H
  6. #define LIBURING_NVME_H
  7. #ifdef __cplusplus
  8. extern "C" {
  9. #endif
  10. #include <sys/ioctl.h>
  11. #include <linux/nvme_ioctl.h>
  12. /*
  13. * If the uapi headers installed on the system lacks nvme uring command
  14. * support, use the local version to prevent compilation issues.
  15. */
  16. #ifndef CONFIG_HAVE_NVME_URING
  17. struct nvme_uring_cmd {
  18. __u8 opcode;
  19. __u8 flags;
  20. __u16 rsvd1;
  21. __u32 nsid;
  22. __u32 cdw2;
  23. __u32 cdw3;
  24. __u64 metadata;
  25. __u64 addr;
  26. __u32 metadata_len;
  27. __u32 data_len;
  28. __u32 cdw10;
  29. __u32 cdw11;
  30. __u32 cdw12;
  31. __u32 cdw13;
  32. __u32 cdw14;
  33. __u32 cdw15;
  34. __u32 timeout_ms;
  35. __u32 rsvd2;
  36. };
  37. #define NVME_URING_CMD_IO _IOWR('N', 0x80, struct nvme_uring_cmd)
  38. #define NVME_URING_CMD_IO_VEC _IOWR('N', 0x81, struct nvme_uring_cmd)
  39. #endif /* CONFIG_HAVE_NVME_URING */
  40. #define NVME_DEFAULT_IOCTL_TIMEOUT 0
  41. #define NVME_IDENTIFY_DATA_SIZE 4096
  42. #define NVME_IDENTIFY_CSI_SHIFT 24
  43. #define NVME_IDENTIFY_CNS_NS 0
  44. #define NVME_CSI_NVM 0
  45. enum nvme_admin_opcode {
  46. nvme_admin_identify = 0x06,
  47. };
  48. enum nvme_io_opcode {
  49. nvme_cmd_write = 0x01,
  50. nvme_cmd_read = 0x02,
  51. };
  52. static int nsid;
  53. static __u32 lba_shift;
  54. struct nvme_lbaf {
  55. __le16 ms;
  56. __u8 ds;
  57. __u8 rp;
  58. };
  59. struct nvme_id_ns {
  60. __le64 nsze;
  61. __le64 ncap;
  62. __le64 nuse;
  63. __u8 nsfeat;
  64. __u8 nlbaf;
  65. __u8 flbas;
  66. __u8 mc;
  67. __u8 dpc;
  68. __u8 dps;
  69. __u8 nmic;
  70. __u8 rescap;
  71. __u8 fpi;
  72. __u8 dlfeat;
  73. __le16 nawun;
  74. __le16 nawupf;
  75. __le16 nacwu;
  76. __le16 nabsn;
  77. __le16 nabo;
  78. __le16 nabspf;
  79. __le16 noiob;
  80. __u8 nvmcap[16];
  81. __le16 npwg;
  82. __le16 npwa;
  83. __le16 npdg;
  84. __le16 npda;
  85. __le16 nows;
  86. __le16 mssrl;
  87. __le32 mcl;
  88. __u8 msrc;
  89. __u8 rsvd81[11];
  90. __le32 anagrpid;
  91. __u8 rsvd96[3];
  92. __u8 nsattr;
  93. __le16 nvmsetid;
  94. __le16 endgid;
  95. __u8 nguid[16];
  96. __u8 eui64[8];
  97. struct nvme_lbaf lbaf[16];
  98. __u8 rsvd192[192];
  99. __u8 vs[3712];
  100. };
  101. static inline int ilog2(uint32_t i)
  102. {
  103. int log = -1;
  104. while (i) {
  105. i >>= 1;
  106. log++;
  107. }
  108. return log;
  109. }
  110. __attribute__((__unused__))
  111. static int nvme_get_info(const char *file)
  112. {
  113. struct nvme_id_ns ns;
  114. int fd, err;
  115. __u32 lba_size;
  116. fd = open(file, O_RDONLY);
  117. if (fd < 0) {
  118. perror("file open");
  119. return -errno;
  120. }
  121. nsid = ioctl(fd, NVME_IOCTL_ID);
  122. if (nsid < 0) {
  123. close(fd);
  124. return -errno;
  125. }
  126. struct nvme_passthru_cmd cmd = {
  127. .opcode = nvme_admin_identify,
  128. .nsid = nsid,
  129. .addr = (__u64)(uintptr_t)&ns,
  130. .data_len = NVME_IDENTIFY_DATA_SIZE,
  131. .cdw10 = NVME_IDENTIFY_CNS_NS,
  132. .cdw11 = NVME_CSI_NVM << NVME_IDENTIFY_CSI_SHIFT,
  133. .timeout_ms = NVME_DEFAULT_IOCTL_TIMEOUT,
  134. };
  135. err = ioctl(fd, NVME_IOCTL_ADMIN_CMD, &cmd);
  136. if (err) {
  137. close(fd);
  138. return err;
  139. }
  140. lba_size = 1 << ns.lbaf[(ns.flbas & 0x0f)].ds;
  141. lba_shift = ilog2(lba_size);
  142. close(fd);
  143. return 0;
  144. }
  145. #ifdef __cplusplus
  146. }
  147. #endif
  148. #endif