Skip to content

Commit

Permalink
Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Linus Torvalds committed Oct 13, 2015
2 parents 25cb62b + 7b98040 commit 06d1ee3
Show file tree
Hide file tree
Showing 29 changed files with 219 additions and 94 deletions.
6 changes: 3 additions & 3 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)

/* get chunks */
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,
sizeof(uint64_t)*cs->in.num_chunks)) {
ret = -EFAULT;
Expand All @@ -197,7 +197,7 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
struct drm_amdgpu_cs_chunk user_chunk;
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,
sizeof(struct drm_amdgpu_cs_chunk))) {
ret = -EFAULT;
Expand All @@ -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;

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].kdata = drm_malloc_ab(size, sizeof(uint32_t));
Expand Down
10 changes: 5 additions & 5 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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},
#endif
/* topaz */
{0x1002, 0x6900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
{0x1002, 0x6901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
{0x1002, 0x6902, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
{0x1002, 0x6903, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
{0x1002, 0x6907, 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|AMD_EXP_HW_SUPPORT},
{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|AMD_EXP_HW_SUPPORT},
{0x1002, 0x6907, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT},
/* 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},
Expand Down
16 changes: 16 additions & 0 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,3 +402,19 @@ bool amdgpu_fbdev_robj_is_fb(struct amdgpu_device *adev, struct amdgpu_bo *robj)
return true;
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");
}
5 changes: 4 additions & 1 deletion drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
Original file line number Diff line number Diff line change
Expand Up @@ -485,14 +485,17 @@ 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).
*/
/**
* amdgpu_driver_firstopen_kms - drm callback for last close
* amdgpu_driver_lastclose_kms - drm callback for last close
*
* @dev: drm dev pointer
*
* Switch vga switcheroo state after last close (all asics).
*/
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();
}

Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,7 @@ void amdgpu_fbdev_fini(struct amdgpu_device *adev);
void amdgpu_fbdev_set_suspend(struct amdgpu_device *adev, int state);
int amdgpu_fbdev_total_size(struct amdgpu_device *adev);
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);

Expand Down
4 changes: 3 additions & 1 deletion drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -455,8 +455,10 @@ int amdgpu_vm_update_page_directory(struct amdgpu_device *adev,
return -ENOMEM;

r = amdgpu_ib_get(ring, NULL, ndw * 4, ib);
if (r)
if (r) {
kfree(ib);
return r;
}
ib->length_dw = 0;

/* walk over the address space and update the page directory */
Expand Down
8 changes: 5 additions & 3 deletions drivers/gpu/drm/amd/amdgpu/ci_dpm.c
Original file line number Diff line number Diff line change
Expand Up @@ -6185,6 +6185,11 @@ static int ci_dpm_late_init(void *handle)
if (!amdgpu_dpm)
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);
if (ret)
return ret;
Expand Down Expand Up @@ -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;
if (amdgpu_dpm == 1)
amdgpu_pm_print_power_states(adev);
ret = amdgpu_pm_sysfs_init(adev);
if (ret)
goto dpm_failed;
mutex_unlock(&adev->pm.mutex);
DRM_INFO("amdgpu: dpm initialized\n");

Expand Down
3 changes: 3 additions & 0 deletions drivers/gpu/drm/amd/amdgpu/cik.c
Original file line number Diff line number Diff line change
Expand Up @@ -1567,6 +1567,9 @@ static void cik_pcie_gen3_enable(struct amdgpu_device *adev)
int ret, i;
u16 tmp16;

if (pci_is_root_bus(adev->pdev->bus))
return;

if (amdgpu_pcie_gen2 == 0)
return;

Expand Down
10 changes: 6 additions & 4 deletions drivers/gpu/drm/amd/amdgpu/cz_dpm.c
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,12 @@ static int cz_dpm_late_init(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle;

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 */
cz_dpm_powergate_uvd(adev, true);
cz_dpm_powergate_vce(adev, true);
Expand Down Expand Up @@ -632,10 +638,6 @@ static int cz_dpm_sw_init(void *handle)
if (amdgpu_dpm == 1)
amdgpu_pm_print_power_states(adev);

ret = amdgpu_pm_sysfs_init(adev);
if (ret)
goto dpm_init_failed;

mutex_unlock(&adev->pm.mutex);
DRM_INFO("amdgpu: dpm initialized\n");

Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
Original file line number Diff line number Diff line change
Expand Up @@ -2888,7 +2888,7 @@ static int dce_v11_0_early_init(void *handle)

switch (adev->asic_type) {
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_dig = 9;
break;
Expand Down
9 changes: 6 additions & 3 deletions drivers/gpu/drm/amd/amdgpu/kv_dpm.c
Original file line number Diff line number Diff line change
Expand Up @@ -2995,6 +2995,12 @@ static int kv_dpm_late_init(void *handle)
{
/* powerdown unused blocks for now */
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_samu(adev, true);
Expand Down Expand Up @@ -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;
if (amdgpu_dpm == 1)
amdgpu_pm_print_power_states(adev);
ret = amdgpu_pm_sysfs_init(adev);
if (ret)
goto dpm_failed;
mutex_unlock(&adev->pm.mutex);
DRM_INFO("amdgpu: dpm initialized\n");

Expand Down
3 changes: 3 additions & 0 deletions drivers/gpu/drm/amd/amdgpu/vi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1005,6 +1005,9 @@ static void vi_pcie_gen3_enable(struct amdgpu_device *adev)
u32 mask;
int ret;

if (pci_is_root_bus(adev->pdev->bus))
return;

if (amdgpu_pcie_gen2 == 0)
return;

Expand Down
12 changes: 3 additions & 9 deletions drivers/gpu/drm/drm_sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -235,18 +235,12 @@ static ssize_t dpms_show(struct device *device,
char *buf)
{
struct drm_connector *connector = to_drm_connector(device);
struct drm_device *dev = connector->dev;
uint64_t dpms_status;
int ret;
int dpms;

ret = drm_object_property_get_value(&connector->base,
dev->mode_config.dpms_property,
&dpms_status);
if (ret)
return 0;
dpms = READ_ONCE(connector->dpms);

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,
Expand Down
6 changes: 5 additions & 1 deletion drivers/gpu/drm/nouveau/nouveau_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -469,9 +469,13 @@ nouveau_display_create(struct drm_device *dev)
if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
dev->mode_config.max_width = 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_height = 8192;
} else {
dev->mode_config.max_width = 16384;
dev->mode_config.max_height = 16384;
}

dev->mode_config.preferred_depth = 24;
Expand Down
24 changes: 24 additions & 0 deletions drivers/gpu/drm/nouveau/nouveau_fbcon.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,30 @@ nouveau_fbcon_sync(struct fb_info *info)
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 = {
.owner = THIS_MODULE,
.fb_open = nouveau_fbcon_open,
.fb_release = nouveau_fbcon_release,
.fb_check_var = drm_fb_helper_check_var,
.fb_set_par = drm_fb_helper_set_par,
.fb_fillrect = nouveau_fbcon_fillrect,
Expand All @@ -195,6 +217,8 @@ static struct fb_ops nouveau_fbcon_ops = {

static struct fb_ops nouveau_fbcon_sw_ops = {
.owner = THIS_MODULE,
.fb_open = nouveau_fbcon_open,
.fb_release = nouveau_fbcon_release,
.fb_check_var = drm_fb_helper_check_var,
.fb_set_par = drm_fb_helper_set_par,
.fb_fillrect = drm_fb_helper_cfb_fillrect,
Expand Down
6 changes: 6 additions & 0 deletions drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,12 @@ init_i2c(struct nvbios_init *init, int index)
index = NVKM_I2C_BUS_PRI;
if (init->outp && init->outp->i2c_upper_default)
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);
Expand Down
3 changes: 3 additions & 0 deletions drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ struct nvbios_source {
void *(*init)(struct nvkm_bios *, const char *);
void (*fini)(void *);
u32 (*read)(void *, u32 offset, u32 length, struct nvkm_bios *);
u32 (*size)(void *);
bool rw;
bool ignore_checksum;
bool no_pcir;
};

int nvbios_extend(struct nvkm_bios *, u32 length);
Expand Down
27 changes: 18 additions & 9 deletions drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
bios->size = start + read;
}
return bios->size >= limit;
return bios->size >= upto;
}

static int
Expand All @@ -55,14 +55,22 @@ shadow_image(struct nvkm_bios *bios, int idx, u32 offset, struct shadow *mthd)
struct nvbios_image image;
int score = 1;

if (!shadow_fetch(bios, mthd, offset + 0x1000)) {
nvkm_debug(subdev, "%08x: header fetch failed\n", offset);
return 0;
}
if (mthd->func->no_pcir) {
image.base = 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)) {
nvkm_debug(subdev, "image %d invalid\n", idx);
return 0;
if (!nvbios_image(bios, idx, &image)) {
nvkm_debug(subdev, "image %d invalid\n", idx);
return 0;
}
}
nvkm_debug(subdev, "%08x: type %02x, %d bytes\n",
image.base, image.type, image.size);
Expand All @@ -74,7 +82,8 @@ shadow_image(struct nvkm_bios *bios, int idx, u32 offset, struct shadow *mthd)

switch (image.type) {
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",
image.base);
if (mthd->func->rw)
Expand Down
17 changes: 15 additions & 2 deletions drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
*
*/
#include "priv.h"

#include <core/pci.h>

#if defined(__powerpc__)
Expand All @@ -33,17 +34,26 @@ static u32
of_read(void *data, u32 offset, u32 length, struct nvkm_bios *bios)
{
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);
return length;
}
return 0;
}

static u32
of_size(void *data)
{
struct priv *priv = data;
return priv->size;
}

static void *
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 priv *priv;
if (!(dn = pci_device_to_OF_node(pdev)))
Expand All @@ -62,7 +72,10 @@ nvbios_of = {
.init = of_init,
.fini = (void(*)(void *))kfree,
.read = of_read,
.size = of_size,
.rw = false,
.ignore_checksum = true,
.no_pcir = true,
};
#else
const struct nvbios_source
Expand Down
Loading

0 comments on commit 06d1ee3

Please sign in to comment.