@@ -703,6 +703,142 @@ static int mock_decoder_reset(struct cxl_decoder *cxld)
703
703
return 0 ;
704
704
}
705
705
706
+ static void default_mock_decoder (struct cxl_decoder * cxld )
707
+ {
708
+ cxld -> hpa_range = (struct range ){
709
+ .start = 0 ,
710
+ .end = -1 ,
711
+ };
712
+
713
+ cxld -> interleave_ways = 1 ;
714
+ cxld -> interleave_granularity = 256 ;
715
+ cxld -> target_type = CXL_DECODER_EXPANDER ;
716
+ cxld -> commit = mock_decoder_commit ;
717
+ cxld -> reset = mock_decoder_reset ;
718
+ }
719
+
720
+ static int first_decoder (struct device * dev , void * data )
721
+ {
722
+ struct cxl_decoder * cxld ;
723
+
724
+ if (!is_switch_decoder (dev ))
725
+ return 0 ;
726
+ cxld = to_cxl_decoder (dev );
727
+ if (cxld -> id == 0 )
728
+ return 1 ;
729
+ return 0 ;
730
+ }
731
+
732
+ static void mock_init_hdm_decoder (struct cxl_decoder * cxld )
733
+ {
734
+ struct acpi_cedt_cfmws * window = mock_cfmws [0 ];
735
+ struct platform_device * pdev = NULL ;
736
+ struct cxl_endpoint_decoder * cxled ;
737
+ struct cxl_switch_decoder * cxlsd ;
738
+ struct cxl_port * port , * iter ;
739
+ const int size = SZ_512M ;
740
+ struct cxl_memdev * cxlmd ;
741
+ struct cxl_dport * dport ;
742
+ struct device * dev ;
743
+ bool hb0 = false;
744
+ u64 base ;
745
+ int i ;
746
+
747
+ if (is_endpoint_decoder (& cxld -> dev )) {
748
+ cxled = to_cxl_endpoint_decoder (& cxld -> dev );
749
+ cxlmd = cxled_to_memdev (cxled );
750
+ WARN_ON (!dev_is_platform (cxlmd -> dev .parent ));
751
+ pdev = to_platform_device (cxlmd -> dev .parent );
752
+
753
+ /* check is endpoint is attach to host-bridge0 */
754
+ port = cxled_to_port (cxled );
755
+ do {
756
+ if (port -> uport == & cxl_host_bridge [0 ]-> dev ) {
757
+ hb0 = true;
758
+ break ;
759
+ }
760
+ if (is_cxl_port (port -> dev .parent ))
761
+ port = to_cxl_port (port -> dev .parent );
762
+ else
763
+ port = NULL ;
764
+ } while (port );
765
+ port = cxled_to_port (cxled );
766
+ }
767
+
768
+ /*
769
+ * The first decoder on the first 2 devices on the first switch
770
+ * attached to host-bridge0 mock a fake / static RAM region. All
771
+ * other decoders are default disabled. Given the round robin
772
+ * assignment those devices are named cxl_mem.0, and cxl_mem.4.
773
+ *
774
+ * See 'cxl list -BMPu -m cxl_mem.0,cxl_mem.4'
775
+ */
776
+ if (!hb0 || pdev -> id % 4 || pdev -> id > 4 || cxld -> id > 0 ) {
777
+ default_mock_decoder (cxld );
778
+ return ;
779
+ }
780
+
781
+ base = window -> base_hpa ;
782
+ cxld -> hpa_range = (struct range ) {
783
+ .start = base ,
784
+ .end = base + size - 1 ,
785
+ };
786
+
787
+ cxld -> interleave_ways = 2 ;
788
+ eig_to_granularity (window -> granularity , & cxld -> interleave_granularity );
789
+ cxld -> target_type = CXL_DECODER_EXPANDER ;
790
+ cxld -> flags = CXL_DECODER_F_ENABLE ;
791
+ cxled -> state = CXL_DECODER_STATE_AUTO ;
792
+ port -> commit_end = cxld -> id ;
793
+ devm_cxl_dpa_reserve (cxled , 0 , size / cxld -> interleave_ways , 0 );
794
+ cxld -> commit = mock_decoder_commit ;
795
+ cxld -> reset = mock_decoder_reset ;
796
+
797
+ /*
798
+ * Now that endpoint decoder is set up, walk up the hierarchy
799
+ * and setup the switch and root port decoders targeting @cxlmd.
800
+ */
801
+ iter = port ;
802
+ for (i = 0 ; i < 2 ; i ++ ) {
803
+ dport = iter -> parent_dport ;
804
+ iter = dport -> port ;
805
+ dev = device_find_child (& iter -> dev , NULL , first_decoder );
806
+ /*
807
+ * Ancestor ports are guaranteed to be enumerated before
808
+ * @port, and all ports have at least one decoder.
809
+ */
810
+ if (WARN_ON (!dev ))
811
+ continue ;
812
+ cxlsd = to_cxl_switch_decoder (dev );
813
+ if (i == 0 ) {
814
+ /* put cxl_mem.4 second in the decode order */
815
+ if (pdev -> id == 4 )
816
+ cxlsd -> target [1 ] = dport ;
817
+ else
818
+ cxlsd -> target [0 ] = dport ;
819
+ } else
820
+ cxlsd -> target [0 ] = dport ;
821
+ cxld = & cxlsd -> cxld ;
822
+ cxld -> target_type = CXL_DECODER_EXPANDER ;
823
+ cxld -> flags = CXL_DECODER_F_ENABLE ;
824
+ iter -> commit_end = 0 ;
825
+ /*
826
+ * Switch targets 2 endpoints, while host bridge targets
827
+ * one root port
828
+ */
829
+ if (i == 0 )
830
+ cxld -> interleave_ways = 2 ;
831
+ else
832
+ cxld -> interleave_ways = 1 ;
833
+ cxld -> interleave_granularity = 256 ;
834
+ cxld -> hpa_range = (struct range ) {
835
+ .start = base ,
836
+ .end = base + size - 1 ,
837
+ };
838
+ put_device (dev );
839
+ }
840
+ }
841
+
706
842
static int mock_cxl_enumerate_decoders (struct cxl_hdm * cxlhdm )
707
843
{
708
844
struct cxl_port * port = cxlhdm -> port ;
@@ -748,16 +884,7 @@ static int mock_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm)
748
884
cxld = & cxled -> cxld ;
749
885
}
750
886
751
- cxld -> hpa_range = (struct range ) {
752
- .start = 0 ,
753
- .end = -1 ,
754
- };
755
-
756
- cxld -> interleave_ways = min_not_zero (target_count , 1 );
757
- cxld -> interleave_granularity = SZ_4K ;
758
- cxld -> target_type = CXL_DECODER_EXPANDER ;
759
- cxld -> commit = mock_decoder_commit ;
760
- cxld -> reset = mock_decoder_reset ;
887
+ mock_init_hdm_decoder (cxld );
761
888
762
889
if (target_count ) {
763
890
rc = device_for_each_child (port -> uport , & ctx ,
0 commit comments