Commit 06d1ee32 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux

Pull drm fixes from Dave Airlie:
 "I got a bit behind last week, so here is a delayed fixes pull:

   - a bunch of radeon/amd gpu fixes
   - some nouveau regression fixes (ppc bios reading and runtime pm fix)
   - one drm core oops fix
   - two qxl locking fixes
   - one qxl regression fix"

* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux:
  drm/nouveau/bios: fix OF loading
  drm/nouveau/fbcon: take runpm reference when userspace has an open fd
  drm/nouveau/nouveau: Disable AGP for SiS 761
  drm/nouveau/display: allow up to 16k width/height for fermi+
  drm/nouveau/bios: translate devinit pri/sec i2c bus to internal identifiers
  drm: Fix locking for sysfs dpms file
  drm/amdgpu: fix memory leak in amdgpu_vm_update_page_directory
  drm/amdgpu: fix 32-bit compiler warning
  drm/qxl: avoid dependency lock
  drm/qxl: avoid buffer reservation in qxl_crtc_page_flip
  drm/qxl: fix framebuffer dirty rectangle tracking.
  drm/amdgpu: flag iceland as experimental
  drm/amdgpu: check before checking pci bridge registers
  drm/amdgpu: fix num_crtc on CZ
  drm/amdgpu: restore the fbdev mode in lastclose
  drm/radeon: restore the fbdev mode in lastclose
  drm/radeon: add quirk for ASUS R7 370
  drm/amdgpu: add pm sysfs files late
  drm/radeon: add pm sysfs files late
parents 25cb62b7 7b98040a
...@@ -177,7 +177,7 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) ...@@ -177,7 +177,7 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
/* get chunks */ /* get chunks */
INIT_LIST_HEAD(&p->validated); INIT_LIST_HEAD(&p->validated);
chunk_array_user = (uint64_t __user *)(cs->in.chunks); chunk_array_user = (uint64_t __user *)(unsigned long)(cs->in.chunks);
if (copy_from_user(chunk_array, chunk_array_user, if (copy_from_user(chunk_array, chunk_array_user,
sizeof(uint64_t)*cs->in.num_chunks)) { sizeof(uint64_t)*cs->in.num_chunks)) {
ret = -EFAULT; ret = -EFAULT;
...@@ -197,7 +197,7 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) ...@@ -197,7 +197,7 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
struct drm_amdgpu_cs_chunk user_chunk; struct drm_amdgpu_cs_chunk user_chunk;
uint32_t __user *cdata; uint32_t __user *cdata;
chunk_ptr = (void __user *)chunk_array[i]; chunk_ptr = (void __user *)(unsigned long)chunk_array[i];
if (copy_from_user(&user_chunk, chunk_ptr, if (copy_from_user(&user_chunk, chunk_ptr,
sizeof(struct drm_amdgpu_cs_chunk))) { sizeof(struct drm_amdgpu_cs_chunk))) {
ret = -EFAULT; ret = -EFAULT;
...@@ -208,7 +208,7 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) ...@@ -208,7 +208,7 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
p->chunks[i].length_dw = user_chunk.length_dw; p->chunks[i].length_dw = user_chunk.length_dw;
size = p->chunks[i].length_dw; size = p->chunks[i].length_dw;
cdata = (void __user *)user_chunk.chunk_data; cdata = (void __user *)(unsigned long)user_chunk.chunk_data;
p->chunks[i].user_ptr = cdata; p->chunks[i].user_ptr = cdata;
p->chunks[i].kdata = drm_malloc_ab(size, sizeof(uint32_t)); p->chunks[i].kdata = drm_malloc_ab(size, sizeof(uint32_t));
......
...@@ -242,11 +242,11 @@ static struct pci_device_id pciidlist[] = { ...@@ -242,11 +242,11 @@ static struct pci_device_id pciidlist[] = {
{0x1002, 0x985F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU}, {0x1002, 0x985F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU},
#endif #endif
/* topaz */ /* topaz */
{0x1002, 0x6900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ}, {0x1002, 0x6900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT},
{0x1002, 0x6901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ}, {0x1002, 0x6901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT},
{0x1002, 0x6902, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ}, {0x1002, 0x6902, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT},
{0x1002, 0x6903, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ}, {0x1002, 0x6903, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT},
{0x1002, 0x6907, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ}, {0x1002, 0x6907, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT},
/* tonga */ /* tonga */
{0x1002, 0x6920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA}, {0x1002, 0x6920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA},
{0x1002, 0x6921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA}, {0x1002, 0x6921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA},
......
...@@ -402,3 +402,19 @@ bool amdgpu_fbdev_robj_is_fb(struct amdgpu_device *adev, struct amdgpu_bo *robj) ...@@ -402,3 +402,19 @@ bool amdgpu_fbdev_robj_is_fb(struct amdgpu_device *adev, struct amdgpu_bo *robj)
return true; return true;
return false; return false;
} }
void amdgpu_fbdev_restore_mode(struct amdgpu_device *adev)
{
struct amdgpu_fbdev *afbdev = adev->mode_info.rfbdev;
struct drm_fb_helper *fb_helper;
int ret;
if (!afbdev)
return;
fb_helper = &afbdev->helper;
ret = drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper);
if (ret)
DRM_DEBUG("failed to restore crtc mode\n");
}
...@@ -485,7 +485,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file ...@@ -485,7 +485,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
* Outdated mess for old drm with Xorg being in charge (void function now). * Outdated mess for old drm with Xorg being in charge (void function now).
*/ */
/** /**
* amdgpu_driver_firstopen_kms - drm callback for last close * amdgpu_driver_lastclose_kms - drm callback for last close
* *
* @dev: drm dev pointer * @dev: drm dev pointer
* *
...@@ -493,6 +493,9 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file ...@@ -493,6 +493,9 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
*/ */
void amdgpu_driver_lastclose_kms(struct drm_device *dev) void amdgpu_driver_lastclose_kms(struct drm_device *dev)
{ {
struct amdgpu_device *adev = dev->dev_private;
amdgpu_fbdev_restore_mode(adev);
vga_switcheroo_process_delayed_switch(); vga_switcheroo_process_delayed_switch();
} }
......
...@@ -567,6 +567,7 @@ void amdgpu_fbdev_fini(struct amdgpu_device *adev); ...@@ -567,6 +567,7 @@ void amdgpu_fbdev_fini(struct amdgpu_device *adev);
void amdgpu_fbdev_set_suspend(struct amdgpu_device *adev, int state); void amdgpu_fbdev_set_suspend(struct amdgpu_device *adev, int state);
int amdgpu_fbdev_total_size(struct amdgpu_device *adev); int amdgpu_fbdev_total_size(struct amdgpu_device *adev);
bool amdgpu_fbdev_robj_is_fb(struct amdgpu_device *adev, struct amdgpu_bo *robj); bool amdgpu_fbdev_robj_is_fb(struct amdgpu_device *adev, struct amdgpu_bo *robj);
void amdgpu_fbdev_restore_mode(struct amdgpu_device *adev);
void amdgpu_fb_output_poll_changed(struct amdgpu_device *adev); void amdgpu_fb_output_poll_changed(struct amdgpu_device *adev);
......
...@@ -455,8 +455,10 @@ int amdgpu_vm_update_page_directory(struct amdgpu_device *adev, ...@@ -455,8 +455,10 @@ int amdgpu_vm_update_page_directory(struct amdgpu_device *adev,
return -ENOMEM; return -ENOMEM;
r = amdgpu_ib_get(ring, NULL, ndw * 4, ib); r = amdgpu_ib_get(ring, NULL, ndw * 4, ib);
if (r) if (r) {
kfree(ib);
return r; return r;
}
ib->length_dw = 0; ib->length_dw = 0;
/* walk over the address space and update the page directory */ /* walk over the address space and update the page directory */
......
...@@ -6185,6 +6185,11 @@ static int ci_dpm_late_init(void *handle) ...@@ -6185,6 +6185,11 @@ static int ci_dpm_late_init(void *handle)
if (!amdgpu_dpm) if (!amdgpu_dpm)
return 0; return 0;
/* init the sysfs and debugfs files late */
ret = amdgpu_pm_sysfs_init(adev);
if (ret)
return ret;
ret = ci_set_temperature_range(adev); ret = ci_set_temperature_range(adev);
if (ret) if (ret)
return ret; return ret;
...@@ -6232,9 +6237,6 @@ static int ci_dpm_sw_init(void *handle) ...@@ -6232,9 +6237,6 @@ static int ci_dpm_sw_init(void *handle)
adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps; adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps;
if (amdgpu_dpm == 1) if (amdgpu_dpm == 1)
amdgpu_pm_print_power_states(adev); amdgpu_pm_print_power_states(adev);
ret = amdgpu_pm_sysfs_init(adev);
if (ret)
goto dpm_failed;
mutex_unlock(&adev->pm.mutex); mutex_unlock(&adev->pm.mutex);
DRM_INFO("amdgpu: dpm initialized\n"); DRM_INFO("amdgpu: dpm initialized\n");
......
...@@ -1567,6 +1567,9 @@ static void cik_pcie_gen3_enable(struct amdgpu_device *adev) ...@@ -1567,6 +1567,9 @@ static void cik_pcie_gen3_enable(struct amdgpu_device *adev)
int ret, i; int ret, i;
u16 tmp16; u16 tmp16;
if (pci_is_root_bus(adev->pdev->bus))
return;
if (amdgpu_pcie_gen2 == 0) if (amdgpu_pcie_gen2 == 0)
return; return;
......
...@@ -596,6 +596,12 @@ static int cz_dpm_late_init(void *handle) ...@@ -596,6 +596,12 @@ static int cz_dpm_late_init(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
if (amdgpu_dpm) { if (amdgpu_dpm) {
int ret;
/* init the sysfs and debugfs files late */
ret = amdgpu_pm_sysfs_init(adev);
if (ret)
return ret;
/* powerdown unused blocks for now */ /* powerdown unused blocks for now */
cz_dpm_powergate_uvd(adev, true); cz_dpm_powergate_uvd(adev, true);
cz_dpm_powergate_vce(adev, true); cz_dpm_powergate_vce(adev, true);
...@@ -632,10 +638,6 @@ static int cz_dpm_sw_init(void *handle) ...@@ -632,10 +638,6 @@ static int cz_dpm_sw_init(void *handle)
if (amdgpu_dpm == 1) if (amdgpu_dpm == 1)
amdgpu_pm_print_power_states(adev); amdgpu_pm_print_power_states(adev);
ret = amdgpu_pm_sysfs_init(adev);
if (ret)
goto dpm_init_failed;
mutex_unlock(&adev->pm.mutex); mutex_unlock(&adev->pm.mutex);
DRM_INFO("amdgpu: dpm initialized\n"); DRM_INFO("amdgpu: dpm initialized\n");
......
...@@ -2888,7 +2888,7 @@ static int dce_v11_0_early_init(void *handle) ...@@ -2888,7 +2888,7 @@ static int dce_v11_0_early_init(void *handle)
switch (adev->asic_type) { switch (adev->asic_type) {
case CHIP_CARRIZO: case CHIP_CARRIZO:
adev->mode_info.num_crtc = 4; adev->mode_info.num_crtc = 3;
adev->mode_info.num_hpd = 6; adev->mode_info.num_hpd = 6;
adev->mode_info.num_dig = 9; adev->mode_info.num_dig = 9;
break; break;
......
...@@ -2995,6 +2995,12 @@ static int kv_dpm_late_init(void *handle) ...@@ -2995,6 +2995,12 @@ static int kv_dpm_late_init(void *handle)
{ {
/* powerdown unused blocks for now */ /* powerdown unused blocks for now */
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
int ret;
/* init the sysfs and debugfs files late */
ret = amdgpu_pm_sysfs_init(adev);
if (ret)
return ret;
kv_dpm_powergate_acp(adev, true); kv_dpm_powergate_acp(adev, true);
kv_dpm_powergate_samu(adev, true); kv_dpm_powergate_samu(adev, true);
...@@ -3038,9 +3044,6 @@ static int kv_dpm_sw_init(void *handle) ...@@ -3038,9 +3044,6 @@ static int kv_dpm_sw_init(void *handle)
adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps; adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps;
if (amdgpu_dpm == 1) if (amdgpu_dpm == 1)
amdgpu_pm_print_power_states(adev); amdgpu_pm_print_power_states(adev);
ret = amdgpu_pm_sysfs_init(adev);
if (ret)
goto dpm_failed;
mutex_unlock(&adev->pm.mutex); mutex_unlock(&adev->pm.mutex);
DRM_INFO("amdgpu: dpm initialized\n"); DRM_INFO("amdgpu: dpm initialized\n");
......
...@@ -1005,6 +1005,9 @@ static void vi_pcie_gen3_enable(struct amdgpu_device *adev) ...@@ -1005,6 +1005,9 @@ static void vi_pcie_gen3_enable(struct amdgpu_device *adev)
u32 mask; u32 mask;
int ret; int ret;
if (pci_is_root_bus(adev->pdev->bus))
return;
if (amdgpu_pcie_gen2 == 0) if (amdgpu_pcie_gen2 == 0)
return; return;
......
...@@ -235,18 +235,12 @@ static ssize_t dpms_show(struct device *device, ...@@ -235,18 +235,12 @@ static ssize_t dpms_show(struct device *device,
char *buf) char *buf)
{ {
struct drm_connector *connector = to_drm_connector(device); struct drm_connector *connector = to_drm_connector(device);
struct drm_device *dev = connector->dev; int dpms;
uint64_t dpms_status;
int ret;
ret = drm_object_property_get_value(&connector->base, dpms = READ_ONCE(connector->dpms);
dev->mode_config.dpms_property,
&dpms_status);
if (ret)
return 0;
return snprintf(buf, PAGE_SIZE, "%s\n", return snprintf(buf, PAGE_SIZE, "%s\n",
drm_get_dpms_name((int)dpms_status)); drm_get_dpms_name(dpms));
} }
static ssize_t enabled_show(struct device *device, static ssize_t enabled_show(struct device *device,
......
...@@ -469,9 +469,13 @@ nouveau_display_create(struct drm_device *dev) ...@@ -469,9 +469,13 @@ nouveau_display_create(struct drm_device *dev)
if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) { if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
dev->mode_config.max_width = 4096; dev->mode_config.max_width = 4096;
dev->mode_config.max_height = 4096; dev->mode_config.max_height = 4096;
} else { } else
if (drm->device.info.family < NV_DEVICE_INFO_V0_FERMI) {
dev->mode_config.max_width = 8192; dev->mode_config.max_width = 8192;
dev->mode_config.max_height = 8192; dev->mode_config.max_height = 8192;
} else {
dev->mode_config.max_width = 16384;
dev->mode_config.max_height = 16384;
} }
dev->mode_config.preferred_depth = 24; dev->mode_config.preferred_depth = 24;
......
...@@ -178,8 +178,30 @@ nouveau_fbcon_sync(struct fb_info *info) ...@@ -178,8 +178,30 @@ nouveau_fbcon_sync(struct fb_info *info)
return 0; return 0;
} }
static int
nouveau_fbcon_open(struct fb_info *info, int user)
{
struct nouveau_fbdev *fbcon = info->par;
struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
int ret = pm_runtime_get_sync(drm->dev->dev);
if (ret < 0 && ret != -EACCES)
return ret;
return 0;
}
static int
nouveau_fbcon_release(struct fb_info *info, int user)
{
struct nouveau_fbdev *fbcon = info->par;
struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
pm_runtime_put(drm->dev->dev);
return 0;
}
static struct fb_ops nouveau_fbcon_ops = { static struct fb_ops nouveau_fbcon_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.fb_open = nouveau_fbcon_open,
.fb_release = nouveau_fbcon_release,
.fb_check_var = drm_fb_helper_check_var, .fb_check_var = drm_fb_helper_check_var,
.fb_set_par = drm_fb_helper_set_par, .fb_set_par = drm_fb_helper_set_par,
.fb_fillrect = nouveau_fbcon_fillrect, .fb_fillrect = nouveau_fbcon_fillrect,
...@@ -195,6 +217,8 @@ static struct fb_ops nouveau_fbcon_ops = { ...@@ -195,6 +217,8 @@ static struct fb_ops nouveau_fbcon_ops = {
static struct fb_ops nouveau_fbcon_sw_ops = { static struct fb_ops nouveau_fbcon_sw_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.fb_open = nouveau_fbcon_open,
.fb_release = nouveau_fbcon_release,
.fb_check_var = drm_fb_helper_check_var, .fb_check_var = drm_fb_helper_check_var,
.fb_set_par = drm_fb_helper_set_par, .fb_set_par = drm_fb_helper_set_par,
.fb_fillrect = drm_fb_helper_cfb_fillrect, .fb_fillrect = drm_fb_helper_cfb_fillrect,
......
...@@ -267,6 +267,12 @@ init_i2c(struct nvbios_init *init, int index) ...@@ -267,6 +267,12 @@ init_i2c(struct nvbios_init *init, int index)
index = NVKM_I2C_BUS_PRI; index = NVKM_I2C_BUS_PRI;
if (init->outp && init->outp->i2c_upper_default) if (init->outp && init->outp->i2c_upper_default)
index = NVKM_I2C_BUS_SEC; index = NVKM_I2C_BUS_SEC;
} else
if (index == 0x80) {
index = NVKM_I2C_BUS_PRI;
} else
if (index == 0x81) {
index = NVKM_I2C_BUS_SEC;
} }
bus = nvkm_i2c_bus_find(i2c, index); bus = nvkm_i2c_bus_find(i2c, index);
......
...@@ -8,7 +8,10 @@ struct nvbios_source { ...@@ -8,7 +8,10 @@ struct nvbios_source {
void *(*init)(struct nvkm_bios *, const char *); void *(*init)(struct nvkm_bios *, const char *);
void (*fini)(void *); void (*fini)(void *);
u32 (*read)(void *, u32 offset, u32 length, struct nvkm_bios *); u32 (*read)(void *, u32 offset, u32 length, struct nvkm_bios *);
u32 (*size)(void *);
bool rw; bool rw;
bool ignore_checksum;
bool no_pcir;
}; };
int nvbios_extend(struct nvkm_bios *, u32 length); int nvbios_extend(struct nvkm_bios *, u32 length);
......
...@@ -45,7 +45,7 @@ shadow_fetch(struct nvkm_bios *bios, struct shadow *mthd, u32 upto) ...@@ -45,7 +45,7 @@ shadow_fetch(struct nvkm_bios *bios, struct shadow *mthd, u32 upto)
u32 read = mthd->func->read(data, start, limit - start, bios); u32 read = mthd->func->read(data, start, limit - start, bios);
bios->size = start + read; bios->size = start + read;
} }
return bios->size >= limit; return bios->size >= upto;
} }
static int static int
...@@ -55,14 +55,22 @@ shadow_image(struct nvkm_bios *bios, int idx, u32 offset, struct shadow *mthd) ...@@ -55,14 +55,22 @@ shadow_image(struct nvkm_bios *bios, int idx, u32 offset, struct shadow *mthd)
struct nvbios_image image; struct nvbios_image image;
int score = 1; int score = 1;
if (!shadow_fetch(bios, mthd, offset + 0x1000)) { if (mthd->func->no_pcir) {
nvkm_debug(subdev, "%08x: header fetch failed\n", offset); image.base = 0;
return 0; image.type = 0;
} image.size = mthd->func->size(mthd->data);
image.last = 1;
} else {
if (!shadow_fetch(bios, mthd, offset + 0x1000)) {
nvkm_debug(subdev, "%08x: header fetch failed\n",
offset);
return 0;
}
if (!nvbios_image(bios, idx, &image)) { if (!nvbios_image(bios, idx, &image)) {
nvkm_debug(subdev, "image %d invalid\n", idx); nvkm_debug(subdev, "image %d invalid\n", idx);
return 0; return 0;
}
} }
nvkm_debug(subdev, "%08x: type %02x, %d bytes\n", nvkm_debug(subdev, "%08x: type %02x, %d bytes\n",
image.base, image.type, image.size); image.base, image.type, image.size);
...@@ -74,7 +82,8 @@ shadow_image(struct nvkm_bios *bios, int idx, u32 offset, struct shadow *mthd) ...@@ -74,7 +82,8 @@ shadow_image(struct nvkm_bios *bios, int idx, u32 offset, struct shadow *mthd)
switch (image.type) { switch (image.type) {
case 0x00: case 0x00:
if (nvbios_checksum(&bios->data[image.base], image.size)) { if (!mthd->func->ignore_checksum &&
nvbios_checksum(&bios->data[image.base], image.size)) {
nvkm_debug(subdev, "%08x: checksum failed\n", nvkm_debug(subdev, "%08x: checksum failed\n",
image.base); image.base);
if (mthd->func->rw) if (mthd->func->rw)
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
* *
*/ */
#include "priv.h" #include "priv.h"
#include <core/pci.h> #include <core/pci.h>
#if defined(__powerpc__) #if defined(__powerpc__)
...@@ -33,17 +34,26 @@ static u32 ...@@ -33,17 +34,26 @@ static u32
of_read(void *data, u32 offset, u32 length, struct nvkm_bios *bios) of_read(void *data, u32 offset, u32 length, struct nvkm_bios *bios)
{ {
struct priv *priv = data; struct priv *priv = data;
if (offset + length <= priv->size) { if (offset < priv->size) {
length = min_t(u32, length, priv->size - offset);
memcpy_fromio(bios->data + offset, priv->data + offset, length); memcpy_fromio(bios->data + offset, priv->data + offset, length);
return length; return length;
} }
return 0; return 0;
} }
static u32
of_size(void *data)
{
struct priv *priv = data;
return priv->size;
}
static void * static void *
of_init(struct nvkm_bios *bios, const char *name) of_init(struct nvkm_bios *bios, const char *name)
{ {
struct pci_dev *pdev = bios->subdev.device->func->pci(bios->subdev.device)->pdev; struct nvkm_device *device = bios->subdev.device;
struct pci_dev *pdev = device->func->pci(device)->pdev;
struct device_node *dn; struct device_node *dn;
struct priv *priv; struct priv *priv;
if (!(dn = pci_device_to_OF_node(pdev))) if (!(dn = pci_device_to_OF_node(pdev)))
...@@ -62,7 +72,10 @@ nvbios_of = { ...@@ -62,7 +72,10 @@ nvbios_of = {
.init = of_init, .init = of_init,
.fini = (void(*)(void *))kfree, .fini = (void(*)(void *))kfree,
.read = of_read, .read = of_read,
.size = of_size,
.rw = false, .rw = false,
.ignore_checksum = true,
.no_pcir = true,
}; };
#else #else
const struct nvbios_source const struct nvbios_source
......
...@@ -35,6 +35,8 @@ static const struct nvkm_device_agp_quirk ...@@ -35,6 +35,8 @@ static const struct nvkm_device_agp_quirk
nvkm_device_agp_quirks[] = { nvkm_device_agp_quirks[] = {
/* VIA Apollo PRO133x / GeForce FX 5600 Ultra - fdo#20341 */ /* VIA Apollo PRO133x / GeForce FX 5600 Ultra - fdo#20341 */
{ PCI_VENDOR_ID_VIA, 0x0691, PCI_VENDOR_ID_NVIDIA, 0x0311, 2 }, { PCI_VENDOR_ID_VIA, 0x0691, PCI_VENDOR_ID_NVIDIA, 0x0311, 2 },
/* SiS 761 does not support AGP cards, use PCI mode */
{ PCI_VENDOR_ID_SI, 0x0761, PCI_ANY_ID, PCI_ANY_ID, 0 },
{}, {},
}; };
...@@ -137,8 +139,10 @@ nvkm_agp_ctor(struct nvkm_pci *pci) ...@@ -137,8 +139,10 @@ nvkm_agp_ctor(struct nvkm_pci *pci)
while (quirk->hostbridge_vendor) { while (quirk->hostbridge_vendor) {
if (info.device->vendor == quirk->hostbridge_vendor && if (info.device->vendor == quirk->hostbridge_vendor &&
info.device->device == quirk->hostbridge_device && info.device->device == quirk->hostbridge_device &&
pci->pdev->vendor == quirk->chip_vendor && (quirk->chip_vendor == (u16)PCI_ANY_ID ||
pci->pdev->device == quirk->chip_device) { pci->pdev->vendor == quirk->chip_vendor) &&
(quirk->chip_device == (u16)PCI_ANY_ID ||
pci->pdev->device == quirk->chip_device)) {
nvkm_info(subdev, "forcing default agp mode to %dX, " nvkm_info(subdev, "forcing default agp mode to %dX, "
"use NvAGP=<mode> to override\n", "use NvAGP=<mode> to override\n",
quirk->mode); quirk->mode);
......
...@@ -242,6 +242,10 @@ static int qxl_crtc_page_flip(struct drm_crtc *crtc, ...@@ -242,6 +242,10 @@ static int qxl_crtc_page_flip(struct drm_crtc *crtc,
bo->is_primary = true; bo->is_primary = true;
ret = qxl_bo_reserve(bo, false); ret = qxl_bo_reserve(bo, false);
if (ret)
return ret;
ret = qxl_bo_pin(bo, bo->type, NULL);
qxl_bo_unreserve(bo);
if (ret) if (ret)
return ret; return ret;
...@@ -257,7 +261,11 @@ static int qxl_crtc_page_flip(struct drm_crtc *crtc, ...@@ -257,7 +261,11 @@ static int qxl_crtc_page_flip(struct drm_crtc *crtc,
} }
drm_vblank_put(dev, qcrtc->index); drm_vblank_put(dev, qcrtc->index);
qxl_bo_unreserve(bo); ret = qxl_bo_reserve(bo, false);
if (!ret) {
qxl_bo_unpin(bo);
qxl_bo_unreserve(bo);
}
return 0; return 0;
} }
......
...@@ -144,14 +144,17 @@ static void qxl_dirty_update(struct qxl_fbdev *qfbdev, ...@@ -144,14 +144,17 @@ static void qxl_dirty_update(struct qxl_fbdev *qfbdev,
spin_lock_irqsave(&qfbdev->dirty.lock, flags); spin_lock_irqsave(&qfbdev->dirty.lock, flags);
if (qfbdev->dirty.y1 < y) if ((qfbdev->dirty.y2 - qfbdev->dirty.y1) &&
y = qfbdev->dirty.y1; (qfbdev->dirty.x2 - qfbdev->dirty.x1)) {
if (qfbdev->dirty.y2 > y2) if (qfbdev->dirty.y1 < y)
y2 = qfbdev->dirty.y2; y = qfbdev->dirty.y1;
if (qfbdev->dirty.x1 < x) if (qfbdev->dirty.y2 > y2)
x = qfbdev->dirty.x1; y2 = qfbdev->dirty.y2;
if (qfbdev->dirty.x2 > x2) if (qfbdev->dirty.x1 < x)
x2 = qfbdev->dirty.x2; x = qfbdev->dirty.x1;
if (qfbdev->dirty.x2 > x2)
x2 = qfbdev->dirty.x2;
}
qfbdev->dirty.x1 = x; qfbdev->dirty.x1 = x;
qfbdev->dirty.x2 = x2; qfbdev->dirty.x2 = x2;
......
...@@ -307,7 +307,7 @@ int qxl_alloc_surface_release_reserved(struct qxl_device *qdev, ...@@ -307,7 +307,7 @@ int qxl_alloc_surface_release_reserved(struct qxl_device *qdev,
idr_ret = qxl_release_alloc(qdev, QXL_RELEASE_SURFACE_CMD, release); idr_ret = qxl_release_alloc(qdev, QXL_RELEASE_SURFACE_CMD, release);
if (idr_ret < 0) if (idr_ret < 0)
return idr_ret; return idr_ret;
bo = qxl_bo_ref(to_qxl_bo(entry->tv.bo)); bo = to_qxl_bo(entry->tv.bo);
(*release)->release_offset = create_rel->release_offset + 64; (*release)->release_offset = create_rel->release_offset + 64;
...@@ -316,8 +316,6 @@ int qxl_alloc_surface_release_reserved(struct qxl_device *qdev, ...@@ -316,8 +316,6 @@ int qxl_alloc_surface_release_reserved(struct qxl_device *qdev,
info = qxl_release_map(qdev, *release); info = qxl_release_map(qdev, *release);
info->id = idr_ret; info->id = idr_ret;
qxl_release_unmap(qdev, *release, info); qxl_release_unmap(qdev, *release, info);
qxl_bo_unref(&bo);
return 0; return 0;
} }
......
...@@ -1633,18 +1633,8 @@ int radeon_modeset_init(struct radeon_device *rdev) ...@@ -1633,18 +1633,8 @@ int radeon_modeset_init(struct radeon_device *rdev)
radeon_fbdev_init(rdev); radeon_fbdev_init(rdev);
drm_kms_helper_poll_init(rdev->ddev); drm_kms_helper_poll_init(rdev->ddev);
if (rdev->pm.dpm_enabled) { /* do pm late init */
/* do dpm late init */ ret = radeon_pm_late_init(rdev);
ret = radeon_pm_late_init(rdev);
if (ret) {
rdev->pm.dpm_enabled = false;
DRM_ERROR("radeon_pm_late_init failed, disabling dpm\n");
}
/* set the dpm state for PX since there won't be
* a modeset to call this.
*/
radeon_pm_compute_clocks(rdev);
}
return 0; return 0;
} }
......
...@@ -397,3 +397,19 @@ void radeon_fb_remove_connector(struct radeon_device *rdev, struct drm_connector ...@@ -397,3 +397,19 @@ void radeon_fb_remove_connector(struct radeon_device *rdev, struct drm_connector
{ {
drm_fb_helper_remove_one_connector(&rdev->mode_info.rfbdev->helper, connector); drm_fb_helper_remove_one_connector(&rdev->mode_info.rfbdev->helper, connector);
} }
void radeon_fbdev_restore_mode(struct radeon_device *rdev)
{
struct radeon_fbdev *rfbdev = rdev->mode_info.rfbdev;
struct drm_fb_helper *fb_helper;
int ret;
if (!rfbdev)
return;
fb_helper = &rfbdev->helper;
ret = drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper);
if (ret)
DRM_DEBUG("failed to restore crtc mode\n");
}
...@@ -598,7 +598,7 @@ static int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file ...@@ -598,7 +598,7 @@ static int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file
* Outdated mess for old drm with Xorg being in charge (void function now). * Outdated mess for old drm with Xorg being in charge (void function now).
*/ */
/** /**
* radeon_driver_firstopen_kms - drm callback for last close * radeon_driver_lastclose_kms - drm callback for last close
* *
* @dev: drm dev pointer * @dev: drm dev pointer
* *
...@@ -606,6 +606,9 @@ static int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file ...@@ -606,6 +606,9 @@ static int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file
*/ */
void radeon_driver_lastclose_kms(struct drm_device *dev) void radeon_driver_lastclose_kms(struct drm_device *dev)
{ {
struct radeon_device *rdev = dev->dev_private;
radeon_fbdev_restore_mode(rdev);
vga_switcheroo_process_delayed_switch(); vga_switcheroo_process_delayed_switch();
} }
......
...@@ -980,6 +980,7 @@ int radeon_fbdev_init(struct radeon_device *rdev); ...@@ -980,6 +980,7 @@ int radeon_fbdev_init(struct radeon_device *rdev);
void radeon_fbdev_fini(struct radeon_device *rdev); void radeon_fbdev_fini(struct radeon_device *rdev);
void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state); void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state);
bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj); bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj);
void radeon_fbdev_restore_mode(struct radeon_device *rdev);
void radeon_fb_output_poll_changed(struct radeon_device *rdev); void radeon_fb_output_poll_changed(struct radeon_device *rdev);
......
...@@ -1326,14 +1326,6 @@ static int radeon_pm_init_old(struct radeon_device *rdev) ...@@ -1326,14 +1326,6 @@ static int radeon_pm_init_old(struct radeon_device *rdev)
INIT_DELAYED_WORK(&rdev->pm.dynpm_idle_work, radeon_dynpm_idle_work_handler); INIT_DELAYED_WORK(&rdev->pm.dynpm_idle_work, radeon_dynpm_idle_work_handler);
if (rdev->pm.num_power_states > 1) { if (rdev->pm.num_power_states > 1) {
/* where's the best place to put these? */
ret = device_create_file(rdev->dev, &dev_attr_power_profile);
if (ret)
DRM_ERROR("failed to create device file for power profile\n");
ret = device_create_file(rdev->dev, &dev_attr_power_method);
if (ret)
DRM_ERROR("failed to create device file for power method\n");
if (radeon_debugfs_pm_init(rdev)) { if (radeon_debugfs_pm_init(rdev)) {
DRM_ERROR("Failed to register debugfs file for PM!\n"); DRM_ERROR("Failed to register debugfs file for PM!\n");
} }
...@@ -1391,20 +1383,6 @@ static int radeon_pm_init_dpm(struct radeon_device *rdev) ...@@ -1391,20 +1383,6 @@ static int radeon_pm_init_dpm(struct radeon_device *rdev)
goto dpm_failed; goto dpm_failed;
rdev->pm.dpm_enabled = true; rdev->pm.dpm_enabled = true;
ret = device_create_file(rdev->dev, &dev_attr_power_dpm_state);
if (ret)
DRM_ERROR("failed to create device file for dpm state\n");
ret = device_create_file(rdev->dev, &dev_attr_power_dpm_force_performance_level);
if (ret)
DRM_ERROR("failed to create device file for dpm state\n");
/* XXX: these are noops for dpm but are here for backwards compat */
ret = device_create_file(rdev->dev, &dev_attr_power_profile);
if (ret)
DRM_ERROR("failed to create device file for power profile\n");
ret = device_create_file(rdev->dev, &dev_attr_power_method);
if (ret)
DRM_ERROR("failed to create device file for power method\n");
if (radeon_debugfs_pm_init(rdev)) { if (radeon_debugfs_pm_init(rdev)) {
DRM_ERROR("Failed to register debugfs file for dpm!\n"); DRM_ERROR("Failed to register debugfs file for dpm!\n");
} }
...@@ -1545,9 +1523,44 @@ int radeon_pm_late_init(struct radeon_device *rdev) ...@@ -1545,9 +1523,44 @@ int radeon_pm_late_init(struct radeon_device *rdev)
int ret = 0; int ret = 0;
if (rdev->pm.pm_method == PM_METHOD_DPM) { if (rdev->pm.pm_method == PM_METHOD_DPM) {
mutex_lock(&rdev->pm.mutex); if (rdev->pm.dpm_enabled) {
ret = radeon_dpm_late_enable(rdev); ret = device_create_file(rdev->dev, &dev_attr_power_dpm_state);
mutex_unlock(&rdev->pm.mutex); if (ret)
DRM_ERROR("failed to create device file for dpm state\n");
ret = device_create_file(rdev->dev, &dev_attr_power_dpm_force_performance_level);
if (ret)
DRM_ERROR("failed to create device file for dpm state\n");
/* XXX: these are noops for dpm but are here for backwards compat */
ret = device_create_file(rdev->dev, &dev_attr_power_profile);
if (ret)
DRM_ERROR("failed to create device file for power profile\n");
ret = device_create_file(rdev->dev, &dev_attr_power_method);
if (ret)
DRM_ERROR("failed to create device file for power method\n");
mutex_lock(&rdev->pm.mutex);
ret = radeon_dpm_late_enable(rdev);
mutex_unlock(&rdev->pm.mutex);
if (ret) {
rdev->pm.dpm_enabled = false;
DRM_ERROR("radeon_pm_late_init failed, disabling dpm\n");
} else {
/* set the dpm state for PX since there won't be
* a modeset to call this.
*/
radeon_pm_compute_clocks(rdev);
}
}
} else {
if (rdev->pm.num_power_states > 1) {
/* where's the best place to put these? */
ret = device_create_file(rdev->dev, &dev_attr_power_profile);
if (ret)
DRM_ERROR("failed to create device file for power profile\n");
ret = device_create_file(rdev->dev, &dev_attr_power_method);
if (ret)
DRM_ERROR("failed to create device file for power method\n");
}
} }
return ret; return ret;
} }
......
...@@ -2928,6 +2928,7 @@ static struct si_dpm_quirk si_dpm_quirk_list[] = { ...@@ -2928,6 +2928,7 @@ static struct si_dpm_quirk si_dpm_quirk_list[] = {
{ PCI_VENDOR_ID_ATI, 0x6811, 0x174b, 0xe271, 0, 120000 }, { PCI_VENDOR_ID_ATI, 0x6811, 0x174b, 0xe271, 0, 120000 },
{ PCI_VENDOR_ID_ATI, 0x6810, 0x174b, 0xe271, 85000, 90000 }, { PCI_VENDOR_ID_ATI, 0x6810, 0x174b, 0xe271, 85000, 90000 },
{ PCI_VENDOR_ID_ATI, 0x6811, 0x1762, 0x2015, 0, 120000 }, { PCI_VENDOR_ID_ATI, 0x6811, 0x1762, 0x2015, 0, 120000 },
{ PCI_VENDOR_ID_ATI, 0x6811, 0x1043, 0x2015, 0, 120000 },
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 },
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment