Skip to content

Commit 7428b2e

Browse files
committed
Merge tag 'drm-fixes-2018-09-12' of git://anongit.freedesktop.org/drm/drm
Pull drm nouveau fixes from Dave Airlie: "I'm sending this separately as it's a bit larger than I generally like for one driver, but it does contain a bunch of make my nvidia laptop not die (runpm) and a bunch to make my docking station and monitor display stuff (mst) fixes. Lyude has spent a lot of time on these, and we are putting the fixes into distro kernels as well asap, as it helps a bunch of standard Lenovo laptops, so I'm fairly happy things are better than they were before these patches, but I decided to split them out just for clarification" * tag 'drm-fixes-2018-09-12' of git://anongit.freedesktop.org/drm/drm: drm/nouveau/disp/gm200-: enforce identity-mapped SOR assignment for LVDS/eDP panels drm/nouveau/disp: fix DP disable race drm/nouveau/disp: move eDP panel power handling drm/nouveau/disp: remove unused struct member drm/nouveau/TBDdevinit: don't fail when PMU/PRE_OS is missing from VBIOS drm/nouveau/mmu: don't attempt to dereference vmm without valid instance pointer drm/nouveau: fix oops in client init failure path drm/nouveau: Fix nouveau_connector_ddc_detect() drm/nouveau/drm/nouveau: Don't forget to cancel hpd_work on suspend/unload drm/nouveau/drm/nouveau: Prevent handling ACPI HPD events too early drm/nouveau: Reset MST branching unit before enabling drm/nouveau: Only write DP_MSTM_CTRL when needed drm/nouveau: Remove useless poll_enable() call in drm_load() drm/nouveau: Remove useless poll_disable() call in switcheroo_set_state() drm/nouveau: Remove useless poll_enable() call in switcheroo_set_state() drm/nouveau: Fix deadlocks in nouveau_connector_detect() drm/nouveau/drm/nouveau: Use pm_runtime_get_noresume() in connector_detect() drm/nouveau/drm/nouveau: Fix deadlock with fb_helper with async RPM requests drm/nouveau: Remove duplicate poll_enable() in pmops_runtime_suspend() drm/nouveau/drm/nouveau: Fix bogus drm_kms_helper_poll_enable() placement
2 parents 67b0760 + 2887e5c commit 7428b2e

File tree

16 files changed

+297
-114
lines changed

16 files changed

+297
-114
lines changed

drivers/gpu/drm/nouveau/dispnv50/disp.c

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,17 +1123,21 @@ nv50_mstm_enable(struct nv50_mstm *mstm, u8 dpcd, int state)
11231123
int ret;
11241124

11251125
if (dpcd >= 0x12) {
1126-
ret = drm_dp_dpcd_readb(mstm->mgr.aux, DP_MSTM_CTRL, &dpcd);
1126+
/* Even if we're enabling MST, start with disabling the
1127+
* branching unit to clear any sink-side MST topology state
1128+
* that wasn't set by us
1129+
*/
1130+
ret = drm_dp_dpcd_writeb(mstm->mgr.aux, DP_MSTM_CTRL, 0);
11271131
if (ret < 0)
11281132
return ret;
11291133

1130-
dpcd &= ~DP_MST_EN;
1131-
if (state)
1132-
dpcd |= DP_MST_EN;
1133-
1134-
ret = drm_dp_dpcd_writeb(mstm->mgr.aux, DP_MSTM_CTRL, dpcd);
1135-
if (ret < 0)
1136-
return ret;
1134+
if (state) {
1135+
/* Now, start initializing */
1136+
ret = drm_dp_dpcd_writeb(mstm->mgr.aux, DP_MSTM_CTRL,
1137+
DP_MST_EN);
1138+
if (ret < 0)
1139+
return ret;
1140+
}
11371141
}
11381142

11391143
return nvif_mthd(disp, 0, &args, sizeof(args));
@@ -1142,31 +1146,58 @@ nv50_mstm_enable(struct nv50_mstm *mstm, u8 dpcd, int state)
11421146
int
11431147
nv50_mstm_detect(struct nv50_mstm *mstm, u8 dpcd[8], int allow)
11441148
{
1145-
int ret, state = 0;
1149+
struct drm_dp_aux *aux;
1150+
int ret;
1151+
bool old_state, new_state;
1152+
u8 mstm_ctrl;
11461153

11471154
if (!mstm)
11481155
return 0;
11491156

1150-
if (dpcd[0] >= 0x12) {
1151-
ret = drm_dp_dpcd_readb(mstm->mgr.aux, DP_MSTM_CAP, &dpcd[1]);
1157+
mutex_lock(&mstm->mgr.lock);
1158+
1159+
old_state = mstm->mgr.mst_state;
1160+
new_state = old_state;
1161+
aux = mstm->mgr.aux;
1162+
1163+
if (old_state) {
1164+
/* Just check that the MST hub is still as we expect it */
1165+
ret = drm_dp_dpcd_readb(aux, DP_MSTM_CTRL, &mstm_ctrl);
1166+
if (ret < 0 || !(mstm_ctrl & DP_MST_EN)) {
1167+
DRM_DEBUG_KMS("Hub gone, disabling MST topology\n");
1168+
new_state = false;
1169+
}
1170+
} else if (dpcd[0] >= 0x12) {
1171+
ret = drm_dp_dpcd_readb(aux, DP_MSTM_CAP, &dpcd[1]);
11521172
if (ret < 0)
1153-
return ret;
1173+
goto probe_error;
11541174

11551175
if (!(dpcd[1] & DP_MST_CAP))
11561176
dpcd[0] = 0x11;
11571177
else
1158-
state = allow;
1178+
new_state = allow;
1179+
}
1180+
1181+
if (new_state == old_state) {
1182+
mutex_unlock(&mstm->mgr.lock);
1183+
return new_state;
11591184
}
11601185

1161-
ret = nv50_mstm_enable(mstm, dpcd[0], state);
1186+
ret = nv50_mstm_enable(mstm, dpcd[0], new_state);
11621187
if (ret)
1163-
return ret;
1188+
goto probe_error;
1189+
1190+
mutex_unlock(&mstm->mgr.lock);
11641191

1165-
ret = drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, state);
1192+
ret = drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, new_state);
11661193
if (ret)
11671194
return nv50_mstm_enable(mstm, dpcd[0], 0);
11681195

1169-
return mstm->mgr.mst_state;
1196+
return new_state;
1197+
1198+
probe_error:
1199+
mutex_unlock(&mstm->mgr.lock);
1200+
return ret;
11701201
}
11711202

11721203
static void
@@ -2074,7 +2105,7 @@ nv50_disp_atomic_state_alloc(struct drm_device *dev)
20742105
static const struct drm_mode_config_funcs
20752106
nv50_disp_func = {
20762107
.fb_create = nouveau_user_framebuffer_create,
2077-
.output_poll_changed = drm_fb_helper_output_poll_changed,
2108+
.output_poll_changed = nouveau_fbcon_output_poll_changed,
20782109
.atomic_check = nv50_disp_atomic_check,
20792110
.atomic_commit = nv50_disp_atomic_commit,
20802111
.atomic_state_alloc = nv50_disp_atomic_state_alloc,

drivers/gpu/drm/nouveau/nouveau_connector.c

Lines changed: 60 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -409,59 +409,45 @@ static struct nouveau_encoder *
409409
nouveau_connector_ddc_detect(struct drm_connector *connector)
410410
{
411411
struct drm_device *dev = connector->dev;
412-
struct nouveau_connector *nv_connector = nouveau_connector(connector);
413-
struct nouveau_drm *drm = nouveau_drm(dev);
414-
struct nvkm_gpio *gpio = nvxx_gpio(&drm->client.device);
415-
struct nouveau_encoder *nv_encoder = NULL;
412+
struct nouveau_encoder *nv_encoder = NULL, *found = NULL;
416413
struct drm_encoder *encoder;
417-
int i, panel = -ENODEV;
418-
419-
/* eDP panels need powering on by us (if the VBIOS doesn't default it
420-
* to on) before doing any AUX channel transactions. LVDS panel power
421-
* is handled by the SOR itself, and not required for LVDS DDC.
422-
*/
423-
if (nv_connector->type == DCB_CONNECTOR_eDP) {
424-
panel = nvkm_gpio_get(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff);
425-
if (panel == 0) {
426-
nvkm_gpio_set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 1);
427-
msleep(300);
428-
}
429-
}
414+
int i, ret;
415+
bool switcheroo_ddc = false;
430416

431417
drm_connector_for_each_possible_encoder(connector, encoder, i) {
432418
nv_encoder = nouveau_encoder(encoder);
433419

434-
if (nv_encoder->dcb->type == DCB_OUTPUT_DP) {
435-
int ret = nouveau_dp_detect(nv_encoder);
420+
switch (nv_encoder->dcb->type) {
421+
case DCB_OUTPUT_DP:
422+
ret = nouveau_dp_detect(nv_encoder);
436423
if (ret == NOUVEAU_DP_MST)
437424
return NULL;
438-
if (ret == NOUVEAU_DP_SST)
439-
break;
440-
} else
441-
if ((vga_switcheroo_handler_flags() &
442-
VGA_SWITCHEROO_CAN_SWITCH_DDC) &&
443-
nv_encoder->dcb->type == DCB_OUTPUT_LVDS &&
444-
nv_encoder->i2c) {
445-
int ret;
446-
vga_switcheroo_lock_ddc(dev->pdev);
447-
ret = nvkm_probe_i2c(nv_encoder->i2c, 0x50);
448-
vga_switcheroo_unlock_ddc(dev->pdev);
449-
if (ret)
425+
else if (ret == NOUVEAU_DP_SST)
426+
found = nv_encoder;
427+
428+
break;
429+
case DCB_OUTPUT_LVDS:
430+
switcheroo_ddc = !!(vga_switcheroo_handler_flags() &
431+
VGA_SWITCHEROO_CAN_SWITCH_DDC);
432+
/* fall-through */
433+
default:
434+
if (!nv_encoder->i2c)
450435
break;
451-
} else
452-
if (nv_encoder->i2c) {
436+
437+
if (switcheroo_ddc)
438+
vga_switcheroo_lock_ddc(dev->pdev);
453439
if (nvkm_probe_i2c(nv_encoder->i2c, 0x50))
454-
break;
440+
found = nv_encoder;
441+
if (switcheroo_ddc)
442+
vga_switcheroo_unlock_ddc(dev->pdev);
443+
444+
break;
455445
}
446+
if (found)
447+
break;
456448
}
457449

458-
/* eDP panel not detected, restore panel power GPIO to previous
459-
* state to avoid confusing the SOR for other output types.
460-
*/
461-
if (!nv_encoder && panel == 0)
462-
nvkm_gpio_set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, panel);
463-
464-
return nv_encoder;
450+
return found;
465451
}
466452

467453
static struct nouveau_encoder *
@@ -555,12 +541,16 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
555541
nv_connector->edid = NULL;
556542
}
557543

558-
/* Outputs are only polled while runtime active, so acquiring a
559-
* runtime PM ref here is unnecessary (and would deadlock upon
560-
* runtime suspend because it waits for polling to finish).
544+
/* Outputs are only polled while runtime active, so resuming the
545+
* device here is unnecessary (and would deadlock upon runtime suspend
546+
* because it waits for polling to finish). We do however, want to
547+
* prevent the autosuspend timer from elapsing during this operation
548+
* if possible.
561549
*/
562-
if (!drm_kms_helper_is_poll_worker()) {
563-
ret = pm_runtime_get_sync(connector->dev->dev);
550+
if (drm_kms_helper_is_poll_worker()) {
551+
pm_runtime_get_noresume(dev->dev);
552+
} else {
553+
ret = pm_runtime_get_sync(dev->dev);
564554
if (ret < 0 && ret != -EACCES)
565555
return conn_status;
566556
}
@@ -638,10 +628,8 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
638628

639629
out:
640630

641-
if (!drm_kms_helper_is_poll_worker()) {
642-
pm_runtime_mark_last_busy(connector->dev->dev);
643-
pm_runtime_put_autosuspend(connector->dev->dev);
644-
}
631+
pm_runtime_mark_last_busy(dev->dev);
632+
pm_runtime_put_autosuspend(dev->dev);
645633

646634
return conn_status;
647635
}
@@ -1105,6 +1093,26 @@ nouveau_connector_hotplug(struct nvif_notify *notify)
11051093
const struct nvif_notify_conn_rep_v0 *rep = notify->data;
11061094
const char *name = connector->name;
11071095
struct nouveau_encoder *nv_encoder;
1096+
int ret;
1097+
1098+
ret = pm_runtime_get(drm->dev->dev);
1099+
if (ret == 0) {
1100+
/* We can't block here if there's a pending PM request
1101+
* running, as we'll deadlock nouveau_display_fini() when it
1102+
* calls nvif_put() on our nvif_notify struct. So, simply
1103+
* defer the hotplug event until the device finishes resuming
1104+
*/
1105+
NV_DEBUG(drm, "Deferring HPD on %s until runtime resume\n",
1106+
name);
1107+
schedule_work(&drm->hpd_work);
1108+
1109+
pm_runtime_put_noidle(drm->dev->dev);
1110+
return NVIF_NOTIFY_KEEP;
1111+
} else if (ret != 1 && ret != -EACCES) {
1112+
NV_WARN(drm, "HPD on %s dropped due to RPM failure: %d\n",
1113+
name, ret);
1114+
return NVIF_NOTIFY_DROP;
1115+
}
11081116

11091117
if (rep->mask & NVIF_NOTIFY_CONN_V0_IRQ) {
11101118
NV_DEBUG(drm, "service %s\n", name);
@@ -1122,6 +1130,8 @@ nouveau_connector_hotplug(struct nvif_notify *notify)
11221130
drm_helper_hpd_irq_event(connector->dev);
11231131
}
11241132

1133+
pm_runtime_mark_last_busy(drm->dev->dev);
1134+
pm_runtime_put_autosuspend(drm->dev->dev);
11251135
return NVIF_NOTIFY_KEEP;
11261136
}
11271137

drivers/gpu/drm/nouveau/nouveau_display.c

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ nouveau_user_framebuffer_create(struct drm_device *dev,
293293

294294
static const struct drm_mode_config_funcs nouveau_mode_config_funcs = {
295295
.fb_create = nouveau_user_framebuffer_create,
296-
.output_poll_changed = drm_fb_helper_output_poll_changed,
296+
.output_poll_changed = nouveau_fbcon_output_poll_changed,
297297
};
298298

299299

@@ -355,8 +355,6 @@ nouveau_display_hpd_work(struct work_struct *work)
355355
pm_runtime_get_sync(drm->dev->dev);
356356

357357
drm_helper_hpd_irq_event(drm->dev);
358-
/* enable polling for external displays */
359-
drm_kms_helper_poll_enable(drm->dev);
360358

361359
pm_runtime_mark_last_busy(drm->dev->dev);
362360
pm_runtime_put_sync(drm->dev->dev);
@@ -379,15 +377,29 @@ nouveau_display_acpi_ntfy(struct notifier_block *nb, unsigned long val,
379377
{
380378
struct nouveau_drm *drm = container_of(nb, typeof(*drm), acpi_nb);
381379
struct acpi_bus_event *info = data;
380+
int ret;
382381

383382
if (!strcmp(info->device_class, ACPI_VIDEO_CLASS)) {
384383
if (info->type == ACPI_VIDEO_NOTIFY_PROBE) {
385-
/*
386-
* This may be the only indication we receive of a
387-
* connector hotplug on a runtime suspended GPU,
388-
* schedule hpd_work to check.
389-
*/
390-
schedule_work(&drm->hpd_work);
384+
ret = pm_runtime_get(drm->dev->dev);
385+
if (ret == 1 || ret == -EACCES) {
386+
/* If the GPU is already awake, or in a state
387+
* where we can't wake it up, it can handle
388+
* it's own hotplug events.
389+
*/
390+
pm_runtime_put_autosuspend(drm->dev->dev);
391+
} else if (ret == 0) {
392+
/* This may be the only indication we receive
393+
* of a connector hotplug on a runtime
394+
* suspended GPU, schedule hpd_work to check.
395+
*/
396+
NV_DEBUG(drm, "ACPI requested connector reprobe\n");
397+
schedule_work(&drm->hpd_work);
398+
pm_runtime_put_noidle(drm->dev->dev);
399+
} else {
400+
NV_WARN(drm, "Dropped ACPI reprobe event due to RPM error: %d\n",
401+
ret);
402+
}
391403

392404
/* acpi-video should not generate keypresses for this */
393405
return NOTIFY_BAD;
@@ -411,6 +423,11 @@ nouveau_display_init(struct drm_device *dev)
411423
if (ret)
412424
return ret;
413425

426+
/* enable connector detection and polling for connectors without HPD
427+
* support
428+
*/
429+
drm_kms_helper_poll_enable(dev);
430+
414431
/* enable hotplug interrupts */
415432
drm_connector_list_iter_begin(dev, &conn_iter);
416433
nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) {
@@ -425,7 +442,7 @@ nouveau_display_init(struct drm_device *dev)
425442
}
426443

427444
void
428-
nouveau_display_fini(struct drm_device *dev, bool suspend)
445+
nouveau_display_fini(struct drm_device *dev, bool suspend, bool runtime)
429446
{
430447
struct nouveau_display *disp = nouveau_display(dev);
431448
struct nouveau_drm *drm = nouveau_drm(dev);
@@ -450,6 +467,9 @@ nouveau_display_fini(struct drm_device *dev, bool suspend)
450467
}
451468
drm_connector_list_iter_end(&conn_iter);
452469

470+
if (!runtime)
471+
cancel_work_sync(&drm->hpd_work);
472+
453473
drm_kms_helper_poll_disable(dev);
454474
disp->fini(dev);
455475
}
@@ -618,11 +638,11 @@ nouveau_display_suspend(struct drm_device *dev, bool runtime)
618638
}
619639
}
620640

621-
nouveau_display_fini(dev, true);
641+
nouveau_display_fini(dev, true, runtime);
622642
return 0;
623643
}
624644

625-
nouveau_display_fini(dev, true);
645+
nouveau_display_fini(dev, true, runtime);
626646

627647
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
628648
struct nouveau_framebuffer *nouveau_fb;

drivers/gpu/drm/nouveau/nouveau_display.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ nouveau_display(struct drm_device *dev)
6262
int nouveau_display_create(struct drm_device *dev);
6363
void nouveau_display_destroy(struct drm_device *dev);
6464
int nouveau_display_init(struct drm_device *dev);
65-
void nouveau_display_fini(struct drm_device *dev, bool suspend);
65+
void nouveau_display_fini(struct drm_device *dev, bool suspend, bool runtime);
6666
int nouveau_display_suspend(struct drm_device *dev, bool runtime);
6767
void nouveau_display_resume(struct drm_device *dev, bool runtime);
6868
int nouveau_display_vblank_enable(struct drm_device *, unsigned int);

0 commit comments

Comments
 (0)