@@ -267,11 +267,13 @@ enum nvme_cmd_dword_fields {
267267 NVME_FORMAT_CDW10_PI_SHIFT = 5 ,
268268 NVME_FORMAT_CDW10_PIL_SHIFT = 8 ,
269269 NVME_FORMAT_CDW10_SES_SHIFT = 9 ,
270+ NVME_FORMAT_CDW10_LBAFU_SHIFT = 12 ,
270271 NVME_FORMAT_CDW10_LBAF_MASK = 0xf ,
271272 NVME_FORMAT_CDW10_MSET_MASK = 0x1 ,
272273 NVME_FORMAT_CDW10_PI_MASK = 0x7 ,
273274 NVME_FORMAT_CDW10_PIL_MASK = 0x1 ,
274275 NVME_FORMAT_CDW10_SES_MASK = 0x7 ,
276+ NVME_FORMAT_CDW10_LBAFU_MASK = 0x3 ,
275277 NVME_SANITIZE_CDW10_SANACT_SHIFT = 0 ,
276278 NVME_SANITIZE_CDW10_AUSE_SHIFT = 3 ,
277279 NVME_SANITIZE_CDW10_OWPASS_SHIFT = 4 ,
@@ -1159,11 +1161,25 @@ int nvme_get_features_iocs_profile(int fd, enum nvme_get_features_sel sel,
11591161
11601162int nvme_format_nvm (struct nvme_format_nvm_args * args )
11611163{
1162- __u32 cdw10 = NVME_SET (args -> lbaf , FORMAT_CDW10_LBAF ) |
1163- NVME_SET (args -> mset , FORMAT_CDW10_MSET ) |
1164- NVME_SET (args -> pi , FORMAT_CDW10_PI ) |
1165- NVME_SET (args -> pil , FORMAT_CDW10_PIL ) |
1166- NVME_SET (args -> ses , FORMAT_CDW10_SES );
1164+ const size_t size_v1 = sizeof_args (struct nvme_format_nvm_args , lbaf , __u64 );
1165+ const size_t size_v2 = sizeof_args (struct nvme_format_nvm_args , lbafu , __u64 );
1166+ __u32 cdw10 ;
1167+
1168+ if (args -> args_size < size_v1 || args -> args_size > size_v2 ) {
1169+ errno = EINVAL ;
1170+ return -1 ;
1171+ }
1172+
1173+ cdw10 = NVME_SET (args -> lbaf , FORMAT_CDW10_LBAF ) |
1174+ NVME_SET (args -> mset , FORMAT_CDW10_MSET ) |
1175+ NVME_SET (args -> pi , FORMAT_CDW10_PI ) |
1176+ NVME_SET (args -> pil , FORMAT_CDW10_PIL ) |
1177+ NVME_SET (args -> ses , FORMAT_CDW10_SES );
1178+
1179+ if (args -> args_size == size_v2 ) {
1180+ /* set lbafu extension */
1181+ cdw10 |= NVME_SET (args -> lbafu , FORMAT_CDW10_LBAFU );
1182+ }
11671183
11681184 struct nvme_passthru_cmd cmd = {
11691185 .opcode = nvme_admin_format_nvm ,
@@ -1172,10 +1188,6 @@ int nvme_format_nvm(struct nvme_format_nvm_args *args)
11721188 .timeout_ms = args -> timeout ,
11731189 };
11741190
1175- if (args -> args_size < sizeof (* args )) {
1176- errno = EINVAL ;
1177- return -1 ;
1178- }
11791191 return nvme_submit_admin_passthru (args -> fd , & cmd , args -> result );
11801192}
11811193
@@ -1588,16 +1600,81 @@ int nvme_io_passthru(int fd, __u8 opcode, __u8 flags, __u16 rsvd,
15881600 timeout_ms , result );
15891601}
15901602
1603+ static int nvme_set_var_size_tags (__u32 * cmd_dw2 , __u32 * cmd_dw3 , __u32 * cmd_dw14 ,
1604+ __u8 pif , __u8 sts , __u64 reftag , __u64 storage_tag )
1605+ {
1606+ __u32 cdw2 = 0 , cdw3 = 0 , cdw14 ;
1607+
1608+ switch (pif ) {
1609+ /* 16b Protection Information */
1610+ case 0 :
1611+ cdw14 = reftag & 0xffffffff ;
1612+ cdw14 |= ((storage_tag << (32 - sts )) & 0xffffffff );
1613+ break ;
1614+ /* 32b Protection Information */
1615+ case 1 :
1616+ cdw14 = reftag & 0xffffffff ;
1617+ cdw3 = reftag >> 32 ;
1618+ cdw14 |= ((storage_tag << (80 - sts )) & 0xffff0000 );
1619+ if (sts >= 48 )
1620+ cdw3 |= ((storage_tag >> (sts - 48 )) & 0xffffffff );
1621+ else
1622+ cdw3 |= ((storage_tag << (48 - sts )) & 0xffffffff );
1623+ cdw2 = (storage_tag >> (sts - 16 )) & 0xffff ;
1624+ break ;
1625+ /* 64b Protection Information */
1626+ case 2 :
1627+ cdw14 = reftag & 0xffffffff ;
1628+ cdw3 = (reftag >> 32 ) & 0xffff ;
1629+ cdw14 |= ((storage_tag << (48 - sts )) & 0xffffffff );
1630+ if (sts >= 16 )
1631+ cdw3 |= ((storage_tag >> (sts - 16 )) & 0xffff );
1632+ else
1633+ cdw3 |= ((storage_tag << (16 - sts )) & 0xffff );
1634+ break ;
1635+ default :
1636+ perror ("Unsupported Protection Information Format" );
1637+ errno = EINVAL ;
1638+ return -1 ;
1639+ }
1640+
1641+ * cmd_dw2 = cdw2 ;
1642+ * cmd_dw3 = cdw3 ;
1643+ * cmd_dw14 = cdw14 ;
1644+ return 0 ;
1645+ }
1646+
15911647int nvme_io (struct nvme_io_args * args , __u8 opcode )
15921648{
1593- __u32 cdw2 = args -> storage_tag & 0xffffffff ;
1594- __u32 cdw3 = (args -> storage_tag >> 32 ) & 0xffff ;
1595- __u32 cdw10 = args -> slba & 0xffffffff ;
1596- __u32 cdw11 = args -> slba >> 32 ;
1597- __u32 cdw12 = args -> nlb | (args -> control << 16 );
1598- __u32 cdw13 = args -> dsm | (args -> dspec << 16 );
1599- __u32 cdw14 = args -> reftag ;
1600- __u32 cdw15 = args -> apptag | (args -> appmask << 16 );
1649+ const size_t size_v1 = sizeof_args (struct nvme_io_args , dsm , __u64 );
1650+ const size_t size_v2 = sizeof_args (struct nvme_io_args , pif , __u64 );
1651+ __u32 cdw2 , cdw3 , cdw10 , cdw11 , cdw12 , cdw13 , cdw14 , cdw15 ;
1652+
1653+ if (args -> args_size < size_v1 || args -> args_size > size_v2 ) {
1654+ errno = EINVAL ;
1655+ return -1 ;
1656+ }
1657+
1658+ cdw10 = args -> slba & 0xffffffff ;
1659+ cdw11 = args -> slba >> 32 ;
1660+ cdw12 = args -> nlb | (args -> control << 16 );
1661+ cdw13 = args -> dsm | (args -> dspec << 16 );
1662+ cdw15 = args -> apptag | (args -> appmask << 16 );
1663+
1664+ if (args -> args_size == size_v1 ) {
1665+ cdw2 = (args -> storage_tag >> 32 ) & 0xffff ;
1666+ cdw3 = args -> storage_tag & 0xffffffff ;
1667+ cdw14 = args -> reftag ;
1668+ } else {
1669+ if (nvme_set_var_size_tags (& cdw2 , & cdw3 , & cdw14 ,
1670+ args -> pif ,
1671+ args -> sts ,
1672+ args -> reftag_u64 ,
1673+ args -> storage_tag )) {
1674+ errno = EINVAL ;
1675+ return -1 ;
1676+ }
1677+ }
16011678
16021679 struct nvme_passthru_cmd cmd = {
16031680 .opcode = opcode ,
@@ -1617,10 +1694,6 @@ int nvme_io(struct nvme_io_args *args, __u8 opcode)
16171694 .timeout_ms = args -> timeout ,
16181695 };
16191696
1620- if (args -> args_size < sizeof (* args )) {
1621- errno = EINVAL ;
1622- return -1 ;
1623- }
16241697 return nvme_submit_io_passthru (args -> fd , & cmd , args -> result );
16251698}
16261699
@@ -1645,29 +1718,48 @@ int nvme_dsm(struct nvme_dsm_args *args)
16451718
16461719int nvme_copy (struct nvme_copy_args * args )
16471720{
1648- __u32 cdw12 = ((args -> nr - 1 ) & 0xff ) | ((args -> format & 0xf ) << 8 ) |
1721+ const size_t size_v1 = sizeof_args (struct nvme_copy_args , format , __u64 );
1722+ const size_t size_v2 = sizeof_args (struct nvme_copy_args , ilbrt_u64 , __u64 );
1723+ __u32 cdw3 , cdw12 , cdw14 , data_len ;
1724+
1725+ if (args -> args_size < size_v1 || args -> args_size > size_v2 ) {
1726+ errno = EINVAL ;
1727+ return -1 ;
1728+ }
1729+
1730+ cdw12 = ((args -> nr - 1 ) & 0xff ) | ((args -> format & 0xf ) << 8 ) |
16491731 ((args -> prinfor & 0xf ) << 12 ) | ((args -> dtype & 0xf ) << 20 ) |
16501732 ((args -> prinfow & 0xf ) << 26 ) | ((args -> fua & 0x1 ) << 30 ) |
16511733 ((args -> lr & 0x1 ) << 31 );
16521734
1735+ if (args -> args_size == size_v1 ) {
1736+ cdw3 = 0 ;
1737+ cdw14 = args -> ilbrt ;
1738+ } else {
1739+ cdw3 = (args -> ilbrt_u64 >> 32 ) & 0xffffffff ;
1740+ cdw14 = args -> ilbrt_u64 & 0xffffffff ;
1741+ }
1742+
1743+ if (args -> format == 1 )
1744+ data_len = args -> nr * sizeof (struct nvme_copy_range_f1 );
1745+ else
1746+ data_len = args -> nr * sizeof (struct nvme_copy_range );
1747+
16531748 struct nvme_passthru_cmd cmd = {
16541749 .opcode = nvme_cmd_copy ,
16551750 .nsid = args -> nsid ,
16561751 .addr = (__u64 )(uintptr_t )args -> copy ,
1657- .data_len = args -> nr * sizeof (* args -> copy ),
1752+ .data_len = data_len ,
1753+ .cdw3 = cdw3 ,
16581754 .cdw10 = args -> sdlba & 0xffffffff ,
16591755 .cdw11 = args -> sdlba >> 32 ,
16601756 .cdw12 = cdw12 ,
16611757 .cdw13 = (args -> dspec & 0xffff ) << 16 ,
1662- .cdw14 = args -> ilbrt ,
1758+ .cdw14 = cdw14 ,
16631759 .cdw15 = (args -> lbatm << 16 ) | args -> lbat ,
16641760 .timeout_ms = args -> timeout ,
16651761 };
16661762
1667- if (args -> args_size < sizeof (* args )) {
1668- errno = EINVAL ;
1669- return -1 ;
1670- }
16711763 return nvme_submit_io_passthru (args -> fd , & cmd , args -> result );
16721764}
16731765
@@ -1821,15 +1913,32 @@ int nvme_zns_mgmt_recv(struct nvme_zns_mgmt_recv_args *args)
18211913
18221914int nvme_zns_append (struct nvme_zns_append_args * args )
18231915{
1824- __u32 cdw10 = args -> zslba & 0xffffffff ;
1825- __u32 cdw11 = args -> zslba >> 32 ;
1826- __u32 cdw12 = args -> nlb | (args -> control << 16 );
1827- __u32 cdw14 = args -> ilbrt ;
1828- __u32 cdw15 = args -> lbat | (args -> lbatm << 16 );
1916+ const size_t size_v1 = sizeof_args (struct nvme_zns_append_args , lbatm , __u64 );
1917+ const size_t size_v2 = sizeof_args (struct nvme_zns_append_args , ilbrt_u64 , __u64 );
1918+ __u32 cdw3 , cdw10 , cdw11 , cdw12 , cdw14 , cdw15 ;
1919+
1920+ if (args -> args_size < size_v1 || args -> args_size > size_v2 ) {
1921+ errno = EINVAL ;
1922+ return -1 ;
1923+ }
1924+
1925+ cdw10 = args -> zslba & 0xffffffff ;
1926+ cdw11 = args -> zslba >> 32 ;
1927+ cdw12 = args -> nlb | (args -> control << 16 );
1928+ cdw15 = args -> lbat | (args -> lbatm << 16 );
1929+
1930+ if (args -> args_size == size_v1 ) {
1931+ cdw3 = 0 ;
1932+ cdw14 = args -> ilbrt ;
1933+ } else {
1934+ cdw3 = (args -> ilbrt_u64 >> 32 ) & 0xffffffff ;
1935+ cdw14 = args -> ilbrt_u64 & 0xffffffff ;
1936+ }
18291937
18301938 struct nvme_passthru_cmd64 cmd = {
18311939 .opcode = nvme_zns_cmd_append ,
18321940 .nsid = args -> nsid ,
1941+ .cdw3 = cdw3 ,
18331942 .cdw10 = cdw10 ,
18341943 .cdw11 = cdw11 ,
18351944 .cdw12 = cdw12 ,
@@ -1842,10 +1951,6 @@ int nvme_zns_append(struct nvme_zns_append_args *args)
18421951 .timeout_ms = args -> timeout ,
18431952 };
18441953
1845- if (args -> args_size < sizeof (* args )) {
1846- errno = EINVAL ;
1847- return -1 ;
1848- }
18491954 return nvme_submit_io_passthru64 (args -> fd , & cmd , args -> result );
18501955}
18511956
0 commit comments