aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_dp_mst_topology.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_dp_mst_topology.c')
-rw-r--r--drivers/gpu/drm/drm_dp_mst_topology.c80
1 files changed, 59 insertions, 21 deletions
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index ac3c2738db94..070f913d2dba 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -682,7 +682,7 @@ static int build_allocate_payload(struct drm_dp_sideband_msg_tx *msg, int port_n
682static int drm_dp_mst_assign_payload_id(struct drm_dp_mst_topology_mgr *mgr, 682static int drm_dp_mst_assign_payload_id(struct drm_dp_mst_topology_mgr *mgr,
683 struct drm_dp_vcpi *vcpi) 683 struct drm_dp_vcpi *vcpi)
684{ 684{
685 int ret; 685 int ret, vcpi_ret;
686 686
687 mutex_lock(&mgr->payload_lock); 687 mutex_lock(&mgr->payload_lock);
688 ret = find_first_zero_bit(&mgr->payload_mask, mgr->max_payloads + 1); 688 ret = find_first_zero_bit(&mgr->payload_mask, mgr->max_payloads + 1);
@@ -692,8 +692,16 @@ static int drm_dp_mst_assign_payload_id(struct drm_dp_mst_topology_mgr *mgr,
692 goto out_unlock; 692 goto out_unlock;
693 } 693 }
694 694
695 vcpi_ret = find_first_zero_bit(&mgr->vcpi_mask, mgr->max_payloads + 1);
696 if (vcpi_ret > mgr->max_payloads) {
697 ret = -EINVAL;
698 DRM_DEBUG_KMS("out of vcpi ids %d\n", ret);
699 goto out_unlock;
700 }
701
695 set_bit(ret, &mgr->payload_mask); 702 set_bit(ret, &mgr->payload_mask);
696 vcpi->vcpi = ret; 703 set_bit(vcpi_ret, &mgr->vcpi_mask);
704 vcpi->vcpi = vcpi_ret + 1;
697 mgr->proposed_vcpis[ret - 1] = vcpi; 705 mgr->proposed_vcpis[ret - 1] = vcpi;
698out_unlock: 706out_unlock:
699 mutex_unlock(&mgr->payload_lock); 707 mutex_unlock(&mgr->payload_lock);
@@ -701,15 +709,23 @@ out_unlock:
701} 709}
702 710
703static void drm_dp_mst_put_payload_id(struct drm_dp_mst_topology_mgr *mgr, 711static void drm_dp_mst_put_payload_id(struct drm_dp_mst_topology_mgr *mgr,
704 int id) 712 int vcpi)
705{ 713{
706 if (id == 0) 714 int i;
715 if (vcpi == 0)
707 return; 716 return;
708 717
709 mutex_lock(&mgr->payload_lock); 718 mutex_lock(&mgr->payload_lock);
710 DRM_DEBUG_KMS("putting payload %d\n", id); 719 DRM_DEBUG_KMS("putting payload %d\n", vcpi);
711 clear_bit(id, &mgr->payload_mask); 720 clear_bit(vcpi - 1, &mgr->vcpi_mask);
712 mgr->proposed_vcpis[id - 1] = NULL; 721
722 for (i = 0; i < mgr->max_payloads; i++) {
723 if (mgr->proposed_vcpis[i])
724 if (mgr->proposed_vcpis[i]->vcpi == vcpi) {
725 mgr->proposed_vcpis[i] = NULL;
726 clear_bit(i + 1, &mgr->payload_mask);
727 }
728 }
713 mutex_unlock(&mgr->payload_lock); 729 mutex_unlock(&mgr->payload_lock);
714} 730}
715 731
@@ -1563,7 +1579,7 @@ static int drm_dp_destroy_payload_step1(struct drm_dp_mst_topology_mgr *mgr,
1563 } 1579 }
1564 1580
1565 drm_dp_dpcd_write_payload(mgr, id, payload); 1581 drm_dp_dpcd_write_payload(mgr, id, payload);
1566 payload->payload_state = 0; 1582 payload->payload_state = DP_PAYLOAD_DELETE_LOCAL;
1567 return 0; 1583 return 0;
1568} 1584}
1569 1585
@@ -1590,7 +1606,7 @@ static int drm_dp_destroy_payload_step2(struct drm_dp_mst_topology_mgr *mgr,
1590 */ 1606 */
1591int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr) 1607int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr)
1592{ 1608{
1593 int i; 1609 int i, j;
1594 int cur_slots = 1; 1610 int cur_slots = 1;
1595 struct drm_dp_payload req_payload; 1611 struct drm_dp_payload req_payload;
1596 struct drm_dp_mst_port *port; 1612 struct drm_dp_mst_port *port;
@@ -1607,26 +1623,46 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr)
1607 port = NULL; 1623 port = NULL;
1608 req_payload.num_slots = 0; 1624 req_payload.num_slots = 0;
1609 } 1625 }
1626
1627 if (mgr->payloads[i].start_slot != req_payload.start_slot) {
1628 mgr->payloads[i].start_slot = req_payload.start_slot;
1629 }
1610 /* work out what is required to happen with this payload */ 1630 /* work out what is required to happen with this payload */
1611 if (mgr->payloads[i].start_slot != req_payload.start_slot || 1631 if (mgr->payloads[i].num_slots != req_payload.num_slots) {
1612 mgr->payloads[i].num_slots != req_payload.num_slots) {
1613 1632
1614 /* need to push an update for this payload */ 1633 /* need to push an update for this payload */
1615 if (req_payload.num_slots) { 1634 if (req_payload.num_slots) {
1616 drm_dp_create_payload_step1(mgr, i + 1, &req_payload); 1635 drm_dp_create_payload_step1(mgr, mgr->proposed_vcpis[i]->vcpi, &req_payload);
1617 mgr->payloads[i].num_slots = req_payload.num_slots; 1636 mgr->payloads[i].num_slots = req_payload.num_slots;
1618 } else if (mgr->payloads[i].num_slots) { 1637 } else if (mgr->payloads[i].num_slots) {
1619 mgr->payloads[i].num_slots = 0; 1638 mgr->payloads[i].num_slots = 0;
1620 drm_dp_destroy_payload_step1(mgr, port, i + 1, &mgr->payloads[i]); 1639 drm_dp_destroy_payload_step1(mgr, port, port->vcpi.vcpi, &mgr->payloads[i]);
1621 req_payload.payload_state = mgr->payloads[i].payload_state; 1640 req_payload.payload_state = mgr->payloads[i].payload_state;
1622 } else 1641 mgr->payloads[i].start_slot = 0;
1623 req_payload.payload_state = 0; 1642 }
1624
1625 mgr->payloads[i].start_slot = req_payload.start_slot;
1626 mgr->payloads[i].payload_state = req_payload.payload_state; 1643 mgr->payloads[i].payload_state = req_payload.payload_state;
1627 } 1644 }
1628 cur_slots += req_payload.num_slots; 1645 cur_slots += req_payload.num_slots;
1629 } 1646 }
1647
1648 for (i = 0; i < mgr->max_payloads; i++) {
1649 if (mgr->payloads[i].payload_state == DP_PAYLOAD_DELETE_LOCAL) {
1650 DRM_DEBUG_KMS("removing payload %d\n", i);
1651 for (j = i; j < mgr->max_payloads - 1; j++) {
1652 memcpy(&mgr->payloads[j], &mgr->payloads[j + 1], sizeof(struct drm_dp_payload));
1653 mgr->proposed_vcpis[j] = mgr->proposed_vcpis[j + 1];
1654 if (mgr->proposed_vcpis[j] && mgr->proposed_vcpis[j]->num_slots) {
1655 set_bit(j + 1, &mgr->payload_mask);
1656 } else {
1657 clear_bit(j + 1, &mgr->payload_mask);
1658 }
1659 }
1660 memset(&mgr->payloads[mgr->max_payloads - 1], 0, sizeof(struct drm_dp_payload));
1661 mgr->proposed_vcpis[mgr->max_payloads - 1] = NULL;
1662 clear_bit(mgr->max_payloads, &mgr->payload_mask);
1663
1664 }
1665 }
1630 mutex_unlock(&mgr->payload_lock); 1666 mutex_unlock(&mgr->payload_lock);
1631 1667
1632 return 0; 1668 return 0;
@@ -1657,9 +1693,9 @@ int drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr)
1657 1693
1658 DRM_DEBUG_KMS("payload %d %d\n", i, mgr->payloads[i].payload_state); 1694 DRM_DEBUG_KMS("payload %d %d\n", i, mgr->payloads[i].payload_state);
1659 if (mgr->payloads[i].payload_state == DP_PAYLOAD_LOCAL) { 1695 if (mgr->payloads[i].payload_state == DP_PAYLOAD_LOCAL) {
1660 ret = drm_dp_create_payload_step2(mgr, port, i + 1, &mgr->payloads[i]); 1696 ret = drm_dp_create_payload_step2(mgr, port, mgr->proposed_vcpis[i]->vcpi, &mgr->payloads[i]);
1661 } else if (mgr->payloads[i].payload_state == DP_PAYLOAD_DELETE_LOCAL) { 1697 } else if (mgr->payloads[i].payload_state == DP_PAYLOAD_DELETE_LOCAL) {
1662 ret = drm_dp_destroy_payload_step2(mgr, i + 1, &mgr->payloads[i]); 1698 ret = drm_dp_destroy_payload_step2(mgr, mgr->proposed_vcpis[i]->vcpi, &mgr->payloads[i]);
1663 } 1699 }
1664 if (ret) { 1700 if (ret) {
1665 mutex_unlock(&mgr->payload_lock); 1701 mutex_unlock(&mgr->payload_lock);
@@ -1772,7 +1808,7 @@ static int drm_dp_get_vc_payload_bw(int dp_link_bw, int dp_link_count)
1772 case DP_LINK_BW_5_4: 1808 case DP_LINK_BW_5_4:
1773 return 10 * dp_link_count; 1809 return 10 * dp_link_count;
1774 } 1810 }
1775 return 0; 1811 BUG();
1776} 1812}
1777 1813
1778/** 1814/**
@@ -1861,6 +1897,7 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
1861 memset(mgr->payloads, 0, mgr->max_payloads * sizeof(struct drm_dp_payload)); 1897 memset(mgr->payloads, 0, mgr->max_payloads * sizeof(struct drm_dp_payload));
1862 mgr->payload_mask = 0; 1898 mgr->payload_mask = 0;
1863 set_bit(0, &mgr->payload_mask); 1899 set_bit(0, &mgr->payload_mask);
1900 mgr->vcpi_mask = 0;
1864 } 1901 }
1865 1902
1866out_unlock: 1903out_unlock:
@@ -2071,6 +2108,7 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
2071 * drm_dp_mst_hpd_irq() - MST hotplug IRQ notify 2108 * drm_dp_mst_hpd_irq() - MST hotplug IRQ notify
2072 * @mgr: manager to notify irq for. 2109 * @mgr: manager to notify irq for.
2073 * @esi: 4 bytes from SINK_COUNT_ESI 2110 * @esi: 4 bytes from SINK_COUNT_ESI
2111 * @handled: whether the hpd interrupt was consumed or not
2074 * 2112 *
2075 * This should be called from the driver when it detects a short IRQ, 2113 * This should be called from the driver when it detects a short IRQ,
2076 * along with the value of the DEVICE_SERVICE_IRQ_VECTOR_ESI0. The 2114 * along with the value of the DEVICE_SERVICE_IRQ_VECTOR_ESI0. The
@@ -2474,7 +2512,7 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
2474 mutex_unlock(&mgr->lock); 2512 mutex_unlock(&mgr->lock);
2475 2513
2476 mutex_lock(&mgr->payload_lock); 2514 mutex_lock(&mgr->payload_lock);
2477 seq_printf(m, "vcpi: %lx\n", mgr->payload_mask); 2515 seq_printf(m, "vcpi: %lx %lx\n", mgr->payload_mask, mgr->vcpi_mask);
2478 2516
2479 for (i = 0; i < mgr->max_payloads; i++) { 2517 for (i = 0; i < mgr->max_payloads; i++) {
2480 if (mgr->proposed_vcpis[i]) { 2518 if (mgr->proposed_vcpis[i]) {