Rev 6088 | Rev 6660 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 6088 | Rev 6320 | ||
---|---|---|---|
Line 804... | Line 804... | ||
804 | INIT_LIST_HEAD(&mstb->ports); |
804 | INIT_LIST_HEAD(&mstb->ports); |
805 | kref_init(&mstb->kref); |
805 | kref_init(&mstb->kref); |
806 | return mstb; |
806 | return mstb; |
807 | } |
807 | } |
Line -... | Line 808... | ||
- | 808 | ||
- | 809 | static void drm_dp_free_mst_port(struct kref *kref); |
|
- | 810 | ||
- | 811 | static void drm_dp_free_mst_branch_device(struct kref *kref) |
|
- | 812 | { |
|
- | 813 | struct drm_dp_mst_branch *mstb = container_of(kref, struct drm_dp_mst_branch, kref); |
|
- | 814 | if (mstb->port_parent) { |
|
- | 815 | if (list_empty(&mstb->port_parent->next)) |
|
- | 816 | kref_put(&mstb->port_parent->kref, drm_dp_free_mst_port); |
|
- | 817 | } |
|
- | 818 | kfree(mstb); |
|
- | 819 | } |
|
808 | 820 | ||
809 | static void drm_dp_destroy_mst_branch_device(struct kref *kref) |
821 | static void drm_dp_destroy_mst_branch_device(struct kref *kref) |
810 | { |
822 | { |
811 | struct drm_dp_mst_branch *mstb = container_of(kref, struct drm_dp_mst_branch, kref); |
823 | struct drm_dp_mst_branch *mstb = container_of(kref, struct drm_dp_mst_branch, kref); |
812 | struct drm_dp_mst_port *port, *tmp; |
824 | struct drm_dp_mst_port *port, *tmp; |
Line 813... | Line 825... | ||
813 | bool wake_tx = false; |
825 | bool wake_tx = false; |
- | 826 | ||
- | 827 | /* |
|
- | 828 | * init kref again to be used by ports to remove mst branch when it is |
|
- | 829 | * not needed anymore |
|
- | 830 | */ |
|
- | 831 | kref_init(kref); |
|
- | 832 | ||
- | 833 | if (mstb->port_parent && list_empty(&mstb->port_parent->next)) |
|
- | 834 | kref_get(&mstb->port_parent->kref); |
|
814 | 835 | ||
815 | /* |
836 | /* |
816 | * destroy all ports - don't need lock |
837 | * destroy all ports - don't need lock |
817 | * as there are no more references to the mst branch |
838 | * as there are no more references to the mst branch |
818 | * device at this point. |
839 | * device at this point. |
Line 836... | Line 857... | ||
836 | } |
857 | } |
837 | mutex_unlock(&mstb->mgr->qlock); |
858 | mutex_unlock(&mstb->mgr->qlock); |
Line 838... | Line 859... | ||
838 | 859 | ||
839 | // if (wake_tx) |
860 | // if (wake_tx) |
840 | // wake_up(&mstb->mgr->tx_waitq); |
861 | // wake_up(&mstb->mgr->tx_waitq); |
841 | kfree(mstb); |
862 | kref_put(kref, drm_dp_free_mst_branch_device); |
Line 842... | Line 863... | ||
842 | } |
863 | } |
843 | 864 | ||
844 | static void drm_dp_put_mst_branch_device(struct drm_dp_mst_branch *mstb) |
865 | static void drm_dp_put_mst_branch_device(struct drm_dp_mst_branch *mstb) |
Line 884... | Line 905... | ||
884 | /* we can't destroy the connector here, as |
905 | /* we can't destroy the connector here, as |
885 | * we might be holding the mode_config.mutex |
906 | * we might be holding the mode_config.mutex |
886 | * from an EDID retrieval */ |
907 | * from an EDID retrieval */ |
Line 887... | Line 908... | ||
887 | 908 | ||
- | 909 | mutex_lock(&mgr->destroy_connector_lock); |
|
888 | mutex_lock(&mgr->destroy_connector_lock); |
910 | kref_get(&port->parent->kref); |
889 | list_add(&port->next, &mgr->destroy_connector_list); |
911 | list_add(&port->next, &mgr->destroy_connector_list); |
890 | mutex_unlock(&mgr->destroy_connector_lock); |
912 | mutex_unlock(&mgr->destroy_connector_lock); |
891 | // schedule_work(&mgr->destroy_connector_work); |
913 | // schedule_work(&mgr->destroy_connector_work); |
892 | return; |
914 | return; |
Line 979... | Line 1001... | ||
979 | * if parent has an LCT of 3 then it has 2 nibbles of RAD, |
1001 | * if parent has an LCT of 3 then it has 2 nibbles of RAD, |
980 | */ |
1002 | */ |
981 | static u8 drm_dp_calculate_rad(struct drm_dp_mst_port *port, |
1003 | static u8 drm_dp_calculate_rad(struct drm_dp_mst_port *port, |
982 | u8 *rad) |
1004 | u8 *rad) |
983 | { |
1005 | { |
984 | int lct = port->parent->lct; |
1006 | int parent_lct = port->parent->lct; |
985 | int shift = 4; |
1007 | int shift = 4; |
986 | int idx = lct / 2; |
1008 | int idx = (parent_lct - 1) / 2; |
987 | if (lct > 1) { |
1009 | if (parent_lct > 1) { |
988 | memcpy(rad, port->parent->rad, idx); |
1010 | memcpy(rad, port->parent->rad, idx + 1); |
989 | shift = (lct % 2) ? 4 : 0; |
1011 | shift = (parent_lct % 2) ? 4 : 0; |
990 | } else |
1012 | } else |
991 | rad[0] = 0; |
1013 | rad[0] = 0; |
Line 992... | Line 1014... | ||
992 | 1014 | ||
993 | rad[idx] |= port->port_num << shift; |
1015 | rad[idx] |= port->port_num << shift; |
994 | return lct + 1; |
1016 | return parent_lct + 1; |
Line 995... | Line 1017... | ||
995 | } |
1017 | } |
996 | 1018 | ||
997 | /* |
1019 | /* |
Line 1019... | Line 1041... | ||
1019 | break; |
1041 | break; |
1020 | } |
1042 | } |
1021 | return send_link; |
1043 | return send_link; |
1022 | } |
1044 | } |
Line 1023... | Line 1045... | ||
1023 | 1045 | ||
1024 | static void drm_dp_check_port_guid(struct drm_dp_mst_branch *mstb, |
- | |
1025 | struct drm_dp_mst_port *port) |
1046 | static void drm_dp_check_mstb_guid(struct drm_dp_mst_branch *mstb, u8 *guid) |
1026 | { |
1047 | { |
- | 1048 | int ret; |
|
1027 | int ret; |
1049 | |
- | 1050 | memcpy(mstb->guid, guid, 16); |
|
1028 | if (port->dpcd_rev >= 0x12) { |
1051 | |
1029 | port->guid_valid = drm_dp_validate_guid(mstb->mgr, port->guid); |
1052 | if (!drm_dp_validate_guid(mstb->mgr, mstb->guid)) { |
1030 | if (!port->guid_valid) { |
1053 | if (mstb->port_parent) { |
1031 | ret = drm_dp_send_dpcd_write(mstb->mgr, |
1054 | ret = drm_dp_send_dpcd_write( |
- | 1055 | mstb->mgr, |
|
- | 1056 | mstb->port_parent, |
|
- | 1057 | DP_GUID, |
|
- | 1058 | 16, |
|
- | 1059 | mstb->guid); |
|
- | 1060 | } else { |
|
- | 1061 | ||
- | 1062 | ret = drm_dp_dpcd_write( |
|
1032 | port, |
1063 | mstb->mgr->aux, |
1033 | DP_GUID, |
1064 | DP_GUID, |
1034 | 16, port->guid); |
1065 | mstb->guid, |
1035 | port->guid_valid = true; |
1066 | 16); |
1036 | } |
1067 | } |
1037 | } |
1068 | } |
Line 1038... | Line 1069... | ||
1038 | } |
1069 | } |
Line 1045... | Line 1076... | ||
1045 | int i; |
1076 | int i; |
1046 | char temp[8]; |
1077 | char temp[8]; |
1047 | snprintf(proppath, proppath_size, "mst:%d", mstb->mgr->conn_base_id); |
1078 | snprintf(proppath, proppath_size, "mst:%d", mstb->mgr->conn_base_id); |
1048 | for (i = 0; i < (mstb->lct - 1); i++) { |
1079 | for (i = 0; i < (mstb->lct - 1); i++) { |
1049 | int shift = (i % 2) ? 0 : 4; |
1080 | int shift = (i % 2) ? 0 : 4; |
1050 | int port_num = mstb->rad[i / 2] >> shift; |
1081 | int port_num = (mstb->rad[i / 2] >> shift) & 0xf; |
1051 | snprintf(temp, sizeof(temp), "-%d", port_num); |
1082 | snprintf(temp, sizeof(temp), "-%d", port_num); |
1052 | strlcat(proppath, temp, proppath_size); |
1083 | strlcat(proppath, temp, proppath_size); |
1053 | } |
1084 | } |
1054 | snprintf(temp, sizeof(temp), "-%d", pnum); |
1085 | snprintf(temp, sizeof(temp), "-%d", pnum); |
1055 | strlcat(proppath, temp, proppath_size); |
1086 | strlcat(proppath, temp, proppath_size); |
Line 1087... | Line 1118... | ||
1087 | port->ddps = port_msg->ddps; |
1118 | port->ddps = port_msg->ddps; |
1088 | port->ldps = port_msg->legacy_device_plug_status; |
1119 | port->ldps = port_msg->legacy_device_plug_status; |
1089 | port->dpcd_rev = port_msg->dpcd_revision; |
1120 | port->dpcd_rev = port_msg->dpcd_revision; |
1090 | port->num_sdp_streams = port_msg->num_sdp_streams; |
1121 | port->num_sdp_streams = port_msg->num_sdp_streams; |
1091 | port->num_sdp_stream_sinks = port_msg->num_sdp_stream_sinks; |
1122 | port->num_sdp_stream_sinks = port_msg->num_sdp_stream_sinks; |
1092 | memcpy(port->guid, port_msg->peer_guid, 16); |
- | |
Line 1093... | Line 1123... | ||
1093 | 1123 | ||
1094 | /* manage mstb port lists with mgr lock - take a reference |
1124 | /* manage mstb port lists with mgr lock - take a reference |
1095 | for this list */ |
1125 | for this list */ |
1096 | if (created) { |
1126 | if (created) { |
Line 1100... | Line 1130... | ||
1100 | mutex_unlock(&mstb->mgr->lock); |
1130 | mutex_unlock(&mstb->mgr->lock); |
1101 | } |
1131 | } |
Line 1102... | Line 1132... | ||
1102 | 1132 | ||
1103 | if (old_ddps != port->ddps) { |
1133 | if (old_ddps != port->ddps) { |
1104 | if (port->ddps) { |
- | |
1105 | drm_dp_check_port_guid(mstb, port); |
1134 | if (port->ddps) { |
1106 | if (!port->input) |
1135 | if (!port->input) |
1107 | drm_dp_send_enum_path_resources(mstb->mgr, mstb, port); |
1136 | drm_dp_send_enum_path_resources(mstb->mgr, mstb, port); |
1108 | } else { |
- | |
1109 | port->guid_valid = false; |
1137 | } else { |
1110 | port->available_pbn = 0; |
1138 | port->available_pbn = 0; |
1111 | } |
1139 | } |
Line 1112... | Line 1140... | ||
1112 | } |
1140 | } |
Line 1163... | Line 1191... | ||
1163 | port->ldps = conn_stat->legacy_device_plug_status; |
1191 | port->ldps = conn_stat->legacy_device_plug_status; |
1164 | port->ddps = conn_stat->displayport_device_plug_status; |
1192 | port->ddps = conn_stat->displayport_device_plug_status; |
Line 1165... | Line 1193... | ||
1165 | 1193 | ||
1166 | if (old_ddps != port->ddps) { |
1194 | if (old_ddps != port->ddps) { |
1167 | if (port->ddps) { |
- | |
1168 | drm_dp_check_port_guid(mstb, port); |
1195 | if (port->ddps) { |
1169 | dowork = true; |
1196 | dowork = true; |
1170 | } else { |
- | |
1171 | port->guid_valid = false; |
1197 | } else { |
1172 | port->available_pbn = 0; |
1198 | port->available_pbn = 0; |
1173 | } |
1199 | } |
1174 | } |
1200 | } |
1175 | if (old_pdt != port->pdt && !port->input) { |
1201 | if (old_pdt != port->pdt && !port->input) { |
Line 1196... | Line 1222... | ||
1196 | mutex_lock(&mgr->lock); |
1222 | mutex_lock(&mgr->lock); |
1197 | mstb = mgr->mst_primary; |
1223 | mstb = mgr->mst_primary; |
Line 1198... | Line 1224... | ||
1198 | 1224 | ||
1199 | for (i = 0; i < lct - 1; i++) { |
1225 | for (i = 0; i < lct - 1; i++) { |
1200 | int shift = (i % 2) ? 0 : 4; |
1226 | int shift = (i % 2) ? 0 : 4; |
Line 1201... | Line 1227... | ||
1201 | int port_num = rad[i / 2] >> shift; |
1227 | int port_num = (rad[i / 2] >> shift) & 0xf; |
1202 | 1228 | ||
1203 | list_for_each_entry(port, &mstb->ports, next) { |
1229 | list_for_each_entry(port, &mstb->ports, next) { |
1204 | if (port->port_num == port_num) { |
1230 | if (port->port_num == port_num) { |
Line 1216... | Line 1242... | ||
1216 | out: |
1242 | out: |
1217 | mutex_unlock(&mgr->lock); |
1243 | mutex_unlock(&mgr->lock); |
1218 | return mstb; |
1244 | return mstb; |
1219 | } |
1245 | } |
Line -... | Line 1246... | ||
- | 1246 | ||
- | 1247 | static struct drm_dp_mst_branch *get_mst_branch_device_by_guid_helper( |
|
- | 1248 | struct drm_dp_mst_branch *mstb, |
|
- | 1249 | uint8_t *guid) |
|
- | 1250 | { |
|
- | 1251 | struct drm_dp_mst_branch *found_mstb; |
|
- | 1252 | struct drm_dp_mst_port *port; |
|
- | 1253 | ||
- | 1254 | if (memcmp(mstb->guid, guid, 16) == 0) |
|
- | 1255 | return mstb; |
|
- | 1256 | ||
- | 1257 | ||
- | 1258 | list_for_each_entry(port, &mstb->ports, next) { |
|
- | 1259 | if (!port->mstb) |
|
- | 1260 | continue; |
|
- | 1261 | ||
- | 1262 | found_mstb = get_mst_branch_device_by_guid_helper(port->mstb, guid); |
|
- | 1263 | ||
- | 1264 | if (found_mstb) |
|
- | 1265 | return found_mstb; |
|
- | 1266 | } |
|
- | 1267 | ||
- | 1268 | return NULL; |
|
- | 1269 | } |
|
- | 1270 | ||
- | 1271 | static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device_by_guid( |
|
- | 1272 | struct drm_dp_mst_topology_mgr *mgr, |
|
- | 1273 | uint8_t *guid) |
|
- | 1274 | { |
|
- | 1275 | struct drm_dp_mst_branch *mstb; |
|
- | 1276 | ||
- | 1277 | /* find the port by iterating down */ |
|
- | 1278 | mutex_lock(&mgr->lock); |
|
- | 1279 | ||
- | 1280 | mstb = get_mst_branch_device_by_guid_helper(mgr->mst_primary, guid); |
|
- | 1281 | ||
- | 1282 | if (mstb) |
|
- | 1283 | kref_get(&mstb->kref); |
|
- | 1284 | ||
- | 1285 | mutex_unlock(&mgr->lock); |
|
- | 1286 | return mstb; |
|
- | 1287 | } |
|
1220 | 1288 | ||
1221 | static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *mgr, |
1289 | static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *mgr, |
1222 | struct drm_dp_mst_branch *mstb) |
1290 | struct drm_dp_mst_branch *mstb) |
1223 | { |
1291 | { |
1224 | struct drm_dp_mst_port *port; |
1292 | struct drm_dp_mst_port *port; |
Line 1326... | Line 1394... | ||
1326 | 1394 | ||
1327 | static int set_hdr_from_dst_qlock(struct drm_dp_sideband_msg_hdr *hdr, |
1395 | static int set_hdr_from_dst_qlock(struct drm_dp_sideband_msg_hdr *hdr, |
1328 | struct drm_dp_sideband_msg_tx *txmsg) |
1396 | struct drm_dp_sideband_msg_tx *txmsg) |
1329 | { |
1397 | { |
- | 1398 | struct drm_dp_mst_branch *mstb = txmsg->dst; |
|
Line 1330... | Line 1399... | ||
1330 | struct drm_dp_mst_branch *mstb = txmsg->dst; |
1399 | u8 req_type; |
1331 | 1400 | ||
1332 | /* both msg slots are full */ |
1401 | /* both msg slots are full */ |
1333 | if (txmsg->seqno == -1) { |
1402 | if (txmsg->seqno == -1) { |
Line 1342... | Line 1411... | ||
1342 | txmsg->seqno = 0; |
1411 | txmsg->seqno = 0; |
1343 | else |
1412 | else |
1344 | txmsg->seqno = 1; |
1413 | txmsg->seqno = 1; |
1345 | mstb->tx_slots[txmsg->seqno] = txmsg; |
1414 | mstb->tx_slots[txmsg->seqno] = txmsg; |
1346 | } |
1415 | } |
- | 1416 | ||
- | 1417 | req_type = txmsg->msg[0] & 0x7f; |
|
- | 1418 | if (req_type == DP_CONNECTION_STATUS_NOTIFY || |
|
- | 1419 | req_type == DP_RESOURCE_STATUS_NOTIFY) |
|
- | 1420 | hdr->broadcast = 1; |
|
- | 1421 | else |
|
1347 | hdr->broadcast = 0; |
1422 | hdr->broadcast = 0; |
1348 | hdr->path_msg = txmsg->path_msg; |
1423 | hdr->path_msg = txmsg->path_msg; |
1349 | hdr->lct = mstb->lct; |
1424 | hdr->lct = mstb->lct; |
1350 | hdr->lcr = mstb->lct - 1; |
1425 | hdr->lcr = mstb->lct - 1; |
1351 | if (mstb->lct > 1) |
1426 | if (mstb->lct > 1) |
Line 1444... | Line 1519... | ||
1444 | return; |
1519 | return; |
1445 | } |
1520 | } |
1446 | } |
1521 | } |
Line 1447... | Line 1522... | ||
1447 | 1522 | ||
1448 | /* called holding qlock */ |
1523 | /* called holding qlock */ |
- | 1524 | static void process_single_up_tx_qlock(struct drm_dp_mst_topology_mgr *mgr, |
|
1449 | static void process_single_up_tx_qlock(struct drm_dp_mst_topology_mgr *mgr) |
1525 | struct drm_dp_sideband_msg_tx *txmsg) |
1450 | { |
- | |
1451 | struct drm_dp_sideband_msg_tx *txmsg; |
1526 | { |
Line 1452... | Line 1527... | ||
1452 | int ret; |
1527 | int ret; |
1453 | - | ||
1454 | /* construct a chunk from the first msg in the tx_msg queue */ |
- | |
1455 | if (list_empty(&mgr->tx_msg_upq)) { |
- | |
1456 | mgr->tx_up_in_progress = false; |
- | |
1457 | return; |
- | |
1458 | } |
- | |
1459 | 1528 | ||
- | 1529 | /* construct a chunk from the first msg in the tx_msg queue */ |
|
1460 | txmsg = list_first_entry(&mgr->tx_msg_upq, struct drm_dp_sideband_msg_tx, next); |
1530 | ret = process_single_tx_qlock(mgr, txmsg, true); |
1461 | ret = process_single_tx_qlock(mgr, txmsg, true); |
- | |
1462 | if (ret == 1) { |
- | |
1463 | /* up txmsgs aren't put in slots - so free after we send it */ |
- | |
1464 | list_del(&txmsg->next); |
- | |
1465 | kfree(txmsg); |
1531 | |
- | 1532 | if (ret != 1) |
|
1466 | } else if (ret) |
1533 | DRM_DEBUG_KMS("failed to send msg in q %d\n", ret); |
1467 | DRM_DEBUG_KMS("failed to send msg in q %d\n", ret); |
1534 | |
Line 1468... | Line 1535... | ||
1468 | mgr->tx_up_in_progress = true; |
1535 | txmsg->dst->tx_slots[txmsg->seqno] = NULL; |
1469 | } |
1536 | } |
1470 | 1537 | ||
Line 1513... | Line 1580... | ||
1513 | txmsg->reply.u.link_addr.ports[i].ddps, |
1580 | txmsg->reply.u.link_addr.ports[i].ddps, |
1514 | txmsg->reply.u.link_addr.ports[i].legacy_device_plug_status, |
1581 | txmsg->reply.u.link_addr.ports[i].legacy_device_plug_status, |
1515 | txmsg->reply.u.link_addr.ports[i].num_sdp_streams, |
1582 | txmsg->reply.u.link_addr.ports[i].num_sdp_streams, |
1516 | txmsg->reply.u.link_addr.ports[i].num_sdp_stream_sinks); |
1583 | txmsg->reply.u.link_addr.ports[i].num_sdp_stream_sinks); |
1517 | } |
1584 | } |
- | 1585 | ||
- | 1586 | drm_dp_check_mstb_guid(mstb, txmsg->reply.u.link_addr.guid); |
|
- | 1587 | ||
1518 | for (i = 0; i < txmsg->reply.u.link_addr.nports; i++) { |
1588 | for (i = 0; i < txmsg->reply.u.link_addr.nports; i++) { |
1519 | drm_dp_add_port(mstb, mgr->dev, &txmsg->reply.u.link_addr.ports[i]); |
1589 | drm_dp_add_port(mstb, mgr->dev, &txmsg->reply.u.link_addr.ports[i]); |
1520 | } |
1590 | } |
1521 | (*mgr->cbs->hotplug)(mgr); |
1591 | (*mgr->cbs->hotplug)(mgr); |
1522 | } |
1592 | } |
Line 1560... | Line 1630... | ||
1560 | 1630 | ||
1561 | kfree(txmsg); |
1631 | kfree(txmsg); |
1562 | return 0; |
1632 | return 0; |
Line -... | Line 1633... | ||
- | 1633 | } |
|
- | 1634 | ||
- | 1635 | static struct drm_dp_mst_port *drm_dp_get_last_connected_port_to_mstb(struct drm_dp_mst_branch *mstb) |
|
- | 1636 | { |
|
- | 1637 | if (!mstb->port_parent) |
|
- | 1638 | return NULL; |
|
- | 1639 | ||
- | 1640 | if (mstb->port_parent->mstb != mstb) |
|
- | 1641 | return mstb->port_parent; |
|
- | 1642 | ||
- | 1643 | return drm_dp_get_last_connected_port_to_mstb(mstb->port_parent->parent); |
|
- | 1644 | } |
|
- | 1645 | ||
- | 1646 | static struct drm_dp_mst_branch *drm_dp_get_last_connected_port_and_mstb(struct drm_dp_mst_topology_mgr *mgr, |
|
- | 1647 | struct drm_dp_mst_branch *mstb, |
|
- | 1648 | int *port_num) |
|
- | 1649 | { |
|
- | 1650 | struct drm_dp_mst_branch *rmstb = NULL; |
|
- | 1651 | struct drm_dp_mst_port *found_port; |
|
- | 1652 | mutex_lock(&mgr->lock); |
|
- | 1653 | if (mgr->mst_primary) { |
|
- | 1654 | found_port = drm_dp_get_last_connected_port_to_mstb(mstb); |
|
- | 1655 | ||
- | 1656 | if (found_port) { |
|
- | 1657 | rmstb = found_port->parent; |
|
- | 1658 | kref_get(&rmstb->kref); |
|
- | 1659 | *port_num = found_port->port_num; |
|
- | 1660 | } |
|
- | 1661 | } |
|
- | 1662 | mutex_unlock(&mgr->lock); |
|
- | 1663 | return rmstb; |
|
1563 | } |
1664 | } |
1564 | 1665 | ||
1565 | static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr, |
1666 | static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr, |
1566 | struct drm_dp_mst_port *port, |
1667 | struct drm_dp_mst_port *port, |
1567 | int id, |
1668 | int id, |
1568 | int pbn) |
1669 | int pbn) |
1569 | { |
1670 | { |
1570 | struct drm_dp_sideband_msg_tx *txmsg; |
1671 | struct drm_dp_sideband_msg_tx *txmsg; |
Line -... | Line 1672... | ||
- | 1672 | struct drm_dp_mst_branch *mstb; |
|
1571 | struct drm_dp_mst_branch *mstb; |
1673 | int len, ret, port_num; |
- | 1674 | ||
- | 1675 | port_num = port->port_num; |
|
- | 1676 | mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent); |
|
1572 | int len, ret; |
1677 | if (!mstb) { |
1573 | 1678 | mstb = drm_dp_get_last_connected_port_and_mstb(mgr, port->parent, &port_num); |
|
- | 1679 | ||
Line 1574... | Line 1680... | ||
1574 | mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent); |
1680 | if (!mstb) |
1575 | if (!mstb) |
1681 | return -EINVAL; |
1576 | return -EINVAL; |
1682 | } |
1577 | 1683 | ||
1578 | txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL); |
1684 | txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL); |
Line 1579... | Line 1685... | ||
1579 | if (!txmsg) { |
1685 | if (!txmsg) { |
1580 | ret = -ENOMEM; |
1686 | ret = -ENOMEM; |
1581 | goto fail_put; |
1687 | goto fail_put; |
1582 | } |
1688 | } |
Line 1583... | Line 1689... | ||
1583 | 1689 | ||
Line 1850... | Line 1956... | ||
1850 | txmsg->dst = mstb; |
1956 | txmsg->dst = mstb; |
1851 | txmsg->seqno = seqno; |
1957 | txmsg->seqno = seqno; |
1852 | drm_dp_encode_up_ack_reply(txmsg, req_type); |
1958 | drm_dp_encode_up_ack_reply(txmsg, req_type); |
Line 1853... | Line 1959... | ||
1853 | 1959 | ||
1854 | mutex_lock(&mgr->qlock); |
- | |
1855 | list_add_tail(&txmsg->next, &mgr->tx_msg_upq); |
- | |
- | 1960 | mutex_lock(&mgr->qlock); |
|
1856 | if (!mgr->tx_up_in_progress) { |
1961 | |
1857 | process_single_up_tx_qlock(mgr); |
1962 | process_single_up_tx_qlock(mgr, txmsg); |
1858 | } |
1963 | |
- | 1964 | mutex_unlock(&mgr->qlock); |
|
- | 1965 | ||
1859 | mutex_unlock(&mgr->qlock); |
1966 | kfree(txmsg); |
1860 | return 0; |
1967 | return 0; |
Line 1861... | Line 1968... | ||
1861 | } |
1968 | } |
1862 | 1969 | ||
Line 1933... | Line 2040... | ||
1933 | 2040 | ||
1934 | /* give this the main reference */ |
2041 | /* give this the main reference */ |
1935 | mgr->mst_primary = mstb; |
2042 | mgr->mst_primary = mstb; |
Line 1936... | Line -... | ||
1936 | kref_get(&mgr->mst_primary->kref); |
- | |
1937 | - | ||
1938 | { |
- | |
1939 | struct drm_dp_payload reset_pay; |
- | |
1940 | reset_pay.start_slot = 0; |
- | |
1941 | reset_pay.num_slots = 0x3f; |
- | |
1942 | drm_dp_dpcd_write_payload(mgr, 0, &reset_pay); |
- | |
1943 | } |
2043 | kref_get(&mgr->mst_primary->kref); |
1944 | 2044 | ||
1945 | ret = drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL, |
2045 | ret = drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL, |
1946 | DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC); |
2046 | DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC); |
1947 | if (ret < 0) { |
2047 | if (ret < 0) { |
Line 1948... | Line -... | ||
1948 | goto out_unlock; |
- | |
1949 | } |
- | |
1950 | - | ||
1951 | - | ||
1952 | /* sort out guid */ |
- | |
1953 | ret = drm_dp_dpcd_read(mgr->aux, DP_GUID, mgr->guid, 16); |
- | |
1954 | if (ret != 16) { |
2048 | goto out_unlock; |
1955 | DRM_DEBUG_KMS("failed to read DP GUID %d\n", ret); |
- | |
1956 | goto out_unlock; |
2049 | } |
1957 | } |
2050 | |
1958 | 2051 | { |
|
1959 | mgr->guid_valid = drm_dp_validate_guid(mgr, mgr->guid); |
2052 | struct drm_dp_payload reset_pay; |
1960 | if (!mgr->guid_valid) { |
2053 | reset_pay.start_slot = 0; |
Line 1961... | Line 2054... | ||
1961 | ret = drm_dp_dpcd_write(mgr->aux, DP_GUID, mgr->guid, 16); |
2054 | reset_pay.num_slots = 0x3f; |
Line 1962... | Line 2055... | ||
1962 | mgr->guid_valid = true; |
2055 | drm_dp_dpcd_write_payload(mgr, 0, &reset_pay); |
Line 2149... | Line 2242... | ||
2149 | int ret = 0; |
2242 | int ret = 0; |
2150 | drm_dp_get_one_sb_msg(mgr, true); |
2243 | drm_dp_get_one_sb_msg(mgr, true); |
Line 2151... | Line 2244... | ||
2151 | 2244 | ||
2152 | if (mgr->up_req_recv.have_eomt) { |
2245 | if (mgr->up_req_recv.have_eomt) { |
2153 | struct drm_dp_sideband_msg_req_body msg; |
2246 | struct drm_dp_sideband_msg_req_body msg; |
2154 | struct drm_dp_mst_branch *mstb; |
2247 | struct drm_dp_mst_branch *mstb = NULL; |
- | 2248 | bool seqno; |
|
- | 2249 | ||
2155 | bool seqno; |
2250 | if (!mgr->up_req_recv.initial_hdr.broadcast) { |
2156 | mstb = drm_dp_get_mst_branch_device(mgr, |
2251 | mstb = drm_dp_get_mst_branch_device(mgr, |
2157 | mgr->up_req_recv.initial_hdr.lct, |
2252 | mgr->up_req_recv.initial_hdr.lct, |
2158 | mgr->up_req_recv.initial_hdr.rad); |
2253 | mgr->up_req_recv.initial_hdr.rad); |
2159 | if (!mstb) { |
2254 | if (!mstb) { |
2160 | DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct); |
2255 | DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct); |
2161 | memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx)); |
2256 | memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx)); |
2162 | return 0; |
2257 | return 0; |
- | 2258 | } |
|
Line 2163... | Line 2259... | ||
2163 | } |
2259 | } |
2164 | 2260 | ||
Line 2165... | Line 2261... | ||
2165 | seqno = mgr->up_req_recv.initial_hdr.seqno; |
2261 | seqno = mgr->up_req_recv.initial_hdr.seqno; |
2166 | drm_dp_sideband_parse_req(&mgr->up_req_recv, &msg); |
2262 | drm_dp_sideband_parse_req(&mgr->up_req_recv, &msg); |
- | 2263 | ||
- | 2264 | if (msg.req_type == DP_CONNECTION_STATUS_NOTIFY) { |
|
- | 2265 | drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false); |
|
- | 2266 | ||
- | 2267 | if (!mstb) |
|
- | 2268 | mstb = drm_dp_get_mst_branch_device_by_guid(mgr, msg.u.conn_stat.guid); |
|
- | 2269 | ||
- | 2270 | if (!mstb) { |
|
- | 2271 | DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct); |
|
- | 2272 | memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx)); |
|
2167 | 2273 | return 0; |
|
- | 2274 | } |
|
2168 | if (msg.req_type == DP_CONNECTION_STATUS_NOTIFY) { |
2275 | |
2169 | drm_dp_send_up_ack_reply(mgr, mstb, msg.req_type, seqno, false); |
2276 | drm_dp_update_port(mstb, &msg.u.conn_stat); |
Line 2170... | Line 2277... | ||
2170 | drm_dp_update_port(mstb, &msg.u.conn_stat); |
2277 | |
2171 | DRM_DEBUG_KMS("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n", msg.u.conn_stat.port_number, msg.u.conn_stat.legacy_device_plug_status, msg.u.conn_stat.displayport_device_plug_status, msg.u.conn_stat.message_capability_status, msg.u.conn_stat.input_port, msg.u.conn_stat.peer_device_type); |
2278 | DRM_DEBUG_KMS("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n", msg.u.conn_stat.port_number, msg.u.conn_stat.legacy_device_plug_status, msg.u.conn_stat.displayport_device_plug_status, msg.u.conn_stat.message_capability_status, msg.u.conn_stat.input_port, msg.u.conn_stat.peer_device_type); |
- | 2279 | (*mgr->cbs->hotplug)(mgr); |
|
- | 2280 | ||
- | 2281 | } else if (msg.req_type == DP_RESOURCE_STATUS_NOTIFY) { |
|
- | 2282 | drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false); |
|
- | 2283 | if (!mstb) |
|
- | 2284 | mstb = drm_dp_get_mst_branch_device_by_guid(mgr, msg.u.resource_stat.guid); |
|
- | 2285 | ||
- | 2286 | if (!mstb) { |
|
- | 2287 | DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct); |
|
2172 | (*mgr->cbs->hotplug)(mgr); |
2288 | memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx)); |
2173 | 2289 | return 0; |
|
Line 2174... | Line 2290... | ||
2174 | } else if (msg.req_type == DP_RESOURCE_STATUS_NOTIFY) { |
2290 | } |
2175 | drm_dp_send_up_ack_reply(mgr, mstb, msg.req_type, seqno, false); |
2291 | |
Line 2350... | Line 2466... | ||
2350 | 2466 | ||
2351 | if (port->vcpi.vcpi > 0) { |
2467 | if (port->vcpi.vcpi > 0) { |
2352 | DRM_DEBUG_KMS("payload: vcpi %d already allocated for pbn %d - requested pbn %d\n", port->vcpi.vcpi, port->vcpi.pbn, pbn); |
2468 | DRM_DEBUG_KMS("payload: vcpi %d already allocated for pbn %d - requested pbn %d\n", port->vcpi.vcpi, port->vcpi.pbn, pbn); |
2353 | if (pbn == port->vcpi.pbn) { |
2469 | if (pbn == port->vcpi.pbn) { |
- | 2470 | *slots = port->vcpi.num_slots; |
|
2354 | *slots = port->vcpi.num_slots; |
2471 | drm_dp_put_port(port); |
2355 | return true; |
2472 | return true; |
2356 | } |
2473 | } |
Line 2357... | Line 2474... | ||
2357 | } |
2474 | } |
Line 2509... | Line 2626... | ||
2509 | * |
2626 | * |
2510 | * This uses the formula in the spec to calculate the PBN value for a mode. |
2627 | * This uses the formula in the spec to calculate the PBN value for a mode. |
2511 | */ |
2628 | */ |
2512 | int drm_dp_calc_pbn_mode(int clock, int bpp) |
2629 | int drm_dp_calc_pbn_mode(int clock, int bpp) |
2513 | { |
2630 | { |
2514 | fixed20_12 pix_bw; |
- | |
2515 | fixed20_12 fbpp; |
2631 | u64 kbps; |
2516 | fixed20_12 result; |
2632 | s64 peak_kbps; |
2517 | fixed20_12 margin, tmp; |
2633 | u32 numerator; |
2518 | u32 res; |
2634 | u32 denominator; |
2519 | 2635 | ||
2520 | pix_bw.full = dfixed_const(clock); |
- | |
2521 | fbpp.full = dfixed_const(bpp); |
2636 | kbps = clock * bpp; |
2522 | tmp.full = dfixed_const(8); |
- | |
2523 | fbpp.full = dfixed_div(fbpp, tmp); |
- | |
2524 | 2637 | ||
- | 2638 | /* |
|
- | 2639 | * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006 |
|
- | 2640 | * The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on |
|
2525 | result.full = dfixed_mul(pix_bw, fbpp); |
2641 | * common multiplier to render an integer PBN for all link rate/lane |
2526 | margin.full = dfixed_const(54); |
2642 | * counts combinations |
- | 2643 | * calculate |
|
2527 | tmp.full = dfixed_const(64); |
2644 | * peak_kbps *= (1006/1000) |
2528 | margin.full = dfixed_div(margin, tmp); |
2645 | * peak_kbps *= (64/54) |
2529 | result.full = dfixed_div(result, margin); |
2646 | * peak_kbps *= 8 convert to bytes |
- | 2647 | */ |
|
2530 | 2648 | ||
2531 | margin.full = dfixed_const(1006); |
2649 | numerator = 64 * 1006; |
2532 | tmp.full = dfixed_const(1000); |
2650 | denominator = 54 * 8 * 1000 * 1000; |
- | 2651 | ||
2533 | margin.full = dfixed_div(margin, tmp); |
2652 | kbps *= numerator; |
2534 | result.full = dfixed_mul(result, margin); |
2653 | peak_kbps = drm_fixp_from_fraction(kbps, denominator); |
2535 | 2654 | ||
2536 | result.full = dfixed_div(result, tmp); |
- | |
2537 | result.full = dfixed_ceil(result); |
2655 | return drm_fixp2int_ceil(peak_kbps); |
2538 | res = dfixed_trunc(result); |
- | |
2539 | return res; |
- | |
2540 | } |
2656 | } |
2541 | EXPORT_SYMBOL(drm_dp_calc_pbn_mode); |
2657 | EXPORT_SYMBOL(drm_dp_calc_pbn_mode); |
Line 2542... | Line 2658... | ||
2542 | 2658 | ||
2543 | static int test_calc_pbn_mode(void) |
2659 | static int test_calc_pbn_mode(void) |
2544 | { |
2660 | { |
2545 | int ret; |
2661 | int ret; |
2546 | ret = drm_dp_calc_pbn_mode(154000, 30); |
2662 | ret = drm_dp_calc_pbn_mode(154000, 30); |
- | 2663 | if (ret != 689) { |
|
- | 2664 | DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, expected PBN %d, actual PBN %d.\n", |
|
2547 | if (ret != 689) |
2665 | 154000, 30, 689, ret); |
- | 2666 | return -EINVAL; |
|
2548 | return -EINVAL; |
2667 | } |
2549 | ret = drm_dp_calc_pbn_mode(234000, 30); |
2668 | ret = drm_dp_calc_pbn_mode(234000, 30); |
- | 2669 | if (ret != 1047) { |
|
- | 2670 | DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, expected PBN %d, actual PBN %d.\n", |
|
- | 2671 | 234000, 30, 1047, ret); |
|
- | 2672 | return -EINVAL; |
|
- | 2673 | } |
|
- | 2674 | ret = drm_dp_calc_pbn_mode(297000, 24); |
|
- | 2675 | if (ret != 1063) { |
|
- | 2676 | DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, expected PBN %d, actual PBN %d.\n", |
|
2550 | if (ret != 1047) |
2677 | 297000, 24, 1063, ret); |
- | 2678 | return -EINVAL; |
|
2551 | return -EINVAL; |
2679 | } |
2552 | return 0; |
2680 | return 0; |
Line 2553... | Line 2681... | ||
2553 | } |
2681 | } |
2554 | 2682 | ||
Line 2625... | Line 2753... | ||
2625 | if (mgr->tx_down_in_progress) |
2753 | if (mgr->tx_down_in_progress) |
2626 | process_single_down_tx_qlock(mgr); |
2754 | process_single_down_tx_qlock(mgr); |
2627 | mutex_unlock(&mgr->qlock); |
2755 | mutex_unlock(&mgr->qlock); |
2628 | } |
2756 | } |
Line -... | Line 2757... | ||
- | 2757 | ||
- | 2758 | static void drm_dp_free_mst_port(struct kref *kref) |
|
- | 2759 | { |
|
- | 2760 | struct drm_dp_mst_port *port = container_of(kref, struct drm_dp_mst_port, kref); |
|
- | 2761 | kref_put(&port->parent->kref, drm_dp_free_mst_branch_device); |
|
- | 2762 | kfree(port); |
|
2629 | 2763 | } |
|
2630 | /** |
2764 | /** |
2631 | * drm_dp_mst_topology_mgr_init - initialise a topology manager |
2765 | * drm_dp_mst_topology_mgr_init - initialise a topology manager |
2632 | * @mgr: manager struct to initialise |
2766 | * @mgr: manager struct to initialise |
2633 | * @dev: device providing this structure - for i2c addition. |
2767 | * @dev: device providing this structure - for i2c addition. |
Line 2645... | Line 2779... | ||
2645 | { |
2779 | { |
2646 | mutex_init(&mgr->lock); |
2780 | mutex_init(&mgr->lock); |
2647 | mutex_init(&mgr->qlock); |
2781 | mutex_init(&mgr->qlock); |
2648 | mutex_init(&mgr->payload_lock); |
2782 | mutex_init(&mgr->payload_lock); |
2649 | mutex_init(&mgr->destroy_connector_lock); |
2783 | mutex_init(&mgr->destroy_connector_lock); |
2650 | INIT_LIST_HEAD(&mgr->tx_msg_upq); |
- | |
2651 | INIT_LIST_HEAD(&mgr->tx_msg_downq); |
2784 | INIT_LIST_HEAD(&mgr->tx_msg_downq); |
2652 | INIT_LIST_HEAD(&mgr->destroy_connector_list); |
2785 | INIT_LIST_HEAD(&mgr->destroy_connector_list); |
2653 | INIT_WORK(&mgr->work, drm_dp_mst_link_probe_work); |
2786 | INIT_WORK(&mgr->work, drm_dp_mst_link_probe_work); |
2654 | INIT_WORK(&mgr->tx_work, drm_dp_tx_work); |
2787 | INIT_WORK(&mgr->tx_work, drm_dp_tx_work); |
2655 | init_waitqueue_head(&mgr->tx_waitq); |
2788 | init_waitqueue_head(&mgr->tx_waitq); |