diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau')
-rw-r--r-- | drivers/gpu/drm/nouveau/Kbuild | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_display.c | 39 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_display.h | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drm.c | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_gem.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_ttm.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_display.c | 31 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/core/object.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c | 59 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c | 2 |
16 files changed, 79 insertions, 95 deletions
diff --git a/drivers/gpu/drm/nouveau/Kbuild b/drivers/gpu/drm/nouveau/Kbuild index fde6e3656636..2e9ce53ae3a8 100644 --- a/drivers/gpu/drm/nouveau/Kbuild +++ b/drivers/gpu/drm/nouveau/Kbuild @@ -1,4 +1,3 @@ -ccflags-y := -Iinclude/drm ccflags-y += -I$(src)/include ccflags-y += -I$(src)/include/nvkm ccflags-y += -I$(src)/nvkm diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 21b10f9840c9..6718c84fb862 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -98,7 +98,7 @@ calc(int blanks, int blanke, int total, int line) return line; } -static int +static bool nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos, ktime_t *stime, ktime_t *etime) { @@ -111,16 +111,16 @@ nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos, }; struct nouveau_display *disp = nouveau_display(crtc->dev); struct drm_vblank_crtc *vblank = &crtc->dev->vblank[drm_crtc_index(crtc)]; - int ret, retry = 20; + int retry = 20; + bool ret = false; do { ret = nvif_mthd(&disp->disp, 0, &args, sizeof(args)); if (ret != 0) - return 0; + return false; if (args.scan.vline) { - ret |= DRM_SCANOUTPOS_ACCURATE; - ret |= DRM_SCANOUTPOS_VALID; + ret = true; break; } @@ -133,14 +133,12 @@ nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos, if (stime) *stime = ns_to_ktime(args.scan.time[0]); if (etime) *etime = ns_to_ktime(args.scan.time[1]); - if (*vpos < 0) - ret |= DRM_SCANOUTPOS_IN_VBLANK; return ret; } -int +bool nouveau_display_scanoutpos(struct drm_device *dev, unsigned int pipe, - unsigned int flags, int *vpos, int *hpos, + bool in_vblank_irq, int *vpos, int *hpos, ktime_t *stime, ktime_t *etime, const struct drm_display_mode *mode) { @@ -153,28 +151,7 @@ nouveau_display_scanoutpos(struct drm_device *dev, unsigned int pipe, } } - return 0; -} - -int -nouveau_display_vblstamp(struct drm_device *dev, unsigned int pipe, - int *max_error, struct timeval *time, unsigned flags) -{ - struct drm_crtc *crtc; - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - if (nouveau_crtc(crtc)->index == pipe) { - struct drm_display_mode *mode; - if (drm_drv_uses_atomic_modeset(dev)) - mode = &crtc->state->adjusted_mode; - else - mode = &crtc->hwmode; - return drm_calc_vbltimestamp_from_scanoutpos(dev, - pipe, max_error, time, flags, mode); - } - } - - return -EINVAL; + return false; } static void diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h index e1d772d39488..201aec2ea5b8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.h +++ b/drivers/gpu/drm/nouveau/nouveau_display.h @@ -68,11 +68,9 @@ int nouveau_display_suspend(struct drm_device *dev, bool runtime); void nouveau_display_resume(struct drm_device *dev, bool runtime); int nouveau_display_vblank_enable(struct drm_device *, unsigned int); void nouveau_display_vblank_disable(struct drm_device *, unsigned int); -int nouveau_display_scanoutpos(struct drm_device *, unsigned int, - unsigned int, int *, int *, ktime_t *, - ktime_t *, const struct drm_display_mode *); -int nouveau_display_vblstamp(struct drm_device *, unsigned int, int *, - struct timeval *, unsigned); +bool nouveau_display_scanoutpos(struct drm_device *, unsigned int, + bool, int *, int *, ktime_t *, + ktime_t *, const struct drm_display_mode *); int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, struct drm_pending_vblank_event *event, diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 2b6ac24ce690..c3dc75fee700 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -29,8 +29,8 @@ #include <linux/pm_runtime.h> #include <linux/vga_switcheroo.h> -#include "drmP.h" -#include "drm_crtc_helper.h" +#include <drm/drmP.h> +#include <drm/drm_crtc_helper.h> #include <core/gpuobj.h> #include <core/option.h> @@ -881,7 +881,7 @@ done: } static void -nouveau_drm_preclose(struct drm_device *dev, struct drm_file *fpriv) +nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv) { struct nouveau_cli *cli = nouveau_cli(fpriv); struct nouveau_drm *drm = nouveau_drm(dev); @@ -897,12 +897,6 @@ nouveau_drm_preclose(struct drm_device *dev, struct drm_file *fpriv) list_del(&cli->head); mutex_unlock(&drm->client.mutex); -} - -static void -nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv) -{ - struct nouveau_cli *cli = nouveau_cli(fpriv); nouveau_cli_fini(cli); kfree(cli); pm_runtime_mark_last_busy(dev->dev); @@ -974,7 +968,6 @@ driver_stub = { .load = nouveau_drm_load, .unload = nouveau_drm_unload, .open = nouveau_drm_open, - .preclose = nouveau_drm_preclose, .postclose = nouveau_drm_postclose, .lastclose = nouveau_vga_lastclose, @@ -985,7 +978,7 @@ driver_stub = { .enable_vblank = nouveau_display_vblank_enable, .disable_vblank = nouveau_display_vblank_disable, .get_scanout_position = nouveau_display_scanoutpos, - .get_vblank_timestamp = nouveau_display_vblstamp, + .get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos, .ioctls = nouveau_ioctls, .num_ioctls = ARRAY_SIZE(nouveau_ioctls), diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index eadec2f49ad3..aaa25641fed6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -43,7 +43,7 @@ #include <nvif/device.h> #include <nvif/ioctl.h> -#include <drmP.h> +#include <drm/drmP.h> #include <drm/ttm/ttm_bo_api.h> #include <drm/ttm/ttm_bo_driver.h> diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index ca5397beb357..2170534101ca 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -568,9 +568,7 @@ u_memcpya(uint64_t user, unsigned nmemb, unsigned size) size *= nmemb; - mem = kmalloc(size, GFP_KERNEL | __GFP_NOWARN); - if (!mem) - mem = vmalloc(size); + mem = kvmalloc(size, GFP_KERNEL); if (!mem) return ERR_PTR(-ENOMEM); diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index 13e5cc5f07fe..999c35a25498 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -28,7 +28,7 @@ #include "nouveau_ttm.h" #include "nouveau_gem.h" -#include "drm_legacy.h" +#include <drm/drm_legacy.h> #include <core/tegra.h> diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 0e58537352fe..9303daa79aba 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -831,8 +831,7 @@ nv50_wndw_atomic_check_release(struct nv50_wndw *wndw, static int nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, - struct nv50_head_atom *asyh, - u32 pflip_flags) + struct nv50_head_atom *asyh) { struct nouveau_framebuffer *fb = nouveau_framebuffer(asyw->state.fb); struct nouveau_drm *drm = nouveau_drm(wndw->plane.dev); @@ -848,7 +847,10 @@ nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw, asyw->image.h = fb->base.height; asyw->image.kind = (fb->nvbo->tile_flags & 0x0000ff00) >> 8; - asyw->interval = pflip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? 0 : 1; + if (asyh->state.pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC) + asyw->interval = 0; + else + asyw->interval = 1; if (asyw->image.kind) { asyw->image.layout = 0; @@ -887,7 +889,6 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) struct nv50_head_atom *harm = NULL, *asyh = NULL; bool varm = false, asyv = false, asym = false; int ret; - u32 pflip_flags = 0; NV_ATOMIC(drm, "%s atomic_check\n", plane->name); if (asyw->state.crtc) { @@ -896,7 +897,6 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) return PTR_ERR(asyh); asym = drm_atomic_crtc_needs_modeset(&asyh->state); asyv = asyh->state.active; - pflip_flags = asyh->state.pageflip_flags; } if (armw->state.crtc) { @@ -912,12 +912,9 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) if (memcmp(&armw->point, &asyw->point, sizeof(asyw->point))) asyw->set.point = true; - if (!varm || asym || armw->state.fb != asyw->state.fb) { - ret = nv50_wndw_atomic_check_acquire( - wndw, asyw, asyh, pflip_flags); - if (ret) - return ret; - } + ret = nv50_wndw_atomic_check_acquire(wndw, asyw, asyh); + if (ret) + return ret; } else if (varm) { nv50_wndw_atomic_check_release(wndw, asyw, harm); @@ -1036,7 +1033,7 @@ nv50_wndw_reset(struct drm_plane *plane) plane->funcs->atomic_destroy_state(plane, plane->state); plane->state = &asyw->state; plane->state->plane = plane; - plane->state->rotation = DRM_ROTATE_0; + plane->state->rotation = DRM_MODE_ROTATE_0; } static void @@ -1122,9 +1119,13 @@ static void nv50_curs_prepare(struct nv50_wndw *wndw, struct nv50_head_atom *asyh, struct nv50_wndw_atom *asyw) { - asyh->curs.handle = nv50_disp(wndw->plane.dev)->mast.base.vram.handle; - asyh->curs.offset = asyw->image.offset; - asyh->set.curs = asyh->curs.visible; + u32 handle = nv50_disp(wndw->plane.dev)->mast.base.vram.handle; + u32 offset = asyw->image.offset; + if (asyh->curs.handle != handle || asyh->curs.offset != offset) { + asyh->curs.handle = handle; + asyh->curs.offset = offset; + asyh->set.curs = asyh->curs.visible; + } } static void diff --git a/drivers/gpu/drm/nouveau/nvkm/core/object.c b/drivers/gpu/drm/nouveau/nvkm/core/object.c index 89d2e9da11c7..acd76fd4f6d8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/object.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/object.c @@ -295,7 +295,7 @@ nvkm_object_ctor(const struct nvkm_object_func *func, INIT_LIST_HEAD(&object->head); INIT_LIST_HEAD(&object->tree); RB_CLEAR_NODE(&object->node); - WARN_ON(oclass->engine && !object->engine); + WARN_ON(IS_ERR(object->engine)); } int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c index c63975907c90..4a9bd4f1cb93 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c @@ -638,7 +638,6 @@ gf100_ram_ctor(const struct nvkm_ram_func *func, struct nvkm_fb *fb, return ret; } - ram->ranks = (nvkm_rd32(device, 0x10f200) & 0x00000004) ? 2 : 1; return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c index df949fa7d05d..be691a7b972f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c @@ -146,7 +146,7 @@ nvkm_therm_update(struct nvkm_therm *therm, int mode) poll = false; } - if (list_empty(&therm->alarm.head) && poll) + if (poll) nvkm_timer_alarm(tmr, 1000000000ULL, &therm->alarm); spin_unlock_irqrestore(&therm->lock, flags); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c index 91198d79393a..e2feccec25f5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c @@ -83,7 +83,7 @@ nvkm_fan_update(struct nvkm_fan *fan, bool immediate, int target) spin_unlock_irqrestore(&fan->lock, flags); /* schedule next fan update, if not at target speed already */ - if (list_empty(&fan->alarm.head) && target != duty) { + if (target != duty) { u16 bump_period = fan->bios.bump_period; u16 slow_down_period = fan->bios.slow_down_period; u64 delay; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c index 59701b7a6597..ff9fbe7950e5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c @@ -53,7 +53,7 @@ nvkm_fantog_update(struct nvkm_fantog *fan, int percent) duty = !nvkm_gpio_get(gpio, 0, DCB_GPIO_FAN, 0xff); nvkm_gpio_set(gpio, 0, DCB_GPIO_FAN, 0xff, duty); - if (list_empty(&fan->alarm.head) && percent != (duty * 100)) { + if (percent != (duty * 100)) { u64 next_change = (percent * fan->period_us) / 100; if (!duty) next_change = fan->period_us - next_change; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c index b9703c02d8ca..9a79e91fdfdc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c @@ -185,7 +185,7 @@ alarm_timer_callback(struct nvkm_alarm *alarm) spin_unlock_irqrestore(&therm->sensor.alarm_program_lock, flags); /* schedule the next poll in one second */ - if (therm->func->temp_get(therm) >= 0 && list_empty(&alarm->head)) + if (therm->func->temp_get(therm) >= 0) nvkm_timer_alarm(tmr, 1000000000ULL, alarm); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c index 07dc82bfe346..f2a86eae0a0d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c @@ -36,23 +36,29 @@ nvkm_timer_alarm_trigger(struct nvkm_timer *tmr) unsigned long flags; LIST_HEAD(exec); - /* move any due alarms off the pending list */ + /* Process pending alarms. */ spin_lock_irqsave(&tmr->lock, flags); list_for_each_entry_safe(alarm, atemp, &tmr->alarms, head) { - if (alarm->timestamp <= nvkm_timer_read(tmr)) - list_move_tail(&alarm->head, &exec); + /* Have we hit the earliest alarm that hasn't gone off? */ + if (alarm->timestamp > nvkm_timer_read(tmr)) { + /* Schedule it. If we didn't race, we're done. */ + tmr->func->alarm_init(tmr, alarm->timestamp); + if (alarm->timestamp > nvkm_timer_read(tmr)) + break; + } + + /* Move to completed list. We'll drop the lock before + * executing the callback so it can reschedule itself. + */ + list_move_tail(&alarm->head, &exec); } - /* reschedule interrupt for next alarm time */ - if (!list_empty(&tmr->alarms)) { - alarm = list_first_entry(&tmr->alarms, typeof(*alarm), head); - tmr->func->alarm_init(tmr, alarm->timestamp); - } else { + /* Shut down interrupt if no more pending alarms. */ + if (list_empty(&tmr->alarms)) tmr->func->alarm_fini(tmr); - } spin_unlock_irqrestore(&tmr->lock, flags); - /* execute any pending alarm handlers */ + /* Execute completed callbacks. */ list_for_each_entry_safe(alarm, atemp, &exec, head) { list_del_init(&alarm->head); alarm->func(alarm); @@ -65,24 +71,37 @@ nvkm_timer_alarm(struct nvkm_timer *tmr, u32 nsec, struct nvkm_alarm *alarm) struct nvkm_alarm *list; unsigned long flags; - alarm->timestamp = nvkm_timer_read(tmr) + nsec; - - /* append new alarm to list, in soonest-alarm-first order */ + /* Remove alarm from pending list. + * + * This both protects against the corruption of the list, + * and implements alarm rescheduling/cancellation. + */ spin_lock_irqsave(&tmr->lock, flags); - if (!nsec) { - if (!list_empty(&alarm->head)) - list_del(&alarm->head); - } else { + list_del_init(&alarm->head); + + if (nsec) { + /* Insert into pending list, ordered earliest to latest. */ + alarm->timestamp = nvkm_timer_read(tmr) + nsec; list_for_each_entry(list, &tmr->alarms, head) { if (list->timestamp > alarm->timestamp) break; } + list_add_tail(&alarm->head, &list->head); + + /* Update HW if this is now the earliest alarm. */ + list = list_first_entry(&tmr->alarms, typeof(*list), head); + if (list == alarm) { + tmr->func->alarm_init(tmr, alarm->timestamp); + /* This shouldn't happen if callers aren't stupid. + * + * Worst case scenario is that it'll take roughly + * 4 seconds for the next alarm to trigger. + */ + WARN_ON(alarm->timestamp <= nvkm_timer_read(tmr)); + } } spin_unlock_irqrestore(&tmr->lock, flags); - - /* process pending alarms */ - nvkm_timer_alarm_trigger(tmr); } void diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c index 7b9ce87f0617..7f48249f41de 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c @@ -76,8 +76,8 @@ nv04_timer_intr(struct nvkm_timer *tmr) u32 stat = nvkm_rd32(device, NV04_PTIMER_INTR_0); if (stat & 0x00000001) { - nvkm_timer_alarm_trigger(tmr); nvkm_wr32(device, NV04_PTIMER_INTR_0, 0x00000001); + nvkm_timer_alarm_trigger(tmr); stat &= ~0x00000001; } |