diff options
| author | Mark Brown <[email protected]> | 2015-10-12 18:09:27 +0100 | 
|---|---|---|
| committer | Mark Brown <[email protected]> | 2015-10-12 18:09:27 +0100 | 
| commit | 79828b4fa835f73cdaf4bffa48696abdcbea9d02 (patch) | |
| tree | 5e0fa7156acb75ba603022bc807df8f2fedb97a8 /drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c | |
| parent | 721b51fcf91898299d96f4b72cb9434cda29dce6 (diff) | |
| parent | 8c1a9d6323abf0fb1e5dad96cf3f1c783505ea5a (diff) | |
Merge remote-tracking branch 'asoc/fix/rt5645' into asoc-fix-rt5645
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c')
| -rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c | 178 | 
1 files changed, 66 insertions, 112 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c index 5b051a26653e..954fbbe56c4b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c @@ -23,147 +23,101 @@   */  #include "priv.h" -#include <core/device.h>  #include <core/option.h> -static inline void -nvkm_mc_unk260(struct nvkm_mc *pmc, u32 data) +void +nvkm_mc_unk260(struct nvkm_mc *mc, u32 data)  { -	const struct nvkm_mc_oclass *impl = (void *)nv_oclass(pmc); -	if (impl->unk260) -		impl->unk260(pmc, data); +	if (mc->func->unk260) +		mc->func->unk260(mc, data);  } -static inline u32 -nvkm_mc_intr_mask(struct nvkm_mc *pmc) +void +nvkm_mc_intr_unarm(struct nvkm_mc *mc)  { -	u32 intr = nv_rd32(pmc, 0x000100); -	if (intr == 0xffffffff) /* likely fallen off the bus */ -		intr = 0x00000000; -	return intr; +	return mc->func->intr_unarm(mc);  } -static irqreturn_t -nvkm_mc_intr(int irq, void *arg) +void +nvkm_mc_intr_rearm(struct nvkm_mc *mc)  { -	struct nvkm_mc *pmc = arg; -	const struct nvkm_mc_oclass *oclass = (void *)nv_object(pmc)->oclass; -	const struct nvkm_mc_intr *map = oclass->intr; -	struct nvkm_subdev *unit; -	u32 intr; +	return mc->func->intr_rearm(mc); +} -	nv_wr32(pmc, 0x000140, 0x00000000); -	nv_rd32(pmc, 0x000140); -	intr = nvkm_mc_intr_mask(pmc); -	if (pmc->use_msi) -		oclass->msi_rearm(pmc); +static u32 +nvkm_mc_intr_mask(struct nvkm_mc *mc) +{ +	u32 intr = mc->func->intr_mask(mc); +	if (WARN_ON_ONCE(intr == 0xffffffff)) +		intr = 0; /* likely fallen off the bus */ +	return intr; +} -	if (intr) { -		u32 stat = intr = nvkm_mc_intr_mask(pmc); -		while (map->stat) { -			if (intr & map->stat) { -				unit = nvkm_subdev(pmc, map->unit); -				if (unit && unit->intr) -					unit->intr(unit); -				stat &= ~map->stat; -			} -			map++; +void +nvkm_mc_intr(struct nvkm_mc *mc, bool *handled) +{ +	struct nvkm_device *device = mc->subdev.device; +	struct nvkm_subdev *subdev; +	const struct nvkm_mc_intr *map = mc->func->intr; +	u32 stat, intr; + +	stat = intr = nvkm_mc_intr_mask(mc); +	while (map->stat) { +		if (intr & map->stat) { +			subdev = nvkm_device_subdev(device, map->unit); +			if (subdev) +				nvkm_subdev_intr(subdev); +			stat &= ~map->stat;  		} - -		if (stat) -			nv_error(pmc, "unknown intr 0x%08x\n", stat); +		map++;  	} -	nv_wr32(pmc, 0x000140, 0x00000001); -	return intr ? IRQ_HANDLED : IRQ_NONE; +	if (stat) +		nvkm_error(&mc->subdev, "intr %08x\n", stat); +	*handled = intr != 0;  } -int -_nvkm_mc_fini(struct nvkm_object *object, bool suspend) +static int +nvkm_mc_fini(struct nvkm_subdev *subdev, bool suspend)  { -	struct nvkm_mc *pmc = (void *)object; -	nv_wr32(pmc, 0x000140, 0x00000000); -	return nvkm_subdev_fini(&pmc->base, suspend); +	struct nvkm_mc *mc = nvkm_mc(subdev); +	nvkm_mc_intr_unarm(mc); +	return 0;  } -int -_nvkm_mc_init(struct nvkm_object *object) +static int +nvkm_mc_init(struct nvkm_subdev *subdev)  { -	struct nvkm_mc *pmc = (void *)object; -	int ret = nvkm_subdev_init(&pmc->base); -	if (ret) -		return ret; -	nv_wr32(pmc, 0x000140, 0x00000001); +	struct nvkm_mc *mc = nvkm_mc(subdev); +	if (mc->func->init) +		mc->func->init(mc); +	nvkm_mc_intr_rearm(mc);  	return 0;  } -void -_nvkm_mc_dtor(struct nvkm_object *object) +static void * +nvkm_mc_dtor(struct nvkm_subdev *subdev)  { -	struct nvkm_device *device = nv_device(object); -	struct nvkm_mc *pmc = (void *)object; -	free_irq(pmc->irq, pmc); -	if (pmc->use_msi) -		pci_disable_msi(device->pdev); -	nvkm_subdev_destroy(&pmc->base); +	return nvkm_mc(subdev);  } +static const struct nvkm_subdev_func +nvkm_mc = { +	.dtor = nvkm_mc_dtor, +	.init = nvkm_mc_init, +	.fini = nvkm_mc_fini, +}; +  int -nvkm_mc_create_(struct nvkm_object *parent, struct nvkm_object *engine, -		struct nvkm_oclass *bclass, int length, void **pobject) +nvkm_mc_new_(const struct nvkm_mc_func *func, struct nvkm_device *device, +	     int index, struct nvkm_mc **pmc)  { -	const struct nvkm_mc_oclass *oclass = (void *)bclass; -	struct nvkm_device *device = nv_device(parent); -	struct nvkm_mc *pmc; -	int ret; - -	ret = nvkm_subdev_create_(parent, engine, bclass, 0, "PMC", -				  "master", length, pobject); -	pmc = *pobject; -	if (ret) -		return ret; - -	pmc->unk260 = nvkm_mc_unk260; - -	if (nv_device_is_pci(device)) { -		switch (device->pdev->device & 0x0ff0) { -		case 0x00f0: -		case 0x02e0: -			/* BR02? NFI how these would be handled yet exactly */ -			break; -		default: -			switch (device->chipset) { -			case 0xaa: -				/* reported broken, nv also disable it */ -				break; -			default: -				pmc->use_msi = true; -				break; -			} -		} - -		pmc->use_msi = nvkm_boolopt(device->cfgopt, "NvMSI", -					    pmc->use_msi); - -		if (pmc->use_msi && oclass->msi_rearm) { -			pmc->use_msi = pci_enable_msi(device->pdev) == 0; -			if (pmc->use_msi) { -				nv_info(pmc, "MSI interrupts enabled\n"); -				oclass->msi_rearm(pmc); -			} -		} else { -			pmc->use_msi = false; -		} -	} - -	ret = nv_device_get_irq(device, true); -	if (ret < 0) -		return ret; -	pmc->irq = ret; +	struct nvkm_mc *mc; -	ret = request_irq(pmc->irq, nvkm_mc_intr, IRQF_SHARED, "nvkm", pmc); -	if (ret < 0) -		return ret; +	if (!(mc = *pmc = kzalloc(sizeof(*mc), GFP_KERNEL))) +		return -ENOMEM; +	nvkm_subdev_ctor(&nvkm_mc, device, index, 0, &mc->subdev); +	mc->func = func;  	return 0;  }  |