Alexandre Courbot
2014-Feb-01 03:16 UTC
[Nouveau] [RFC 00/16] drm/nouveau: initial support for GK20A (Tegra K1)
Hello everyone, GK20A is the Kepler-based GPU used in the upcoming Tegra K1 chips. The following patches perform architectural changes to Nouveau that are necessary to support non-PCI GPUs and add initial support for GK20A. Although the support is still very basic and more user-space changes will be needed to make the full graphics stack run on top of it, we were able to successfully open channels and run simple pushbuffers with libdrm (more testing including rendering is in progress as we get more familiar with Nouveau's user-space interface). This work should be considered as a RFC and a proof-of-concept for driving future Tegra GPUs with Nouveau. Some design choices need to be discussed and quite a few inelegant shortcuts were purposely taken to minimize the size of this first set. Or said otherwise, apart from the changes that add support for non-PCI GPUs, remarkably little code needs to be added to get GK20A to a point where it is actually running. This is very encouraging, and it will be interesting to keep improving this support and see where this gets us. The first part of this series (patches 01/09) adds support for platform devices to Nouveau. Nouveau currently only supports PCI devices, and GK20A uses the platform bus and Device Tree. So the first step towards GK20A support is to abstract the PCI functions used by Nouveau (mainly resources range querying and page mapping functions) and add platform device probing functions. For most of the existing chips, platform device support does not make any sense, so only the subdev and engine drivers actually used by GK20A were updated to use these abstractions. If, for consistency reasons, it is deemed preferable to use them everywhere in the driver, we will do it in the next revision of this series. This part can be considered independently from the actual GK20A support, and I believe it would make sense to discuss what needs to be improved and drive it to merge separately, as the remainder of the series will likely require more work. The second part (10/14) updates existing subdev/engine drivers to support GK20A, and adds a very simple memory driver that simulates dedicated video memory by allocating a large system memory chunk at boot time. This is clearly sub-optimal and should not be merged, but allowed us to quickly bring GK20A up with Nouveau. Other drivers changes are fairly small, and are here to handle the difference in number of engines and units compared to desktop Kepler as well as to perform a few things usually done by the video BIOS (which Tegra does not feature). Finally, support for probing GK20A is added in the last 2 patches. It should be noted that contrary to what Nouveau currently expects, GK20A does not embed any display hardware (that part being handled by tegradrm). So this driver should really be only used through DRM render-nodes and collaborate with the display driver using PRIME. I have not yet figured out how to turn GK20A?s instantiation of Nouveau into a render-node only driver without breaking support for existing desktop GPUs, and consequently the driver spawns a /dev/dri/cardX node which we should try to get rid of. I guess my email address might surprise some of you, so let me anticipate some questions you might have. :P Yes, this work is endorsed by NVIDIA. Several other NVIDIAns (CC'd), including core GPU experts, have provided significant technical guidance and will continue their involvement. Special thanks go to Terje Bergstrom and Ken Adams for their invaluable GPU expertise, and Thierry Reding (at FOSDEM this weekend) for help with debugging and user-space testing. Let me also stress that although very exciting, this effort is still experimental, so I would like to make sure that nobody makes excessive expectations based on these few patches. The scope of this work is strictly limited to Tegra (although given the similarities desktop GPU support will certainly benefit from it indirectly), and we do not have any plan to work on user-space support. So do not uninstall that proprietary driver just yet. ;) With this being clarified, we are looking forward to getting your feedback and working with you guys to bring and improve Tegra K1 support into Nouveau! :) Alexandre Courbot (16): drm/nouveau: handle -EACCES runtime PM return code drm/nouveau: basic support for platform devices drm/nouveau: add platform device probing function drm/nouveau/fifo: support platform devices drm/nouveau/bar: support platform devices drm/nouveau/bar: only ioremap BAR3 if it exists drm/nouveau/bar/nvc0: support chips without BAR3 drm/nouveau/mc: support platform devices drm/nouveau/fb: support platform devices drm/nouveau/timer: skip calibration on GK20A drm/nouveau/fifo: allocate usermem as needed drm/nouveau/fifo: add GK20A support drm/nouveau/ibus: add GK20A support drm/nouveau/fb: add GK20A support drm/nouveau: support GK20A in nouveau_accel_init() drm/nouveau: support for probing GK20A drivers/gpu/drm/nouveau/Makefile | 4 + drivers/gpu/drm/nouveau/core/engine/device/base.c | 92 +++++++++++++++- drivers/gpu/drm/nouveau/core/engine/device/nve0.c | 20 ++++ drivers/gpu/drm/nouveau/core/engine/fifo/base.c | 2 +- drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c | 4 +- drivers/gpu/drm/nouveau/core/engine/fifo/nve0.h | 1 + drivers/gpu/drm/nouveau/core/engine/fifo/nvea.c | 27 +++++ drivers/gpu/drm/nouveau/core/include/core/device.h | 27 +++++ .../gpu/drm/nouveau/core/include/engine/device.h | 10 ++ drivers/gpu/drm/nouveau/core/include/engine/fifo.h | 1 + drivers/gpu/drm/nouveau/core/include/subdev/fb.h | 1 + drivers/gpu/drm/nouveau/core/include/subdev/ibus.h | 1 + drivers/gpu/drm/nouveau/core/include/subdev/mc.h | 1 + drivers/gpu/drm/nouveau/core/os.h | 1 + drivers/gpu/drm/nouveau/core/subdev/bar/base.c | 7 +- drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c | 4 +- drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c | 116 +++++++++++---------- drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c | 9 +- drivers/gpu/drm/nouveau/core/subdev/fb/nvea.c | 28 +++++ drivers/gpu/drm/nouveau/core/subdev/fb/priv.h | 1 + drivers/gpu/drm/nouveau/core/subdev/fb/ramnvea.c | 67 ++++++++++++ drivers/gpu/drm/nouveau/core/subdev/ibus/nvea.c | 108 +++++++++++++++++++ drivers/gpu/drm/nouveau/core/subdev/mc/base.c | 43 +++++--- drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c | 19 ++-- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 2 +- drivers/gpu/drm/nouveau/nouveau_abi16.c | 13 ++- drivers/gpu/drm/nouveau/nouveau_bo.c | 22 ++-- drivers/gpu/drm/nouveau/nouveau_connector.c | 2 +- drivers/gpu/drm/nouveau/nouveau_display.c | 3 +- drivers/gpu/drm/nouveau/nouveau_drm.c | 86 ++++++++++++--- drivers/gpu/drm/nouveau/nouveau_sysfs.c | 8 +- drivers/gpu/drm/nouveau/nouveau_ttm.c | 31 +++--- 32 files changed, 622 insertions(+), 139 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/core/engine/fifo/nvea.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/fb/nvea.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/fb/ramnvea.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/ibus/nvea.c -- 1.8.5.3
Alexandre Courbot
2014-Feb-01 03:16 UTC
[Nouveau] [RFC 01/16] drm/nouveau: handle -EACCES runtime PM return code
pm_runtime_get*() may return -EACCESS to indicate a device does not have runtime PM enabled. This is the case when the nouveau.runpm parameter is set to 0, and is not an error in that context. Handle this case without failure. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 2 +- drivers/gpu/drm/nouveau/nouveau_connector.c | 2 +- drivers/gpu/drm/nouveau/nouveau_drm.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index 0e3270c..1caef1f 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -1048,7 +1048,7 @@ nouveau_crtc_set_config(struct drm_mode_set *set) /* get a pm reference here */ ret = pm_runtime_get_sync(dev->dev); - if (ret < 0) + if (ret < 0 && ret != -EACCES) return ret; ret = drm_crtc_helper_set_config(set); diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 1674882..cddef54 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -255,7 +255,7 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) } ret = pm_runtime_get_sync(connector->dev->dev); - if (ret < 0) + if (ret < 0 && ret != -EACCES) return conn_status; i2c = nouveau_connector_ddc_detect(connector, &nv_encoder); diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 98a22e6..23299ca 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -670,7 +670,7 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv) /* need to bring up power immediately if opening device */ ret = pm_runtime_get_sync(dev->dev); - if (ret < 0) + if (ret < 0 && ret != -EACCES) return ret; get_task_comm(tmpname, current); @@ -753,7 +753,7 @@ long nouveau_drm_ioctl(struct file *filp, dev = file_priv->minor->dev; ret = pm_runtime_get_sync(dev->dev); - if (ret < 0) + if (ret < 0 && ret != -EACCES) return ret; ret = drm_ioctl(filp, cmd, arg); -- 1.8.5.3
Alexandre Courbot
2014-Feb-01 03:16 UTC
[Nouveau] [RFC 02/16] drm/nouveau: basic support for platform devices
The T124 generation of Tegra GPUs uses the Kepler architecture and can thus be driven by Nouveau. However, they are declared as platform devices using the Device Tree, and Nouveau has a very strong dependency on PCI. This patch makes Nouveau core able to handle platform devices as well as PCI devices. Commonly-used PCI functions include resource range query and page mapping. These functions are abstracted so the correct bus type is used to perform them. Some PCI-dependent code is also disabled when probing a non-PCI device. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drivers/gpu/drm/nouveau/core/engine/device/base.c | 58 +++++++++++++++++++++- drivers/gpu/drm/nouveau/core/include/core/device.h | 27 ++++++++++ drivers/gpu/drm/nouveau/core/os.h | 1 + drivers/gpu/drm/nouveau/nouveau_abi16.c | 13 ++++- drivers/gpu/drm/nouveau/nouveau_bo.c | 22 ++++---- drivers/gpu/drm/nouveau/nouveau_display.c | 3 +- drivers/gpu/drm/nouveau/nouveau_drm.c | 53 ++++++++++++++------ drivers/gpu/drm/nouveau/nouveau_sysfs.c | 8 +-- drivers/gpu/drm/nouveau/nouveau_ttm.c | 31 +++++++----- 9 files changed, 170 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/nouveau/core/engine/device/base.c b/drivers/gpu/drm/nouveau/core/engine/device/base.c index dd01c6c..a6abb51 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/base.c @@ -131,8 +131,8 @@ nouveau_devobj_ctor(struct nouveau_object *parent, if (ret) return ret; - mmio_base = pci_resource_start(device->pdev, 0); - mmio_size = pci_resource_len(device->pdev, 0); + mmio_base = nv_device_resource_start(device, 0); + mmio_size = nv_device_resource_len(device, 0); /* translate api disable mask into internal mapping */ disable = args->debug0; @@ -446,6 +446,60 @@ nouveau_device_dtor(struct nouveau_object *object) nouveau_engine_destroy(&device->base); } +resource_size_t +nv_device_resource_start(struct nouveau_device *device, unsigned int bar) +{ + if (nv_device_is_pci(device)) { + return pci_resource_start(device->pdev, bar); + } else { + struct resource *res; + res = platform_get_resource(device->platformdev, + IORESOURCE_MEM, bar); + if (!res) + return 0; + return res->start; + } +} + +resource_size_t +nv_device_resource_len(struct nouveau_device *device, unsigned int bar) +{ + if (nv_device_is_pci(device)) { + return pci_resource_len(device->pdev, bar); + } else { + struct resource *res; + res = platform_get_resource(device->platformdev, + IORESOURCE_MEM, bar); + if (!res) + return 0; + return resource_size(res); + } +} + +dma_addr_t +nv_device_map_page(struct nouveau_device *device, struct page *page) { + dma_addr_t ret; + + if (nv_device_is_pci(device)) { + ret = pci_map_page(device->pdev, page, 0, PAGE_SIZE, + PCI_DMA_BIDIRECTIONAL); + if (pci_dma_mapping_error(device->pdev, ret)) + ret = 0; + } else { + ret = page_to_phys(page); + } + + return ret; +} + +void +nv_device_unmap_page(struct nouveau_device *device, dma_addr_t addr) +{ + if (nv_device_is_pci(device)) + pci_unmap_page(device->pdev, addr, PAGE_SIZE, + PCI_DMA_BIDIRECTIONAL); +} + static struct nouveau_oclass nouveau_device_oclass = { .handle = NV_ENGINE(DEVICE, 0x00), diff --git a/drivers/gpu/drm/nouveau/core/include/core/device.h b/drivers/gpu/drm/nouveau/core/include/core/device.h index 7b8ea22..23f4a25 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/device.h +++ b/drivers/gpu/drm/nouveau/core/include/core/device.h @@ -65,6 +65,7 @@ struct nouveau_device { struct list_head head; struct pci_dev *pdev; + struct platform_device *platformdev; u64 handle; const char *cfgopt; @@ -140,4 +141,30 @@ nv_device_match(struct nouveau_object *object, u16 dev, u16 ven, u16 sub) device->pdev->subsystem_device == sub; } +static inline bool +nv_device_is_pci(struct nouveau_device *device) +{ + return device->pdev != NULL; +} + +static inline struct device * +nv_device_base(struct nouveau_device *device) +{ + return nv_device_is_pci(device) ? &device->pdev->dev : + &device->platformdev->dev; +} + +resource_size_t +nv_device_resource_start(struct nouveau_device *device, unsigned int bar); + +resource_size_t +nv_device_resource_len(struct nouveau_device *device, unsigned int bar); + +dma_addr_t +nv_device_map_page(struct nouveau_device *device, struct page *page); + +void +nv_device_unmap_page(struct nouveau_device *device, dma_addr_t addr); + #endif + diff --git a/drivers/gpu/drm/nouveau/core/os.h b/drivers/gpu/drm/nouveau/core/os.h index 191e739..90a6c90 100644 --- a/drivers/gpu/drm/nouveau/core/os.h +++ b/drivers/gpu/drm/nouveau/core/os.h @@ -5,6 +5,7 @@ #include <linux/slab.h> #include <linux/mutex.h> #include <linux/pci.h> +#include <linux/platform_device.h> #include <linux/printk.h> #include <linux/bitops.h> #include <linux/firmware.h> diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c index 900fae0..a28422b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c @@ -179,12 +179,21 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS) getparam->value = device->chipset; break; case NOUVEAU_GETPARAM_PCI_VENDOR: - getparam->value = dev->pdev->vendor; + if (nv_device_is_pci(device)) + getparam->value = dev->pdev->vendor; + else + getparam->value = 0; break; case NOUVEAU_GETPARAM_PCI_DEVICE: - getparam->value = dev->pdev->device; + if (nv_device_is_pci(device)) + getparam->value = dev->pdev->device; + else + getparam->value = 0; break; case NOUVEAU_GETPARAM_BUS_TYPE: + if (!nv_device_is_pci(device)) + getparam->value = 3; + else if (drm_pci_device_is_agp(dev)) getparam->value = 0; else diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 488686d..f8d43cf 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1255,7 +1255,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) /* fallthrough, tiled memory */ case TTM_PL_VRAM: mem->bus.offset = mem->start << PAGE_SHIFT; - mem->bus.base = pci_resource_start(dev->pdev, 1); + mem->bus.base = nv_device_resource_start(nouveau_dev(dev), 1); mem->bus.is_iomem = true; if (nv_device(drm->device)->card_type >= NV_50) { struct nouveau_bar *bar = nouveau_bar(drm->device); @@ -1293,7 +1293,7 @@ nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo) struct nouveau_drm *drm = nouveau_bdev(bo->bdev); struct nouveau_bo *nvbo = nouveau_bo(bo); struct nouveau_device *device = nv_device(drm->device); - u32 mappable = pci_resource_len(device->pdev, 1) >> PAGE_SHIFT; + u32 mappable = nv_device_resource_len(device, 1) >> PAGE_SHIFT; int ret; /* as long as the bo isn't in vram, and isn't tiled, we've got @@ -1331,6 +1331,7 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm) { struct ttm_dma_tt *ttm_dma = (void *)ttm; struct nouveau_drm *drm; + struct nouveau_device *device; struct drm_device *dev; unsigned i; int r; @@ -1348,6 +1349,7 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm) } drm = nouveau_bdev(ttm->bdev); + device = nv_device(drm->device); dev = drm->dev; #if __OS_HAS_AGP @@ -1368,13 +1370,12 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm) } for (i = 0; i < ttm->num_pages; i++) { - ttm_dma->dma_address[i] = pci_map_page(dev->pdev, ttm->pages[i], - 0, PAGE_SIZE, - PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(dev->pdev, ttm_dma->dma_address[i])) { + ttm_dma->dma_address[i] = nv_device_map_page(device, + ttm->pages[i]); + if (ttm_dma->dma_address[i] == 0) { while (--i) { - pci_unmap_page(dev->pdev, ttm_dma->dma_address[i], - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + nv_device_unmap_page(device, + ttm_dma->dma_address[i]); ttm_dma->dma_address[i] = 0; } ttm_pool_unpopulate(ttm); @@ -1389,6 +1390,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) { struct ttm_dma_tt *ttm_dma = (void *)ttm; struct nouveau_drm *drm; + struct nouveau_device *device; struct drm_device *dev; unsigned i; bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); @@ -1397,6 +1399,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) return; drm = nouveau_bdev(ttm->bdev); + device = nv_device(drm->device); dev = drm->dev; #if __OS_HAS_AGP @@ -1415,8 +1418,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) for (i = 0; i < ttm->num_pages; i++) { if (ttm_dma->dma_address[i]) { - pci_unmap_page(dev->pdev, ttm_dma->dma_address[i], - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + nv_device_unmap_page(device, ttm_dma->dma_address[i]); } } diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index b4262ad..bc39241 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -339,6 +339,7 @@ int nouveau_display_create(struct drm_device *dev) { struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_device *device = nouveau_dev(dev); struct nouveau_display *disp; int ret, gen; @@ -379,7 +380,7 @@ nouveau_display_create(struct drm_device *dev) } dev->mode_config.funcs = &nouveau_mode_config_funcs; - dev->mode_config.fb_base = pci_resource_start(dev->pdev, 1); + dev->mode_config.fb_base = nv_device_resource_start(device, 1); dev->mode_config.min_width = 0; dev->mode_config.min_height = 0; diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 23299ca..4cba4d8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -81,7 +81,7 @@ module_param_named(runpm, nouveau_runtime_pm, int, 0400); static struct drm_driver driver; static u64 -nouveau_name(struct pci_dev *pdev) +nouveau_pci_name(struct pci_dev *pdev) { u64 name = (u64)pci_domain_nr(pdev->bus) << 32; name |= pdev->bus->number << 16; @@ -89,15 +89,30 @@ nouveau_name(struct pci_dev *pdev) return name | PCI_FUNC(pdev->devfn); } +static u64 +nouveau_platform_name(struct platform_device *pdev) +{ + return pdev->id; +} + +static u64 +nouveau_name(struct drm_device *dev) +{ + if (dev->pdev) + return nouveau_pci_name(dev->pdev); + else + return nouveau_platform_name(dev->platformdev); +} + static int -nouveau_cli_create(struct pci_dev *pdev, const char *name, +nouveau_cli_create(u64 name, const char *sname, int size, void **pcli) { struct nouveau_cli *cli; int ret; *pcli = NULL; - ret = nouveau_client_create_(name, nouveau_name(pdev), nouveau_config, + ret = nouveau_client_create_(sname, name, nouveau_config, nouveau_debug, size, pcli); cli = *pcli; if (ret) { @@ -281,8 +296,9 @@ static int nouveau_drm_probe(struct pci_dev *pdev, remove_conflicting_framebuffers(aper, "nouveaufb", boot); kfree(aper); - ret = nouveau_device_create(pdev, nouveau_name(pdev), pci_name(pdev), - nouveau_config, nouveau_debug, &device); + ret = nouveau_device_create(pdev, nouveau_pci_name(pdev), + pci_name(pdev), nouveau_config, + nouveau_debug, &device); if (ret) return ret; @@ -330,7 +346,8 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) struct nouveau_drm *drm; int ret; - ret = nouveau_cli_create(pdev, "DRM", sizeof(*drm), (void**)&drm); + ret = nouveau_cli_create(nouveau_name(dev), "DRM", sizeof(*drm), + (void **)&drm); if (ret) return ret; @@ -340,12 +357,13 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) INIT_LIST_HEAD(&drm->clients); spin_lock_init(&drm->tile.lock); - nouveau_get_hdmi_dev(dev); + if (pdev) + nouveau_get_hdmi_dev(dev); /* make sure AGP controller is in a consistent state before we * (possibly) execute vbios init tables (see nouveau_agp.h) */ - if (drm_pci_device_is_agp(dev) && dev->agp) { + if (pdev && drm_pci_device_is_agp(dev) && dev->agp) { /* dummy device object, doesn't init anything, but allows * agp code access to registers */ @@ -384,8 +402,10 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) if (nv_device(drm->device)->chipset == 0xc1) nv_mask(device, 0x00088080, 0x00000800, 0x00000000); - nouveau_vga_init(drm); - nouveau_agp_init(drm); + if (pdev) { + nouveau_vga_init(drm); + nouveau_agp_init(drm); + } if (device->card_type >= NV_50) { ret = nouveau_vm_new(nv_device(drm->device), 0, (1ULL << 40), @@ -398,9 +418,11 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) if (ret) goto fail_ttm; - ret = nouveau_bios_init(dev); - if (ret) - goto fail_bios; + if (pdev) { + ret = nouveau_bios_init(dev); + if (ret) + goto fail_bios; + } ret = nouveau_display_create(dev); if (ret) @@ -662,7 +684,6 @@ static int nouveau_pmops_thaw(struct device *dev) static int nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv) { - struct pci_dev *pdev = dev->pdev; struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_cli *cli; char name[32], tmpname[TASK_COMM_LEN]; @@ -676,7 +697,9 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv) get_task_comm(tmpname, current); snprintf(name, sizeof(name), "%s[%d]", tmpname, pid_nr(fpriv->pid)); - ret = nouveau_cli_create(pdev, name, sizeof(*cli), (void **)&cli); + ret = nouveau_cli_create(nouveau_name(dev), name, sizeof(*cli), + (void **)&cli); + if (ret) goto out_suspend; diff --git a/drivers/gpu/drm/nouveau/nouveau_sysfs.c b/drivers/gpu/drm/nouveau/nouveau_sysfs.c index 89201a1..75dda2b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sysfs.c +++ b/drivers/gpu/drm/nouveau/nouveau_sysfs.c @@ -30,7 +30,7 @@ static inline struct drm_device * drm_device(struct device *d) { - return pci_get_drvdata(to_pci_dev(d)); + return dev_get_drvdata(d); } #define snappendf(p,r,f,a...) do { \ @@ -132,9 +132,10 @@ nouveau_sysfs_fini(struct drm_device *dev) { struct nouveau_sysfs *sysfs = nouveau_sysfs(dev); struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_device *device = nv_device(drm->device); if (sysfs->ctrl) { - device_remove_file(&dev->pdev->dev, &dev_attr_pstate); + device_remove_file(nv_device_base(device), &dev_attr_pstate); nouveau_object_del(nv_object(drm), NVDRM_DEVICE, NVDRM_CONTROL); } @@ -146,6 +147,7 @@ int nouveau_sysfs_init(struct drm_device *dev) { struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_device *device = nv_device(drm->device); struct nouveau_sysfs *sysfs; int ret; @@ -156,7 +158,7 @@ nouveau_sysfs_init(struct drm_device *dev) ret = nouveau_object_new(nv_object(drm), NVDRM_DEVICE, NVDRM_CONTROL, NV_CONTROL_CLASS, NULL, 0, &sysfs->ctrl); if (ret == 0) - device_create_file(&dev->pdev->dev, &dev_attr_pstate); + device_create_file(nv_device_base(device), &dev_attr_pstate); return 0; } diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index d45d50d..9574f87 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -354,21 +354,26 @@ int nouveau_ttm_init(struct nouveau_drm *drm) { struct drm_device *dev = drm->dev; + struct nouveau_device *device = nv_device(drm->device); u32 bits; int ret; bits = nouveau_vmmgr(drm->device)->dma_bits; - if ( drm->agp.stat == ENABLED || - !pci_dma_supported(dev->pdev, DMA_BIT_MASK(bits))) - bits = 32; - - ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(bits)); - if (ret) - return ret; - - ret = pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(bits)); - if (ret) - pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(32)); + if (nv_device_is_pci(device)) { + if (drm->agp.stat == ENABLED || + !pci_dma_supported(dev->pdev, DMA_BIT_MASK(bits))) + bits = 32; + + ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(bits)); + if (ret) + return ret; + + ret = pci_set_consistent_dma_mask(dev->pdev, + DMA_BIT_MASK(bits)); + if (ret) + pci_set_consistent_dma_mask(dev->pdev, + DMA_BIT_MASK(32)); + } ret = nouveau_ttm_global_init(drm); if (ret) @@ -394,8 +399,8 @@ nouveau_ttm_init(struct nouveau_drm *drm) return ret; } - drm->ttm.mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 1), - pci_resource_len(dev->pdev, 1)); + drm->ttm.mtrr = arch_phys_wc_add(nv_device_resource_start(device, 1), + nv_device_resource_len(device, 1)); /* GART init */ if (drm->agp.stat != ENABLED) { -- 1.8.5.3
Alexandre Courbot
2014-Feb-01 03:16 UTC
[Nouveau] [RFC 03/16] drm/nouveau: add platform device probing function
Add a nouveau_drm_platform_probe() function that probes a Nouveau platform device and registers it using drm_platform_init(). Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drivers/gpu/drm/nouveau/core/engine/device/base.c | 34 ++++++++++++++++++++++ .../gpu/drm/nouveau/core/include/engine/device.h | 10 +++++++ drivers/gpu/drm/nouveau/nouveau_drm.c | 19 ++++++++++++ 3 files changed, 63 insertions(+) diff --git a/drivers/gpu/drm/nouveau/core/engine/device/base.c b/drivers/gpu/drm/nouveau/core/engine/device/base.c index a6abb51..ba6c2f2 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/base.c @@ -543,3 +543,37 @@ done: mutex_unlock(&nv_devices_mutex); return ret; } + +int +nouveau_device_platform_create_(struct platform_device *pdev, u64 name, + const char *sname, const char *cfg, + const char *dbg, int length, void **pobject) +{ + struct nouveau_device *device; + int ret = -EEXIST; + + mutex_lock(&nv_devices_mutex); + list_for_each_entry(device, &nv_devices, head) { + if (device->handle == name) + goto done; + } + + ret = nouveau_engine_create_(NULL, NULL, &nouveau_device_oclass, true, + "DEVICE", "device", length, pobject); + device = *pobject; + if (ret) + goto done; + + device->platformdev = pdev; + device->handle = name; + device->cfgopt = cfg; + device->dbgopt = dbg; + device->name = sname; + + nv_subdev(device)->debug = nouveau_dbgopt(device->dbgopt, "DEVICE"); + nv_engine(device)->sclass = nouveau_device_sclass; + list_add(&device->head, &nv_devices); +done: + mutex_unlock(&nv_devices_mutex); + return ret; +} diff --git a/drivers/gpu/drm/nouveau/core/include/engine/device.h b/drivers/gpu/drm/nouveau/core/include/engine/device.h index b3dd2c4..90056190 100644 --- a/drivers/gpu/drm/nouveau/core/include/engine/device.h +++ b/drivers/gpu/drm/nouveau/core/include/engine/device.h @@ -3,12 +3,22 @@ #include <core/device.h> +struct platform_device; + #define nouveau_device_create(p,n,s,c,d,u) \ nouveau_device_create_((p), (n), (s), (c), (d), sizeof(**u), (void **)u) int nouveau_device_create_(struct pci_dev *, u64 name, const char *sname, const char *cfg, const char *dbg, int, void **); +#define nouveau_device_platform_create(p,n,s,c,d,u) \ + nouveau_device_platform_create_((p), (n), (s), (c), (d), sizeof(**u), \ + (void **)u) + +int nouveau_device_platform_create_(struct platform_device *pdev, u64 name, + const char *sname, const char *cfg, + const char *dbg, int, void **); + int nv04_identify(struct nouveau_device *); int nv10_identify(struct nouveau_device *); int nv20_identify(struct nouveau_device *); diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 4cba4d8..8d55a50 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -986,6 +986,25 @@ nouveau_drm_pci_driver = { .driver.pm = &nouveau_pm_ops, }; + +int nouveau_drm_platform_probe(struct platform_device *pdev) +{ + struct nouveau_device *device; + int ret; + + ret = nouveau_device_platform_create(pdev, nouveau_platform_name(pdev), + dev_name(&pdev->dev), nouveau_config, + nouveau_debug, &device); + + ret = drm_platform_init(&driver, pdev); + if (ret) { + nouveau_object_ref(NULL, (struct nouveau_object **)&device); + return ret; + } + + return ret; +} + static int __init nouveau_drm_init(void) { -- 1.8.5.3
Alexandre Courbot
2014-Feb-01 03:16 UTC
[Nouveau] [RFC 04/16] drm/nouveau/fifo: support platform devices
Remove PCI-dependent code so the FIFO engine can also handle platform devices. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drivers/gpu/drm/nouveau/core/engine/fifo/base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/base.c b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c index d3ec436d9..6f9041c 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c @@ -86,7 +86,7 @@ nouveau_fifo_channel_create_(struct nouveau_object *parent, } /* map fifo control registers */ - chan->user = ioremap(pci_resource_start(device->pdev, bar) + addr + + chan->user = ioremap(nv_device_resource_start(device, bar) + addr + (chan->chid * size), size); if (!chan->user) return -EFAULT; -- 1.8.5.3
Alexandre Courbot
2014-Feb-01 03:16 UTC
[Nouveau] [RFC 05/16] drm/nouveau/bar: support platform devices
Remove PCI-dependent code so the BAR core can also handle platform devices. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drivers/gpu/drm/nouveau/core/subdev/bar/base.c | 4 ++-- drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c | 4 ++-- drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c | 15 +++++++-------- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/base.c b/drivers/gpu/drm/nouveau/core/subdev/bar/base.c index 7098ddd..bdf5941 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bar/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bar/base.c @@ -118,8 +118,8 @@ nouveau_bar_create_(struct nouveau_object *parent, if (ret) return ret; - bar->iomem = ioremap(pci_resource_start(device->pdev, 3), - pci_resource_len(device->pdev, 3)); + bar->iomem = ioremap(nv_device_resource_start(device, 3), + nv_device_resource_len(device, 3)); return 0; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c index 090d594..baa2b62 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c @@ -139,7 +139,7 @@ nv50_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine, /* BAR3 */ start = 0x0100000000ULL; - limit = start + pci_resource_len(device->pdev, 3); + limit = start + nv_device_resource_len(device, 3); ret = nouveau_vm_new(device, start, limit, start, &vm); if (ret) @@ -173,7 +173,7 @@ nv50_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine, /* BAR1 */ start = 0x0000000000ULL; - limit = start + pci_resource_len(device->pdev, 1); + limit = start + nv_device_resource_len(device, 1); ret = nouveau_vm_new(device, start, limit--, start, &vm); if (ret) diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c index bac5e75..3f30db6 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c @@ -84,7 +84,6 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_object **pobject) { struct nouveau_device *device = nv_device(parent); - struct pci_dev *pdev = device->pdev; struct nvc0_bar_priv *priv; struct nouveau_gpuobj *mem; struct nouveau_vm *vm; @@ -107,14 +106,14 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - ret = nouveau_vm_new(device, 0, pci_resource_len(pdev, 3), 0, &vm); + ret = nouveau_vm_new(device, 0, nv_device_resource_len(device, 3), 0, &vm); if (ret) return ret; atomic_inc(&vm->engref[NVDEV_SUBDEV_BAR]); ret = nouveau_gpuobj_new(nv_object(priv), NULL, - (pci_resource_len(pdev, 3) >> 12) * 8, + (nv_device_resource_len(device, 3) >> 12) * 8, 0x1000, NVOBJ_FLAG_ZERO_ALLOC, &vm->pgt[0].obj[0]); vm->pgt[0].refcount[0] = 1; @@ -128,8 +127,8 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[0].pgd->addr)); nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[0].pgd->addr)); - nv_wo32(mem, 0x0208, lower_32_bits(pci_resource_len(pdev, 3) - 1)); - nv_wo32(mem, 0x020c, upper_32_bits(pci_resource_len(pdev, 3) - 1)); + nv_wo32(mem, 0x0208, lower_32_bits(nv_device_resource_len(device, 3) - 1)); + nv_wo32(mem, 0x020c, upper_32_bits(nv_device_resource_len(device, 3) - 1)); /* BAR1 */ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0, 0, @@ -143,7 +142,7 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - ret = nouveau_vm_new(device, 0, pci_resource_len(pdev, 1), 0, &vm); + ret = nouveau_vm_new(device, 0, nv_device_resource_len(device, 1), 0, &vm); if (ret) return ret; @@ -156,8 +155,8 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[1].pgd->addr)); nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[1].pgd->addr)); - nv_wo32(mem, 0x0208, lower_32_bits(pci_resource_len(pdev, 1) - 1)); - nv_wo32(mem, 0x020c, upper_32_bits(pci_resource_len(pdev, 1) - 1)); + nv_wo32(mem, 0x0208, lower_32_bits(nv_device_resource_len(device, 1) - 1)); + nv_wo32(mem, 0x020c, upper_32_bits(nv_device_resource_len(device, 1) - 1)); priv->base.alloc = nouveau_bar_alloc; priv->base.kmap = nvc0_bar_kmap; -- 1.8.5.3
Alexandre Courbot
2014-Feb-01 03:16 UTC
[Nouveau] [RFC 06/16] drm/nouveau/bar: only ioremap BAR3 if it exists
Some chips that use system memory exclusively (e.g. GK20A) do not expose 2 BAR regions. For them only BAR1 exists, and it should be used for USERD mapping. Do not map BAR3 if its resource does not exist. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drivers/gpu/drm/nouveau/core/subdev/bar/base.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/base.c b/drivers/gpu/drm/nouveau/core/subdev/bar/base.c index bdf5941..d713eeb 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bar/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bar/base.c @@ -110,6 +110,7 @@ nouveau_bar_create_(struct nouveau_object *parent, { struct nouveau_device *device = nv_device(parent); struct nouveau_bar *bar; + bool has_bar3 = nv_device_resource_len(device, 3) != 0; int ret; ret = nouveau_subdev_create_(parent, engine, oclass, 0, "BARCTL", @@ -118,8 +119,10 @@ nouveau_bar_create_(struct nouveau_object *parent, if (ret) return ret; - bar->iomem = ioremap(nv_device_resource_start(device, 3), - nv_device_resource_len(device, 3)); + if (has_bar3) + bar->iomem = ioremap(nv_device_resource_start(device, 3), + nv_device_resource_len(device, 3)); + return 0; } -- 1.8.5.3
Alexandre Courbot
2014-Feb-01 03:16 UTC
[Nouveau] [RFC 07/16] drm/nouveau/bar/nvc0: support chips without BAR3
Adapt the NVC0 BAR driver to make it able to support chips that do not expose a BAR3. When this happens, BAR1 is then used for USERD mapping and the BAR alloc() functions is disabled, making GPU objects unable to rely on BAR for data access and falling back to PRAMIN. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c | 115 +++++++++++++------------ 1 file changed, 61 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c index 3f30db6..c2bb0e5 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c @@ -79,87 +79,88 @@ nvc0_bar_unmap(struct nouveau_bar *bar, struct nouveau_vma *vma) } static int -nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 size, - struct nouveau_object **pobject) +nvc0_bar_init_vm(struct nvc0_bar_priv *priv, int nr, int bar) { - struct nouveau_device *device = nv_device(parent); - struct nvc0_bar_priv *priv; + struct nouveau_device *device = nv_device(&priv->base); struct nouveau_gpuobj *mem; struct nouveau_vm *vm; + resource_size_t bar_len; int ret; - ret = nouveau_bar_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - /* BAR3 */ ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0, 0, - &priv->bar[0].mem); - mem = priv->bar[0].mem; + &priv->bar[nr].mem); + mem = priv->bar[nr].mem; if (ret) return ret; ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0, 0, - &priv->bar[0].pgd); + &priv->bar[nr].pgd); if (ret) return ret; - ret = nouveau_vm_new(device, 0, nv_device_resource_len(device, 3), 0, &vm); + bar_len = nv_device_resource_len(device, bar); + + ret = nouveau_vm_new(device, 0, bar_len, 0, &vm); if (ret) return ret; atomic_inc(&vm->engref[NVDEV_SUBDEV_BAR]); - ret = nouveau_gpuobj_new(nv_object(priv), NULL, - (nv_device_resource_len(device, 3) >> 12) * 8, - 0x1000, NVOBJ_FLAG_ZERO_ALLOC, - &vm->pgt[0].obj[0]); - vm->pgt[0].refcount[0] = 1; - if (ret) - return ret; + /* + * Bootstrap page table lookup. + */ + if (bar == 3) { + ret = nouveau_gpuobj_new(nv_object(priv), NULL, + (bar_len >> 12) * 8, 0x1000, + NVOBJ_FLAG_ZERO_ALLOC, + &vm->pgt[0].obj[0]); + vm->pgt[0].refcount[0] = 1; + if (ret) + return ret; + } - ret = nouveau_vm_ref(vm, &priv->bar[0].vm, priv->bar[0].pgd); + ret = nouveau_vm_ref(vm, &priv->bar[nr].vm, priv->bar[nr].pgd); nouveau_vm_ref(NULL, &vm, NULL); if (ret) return ret; - nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[0].pgd->addr)); - nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[0].pgd->addr)); - nv_wo32(mem, 0x0208, lower_32_bits(nv_device_resource_len(device, 3) - 1)); - nv_wo32(mem, 0x020c, upper_32_bits(nv_device_resource_len(device, 3) - 1)); + nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[nr].pgd->addr)); + nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[nr].pgd->addr)); + nv_wo32(mem, 0x0208, lower_32_bits(bar_len - 1)); + nv_wo32(mem, 0x020c, upper_32_bits(bar_len - 1)); - /* BAR1 */ - ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0, 0, - &priv->bar[1].mem); - mem = priv->bar[1].mem; - if (ret) - return ret; + return 0; +} - ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0, 0, - &priv->bar[1].pgd); - if (ret) - return ret; +static int +nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nouveau_device *device = nv_device(parent); + struct nvc0_bar_priv *priv; + bool has_bar3 = nv_device_resource_len(device, 3) != 0; + int ret; - ret = nouveau_vm_new(device, 0, nv_device_resource_len(device, 1), 0, &vm); + ret = nouveau_bar_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); if (ret) return ret; - atomic_inc(&vm->engref[NVDEV_SUBDEV_BAR]); + /* BAR3 */ + if (has_bar3) { + ret = nvc0_bar_init_vm(priv, 0, 3); + if (ret) + return ret; + priv->base.alloc = nouveau_bar_alloc; + priv->base.kmap = nvc0_bar_kmap; + } - ret = nouveau_vm_ref(vm, &priv->bar[1].vm, priv->bar[1].pgd); - nouveau_vm_ref(NULL, &vm, NULL); + /* BAR1 */ + ret = nvc0_bar_init_vm(priv, 1, 1); if (ret) return ret; - nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[1].pgd->addr)); - nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[1].pgd->addr)); - nv_wo32(mem, 0x0208, lower_32_bits(nv_device_resource_len(device, 1) - 1)); - nv_wo32(mem, 0x020c, upper_32_bits(nv_device_resource_len(device, 1) - 1)); - - priv->base.alloc = nouveau_bar_alloc; - priv->base.kmap = nvc0_bar_kmap; priv->base.umap = nvc0_bar_umap; priv->base.unmap = nvc0_bar_unmap; priv->base.flush = nv84_bar_flush; @@ -176,12 +177,16 @@ nvc0_bar_dtor(struct nouveau_object *object) nouveau_gpuobj_ref(NULL, &priv->bar[1].pgd); nouveau_gpuobj_ref(NULL, &priv->bar[1].mem); - if (priv->bar[0].vm) { - nouveau_gpuobj_ref(NULL, &priv->bar[0].vm->pgt[0].obj[0]); - nouveau_vm_ref(NULL, &priv->bar[0].vm, priv->bar[0].pgd); + if (priv->bar[0].mem) { + if (priv->bar[0].vm) { + nouveau_gpuobj_ref(NULL, + &priv->bar[0].vm->pgt[0].obj[0]); + nouveau_vm_ref(NULL, &priv->bar[0].vm, + priv->bar[0].pgd); + } + nouveau_gpuobj_ref(NULL, &priv->bar[0].pgd); + nouveau_gpuobj_ref(NULL, &priv->bar[0].mem); } - nouveau_gpuobj_ref(NULL, &priv->bar[0].pgd); - nouveau_gpuobj_ref(NULL, &priv->bar[0].mem); nouveau_bar_destroy(&priv->base); } @@ -201,7 +206,9 @@ nvc0_bar_init(struct nouveau_object *object) nv_mask(priv, 0x100c80, 0x00000001, 0x00000000); nv_wr32(priv, 0x001704, 0x80000000 | priv->bar[1].mem->addr >> 12); - nv_wr32(priv, 0x001714, 0xc0000000 | priv->bar[0].mem->addr >> 12); + if (priv->bar[0].mem) + nv_wr32(priv, 0x001714, + 0xc0000000 | priv->bar[0].mem->addr >> 12); return 0; } -- 1.8.5.3
Alexandre Courbot
2014-Feb-01 03:16 UTC
[Nouveau] [RFC 08/16] drm/nouveau/mc: support platform devices
Use abstracted resource query functions, and obtain the IRQ from the correct bus. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drivers/gpu/drm/nouveau/core/include/subdev/mc.h | 1 + drivers/gpu/drm/nouveau/core/subdev/mc/base.c | 43 +++++++++++++++--------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h index adc88b7..7c551b5 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h @@ -12,6 +12,7 @@ struct nouveau_mc_intr { struct nouveau_mc { struct nouveau_subdev base; bool use_msi; + unsigned int irq; }; static inline struct nouveau_mc * diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c index b4b9943..081fd96 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c @@ -93,8 +93,8 @@ _nouveau_mc_dtor(struct nouveau_object *object) { struct nouveau_device *device = nv_device(object); struct nouveau_mc *pmc = (void *)object; - free_irq(device->pdev->irq, pmc); - if (pmc->use_msi) + free_irq(pmc->irq, pmc); + if (nv_device_is_pci(device) && pmc->use_msi) pci_disable_msi(device->pdev); nouveau_subdev_destroy(&pmc->base); } @@ -114,22 +114,25 @@ nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - 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: break; /* reported broken, nv also disable it */ - default: - pmc->use_msi = true; + 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 = nouveau_boolopt(device->cfgopt, "NvMSI", pmc->use_msi); - if (pmc->use_msi && oclass->msi_rearm) { + if (nv_device_is_pci(device) && 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"); @@ -139,8 +142,18 @@ nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine, pmc->use_msi = false; } - ret = request_irq(device->pdev->irq, nouveau_mc_intr, - IRQF_SHARED, "nouveau", pmc); + if (nv_device_is_pci(device)) { + pmc->irq = device->pdev->irq; + } else { + int irq = platform_get_irq_byname(device->platformdev, "stall"); + if (irq < 0) + return irq; + pmc->irq = irq; + } + + ret = request_irq(pmc->irq, nouveau_mc_intr, IRQF_SHARED, "nouveau", + pmc); + if (ret < 0) return ret; -- 1.8.5.3
Alexandre Courbot
2014-Feb-01 03:16 UTC
[Nouveau] [RFC 09/16] drm/nouveau/fb: support platform devices
Use abstracted resource query functions to allow FB core to handle both PCI and platform devices. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c index 45470e1..0670ae3 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c @@ -70,8 +70,7 @@ nvc0_fb_dtor(struct nouveau_object *object) struct nvc0_fb_priv *priv = (void *)object; if (priv->r100c10_page) { - pci_unmap_page(device->pdev, priv->r100c10, PAGE_SIZE, - PCI_DMA_BIDIRECTIONAL); + nv_device_unmap_page(device, priv->r100c10); __free_page(priv->r100c10_page); } @@ -94,10 +93,8 @@ nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO); if (priv->r100c10_page) { - priv->r100c10 = pci_map_page(device->pdev, priv->r100c10_page, - 0, PAGE_SIZE, - PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(device->pdev, priv->r100c10)) + priv->r100c10 = nv_device_map_page(device, priv->r100c10_page); + if (!priv->r100c10) return -EFAULT; } -- 1.8.5.3
Alexandre Courbot
2014-Feb-01 03:16 UTC
[Nouveau] [RFC 10/16] drm/nouveau/timer: skip calibration on GK20A
GK20A's timer is directly attached to the system timer and cannot be calibrated. Skip the calibration phase on that chip since the corresponding registers do not exist. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c index c0bdd10..822fe0d 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c @@ -185,6 +185,10 @@ nv04_timer_init(struct nouveau_object *object) if (ret) return ret; + /* gk20a does not have the calibration registers */ + if (device->chipset == 0xea) + goto skip_clk_init; + /* aim for 31.25MHz, which gives us nanosecond timestamps */ d = 1000000 / 32; @@ -235,20 +239,23 @@ nv04_timer_init(struct nouveau_object *object) d >>= 1; } - /* restore the time before suspend */ - lo = priv->suspend_time; - hi = (priv->suspend_time >> 32); - nv_debug(priv, "input frequency : %dHz\n", f); nv_debug(priv, "input multiplier: %d\n", m); nv_debug(priv, "numerator : 0x%08x\n", n); nv_debug(priv, "denominator : 0x%08x\n", d); nv_debug(priv, "timer frequency : %dHz\n", (f * m) * d / n); - nv_debug(priv, "time low : 0x%08x\n", lo); - nv_debug(priv, "time high : 0x%08x\n", hi); nv_wr32(priv, NV04_PTIMER_NUMERATOR, n); nv_wr32(priv, NV04_PTIMER_DENOMINATOR, d); + +skip_clk_init: + /* restore the time before suspend */ + lo = priv->suspend_time; + hi = (priv->suspend_time >> 32); + + nv_debug(priv, "time low : 0x%08x\n", lo); + nv_debug(priv, "time high : 0x%08x\n", hi); + nv_wr32(priv, NV04_PTIMER_INTR_0, 0xffffffff); nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000); nv_wr32(priv, NV04_PTIMER_TIME_1, hi); -- 1.8.5.3
Alexandre Courbot
2014-Feb-01 03:16 UTC
[Nouveau] [RFC 11/16] drm/nouveau/fifo: allocate usermem as needed
Memory was always allocated for 4096 channels. Change this to allocate what we actually need according to the number of channels we use. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c index 54c1b5b..dbc3ff6 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c @@ -852,8 +852,8 @@ nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; } - ret = nouveau_gpuobj_new(nv_object(priv), NULL, 4096 * 0x200, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC, &priv->user.mem); + ret = nouveau_gpuobj_new(nv_object(priv), NULL, impl->channels * 0x200, + 0x1000, NVOBJ_FLAG_ZERO_ALLOC, &priv->user.mem); if (ret) return ret; -- 1.8.5.3
Alexandre Courbot
2014-Feb-01 03:16 UTC
[Nouveau] [RFC 12/16] drm/nouveau/fifo: add GK20A support
GK20A's FIFO is compatible with NVE0, but only features 128 channels and 1 runlist. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drivers/gpu/drm/nouveau/Makefile | 1 + drivers/gpu/drm/nouveau/core/engine/fifo/nve0.h | 1 + drivers/gpu/drm/nouveau/core/engine/fifo/nvea.c | 27 ++++++++++++++++++++++ drivers/gpu/drm/nouveau/core/include/engine/fifo.h | 1 + 4 files changed, 30 insertions(+) create mode 100644 drivers/gpu/drm/nouveau/core/engine/fifo/nvea.c diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index e88145b..6c4b76d 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -236,6 +236,7 @@ nouveau-y += core/engine/fifo/nv50.o nouveau-y += core/engine/fifo/nv84.o nouveau-y += core/engine/fifo/nvc0.o nouveau-y += core/engine/fifo/nve0.o +nouveau-y += core/engine/fifo/nvea.o nouveau-y += core/engine/fifo/nv108.o nouveau-y += core/engine/graph/ctxnv40.o nouveau-y += core/engine/graph/ctxnv50.o diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.h b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.h index 014344e..e96b32b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.h +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.h @@ -8,6 +8,7 @@ int nve0_fifo_ctor(struct nouveau_object *, struct nouveau_object *, struct nouveau_object **); void nve0_fifo_dtor(struct nouveau_object *); int nve0_fifo_init(struct nouveau_object *); +int nve0_fifo_fini(struct nouveau_object *, bool); struct nve0_fifo_impl { struct nouveau_oclass base; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvea.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvea.c new file mode 100644 index 0000000..16f8905 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvea.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include "nve0.h" + +struct nouveau_oclass * +nvea_fifo_oclass = &(struct nve0_fifo_impl) { + .base.handle = NV_ENGINE(FIFO, 0xea), + .base.ofuncs = &(struct nouveau_ofuncs) { + .ctor = nve0_fifo_ctor, + .dtor = nve0_fifo_dtor, + .init = nve0_fifo_init, + .fini = nve0_fifo_fini, + }, + .channels = 128, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/include/engine/fifo.h b/drivers/gpu/drm/nouveau/core/include/engine/fifo.h index 26b6b2b..823356f 100644 --- a/drivers/gpu/drm/nouveau/core/include/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/core/include/engine/fifo.h @@ -109,6 +109,7 @@ extern struct nouveau_oclass *nv50_fifo_oclass; extern struct nouveau_oclass *nv84_fifo_oclass; extern struct nouveau_oclass *nvc0_fifo_oclass; extern struct nouveau_oclass *nve0_fifo_oclass; +extern struct nouveau_oclass *nvea_fifo_oclass; extern struct nouveau_oclass *nv108_fifo_oclass; void nv04_fifo_intr(struct nouveau_subdev *); -- 1.8.5.3
Alexandre Courbot
2014-Feb-01 03:16 UTC
[Nouveau] [RFC 13/16] drm/nouveau/ibus: add GK20A support
Add support for initializing the priv ring of GK20A. This is done by the BIOS on desktop GPUs, but needs to be done by hand on Tegra. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drivers/gpu/drm/nouveau/Makefile | 1 + drivers/gpu/drm/nouveau/core/include/subdev/ibus.h | 1 + drivers/gpu/drm/nouveau/core/subdev/ibus/nvea.c | 108 +++++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 drivers/gpu/drm/nouveau/core/subdev/ibus/nvea.c diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 6c4b76d..3548fcd 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -132,6 +132,7 @@ nouveau-y += core/subdev/i2c/nv94.o nouveau-y += core/subdev/i2c/nvd0.o nouveau-y += core/subdev/ibus/nvc0.o nouveau-y += core/subdev/ibus/nve0.o +nouveau-y += core/subdev/ibus/nvea.o nouveau-y += core/subdev/instmem/base.o nouveau-y += core/subdev/instmem/nv04.o nouveau-y += core/subdev/instmem/nv40.o diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/ibus.h b/drivers/gpu/drm/nouveau/core/include/subdev/ibus.h index 88814f1..056a42f 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/ibus.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/ibus.h @@ -30,5 +30,6 @@ nouveau_ibus(void *obj) extern struct nouveau_oclass nvc0_ibus_oclass; extern struct nouveau_oclass nve0_ibus_oclass; +extern struct nouveau_oclass nvea_ibus_oclass; #endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/ibus/nvea.c b/drivers/gpu/drm/nouveau/core/subdev/ibus/nvea.c new file mode 100644 index 0000000..0bcd281 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/ibus/nvea.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include <subdev/ibus.h> + +struct nvea_ibus_priv { + struct nouveau_ibus base; +}; + +static void +nvea_ibus_init_priv_ring(struct nvea_ibus_priv *priv) +{ + u32 data; + + data = nv_rd32(priv, 0x137250); + data &= (~0x3f); + nv_wr32(priv, 0x137250, data); + + nv_mask(priv, 0x000200, 0x20, 0); + udelay(20); + nv_mask(priv, 0x000200, 0x20, 0x20); + + nv_wr32(priv, 0x12004c, 0x4); + nv_wr32(priv, 0x122204, 0x2); + nv_rd32(priv, 0x122204); +} + +static void +nvea_ibus_intr(struct nouveau_subdev *subdev) +{ + struct nvea_ibus_priv *priv = (void *)subdev; + u32 status0 = nv_rd32(priv, 0x120058); + s32 retry = 100; + u32 command; + + if (status0 & 0x7) { + nv_debug(priv, "resetting priv ring\n"); + nvea_ibus_init_priv_ring(priv); + } + + /* Acknowledge interrupt */ + command = nv_rd32(priv, 0x0012004c); + command |= 0x2; + nv_wr32(priv, 0x0012004c, command); + + while (--retry >= 0) { + command = nv_rd32(priv, 0x12004c) & 0x3f; + if (command == 0) + break; + } + + if (retry < 0) + nv_debug(priv, "timeout waiting for ringmaster ack\n"); +} + +static int +nvea_ibus_init(struct nouveau_object *object) +{ + struct nvea_ibus_priv *priv = (void *)object; + int ret; + + ret = _nouveau_ibus_init(object); + if (ret) + return ret; + + nvea_ibus_init_priv_ring(priv); + + return 0; +} + +static int +nvea_ibus_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) +{ + struct nvea_ibus_priv *priv; + int ret; + + ret = nouveau_ibus_create(parent, engine, oclass, &priv); + *pobject = nv_object(priv); + if (ret) + return ret; + + nv_subdev(priv)->intr = nvea_ibus_intr; + return 0; +} + +struct nouveau_oclass +nvea_ibus_oclass = { + .handle = NV_SUBDEV(IBUS, 0xea), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvea_ibus_ctor, + .dtor = _nouveau_ibus_dtor, + .init = nvea_ibus_init, + .fini = _nouveau_ibus_fini, + }, +}; -- 1.8.5.3
Alexandre Courbot
2014-Feb-01 03:16 UTC
[Nouveau] [RFC 14/16] drm/nouveau/fb: add GK20A support
Add a clumsy-but-working FB support for GK20A. This chip only uses system memory, so we allocate a big chunk using CMA and let the existing memory managers work on it. A better future design would be to allocate objects directly from system memory without having to suffer from the limitations of a large, contiguous pool. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drivers/gpu/drm/nouveau/Makefile | 2 + drivers/gpu/drm/nouveau/core/include/subdev/fb.h | 1 + drivers/gpu/drm/nouveau/core/subdev/fb/nvea.c | 28 ++++++++++ drivers/gpu/drm/nouveau/core/subdev/fb/priv.h | 1 + drivers/gpu/drm/nouveau/core/subdev/fb/ramnvea.c | 67 ++++++++++++++++++++++++ 5 files changed, 99 insertions(+) create mode 100644 drivers/gpu/drm/nouveau/core/subdev/fb/nvea.c create mode 100644 drivers/gpu/drm/nouveau/core/subdev/fb/ramnvea.c diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 3548fcd..d9fe3e6 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -100,6 +100,7 @@ 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/nvea.o nouveau-y += core/subdev/fb/ramnv04.o nouveau-y += core/subdev/fb/ramnv10.o nouveau-y += core/subdev/fb/ramnv1a.o @@ -114,6 +115,7 @@ 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/ramnvea.o nouveau-y += core/subdev/fb/sddr3.o nouveau-y += core/subdev/fb/gddr5.o nouveau-y += core/subdev/gpio/base.o diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h index d7ecafb..3905816 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h @@ -105,6 +105,7 @@ extern struct nouveau_oclass *nvaa_fb_oclass; extern struct nouveau_oclass *nvaf_fb_oclass; extern struct nouveau_oclass *nvc0_fb_oclass; extern struct nouveau_oclass *nve0_fb_oclass; +extern struct nouveau_oclass *nvea_fb_oclass; #include <subdev/bios/ramcfg.h> diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvea.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvea.c new file mode 100644 index 0000000..5ff6029 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvea.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include "nvc0.h" + +struct nouveau_oclass * +nvea_fb_oclass = &(struct nouveau_fb_impl) { + .base.handle = NV_SUBDEV(FB, 0xea), + .base.ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvc0_fb_ctor, + .dtor = nvc0_fb_dtor, + .init = nvc0_fb_init, + .fini = _nouveau_fb_fini, + }, + .memtype = nvc0_fb_memtype_valid, + .ram = &nvea_ram_oclass, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h b/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h index edaf95d..0b95a25 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h @@ -32,6 +32,7 @@ extern struct nouveau_oclass nva3_ram_oclass; extern struct nouveau_oclass nvaa_ram_oclass; extern struct nouveau_oclass nvc0_ram_oclass; extern struct nouveau_oclass nve0_ram_oclass; +extern struct nouveau_oclass nvea_ram_oclass; int nouveau_sddr3_calc(struct nouveau_ram *ram); int nouveau_gddr5_calc(struct nouveau_ram *ram, bool nuts); diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvea.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvea.c new file mode 100644 index 0000000..3038e08 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvea.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +/* + * TODO replace this CMA-requiring horror with a proper allocator for GPU + * objects in main memory. But for the moment it does the job and can reuse some + * of the nvc0 functions. + */ + +#include "nvc0.h" + +#include <linux/dma-mapping.h> + +static int +nvea_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 datasize, + struct nouveau_object **pobject) +{ + struct nouveau_fb *pfb = nouveau_fb(parent); + struct nouveau_ram *ram; + void *vram; + dma_addr_t dma_handle; + int ret; + + ret = nouveau_ram_create(parent, engine, oclass, &ram); + *pobject = nv_object(ram); + if (ret) + return ret; + + ram->type = NV_MEM_TYPE_STOLEN; + /* Use a fixed size of 64MB for now */ + ram->size = 0x4000000; + ram->stolen = (u64)0x00000000; + vram = dma_alloc_coherent(nv_device_base(nv_device(parent)), ram->size, + &dma_handle, GFP_KERNEL); + if (!vram) + return -ENOMEM; + + ret = nouveau_mm_init(&pfb->vram, dma_handle >> 12, ram->size >> 12, 1); + if (ret) + return ret; + + ram->get = nvc0_ram_get; + ram->put = nvc0_ram_put; + return 0; +} + +struct nouveau_oclass +nvea_ram_oclass = { + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nvea_ram_ctor, + .dtor = _nouveau_ram_dtor, + .init = _nouveau_ram_init, + .fini = _nouveau_ram_fini, + }, +}; -- 1.8.5.3
Alexandre Courbot
2014-Feb-01 03:16 UTC
[Nouveau] [RFC 15/16] drm/nouveau: support GK20A in nouveau_accel_init()
GK20A does not embed a dedicated COPY engine and thus cannot allocate the copy channel that nouveau_accel_init() attempts to create. It also lacks any display hardware, so the creation of a software channel does not apply neither. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drivers/gpu/drm/nouveau/nouveau_drm.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 8d55a50..87bdf04 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -171,6 +171,11 @@ nouveau_accel_init(struct nouveau_drm *drm) return; } + if (device->chipset == 0xea) { + /* gk20a does not have CE0/CE1 */ + arg0 = NVE0_CHANNEL_IND_ENGINE_GR; + arg1 = 1; + } else if (device->card_type >= NV_E0) { ret = nouveau_channel_new(drm, &drm->client, NVDRM_DEVICE, NVDRM_CHAN + 1, @@ -207,6 +212,10 @@ nouveau_accel_init(struct nouveau_drm *drm) return; } + /* Need to figure out how to handle sw for gk20a */ + if (device->chipset == 0xea) + goto skip_sw_init; + ret = nouveau_object_new(nv_object(drm), NVDRM_CHAN, NVDRM_NVSW, nouveau_abi16_swclass(drm), NULL, 0, &object); if (ret == 0) { @@ -233,6 +242,7 @@ nouveau_accel_init(struct nouveau_drm *drm) return; } +skip_sw_init: if (device->card_type < NV_C0) { ret = nouveau_gpuobj_new(drm->device, NULL, 32, 0, 0, &drm->notify); -- 1.8.5.3
Alexandre Courbot
2014-Feb-01 03:16 UTC
[Nouveau] [RFC 16/16] drm/nouveau: support for probing GK20A
Set the correct subdev/engine classes when GK20A (0xea) is probed. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drivers/gpu/drm/nouveau/core/engine/device/nve0.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nve0.c b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c index 987edbc..30d652e 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c @@ -156,6 +156,26 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; device->oclass[NVDEV_ENGINE_PERFMON] = &nve0_perfmon_oclass; break; + case 0xea: + device->cname = "GK20A"; + device->oclass[NVDEV_SUBDEV_MC ] = nvc3_mc_oclass; + device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass; + device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; + device->oclass[NVDEV_SUBDEV_FB ] = nvea_fb_oclass; + device->oclass[NVDEV_SUBDEV_IBUS ] = &nvea_ibus_oclass; + device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; + device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; + device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; + device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass; + device->oclass[NVDEV_ENGINE_FIFO ] = nvea_fifo_oclass; + /* TODO will need an implementation for this at some point... */ +#if 0 + device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass; +#endif + device->oclass[NVDEV_ENGINE_GR ] = nve4_graph_oclass; + device->oclass[NVDEV_ENGINE_COPY2 ] = &nve0_copy2_oclass; + device->oclass[NVDEV_ENGINE_PERFMON] = &nve0_perfmon_oclass; + break; case 0xf0: device->cname = "GK110"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; -- 1.8.5.3
Am Samstag, den 01.02.2014, 12:16 +0900 schrieb Alexandre Courbot:> Add a clumsy-but-working FB support for GK20A. This chip only uses system > memory, so we allocate a big chunk using CMA and let the existing memory > managers work on it. > > A better future design would be to allocate objects directly from system > memory without having to suffer from the limitations of a large, > contiguous pool. >I don't know if Tegra124 is similar to 114 in this regard [hint: get the TRM out :)], but if you go for a dedicated VRAM allocator, wouldn't it make sense to take a chunk of the MMIO overlaid memory for this when possible, rather than carving this out of CPU accessible mem?> Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> > --- > drivers/gpu/drm/nouveau/Makefile | 2 + > drivers/gpu/drm/nouveau/core/include/subdev/fb.h | 1 + > drivers/gpu/drm/nouveau/core/subdev/fb/nvea.c | 28 ++++++++++ > drivers/gpu/drm/nouveau/core/subdev/fb/priv.h | 1 + > drivers/gpu/drm/nouveau/core/subdev/fb/ramnvea.c | 67 ++++++++++++++++++++++++ > 5 files changed, 99 insertions(+) > create mode 100644 drivers/gpu/drm/nouveau/core/subdev/fb/nvea.c > create mode 100644 drivers/gpu/drm/nouveau/core/subdev/fb/ramnvea.c > > diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile > index 3548fcd..d9fe3e6 100644 > --- a/drivers/gpu/drm/nouveau/Makefile > +++ b/drivers/gpu/drm/nouveau/Makefile > @@ -100,6 +100,7 @@ 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/nvea.o > nouveau-y += core/subdev/fb/ramnv04.o > nouveau-y += core/subdev/fb/ramnv10.o > nouveau-y += core/subdev/fb/ramnv1a.o > @@ -114,6 +115,7 @@ 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/ramnvea.o > nouveau-y += core/subdev/fb/sddr3.o > nouveau-y += core/subdev/fb/gddr5.o > nouveau-y += core/subdev/gpio/base.o > diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h > index d7ecafb..3905816 100644 > --- a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h > +++ b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h > @@ -105,6 +105,7 @@ extern struct nouveau_oclass *nvaa_fb_oclass; > extern struct nouveau_oclass *nvaf_fb_oclass; > extern struct nouveau_oclass *nvc0_fb_oclass; > extern struct nouveau_oclass *nve0_fb_oclass; > +extern struct nouveau_oclass *nvea_fb_oclass; > > #include <subdev/bios/ramcfg.h> > > diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvea.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvea.c > new file mode 100644 > index 0000000..5ff6029 > --- /dev/null > +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvea.c > @@ -0,0 +1,28 @@ > +/* > + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms and conditions of the GNU General Public License, > + * version 2, as published by the Free Software Foundation. > + * > + * This program is distributed in the hope it will be useful, but WITHOUT > + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or > + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for > + * more details. > + * > + */ > + > +#include "nvc0.h" > + > +struct nouveau_oclass * > +nvea_fb_oclass = &(struct nouveau_fb_impl) { > + .base.handle = NV_SUBDEV(FB, 0xea), > + .base.ofuncs = &(struct nouveau_ofuncs) { > + .ctor = nvc0_fb_ctor, > + .dtor = nvc0_fb_dtor, > + .init = nvc0_fb_init, > + .fini = _nouveau_fb_fini, > + }, > + .memtype = nvc0_fb_memtype_valid, > + .ram = &nvea_ram_oclass, > +}.base; > diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h b/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h > index edaf95d..0b95a25 100644 > --- a/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h > +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h > @@ -32,6 +32,7 @@ extern struct nouveau_oclass nva3_ram_oclass; > extern struct nouveau_oclass nvaa_ram_oclass; > extern struct nouveau_oclass nvc0_ram_oclass; > extern struct nouveau_oclass nve0_ram_oclass; > +extern struct nouveau_oclass nvea_ram_oclass; > > int nouveau_sddr3_calc(struct nouveau_ram *ram); > int nouveau_gddr5_calc(struct nouveau_ram *ram, bool nuts); > diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvea.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvea.c > new file mode 100644 > index 0000000..3038e08 > --- /dev/null > +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvea.c > @@ -0,0 +1,67 @@ > +/* > + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms and conditions of the GNU General Public License, > + * version 2, as published by the Free Software Foundation. > + * > + * This program is distributed in the hope it will be useful, but WITHOUT > + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or > + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for > + * more details. > + * > + */ > + > +/* > + * TODO replace this CMA-requiring horror with a proper allocator for GPU > + * objects in main memory. But for the moment it does the job and can reuse some > + * of the nvc0 functions. > + */ > + > +#include "nvc0.h" > + > +#include <linux/dma-mapping.h> > + > +static int > +nvea_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine, > + struct nouveau_oclass *oclass, void *data, u32 datasize, > + struct nouveau_object **pobject) > +{ > + struct nouveau_fb *pfb = nouveau_fb(parent); > + struct nouveau_ram *ram; > + void *vram; > + dma_addr_t dma_handle; > + int ret; > + > + ret = nouveau_ram_create(parent, engine, oclass, &ram); > + *pobject = nv_object(ram); > + if (ret) > + return ret; > + > + ram->type = NV_MEM_TYPE_STOLEN; > + /* Use a fixed size of 64MB for now */ > + ram->size = 0x4000000; > + ram->stolen = (u64)0x00000000; > + vram = dma_alloc_coherent(nv_device_base(nv_device(parent)), ram->size, > + &dma_handle, GFP_KERNEL); > + if (!vram) > + return -ENOMEM; > + > + ret = nouveau_mm_init(&pfb->vram, dma_handle >> 12, ram->size >> 12, 1); > + if (ret) > + return ret; > + > + ram->get = nvc0_ram_get; > + ram->put = nvc0_ram_put; > + return 0; > +} > + > +struct nouveau_oclass > +nvea_ram_oclass = { > + .ofuncs = &(struct nouveau_ofuncs) { > + .ctor = nvea_ram_ctor, > + .dtor = _nouveau_ram_dtor, > + .init = _nouveau_ram_init, > + .fini = _nouveau_ram_fini, > + }, > +};
Ilia Mirkin
2014-Feb-02 06:35 UTC
[Nouveau] [RFC 13/16] drm/nouveau/ibus: add GK20A support
Some very trivial comments below: On Fri, Jan 31, 2014 at 10:16 PM, Alexandre Courbot <acourbot at nvidia.com> wrote:> Add support for initializing the priv ring of GK20A. This is done by the > BIOS on desktop GPUs, but needs to be done by hand on Tegra. > > Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> > --- > drivers/gpu/drm/nouveau/Makefile | 1 + > drivers/gpu/drm/nouveau/core/include/subdev/ibus.h | 1 + > drivers/gpu/drm/nouveau/core/subdev/ibus/nvea.c | 108 +++++++++++++++++++++ > 3 files changed, 110 insertions(+) > create mode 100644 drivers/gpu/drm/nouveau/core/subdev/ibus/nvea.c > > diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile > index 6c4b76d..3548fcd 100644 > --- a/drivers/gpu/drm/nouveau/Makefile > +++ b/drivers/gpu/drm/nouveau/Makefile > @@ -132,6 +132,7 @@ nouveau-y += core/subdev/i2c/nv94.o > nouveau-y += core/subdev/i2c/nvd0.o > nouveau-y += core/subdev/ibus/nvc0.o > nouveau-y += core/subdev/ibus/nve0.o > +nouveau-y += core/subdev/ibus/nvea.o > nouveau-y += core/subdev/instmem/base.o > nouveau-y += core/subdev/instmem/nv04.o > nouveau-y += core/subdev/instmem/nv40.o > diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/ibus.h b/drivers/gpu/drm/nouveau/core/include/subdev/ibus.h > index 88814f1..056a42f 100644 > --- a/drivers/gpu/drm/nouveau/core/include/subdev/ibus.h > +++ b/drivers/gpu/drm/nouveau/core/include/subdev/ibus.h > @@ -30,5 +30,6 @@ nouveau_ibus(void *obj) > > extern struct nouveau_oclass nvc0_ibus_oclass; > extern struct nouveau_oclass nve0_ibus_oclass; > +extern struct nouveau_oclass nvea_ibus_oclass; > > #endif > diff --git a/drivers/gpu/drm/nouveau/core/subdev/ibus/nvea.c b/drivers/gpu/drm/nouveau/core/subdev/ibus/nvea.c > new file mode 100644 > index 0000000..0bcd281 > --- /dev/null > +++ b/drivers/gpu/drm/nouveau/core/subdev/ibus/nvea.c > @@ -0,0 +1,108 @@ > +/* > + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms and conditions of the GNU General Public License, > + * version 2, as published by the Free Software Foundation. > + * > + * This program is distributed in the hope it will be useful, but WITHOUT > + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or > + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for > + * more details. > + * > + */ > + > +#include <subdev/ibus.h> > + > +struct nvea_ibus_priv { > + struct nouveau_ibus base; > +}; > + > +static void > +nvea_ibus_init_priv_ring(struct nvea_ibus_priv *priv) > +{ > + u32 data; > + > + data = nv_rd32(priv, 0x137250); > + data &= (~0x3f); > + nv_wr32(priv, 0x137250, data);nv_mask(priv, 0x137250, 0x3f, 0) should do this, right?> + > + nv_mask(priv, 0x000200, 0x20, 0); > + udelay(20); > + nv_mask(priv, 0x000200, 0x20, 0x20); > + > + nv_wr32(priv, 0x12004c, 0x4); > + nv_wr32(priv, 0x122204, 0x2); > + nv_rd32(priv, 0x122204); > +} > + > +static void > +nvea_ibus_intr(struct nouveau_subdev *subdev) > +{ > + struct nvea_ibus_priv *priv = (void *)subdev; > + u32 status0 = nv_rd32(priv, 0x120058); > + s32 retry = 100; > + u32 command; > + > + if (status0 & 0x7) { > + nv_debug(priv, "resetting priv ring\n"); > + nvea_ibus_init_priv_ring(priv); > + } > + > + /* Acknowledge interrupt */ > + command = nv_rd32(priv, 0x0012004c); > + command |= 0x2; > + nv_wr32(priv, 0x0012004c, command);nv_mask(priv, 0x12004c, 0x2, 0x2)> + > + while (--retry >= 0) { > + command = nv_rd32(priv, 0x12004c) & 0x3f; > + if (command == 0) > + break; > + } > + > + if (retry < 0) > + nv_debug(priv, "timeout waiting for ringmaster ack\n");this sounds kinda bad, no? perhaps a nv_warn?> +} > + > +static int > +nvea_ibus_init(struct nouveau_object *object) > +{ > + struct nvea_ibus_priv *priv = (void *)object; > + int ret; > + > + ret = _nouveau_ibus_init(object); > + if (ret) > + return ret; > + > + nvea_ibus_init_priv_ring(priv); > + > + return 0; > +} > + > +static int > +nvea_ibus_ctor(struct nouveau_object *parent, struct nouveau_object *engine, > + struct nouveau_oclass *oclass, void *data, u32 size, > + struct nouveau_object **pobject) > +{ > + struct nvea_ibus_priv *priv; > + int ret; > + > + ret = nouveau_ibus_create(parent, engine, oclass, &priv); > + *pobject = nv_object(priv); > + if (ret) > + return ret; > + > + nv_subdev(priv)->intr = nvea_ibus_intr; > + return 0; > +} > + > +struct nouveau_oclass > +nvea_ibus_oclass = { > + .handle = NV_SUBDEV(IBUS, 0xea), > + .ofuncs = &(struct nouveau_ofuncs) { > + .ctor = nvea_ibus_ctor, > + .dtor = _nouveau_ibus_dtor, > + .init = nvea_ibus_init, > + .fini = _nouveau_ibus_fini, > + }, > +}; > -- > 1.8.5.3 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to majordomo at vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > Please read the FAQ at http://www.tux.org/lkml/
Ilia Mirkin
2014-Feb-02 19:10 UTC
[Nouveau] [RFC 00/16] drm/nouveau: initial support for GK20A (Tegra K1)
Hi Alexandre, On Fri, Jan 31, 2014 at 10:16 PM, Alexandre Courbot <acourbot at nvidia.com> wrote:> I guess my email address might surprise some of you, so let me anticipate some > questions you might have. :P Yes, this work is endorsed by NVIDIA. Several other > NVIDIAns (CC'd), including core GPU experts, have provided significant technical > guidance and will continue their involvement. Special thanks go to Terje > Bergstrom and Ken Adams for their invaluable GPU expertise, and Thierry Reding > (at FOSDEM this weekend) for help with debugging and user-space testing. > > Let me also stress that although very exciting, this effort is still > experimental, so I would like to make sure that nobody makes excessive > expectations based on these few patches. The scope of this work is strictly > limited to Tegra (although given the similarities desktop GPU support will > certainly benefit from it indirectly), and we do not have any plan to work on > user-space support. So do not uninstall that proprietary driver just yet. ;) > > With this being clarified, we are looking forward to getting your feedback and > working with you guys to bring and improve Tegra K1 support into Nouveau! :)I've sent a couple of fairly trivial comments, as you saw, and I suspect that others with a better understanding of the guts will have more substantial architectural feedback, esp after the weekend/FOSDEM. However, since no one's said it already -- welcome to Nouveau!>From the looks of it, you could bring up a full open-source stack withyour patches (i.e. Xorg + nouveau DDX + mesa) and use PRIME to render stuff (assuming the actual display hw has an X ddx). Although I suspect that you're going to want to use your own drivers. Still a little curious if you've tried the open-source stack and whether it worked. [Not sure what the status is of render-node support is in mesa, but perhaps it's enough to try running piglit tests, if you can't get X going with the display HW.] -ilia
Alexandre Courbot
2014-Feb-03 02:44 UTC
[Nouveau] [RFC 00/16] drm/nouveau: initial support for GK20A (Tegra K1)
On 02/03/2014 04:10 AM, Ilia Mirkin wrote:> Hi Alexandre, > > On Fri, Jan 31, 2014 at 10:16 PM, Alexandre Courbot <acourbot at nvidia.com> wrote: >> I guess my email address might surprise some of you, so let me anticipate some >> questions you might have. :P Yes, this work is endorsed by NVIDIA. Several other >> NVIDIAns (CC'd), including core GPU experts, have provided significant technical >> guidance and will continue their involvement. Special thanks go to Terje >> Bergstrom and Ken Adams for their invaluable GPU expertise, and Thierry Reding >> (at FOSDEM this weekend) for help with debugging and user-space testing. >> >> Let me also stress that although very exciting, this effort is still >> experimental, so I would like to make sure that nobody makes excessive >> expectations based on these few patches. The scope of this work is strictly >> limited to Tegra (although given the similarities desktop GPU support will >> certainly benefit from it indirectly), and we do not have any plan to work on >> user-space support. So do not uninstall that proprietary driver just yet. ;) >> >> With this being clarified, we are looking forward to getting your feedback and >> working with you guys to bring and improve Tegra K1 support into Nouveau! :) > > I've sent a couple of fairly trivial comments, as you saw, and I > suspect that others with a better understanding of the guts will have > more substantial architectural feedback, esp after the weekend/FOSDEM. > However, since no one's said it already -- welcome to Nouveau!Thanks! ^_^v One beginner question: is it appropriate to send kernel patches to the nouveau list in addition to dri-devel? The moderation messages I receive make me think that this list might rather be intended for general discussion.> From the looks of it, you could bring up a full open-source stack with > your patches (i.e. Xorg + nouveau DDX + mesa) and use PRIME to render > stuff (assuming the actual display hw has an X ddx). Although I > suspect that you're going to want to use your own drivers. Still a > little curious if you've tried the open-source stack and whether it > worked. [Not sure what the status is of render-node support is in > mesa, but perhaps it's enough to try running piglit tests, if you > can't get X going with the display HW.]We are still testing things at libdrm level, but are eventually interested in bringing up the existing open-source stack. Our guess (and hope) is that it will work nicely almost as-is, minus the fact that the display hardware is not handled by Nouveau and we only support render nodes (I have yet to look at what the state of render nodes in Mesa is). For X, Thierry is IIUC working on the display driver, and at some point these efforts should join to connect tegradrm and Nouveau using PRIME. We are not quite there yet, and since we are working with limited resources it will likely require some time, but the fact we could bring up a (seemingly) working Nouveau kernel driver with so little code is encouraging. Thanks, Alex.
David Herrmann
2014-Feb-03 11:25 UTC
[Nouveau] [RFC 00/16] drm/nouveau: initial support for GK20A (Tegra K1)
Hi [..snip..]> Finally, support for probing GK20A is added in the last 2 patches. It should be > noted that contrary to what Nouveau currently expects, GK20A does not embed any > display hardware (that part being handled by tegradrm). So this driver should > really be only used through DRM render-nodes and collaborate with the display > driver using PRIME. I have not yet figured out how to turn GK20A's instantiation > of Nouveau into a render-node only driver without breaking support for existing > desktop GPUs, and consequently the driver spawns a /dev/dri/cardX node which we > should try to get rid of.You cannot get rid of cardX currently. It is implied by DRIVER_MODESET and that flag should actually be called NOT_A_LEGACY_DRIVER. So you cannot remove it. I did try to replace DRIVER_MODESET by an inverted DRIVER_LEGACY flag some time ago, but I thought it's not worth it. Anyhow, you can easily add a new flag to make drm_dev_register()/drm_dev_alloc() not create the drm_minor for DRM_MINOR_LEGACY, which would prevent the card0 node from showing up. But people started using the cardX interface as base interface so mesa might not be able to open render-nodes if the related card-node is not available (which is a bug in their code, so no reason to support that by not adding stand-alone render-nodes). Long story short: If you want to do it properly, just add a flag to DRM core that prevents DRM_MINOR_LEGACY from showing up. If you just want it to work, simply keep a dummy card0. Thanks David
Daniel Vetter
2014-Feb-03 17:33 UTC
[Nouveau] [RFC 00/16] drm/nouveau: initial support for GK20A (Tegra K1)
On Sat, Feb 1, 2014 at 4:16 AM, Alexandre Courbot <acourbot at nvidia.com> wrote:> Finally, support for probing GK20A is added in the last 2 patches. It should be > noted that contrary to what Nouveau currently expects, GK20A does not embed any > display hardware (that part being handled by tegradrm). So this driver should > really be only used through DRM render-nodes and collaborate with the display > driver using PRIME. I have not yet figured out how to turn GK20A's instantiation > of Nouveau into a render-node only driver without breaking support for existing > desktop GPUs, and consequently the driver spawns a /dev/dri/cardX node which we > should try to get rid of.tbh I wouldn't care about the lagecy dev nodes - we have hw platforms on intel with similar setup (i.e. just rendering and no outputs) and we don't bother to hide the legacy node. kms ioctl will still be there, but as long as no encoder/connector/crtc/... gets set up by the driver the only thing userspace can do is create framebuffers. Which is rather harmless ;-) And having legacy dev nodes around helps on older userspace (e.g. X/Prime with dri2 which uses flink). -Daniel -- Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Alexandre Courbot
2014-Feb-04 02:47 UTC
[Nouveau] [RFC 00/16] drm/nouveau: initial support for GK20A (Tegra K1)
On 02/03/2014 08:25 PM, David Herrmann wrote:> Hi > > [..snip..] >> Finally, support for probing GK20A is added in the last 2 patches. It should be >> noted that contrary to what Nouveau currently expects, GK20A does not embed any >> display hardware (that part being handled by tegradrm). So this driver should >> really be only used through DRM render-nodes and collaborate with the display >> driver using PRIME. I have not yet figured out how to turn GK20A's instantiation >> of Nouveau into a render-node only driver without breaking support for existing >> desktop GPUs, and consequently the driver spawns a /dev/dri/cardX node which we >> should try to get rid of. > > You cannot get rid of cardX currently. It is implied by DRIVER_MODESET > and that flag should actually be called NOT_A_LEGACY_DRIVER. So you > cannot remove it. I did try to replace DRIVER_MODESET by an inverted > DRIVER_LEGACY flag some time ago, but I thought it's not worth it. > > Anyhow, you can easily add a new flag to make > drm_dev_register()/drm_dev_alloc() not create the drm_minor for > DRM_MINOR_LEGACY, which would prevent the card0 node from showing up. > But people started using the cardX interface as base interface so mesa > might not be able to open render-nodes if the related card-node is not > available (which is a bug in their code, so no reason to support that > by not adding stand-alone render-nodes).Actually my mention of /dev/dri/cardX was misleading. I was rather thinking about getting rid of the DRIVER_MODESET flag to correctly expose what the card provides, not only to user-space, but to DRM itself. The legacy node is ok as long as DRM itself correctly knows what the driver can and cannot do and fails gracefully if the user tries to set a mode. DRIVER_MODESET is statically set in nouveau_drm.c, and the reason why I cannot get rid of it is because the driver (and its features) is registered with drm_pci_init() before the card is probed and its actual features known. For platform devices, you could check the card features before registering it with drm_platform_init(), but then you have the issue that the driver instance is referenced by every probed card, and thus you cannot have cards with different capabilities. So it seems like handling this would require the driver_features to move from drm_driver to drm_device, but that's quite a core change. As pointed out by you and Daniel, we can certainly live with the control and legacy nodes. Nonetheless I'd be curious to know how (and if) this case can be correctly handled. Alex.
Ben Skeggs
2014-Feb-04 03:53 UTC
[Nouveau] [RFC 00/16] drm/nouveau: initial support for GK20A (Tegra K1)
On Sat, Feb 1, 2014 at 1:16 PM, Alexandre Courbot <acourbot at nvidia.com> wrote:> Hello everyone,Hey Alex, The series looks pretty good to me. I'll reply to the relevant patches with any minor nit-picks on top of what's already been said by others. Thank you, and welcome to Nouveau :) Ben.> > GK20A is the Kepler-based GPU used in the upcoming Tegra K1 chips. The following > patches perform architectural changes to Nouveau that are necessary to support > non-PCI GPUs and add initial support for GK20A. Although the support is still > very basic and more user-space changes will be needed to make the full graphics > stack run on top of it, we were able to successfully open channels and run > simple pushbuffers with libdrm (more testing including rendering is in progress > as we get more familiar with Nouveau's user-space interface). > > This work should be considered as a RFC and a proof-of-concept for driving > future Tegra GPUs with Nouveau. Some design choices need to be discussed and > quite a few inelegant shortcuts were purposely taken to minimize the size of > this first set. Or said otherwise, apart from the changes that add support for > non-PCI GPUs, remarkably little code needs to be added to get GK20A to a point > where it is actually running. This is very encouraging, and it will be > interesting to keep improving this support and see where this gets us. > > The first part of this series (patches 01/09) adds support for platform devices > to Nouveau. Nouveau currently only supports PCI devices, and GK20A uses the > platform bus and Device Tree. So the first step towards GK20A support is to > abstract the PCI functions used by Nouveau (mainly resources range querying and > page mapping functions) and add platform device probing functions. For most of > the existing chips, platform device support does not make any sense, so only the > subdev and engine drivers actually used by GK20A were updated to use these > abstractions. If, for consistency reasons, it is deemed preferable to use them > everywhere in the driver, we will do it in the next revision of this series. > > This part can be considered independently from the actual GK20A support, and I > believe it would make sense to discuss what needs to be improved and drive it to > merge separately, as the remainder of the series will likely require more work. > > The second part (10/14) updates existing subdev/engine drivers to support GK20A, > and adds a very simple memory driver that simulates dedicated video memory by > allocating a large system memory chunk at boot time. This is clearly sub-optimal > and should not be merged, but allowed us to quickly bring GK20A up with Nouveau. > Other drivers changes are fairly small, and are here to handle the difference in > number of engines and units compared to desktop Kepler as well as to perform a > few things usually done by the video BIOS (which Tegra does not feature). > > Finally, support for probing GK20A is added in the last 2 patches. It should be > noted that contrary to what Nouveau currently expects, GK20A does not embed any > display hardware (that part being handled by tegradrm). So this driver should > really be only used through DRM render-nodes and collaborate with the display > driver using PRIME. I have not yet figured out how to turn GK20A's instantiation > of Nouveau into a render-node only driver without breaking support for existing > desktop GPUs, and consequently the driver spawns a /dev/dri/cardX node which we > should try to get rid of. > > I guess my email address might surprise some of you, so let me anticipate some > questions you might have. :P Yes, this work is endorsed by NVIDIA. Several other > NVIDIAns (CC'd), including core GPU experts, have provided significant technical > guidance and will continue their involvement. Special thanks go to Terje > Bergstrom and Ken Adams for their invaluable GPU expertise, and Thierry Reding > (at FOSDEM this weekend) for help with debugging and user-space testing. > > Let me also stress that although very exciting, this effort is still > experimental, so I would like to make sure that nobody makes excessive > expectations based on these few patches. The scope of this work is strictly > limited to Tegra (although given the similarities desktop GPU support will > certainly benefit from it indirectly), and we do not have any plan to work on > user-space support. So do not uninstall that proprietary driver just yet. ;) > > With this being clarified, we are looking forward to getting your feedback and > working with you guys to bring and improve Tegra K1 support into Nouveau! :) > > Alexandre Courbot (16): > drm/nouveau: handle -EACCES runtime PM return code > drm/nouveau: basic support for platform devices > drm/nouveau: add platform device probing function > drm/nouveau/fifo: support platform devices > drm/nouveau/bar: support platform devices > drm/nouveau/bar: only ioremap BAR3 if it exists > drm/nouveau/bar/nvc0: support chips without BAR3 > drm/nouveau/mc: support platform devices > drm/nouveau/fb: support platform devices > drm/nouveau/timer: skip calibration on GK20A > drm/nouveau/fifo: allocate usermem as needed > drm/nouveau/fifo: add GK20A support > drm/nouveau/ibus: add GK20A support > drm/nouveau/fb: add GK20A support > drm/nouveau: support GK20A in nouveau_accel_init() > drm/nouveau: support for probing GK20A > > drivers/gpu/drm/nouveau/Makefile | 4 + > drivers/gpu/drm/nouveau/core/engine/device/base.c | 92 +++++++++++++++- > drivers/gpu/drm/nouveau/core/engine/device/nve0.c | 20 ++++ > drivers/gpu/drm/nouveau/core/engine/fifo/base.c | 2 +- > drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c | 4 +- > drivers/gpu/drm/nouveau/core/engine/fifo/nve0.h | 1 + > drivers/gpu/drm/nouveau/core/engine/fifo/nvea.c | 27 +++++ > drivers/gpu/drm/nouveau/core/include/core/device.h | 27 +++++ > .../gpu/drm/nouveau/core/include/engine/device.h | 10 ++ > drivers/gpu/drm/nouveau/core/include/engine/fifo.h | 1 + > drivers/gpu/drm/nouveau/core/include/subdev/fb.h | 1 + > drivers/gpu/drm/nouveau/core/include/subdev/ibus.h | 1 + > drivers/gpu/drm/nouveau/core/include/subdev/mc.h | 1 + > drivers/gpu/drm/nouveau/core/os.h | 1 + > drivers/gpu/drm/nouveau/core/subdev/bar/base.c | 7 +- > drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c | 4 +- > drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c | 116 +++++++++++---------- > drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c | 9 +- > drivers/gpu/drm/nouveau/core/subdev/fb/nvea.c | 28 +++++ > drivers/gpu/drm/nouveau/core/subdev/fb/priv.h | 1 + > drivers/gpu/drm/nouveau/core/subdev/fb/ramnvea.c | 67 ++++++++++++ > drivers/gpu/drm/nouveau/core/subdev/ibus/nvea.c | 108 +++++++++++++++++++ > drivers/gpu/drm/nouveau/core/subdev/mc/base.c | 43 +++++--- > drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c | 19 ++-- > drivers/gpu/drm/nouveau/dispnv04/crtc.c | 2 +- > drivers/gpu/drm/nouveau/nouveau_abi16.c | 13 ++- > drivers/gpu/drm/nouveau/nouveau_bo.c | 22 ++-- > drivers/gpu/drm/nouveau/nouveau_connector.c | 2 +- > drivers/gpu/drm/nouveau/nouveau_display.c | 3 +- > drivers/gpu/drm/nouveau/nouveau_drm.c | 86 ++++++++++++--- > drivers/gpu/drm/nouveau/nouveau_sysfs.c | 8 +- > drivers/gpu/drm/nouveau/nouveau_ttm.c | 31 +++--- > 32 files changed, 622 insertions(+), 139 deletions(-) > create mode 100644 drivers/gpu/drm/nouveau/core/engine/fifo/nvea.c > create mode 100644 drivers/gpu/drm/nouveau/core/subdev/fb/nvea.c > create mode 100644 drivers/gpu/drm/nouveau/core/subdev/fb/ramnvea.c > create mode 100644 drivers/gpu/drm/nouveau/core/subdev/ibus/nvea.c > > -- > 1.8.5.3 > > _______________________________________________ > dri-devel mailing list > dri-devel at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel
Ben Skeggs
2014-Feb-04 03:54 UTC
[Nouveau] [RFC 07/16] drm/nouveau/bar/nvc0: support chips without BAR3
On Sat, Feb 1, 2014 at 1:16 PM, Alexandre Courbot <acourbot at nvidia.com> wrote:> Adapt the NVC0 BAR driver to make it able to support chips that do not > expose a BAR3. When this happens, BAR1 is then used for USERD mapping > and the BAR alloc() functions is disabled, making GPU objects unable > to rely on BAR for data access and falling back to PRAMIN. > > Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> > --- > drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c | 115 +++++++++++++------------ > 1 file changed, 61 insertions(+), 54 deletions(-) > > diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c > index 3f30db6..c2bb0e5 100644 > --- a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c > +++ b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c > @@ -79,87 +79,88 @@ nvc0_bar_unmap(struct nouveau_bar *bar, struct nouveau_vma *vma) > } > > static int > -nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine, > - struct nouveau_oclass *oclass, void *data, u32 size, > - struct nouveau_object **pobject) > +nvc0_bar_init_vm(struct nvc0_bar_priv *priv, int nr, int bar) > { > - struct nouveau_device *device = nv_device(parent); > - struct nvc0_bar_priv *priv; > + struct nouveau_device *device = nv_device(&priv->base); > struct nouveau_gpuobj *mem; > struct nouveau_vm *vm; > + resource_size_t bar_len; > int ret; > > - ret = nouveau_bar_create(parent, engine, oclass, &priv); > - *pobject = nv_object(priv); > - if (ret) > - return ret; > - > - /* BAR3 */ > ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0, 0, > - &priv->bar[0].mem); > - mem = priv->bar[0].mem; > + &priv->bar[nr].mem); > + mem = priv->bar[nr].mem; > if (ret) > return ret; > > ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0, 0, > - &priv->bar[0].pgd); > + &priv->bar[nr].pgd); > if (ret) > return ret; > > - ret = nouveau_vm_new(device, 0, nv_device_resource_len(device, 3), 0, &vm); > + bar_len = nv_device_resource_len(device, bar); > + > + ret = nouveau_vm_new(device, 0, bar_len, 0, &vm); > if (ret) > return ret; > > atomic_inc(&vm->engref[NVDEV_SUBDEV_BAR]); > > - ret = nouveau_gpuobj_new(nv_object(priv), NULL, > - (nv_device_resource_len(device, 3) >> 12) * 8, > - 0x1000, NVOBJ_FLAG_ZERO_ALLOC, > - &vm->pgt[0].obj[0]); > - vm->pgt[0].refcount[0] = 1; > - if (ret) > - return ret; > + /* > + * Bootstrap page table lookup. > + */ > + if (bar == 3) { > + ret = nouveau_gpuobj_new(nv_object(priv), NULL, > + (bar_len >> 12) * 8, 0x1000, > + NVOBJ_FLAG_ZERO_ALLOC, > + &vm->pgt[0].obj[0]); > + vm->pgt[0].refcount[0] = 1; > + if (ret) > + return ret; > + } > > - ret = nouveau_vm_ref(vm, &priv->bar[0].vm, priv->bar[0].pgd); > + ret = nouveau_vm_ref(vm, &priv->bar[nr].vm, priv->bar[nr].pgd); > nouveau_vm_ref(NULL, &vm, NULL); > if (ret) > return ret; > > - nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[0].pgd->addr)); > - nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[0].pgd->addr)); > - nv_wo32(mem, 0x0208, lower_32_bits(nv_device_resource_len(device, 3) - 1)); > - nv_wo32(mem, 0x020c, upper_32_bits(nv_device_resource_len(device, 3) - 1)); > + nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[nr].pgd->addr)); > + nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[nr].pgd->addr)); > + nv_wo32(mem, 0x0208, lower_32_bits(bar_len - 1)); > + nv_wo32(mem, 0x020c, upper_32_bits(bar_len - 1)); > > - /* BAR1 */ > - ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0, 0, > - &priv->bar[1].mem); > - mem = priv->bar[1].mem; > - if (ret) > - return ret; > + return 0; > +} > > - ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0, 0, > - &priv->bar[1].pgd); > - if (ret) > - return ret; > +static int > +nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine, > + struct nouveau_oclass *oclass, void *data, u32 size, > + struct nouveau_object **pobject) > +{ > + struct nouveau_device *device = nv_device(parent); > + struct nvc0_bar_priv *priv; > + bool has_bar3 = nv_device_resource_len(device, 3) != 0; > + int ret; > > - ret = nouveau_vm_new(device, 0, nv_device_resource_len(device, 1), 0, &vm); > + ret = nouveau_bar_create(parent, engine, oclass, &priv); > + *pobject = nv_object(priv); > if (ret) > return ret; > > - atomic_inc(&vm->engref[NVDEV_SUBDEV_BAR]); > + /* BAR3 */ > + if (has_bar3) { > + ret = nvc0_bar_init_vm(priv, 0, 3); > + if (ret) > + return ret; > + priv->base.alloc = nouveau_bar_alloc; > + priv->base.kmap = nvc0_bar_kmap; > + } > > - ret = nouveau_vm_ref(vm, &priv->bar[1].vm, priv->bar[1].pgd); > - nouveau_vm_ref(NULL, &vm, NULL); > + /* BAR1 */ > + ret = nvc0_bar_init_vm(priv, 1, 1); > if (ret) > return ret; > > - nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[1].pgd->addr)); > - nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[1].pgd->addr)); > - nv_wo32(mem, 0x0208, lower_32_bits(nv_device_resource_len(device, 1) - 1)); > - nv_wo32(mem, 0x020c, upper_32_bits(nv_device_resource_len(device, 1) - 1)); > - > - priv->base.alloc = nouveau_bar_alloc; > - priv->base.kmap = nvc0_bar_kmap; > priv->base.umap = nvc0_bar_umap; > priv->base.unmap = nvc0_bar_unmap; > priv->base.flush = nv84_bar_flush; > @@ -176,12 +177,16 @@ nvc0_bar_dtor(struct nouveau_object *object) > nouveau_gpuobj_ref(NULL, &priv->bar[1].pgd); > nouveau_gpuobj_ref(NULL, &priv->bar[1].mem); > > - if (priv->bar[0].vm) { > - nouveau_gpuobj_ref(NULL, &priv->bar[0].vm->pgt[0].obj[0]); > - nouveau_vm_ref(NULL, &priv->bar[0].vm, priv->bar[0].pgd); > + if (priv->bar[0].mem) { > + if (priv->bar[0].vm) { > + nouveau_gpuobj_ref(NULL, > + &priv->bar[0].vm->pgt[0].obj[0]); > + nouveau_vm_ref(NULL, &priv->bar[0].vm, > + priv->bar[0].pgd); > + } > + nouveau_gpuobj_ref(NULL, &priv->bar[0].pgd); > + nouveau_gpuobj_ref(NULL, &priv->bar[0].mem); > } > - nouveau_gpuobj_ref(NULL, &priv->bar[0].pgd); > - nouveau_gpuobj_ref(NULL, &priv->bar[0].mem);Did the conditional on priv->bar[0].mem fix anything here? The ref() functions called are designed to handle the NULL pointers already.> > nouveau_bar_destroy(&priv->base); > } > @@ -201,7 +206,9 @@ nvc0_bar_init(struct nouveau_object *object) > nv_mask(priv, 0x100c80, 0x00000001, 0x00000000); > > nv_wr32(priv, 0x001704, 0x80000000 | priv->bar[1].mem->addr >> 12); > - nv_wr32(priv, 0x001714, 0xc0000000 | priv->bar[0].mem->addr >> 12); > + if (priv->bar[0].mem) > + nv_wr32(priv, 0x001714, > + 0xc0000000 | priv->bar[0].mem->addr >> 12); > return 0; > } > > -- > 1.8.5.3 > > _______________________________________________ > dri-devel mailing list > dri-devel at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel
Ben Skeggs
2014-Feb-04 03:55 UTC
[Nouveau] [RFC 10/16] drm/nouveau/timer: skip calibration on GK20A
On Sat, Feb 1, 2014 at 1:16 PM, Alexandre Courbot <acourbot at nvidia.com> wrote:> GK20A's timer is directly attached to the system timer and cannot be > calibrated. Skip the calibration phase on that chip since the > corresponding registers do not exist.Just a curiosity: What timer resolution does the HW initialise at?> > Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> > --- > drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c | 19 +++++++++++++------ > 1 file changed, 13 insertions(+), 6 deletions(-) > > diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c > index c0bdd10..822fe0d 100644 > --- a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c > +++ b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c > @@ -185,6 +185,10 @@ nv04_timer_init(struct nouveau_object *object) > if (ret) > return ret; > > + /* gk20a does not have the calibration registers */ > + if (device->chipset == 0xea) > + goto skip_clk_init; > + > /* aim for 31.25MHz, which gives us nanosecond timestamps */ > d = 1000000 / 32; > > @@ -235,20 +239,23 @@ nv04_timer_init(struct nouveau_object *object) > d >>= 1; > } > > - /* restore the time before suspend */ > - lo = priv->suspend_time; > - hi = (priv->suspend_time >> 32); > - > nv_debug(priv, "input frequency : %dHz\n", f); > nv_debug(priv, "input multiplier: %d\n", m); > nv_debug(priv, "numerator : 0x%08x\n", n); > nv_debug(priv, "denominator : 0x%08x\n", d); > nv_debug(priv, "timer frequency : %dHz\n", (f * m) * d / n); > - nv_debug(priv, "time low : 0x%08x\n", lo); > - nv_debug(priv, "time high : 0x%08x\n", hi); > > nv_wr32(priv, NV04_PTIMER_NUMERATOR, n); > nv_wr32(priv, NV04_PTIMER_DENOMINATOR, d); > + > +skip_clk_init: > + /* restore the time before suspend */ > + lo = priv->suspend_time; > + hi = (priv->suspend_time >> 32); > + > + nv_debug(priv, "time low : 0x%08x\n", lo); > + nv_debug(priv, "time high : 0x%08x\n", hi); > + > nv_wr32(priv, NV04_PTIMER_INTR_0, 0xffffffff); > nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000); > nv_wr32(priv, NV04_PTIMER_TIME_1, hi); > -- > 1.8.5.3 > > _______________________________________________ > dri-devel mailing list > dri-devel at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel
Alexandre Courbot
2014-Feb-04 08:44 UTC
[Nouveau] [RFC 00/16] drm/nouveau: initial support for GK20A (Tegra K1)
On 02/04/2014 12:53 PM, Ben Skeggs wrote:> On Sat, Feb 1, 2014 at 1:16 PM, Alexandre Courbot <acourbot at nvidia.com> wrote: >> Hello everyone, > Hey Alex, > > The series looks pretty good to me. I'll reply to the relevant > patches with any minor nit-picks on top of what's already been said by > others.Thanks for the review and the welcome. The first part (infrastructure changes to support platform devices) has not really been commented yet. If this means it is already in acceptable shape, I propose to re-submit it separately so it can be merged ahead of the rest. Let me know if you would like us to generalize the use of the bus abstraction functions throughout the driver. For the actual GK20A support, what worries me the most is the memory model, and my very incomplete understanding of how Nouveau manages memory doesn't help here. I hope to get some more feedback about it and see if we can fit somewhere before attempting broader changes. Thanks! Alex.
Daniel Vetter
2014-Feb-04 09:15 UTC
[Nouveau] [RFC 12/16] drm/nouveau/fifo: add GK20A support
On Sat, Feb 01, 2014 at 12:16:54PM +0900, Alexandre Courbot wrote:> GK20A's FIFO is compatible with NVE0, but only features 128 channels and > 1 runlist. > > Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> > --- > drivers/gpu/drm/nouveau/Makefile | 1 + > drivers/gpu/drm/nouveau/core/engine/fifo/nve0.h | 1 + > drivers/gpu/drm/nouveau/core/engine/fifo/nvea.c | 27 ++++++++++++++++++++++ > drivers/gpu/drm/nouveau/core/include/engine/fifo.h | 1 + > 4 files changed, 30 insertions(+) > create mode 100644 drivers/gpu/drm/nouveau/core/engine/fifo/nvea.c > > diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile > index e88145b..6c4b76d 100644 > --- a/drivers/gpu/drm/nouveau/Makefile > +++ b/drivers/gpu/drm/nouveau/Makefile > @@ -236,6 +236,7 @@ nouveau-y += core/engine/fifo/nv50.o > nouveau-y += core/engine/fifo/nv84.o > nouveau-y += core/engine/fifo/nvc0.o > nouveau-y += core/engine/fifo/nve0.o > +nouveau-y += core/engine/fifo/nvea.o > nouveau-y += core/engine/fifo/nv108.o > nouveau-y += core/engine/graph/ctxnv40.o > nouveau-y += core/engine/graph/ctxnv50.o > diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.h b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.h > index 014344e..e96b32b 100644 > --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.h > +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.h > @@ -8,6 +8,7 @@ int nve0_fifo_ctor(struct nouveau_object *, struct nouveau_object *, > struct nouveau_object **); > void nve0_fifo_dtor(struct nouveau_object *); > int nve0_fifo_init(struct nouveau_object *); > +int nve0_fifo_fini(struct nouveau_object *, bool); > > struct nve0_fifo_impl { > struct nouveau_oclass base; > diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvea.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvea.c > new file mode 100644 > index 0000000..16f8905 > --- /dev/null > +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvea.c > @@ -0,0 +1,27 @@ > +/* > + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms and conditions of the GNU General Public License, > + * version 2, as published by the Free Software Foundation.Just stumbled over this lincense header: Generally drm is mit/gpl dual lincensed. The important part for me is the drm core, but due to all the refactoring we tend to do and code extraction from drivers those are rather relevant imo, too. Was this just an oversight or are you still working with your legap people on this? -Daniel -- Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Reasonably Related Threads
- [RFC 10/16] drm/nouveau/timer: skip calibration on GK20A
- [PATCH 02/12] drm/nouveau/timer: skip calibration on GK20A
- [PATCH 02/12] drm/nouveau/timer: skip calibration on GK20A
- [PATCH 02/12] drm/nouveau/timer: skip calibration on GK20A
- [PATCH 02/12] drm/nouveau/timer: skip calibration on GK20A