Skip to content

Commit 851daf0

Browse files
Sean Andersontomba
authored andcommitted
drm: zynqmp_dp: Don't retrain the link in our IRQ
Retraining the link can take a while, and might involve waiting for DPCD reads/writes to complete. In preparation for unthreading the IRQ handler, move this into its own work function. Signed-off-by: Sean Anderson <sean.anderson@linux.dev> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> Link: https://patchwork.freedesktop.org/patch/msgid/20240809193600.3360015-4-sean.anderson@linux.dev
1 parent a7d5eea commit 851daf0

1 file changed

Lines changed: 29 additions & 16 deletions

File tree

drivers/gpu/drm/xlnx/zynqmp_dp.c

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@ struct zynqmp_dp_config {
289289
* @phy: PHY handles for DP lanes
290290
* @num_lanes: number of enabled phy lanes
291291
* @hpd_work: hot plug detection worker
292+
* @hpd_irq_work: hot plug detection IRQ worker
292293
* @status: connection status
293294
* @enabled: flag to indicate if the device is enabled
294295
* @dpcd: DP configuration data from currently connected sink device
@@ -304,6 +305,7 @@ struct zynqmp_dp {
304305
struct drm_dp_aux aux;
305306
struct drm_bridge bridge;
306307
struct work_struct hpd_work;
308+
struct work_struct hpd_irq_work;
307309
struct mutex lock;
308310

309311
struct drm_bridge *next_bridge;
@@ -1671,6 +1673,29 @@ static void zynqmp_dp_hpd_work_func(struct work_struct *work)
16711673
drm_bridge_hpd_notify(&dp->bridge, status);
16721674
}
16731675

1676+
static void zynqmp_dp_hpd_irq_work_func(struct work_struct *work)
1677+
{
1678+
struct zynqmp_dp *dp = container_of(work, struct zynqmp_dp,
1679+
hpd_irq_work);
1680+
u8 status[DP_LINK_STATUS_SIZE + 2];
1681+
int err;
1682+
1683+
mutex_lock(&dp->lock);
1684+
err = drm_dp_dpcd_read(&dp->aux, DP_SINK_COUNT, status,
1685+
DP_LINK_STATUS_SIZE + 2);
1686+
if (err < 0) {
1687+
dev_dbg_ratelimited(dp->dev,
1688+
"could not read sink status: %d\n", err);
1689+
} else {
1690+
if (status[4] & DP_LINK_STATUS_UPDATED ||
1691+
!drm_dp_clock_recovery_ok(&status[2], dp->mode.lane_cnt) ||
1692+
!drm_dp_channel_eq_ok(&status[2], dp->mode.lane_cnt)) {
1693+
zynqmp_dp_train_loop(dp);
1694+
}
1695+
}
1696+
mutex_unlock(&dp->lock);
1697+
}
1698+
16741699
static irqreturn_t zynqmp_dp_irq_handler(int irq, void *data)
16751700
{
16761701
struct zynqmp_dp *dp = (struct zynqmp_dp *)data;
@@ -1702,23 +1727,9 @@ static irqreturn_t zynqmp_dp_irq_handler(int irq, void *data)
17021727
if (status & ZYNQMP_DP_INT_HPD_EVENT)
17031728
schedule_work(&dp->hpd_work);
17041729

1705-
if (status & ZYNQMP_DP_INT_HPD_IRQ) {
1706-
int ret;
1707-
u8 status[DP_LINK_STATUS_SIZE + 2];
1708-
1709-
ret = drm_dp_dpcd_read(&dp->aux, DP_SINK_COUNT, status,
1710-
DP_LINK_STATUS_SIZE + 2);
1711-
if (ret < 0)
1712-
goto handled;
1713-
1714-
if (status[4] & DP_LINK_STATUS_UPDATED ||
1715-
!drm_dp_clock_recovery_ok(&status[2], dp->mode.lane_cnt) ||
1716-
!drm_dp_channel_eq_ok(&status[2], dp->mode.lane_cnt)) {
1717-
zynqmp_dp_train_loop(dp);
1718-
}
1719-
}
1730+
if (status & ZYNQMP_DP_INT_HPD_IRQ)
1731+
schedule_work(&dp->hpd_irq_work);
17201732

1721-
handled:
17221733
return IRQ_HANDLED;
17231734
}
17241735

@@ -1744,6 +1755,7 @@ int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub)
17441755
mutex_init(&dp->lock);
17451756

17461757
INIT_WORK(&dp->hpd_work, zynqmp_dp_hpd_work_func);
1758+
INIT_WORK(&dp->hpd_irq_work, zynqmp_dp_hpd_irq_work_func);
17471759

17481760
/* Acquire all resources (IOMEM, IRQ and PHYs). */
17491761
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dp");
@@ -1848,6 +1860,7 @@ void zynqmp_dp_remove(struct zynqmp_dpsub *dpsub)
18481860
zynqmp_dp_write(dp, ZYNQMP_DP_INT_DS, ZYNQMP_DP_INT_ALL);
18491861
disable_irq(dp->irq);
18501862

1863+
cancel_work_sync(&dp->hpd_irq_work);
18511864
cancel_work_sync(&dp->hpd_work);
18521865

18531866
zynqmp_dp_write(dp, ZYNQMP_DP_TRANSMITTER_ENABLE, 0);

0 commit comments

Comments
 (0)