diff options
Diffstat (limited to 'drivers/gpu/drm/drm_dp_mst_topology.c')
-rw-r--r-- | drivers/gpu/drm/drm_dp_mst_topology.c | 80 |
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 | |||
682 | static int drm_dp_mst_assign_payload_id(struct drm_dp_mst_topology_mgr *mgr, | 682 | static 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; |
698 | out_unlock: | 706 | out_unlock: |
699 | mutex_unlock(&mgr->payload_lock); | 707 | mutex_unlock(&mgr->payload_lock); |
@@ -701,15 +709,23 @@ out_unlock: | |||
701 | } | 709 | } |
702 | 710 | ||
703 | static void drm_dp_mst_put_payload_id(struct drm_dp_mst_topology_mgr *mgr, | 711 | static 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 | */ |
1591 | int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr) | 1607 | int 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 | ||
1866 | out_unlock: | 1903 | out_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]) { |