From patchwork Wed Jun 5 22:17:25 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Vetter X-Patchwork-Id: 2676311 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork2.kernel.org (Postfix) with ESMTP id 84AA0DF264 for ; Wed, 5 Jun 2013 22:18:02 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id B3B95E5F2F for ; Wed, 5 Jun 2013 15:18:02 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-ea0-f172.google.com (mail-ea0-f172.google.com [209.85.215.172]) by gabe.freedesktop.org (Postfix) with ESMTP id 19C56E5CE7 for ; Wed, 5 Jun 2013 15:17:39 -0700 (PDT) Received: by mail-ea0-f172.google.com with SMTP id q10so310227eaj.31 for ; Wed, 05 Jun 2013 15:17:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ffwll.ch; s=google; h=from:to:cc:subject:date:message-id:x-mailer; bh=wXA6m2YPJr3WqPbnUJlNLaaBv2fLgaxvQcN3nx+AeSM=; b=U52g4evatPlZIOIb9gqyS0RdZAb+gKmBCj1RgbazJDeTVogiTuzLdh4BH13jZhT3/J 9B0aUe14Wo0yFhErAHzbKKNuuyUNkRdq7Cbo6yF5GW3O+a4HUMr1584FVBaLY1xODcpI fEq9ln0rF6VSrup3WGC4sY3vCSUAiJJn9V1zU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:x-gm-message-state; bh=wXA6m2YPJr3WqPbnUJlNLaaBv2fLgaxvQcN3nx+AeSM=; b=axsi6nwpiUEjjaIfelwIDfhpsSzkkgQc8YMv7/6iYI+OqarRKOBRvFDoiSpHJZdjx5 M7ahHM54NgWu9Nr4Ar6KB9019otTZgqrK8QaR6KgsYRKe90no9FyYJm9j093EjP4B2PY 8X8gSr7u6javFkXd3oCXnuNtUr/J2GA1O5rIBPpQpaplGVkJCCnOzjHLEcGCg817sQUe /ZVoQXM9vGngjHkA8N2rL8L7PLAHTecZUre3p5xpQwNGbcnsu2+BG/37PYAvYmTbM2DX EKZ1Jz0p+OFCrWTJehuxlBzAixarPJAbVhekJMNsT+mLZ82G6baUuiZt/tH0BhbL4SUn DS5Q== X-Received: by 10.15.108.6 with SMTP id cc6mr31201034eeb.28.1370470658655; Wed, 05 Jun 2013 15:17:38 -0700 (PDT) Received: from bremse.ffwll.local (178-83-130-250.dynamic.hispeed.ch. [178.83.130.250]) by mx.google.com with ESMTPSA id y44sm19160242eel.10.2013.06.05.15.17.37 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Wed, 05 Jun 2013 15:17:37 -0700 (PDT) From: Daniel Vetter To: DRI Development Subject: [PATCH 1/2] drm: kms_helper: don't lose hotplug event Date: Thu, 6 Jun 2013 00:17:25 +0200 Message-Id: <1370470646-20006-1-git-send-email-daniel.vetter@ffwll.ch> X-Mailer: git-send-email 1.7.11.7 X-Gm-Message-State: ALoCoQlffXOPkmnPy7Qcd2TgfkyLqXjlHSxcQ0Dwgw8NMhXGSR+7cobRlIezIyKEJUA6Ry4urriW Cc: Daniel Vetter , Intel Graphics Development X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Errors-To: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org There's a race window (small for hpd, 10s large for polled outputs) where userspace could sneak in with an unrelated connnector probe ioctl call and eat the hotplug event (since neither the hpd nor the poll code see a state change). To avoid this, check whether the connector state changes in all other ->detect calls (in the current helper code that's only probe_single) and if that's the case, fire off a hotplug event. Note that we can't directly call the hotplug event handler, since that expects that no locks are held (due to reentrancy with the fb code to update the kms console). Also, this requires that drivers using the probe_single helper function set up the poll work. All current drivers do that already, and with the reworked hpd handling there'll be no downside to unconditionally setting up the poll work any more. Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc_helper.c | 32 +++++++++++++++++++++++++++++++- include/drm/drm_crtc.h | 1 + 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index ed1334e..1c0c0bc 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -122,6 +122,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, int count = 0; int mode_flags = 0; bool verbose_prune = true; + enum drm_connector_status old_status; DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, drm_get_connector_name(connector)); @@ -137,7 +138,32 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, if (connector->funcs->force) connector->funcs->force(connector); } else { + old_status = connector->status; + connector->status = connector->funcs->detect(connector, true); + + /* + * Normally either the driver's hpd code or the poll loop should + * pick up any changes and fire the hotplug event. But if + * userspace sneaks in a probe, we might miss a change. Hence + * check here, and if anything changed start the hotplug code. + */ + if (old_status != connector->status) { + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n", + connector->base.id, + drm_get_connector_name(connector), + old_status, connector->status); + + /* + * The hotplug event code might call into the fb + * helpers, and so expects that we do not hold any + * locks. Fire up the poll struct instead, it will + * disable itself again. + */ + dev->mode_config.delayed_event = true; + schedule_delayed_work(&dev->mode_config.output_poll_work, + 0); + } } /* Re-enable polling in case the global poll config changed. */ @@ -980,7 +1006,11 @@ static void output_poll_execute(struct work_struct *work) struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_work); struct drm_connector *connector; enum drm_connector_status old_status; - bool repoll = false, changed = false; + bool repoll = false, changed; + + /* Pick up any changes detected by the probe functions. */ + changed = dev->mode_config.delayed_event; + dev->mode_config.delayed_event = false; if (!drm_kms_helper_poll) return; diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index adb3f9b..91c8568 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -815,6 +815,7 @@ struct drm_mode_config { /* output poll support */ bool poll_enabled; bool poll_running; + bool delayed_event; struct delayed_work output_poll_work; /* pointers to standard properties */