@@ -101,11 +101,34 @@ static int map_hdm_decoder_regs(struct cxl_port *port, void __iomem *crb,
101
101
BIT (CXL_CM_CAP_CAP_ID_HDM ));
102
102
}
103
103
104
+ static struct cxl_hdm * devm_cxl_setup_emulated_hdm (struct cxl_port * port ,
105
+ struct cxl_endpoint_dvsec_info * info )
106
+ {
107
+ struct device * dev = & port -> dev ;
108
+ struct cxl_hdm * cxlhdm ;
109
+
110
+ if (!info -> mem_enabled )
111
+ return ERR_PTR (- ENODEV );
112
+
113
+ cxlhdm = devm_kzalloc (dev , sizeof (* cxlhdm ), GFP_KERNEL );
114
+ if (!cxlhdm )
115
+ return ERR_PTR (- ENOMEM );
116
+
117
+ cxlhdm -> port = port ;
118
+ cxlhdm -> decoder_count = info -> ranges ;
119
+ cxlhdm -> target_count = info -> ranges ;
120
+ dev_set_drvdata (& port -> dev , cxlhdm );
121
+
122
+ return cxlhdm ;
123
+ }
124
+
104
125
/**
105
126
* devm_cxl_setup_hdm - map HDM decoder component registers
106
127
* @port: cxl_port to map
128
+ * @info: cached DVSEC range register info
107
129
*/
108
- struct cxl_hdm * devm_cxl_setup_hdm (struct cxl_port * port )
130
+ struct cxl_hdm * devm_cxl_setup_hdm (struct cxl_port * port ,
131
+ struct cxl_endpoint_dvsec_info * info )
109
132
{
110
133
struct device * dev = & port -> dev ;
111
134
struct cxl_hdm * cxlhdm ;
@@ -119,6 +142,9 @@ struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port)
119
142
cxlhdm -> port = port ;
120
143
crb = ioremap (port -> component_reg_phys , CXL_COMPONENT_REG_BLOCK_SIZE );
121
144
if (!crb ) {
145
+ if (info && info -> mem_enabled )
146
+ return devm_cxl_setup_emulated_hdm (port , info );
147
+
122
148
dev_err (dev , "No component registers mapped\n" );
123
149
return ERR_PTR (- ENXIO );
124
150
}
@@ -688,9 +714,60 @@ static int cxl_decoder_reset(struct cxl_decoder *cxld)
688
714
return 0 ;
689
715
}
690
716
717
+ static int cxl_setup_hdm_decoder_from_dvsec (struct cxl_port * port ,
718
+ struct cxl_decoder * cxld , int which ,
719
+ struct cxl_endpoint_dvsec_info * info )
720
+ {
721
+ if (!is_cxl_endpoint (port ))
722
+ return - EOPNOTSUPP ;
723
+
724
+ if (!range_len (& info -> dvsec_range [which ]))
725
+ return - ENOENT ;
726
+
727
+ cxld -> target_type = CXL_DECODER_EXPANDER ;
728
+ cxld -> commit = NULL ;
729
+ cxld -> reset = NULL ;
730
+ cxld -> hpa_range = info -> dvsec_range [which ];
731
+
732
+ /*
733
+ * Set the emulated decoder as locked pending additional support to
734
+ * change the range registers at run time.
735
+ */
736
+ cxld -> flags |= CXL_DECODER_F_ENABLE | CXL_DECODER_F_LOCK ;
737
+ port -> commit_end = cxld -> id ;
738
+
739
+ return 0 ;
740
+ }
741
+
742
+ static bool should_emulate_decoders (struct cxl_port * port )
743
+ {
744
+ struct cxl_hdm * cxlhdm = dev_get_drvdata (& port -> dev );
745
+ void __iomem * hdm = cxlhdm -> regs .hdm_decoder ;
746
+ u32 ctrl ;
747
+ int i ;
748
+
749
+ if (!is_cxl_endpoint (cxlhdm -> port ))
750
+ return false;
751
+
752
+ if (!hdm )
753
+ return true;
754
+
755
+ /*
756
+ * If any decoders are committed already, there should not be any
757
+ * emulated DVSEC decoders.
758
+ */
759
+ for (i = 0 ; i < cxlhdm -> decoder_count ; i ++ ) {
760
+ ctrl = readl (hdm + CXL_HDM_DECODER0_CTRL_OFFSET (i ));
761
+ if (FIELD_GET (CXL_HDM_DECODER0_CTRL_COMMITTED , ctrl ))
762
+ return false;
763
+ }
764
+
765
+ return true;
766
+ }
767
+
691
768
static int init_hdm_decoder (struct cxl_port * port , struct cxl_decoder * cxld ,
692
769
int * target_map , void __iomem * hdm , int which ,
693
- u64 * dpa_base )
770
+ u64 * dpa_base , struct cxl_endpoint_dvsec_info * info )
694
771
{
695
772
struct cxl_endpoint_decoder * cxled = NULL ;
696
773
u64 size , base , skip , dpa_size ;
@@ -703,6 +780,9 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
703
780
unsigned char target_id [8 ];
704
781
} target_list ;
705
782
783
+ if (should_emulate_decoders (port ))
784
+ return cxl_setup_hdm_decoder_from_dvsec (port , cxld , which , info );
785
+
706
786
if (is_endpoint_decoder (& cxld -> dev ))
707
787
cxled = to_cxl_endpoint_decoder (& cxld -> dev );
708
788
@@ -726,6 +806,9 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
726
806
.end = base + size - 1 ,
727
807
};
728
808
809
+ if (cxled && !committed && range_len (& info -> dvsec_range [which ]))
810
+ return cxl_setup_hdm_decoder_from_dvsec (port , cxld , which , info );
811
+
729
812
/* decoders are enabled if committed */
730
813
if (committed ) {
731
814
cxld -> flags |= CXL_DECODER_F_ENABLE ;
@@ -798,18 +881,15 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
798
881
return 0 ;
799
882
}
800
883
801
- /**
802
- * devm_cxl_enumerate_decoders - add decoder objects per HDM register set
803
- * @cxlhdm: Structure to populate with HDM capabilities
804
- */
805
- int devm_cxl_enumerate_decoders (struct cxl_hdm * cxlhdm )
884
+ static void cxl_settle_decoders (struct cxl_hdm * cxlhdm )
806
885
{
807
886
void __iomem * hdm = cxlhdm -> regs .hdm_decoder ;
808
- struct cxl_port * port = cxlhdm -> port ;
809
- int i , committed ;
810
- u64 dpa_base = 0 ;
887
+ int committed , i ;
811
888
u32 ctrl ;
812
889
890
+ if (!hdm )
891
+ return ;
892
+
813
893
/*
814
894
* Since the register resource was recently claimed via request_region()
815
895
* be careful about trusting the "not-committed" status until the commit
@@ -826,6 +906,22 @@ int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm)
826
906
/* ensure that future checks of committed can be trusted */
827
907
if (committed != cxlhdm -> decoder_count )
828
908
msleep (20 );
909
+ }
910
+
911
+ /**
912
+ * devm_cxl_enumerate_decoders - add decoder objects per HDM register set
913
+ * @cxlhdm: Structure to populate with HDM capabilities
914
+ * @info: cached DVSEC range register info
915
+ */
916
+ int devm_cxl_enumerate_decoders (struct cxl_hdm * cxlhdm ,
917
+ struct cxl_endpoint_dvsec_info * info )
918
+ {
919
+ void __iomem * hdm = cxlhdm -> regs .hdm_decoder ;
920
+ struct cxl_port * port = cxlhdm -> port ;
921
+ int i ;
922
+ u64 dpa_base = 0 ;
923
+
924
+ cxl_settle_decoders (cxlhdm );
829
925
830
926
for (i = 0 ; i < cxlhdm -> decoder_count ; i ++ ) {
831
927
int target_map [CXL_DECODER_MAX_INTERLEAVE ] = { 0 };
@@ -856,7 +952,8 @@ int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm)
856
952
cxld = & cxlsd -> cxld ;
857
953
}
858
954
859
- rc = init_hdm_decoder (port , cxld , target_map , hdm , i , & dpa_base );
955
+ rc = init_hdm_decoder (port , cxld , target_map , hdm , i ,
956
+ & dpa_base , info );
860
957
if (rc ) {
861
958
dev_warn (& port -> dev ,
862
959
"Failed to initialize decoder%d.%d\n" ,
0 commit comments