diff options
-rw-r--r-- | drivers/ntb/hw/mscc/ntb_hw_switchtec.c | 65 |
1 files changed, 55 insertions, 10 deletions
diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c index 17db0f50bb22..145b31209f20 100644 --- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c +++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c | |||
@@ -94,6 +94,7 @@ struct switchtec_ntb { | |||
94 | struct ntb_ctrl_regs __iomem *mmio_self_ctrl; | 94 | struct ntb_ctrl_regs __iomem *mmio_self_ctrl; |
95 | struct ntb_ctrl_regs __iomem *mmio_peer_ctrl; | 95 | struct ntb_ctrl_regs __iomem *mmio_peer_ctrl; |
96 | struct ntb_dbmsg_regs __iomem *mmio_self_dbmsg; | 96 | struct ntb_dbmsg_regs __iomem *mmio_self_dbmsg; |
97 | struct ntb_dbmsg_regs __iomem *mmio_peer_dbmsg; | ||
97 | 98 | ||
98 | void __iomem *mmio_xlink_win; | 99 | void __iomem *mmio_xlink_win; |
99 | 100 | ||
@@ -188,10 +189,10 @@ static int switchtec_ntb_part_op(struct switchtec_ntb *sndev, | |||
188 | static int switchtec_ntb_send_msg(struct switchtec_ntb *sndev, int idx, | 189 | static int switchtec_ntb_send_msg(struct switchtec_ntb *sndev, int idx, |
189 | u32 val) | 190 | u32 val) |
190 | { | 191 | { |
191 | if (idx < 0 || idx >= ARRAY_SIZE(sndev->mmio_self_dbmsg->omsg)) | 192 | if (idx < 0 || idx >= ARRAY_SIZE(sndev->mmio_peer_dbmsg->omsg)) |
192 | return -EINVAL; | 193 | return -EINVAL; |
193 | 194 | ||
194 | iowrite32(val, &sndev->mmio_self_dbmsg->omsg[idx].msg); | 195 | iowrite32(val, &sndev->mmio_peer_dbmsg->omsg[idx].msg); |
195 | 196 | ||
196 | return 0; | 197 | return 0; |
197 | } | 198 | } |
@@ -474,6 +475,25 @@ static int crosslink_is_enabled(struct switchtec_ntb *sndev) | |||
474 | return ioread8(&inf->ntp_info[sndev->peer_partition].xlink_enabled); | 475 | return ioread8(&inf->ntp_info[sndev->peer_partition].xlink_enabled); |
475 | } | 476 | } |
476 | 477 | ||
478 | static void crosslink_init_dbmsgs(struct switchtec_ntb *sndev) | ||
479 | { | ||
480 | int i; | ||
481 | u32 msg_map = 0; | ||
482 | |||
483 | if (!crosslink_is_enabled(sndev)) | ||
484 | return; | ||
485 | |||
486 | for (i = 0; i < ARRAY_SIZE(sndev->mmio_peer_dbmsg->imsg); i++) { | ||
487 | int m = i | sndev->self_partition << 2; | ||
488 | |||
489 | msg_map |= m << i * 8; | ||
490 | } | ||
491 | |||
492 | iowrite32(msg_map, &sndev->mmio_peer_dbmsg->msg_map); | ||
493 | iowrite64(sndev->db_valid_mask << sndev->db_peer_shift, | ||
494 | &sndev->mmio_peer_dbmsg->odb_mask); | ||
495 | } | ||
496 | |||
477 | enum { | 497 | enum { |
478 | LINK_MESSAGE = 0, | 498 | LINK_MESSAGE = 0, |
479 | MSG_LINK_UP = 1, | 499 | MSG_LINK_UP = 1, |
@@ -504,6 +524,9 @@ static void switchtec_ntb_check_link(struct switchtec_ntb *sndev) | |||
504 | ntb_link_event(&sndev->ntb); | 524 | ntb_link_event(&sndev->ntb); |
505 | dev_info(&sndev->stdev->dev, "ntb link %s\n", | 525 | dev_info(&sndev->stdev->dev, "ntb link %s\n", |
506 | link_sta ? "up" : "down"); | 526 | link_sta ? "up" : "down"); |
527 | |||
528 | if (link_sta) | ||
529 | crosslink_init_dbmsgs(sndev); | ||
507 | } | 530 | } |
508 | } | 531 | } |
509 | 532 | ||
@@ -649,7 +672,7 @@ static int switchtec_ntb_peer_db_addr(struct ntb_dev *ntb, | |||
649 | struct switchtec_ntb *sndev = ntb_sndev(ntb); | 672 | struct switchtec_ntb *sndev = ntb_sndev(ntb); |
650 | unsigned long offset; | 673 | unsigned long offset; |
651 | 674 | ||
652 | offset = (unsigned long)sndev->mmio_self_dbmsg->odb - | 675 | offset = (unsigned long)sndev->mmio_peer_dbmsg->odb - |
653 | (unsigned long)sndev->stdev->mmio; | 676 | (unsigned long)sndev->stdev->mmio; |
654 | 677 | ||
655 | offset += sndev->db_shift / 8; | 678 | offset += sndev->db_shift / 8; |
@@ -667,7 +690,7 @@ static int switchtec_ntb_peer_db_set(struct ntb_dev *ntb, u64 db_bits) | |||
667 | struct switchtec_ntb *sndev = ntb_sndev(ntb); | 690 | struct switchtec_ntb *sndev = ntb_sndev(ntb); |
668 | 691 | ||
669 | iowrite64(db_bits << sndev->db_peer_shift, | 692 | iowrite64(db_bits << sndev->db_peer_shift, |
670 | &sndev->mmio_self_dbmsg->odb); | 693 | &sndev->mmio_peer_dbmsg->odb); |
671 | 694 | ||
672 | return 0; | 695 | return 0; |
673 | } | 696 | } |
@@ -852,6 +875,7 @@ static int switchtec_ntb_init_sndev(struct switchtec_ntb *sndev) | |||
852 | sndev->mmio_self_ctrl = &sndev->mmio_ctrl[sndev->self_partition]; | 875 | sndev->mmio_self_ctrl = &sndev->mmio_ctrl[sndev->self_partition]; |
853 | sndev->mmio_peer_ctrl = &sndev->mmio_ctrl[sndev->peer_partition]; | 876 | sndev->mmio_peer_ctrl = &sndev->mmio_ctrl[sndev->peer_partition]; |
854 | sndev->mmio_self_dbmsg = &sndev->mmio_dbmsg[sndev->self_partition]; | 877 | sndev->mmio_self_dbmsg = &sndev->mmio_dbmsg[sndev->self_partition]; |
878 | sndev->mmio_peer_dbmsg = sndev->mmio_self_dbmsg; | ||
855 | 879 | ||
856 | return 0; | 880 | return 0; |
857 | } | 881 | } |
@@ -1072,6 +1096,7 @@ static int switchtec_ntb_init_crosslink(struct switchtec_ntb *sndev) | |||
1072 | const int ntb_lut_idx = 1; | 1096 | const int ntb_lut_idx = 1; |
1073 | u64 bar_addrs[6]; | 1097 | u64 bar_addrs[6]; |
1074 | u64 addr; | 1098 | u64 addr; |
1099 | int offset; | ||
1075 | int bar_cnt; | 1100 | int bar_cnt; |
1076 | 1101 | ||
1077 | if (!crosslink_is_enabled(sndev)) | 1102 | if (!crosslink_is_enabled(sndev)) |
@@ -1087,7 +1112,13 @@ static int switchtec_ntb_init_crosslink(struct switchtec_ntb *sndev) | |||
1087 | return -EINVAL; | 1112 | return -EINVAL; |
1088 | } | 1113 | } |
1089 | 1114 | ||
1090 | addr = bar_addrs[0]; | 1115 | addr = (bar_addrs[0] + SWITCHTEC_GAS_NTB_OFFSET + |
1116 | SWITCHTEC_NTB_REG_DBMSG_OFFSET + | ||
1117 | sizeof(struct ntb_dbmsg_regs) * sndev->peer_partition); | ||
1118 | |||
1119 | offset = addr & (LUT_SIZE - 1); | ||
1120 | addr -= offset; | ||
1121 | |||
1091 | rc = config_rsvd_lut_win(sndev, sndev->mmio_self_ctrl, ntb_lut_idx, | 1122 | rc = config_rsvd_lut_win(sndev, sndev->mmio_self_ctrl, ntb_lut_idx, |
1092 | sndev->peer_partition, addr); | 1123 | sndev->peer_partition, addr); |
1093 | if (rc) | 1124 | if (rc) |
@@ -1109,8 +1140,11 @@ static int switchtec_ntb_init_crosslink(struct switchtec_ntb *sndev) | |||
1109 | return rc; | 1140 | return rc; |
1110 | } | 1141 | } |
1111 | 1142 | ||
1143 | sndev->mmio_peer_dbmsg = sndev->mmio_xlink_win + offset; | ||
1112 | sndev->nr_rsvd_luts++; | 1144 | sndev->nr_rsvd_luts++; |
1113 | 1145 | ||
1146 | crosslink_init_dbmsgs(sndev); | ||
1147 | |||
1114 | return 0; | 1148 | return 0; |
1115 | } | 1149 | } |
1116 | 1150 | ||
@@ -1163,24 +1197,35 @@ static void switchtec_ntb_init_mw(struct switchtec_ntb *sndev) | |||
1163 | * shared among all partitions. So we must split them in half | 1197 | * shared among all partitions. So we must split them in half |
1164 | * (32 for each partition). However, the message interrupts are | 1198 | * (32 for each partition). However, the message interrupts are |
1165 | * also shared with the top 4 doorbells so we just limit this to | 1199 | * also shared with the top 4 doorbells so we just limit this to |
1166 | * 28 doorbells per partition | 1200 | * 28 doorbells per partition. |
1201 | * | ||
1202 | * In crosslink mode, each side has it's own dbmsg register so | ||
1203 | * they can each use all 60 of the available doorbells. | ||
1167 | */ | 1204 | */ |
1168 | static void switchtec_ntb_init_db(struct switchtec_ntb *sndev) | 1205 | static void switchtec_ntb_init_db(struct switchtec_ntb *sndev) |
1169 | { | 1206 | { |
1170 | sndev->db_valid_mask = 0x0FFFFFFF; | 1207 | sndev->db_mask = 0x0FFFFFFFFFFFFFFFULL; |
1171 | 1208 | ||
1172 | if (sndev->self_partition < sndev->peer_partition) { | 1209 | if (sndev->mmio_peer_dbmsg != sndev->mmio_self_dbmsg) { |
1210 | sndev->db_shift = 0; | ||
1211 | sndev->db_peer_shift = 0; | ||
1212 | sndev->db_valid_mask = sndev->db_mask; | ||
1213 | } else if (sndev->self_partition < sndev->peer_partition) { | ||
1173 | sndev->db_shift = 0; | 1214 | sndev->db_shift = 0; |
1174 | sndev->db_peer_shift = 32; | 1215 | sndev->db_peer_shift = 32; |
1216 | sndev->db_valid_mask = 0x0FFFFFFF; | ||
1175 | } else { | 1217 | } else { |
1176 | sndev->db_shift = 32; | 1218 | sndev->db_shift = 32; |
1177 | sndev->db_peer_shift = 0; | 1219 | sndev->db_peer_shift = 0; |
1220 | sndev->db_valid_mask = 0x0FFFFFFF; | ||
1178 | } | 1221 | } |
1179 | 1222 | ||
1180 | sndev->db_mask = 0x0FFFFFFFFFFFFFFFULL; | ||
1181 | iowrite64(~sndev->db_mask, &sndev->mmio_self_dbmsg->idb_mask); | 1223 | iowrite64(~sndev->db_mask, &sndev->mmio_self_dbmsg->idb_mask); |
1182 | iowrite64(sndev->db_valid_mask << sndev->db_peer_shift, | 1224 | iowrite64(sndev->db_valid_mask << sndev->db_peer_shift, |
1183 | &sndev->mmio_self_dbmsg->odb_mask); | 1225 | &sndev->mmio_peer_dbmsg->odb_mask); |
1226 | |||
1227 | dev_dbg(&sndev->stdev->dev, "dbs: shift %d/%d, mask %016llx\n", | ||
1228 | sndev->db_shift, sndev->db_peer_shift, sndev->db_valid_mask); | ||
1184 | } | 1229 | } |
1185 | 1230 | ||
1186 | static void switchtec_ntb_init_msgs(struct switchtec_ntb *sndev) | 1231 | static void switchtec_ntb_init_msgs(struct switchtec_ntb *sndev) |