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

Commit 4a15cdff authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge branch 'drm-nouveau-next' of...

Merge branch 'drm-nouveau-next' of git://anongit.freedesktop.org/git/nouveau/linux-2.6 into drm-next

- Ilia's PMPEG improvements
- MSI fixes, and another attempt at enabling by default
- Initial GK208 support, just modesetting
- "Old" PM code gone, new infrastructure and various different stages of support (depending which chipset / ram type etc) is in its place.  This includes support that goes beyond what the previous code was capable of.  User control has been deliberately sabotaged, it's not safe to use still.
- Thermal management / fan control that's been present for a while is turned ON by default now.
- Misc other fixes that have accumulated

* 'drm-nouveau-next' of git://anongit.freedesktop.org/git/nouveau/linux-2.6: (74 commits)
  drm/nouveau/fb: implement various bits of work towards memory reclocking
  drm/nouveau: implement a simple sysfs interface to new pm code
  drm/nouveau/device: initial control object class, with pstate control methods
  drm/nouveau/clk: implement power state and engine clock control in core
  drm/nouveau/volt: implement voltage control in core
  drm/nouveau/bios: parsing for various tables required for power management
  drm/nouveau/perfmon: initial infrastructure to expose performance counters
  drm/nouveau/bus: add interfaces/helpers for sequencer
  drm/nouveau/bus: make external class definitions pointers
  drm/nouveau/pwr: initial implementation
  drm/nouveau/therm: update target fanspeed outside of therm lock
  drm/nouveau/therm: automatic mode by default
  drm/nouveau/therm: no toggle fan control either if we can't guarantee no pwm connected
  drm/nvc0/therm: allow fan control if we've killed the vbios ppwr ucode
  drm/nouveau/therm: if no bios trip/linear info, default to perf-suggested speed
  drm/nouveau/therm: add hook for clk to suggest fanspeed to therm
  drm/nouveau/pwr: assign a subdev id for upcoming implementation
  drm/nouveau/gpio: return different error code for not found vs invalid
  drm/nouveau/drm/pm: remove everything except the hwmon interfaces to THERM
  drm/nouveau/core: make all info-level messages silent for runtime pm
  ...
parents ec61f5eb aae95ca7
Loading
Loading
Loading
Loading
+45 −3
Original line number Diff line number Diff line
@@ -28,7 +28,9 @@ nouveau-y += core/subdev/bar/nv50.o
nouveau-y += core/subdev/bar/nvc0.o
nouveau-y += core/subdev/bios/base.o
nouveau-y += core/subdev/bios/bit.o
nouveau-y += core/subdev/bios/boost.o
nouveau-y += core/subdev/bios/conn.o
nouveau-y += core/subdev/bios/cstep.o
nouveau-y += core/subdev/bios/dcb.o
nouveau-y += core/subdev/bios/disp.o
nouveau-y += core/subdev/bios/dp.o
@@ -39,17 +41,26 @@ nouveau-y += core/subdev/bios/init.o
nouveau-y += core/subdev/bios/mxm.o
nouveau-y += core/subdev/bios/perf.o
nouveau-y += core/subdev/bios/pll.o
nouveau-y += core/subdev/bios/rammap.o
nouveau-y += core/subdev/bios/timing.o
nouveau-y += core/subdev/bios/therm.o
nouveau-y += core/subdev/bios/vmap.o
nouveau-y += core/subdev/bios/volt.o
nouveau-y += core/subdev/bios/xpio.o
nouveau-y += core/subdev/bus/hwsq.o
nouveau-y += core/subdev/bus/nv04.o
nouveau-y += core/subdev/bus/nv31.o
nouveau-y += core/subdev/bus/nv50.o
nouveau-y += core/subdev/bus/nv94.o
nouveau-y += core/subdev/bus/nvc0.o
nouveau-y += core/subdev/clock/base.o
nouveau-y += core/subdev/clock/nv04.o
nouveau-y += core/subdev/clock/nv40.o
nouveau-y += core/subdev/clock/nv50.o
nouveau-y += core/subdev/clock/nv84.o
nouveau-y += core/subdev/clock/nva3.o
nouveau-y += core/subdev/clock/nvc0.o
nouveau-y += core/subdev/clock/nve0.o
nouveau-y += core/subdev/clock/pllnv04.o
nouveau-y += core/subdev/clock/pllnva3.o
nouveau-y += core/subdev/devinit/base.o
@@ -78,7 +89,12 @@ nouveau-y += core/subdev/fb/nv47.o
nouveau-y += core/subdev/fb/nv49.o
nouveau-y += core/subdev/fb/nv4e.o
nouveau-y += core/subdev/fb/nv50.o
nouveau-y += core/subdev/fb/nv84.o
nouveau-y += core/subdev/fb/nva3.o
nouveau-y += core/subdev/fb/nvaa.o
nouveau-y += core/subdev/fb/nvaf.o
nouveau-y += core/subdev/fb/nvc0.o
nouveau-y += core/subdev/fb/nve0.o
nouveau-y += core/subdev/fb/ramnv04.o
nouveau-y += core/subdev/fb/ramnv10.o
nouveau-y += core/subdev/fb/ramnv1a.o
@@ -89,7 +105,12 @@ nouveau-y += core/subdev/fb/ramnv44.o
nouveau-y += core/subdev/fb/ramnv49.o
nouveau-y += core/subdev/fb/ramnv4e.o
nouveau-y += core/subdev/fb/ramnv50.o
nouveau-y += core/subdev/fb/ramnva3.o
nouveau-y += core/subdev/fb/ramnvaa.o
nouveau-y += core/subdev/fb/ramnvc0.o
nouveau-y += core/subdev/fb/ramnve0.o
nouveau-y += core/subdev/fb/sddr3.o
nouveau-y += core/subdev/fb/gddr5.o
nouveau-y += core/subdev/gpio/base.o
nouveau-y += core/subdev/gpio/nv10.o
nouveau-y += core/subdev/gpio/nv50.o
@@ -113,13 +134,22 @@ nouveau-y += core/subdev/instmem/nv50.o
nouveau-y += core/subdev/ltcg/nvc0.o
nouveau-y += core/subdev/mc/base.o
nouveau-y += core/subdev/mc/nv04.o
nouveau-y += core/subdev/mc/nv40.o
nouveau-y += core/subdev/mc/nv44.o
nouveau-y += core/subdev/mc/nv50.o
nouveau-y += core/subdev/mc/nv94.o
nouveau-y += core/subdev/mc/nv98.o
nouveau-y += core/subdev/mc/nvc0.o
nouveau-y += core/subdev/mc/nvc3.o
nouveau-y += core/subdev/mxm/base.o
nouveau-y += core/subdev/mxm/mxms.o
nouveau-y += core/subdev/mxm/nv50.o
nouveau-y += core/subdev/pwr/base.o
nouveau-y += core/subdev/pwr/memx.o
nouveau-y += core/subdev/pwr/nva3.o
nouveau-y += core/subdev/pwr/nvc0.o
nouveau-y += core/subdev/pwr/nvd0.o
nouveau-y += core/subdev/pwr/nv108.o
nouveau-y += core/subdev/therm/base.o
nouveau-y += core/subdev/therm/fan.o
nouveau-y += core/subdev/therm/fannil.o
@@ -140,6 +170,9 @@ nouveau-y += core/subdev/vm/nv41.o
nouveau-y += core/subdev/vm/nv44.o
nouveau-y += core/subdev/vm/nv50.o
nouveau-y += core/subdev/vm/nvc0.o
nouveau-y += core/subdev/volt/base.o
nouveau-y += core/subdev/volt/gpio.o
nouveau-y += core/subdev/volt/nv40.o

nouveau-y += core/engine/falcon.o
nouveau-y += core/engine/xtensa.o
@@ -158,6 +191,7 @@ nouveau-y += core/engine/copy/nve0.o
nouveau-y += core/engine/crypt/nv84.o
nouveau-y += core/engine/crypt/nv98.o
nouveau-y += core/engine/device/base.o
nouveau-y += core/engine/device/ctrl.o
nouveau-y += core/engine/device/nv04.o
nouveau-y += core/engine/device/nv10.o
nouveau-y += core/engine/device/nv20.o
@@ -227,8 +261,18 @@ nouveau-y += core/engine/graph/nve4.o
nouveau-y += core/engine/graph/nvf0.o
nouveau-y += core/engine/mpeg/nv31.o
nouveau-y += core/engine/mpeg/nv40.o
nouveau-y += core/engine/mpeg/nv44.o
nouveau-y += core/engine/mpeg/nv50.o
nouveau-y += core/engine/mpeg/nv84.o
nouveau-y += core/engine/perfmon/base.o
nouveau-y += core/engine/perfmon/daemon.o
nouveau-y += core/engine/perfmon/nv40.o
nouveau-y += core/engine/perfmon/nv50.o
nouveau-y += core/engine/perfmon/nv84.o
nouveau-y += core/engine/perfmon/nva3.o
nouveau-y += core/engine/perfmon/nvc0.o
nouveau-y += core/engine/perfmon/nve0.o
nouveau-y += core/engine/perfmon/nvf0.o
nouveau-y += core/engine/ppp/nv98.o
nouveau-y += core/engine/ppp/nvc0.o
nouveau-y += core/engine/software/nv04.o
@@ -260,9 +304,7 @@ include $(src)/dispnv04/Makefile
nouveau-y += nv50_display.o

# drm/pm
nouveau-y += nouveau_pm.o nouveau_volt.o nouveau_perf.o
nouveau-y += nv04_pm.o nv40_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o
nouveau-y += nouveau_mem.o
nouveau-y += nouveau_hwmon.o nouveau_sysfs.o

# other random bits
nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o
+86 −33
Original line number Diff line number Diff line
@@ -23,62 +23,114 @@
#include <core/os.h>
#include <core/event.h>

static void
nouveau_event_put_locked(struct nouveau_event *event, int index,
			 struct nouveau_eventh *handler)
void
nouveau_event_put(struct nouveau_eventh *handler)
{
	if (!--event->index[index].refs) {
	struct nouveau_event *event = handler->event;
	unsigned long flags;
	if (__test_and_clear_bit(NVKM_EVENT_ENABLE, &handler->flags)) {
		spin_lock_irqsave(&event->refs_lock, flags);
		if (!--event->index[handler->index].refs) {
			if (event->disable)
			event->disable(event, index);
				event->disable(event, handler->index);
		}
		spin_unlock_irqrestore(&event->refs_lock, flags);
	}
	list_del(&handler->head);
}

void
nouveau_event_put(struct nouveau_event *event, int index,
		  struct nouveau_eventh *handler)
nouveau_event_get(struct nouveau_eventh *handler)
{
	struct nouveau_event *event = handler->event;
	unsigned long flags;
	if (!__test_and_set_bit(NVKM_EVENT_ENABLE, &handler->flags)) {
		spin_lock_irqsave(&event->refs_lock, flags);
		if (!event->index[handler->index].refs++) {
			if (event->enable)
				event->enable(event, handler->index);
		}
		spin_unlock_irqrestore(&event->refs_lock, flags);
	}
}

	spin_lock_irqsave(&event->lock, flags);
	if (index < event->index_nr)
		nouveau_event_put_locked(event, index, handler);
	spin_unlock_irqrestore(&event->lock, flags);
static void
nouveau_event_fini(struct nouveau_eventh *handler)
{
	struct nouveau_event *event = handler->event;
	unsigned long flags;
	nouveau_event_put(handler);
	spin_lock_irqsave(&event->list_lock, flags);
	list_del(&handler->head);
	spin_unlock_irqrestore(&event->list_lock, flags);
}

void
nouveau_event_get(struct nouveau_event *event, int index,
static int
nouveau_event_init(struct nouveau_event *event, int index,
		   int (*func)(void *, int), void *priv,
		   struct nouveau_eventh *handler)
{
	unsigned long flags;

	spin_lock_irqsave(&event->lock, flags);
	if (index < event->index_nr) {
		list_add(&handler->head, &event->index[index].list);
		if (!event->index[index].refs++) {
			if (event->enable)
				event->enable(event, index);
	if (index >= event->index_nr)
		return -EINVAL;

	handler->event = event;
	handler->flags = 0;
	handler->index = index;
	handler->func = func;
	handler->priv = priv;

	spin_lock_irqsave(&event->list_lock, flags);
	list_add_tail(&handler->head, &event->index[index].list);
	spin_unlock_irqrestore(&event->list_lock, flags);
	return 0;
}

int
nouveau_event_new(struct nouveau_event *event, int index,
		  int (*func)(void *, int), void *priv,
		  struct nouveau_eventh **phandler)
{
	struct nouveau_eventh *handler;
	int ret = -ENOMEM;

	handler = *phandler = kmalloc(sizeof(*handler), GFP_KERNEL);
	if (handler) {
		ret = nouveau_event_init(event, index, func, priv, handler);
		if (ret)
			kfree(handler);
	}

	return ret;
}

void
nouveau_event_ref(struct nouveau_eventh *handler, struct nouveau_eventh **ref)
{
	BUG_ON(handler != NULL);
	if (*ref) {
		nouveau_event_fini(*ref);
		kfree(*ref);
	}
	spin_unlock_irqrestore(&event->lock, flags);
	*ref = handler;
}

void
nouveau_event_trigger(struct nouveau_event *event, int index)
{
	struct nouveau_eventh *handler, *temp;
	struct nouveau_eventh *handler;
	unsigned long flags;

	if (index >= event->index_nr)
	if (WARN_ON(index >= event->index_nr))
		return;

	spin_lock_irqsave(&event->lock, flags);
	list_for_each_entry_safe(handler, temp, &event->index[index].list, head) {
		if (handler->func(handler, index) == NVKM_EVENT_DROP) {
			nouveau_event_put_locked(event, index, handler);
		}
	spin_lock_irqsave(&event->list_lock, flags);
	list_for_each_entry(handler, &event->index[index].list, head) {
		if (test_bit(NVKM_EVENT_ENABLE, &handler->flags) &&
		    handler->func(handler->priv, index) == NVKM_EVENT_DROP)
			nouveau_event_put(handler);
	}
	spin_unlock_irqrestore(&event->lock, flags);
	spin_unlock_irqrestore(&event->list_lock, flags);
}

void
@@ -102,7 +154,8 @@ nouveau_event_create(int index_nr, struct nouveau_event **pevent)
	if (!event)
		return -ENOMEM;

	spin_lock_init(&event->lock);
	spin_lock_init(&event->list_lock);
	spin_lock_init(&event->refs_lock);
	for (i = 0; i < index_nr; i++)
		INIT_LIST_HEAD(&event->index[i].list);
	event->index_nr = index_nr;
+1 −10
Original line number Diff line number Diff line
@@ -25,15 +25,6 @@
#include <core/option.h>
#include <core/debug.h>

/* compares unterminated string 'str' with zero-terminated string 'cmp' */
static inline int
strncasecmpz(const char *str, const char *cmp, size_t len)
{
	if (strlen(cmp) != len)
		return len;
	return strncasecmp(str, cmp, len);
}

const char *
nouveau_stropt(const char *optstr, const char *opt, int *arglen)
{
@@ -105,7 +96,7 @@ nouveau_dbgopt(const char *optstr, const char *sub)
				else if (!strncasecmpz(optstr, "warn", len))
					level = NV_DBG_WARN;
				else if (!strncasecmpz(optstr, "info", len))
					level = NV_DBG_INFO;
					level = NV_DBG_INFO_NORMAL;
				else if (!strncasecmpz(optstr, "debug", len))
					level = NV_DBG_DEBUG;
				else if (!strncasecmpz(optstr, "trace", len))
+25 −20
Original line number Diff line number Diff line
@@ -27,16 +27,38 @@
#include <core/subdev.h>
#include <core/printk.h>

int nv_printk_suspend_level = NV_DBG_DEBUG;
int nv_info_debug_level = NV_DBG_INFO_NORMAL;

void
nv_printk_(struct nouveau_object *object, const char *pfx, int level,
	   const char *fmt, ...)
nv_printk_(struct nouveau_object *object, int level, const char *fmt, ...)
{
	static const char name[] = { '!', 'E', 'W', ' ', 'D', 'T', 'P', 'S' };
	const char *pfx;
	char mfmt[256];
	va_list args;

	switch (level) {
	case NV_DBG_FATAL:
		pfx = KERN_CRIT;
		break;
	case NV_DBG_ERROR:
		pfx = KERN_ERR;
		break;
	case NV_DBG_WARN:
		pfx = KERN_WARNING;
		break;
	case NV_DBG_INFO_NORMAL:
		pfx = KERN_INFO;
		break;
	case NV_DBG_DEBUG:
	case NV_DBG_PARANOIA:
	case NV_DBG_TRACE:
	case NV_DBG_SPAM:
	default:
		pfx = KERN_DEBUG;
		break;
	}

	if (object && !nv_iclass(object, NV_CLIENT_CLASS)) {
		struct nouveau_object *device = object;
		struct nouveau_object *subdev = object;
@@ -74,20 +96,3 @@ nv_printk_(struct nouveau_object *object, const char *pfx, int level,
	vprintk(mfmt, args);
	va_end(args);
}

#define CONV_LEVEL(x) case NV_DBG_##x: return NV_PRINTK_##x

const char *nv_printk_level_to_pfx(int level)
{
	switch (level) {
	CONV_LEVEL(FATAL);
	CONV_LEVEL(ERROR);
	CONV_LEVEL(WARN);
	CONV_LEVEL(INFO);
	CONV_LEVEL(DEBUG);
	CONV_LEVEL(PARANOIA);
	CONV_LEVEL(TRACE);
	CONV_LEVEL(SPAM);
	}
	return NV_PRINTK_DEBUG;
}
+34 −22
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@

#include <core/class.h>

#include <engine/device.h>
#include "priv.h"

static DEFINE_MUTEX(nv_devices_mutex);
static LIST_HEAD(nv_devices);
@@ -75,7 +75,9 @@ static const u64 disable_map[] = {
	[NVDEV_SUBDEV_BAR]	= NV_DEVICE_DISABLE_CORE,
	[NVDEV_SUBDEV_VOLT]	= NV_DEVICE_DISABLE_CORE,
	[NVDEV_SUBDEV_THERM]	= NV_DEVICE_DISABLE_CORE,
	[NVDEV_SUBDEV_PWR]	= NV_DEVICE_DISABLE_CORE,
	[NVDEV_ENGINE_DMAOBJ]	= NV_DEVICE_DISABLE_CORE,
	[NVDEV_ENGINE_PERFMON]  = NV_DEVICE_DISABLE_CORE,
	[NVDEV_ENGINE_FIFO]	= NV_DEVICE_DISABLE_FIFO,
	[NVDEV_ENGINE_SW]	= NV_DEVICE_DISABLE_FIFO,
	[NVDEV_ENGINE_GR]	= NV_DEVICE_DISABLE_GRAPH,
@@ -87,7 +89,7 @@ static const u64 disable_map[] = {
	[NVDEV_ENGINE_PPP]	= NV_DEVICE_DISABLE_PPP,
	[NVDEV_ENGINE_COPY0]	= NV_DEVICE_DISABLE_COPY0,
	[NVDEV_ENGINE_COPY1]	= NV_DEVICE_DISABLE_COPY1,
	[NVDEV_ENGINE_UNK1C1]	= NV_DEVICE_DISABLE_UNK1C1,
	[NVDEV_ENGINE_VIC]	= NV_DEVICE_DISABLE_VIC,
	[NVDEV_ENGINE_VENC]	= NV_DEVICE_DISABLE_VENC,
	[NVDEV_ENGINE_DISP]	= NV_DEVICE_DISABLE_DISP,
	[NVDEV_SUBDEV_NR]	= 0,
@@ -119,10 +121,12 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
			return -ENODEV;
	}

	ret = nouveau_parent_create(parent, nv_object(device), oclass, 0, NULL,
	ret = nouveau_parent_create(parent, nv_object(device), oclass, 0,
				    nouveau_control_oclass,
				    (1ULL << NVDEV_ENGINE_DMAOBJ) |
				    (1ULL << NVDEV_ENGINE_FIFO) |
				    (1ULL << NVDEV_ENGINE_DISP), &devobj);
				    (1ULL << NVDEV_ENGINE_DISP) |
				    (1ULL << NVDEV_ENGINE_PERFMON), &devobj);
	*pobject = nv_object(devobj);
	if (ret)
		return ret;
@@ -158,22 +162,29 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
		iounmap(map);

		/* determine chipset and derive architecture from it */
		if ((boot0 & 0x0f000000) > 0) {
			device->chipset = (boot0 & 0xff00000) >> 20;
			switch (device->chipset & 0xf0) {
			case 0x10: device->card_type = NV_10; break;
			case 0x20: device->card_type = NV_20; break;
			case 0x30: device->card_type = NV_30; break;
			case 0x40:
			case 0x60: device->card_type = NV_40; break;
			case 0x50:
			case 0x80:
			case 0x90:
			case 0xa0: device->card_type = NV_50; break;
			case 0xc0: device->card_type = NV_C0; break;
			case 0xd0: device->card_type = NV_D0; break;
			case 0xe0:
			case 0xf0: device->card_type = NV_E0; break;
		if ((boot0 & 0x1f000000) > 0) {
			device->chipset = (boot0 & 0x1ff00000) >> 20;
			switch (device->chipset & 0x1f0) {
			case 0x010: {
				if (0x461 & (1 << (device->chipset & 0xf)))
					device->card_type = NV_10;
				else
					device->card_type = NV_11;
				break;
			}
			case 0x020: device->card_type = NV_20; break;
			case 0x030: device->card_type = NV_30; break;
			case 0x040:
			case 0x060: device->card_type = NV_40; break;
			case 0x050:
			case 0x080:
			case 0x090:
			case 0x0a0: device->card_type = NV_50; break;
			case 0x0c0: device->card_type = NV_C0; break;
			case 0x0d0: device->card_type = NV_D0; break;
			case 0x0e0:
			case 0x0f0:
			case 0x100: device->card_type = NV_E0; break;
			default:
				break;
			}
@@ -188,7 +199,8 @@ nouveau_devobj_ctor(struct nouveau_object *parent,

		switch (device->card_type) {
		case NV_04: ret = nv04_identify(device); break;
		case NV_10: ret = nv10_identify(device); break;
		case NV_10:
		case NV_11: ret = nv10_identify(device); break;
		case NV_20: ret = nv20_identify(device); break;
		case NV_30: ret = nv30_identify(device); break;
		case NV_40: ret = nv40_identify(device); break;
@@ -212,7 +224,7 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
		nv_info(device, "Family : NV%02X\n", device->card_type);

		/* determine frequency of timing crystal */
		if ( device->chipset < 0x17 ||
		if ( device->card_type <= NV_10 || device->chipset < 0x17 ||
		    (device->chipset >= 0x20 && device->chipset < 0x25))
			strap &= 0x00000040;
		else
Loading