diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h index bc151c64bbad2733d0e77db2097a794becdcc7ff..b4974505af054d999940bbb124e727d3c667c056 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h @@ -146,6 +146,7 @@ struct nvkm_device_func { struct nvkm_device_tegra *(*tegra)(struct nvkm_device *); void *(*dtor)(struct nvkm_device *); int (*preinit)(struct nvkm_device *); + int (*init)(struct nvkm_device *); void (*fini)(struct nvkm_device *, bool suspend); }; @@ -247,9 +248,6 @@ nv_device_resource_start(struct nvkm_device *device, unsigned int bar); resource_size_t nv_device_resource_len(struct nvkm_device *device, unsigned int bar); -int -nv_device_get_irq(struct nvkm_device *device, bool stall); - struct platform_device; enum nv_bus_type { diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h b/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h index 162986e7f8c4092f1917dfabbf23e1e07abaefdb..1755c2d30fcdf827f4920df5015ee0a0cb6d0f6f 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h @@ -5,6 +5,7 @@ struct nvkm_device_tegra { struct nvkm_device device; struct platform_device *pdev; + int irq; }; int nvkm_device_tegra_new(struct platform_device *, diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h index 1fbbdaad7fcd92234ead67846c6923000244d732..4de05e718f83825a3f67317213716afb1bd45a24 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h @@ -5,24 +5,17 @@ struct nvkm_mc { const struct nvkm_mc_func *func; struct nvkm_subdev subdev; - - unsigned int irq; - bool use_msi; }; +void nvkm_mc_intr(struct nvkm_mc *, bool *handled); void nvkm_mc_intr_unarm(struct nvkm_mc *); void nvkm_mc_intr_rearm(struct nvkm_mc *); -u32 nvkm_mc_intr_mask(struct nvkm_mc *); void nvkm_mc_unk260(struct nvkm_mc *, u32 data); int nv04_mc_new(struct nvkm_device *, int, struct nvkm_mc **); -int nv40_mc_new(struct nvkm_device *, int, struct nvkm_mc **); int nv44_mc_new(struct nvkm_device *, int, struct nvkm_mc **); -int nv4c_mc_new(struct nvkm_device *, int, struct nvkm_mc **); int nv50_mc_new(struct nvkm_device *, int, struct nvkm_mc **); -int g94_mc_new(struct nvkm_device *, int, struct nvkm_mc **); int g98_mc_new(struct nvkm_device *, int, struct nvkm_mc **); int gf100_mc_new(struct nvkm_device *, int, struct nvkm_mc **); -int gf106_mc_new(struct nvkm_device *, int, struct nvkm_mc **); int gk20a_mc_new(struct nvkm_device *, int, struct nvkm_mc **); #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h index ea4b0cce6159a2acc78692c6b6fd63f4bd457c89..ac14fdf2f967a1525415f7eba2ae0624a8841c56 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h @@ -5,13 +5,15 @@ struct nvkm_pci { const struct nvkm_pci_func *func; struct nvkm_subdev subdev; + struct pci_dev *pdev; + int irq; + bool msi; }; u32 nvkm_pci_rd32(struct nvkm_pci *, u16 addr); void nvkm_pci_wr08(struct nvkm_pci *, u16 addr, u8 data); void nvkm_pci_wr32(struct nvkm_pci *, u16 addr, u32 data); void nvkm_pci_rom_shadow(struct nvkm_pci *, bool shadow); -void nvkm_pci_msi_rearm(struct nvkm_pci *); int nv04_pci_new(struct nvkm_device *, int, struct nvkm_pci **); int nv40_pci_new(struct nvkm_device *, int, struct nvkm_pci **); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 743a3e9796dd77e278c83d97ffdd583a4596d143..5fab8384d1f47f48c071e5be519329f9a36c1264 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -479,7 +479,7 @@ nv40_chipset = { .gpio = nv10_gpio_new, .i2c = nv04_i2c_new, .imem = nv40_instmem_new, - .mc = nv40_mc_new, + .mc = nv04_mc_new, .mmu = nv04_mmu_new, .pci = nv40_pci_new, .therm = nv40_therm_new, @@ -505,7 +505,7 @@ nv41_chipset = { .gpio = nv10_gpio_new, .i2c = nv04_i2c_new, .imem = nv40_instmem_new, - .mc = nv40_mc_new, + .mc = nv04_mc_new, .mmu = nv41_mmu_new, .pci = nv40_pci_new, .therm = nv40_therm_new, @@ -531,7 +531,7 @@ nv42_chipset = { .gpio = nv10_gpio_new, .i2c = nv04_i2c_new, .imem = nv40_instmem_new, - .mc = nv40_mc_new, + .mc = nv04_mc_new, .mmu = nv41_mmu_new, .pci = nv40_pci_new, .therm = nv40_therm_new, @@ -557,7 +557,7 @@ nv43_chipset = { .gpio = nv10_gpio_new, .i2c = nv04_i2c_new, .imem = nv40_instmem_new, - .mc = nv40_mc_new, + .mc = nv04_mc_new, .mmu = nv41_mmu_new, .pci = nv40_pci_new, .therm = nv40_therm_new, @@ -609,7 +609,7 @@ nv45_chipset = { .gpio = nv10_gpio_new, .i2c = nv04_i2c_new, .imem = nv40_instmem_new, - .mc = nv40_mc_new, + .mc = nv04_mc_new, .mmu = nv04_mmu_new, .pci = nv40_pci_new, .therm = nv40_therm_new, @@ -661,7 +661,7 @@ nv47_chipset = { .gpio = nv10_gpio_new, .i2c = nv04_i2c_new, .imem = nv40_instmem_new, - .mc = nv40_mc_new, + .mc = nv04_mc_new, .mmu = nv41_mmu_new, .pci = nv40_pci_new, .therm = nv40_therm_new, @@ -687,7 +687,7 @@ nv49_chipset = { .gpio = nv10_gpio_new, .i2c = nv04_i2c_new, .imem = nv40_instmem_new, - .mc = nv40_mc_new, + .mc = nv04_mc_new, .mmu = nv41_mmu_new, .pci = nv40_pci_new, .therm = nv40_therm_new, @@ -739,7 +739,7 @@ nv4b_chipset = { .gpio = nv10_gpio_new, .i2c = nv04_i2c_new, .imem = nv40_instmem_new, - .mc = nv40_mc_new, + .mc = nv04_mc_new, .mmu = nv41_mmu_new, .pci = nv40_pci_new, .therm = nv40_therm_new, @@ -765,7 +765,7 @@ nv4c_chipset = { .gpio = nv10_gpio_new, .i2c = nv04_i2c_new, .imem = nv40_instmem_new, - .mc = nv4c_mc_new, + .mc = nv44_mc_new, .mmu = nv44_mmu_new, .pci = nv4c_pci_new, .therm = nv40_therm_new, @@ -791,7 +791,7 @@ nv4e_chipset = { .gpio = nv10_gpio_new, .i2c = nv4e_i2c_new, .imem = nv40_instmem_new, - .mc = nv4c_mc_new, + .mc = nv44_mc_new, .mmu = nv44_mmu_new, .pci = nv4c_pci_new, .therm = nv40_therm_new, @@ -846,7 +846,7 @@ nv63_chipset = { .gpio = nv10_gpio_new, .i2c = nv04_i2c_new, .imem = nv40_instmem_new, - .mc = nv4c_mc_new, + .mc = nv44_mc_new, .mmu = nv44_mmu_new, .pci = nv4c_pci_new, .therm = nv40_therm_new, @@ -872,7 +872,7 @@ nv67_chipset = { .gpio = nv10_gpio_new, .i2c = nv04_i2c_new, .imem = nv40_instmem_new, - .mc = nv4c_mc_new, + .mc = nv44_mc_new, .mmu = nv44_mmu_new, .pci = nv4c_pci_new, .therm = nv40_therm_new, @@ -898,7 +898,7 @@ nv68_chipset = { .gpio = nv10_gpio_new, .i2c = nv04_i2c_new, .imem = nv40_instmem_new, - .mc = nv4c_mc_new, + .mc = nv44_mc_new, .mmu = nv44_mmu_new, .pci = nv4c_pci_new, .therm = nv40_therm_new, @@ -1022,7 +1022,7 @@ nv94_chipset = { .gpio = g94_gpio_new, .i2c = g94_i2c_new, .imem = nv50_instmem_new, - .mc = g94_mc_new, + .mc = nv50_mc_new, .mmu = nv50_mmu_new, .mxm = nv50_mxm_new, .pci = nv40_pci_new, @@ -1054,7 +1054,7 @@ nv96_chipset = { .gpio = g94_gpio_new, .i2c = g94_i2c_new, .imem = nv50_instmem_new, - .mc = g94_mc_new, + .mc = nv50_mc_new, .mmu = nv50_mmu_new, .mxm = nv50_mxm_new, .pci = nv40_pci_new, @@ -1385,7 +1385,7 @@ nvc1_chipset = { .ibus = gf100_ibus_new, .imem = nv50_instmem_new, .ltc = gf100_ltc_new, - .mc = gf106_mc_new, + .mc = gf100_mc_new, .mmu = gf100_mmu_new, .mxm = nv50_mxm_new, .pci = nv40_pci_new, @@ -1420,7 +1420,7 @@ nvc3_chipset = { .ibus = gf100_ibus_new, .imem = nv50_instmem_new, .ltc = gf100_ltc_new, - .mc = gf106_mc_new, + .mc = gf100_mc_new, .mmu = gf100_mmu_new, .mxm = nv50_mxm_new, .pci = nv40_pci_new, @@ -1563,7 +1563,7 @@ nvcf_chipset = { .ibus = gf100_ibus_new, .imem = nv50_instmem_new, .ltc = gf100_ltc_new, - .mc = gf106_mc_new, + .mc = gf100_mc_new, .mmu = gf100_mmu_new, .mxm = nv50_mxm_new, .pci = nv40_pci_new, @@ -1598,7 +1598,7 @@ nvd7_chipset = { .ibus = gf100_ibus_new, .imem = nv50_instmem_new, .ltc = gf100_ltc_new, - .mc = gf106_mc_new, + .mc = gf100_mc_new, .mmu = gf100_mmu_new, .mxm = nv50_mxm_new, .pci = nv40_pci_new, @@ -1631,7 +1631,7 @@ nvd9_chipset = { .ibus = gf100_ibus_new, .imem = nv50_instmem_new, .ltc = gf100_ltc_new, - .mc = gf106_mc_new, + .mc = gf100_mc_new, .mmu = gf100_mmu_new, .mxm = nv50_mxm_new, .pci = nv40_pci_new, @@ -1666,7 +1666,7 @@ nve4_chipset = { .ibus = gk104_ibus_new, .imem = nv50_instmem_new, .ltc = gk104_ltc_new, - .mc = gf106_mc_new, + .mc = gf100_mc_new, .mmu = gf100_mmu_new, .mxm = nv50_mxm_new, .pci = nv40_pci_new, @@ -1703,7 +1703,7 @@ nve6_chipset = { .ibus = gk104_ibus_new, .imem = nv50_instmem_new, .ltc = gk104_ltc_new, - .mc = gf106_mc_new, + .mc = gf100_mc_new, .mmu = gf100_mmu_new, .mxm = nv50_mxm_new, .pci = nv40_pci_new, @@ -1740,7 +1740,7 @@ nve7_chipset = { .ibus = gk104_ibus_new, .imem = nv50_instmem_new, .ltc = gk104_ltc_new, - .mc = gf106_mc_new, + .mc = gf100_mc_new, .mmu = gf100_mmu_new, .mxm = nv50_mxm_new, .pci = nv40_pci_new, @@ -1801,7 +1801,7 @@ nvf0_chipset = { .ibus = gk104_ibus_new, .imem = nv50_instmem_new, .ltc = gk104_ltc_new, - .mc = gf106_mc_new, + .mc = gf100_mc_new, .mmu = gf100_mmu_new, .mxm = nv50_mxm_new, .pci = nv40_pci_new, @@ -1837,7 +1837,7 @@ nvf1_chipset = { .ibus = gk104_ibus_new, .imem = nv50_instmem_new, .ltc = gk104_ltc_new, - .mc = gf106_mc_new, + .mc = gf100_mc_new, .mmu = gf100_mmu_new, .mxm = nv50_mxm_new, .pci = nv40_pci_new, @@ -2231,11 +2231,17 @@ nvkm_device_init(struct nvkm_device *device) nvdev_trace(device, "init running...\n"); time = ktime_to_us(ktime_get()); + if (device->func->init) { + ret = device->func->init(device); + if (ret) + goto fail; + } + for (i = 0; i < NVKM_SUBDEV_NR; i++) { if ((subdev = nvkm_device_subdev(device, i))) { ret = nvkm_subdev_init(subdev); if (ret) - goto fail; + goto fail_subdev; } } @@ -2245,12 +2251,13 @@ nvkm_device_init(struct nvkm_device *device) nvdev_trace(device, "init completed in %lldus\n", time); return 0; -fail: +fail_subdev: do { if ((subdev = nvkm_device_subdev(device, i))) nvkm_subdev_fini(subdev, false); } while (--i >= 0); +fail: nvdev_error(device, "init failed with %d\n", ret); return ret; } @@ -2285,17 +2292,6 @@ nv_device_resource_len(struct nvkm_device *device, unsigned int bar) } } -int -nv_device_get_irq(struct nvkm_device *device, bool stall) -{ - if (nv_device_is_pci(device)) { - return device->pdev->irq; - } else { - return platform_get_irq_byname(device->platformdev, - stall ? "stall" : "nonstall"); - } -} - void nvkm_device_del(struct nvkm_device **pdevice) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c index 0a5e5b88fee2a10be3800cf867bbeb86e45628a5..2587a17981b2f3acd73ec33299c8ae8b84a2298b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c @@ -31,9 +31,54 @@ nvkm_device_tegra(struct nvkm_device *obj) return container_of(obj, struct nvkm_device_tegra, device); } +static irqreturn_t +nvkm_device_tegra_intr(int irq, void *arg) +{ + struct nvkm_device_tegra *tdev = arg; + struct nvkm_mc *mc = tdev->device.mc; + bool handled = false; + if (likely(mc)) { + nvkm_mc_intr_unarm(mc); + nvkm_mc_intr(mc, &handled); + nvkm_mc_intr_rearm(mc); + } + return handled ? IRQ_HANDLED : IRQ_NONE; +} + +static void +nvkm_device_tegra_fini(struct nvkm_device *device, bool suspend) +{ + struct nvkm_device_tegra *tdev = nvkm_device_tegra(device); + if (tdev->irq) { + free_irq(tdev->irq, tdev); + tdev->irq = 0; + }; +} + +static int +nvkm_device_tegra_init(struct nvkm_device *device) +{ + struct nvkm_device_tegra *tdev = nvkm_device_tegra(device); + int irq, ret; + + irq = platform_get_irq_byname(tdev->pdev, "stall"); + if (irq < 0) + return irq; + + ret = request_irq(irq, nvkm_device_tegra_intr, + IRQF_SHARED, "nvkm", tdev); + if (ret) + return ret; + + tdev->irq = irq; + return 0; +} + static const struct nvkm_device_func nvkm_device_tegra_func = { .tegra = nvkm_device_tegra, + .init = nvkm_device_tegra_init, + .fini = nvkm_device_tegra_fini, }; int @@ -48,6 +93,7 @@ nvkm_device_tegra_new(struct platform_device *pdev, return -ENOMEM; *pdevice = &tdev->device; tdev->pdev = pdev; + tdev->irq = -1; return nvkm_device_ctor(&nvkm_device_tegra_func, NULL, pdev, NVKM_BUS_PLATFORM, pdev->id, NULL, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild index 721643f04bb55d9a69874dea58aeddfe362af163..bef325dcb4d001c02a8c161edca772cff86347d5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild @@ -1,11 +1,7 @@ nvkm-y += nvkm/subdev/mc/base.o nvkm-y += nvkm/subdev/mc/nv04.o -nvkm-y += nvkm/subdev/mc/nv40.o nvkm-y += nvkm/subdev/mc/nv44.o -nvkm-y += nvkm/subdev/mc/nv4c.o nvkm-y += nvkm/subdev/mc/nv50.o -nvkm-y += nvkm/subdev/mc/g94.o nvkm-y += nvkm/subdev/mc/g98.o nvkm-y += nvkm/subdev/mc/gf100.o -nvkm-y += nvkm/subdev/mc/gf106.o nvkm-y += nvkm/subdev/mc/gk20a.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c index 6a8d56c7201eabfcb61dc61ccb6b4ef9c5cdc0fa..954fbbe56c4ba1a15ff4b450d799bdb14c7099d1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c @@ -44,7 +44,7 @@ nvkm_mc_intr_rearm(struct nvkm_mc *mc) return mc->func->intr_rearm(mc); } -u32 +static u32 nvkm_mc_intr_mask(struct nvkm_mc *mc) { u32 intr = mc->func->intr_mask(mc); @@ -53,39 +53,28 @@ nvkm_mc_intr_mask(struct nvkm_mc *mc) return intr; } -static irqreturn_t -nvkm_mc_intr(int irq, void *arg) +void +nvkm_mc_intr(struct nvkm_mc *mc, bool *handled) { - struct nvkm_mc *mc = arg; - struct nvkm_subdev *subdev = &mc->subdev; - struct nvkm_device *device = subdev->device; + struct nvkm_device *device = mc->subdev.device; + struct nvkm_subdev *subdev; const struct nvkm_mc_intr *map = mc->func->intr; - struct nvkm_subdev *unit; - u32 intr; - - nvkm_mc_intr_unarm(mc); - intr = nvkm_mc_intr_mask(mc); - if (mc->use_msi) - mc->func->msi_rearm(mc); - - if (intr) { - u32 stat = intr = nvkm_mc_intr_mask(mc); - while (map->stat) { - if (intr & map->stat) { - unit = nvkm_device_subdev(device, map->unit); - if (unit) - nvkm_subdev_intr(unit); - stat &= ~map->stat; - } - map++; + 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) - nvkm_error(subdev, "unknown intr %08x\n", stat); + map++; } - nvkm_mc_intr_rearm(mc); - return intr ? IRQ_HANDLED : IRQ_NONE; + if (stat) + nvkm_error(&mc->subdev, "intr %08x\n", stat); + *handled = intr != 0; } static int @@ -96,13 +85,6 @@ nvkm_mc_fini(struct nvkm_subdev *subdev, bool suspend) return 0; } -static int -nvkm_mc_oneinit(struct nvkm_subdev *subdev) -{ - struct nvkm_mc *mc = nvkm_mc(subdev); - return request_irq(mc->irq, nvkm_mc_intr, IRQF_SHARED, "nvkm", mc); -} - static int nvkm_mc_init(struct nvkm_subdev *subdev) { @@ -116,18 +98,12 @@ nvkm_mc_init(struct nvkm_subdev *subdev) static void * nvkm_mc_dtor(struct nvkm_subdev *subdev) { - struct nvkm_mc *mc = nvkm_mc(subdev); - struct nvkm_device *device = mc->subdev.device; - free_irq(mc->irq, mc); - if (mc->use_msi) - pci_disable_msi(device->pdev); - return mc; + return nvkm_mc(subdev); } static const struct nvkm_subdev_func nvkm_mc = { .dtor = nvkm_mc_dtor, - .oneinit = nvkm_mc_oneinit, .init = nvkm_mc_init, .fini = nvkm_mc_fini, }; @@ -137,48 +113,11 @@ nvkm_mc_new_(const struct nvkm_mc_func *func, struct nvkm_device *device, int index, struct nvkm_mc **pmc) { struct nvkm_mc *mc; - int ret; if (!(mc = *pmc = kzalloc(sizeof(*mc), GFP_KERNEL))) return -ENOMEM; nvkm_subdev_ctor(&nvkm_mc, device, index, 0, &mc->subdev); mc->func = func; - - 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: - mc->use_msi = true; - break; - } - } - - mc->use_msi = nvkm_boolopt(device->cfgopt, "NvMSI", - mc->use_msi); - - if (mc->use_msi && mc->func->msi_rearm) { - mc->use_msi = pci_enable_msi(device->pdev) == 0; - if (mc->use_msi) { - nvkm_debug(&mc->subdev, "MSI enabled\n"); - mc->func->msi_rearm(mc); - } - } else { - mc->use_msi = false; - } - } - - ret = nv_device_get_irq(device, true); - if (ret < 0) - return ret; - mc->irq = ret; return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g94.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g94.c deleted file mode 100644 index 7d6a87f22b42e4f99595833339360f7f9d0c96cb..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g94.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "priv.h" - -static const struct nvkm_mc_func -g94_mc = { - .init = nv50_mc_init, - .intr = nv50_mc_intr, - .intr_unarm = nv04_mc_intr_unarm, - .intr_rearm = nv04_mc_intr_rearm, - .intr_mask = nv04_mc_intr_mask, - .msi_rearm = nv40_mc_msi_rearm, -}; - -int -g94_mc_new(struct nvkm_device *device, int index, struct nvkm_mc **pmc) -{ - return nvkm_mc_new_(&g94_mc, device, index, pmc); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c index 3eec7251b4d3ff45ab25200393d200d4424f6dbe..7344ad659105c9883f200ce7dd6d9b08eb1530bd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c @@ -51,7 +51,6 @@ g98_mc = { .intr_unarm = nv04_mc_intr_unarm, .intr_rearm = nv04_mc_intr_rearm, .intr_mask = nv04_mc_intr_mask, - .msi_rearm = nv40_mc_msi_rearm, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c index 6688d233a3e572f5fb236139e0ab40f94f443574..122fe69e83e41227ac86f494581586e6f89da734 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c @@ -74,12 +74,6 @@ gf100_mc_intr_mask(struct nvkm_mc *mc) return intr0 | intr1; } -static void -gf100_mc_msi_rearm(struct nvkm_mc *mc) -{ - nvkm_wr32(mc->subdev.device, 0x088704, 0x00000000); -} - void gf100_mc_unk260(struct nvkm_mc *mc, u32 data) { @@ -93,7 +87,6 @@ gf100_mc = { .intr_unarm = gf100_mc_intr_unarm, .intr_rearm = gf100_mc_intr_rearm, .intr_mask = gf100_mc_intr_mask, - .msi_rearm = gf100_mc_msi_rearm, .unk260 = gf100_mc_unk260, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf106.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf106.c deleted file mode 100644 index 31223cfa1a0a8ac52ba1b55bf136e7f643566a08..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf106.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "priv.h" - -static const struct nvkm_mc_func -gf106_mc = { - .init = nv50_mc_init, - .intr = gf100_mc_intr, - .intr_unarm = gf100_mc_intr_unarm, - .intr_rearm = gf100_mc_intr_rearm, - .intr_mask = gf100_mc_intr_mask, - .msi_rearm = nv40_mc_msi_rearm, - .unk260 = gf100_mc_unk260, -}; - -int -gf106_mc_new(struct nvkm_device *device, int index, struct nvkm_mc **pmc) -{ - return nvkm_mc_new_(&gf106_mc, device, index, pmc); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c index 0592bd54bb82c1a754c410c411cbf2a4cc9b981b..d92efb33bcc3ce0039ff9a24b3252b5dc9bc05cf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c @@ -30,7 +30,6 @@ gk20a_mc = { .intr_unarm = gf100_mc_intr_unarm, .intr_rearm = gf100_mc_intr_rearm, .intr_mask = gf100_mc_intr_mask, - .msi_rearm = nv40_mc_msi_rearm, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv40.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv40.c deleted file mode 100644 index 80912e7d1dec6eebee475428448bd2a8ba39c593..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv40.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "priv.h" - -void -nv40_mc_msi_rearm(struct nvkm_mc *mc) -{ - nvkm_wr08(mc->subdev.device, 0x088068, 0xff); -} - -static const struct nvkm_mc_func -nv40_mc = { - .init = nv04_mc_init, - .intr = nv04_mc_intr, - .intr_unarm = nv04_mc_intr_unarm, - .intr_rearm = nv04_mc_intr_rearm, - .intr_mask = nv04_mc_intr_mask, - .msi_rearm = nv40_mc_msi_rearm, -}; - -int -nv40_mc_new(struct nvkm_device *device, int index, struct nvkm_mc **pmc) -{ - return nvkm_mc_new_(&nv40_mc, device, index, pmc); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c index 79958c13a5f827b30d1c2af729c90c6aeeeeaaf9..9a3ac9965be06255722b288abbf97037fbf1842e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c @@ -44,7 +44,6 @@ nv44_mc = { .intr_unarm = nv04_mc_intr_unarm, .intr_rearm = nv04_mc_intr_rearm, .intr_mask = nv04_mc_intr_mask, - .msi_rearm = nv40_mc_msi_rearm, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv4c.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv4c.c deleted file mode 100644 index 68a4a04777215ebe5e653c3030d238cb447ab4c9..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv4c.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2014 Ilia Mirkin - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ilia Mirkin - */ -#include "priv.h" - -static const struct nvkm_mc_func -nv4c_mc = { - .init = nv44_mc_init, - .intr = nv04_mc_intr, - .intr_unarm = nv04_mc_intr_unarm, - .intr_rearm = nv04_mc_intr_rearm, - .intr_mask = nv04_mc_intr_mask, -}; - -int -nv4c_mc_new(struct nvkm_device *device, int index, struct nvkm_mc **pmc) -{ - return nvkm_mc_new_(&nv4c_mc, device, index, pmc); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c index 325a18232030b17759326783e11fe976d4b05f5d..5f27d7b8fddda2aa64e7ea93ded3619112bac430 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c @@ -41,13 +41,6 @@ nv50_mc_intr[] = { {}, }; -static void -nv50_mc_msi_rearm(struct nvkm_mc *mc) -{ - struct nvkm_device *device = mc->subdev.device; - pci_write_config_byte(device->pdev, 0x68, 0xff); -} - void nv50_mc_init(struct nvkm_mc *mc) { @@ -62,7 +55,6 @@ nv50_mc = { .intr_unarm = nv04_mc_intr_unarm, .intr_rearm = nv04_mc_intr_rearm, .intr_mask = nv04_mc_intr_mask, - .msi_rearm = nv50_mc_msi_rearm, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h index 5e10ea6054223757f50bdc16ff0db00f6c923052..307f6c6922879eec61f5af8035a18dc0aa948274 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h @@ -20,7 +20,6 @@ struct nvkm_mc_func { void (*intr_rearm)(struct nvkm_mc *); /* retrieve pending interrupt mask (NV_PMC_INTR) */ u32 (*intr_mask)(struct nvkm_mc *); - void (*msi_rearm)(struct nvkm_mc *); void (*unk260)(struct nvkm_mc *, u32); }; @@ -30,8 +29,6 @@ void nv04_mc_intr_unarm(struct nvkm_mc *); void nv04_mc_intr_rearm(struct nvkm_mc *); u32 nv04_mc_intr_mask(struct nvkm_mc *); -void nv40_mc_msi_rearm(struct nvkm_mc *); - void nv44_mc_init(struct nvkm_mc *); void nv50_mc_init(struct nvkm_mc *); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c index 6a742659a90194f142c0bd2936fdd04b9a6bf807..e5e0d02f3d88ea0ff45c667d8b5a3d16f08b7685 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c @@ -23,6 +23,10 @@ */ #include "priv.h" +#include +#include +#include + u32 nvkm_pci_rd32(struct nvkm_pci *pci, u16 addr) { @@ -52,21 +56,62 @@ nvkm_pci_rom_shadow(struct nvkm_pci *pci, bool shadow) nvkm_pci_wr32(pci, 0x0050, data); } -void -nvkm_pci_msi_rearm(struct nvkm_pci *pci) +static irqreturn_t +nvkm_pci_intr(int irq, void *arg) +{ + struct nvkm_pci *pci = arg; + struct nvkm_mc *mc = pci->subdev.device->mc; + bool handled = false; + if (likely(mc)) { + nvkm_mc_intr_unarm(mc); + if (pci->msi) + pci->func->msi_rearm(pci); + nvkm_mc_intr(mc, &handled); + nvkm_mc_intr_rearm(mc); + } + return handled ? IRQ_HANDLED : IRQ_NONE; +} + +static int +nvkm_pci_fini(struct nvkm_subdev *subdev, bool suspend) { - pci->func->msi_rearm(pci); + struct nvkm_pci *pci = nvkm_pci(subdev); + if (pci->irq >= 0) { + free_irq(pci->irq, pci); + pci->irq = -1; + }; + return 0; +} + +static int +nvkm_pci_init(struct nvkm_subdev *subdev) +{ + struct nvkm_pci *pci = nvkm_pci(subdev); + struct pci_dev *pdev = pci->pdev; + int ret; + + ret = request_irq(pdev->irq, nvkm_pci_intr, IRQF_SHARED, "nvkm", pci); + if (ret) + return ret; + + pci->irq = pdev->irq; + return ret; } static void * nvkm_pci_dtor(struct nvkm_subdev *subdev) { + struct nvkm_pci *pci = nvkm_pci(subdev); + if (pci->msi) + pci_disable_msi(pci->pdev); return nvkm_pci(subdev); } static const struct nvkm_subdev_func nvkm_pci_func = { .dtor = nvkm_pci_dtor, + .init = nvkm_pci_init, + .fini = nvkm_pci_fini, }; int @@ -74,9 +119,38 @@ nvkm_pci_new_(const struct nvkm_pci_func *func, struct nvkm_device *device, int index, struct nvkm_pci **ppci) { struct nvkm_pci *pci; + if (!(pci = *ppci = kzalloc(sizeof(**ppci), GFP_KERNEL))) return -ENOMEM; nvkm_subdev_ctor(&nvkm_pci_func, device, index, 0, &pci->subdev); pci->func = func; + pci->pdev = device->func->pci(device)->pdev; + pci->irq = -1; + + switch (pci->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: + pci->msi = true; + break; + } + } + + pci->msi = nvkm_boolopt(device->cfgopt, "NvMSI", pci->msi); + if (pci->msi && func->msi_rearm) { + pci->msi = pci_enable_msi(pci->pdev) == 0; + if (pci->msi) + nvkm_debug(&pci->subdev, "MSI enabled\n"); + } else { + pci->msi = false; + } + return 0; }