Skip to content

Commit bb57d04

Browse files
committed
Merge branch 'linux-4.12' of git://github.com/skeggsb/linux into drm-next
Quite a few patches, but not much code changed: - Fixes regression from atomic when only the source rect of a plane changes (ie. xrandr --right-of) - Fixes another issue where atomic changed behaviour underneath us, potentially causing laggy cursor position updates - Fixes for a bunch of races in thermal code, which lead to random lockups for a lot of users * 'linux-4.12' of git://github.com/skeggsb/linux: drm/nouveau/therm: remove ineffective workarounds for alarm bugs drm/nouveau/tmr: avoid processing completed alarms when adding a new one drm/nouveau/tmr: fix corruption of the pending list when rescheduling an alarm drm/nouveau/tmr: handle races with hw when updating the next alarm time drm/nouveau/tmr: ack interrupt before processing alarms drm/nouveau/core: fix static checker warning drm/nouveau/fb/ram/gf100-: remove 0x10f200 read drm/nouveau/kms/nv50: skip core channel cursor update on position-only changes drm/nouveau/kms/nv50: fix source-rect-only plane updates drm/nouveau/kms/nv50: remove pointless argument to window atomic_check_acquire()
2 parents 7ec2723 + e4311ee commit bb57d04

File tree

9 files changed

+60
-41
lines changed

9 files changed

+60
-41
lines changed

drivers/gpu/drm/nouveau/nv50_display.c

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -831,8 +831,7 @@ nv50_wndw_atomic_check_release(struct nv50_wndw *wndw,
831831
static int
832832
nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw,
833833
struct nv50_wndw_atom *asyw,
834-
struct nv50_head_atom *asyh,
835-
u32 pflip_flags)
834+
struct nv50_head_atom *asyh)
836835
{
837836
struct nouveau_framebuffer *fb = nouveau_framebuffer(asyw->state.fb);
838837
struct nouveau_drm *drm = nouveau_drm(wndw->plane.dev);
@@ -848,7 +847,10 @@ nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw,
848847
asyw->image.h = fb->base.height;
849848
asyw->image.kind = (fb->nvbo->tile_flags & 0x0000ff00) >> 8;
850849

851-
asyw->interval = pflip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? 0 : 1;
850+
if (asyh->state.pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC)
851+
asyw->interval = 0;
852+
else
853+
asyw->interval = 1;
852854

853855
if (asyw->image.kind) {
854856
asyw->image.layout = 0;
@@ -887,7 +889,6 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
887889
struct nv50_head_atom *harm = NULL, *asyh = NULL;
888890
bool varm = false, asyv = false, asym = false;
889891
int ret;
890-
u32 pflip_flags = 0;
891892

892893
NV_ATOMIC(drm, "%s atomic_check\n", plane->name);
893894
if (asyw->state.crtc) {
@@ -896,7 +897,6 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
896897
return PTR_ERR(asyh);
897898
asym = drm_atomic_crtc_needs_modeset(&asyh->state);
898899
asyv = asyh->state.active;
899-
pflip_flags = asyh->state.pageflip_flags;
900900
}
901901

902902
if (armw->state.crtc) {
@@ -912,12 +912,9 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
912912
if (memcmp(&armw->point, &asyw->point, sizeof(asyw->point)))
913913
asyw->set.point = true;
914914

915-
if (!varm || asym || armw->state.fb != asyw->state.fb) {
916-
ret = nv50_wndw_atomic_check_acquire(
917-
wndw, asyw, asyh, pflip_flags);
918-
if (ret)
919-
return ret;
920-
}
915+
ret = nv50_wndw_atomic_check_acquire(wndw, asyw, asyh);
916+
if (ret)
917+
return ret;
921918
} else
922919
if (varm) {
923920
nv50_wndw_atomic_check_release(wndw, asyw, harm);
@@ -1122,9 +1119,13 @@ static void
11221119
nv50_curs_prepare(struct nv50_wndw *wndw, struct nv50_head_atom *asyh,
11231120
struct nv50_wndw_atom *asyw)
11241121
{
1125-
asyh->curs.handle = nv50_disp(wndw->plane.dev)->mast.base.vram.handle;
1126-
asyh->curs.offset = asyw->image.offset;
1127-
asyh->set.curs = asyh->curs.visible;
1122+
u32 handle = nv50_disp(wndw->plane.dev)->mast.base.vram.handle;
1123+
u32 offset = asyw->image.offset;
1124+
if (asyh->curs.handle != handle || asyh->curs.offset != offset) {
1125+
asyh->curs.handle = handle;
1126+
asyh->curs.offset = offset;
1127+
asyh->set.curs = asyh->curs.visible;
1128+
}
11281129
}
11291130

11301131
static void

drivers/gpu/drm/nouveau/nvkm/core/object.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ nvkm_object_ctor(const struct nvkm_object_func *func,
295295
INIT_LIST_HEAD(&object->head);
296296
INIT_LIST_HEAD(&object->tree);
297297
RB_CLEAR_NODE(&object->node);
298-
WARN_ON(oclass->engine && !object->engine);
298+
WARN_ON(IS_ERR(object->engine));
299299
}
300300

301301
int

drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,6 @@ gf100_ram_ctor(const struct nvkm_ram_func *func, struct nvkm_fb *fb,
638638
return ret;
639639
}
640640

641-
ram->ranks = (nvkm_rd32(device, 0x10f200) & 0x00000004) ? 2 : 1;
642641
return 0;
643642
}
644643

drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ nvkm_therm_update(struct nvkm_therm *therm, int mode)
146146
poll = false;
147147
}
148148

149-
if (list_empty(&therm->alarm.head) && poll)
149+
if (poll)
150150
nvkm_timer_alarm(tmr, 1000000000ULL, &therm->alarm);
151151
spin_unlock_irqrestore(&therm->lock, flags);
152152

drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ nvkm_fan_update(struct nvkm_fan *fan, bool immediate, int target)
8383
spin_unlock_irqrestore(&fan->lock, flags);
8484

8585
/* schedule next fan update, if not at target speed already */
86-
if (list_empty(&fan->alarm.head) && target != duty) {
86+
if (target != duty) {
8787
u16 bump_period = fan->bios.bump_period;
8888
u16 slow_down_period = fan->bios.slow_down_period;
8989
u64 delay;

drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ nvkm_fantog_update(struct nvkm_fantog *fan, int percent)
5353
duty = !nvkm_gpio_get(gpio, 0, DCB_GPIO_FAN, 0xff);
5454
nvkm_gpio_set(gpio, 0, DCB_GPIO_FAN, 0xff, duty);
5555

56-
if (list_empty(&fan->alarm.head) && percent != (duty * 100)) {
56+
if (percent != (duty * 100)) {
5757
u64 next_change = (percent * fan->period_us) / 100;
5858
if (!duty)
5959
next_change = fan->period_us - next_change;

drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ alarm_timer_callback(struct nvkm_alarm *alarm)
185185
spin_unlock_irqrestore(&therm->sensor.alarm_program_lock, flags);
186186

187187
/* schedule the next poll in one second */
188-
if (therm->func->temp_get(therm) >= 0 && list_empty(&alarm->head))
188+
if (therm->func->temp_get(therm) >= 0)
189189
nvkm_timer_alarm(tmr, 1000000000ULL, alarm);
190190
}
191191

drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -36,23 +36,29 @@ nvkm_timer_alarm_trigger(struct nvkm_timer *tmr)
3636
unsigned long flags;
3737
LIST_HEAD(exec);
3838

39-
/* move any due alarms off the pending list */
39+
/* Process pending alarms. */
4040
spin_lock_irqsave(&tmr->lock, flags);
4141
list_for_each_entry_safe(alarm, atemp, &tmr->alarms, head) {
42-
if (alarm->timestamp <= nvkm_timer_read(tmr))
43-
list_move_tail(&alarm->head, &exec);
42+
/* Have we hit the earliest alarm that hasn't gone off? */
43+
if (alarm->timestamp > nvkm_timer_read(tmr)) {
44+
/* Schedule it. If we didn't race, we're done. */
45+
tmr->func->alarm_init(tmr, alarm->timestamp);
46+
if (alarm->timestamp > nvkm_timer_read(tmr))
47+
break;
48+
}
49+
50+
/* Move to completed list. We'll drop the lock before
51+
* executing the callback so it can reschedule itself.
52+
*/
53+
list_move_tail(&alarm->head, &exec);
4454
}
4555

46-
/* reschedule interrupt for next alarm time */
47-
if (!list_empty(&tmr->alarms)) {
48-
alarm = list_first_entry(&tmr->alarms, typeof(*alarm), head);
49-
tmr->func->alarm_init(tmr, alarm->timestamp);
50-
} else {
56+
/* Shut down interrupt if no more pending alarms. */
57+
if (list_empty(&tmr->alarms))
5158
tmr->func->alarm_fini(tmr);
52-
}
5359
spin_unlock_irqrestore(&tmr->lock, flags);
5460

55-
/* execute any pending alarm handlers */
61+
/* Execute completed callbacks. */
5662
list_for_each_entry_safe(alarm, atemp, &exec, head) {
5763
list_del_init(&alarm->head);
5864
alarm->func(alarm);
@@ -65,24 +71,37 @@ nvkm_timer_alarm(struct nvkm_timer *tmr, u32 nsec, struct nvkm_alarm *alarm)
6571
struct nvkm_alarm *list;
6672
unsigned long flags;
6773

68-
alarm->timestamp = nvkm_timer_read(tmr) + nsec;
69-
70-
/* append new alarm to list, in soonest-alarm-first order */
74+
/* Remove alarm from pending list.
75+
*
76+
* This both protects against the corruption of the list,
77+
* and implements alarm rescheduling/cancellation.
78+
*/
7179
spin_lock_irqsave(&tmr->lock, flags);
72-
if (!nsec) {
73-
if (!list_empty(&alarm->head))
74-
list_del(&alarm->head);
75-
} else {
80+
list_del_init(&alarm->head);
81+
82+
if (nsec) {
83+
/* Insert into pending list, ordered earliest to latest. */
84+
alarm->timestamp = nvkm_timer_read(tmr) + nsec;
7685
list_for_each_entry(list, &tmr->alarms, head) {
7786
if (list->timestamp > alarm->timestamp)
7887
break;
7988
}
89+
8090
list_add_tail(&alarm->head, &list->head);
91+
92+
/* Update HW if this is now the earliest alarm. */
93+
list = list_first_entry(&tmr->alarms, typeof(*list), head);
94+
if (list == alarm) {
95+
tmr->func->alarm_init(tmr, alarm->timestamp);
96+
/* This shouldn't happen if callers aren't stupid.
97+
*
98+
* Worst case scenario is that it'll take roughly
99+
* 4 seconds for the next alarm to trigger.
100+
*/
101+
WARN_ON(alarm->timestamp <= nvkm_timer_read(tmr));
102+
}
81103
}
82104
spin_unlock_irqrestore(&tmr->lock, flags);
83-
84-
/* process pending alarms */
85-
nvkm_timer_alarm_trigger(tmr);
86105
}
87106

88107
void

drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ nv04_timer_intr(struct nvkm_timer *tmr)
7676
u32 stat = nvkm_rd32(device, NV04_PTIMER_INTR_0);
7777

7878
if (stat & 0x00000001) {
79-
nvkm_timer_alarm_trigger(tmr);
8079
nvkm_wr32(device, NV04_PTIMER_INTR_0, 0x00000001);
80+
nvkm_timer_alarm_trigger(tmr);
8181
stat &= ~0x00000001;
8282
}
8383

0 commit comments

Comments
 (0)