Commit d0333038 authored by Dave Airlie's avatar Dave Airlie

Merge remote branch 'nouveau/for-airlied' of /ssd/git/drm-nouveau-next into drm-core-next

* 'nouveau/for-airlied' of /ssd/git/drm-nouveau-next:
  drm/nouveau: fix earlier mistake when fixing merge conflict
  drm/nvc0: fix thinko in instmem suspend/resume
  drm/nouveau: Workaround missing GPIO tables on an Apple iMac G4 NV18.
  drm/nouveau: Add TV-out quirk for an MSI nForce2 IGP.
  drm/nv50-nvc0: ramht_size is meant to be in bytes, not entries
  drm/nouveau: punt some more log messages to debug level
  drm/nouveau: remove warning about unknown tmds table revisions
  drm/nouveau: check for error when allocating/mapping dummy page
  drm/nouveau: fix race condition when under memory pressure
  drm/nv50: fix minor thinko from nvc0 changes
  drm/nouveau: Don't try DDC on the dummy I2C channel.
parents 0537398b 625db6b7
...@@ -2166,7 +2166,7 @@ peek_fb(struct drm_device *dev, struct io_mapping *fb, ...@@ -2166,7 +2166,7 @@ peek_fb(struct drm_device *dev, struct io_mapping *fb,
uint32_t val = 0; uint32_t val = 0;
if (off < pci_resource_len(dev->pdev, 1)) { if (off < pci_resource_len(dev->pdev, 1)) {
uint32_t __iomem *p = uint8_t __iomem *p =
io_mapping_map_atomic_wc(fb, off & PAGE_MASK, KM_USER0); io_mapping_map_atomic_wc(fb, off & PAGE_MASK, KM_USER0);
val = ioread32(p + (off & ~PAGE_MASK)); val = ioread32(p + (off & ~PAGE_MASK));
...@@ -2182,7 +2182,7 @@ poke_fb(struct drm_device *dev, struct io_mapping *fb, ...@@ -2182,7 +2182,7 @@ poke_fb(struct drm_device *dev, struct io_mapping *fb,
uint32_t off, uint32_t val) uint32_t off, uint32_t val)
{ {
if (off < pci_resource_len(dev->pdev, 1)) { if (off < pci_resource_len(dev->pdev, 1)) {
uint32_t __iomem *p = uint8_t __iomem *p =
io_mapping_map_atomic_wc(fb, off & PAGE_MASK, KM_USER0); io_mapping_map_atomic_wc(fb, off & PAGE_MASK, KM_USER0);
iowrite32(val, p + (off & ~PAGE_MASK)); iowrite32(val, p + (off & ~PAGE_MASK));
...@@ -4587,7 +4587,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, ...@@ -4587,7 +4587,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
return 1; return 1;
} }
NV_TRACE(dev, "0x%04X: parsing output script 0\n", script); NV_DEBUG_KMS(dev, "0x%04X: parsing output script 0\n", script);
nouveau_bios_run_init_table(dev, script, dcbent); nouveau_bios_run_init_table(dev, script, dcbent);
} else } else
if (pxclk == -1) { if (pxclk == -1) {
...@@ -4597,7 +4597,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, ...@@ -4597,7 +4597,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
return 1; return 1;
} }
NV_TRACE(dev, "0x%04X: parsing output script 1\n", script); NV_DEBUG_KMS(dev, "0x%04X: parsing output script 1\n", script);
nouveau_bios_run_init_table(dev, script, dcbent); nouveau_bios_run_init_table(dev, script, dcbent);
} else } else
if (pxclk == -2) { if (pxclk == -2) {
...@@ -4610,7 +4610,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, ...@@ -4610,7 +4610,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
return 1; return 1;
} }
NV_TRACE(dev, "0x%04X: parsing output script 2\n", script); NV_DEBUG_KMS(dev, "0x%04X: parsing output script 2\n", script);
nouveau_bios_run_init_table(dev, script, dcbent); nouveau_bios_run_init_table(dev, script, dcbent);
} else } else
if (pxclk > 0) { if (pxclk > 0) {
...@@ -4622,7 +4622,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, ...@@ -4622,7 +4622,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
return 1; return 1;
} }
NV_TRACE(dev, "0x%04X: parsing clock script 0\n", script); NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 0\n", script);
nouveau_bios_run_init_table(dev, script, dcbent); nouveau_bios_run_init_table(dev, script, dcbent);
} else } else
if (pxclk < 0) { if (pxclk < 0) {
...@@ -4634,7 +4634,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, ...@@ -4634,7 +4634,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
return 1; return 1;
} }
NV_TRACE(dev, "0x%04X: parsing clock script 1\n", script); NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 1\n", script);
nouveau_bios_run_init_table(dev, script, dcbent); nouveau_bios_run_init_table(dev, script, dcbent);
} }
...@@ -5357,19 +5357,17 @@ static int parse_bit_tmds_tbl_entry(struct drm_device *dev, struct nvbios *bios, ...@@ -5357,19 +5357,17 @@ static int parse_bit_tmds_tbl_entry(struct drm_device *dev, struct nvbios *bios,
} }
tmdstableptr = ROM16(bios->data[bitentry->offset]); tmdstableptr = ROM16(bios->data[bitentry->offset]);
if (!tmdstableptr) {
if (tmdstableptr == 0x0) {
NV_ERROR(dev, "Pointer to TMDS table invalid\n"); NV_ERROR(dev, "Pointer to TMDS table invalid\n");
return -EINVAL; return -EINVAL;
} }
NV_INFO(dev, "TMDS table version %d.%d\n",
bios->data[tmdstableptr] >> 4, bios->data[tmdstableptr] & 0xf);
/* nv50+ has v2.0, but we don't parse it atm */ /* nv50+ has v2.0, but we don't parse it atm */
if (bios->data[tmdstableptr] != 0x11) { if (bios->data[tmdstableptr] != 0x11)
NV_WARN(dev,
"TMDS table revision %d.%d not currently supported\n",
bios->data[tmdstableptr] >> 4, bios->data[tmdstableptr] & 0xf);
return -ENOSYS; return -ENOSYS;
}
/* /*
* These two scripts are odd: they don't seem to get run even when * These two scripts are odd: they don't seem to get run even when
...@@ -5809,6 +5807,22 @@ parse_dcb_gpio_table(struct nvbios *bios) ...@@ -5809,6 +5807,22 @@ parse_dcb_gpio_table(struct nvbios *bios)
gpio->line = tvdac_gpio[1] >> 4; gpio->line = tvdac_gpio[1] >> 4;
gpio->invert = tvdac_gpio[0] & 2; gpio->invert = tvdac_gpio[0] & 2;
} }
} else {
/*
* No systematic way to store GPIO info on pre-v2.2
* DCBs, try to match the PCI device IDs.
*/
/* Apple iMac G4 NV18 */
if (dev->pdev->device == 0x0189 &&
dev->pdev->subsystem_vendor == 0x10de &&
dev->pdev->subsystem_device == 0x0010) {
struct dcb_gpio_entry *gpio = new_gpio_entry(bios);
gpio->tag = DCB_GPIO_TVDAC0;
gpio->line = 4;
}
} }
if (!gpio_table_ptr) if (!gpio_table_ptr)
......
...@@ -36,6 +36,21 @@ ...@@ -36,6 +36,21 @@
#include <linux/log2.h> #include <linux/log2.h>
#include <linux/slab.h> #include <linux/slab.h>
int
nouveau_bo_sync_gpu(struct nouveau_bo *nvbo, struct nouveau_channel *chan)
{
struct nouveau_fence *prev_fence = nvbo->bo.sync_obj;
int ret;
if (!prev_fence || nouveau_fence_channel(prev_fence) == chan)
return 0;
spin_lock(&nvbo->bo.lock);
ret = ttm_bo_wait(&nvbo->bo, false, false, false);
spin_unlock(&nvbo->bo.lock);
return ret;
}
static void static void
nouveau_bo_del_ttm(struct ttm_buffer_object *bo) nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
{ {
......
...@@ -104,7 +104,7 @@ nouveau_connector_ddc_detect(struct drm_connector *connector, ...@@ -104,7 +104,7 @@ nouveau_connector_ddc_detect(struct drm_connector *connector,
int i; int i;
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
struct nouveau_i2c_chan *i2c; struct nouveau_i2c_chan *i2c = NULL;
struct nouveau_encoder *nv_encoder; struct nouveau_encoder *nv_encoder;
struct drm_mode_object *obj; struct drm_mode_object *obj;
int id; int id;
...@@ -117,7 +117,9 @@ nouveau_connector_ddc_detect(struct drm_connector *connector, ...@@ -117,7 +117,9 @@ nouveau_connector_ddc_detect(struct drm_connector *connector,
if (!obj) if (!obj)
continue; continue;
nv_encoder = nouveau_encoder(obj_to_encoder(obj)); nv_encoder = nouveau_encoder(obj_to_encoder(obj));
i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
if (nv_encoder->dcb->i2c_index < 0xf)
i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
if (i2c && nouveau_probe_i2c_addr(i2c, 0x50)) { if (i2c && nouveau_probe_i2c_addr(i2c, 0x50)) {
*pnv_encoder = nv_encoder; *pnv_encoder = nv_encoder;
......
...@@ -1165,6 +1165,7 @@ extern u16 nouveau_bo_rd16(struct nouveau_bo *nvbo, unsigned index); ...@@ -1165,6 +1165,7 @@ extern u16 nouveau_bo_rd16(struct nouveau_bo *nvbo, unsigned index);
extern void nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val); extern void nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val);
extern u32 nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index); extern u32 nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index);
extern void nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val); extern void nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val);
extern int nouveau_bo_sync_gpu(struct nouveau_bo *, struct nouveau_channel *);
/* nouveau_fence.c */ /* nouveau_fence.c */
struct nouveau_fence; struct nouveau_fence;
......
...@@ -361,16 +361,11 @@ validate_list(struct nouveau_channel *chan, struct list_head *list, ...@@ -361,16 +361,11 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
list_for_each_entry(nvbo, list, entry) { list_for_each_entry(nvbo, list, entry) {
struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index]; struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index];
struct nouveau_fence *prev_fence = nvbo->bo.sync_obj;
if (prev_fence && nouveau_fence_channel(prev_fence) != chan) { ret = nouveau_bo_sync_gpu(nvbo, chan);
spin_lock(&nvbo->bo.lock); if (unlikely(ret)) {
ret = ttm_bo_wait(&nvbo->bo, false, false, false); NV_ERROR(dev, "fail pre-validate sync\n");
spin_unlock(&nvbo->bo.lock); return ret;
if (unlikely(ret)) {
NV_ERROR(dev, "fail wait other chan\n");
return ret;
}
} }
ret = nouveau_gem_set_domain(nvbo->gem, b->read_domains, ret = nouveau_gem_set_domain(nvbo->gem, b->read_domains,
...@@ -381,7 +376,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list, ...@@ -381,7 +376,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
return ret; return ret;
} }
nvbo->channel = chan; nvbo->channel = (b->read_domains & (1 << 31)) ? NULL : chan;
ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement, ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement,
false, false, false); false, false, false);
nvbo->channel = NULL; nvbo->channel = NULL;
...@@ -390,6 +385,12 @@ validate_list(struct nouveau_channel *chan, struct list_head *list, ...@@ -390,6 +385,12 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
return ret; return ret;
} }
ret = nouveau_bo_sync_gpu(nvbo, chan);
if (unlikely(ret)) {
NV_ERROR(dev, "fail post-validate sync\n");
return ret;
}
if (nvbo->bo.offset == b->presumed.offset && if (nvbo->bo.offset == b->presumed.offset &&
((nvbo->bo.mem.mem_type == TTM_PL_VRAM && ((nvbo->bo.mem.mem_type == TTM_PL_VRAM &&
b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) || b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) ||
...@@ -615,6 +616,21 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, ...@@ -615,6 +616,21 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
/* Mark push buffers as being used on PFIFO, the validation code
* will then make sure that if the pushbuf bo moves, that they
* happen on the kernel channel, which will in turn cause a sync
* to happen before we try and submit the push buffer.
*/
for (i = 0; i < req->nr_push; i++) {
if (push[i].bo_index >= req->nr_buffers) {
NV_ERROR(dev, "push %d buffer not in list\n", i);
ret = -EINVAL;
goto out;
}
bo[push[i].bo_index].read_domains |= (1 << 31);
}
/* Validate buffer list */ /* Validate buffer list */
ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo, req->buffers, ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo, req->buffers,
req->nr_buffers, &op, &do_reloc); req->nr_buffers, &op, &do_reloc);
......
...@@ -163,7 +163,7 @@ nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) ...@@ -163,7 +163,7 @@ nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index)
if (entry->chan) if (entry->chan)
return -EEXIST; return -EEXIST;
if (dev_priv->card_type == NV_C0 && entry->read >= NV50_I2C_PORTS) { if (dev_priv->card_type >= NV_50 && entry->read >= NV50_I2C_PORTS) {
NV_ERROR(dev, "unknown i2c port %d\n", entry->read); NV_ERROR(dev, "unknown i2c port %d\n", entry->read);
return -EINVAL; return -EINVAL;
} }
......
...@@ -214,6 +214,7 @@ int ...@@ -214,6 +214,7 @@ int
nouveau_sgdma_init(struct drm_device *dev) nouveau_sgdma_init(struct drm_device *dev)
{ {
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
struct pci_dev *pdev = dev->pdev;
struct nouveau_gpuobj *gpuobj = NULL; struct nouveau_gpuobj *gpuobj = NULL;
uint32_t aper_size, obj_size; uint32_t aper_size, obj_size;
int i, ret; int i, ret;
...@@ -239,10 +240,19 @@ nouveau_sgdma_init(struct drm_device *dev) ...@@ -239,10 +240,19 @@ nouveau_sgdma_init(struct drm_device *dev)
dev_priv->gart_info.sg_dummy_page = dev_priv->gart_info.sg_dummy_page =
alloc_page(GFP_KERNEL|__GFP_DMA32); alloc_page(GFP_KERNEL|__GFP_DMA32);
if (!dev_priv->gart_info.sg_dummy_page) {
nouveau_gpuobj_del(dev, &gpuobj);
return -ENOMEM;
}
set_bit(PG_locked, &dev_priv->gart_info.sg_dummy_page->flags); set_bit(PG_locked, &dev_priv->gart_info.sg_dummy_page->flags);
dev_priv->gart_info.sg_dummy_bus = dev_priv->gart_info.sg_dummy_bus =
pci_map_page(dev->pdev, dev_priv->gart_info.sg_dummy_page, 0, pci_map_page(pdev, dev_priv->gart_info.sg_dummy_page, 0,
PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
if (pci_dma_mapping_error(pdev, dev_priv->gart_info.sg_dummy_bus)) {
nouveau_gpuobj_del(dev, &gpuobj);
return -EFAULT;
}
if (dev_priv->card_type < NV_50) { if (dev_priv->card_type < NV_50) {
/* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and /* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and
......
...@@ -129,6 +129,14 @@ get_tv_detect_quirks(struct drm_device *dev, uint32_t *pin_mask) ...@@ -129,6 +129,14 @@ get_tv_detect_quirks(struct drm_device *dev, uint32_t *pin_mask)
return false; return false;
} }
/* MSI nForce2 IGP */
if (dev->pdev->device == 0x01f0 &&
dev->pdev->subsystem_vendor == 0x1462 &&
dev->pdev->subsystem_device == 0x5710) {
*pin_mask = 0xc;
return false;
}
return true; return true;
} }
......
...@@ -278,7 +278,7 @@ nv50_instmem_init(struct drm_device *dev) ...@@ -278,7 +278,7 @@ nv50_instmem_init(struct drm_device *dev)
/*XXX: incorrect, but needed to make hash func "work" */ /*XXX: incorrect, but needed to make hash func "work" */
dev_priv->ramht_offset = 0x10000; dev_priv->ramht_offset = 0x10000;
dev_priv->ramht_bits = 9; dev_priv->ramht_bits = 9;
dev_priv->ramht_size = (1 << dev_priv->ramht_bits); dev_priv->ramht_size = (1 << dev_priv->ramht_bits) * 8;
return 0; return 0;
} }
......
...@@ -142,14 +142,16 @@ int ...@@ -142,14 +142,16 @@ int
nvc0_instmem_suspend(struct drm_device *dev) nvc0_instmem_suspend(struct drm_device *dev)
{ {
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
u32 *buf;
int i; int i;
dev_priv->susres.ramin_copy = vmalloc(65536); dev_priv->susres.ramin_copy = vmalloc(65536);
if (!dev_priv->susres.ramin_copy) if (!dev_priv->susres.ramin_copy)
return -ENOMEM; return -ENOMEM;
buf = dev_priv->susres.ramin_copy;
for (i = 0x700000; i < 0x710000; i += 4) for (i = 0; i < 65536; i += 4)
dev_priv->susres.ramin_copy[i/4] = nv_rd32(dev, i); buf[i/4] = nv_rd32(dev, NV04_PRAMIN + i);
return 0; return 0;
} }
...@@ -157,14 +159,15 @@ void ...@@ -157,14 +159,15 @@ void
nvc0_instmem_resume(struct drm_device *dev) nvc0_instmem_resume(struct drm_device *dev)
{ {
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
u32 *buf = dev_priv->susres.ramin_copy;
u64 chan; u64 chan;
int i; int i;
chan = dev_priv->vram_size - dev_priv->ramin_rsvd_vram; chan = dev_priv->vram_size - dev_priv->ramin_rsvd_vram;
nv_wr32(dev, 0x001700, chan >> 16); nv_wr32(dev, 0x001700, chan >> 16);
for (i = 0x700000; i < 0x710000; i += 4) for (i = 0; i < 65536; i += 4)
nv_wr32(dev, i, dev_priv->susres.ramin_copy[i/4]); nv_wr32(dev, NV04_PRAMIN + i, buf[i/4]);
vfree(dev_priv->susres.ramin_copy); vfree(dev_priv->susres.ramin_copy);
dev_priv->susres.ramin_copy = NULL; dev_priv->susres.ramin_copy = NULL;
...@@ -221,7 +224,7 @@ nvc0_instmem_init(struct drm_device *dev) ...@@ -221,7 +224,7 @@ nvc0_instmem_init(struct drm_device *dev)
/*XXX: incorrect, but needed to make hash func "work" */ /*XXX: incorrect, but needed to make hash func "work" */
dev_priv->ramht_offset = 0x10000; dev_priv->ramht_offset = 0x10000;
dev_priv->ramht_bits = 9; dev_priv->ramht_bits = 9;
dev_priv->ramht_size = (1 << dev_priv->ramht_bits); dev_priv->ramht_size = (1 << dev_priv->ramht_bits) * 8;
return 0; return 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