summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ntb/hw/mscc/ntb_hw_switchtec.c65
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,
188static int switchtec_ntb_send_msg(struct switchtec_ntb *sndev, int idx, 189static 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
478static 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
477enum { 497enum {
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 */
1168static void switchtec_ntb_init_db(struct switchtec_ntb *sndev) 1205static 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
1186static void switchtec_ntb_init_msgs(struct switchtec_ntb *sndev) 1231static void switchtec_ntb_init_msgs(struct switchtec_ntb *sndev)