@@ -277,15 +277,14 @@ static const uint32_t nvme_cse_acs_default[256] = {
277277 [NVME_ADM_CMD_SET_FEATURES ] = NVME_CMD_EFF_CSUPP ,
278278 [NVME_ADM_CMD_GET_FEATURES ] = NVME_CMD_EFF_CSUPP ,
279279 [NVME_ADM_CMD_ASYNC_EV_REQ ] = NVME_CMD_EFF_CSUPP ,
280- [NVME_ADM_CMD_NS_ATTACHMENT ] = NVME_CMD_EFF_CSUPP | NVME_CMD_EFF_NIC ,
280+ [NVME_ADM_CMD_NS_ATTACHMENT ] = NVME_CMD_EFF_CSUPP | NVME_CMD_EFF_NIC |
281+ NVME_CMD_EFF_CCC ,
281282 [NVME_ADM_CMD_FORMAT_NVM ] = NVME_CMD_EFF_CSUPP | NVME_CMD_EFF_LBCC ,
282283 [NVME_ADM_CMD_DIRECTIVE_RECV ] = NVME_CMD_EFF_CSUPP ,
283284 [NVME_ADM_CMD_DIRECTIVE_SEND ] = NVME_CMD_EFF_CSUPP ,
284285};
285286
286- static const uint32_t nvme_cse_iocs_none [256 ];
287-
288- static const uint32_t nvme_cse_iocs_nvm [256 ] = {
287+ static const uint32_t nvme_cse_iocs_nvm_default [256 ] = {
289288 [NVME_CMD_FLUSH ] = NVME_CMD_EFF_CSUPP | NVME_CMD_EFF_LBCC ,
290289 [NVME_CMD_WRITE_ZEROES ] = NVME_CMD_EFF_CSUPP | NVME_CMD_EFF_LBCC ,
291290 [NVME_CMD_WRITE ] = NVME_CMD_EFF_CSUPP | NVME_CMD_EFF_LBCC ,
@@ -298,7 +297,7 @@ static const uint32_t nvme_cse_iocs_nvm[256] = {
298297 [NVME_CMD_IO_MGMT_SEND ] = NVME_CMD_EFF_CSUPP | NVME_CMD_EFF_LBCC ,
299298};
300299
301- static const uint32_t nvme_cse_iocs_zoned [256 ] = {
300+ static const uint32_t nvme_cse_iocs_zoned_default [256 ] = {
302301 [NVME_CMD_FLUSH ] = NVME_CMD_EFF_CSUPP | NVME_CMD_EFF_LBCC ,
303302 [NVME_CMD_WRITE_ZEROES ] = NVME_CMD_EFF_CSUPP | NVME_CMD_EFF_LBCC ,
304303 [NVME_CMD_WRITE ] = NVME_CMD_EFF_CSUPP | NVME_CMD_EFF_LBCC ,
@@ -307,6 +306,9 @@ static const uint32_t nvme_cse_iocs_zoned[256] = {
307306 [NVME_CMD_VERIFY ] = NVME_CMD_EFF_CSUPP ,
308307 [NVME_CMD_COPY ] = NVME_CMD_EFF_CSUPP | NVME_CMD_EFF_LBCC ,
309308 [NVME_CMD_COMPARE ] = NVME_CMD_EFF_CSUPP ,
309+ [NVME_CMD_IO_MGMT_RECV ] = NVME_CMD_EFF_CSUPP ,
310+ [NVME_CMD_IO_MGMT_SEND ] = NVME_CMD_EFF_CSUPP | NVME_CMD_EFF_LBCC ,
311+
310312 [NVME_CMD_ZONE_APPEND ] = NVME_CMD_EFF_CSUPP | NVME_CMD_EFF_LBCC ,
311313 [NVME_CMD_ZONE_MGMT_SEND ] = NVME_CMD_EFF_CSUPP | NVME_CMD_EFF_LBCC ,
312314 [NVME_CMD_ZONE_MGMT_RECV ] = NVME_CMD_EFF_CSUPP ,
@@ -4603,6 +4605,61 @@ static uint16_t nvme_io_mgmt_send(NvmeCtrl *n, NvmeRequest *req)
46034605 };
46044606}
46054607
4608+ static uint16_t __nvme_io_cmd_nvm (NvmeCtrl * n , NvmeRequest * req )
4609+ {
4610+ switch (req -> cmd .opcode ) {
4611+ case NVME_CMD_WRITE :
4612+ return nvme_write (n , req );
4613+ case NVME_CMD_READ :
4614+ return nvme_read (n , req );
4615+ case NVME_CMD_COMPARE :
4616+ return nvme_compare (n , req );
4617+ case NVME_CMD_WRITE_ZEROES :
4618+ return nvme_write_zeroes (n , req );
4619+ case NVME_CMD_DSM :
4620+ return nvme_dsm (n , req );
4621+ case NVME_CMD_VERIFY :
4622+ return nvme_verify (n , req );
4623+ case NVME_CMD_COPY :
4624+ return nvme_copy (n , req );
4625+ case NVME_CMD_IO_MGMT_RECV :
4626+ return nvme_io_mgmt_recv (n , req );
4627+ case NVME_CMD_IO_MGMT_SEND :
4628+ return nvme_io_mgmt_send (n , req );
4629+ }
4630+
4631+ g_assert_not_reached ();
4632+ }
4633+
4634+ static uint16_t nvme_io_cmd_nvm (NvmeCtrl * n , NvmeRequest * req )
4635+ {
4636+ if (!(n -> cse .iocs .nvm [req -> cmd .opcode ] & NVME_CMD_EFF_CSUPP )) {
4637+ trace_pci_nvme_err_invalid_opc (req -> cmd .opcode );
4638+ return NVME_INVALID_OPCODE | NVME_DNR ;
4639+ }
4640+
4641+ return __nvme_io_cmd_nvm (n , req );
4642+ }
4643+
4644+ static uint16_t nvme_io_cmd_zoned (NvmeCtrl * n , NvmeRequest * req )
4645+ {
4646+ if (!(n -> cse .iocs .zoned [req -> cmd .opcode ] & NVME_CMD_EFF_CSUPP )) {
4647+ trace_pci_nvme_err_invalid_opc (req -> cmd .opcode );
4648+ return NVME_INVALID_OPCODE | NVME_DNR ;
4649+ }
4650+
4651+ switch (req -> cmd .opcode ) {
4652+ case NVME_CMD_ZONE_APPEND :
4653+ return nvme_zone_append (n , req );
4654+ case NVME_CMD_ZONE_MGMT_SEND :
4655+ return nvme_zone_mgmt_send (n , req );
4656+ case NVME_CMD_ZONE_MGMT_RECV :
4657+ return nvme_zone_mgmt_recv (n , req );
4658+ }
4659+
4660+ return __nvme_io_cmd_nvm (n , req );
4661+ }
4662+
46064663static uint16_t nvme_io_cmd (NvmeCtrl * n , NvmeRequest * req )
46074664{
46084665 NvmeNamespace * ns ;
@@ -4644,11 +4701,6 @@ static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeRequest *req)
46444701 return NVME_INVALID_FIELD | NVME_DNR ;
46454702 }
46464703
4647- if (!(ns -> iocs [req -> cmd .opcode ] & NVME_CMD_EFF_CSUPP )) {
4648- trace_pci_nvme_err_invalid_opc (req -> cmd .opcode );
4649- return NVME_INVALID_OPCODE | NVME_DNR ;
4650- }
4651-
46524704 if (ns -> status ) {
46534705 return ns -> status ;
46544706 }
@@ -4659,36 +4711,14 @@ static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeRequest *req)
46594711
46604712 req -> ns = ns ;
46614713
4662- switch (req -> cmd .opcode ) {
4663- case NVME_CMD_WRITE_ZEROES :
4664- return nvme_write_zeroes (n , req );
4665- case NVME_CMD_ZONE_APPEND :
4666- return nvme_zone_append (n , req );
4667- case NVME_CMD_WRITE :
4668- return nvme_write (n , req );
4669- case NVME_CMD_READ :
4670- return nvme_read (n , req );
4671- case NVME_CMD_COMPARE :
4672- return nvme_compare (n , req );
4673- case NVME_CMD_DSM :
4674- return nvme_dsm (n , req );
4675- case NVME_CMD_VERIFY :
4676- return nvme_verify (n , req );
4677- case NVME_CMD_COPY :
4678- return nvme_copy (n , req );
4679- case NVME_CMD_ZONE_MGMT_SEND :
4680- return nvme_zone_mgmt_send (n , req );
4681- case NVME_CMD_ZONE_MGMT_RECV :
4682- return nvme_zone_mgmt_recv (n , req );
4683- case NVME_CMD_IO_MGMT_RECV :
4684- return nvme_io_mgmt_recv (n , req );
4685- case NVME_CMD_IO_MGMT_SEND :
4686- return nvme_io_mgmt_send (n , req );
4687- default :
4688- g_assert_not_reached ();
4714+ switch (ns -> csi ) {
4715+ case NVME_CSI_NVM :
4716+ return nvme_io_cmd_nvm (n , req );
4717+ case NVME_CSI_ZONED :
4718+ return nvme_io_cmd_zoned (n , req );
46894719 }
46904720
4691- return NVME_INVALID_OPCODE | NVME_DNR ;
4721+ g_assert_not_reached () ;
46924722}
46934723
46944724static void nvme_cq_notifier (EventNotifier * e )
@@ -5147,7 +5177,7 @@ static uint16_t nvme_cmd_effects(NvmeCtrl *n, uint8_t csi, uint32_t buf_len,
51475177 uint64_t off , NvmeRequest * req )
51485178{
51495179 NvmeEffectsLog log = {};
5150- const uint32_t * src_iocs = NULL ;
5180+ const uint32_t * iocs = NULL ;
51515181 uint32_t trans_len ;
51525182
51535183 if (off >= sizeof (log )) {
@@ -5157,25 +5187,26 @@ static uint16_t nvme_cmd_effects(NvmeCtrl *n, uint8_t csi, uint32_t buf_len,
51575187
51585188 switch (NVME_CC_CSS (ldl_le_p (& n -> bar .cc ))) {
51595189 case NVME_CC_CSS_NVM :
5160- src_iocs = nvme_cse_iocs_nvm ;
5161- /* fall through */
5162- case NVME_CC_CSS_ADMIN_ONLY :
5190+ iocs = n -> cse .iocs .nvm ;
51635191 break ;
5164- case NVME_CC_CSS_CSI :
5192+
5193+ case NVME_CC_CSS_ALL :
51655194 switch (csi ) {
51665195 case NVME_CSI_NVM :
5167- src_iocs = nvme_cse_iocs_nvm ;
5196+ iocs = n -> cse . iocs . nvm ;
51685197 break ;
51695198 case NVME_CSI_ZONED :
5170- src_iocs = nvme_cse_iocs_zoned ;
5199+ iocs = n -> cse . iocs . zoned ;
51715200 break ;
51725201 }
5202+
5203+ break ;
51735204 }
51745205
51755206 memcpy (log .acs , n -> cse .acs , sizeof (log .acs ));
51765207
5177- if (src_iocs ) {
5178- memcpy (log .iocs , src_iocs , sizeof (log .iocs ));
5208+ if (iocs ) {
5209+ memcpy (log .iocs , iocs , sizeof (log .iocs ));
51795210 }
51805211
51815212 trans_len = MIN (sizeof (log ) - off , buf_len );
@@ -6718,25 +6749,29 @@ static void nvme_update_dsm_limits(NvmeCtrl *n, NvmeNamespace *ns)
67186749 }
67196750}
67206751
6721- static void nvme_select_iocs_ns (NvmeCtrl * n , NvmeNamespace * ns )
6752+ static bool nvme_csi_supported (NvmeCtrl * n , uint8_t csi )
67226753{
6723- uint32_t cc = ldl_le_p ( & n -> bar . cc ) ;
6754+ uint32_t cc ;
67246755
6725- ns -> iocs = nvme_cse_iocs_none ;
6726- switch (ns -> csi ) {
6756+ switch (csi ) {
67276757 case NVME_CSI_NVM :
6728- if (NVME_CC_CSS (cc ) != NVME_CC_CSS_ADMIN_ONLY ) {
6729- ns -> iocs = nvme_cse_iocs_nvm ;
6730- }
6731- break ;
6758+ return true;
6759+
67326760 case NVME_CSI_ZONED :
6733- if (NVME_CC_CSS (cc ) == NVME_CC_CSS_CSI ) {
6734- ns -> iocs = nvme_cse_iocs_zoned ;
6735- } else if (NVME_CC_CSS (cc ) == NVME_CC_CSS_NVM ) {
6736- ns -> iocs = nvme_cse_iocs_nvm ;
6737- }
6738- break ;
6761+ cc = ldl_le_p (& n -> bar .cc );
6762+
6763+ return NVME_CC_CSS (cc ) == NVME_CC_CSS_ALL ;
67396764 }
6765+
6766+ g_assert_not_reached ();
6767+ }
6768+
6769+ static void nvme_detach_ns (NvmeCtrl * n , NvmeNamespace * ns )
6770+ {
6771+ assert (ns -> attached > 0 );
6772+
6773+ n -> namespaces [ns -> params .nsid ] = NULL ;
6774+ ns -> attached -- ;
67406775}
67416776
67426777static uint16_t nvme_ns_attachment (NvmeCtrl * n , NvmeRequest * req )
@@ -6781,27 +6816,25 @@ static uint16_t nvme_ns_attachment(NvmeCtrl *n, NvmeRequest *req)
67816816
67826817 switch (sel ) {
67836818 case NVME_NS_ATTACHMENT_ATTACH :
6784- if (nvme_ns (ctrl , nsid )) {
6819+ if (nvme_ns (n , nsid )) {
67856820 return NVME_NS_ALREADY_ATTACHED | NVME_DNR ;
67866821 }
67876822
67886823 if (ns -> attached && !ns -> params .shared ) {
67896824 return NVME_NS_PRIVATE | NVME_DNR ;
67906825 }
67916826
6827+ if (!nvme_csi_supported (n , ns -> csi )) {
6828+ return NVME_IOCS_NOT_SUPPORTED | NVME_DNR ;
6829+ }
6830+
67926831 nvme_attach_ns (ctrl , ns );
6793- nvme_select_iocs_ns (ctrl , ns );
6832+ nvme_update_dsm_limits (ctrl , ns );
67946833
67956834 break ;
67966835
67976836 case NVME_NS_ATTACHMENT_DETACH :
6798- if (!nvme_ns (ctrl , nsid )) {
6799- return NVME_NS_NOT_ATTACHED | NVME_DNR ;
6800- }
6801-
6802- ctrl -> namespaces [nsid ] = NULL ;
6803- ns -> attached -- ;
6804-
6837+ nvme_detach_ns (ctrl , ns );
68056838 nvme_update_dsm_limits (ctrl , NULL );
68066839
68076840 break ;
@@ -7652,21 +7685,6 @@ static void nvme_ctrl_shutdown(NvmeCtrl *n)
76527685 }
76537686}
76547687
7655- static void nvme_select_iocs (NvmeCtrl * n )
7656- {
7657- NvmeNamespace * ns ;
7658- int i ;
7659-
7660- for (i = 1 ; i <= NVME_MAX_NAMESPACES ; i ++ ) {
7661- ns = nvme_ns (n , i );
7662- if (!ns ) {
7663- continue ;
7664- }
7665-
7666- nvme_select_iocs_ns (n , ns );
7667- }
7668- }
7669-
76707688static int nvme_start_ctrl (NvmeCtrl * n )
76717689{
76727690 uint64_t cap = ldq_le_p (& n -> bar .cap );
@@ -7733,7 +7751,18 @@ static int nvme_start_ctrl(NvmeCtrl *n)
77337751
77347752 nvme_set_timestamp (n , 0ULL );
77357753
7736- nvme_select_iocs (n );
7754+ /* verify that the command sets of attached namespaces are supported */
7755+ for (int i = 1 ; i <= NVME_MAX_NAMESPACES ; i ++ ) {
7756+ NvmeNamespace * ns = nvme_subsys_ns (n -> subsys , i );
7757+
7758+ if (ns && nvme_csi_supported (n , ns -> csi ) && !ns -> params .detached ) {
7759+ if (!ns -> attached || ns -> params .shared ) {
7760+ nvme_attach_ns (n , ns );
7761+ }
7762+ }
7763+ }
7764+
7765+ nvme_update_dsm_limits (n , NULL );
77377766
77387767 return 0 ;
77397768}
@@ -8748,6 +8777,9 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev)
87488777 uint16_t oacs ;
87498778
87508779 memcpy (n -> cse .acs , nvme_cse_acs_default , sizeof (n -> cse .acs ));
8780+ memcpy (n -> cse .iocs .nvm , nvme_cse_iocs_nvm_default , sizeof (n -> cse .iocs .nvm ));
8781+ memcpy (n -> cse .iocs .zoned , nvme_cse_iocs_zoned_default ,
8782+ sizeof (n -> cse .iocs .zoned ));
87518783
87528784 id -> vid = cpu_to_le16 (pci_get_word (pci_conf + PCI_VENDOR_ID ));
87538785 id -> ssvid = cpu_to_le16 (pci_get_word (pci_conf + PCI_SUBSYSTEM_VENDOR_ID ));
@@ -8859,9 +8891,8 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev)
88598891 NVME_CAP_SET_MQES (cap , n -> params .mqes );
88608892 NVME_CAP_SET_CQR (cap , 1 );
88618893 NVME_CAP_SET_TO (cap , 0xf );
8862- NVME_CAP_SET_CSS (cap , NVME_CAP_CSS_NVM );
8863- NVME_CAP_SET_CSS (cap , NVME_CAP_CSS_CSI_SUPP );
8864- NVME_CAP_SET_CSS (cap , NVME_CAP_CSS_ADMIN_ONLY );
8894+ NVME_CAP_SET_CSS (cap , NVME_CAP_CSS_NCSS );
8895+ NVME_CAP_SET_CSS (cap , NVME_CAP_CSS_IOCSS );
88658896 NVME_CAP_SET_MPSMAX (cap , 4 );
88668897 NVME_CAP_SET_CMBS (cap , n -> params .cmb_size_mb ? 1 : 0 );
88678898 NVME_CAP_SET_PMRS (cap , n -> pmr .dev ? 1 : 0 );
@@ -8908,8 +8939,6 @@ void nvme_attach_ns(NvmeCtrl *n, NvmeNamespace *ns)
89088939
89098940 n -> namespaces [nsid ] = ns ;
89108941 ns -> attached ++ ;
8911-
8912- nvme_update_dsm_limits (n , ns );
89138942}
89148943
89158944static void nvme_realize (PCIDevice * pci_dev , Error * * errp )
@@ -8965,7 +8994,7 @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
89658994 return ;
89668995 }
89678996
8968- nvme_attach_ns ( n , ns ) ;
8997+ n -> subsys -> namespaces [ ns -> params . nsid ] = ns ;
89698998 }
89708999}
89719000
0 commit comments