Skip to content

Commit 3864300

Browse files
committed
displayport: save and restore compound query state around speculative MST pre-check
The speculative uncompressed pre-check calls compoundQueryAttachMSTGeneric to determine if DSC can be skipped. However, this function mutates shared state that the subsequent DSC path depends on: 1. compoundQueryResult is set to false on failure but never reset, poisoning all subsequent compoundQueryAttachMSTGeneric calls which unconditionally return the (now-false) flag. 2. Per-device compound_query_state (timeslots_used_by_query and bandwidthAllocatedForIndex) is only partially rolled back on failure. Intermediate branch devices between the source and the bottleneck retain their uncompressed timeslot allocations. When the DSC path calls compoundQueryAttachMSTGeneric again, these devices are skipped via the bandwidthAllocatedForIndex bitmask, keeping incorrect (too-large) uncompressed allocations instead of the correct (smaller) compressed ones. Fix this by saving all relevant state before the speculative call and restoring it on failure, so the DSC path always starts from a clean slate. Also clear pErrorCode on rollback since the speculative failure is not a real error.
1 parent e91a9fb commit 3864300

File tree

1 file changed

+60
-7
lines changed

1 file changed

+60
-7
lines changed

src/common/displayport/src/dp_connectorimpl.cpp

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,22 +1422,75 @@ bool ConnectorImpl::compoundQueryAttachMST(Group * target,
14221422
{
14231423
//
14241424
// The uncompressed mode fits within available local link PBN.
1425-
// Try the full generic validation (watermark, per-device
1426-
// bandwidth at intermediate MST branches). If it succeeds,
1427-
// DSC is unnecessary.
1425+
// Speculatively try the full generic validation (watermark,
1426+
// per-device bandwidth at intermediate MST branches). If it
1427+
// succeeds, DSC is unnecessary.
14281428
//
1429+
// compoundQueryAttachMSTGeneric mutates connector and
1430+
// per-device state (compoundQueryResult, compoundQueryLocalLinkPBN,
1431+
// and device compound_query_state). Since this is a speculative
1432+
// check, save the state before and restore it on failure so the
1433+
// DSC path starts from a clean slate.
1434+
//
1435+
bool savedCompoundQueryResult = compoundQueryResult;
1436+
1437+
//
1438+
// Save per-device compound_query_state for all devices in this
1439+
// group's MST path. On failure, intermediate branch devices may
1440+
// retain stale timeslot allocations from the uncompressed attempt
1441+
// which would cause the DSC path to either skip them (via
1442+
// bandwidthAllocatedForIndex) or over-count their timeslots.
1443+
//
1444+
struct {
1445+
DeviceImpl *dev;
1446+
unsigned timeslots_used_by_query;
1447+
unsigned bandwidthAllocatedForIndex;
1448+
} savedDevState[63];
1449+
unsigned savedDevCount = 0;
1450+
1451+
for (Device * d = target->enumDevices(0); d;
1452+
d = target->enumDevices(d))
1453+
{
1454+
DeviceImpl * tail = (DeviceImpl *)d;
1455+
while (tail && tail->getParent() &&
1456+
savedDevCount < 63)
1457+
{
1458+
savedDevState[savedDevCount].dev = tail;
1459+
savedDevState[savedDevCount].timeslots_used_by_query =
1460+
tail->bandwidth.compound_query_state.timeslots_used_by_query;
1461+
savedDevState[savedDevCount].bandwidthAllocatedForIndex =
1462+
tail->bandwidth.compound_query_state.bandwidthAllocatedForIndex;
1463+
savedDevCount++;
1464+
tail = (DeviceImpl*)tail->getParent();
1465+
}
1466+
}
14291467
if (compoundQueryAttachMSTGeneric(target, modesetParams,
14301468
&localInfo, pDscParams,
14311469
pErrorCode))
14321470
{
14331471
return true;
14341472
}
1473+
1474+
//
1475+
// Generic validation failed — restore all state so the DSC
1476+
// path runs on a clean slate.
14351477
//
1436-
// Generic validation failed — possibly due to insufficient
1437-
// bandwidth at an intermediate MST branch link. DSC can
1438-
// reduce PBN enough to fit through the bottleneck, so fall
1439-
// through to the DSC path below.
1478+
// compoundQueryLocalLinkPBN is already rolled back by
1479+
// compoundQueryAttachMSTGeneric on failure.
14401480
//
1481+
compoundQueryResult = savedCompoundQueryResult;
1482+
for (unsigned idx = 0; idx < savedDevCount; idx++)
1483+
{
1484+
savedDevState[idx].dev->bandwidth.compound_query_state
1485+
.timeslots_used_by_query =
1486+
savedDevState[idx].timeslots_used_by_query;
1487+
savedDevState[idx].dev->bandwidth.compound_query_state
1488+
.bandwidthAllocatedForIndex =
1489+
savedDevState[idx].bandwidthAllocatedForIndex;
1490+
}
1491+
1492+
if (pErrorCode)
1493+
*pErrorCode = DP_IMP_ERROR_NONE;
14411494
}
14421495
}
14431496

0 commit comments

Comments
 (0)