Skip to content

Commit 0643de6

Browse files
committed
Add crosslink initialization
1 parent 72fc6f7 commit 0643de6

File tree

2 files changed

+205
-5
lines changed

2 files changed

+205
-5
lines changed

linux/switchtec.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,15 @@ struct ntb_info_regs {
172172
u16 reserved1;
173173
u64 ep_map;
174174
u16 requester_id;
175+
u16 reserved2;
176+
u32 reserved3[4];
177+
struct {
178+
u8 enabled;
179+
u8 partition_vec_low;
180+
u8 partition_vec_high;
181+
u8 reserved1;
182+
u32 reserved2[3];
183+
} crosslink[48];
175184
} __packed;
176185

177186
struct part_cfg_regs {

ntb_hw_switchtec.c

Lines changed: 196 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
445454
enum {
446455
LINK_MESSAGE = 0,
447456
MSG_LINK_UP = 1,
@@ -774,8 +783,7 @@ static void switchtec_ntb_init_sndev(struct switchtec_ntb *sndev)
774783

775784
static 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+
8641047
static 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);
11771365
deinit_shared_and_exit:
11781366
switchtec_ntb_deinit_shared_mw(sndev);
1367+
deinit_crosslink:
1368+
switchtec_ntb_deinit_crosslink(sndev);
11791369
free_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

Comments
 (0)