Commit 016dacb6 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/kms: pass event mask to hpd handler



Will be moving the DP link status check / re-train here so it's safe
from racing with modeset routing changes.

MST message handling etc. will remain where it is.

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Reviewed-by: default avatarLyude Paul <lyude@redhat.com>
parent d62f8e98
Loading
Loading
Loading
Loading
+5 −6
Original line number Diff line number Diff line
@@ -1162,14 +1162,15 @@ nouveau_connector_funcs_lvds = {
};

void
nouveau_connector_hpd(struct drm_connector *connector)
nouveau_connector_hpd(struct nouveau_connector *nv_connector, u64 bits)
{
	struct nouveau_drm *drm = nouveau_drm(connector->dev);
	u32 mask = drm_connector_mask(connector);
	struct nouveau_drm *drm = nouveau_drm(nv_connector->base.dev);
	u32 mask = drm_connector_mask(&nv_connector->base);
	unsigned long flags;

	spin_lock_irqsave(&drm->hpd_lock, flags);
	if (!(drm->hpd_pending & mask)) {
		nv_connector->hpd_pending |= bits;
		drm->hpd_pending |= mask;
		schedule_work(&drm->hpd_work);
	}
@@ -1185,15 +1186,13 @@ nouveau_connector_hotplug(struct nvif_notify *notify)
	struct drm_device *dev = connector->dev;
	struct nouveau_drm *drm = nouveau_drm(dev);
	const struct nvif_notify_conn_rep_v0 *rep = notify->data;
	bool plugged = (rep->mask != NVIF_NOTIFY_CONN_V0_UNPLUG);

	if (rep->mask & NVIF_NOTIFY_CONN_V0_IRQ) {
		nouveau_dp_irq(drm, nv_connector);
		return NVIF_NOTIFY_KEEP;
	}

	NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", connector->name);
	nouveau_connector_hpd(connector);
	nouveau_connector_hpd(nv_connector, rep->mask);

	return NVIF_NOTIFY_KEEP;
}
+2 −1
Original line number Diff line number Diff line
@@ -124,6 +124,7 @@ struct nouveau_connector {
	u8 *dcb;

	struct nvif_conn conn;
	u64 hpd_pending;
	struct nvif_notify hpd;

	struct drm_dp_aux aux;
@@ -198,7 +199,7 @@ nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc)

struct drm_connector *
nouveau_connector_create(struct drm_device *, const struct dcb_output *);
void nouveau_connector_hpd(struct drm_connector *connector);
void nouveau_connector_hpd(struct nouveau_connector *, u64 bits);

extern int nouveau_tv_disable;
extern int nouveau_ignorelid;
+17 −3
Original line number Diff line number Diff line
@@ -488,14 +488,28 @@ nouveau_display_hpd_work(struct work_struct *work)
	drm_connector_list_iter_begin(dev, &conn_iter);

	nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) {
		struct nouveau_connector *nv_connector = nouveau_connector(connector);
		enum drm_connector_status old_status = connector->status;
		u64 old_epoch_counter = connector->epoch_counter;
		u64 bits, old_epoch_counter = connector->epoch_counter;

		if (!(pending & drm_connector_mask(connector)))
			continue;

		connector->status = drm_helper_probe_detect(connector, NULL,
							    false);
		spin_lock_irq(&drm->hpd_lock);
		bits = nv_connector->hpd_pending;
		nv_connector->hpd_pending = 0;
		spin_unlock_irq(&drm->hpd_lock);

		drm_dbg_kms(dev, "[CONNECTOR:%d:%s] plug:%d unplug:%d irq:%d\n",
			    connector->base.id, connector->name,
			    !!(bits & NVIF_NOTIFY_CONN_V0_PLUG),
			    !!(bits & NVIF_NOTIFY_CONN_V0_UNPLUG),
			    !!(bits & NVIF_NOTIFY_CONN_V0_IRQ));

		if (bits & NVIF_NOTIFY_CONN_V0_IRQ)
			continue;

		connector->status = drm_helper_probe_detect(connector, NULL, false);
		if (old_epoch_counter == connector->epoch_counter)
			continue;

+5 −7
Original line number Diff line number Diff line
@@ -29,8 +29,7 @@
#include "nouveau_encoder.h"
#include "nouveau_crtc.h"

#include <nvif/class.h>
#include <nvif/cl5070.h>
#include <nvif/event.h>

MODULE_PARM_DESC(mst, "Enable DisplayPort multi-stream (default: enabled)");
static int nouveau_mst = 1;
@@ -218,8 +217,8 @@ void nouveau_dp_irq(struct nouveau_drm *drm,
	struct drm_connector *connector = &nv_connector->base;
	struct nouveau_encoder *outp = find_encoder(connector, DCB_OUTPUT_DP);
	struct nv50_mstm *mstm;
	u64 hpd = 0;
	int ret;
	bool send_hpd = false;

	if (!outp)
		return;
@@ -231,14 +230,14 @@ void nouveau_dp_irq(struct nouveau_drm *drm,

	if (mstm && mstm->is_mst) {
		if (!nv50_mstm_service(drm, nv_connector, mstm))
			send_hpd = true;
			hpd |= NVIF_NOTIFY_CONN_V0_UNPLUG;
	} else {
		drm_dp_cec_irq(&nv_connector->aux);

		if (nouveau_dp_has_sink_count(connector, outp)) {
			ret = drm_dp_read_sink_count(&nv_connector->aux);
			if (ret != outp->dp.sink_count)
				send_hpd = true;
				hpd |= NVIF_NOTIFY_CONN_V0_PLUG;
			if (ret >= 0)
				outp->dp.sink_count = ret;
		}
@@ -246,8 +245,7 @@ void nouveau_dp_irq(struct nouveau_drm *drm,

	mutex_unlock(&outp->dp.hpd_irq_lock);

	if (send_hpd)
		nouveau_connector_hpd(connector);
	nouveau_connector_hpd(nv_connector, NVIF_NOTIFY_CONN_V0_IRQ | hpd);
}

/* TODO: