Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ca9693a1 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge remote branch 'nouveau/drm-nouveau-next' of ../drm-nouveau-next into drm-core-next

* 'nouveau/drm-nouveau-next' of ../drm-nouveau-next: (93 commits)
  drm/nv50: fix a couple of vm init issues
  drm/nv04-nv40: Fix up PCI(E) GART DMA object bus address calculation.
  drm/nouveau: kick vram functions out into an "engine"
  drm/nouveau: allow gpuobj vinst to be a virtual address when necessary
  drm/nv50: tidy up PCIEGART implementation
  drm/nv50: enable non-contig vram allocations where requested
  drm/nv50: enable 4KiB pages for small vram allocations
  drm/nv50: implement global channel address space on new VM code
  drm/nv50: implement BAR1/BAR3 management on top of new VM code
  drm/nv50: import new vm code
  drm/nv50: implement custom vram mm
  drm/nouveau: Avoid potential race between nouveau_fence_update() and context takedown.
  drm/nouveau: fix use of drm_mm_node in semaphore object
  drm/nouveau: wrap calls to ttm_bo_validate()
  drm/nouveau: no need to zero dma objects, we fill them completely anyway
  drm/nouveau: introduce a util function to wait on reg != val
  drm/nouveau: implicitly insert non-DMA objects into RAMHT
  drm/nouveau: make fifo.create_context() responsible for mapping control regs
  drm/nouveau: Spin for a bit in nouveau_fence_wait() before yielding the CPU.
  drm/nouveau: Use WC memory on the AGP GART.
  ...
parents b921bae2 c45aadab
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -5,12 +5,13 @@
ccflags-y := -Iinclude/drm
nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
             nouveau_object.o nouveau_irq.o nouveau_notifier.o \
             nouveau_sgdma.o nouveau_dma.o \
             nouveau_sgdma.o nouveau_dma.o nouveau_util.o \
             nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \
             nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \
             nouveau_display.o nouveau_connector.o nouveau_fbcon.o \
             nouveau_dp.o nouveau_ramht.o \
	     nouveau_pm.o nouveau_volt.o nouveau_perf.o nouveau_temp.o \
	     nouveau_mm.o nouveau_vm.o \
             nv04_timer.o \
             nv04_mc.o nv40_mc.o nv50_mc.o \
             nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o nvc0_fb.o \
@@ -18,14 +19,16 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
             nv04_graph.o nv10_graph.o nv20_graph.o \
             nv40_graph.o nv50_graph.o nvc0_graph.o \
             nv40_grctx.o nv50_grctx.o \
             nv84_crypt.o \
             nv04_instmem.o nv50_instmem.o nvc0_instmem.o \
             nv50_crtc.o nv50_dac.o nv50_sor.o \
             nv50_evo.o nv50_crtc.o nv50_dac.o nv50_sor.o \
             nv50_cursor.o nv50_display.o nv50_fbcon.o \
             nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \
             nv04_crtc.o nv04_display.o nv04_cursor.o nv04_fbcon.o \
             nv10_gpio.o nv50_gpio.o \
	     nv50_calc.o \
	     nv04_pm.o nv50_pm.o nva3_pm.o
	     nv04_pm.o nv50_pm.o nva3_pm.o \
	     nv50_vram.o nv50_vm.o

nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o
nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o
+38 −64
Original line number Diff line number Diff line
@@ -6053,52 +6053,17 @@ static struct dcb_entry *new_dcb_entry(struct dcb_table *dcb)
	return entry;
}

static void fabricate_vga_output(struct dcb_table *dcb, int i2c, int heads)
static void fabricate_dcb_output(struct dcb_table *dcb, int type, int i2c,
				 int heads, int or)
{
	struct dcb_entry *entry = new_dcb_entry(dcb);

	entry->type = 0;
	entry->type = type;
	entry->i2c_index = i2c;
	entry->heads = heads;
	entry->location = DCB_LOC_ON_CHIP;
	entry->or = 1;
}

static void fabricate_dvi_i_output(struct dcb_table *dcb, bool twoHeads)
{
	struct dcb_entry *entry = new_dcb_entry(dcb);

	entry->type = 2;
	entry->i2c_index = LEGACY_I2C_PANEL;
	entry->heads = twoHeads ? 3 : 1;
	entry->location = !DCB_LOC_ON_CHIP;	/* ie OFF CHIP */
	entry->or = 1;	/* means |0x10 gets set on CRE_LCD__INDEX */
	entry->duallink_possible = false; /* SiI164 and co. are single link */

#if 0
	/*
	 * For dvi-a either crtc probably works, but my card appears to only
	 * support dvi-d.  "nvidia" still attempts to program it for dvi-a,
	 * doing the full fp output setup (program 0x6808.. fp dimension regs,
	 * setting 0x680848 to 0x10000111 to enable, maybe setting 0x680880);
	 * the monitor picks up the mode res ok and lights up, but no pixel
	 * data appears, so the board manufacturer probably connected up the
	 * sync lines, but missed the video traces / components
	 *
	 * with this introduction, dvi-a left as an exercise for the reader.
	 */
	fabricate_vga_output(dcb, LEGACY_I2C_PANEL, entry->heads);
#endif
}

static void fabricate_tv_output(struct dcb_table *dcb, bool twoHeads)
{
	struct dcb_entry *entry = new_dcb_entry(dcb);

	entry->type = 1;
	entry->i2c_index = LEGACY_I2C_TV;
	entry->heads = twoHeads ? 3 : 1;
	if (type != OUTPUT_ANALOG)
		entry->location = !DCB_LOC_ON_CHIP; /* ie OFF CHIP */
	entry->or = or;
}

static bool
@@ -6365,8 +6330,36 @@ apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf)
	return true;
}

static void
fabricate_dcb_encoder_table(struct drm_device *dev, struct nvbios *bios)
{
	struct dcb_table *dcb = &bios->dcb;
	int all_heads = (nv_two_heads(dev) ? 3 : 1);

#ifdef __powerpc__
	/* Apple iMac G4 NV17 */
	if (of_machine_is_compatible("PowerMac4,5")) {
		fabricate_dcb_output(dcb, OUTPUT_TMDS, 0, all_heads, 1);
		fabricate_dcb_output(dcb, OUTPUT_ANALOG, 1, all_heads, 2);
		return;
	}
#endif

	/* Make up some sane defaults */
	fabricate_dcb_output(dcb, OUTPUT_ANALOG, LEGACY_I2C_CRT, 1, 1);

	if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0)
		fabricate_dcb_output(dcb, OUTPUT_TV, LEGACY_I2C_TV,
				     all_heads, 0);

	else if (bios->tmds.output0_script_ptr ||
		 bios->tmds.output1_script_ptr)
		fabricate_dcb_output(dcb, OUTPUT_TMDS, LEGACY_I2C_PANEL,
				     all_heads, 1);
}

static int
parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
parse_dcb_table(struct drm_device *dev, struct nvbios *bios)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct dcb_table *dcb = &bios->dcb;
@@ -6386,12 +6379,7 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)

	/* this situation likely means a really old card, pre DCB */
	if (dcbptr == 0x0) {
		NV_INFO(dev, "Assuming a CRT output exists\n");
		fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1);

		if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0)
			fabricate_tv_output(dcb, twoHeads);

		fabricate_dcb_encoder_table(dev, bios);
		return 0;
	}

@@ -6451,21 +6439,7 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
		 */
		NV_TRACEWARN(dev, "No useful information in BIOS output table; "
				  "adding all possible outputs\n");
		fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1);

		/*
		 * Attempt to detect TV before DVI because the test
		 * for the former is more accurate and it rules the
		 * latter out.
		 */
		if (nv04_tv_identify(dev,
				     bios->legacy.i2c_indices.tv) >= 0)
			fabricate_tv_output(dcb, twoHeads);

		else if (bios->tmds.output0_script_ptr ||
			 bios->tmds.output1_script_ptr)
			fabricate_dvi_i_output(dcb, twoHeads);

		fabricate_dcb_encoder_table(dev, bios);
		return 0;
	}

@@ -6859,7 +6833,7 @@ nouveau_bios_init(struct drm_device *dev)
	if (ret)
		return ret;

	ret = parse_dcb_table(dev, bios, nv_two_heads(dev));
	ret = parse_dcb_table(dev, bios);
	if (ret)
		return ret;

+152 −104
Original line number Diff line number Diff line
@@ -32,6 +32,8 @@
#include "nouveau_drm.h"
#include "nouveau_drv.h"
#include "nouveau_dma.h"
#include "nouveau_mm.h"
#include "nouveau_vm.h"

#include <linux/log2.h>
#include <linux/slab.h>
@@ -46,82 +48,51 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
	if (unlikely(nvbo->gem))
		DRM_ERROR("bo %p still attached to GEM object\n", bo);

	if (nvbo->tile)
		nv10_mem_expire_tiling(dev, nvbo->tile, NULL);

	nv10_mem_put_tile_region(dev, nvbo->tile, NULL);
	nouveau_vm_put(&nvbo->vma);
	kfree(nvbo);
}

static void
nouveau_bo_fixup_align(struct drm_device *dev,
		       uint32_t tile_mode, uint32_t tile_flags,
		       int *align, int *size)
nouveau_bo_fixup_align(struct nouveau_bo *nvbo, int *align, int *size,
		       int *page_shift)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;

	/*
	 * Some of the tile_flags have a periodic structure of N*4096 bytes,
	 * align to to that as well as the page size. Align the size to the
	 * appropriate boundaries. This does imply that sizes are rounded up
	 * 3-7 pages, so be aware of this and do not waste memory by allocating
	 * many small buffers.
	 */
	if (dev_priv->card_type == NV_50) {
		uint32_t block_size = dev_priv->vram_size >> 15;
		int i;

		switch (tile_flags) {
		case 0x1800:
		case 0x2800:
		case 0x4800:
		case 0x7a00:
			if (is_power_of_2(block_size)) {
				for (i = 1; i < 10; i++) {
					*align = 12 * i * block_size;
					if (!(*align % 65536))
						break;
				}
			} else {
				for (i = 1; i < 10; i++) {
					*align = 8 * i * block_size;
					if (!(*align % 65536))
						break;
				}
			}
			*size = roundup(*size, *align);
			break;
		default:
			break;
		}
	struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev);

	} else {
		if (tile_mode) {
	if (dev_priv->card_type < NV_50) {
		if (nvbo->tile_mode) {
			if (dev_priv->chipset >= 0x40) {
				*align = 65536;
				*size = roundup(*size, 64 * tile_mode);
				*size = roundup(*size, 64 * nvbo->tile_mode);

			} else if (dev_priv->chipset >= 0x30) {
				*align = 32768;
				*size = roundup(*size, 64 * tile_mode);
				*size = roundup(*size, 64 * nvbo->tile_mode);

			} else if (dev_priv->chipset >= 0x20) {
				*align = 16384;
				*size = roundup(*size, 64 * tile_mode);
				*size = roundup(*size, 64 * nvbo->tile_mode);

			} else if (dev_priv->chipset >= 0x10) {
				*align = 16384;
				*size = roundup(*size, 32 * tile_mode);
				*size = roundup(*size, 32 * nvbo->tile_mode);
			}
		}
	} else {
		if (likely(dev_priv->chan_vm)) {
			if (*size > 256 * 1024)
				*page_shift = dev_priv->chan_vm->lpg_shift;
			else
				*page_shift = dev_priv->chan_vm->spg_shift;
		} else {
			*page_shift = 12;
		}

	/* ALIGN works only on powers of two. */
	*size = roundup(*size, PAGE_SIZE);

	if (dev_priv->card_type == NV_50) {
		*size = roundup(*size, 65536);
		*align = max(65536, *align);
		*size = roundup(*size, (1 << *page_shift));
		*align = max((1 << *page_shift), *align);
	}

	*size = roundup(*size, PAGE_SIZE);
}

int
@@ -132,7 +103,7 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_bo *nvbo;
	int ret = 0;
	int ret = 0, page_shift = 0;

	nvbo = kzalloc(sizeof(struct nouveau_bo), GFP_KERNEL);
	if (!nvbo)
@@ -145,10 +116,18 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,
	nvbo->tile_flags = tile_flags;
	nvbo->bo.bdev = &dev_priv->ttm.bdev;

	nouveau_bo_fixup_align(dev, tile_mode, nouveau_bo_tile_layout(nvbo),
			       &align, &size);
	nouveau_bo_fixup_align(nvbo, &align, &size, &page_shift);
	align >>= PAGE_SHIFT;

	if (!nvbo->no_vm && dev_priv->chan_vm) {
		ret = nouveau_vm_get(dev_priv->chan_vm, size, page_shift,
				     NV_MEM_ACCESS_RW, &nvbo->vma);
		if (ret) {
			kfree(nvbo);
			return ret;
		}
	}

	nouveau_bo_placement_set(nvbo, flags, 0);

	nvbo->channel = chan;
@@ -161,6 +140,11 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,
	}
	nvbo->channel = NULL;

	if (nvbo->vma.node) {
		if (nvbo->bo.mem.mem_type == TTM_PL_VRAM)
			nvbo->bo.offset = nvbo->vma.offset;
	}

	*pnvbo = nvbo;
	return 0;
}
@@ -244,7 +228,7 @@ nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t memtype)

	nouveau_bo_placement_set(nvbo, memtype, 0);

	ret = ttm_bo_validate(bo, &nvbo->placement, false, false, false);
	ret = nouveau_bo_validate(nvbo, false, false, false);
	if (ret == 0) {
		switch (bo->mem.mem_type) {
		case TTM_PL_VRAM:
@@ -280,7 +264,7 @@ nouveau_bo_unpin(struct nouveau_bo *nvbo)

	nouveau_bo_placement_set(nvbo, bo->mem.placement, 0);

	ret = ttm_bo_validate(bo, &nvbo->placement, false, false, false);
	ret = nouveau_bo_validate(nvbo, false, false, false);
	if (ret == 0) {
		switch (bo->mem.mem_type) {
		case TTM_PL_VRAM:
@@ -319,6 +303,25 @@ nouveau_bo_unmap(struct nouveau_bo *nvbo)
		ttm_bo_kunmap(&nvbo->kmap);
}

int
nouveau_bo_validate(struct nouveau_bo *nvbo, bool interruptible,
		    bool no_wait_reserve, bool no_wait_gpu)
{
	int ret;

	ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement, interruptible,
			      no_wait_reserve, no_wait_gpu);
	if (ret)
		return ret;

	if (nvbo->vma.node) {
		if (nvbo->bo.mem.mem_type == TTM_PL_VRAM)
			nvbo->bo.offset = nvbo->vma.offset;
	}

	return 0;
}

u16
nouveau_bo_rd16(struct nouveau_bo *nvbo, unsigned index)
{
@@ -410,37 +413,40 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
		man->default_caching = TTM_PL_FLAG_CACHED;
		break;
	case TTM_PL_VRAM:
		if (dev_priv->card_type == NV_50) {
			man->func = &nouveau_vram_manager;
			man->io_reserve_fastpath = false;
			man->use_io_reserve_lru = true;
		} else {
			man->func = &ttm_bo_manager_func;
		}
		man->flags = TTM_MEMTYPE_FLAG_FIXED |
			     TTM_MEMTYPE_FLAG_MAPPABLE;
		man->available_caching = TTM_PL_FLAG_UNCACHED |
					 TTM_PL_FLAG_WC;
		man->default_caching = TTM_PL_FLAG_WC;
		if (dev_priv->card_type == NV_50)
			man->gpu_offset = 0x40000000;
		else
			man->gpu_offset = 0;
		break;
	case TTM_PL_TT:
		man->func = &ttm_bo_manager_func;
		switch (dev_priv->gart_info.type) {
		case NOUVEAU_GART_AGP:
			man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
			man->available_caching = TTM_PL_FLAG_UNCACHED;
			man->default_caching = TTM_PL_FLAG_UNCACHED;
			man->available_caching = TTM_PL_FLAG_UNCACHED |
				TTM_PL_FLAG_WC;
			man->default_caching = TTM_PL_FLAG_WC;
			break;
		case NOUVEAU_GART_SGDMA:
			man->flags = TTM_MEMTYPE_FLAG_MAPPABLE |
				     TTM_MEMTYPE_FLAG_CMA;
			man->available_caching = TTM_PL_MASK_CACHING;
			man->default_caching = TTM_PL_FLAG_CACHED;
			man->gpu_offset = dev_priv->gart_info.aper_base;
			break;
		default:
			NV_ERROR(dev, "Unknown GART type: %d\n",
				 dev_priv->gart_info.type);
			return -EINVAL;
		}
		man->gpu_offset = dev_priv->vm_gart_base;
		break;
	default:
		NV_ERROR(dev, "Unsupported memory type %u\n", (unsigned)type);
@@ -485,16 +491,9 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan,
	if (ret)
		return ret;

	if (nvbo->channel) {
		ret = nouveau_fence_sync(fence, nvbo->channel);
		if (ret)
			goto out;
	}

	ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL, evict,
					no_wait_reserve, no_wait_gpu, new_mem);
out:
	nouveau_fence_unref((void *)&fence);
	nouveau_fence_unref(&fence);
	return ret;
}

@@ -529,14 +528,14 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
	dst_offset = new_mem->start << PAGE_SHIFT;
	if (!nvbo->no_vm) {
		if (old_mem->mem_type == TTM_PL_VRAM)
			src_offset += dev_priv->vm_vram_base;
			src_offset  = nvbo->vma.offset;
		else
			src_offset += dev_priv->vm_gart_base;
			src_offset += dev_priv->gart_info.aper_base;

		if (new_mem->mem_type == TTM_PL_VRAM)
			dst_offset += dev_priv->vm_vram_base;
			dst_offset  = nvbo->vma.offset;
		else
			dst_offset += dev_priv->vm_gart_base;
			dst_offset += dev_priv->gart_info.aper_base;
	}

	ret = RING_SPACE(chan, 3);
@@ -683,17 +682,24 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr,
	int ret;

	chan = nvbo->channel;
	if (!chan || nvbo->no_vm)
	if (!chan || nvbo->no_vm) {
		chan = dev_priv->channel;
		mutex_lock_nested(&chan->mutex, NOUVEAU_KCHANNEL_MUTEX);
	}

	if (dev_priv->card_type < NV_50)
		ret = nv04_bo_move_m2mf(chan, bo, &bo->mem, new_mem);
	else
		ret = nv50_bo_move_m2mf(chan, bo, &bo->mem, new_mem);
	if (ret)
		return ret;
	if (ret == 0) {
		ret = nouveau_bo_move_accel_cleanup(chan, nvbo, evict,
						    no_wait_reserve,
						    no_wait_gpu, new_mem);
	}

	return nouveau_bo_move_accel_cleanup(chan, nvbo, evict, no_wait_reserve, no_wait_gpu, new_mem);
	if (chan == dev_priv->channel)
		mutex_unlock(&chan->mutex);
	return ret;
}

static int
@@ -771,7 +777,6 @@ nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem,
	struct drm_device *dev = dev_priv->dev;
	struct nouveau_bo *nvbo = nouveau_bo(bo);
	uint64_t offset;
	int ret;

	if (nvbo->no_vm || new_mem->mem_type != TTM_PL_VRAM) {
		/* Nothing to do. */
@@ -781,18 +786,12 @@ nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem,

	offset = new_mem->start << PAGE_SHIFT;

	if (dev_priv->card_type == NV_50) {
		ret = nv50_mem_vm_bind_linear(dev,
					      offset + dev_priv->vm_vram_base,
					      new_mem->size,
					      nouveau_bo_tile_layout(nvbo),
					      offset);
		if (ret)
			return ret;

	if (dev_priv->chan_vm) {
		nouveau_vm_map(&nvbo->vma, new_mem->mm_node);
	} else if (dev_priv->card_type >= NV_10) {
		*new_tile = nv10_mem_set_tiling(dev, offset, new_mem->size,
						nvbo->tile_mode);
						nvbo->tile_mode,
						nvbo->tile_flags);
	}

	return 0;
@@ -808,9 +807,7 @@ nouveau_bo_vm_cleanup(struct ttm_buffer_object *bo,

	if (dev_priv->card_type >= NV_10 &&
	    dev_priv->card_type < NV_50) {
		if (*old_tile)
			nv10_mem_expire_tiling(dev, *old_tile, bo->sync_obj);

		nv10_mem_put_tile_region(dev, *old_tile, bo->sync_obj);
		*old_tile = new_tile;
	}
}
@@ -879,6 +876,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
	struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
	struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev);
	struct drm_device *dev = dev_priv->dev;
	int ret;

	mem->bus.addr = NULL;
	mem->bus.offset = 0;
@@ -901,10 +899,33 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
#endif
		break;
	case TTM_PL_VRAM:
	{
		struct nouveau_vram *vram = mem->mm_node;

		if (!dev_priv->bar1_vm) {
			mem->bus.offset = mem->start << PAGE_SHIFT;
			mem->bus.base = pci_resource_start(dev->pdev, 1);
			mem->bus.is_iomem = true;
			break;
		}

		ret = nouveau_vm_get(dev_priv->bar1_vm, mem->bus.size, 12,
				     NV_MEM_ACCESS_RW, &vram->bar_vma);
		if (ret)
			return ret;

		nouveau_vm_map(&vram->bar_vma, vram);
		if (ret) {
			nouveau_vm_put(&vram->bar_vma);
			return ret;
		}

		mem->bus.offset  = vram->bar_vma.offset;
		mem->bus.offset -= 0x0020000000ULL;
		mem->bus.base = pci_resource_start(dev->pdev, 1);
		mem->bus.is_iomem = true;
	}
		break;
	default:
		return -EINVAL;
	}
@@ -914,6 +935,17 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
static void
nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
{
	struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev);
	struct nouveau_vram *vram = mem->mm_node;

	if (!dev_priv->bar1_vm || mem->mem_type != TTM_PL_VRAM)
		return;

	if (!vram->bar_vma.node)
		return;

	nouveau_vm_unmap(&vram->bar_vma);
	nouveau_vm_put(&vram->bar_vma);
}

static int
@@ -939,7 +971,23 @@ nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)
	nvbo->placement.fpfn = 0;
	nvbo->placement.lpfn = dev_priv->fb_mappable_pages;
	nouveau_bo_placement_set(nvbo, TTM_PL_VRAM, 0);
	return ttm_bo_validate(bo, &nvbo->placement, false, true, false);
	return nouveau_bo_validate(nvbo, false, true, false);
}

void
nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence)
{
	struct nouveau_fence *old_fence;

	if (likely(fence))
		nouveau_fence_ref(fence);

	spin_lock(&nvbo->bo.bdev->fence_lock);
	old_fence = nvbo->bo.sync_obj;
	nvbo->bo.sync_obj = fence;
	spin_unlock(&nvbo->bo.bdev->fence_lock);

	nouveau_fence_unref(&old_fence);
}

struct ttm_bo_driver nouveau_bo_driver = {
@@ -949,11 +997,11 @@ struct ttm_bo_driver nouveau_bo_driver = {
	.evict_flags = nouveau_bo_evict_flags,
	.move = nouveau_bo_move,
	.verify_access = nouveau_bo_verify_access,
	.sync_obj_signaled = nouveau_fence_signalled,
	.sync_obj_wait = nouveau_fence_wait,
	.sync_obj_flush = nouveau_fence_flush,
	.sync_obj_unref = nouveau_fence_unref,
	.sync_obj_ref = nouveau_fence_ref,
	.sync_obj_signaled = __nouveau_fence_signalled,
	.sync_obj_wait = __nouveau_fence_wait,
	.sync_obj_flush = __nouveau_fence_flush,
	.sync_obj_unref = __nouveau_fence_unref,
	.sync_obj_ref = __nouveau_fence_ref,
	.fault_reserve_notify = &nouveau_ttm_fault_reserve_notify,
	.io_mem_reserve = &nouveau_ttm_io_mem_reserve,
	.io_mem_free = &nouveau_ttm_io_mem_free,
+197 −147

File changed.

Preview size limit exceeded, changes collapsed.

+48 −6
Original line number Diff line number Diff line
@@ -37,6 +37,8 @@
#include "nouveau_connector.h"
#include "nouveau_hw.h"

static void nouveau_connector_hotplug(void *, int);

static struct nouveau_encoder *
find_encoder_by_type(struct drm_connector *connector, int type)
{
@@ -94,22 +96,30 @@ nouveau_connector_bpp(struct drm_connector *connector)
}

static void
nouveau_connector_destroy(struct drm_connector *drm_connector)
nouveau_connector_destroy(struct drm_connector *connector)
{
	struct nouveau_connector *nv_connector =
		nouveau_connector(drm_connector);
	struct nouveau_connector *nv_connector = nouveau_connector(connector);
	struct drm_nouveau_private *dev_priv;
	struct nouveau_gpio_engine *pgpio;
	struct drm_device *dev;

	if (!nv_connector)
		return;

	dev = nv_connector->base.dev;
	dev_priv = dev->dev_private;
	NV_DEBUG_KMS(dev, "\n");

	pgpio = &dev_priv->engine.gpio;
	if (pgpio->irq_unregister) {
		pgpio->irq_unregister(dev, nv_connector->dcb->gpio_tag,
				      nouveau_connector_hotplug, connector);
	}

	kfree(nv_connector->edid);
	drm_sysfs_connector_remove(drm_connector);
	drm_connector_cleanup(drm_connector);
	kfree(drm_connector);
	drm_sysfs_connector_remove(connector);
	drm_connector_cleanup(connector);
	kfree(connector);
}

static struct nouveau_i2c_chan *
@@ -760,6 +770,7 @@ nouveau_connector_create(struct drm_device *dev, int index)
{
	const struct drm_connector_funcs *funcs = &nouveau_connector_funcs;
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
	struct nouveau_connector *nv_connector = NULL;
	struct dcb_connector_table_entry *dcb = NULL;
	struct drm_connector *connector;
@@ -876,6 +887,11 @@ nouveau_connector_create(struct drm_device *dev, int index)
		break;
	}

	if (pgpio->irq_register) {
		pgpio->irq_register(dev, nv_connector->dcb->gpio_tag,
				    nouveau_connector_hotplug, connector);
	}

	drm_sysfs_connector_add(connector);
	dcb->drm = connector;
	return dcb->drm;
@@ -886,3 +902,29 @@ nouveau_connector_create(struct drm_device *dev, int index)
	return ERR_PTR(ret);

}

static void
nouveau_connector_hotplug(void *data, int plugged)
{
	struct drm_connector *connector = data;
	struct drm_device *dev = connector->dev;

	NV_INFO(dev, "%splugged %s\n", plugged ? "" : "un",
		drm_get_connector_name(connector));

	if (connector->encoder && connector->encoder->crtc &&
	    connector->encoder->crtc->enabled) {
		struct nouveau_encoder *nv_encoder = nouveau_encoder(connector->encoder);
		struct drm_encoder_helper_funcs *helper =
			connector->encoder->helper_private;

		if (nv_encoder->dcb->type == OUTPUT_DP) {
			if (plugged)
				helper->dpms(connector->encoder, DRM_MODE_DPMS_ON);
			else
				helper->dpms(connector->encoder, DRM_MODE_DPMS_OFF);
		}
	}

	drm_helper_hpd_irq_event(dev);
}
Loading