@@ -95,6 +95,8 @@ struct switchtec_ntb {
9595 struct ntb_ctrl_regs __iomem * mmio_peer_ctrl ;
9696 struct ntb_dbmsg_regs __iomem * mmio_self_dbmsg ;
9797
98+ void __iomem * mmio_xlink_win ;
99+
98100 struct shared_mw * self_shared ;
99101 struct shared_mw __iomem * peer_shared ;
100102 dma_addr_t self_shared_dma ;
@@ -442,6 +444,13 @@ static void switchtec_ntb_set_link_speed(struct switchtec_ntb *sndev)
442444 sndev -> link_width = min (self_width , peer_width );
443445}
444446
447+ static int crosslink_is_enabled (struct switchtec_ntb * sndev )
448+ {
449+ struct ntb_info_regs __iomem * inf = sndev -> mmio_ntb ;
450+
451+ return ioread8 (& inf -> crosslink [sndev -> self_partition ].enabled );
452+ }
453+
445454enum {
446455 LINK_MESSAGE = 0 ,
447456 MSG_LINK_UP = 1 ,
@@ -774,8 +783,7 @@ static void switchtec_ntb_init_sndev(struct switchtec_ntb *sndev)
774783
775784static int config_rsvd_lut_win (struct switchtec_ntb * sndev ,
776785 struct ntb_ctrl_regs __iomem * ctl ,
777- int lut_idx , int partition ,
778- dma_addr_t addr )
786+ int lut_idx , int partition , u64 addr )
779787{
780788 int bar = sndev -> direct_mw_to_bar [0 ];
781789 u32 ctl_val ;
@@ -861,6 +869,181 @@ static int config_req_id_table(struct switchtec_ntb *sndev,
861869 return 0 ;
862870}
863871
872+ static int crosslink_setup_mws (struct switchtec_ntb * sndev , int ntb_lut_idx ,
873+ u64 * mw_addrs , int mw_count )
874+ {
875+ int rc , i ;
876+ struct ntb_ctrl_regs __iomem * ctl = sndev -> mmio_self_ctrl ;
877+ u64 addr ;
878+ size_t size , offset ;
879+ int bar ;
880+ int xlate_pos ;
881+ u32 ctl_val ;
882+
883+ rc = switchtec_ntb_part_op (sndev , ctl , NTB_CTRL_PART_OP_LOCK ,
884+ NTB_CTRL_PART_STATUS_LOCKED );
885+ if (rc )
886+ return rc ;
887+
888+ for (i = 0 ; i < sndev -> nr_lut_mw ; i ++ ) {
889+ if (i == ntb_lut_idx )
890+ continue ;
891+
892+ addr = mw_addrs [0 ] + LUT_SIZE * i ;
893+
894+ iowrite64 ((NTB_CTRL_LUT_EN | (sndev -> peer_partition << 1 ) |
895+ addr ),
896+ & ctl -> lut_entry [i ]);
897+ }
898+
899+ sndev -> nr_direct_mw = min_t (int , sndev -> nr_direct_mw , mw_count );
900+
901+ for (i = 0 ; i < sndev -> nr_direct_mw ; i ++ ) {
902+ bar = sndev -> direct_mw_to_bar [i ];
903+ offset = (i == 0 ) ? LUT_SIZE * sndev -> nr_lut_mw : 0 ;
904+ addr = mw_addrs [i ] + offset ;
905+ size = pci_resource_len (sndev -> ntb .pdev , bar ) - offset ;
906+ xlate_pos = ilog2 (size );
907+
908+ if (offset && size > offset )
909+ size = offset ;
910+
911+ ctl_val = ioread32 (& ctl -> bar_entry [bar ].ctl );
912+ ctl_val |= NTB_CTRL_BAR_DIR_WIN_EN ;
913+
914+ iowrite32 (ctl_val , & ctl -> bar_entry [bar ].ctl );
915+ iowrite32 (xlate_pos | size , & ctl -> bar_entry [bar ].win_size );
916+ iowrite64 (sndev -> peer_partition | addr ,
917+ & ctl -> bar_entry [bar ].xlate_addr );
918+ }
919+
920+ rc = switchtec_ntb_part_op (sndev , ctl , NTB_CTRL_PART_OP_CFG ,
921+ NTB_CTRL_PART_STATUS_NORMAL );
922+ if (rc ) {
923+ u32 bar_error , lut_error ;
924+
925+ bar_error = ioread32 (& ctl -> bar_error );
926+ lut_error = ioread32 (& ctl -> lut_error );
927+ dev_err (& sndev -> stdev -> dev ,
928+ "Error setting up cross link windows: %08x / %08x" ,
929+ bar_error , lut_error );
930+ return rc ;
931+ }
932+
933+ return 0 ;
934+ }
935+
936+ static int crosslink_setup_req_ids (struct switchtec_ntb * sndev ,
937+ struct ntb_ctrl_regs __iomem * mmio_ctrl )
938+ {
939+ int req_ids [16 ];
940+ int i ;
941+ u32 proxy_id ;
942+
943+ for (i = 0 ; i < ARRAY_SIZE (req_ids ); i ++ ) {
944+ proxy_id = ioread32 (& sndev -> mmio_self_ctrl -> req_id_table [i ]);
945+
946+ if (!(proxy_id & NTB_CTRL_REQ_ID_EN ))
947+ break ;
948+
949+ req_ids [i ] = ((proxy_id >> 1 ) & 0xFF );
950+ }
951+
952+ return config_req_id_table (sndev , mmio_ctrl , req_ids , i );
953+ }
954+
955+ /*
956+ * In crosslink configuration there is a virtual partition in the
957+ * middle of the two switches. The BARs in this partition have to be
958+ * enumerated and assigned addresses.
959+ */
960+ static int crosslink_enum_partition (struct switchtec_ntb * sndev ,
961+ u64 * bar_addrs )
962+ {
963+ struct part_cfg_regs __iomem * part_cfg =
964+ & sndev -> stdev -> mmio_part_cfg_all [sndev -> peer_partition ];
965+ u32 pff = ioread32 (& part_cfg -> vep_pff_inst_id );
966+ struct pff_csr_regs __iomem * mmio_pff =
967+ & sndev -> stdev -> mmio_pff_csr [pff ];
968+ const u64 bar_space = 0x1000000000LL ;
969+ u64 bar_addr ;
970+ int bar_cnt = 0 ;
971+ int i ;
972+
973+ iowrite16 (0x6 , & mmio_pff -> pcicmd );
974+
975+ for (i = 0 ; i < ARRAY_SIZE (mmio_pff -> pci_bar64 ); i ++ ) {
976+ iowrite64 (bar_space * i , & mmio_pff -> pci_bar64 [i ]);
977+ bar_addr = ioread64 (& mmio_pff -> pci_bar64 [i ]);
978+ bar_addr &= ~0xf ;
979+
980+ dev_dbg (& sndev -> stdev -> dev ,
981+ "Crosslink BAR%d addr: %llx\n" ,
982+ i , bar_addr );
983+
984+ if (bar_addr != bar_space * i )
985+ continue ;
986+
987+ bar_addrs [bar_cnt ++ ] = bar_addr ;
988+ }
989+
990+ return bar_cnt ;
991+ }
992+
993+ static int switchtec_ntb_init_crosslink (struct switchtec_ntb * sndev )
994+ {
995+ int rc ;
996+ int bar = sndev -> direct_mw_to_bar [0 ];
997+ const int ntb_lut_idx = 1 ;
998+ u64 bar_addrs [6 ];
999+ u64 addr ;
1000+ int bar_cnt ;
1001+
1002+ if (!crosslink_is_enabled (sndev ))
1003+ return 0 ;
1004+
1005+ dev_info (& sndev -> stdev -> dev , "Using crosslink configuration" );
1006+
1007+ bar_cnt = crosslink_enum_partition (sndev , bar_addrs );
1008+ if (bar_cnt < sndev -> nr_direct_mw + 1 ) {
1009+ dev_err (& sndev -> stdev -> dev ,
1010+ "Error enumerating crosslink partition\n" );
1011+ return - EINVAL ;
1012+ }
1013+
1014+ addr = bar_addrs [0 ];
1015+ rc = config_rsvd_lut_win (sndev , sndev -> mmio_self_ctrl , ntb_lut_idx ,
1016+ sndev -> peer_partition , addr );
1017+ if (rc )
1018+ return rc ;
1019+
1020+ rc = crosslink_setup_mws (sndev , ntb_lut_idx , & bar_addrs [1 ],
1021+ bar_cnt - 1 );
1022+ if (rc )
1023+ return rc ;
1024+
1025+ rc = crosslink_setup_req_ids (sndev , sndev -> mmio_peer_ctrl );
1026+ if (rc )
1027+ return rc ;
1028+
1029+ sndev -> mmio_xlink_win = pci_iomap_range (sndev -> stdev -> pdev , bar ,
1030+ LUT_SIZE , LUT_SIZE );
1031+ if (!sndev -> mmio_xlink_win ) {
1032+ rc = - ENOMEM ;
1033+ return rc ;
1034+ }
1035+
1036+ sndev -> nr_rsvd_luts ++ ;
1037+
1038+ return 0 ;
1039+ }
1040+
1041+ static void switchtec_ntb_deinit_crosslink (struct switchtec_ntb * sndev )
1042+ {
1043+ if (sndev -> mmio_xlink_win )
1044+ pci_iounmap (sndev -> stdev -> pdev , sndev -> mmio_xlink_win );
1045+ }
1046+
8641047static int map_bars (int * map , struct ntb_ctrl_regs __iomem * ctrl )
8651048{
8661049 int i ;
@@ -1147,17 +1330,22 @@ static int switchtec_ntb_add(struct device *dev,
11471330 sndev -> stdev = stdev ;
11481331 switchtec_ntb_init_sndev (sndev );
11491332 switchtec_ntb_init_mw (sndev );
1150- switchtec_ntb_init_db (sndev );
1151- switchtec_ntb_init_msgs (sndev );
11521333
11531334 rc = switchtec_ntb_init_req_id_table (sndev );
11541335 if (rc )
11551336 goto free_and_exit ;
11561337
1157- rc = switchtec_ntb_init_shared_mw (sndev );
1338+ rc = switchtec_ntb_init_crosslink (sndev );
11581339 if (rc )
11591340 goto free_and_exit ;
11601341
1342+ switchtec_ntb_init_db (sndev );
1343+ switchtec_ntb_init_msgs (sndev );
1344+
1345+ rc = switchtec_ntb_init_shared_mw (sndev );
1346+ if (rc )
1347+ goto deinit_crosslink ;
1348+
11611349 rc = switchtec_ntb_init_db_msg_irq (sndev );
11621350 if (rc )
11631351 goto deinit_shared_and_exit ;
@@ -1176,6 +1364,8 @@ static int switchtec_ntb_add(struct device *dev,
11761364 switchtec_ntb_deinit_db_msg_irq (sndev );
11771365deinit_shared_and_exit :
11781366 switchtec_ntb_deinit_shared_mw (sndev );
1367+ deinit_crosslink :
1368+ switchtec_ntb_deinit_crosslink (sndev );
11791369free_and_exit :
11801370 kfree (sndev );
11811371 dev_err (dev , "failed to register ntb device: %d" , rc );
@@ -1196,6 +1386,7 @@ void switchtec_ntb_remove(struct device *dev,
11961386 ntb_unregister_device (& sndev -> ntb );
11971387 switchtec_ntb_deinit_db_msg_irq (sndev );
11981388 switchtec_ntb_deinit_shared_mw (sndev );
1389+ switchtec_ntb_deinit_crosslink (sndev );
11991390 kfree (sndev );
12001391 dev_info (dev , "ntb device unregistered" );
12011392}
0 commit comments