From 7ba33f3dec819903ce62b39de0b5da09704c0283 Mon Sep 17 00:00:00 2001 From: Ramalingam C Date: Fri, 30 Dec 2022 10:52:53 +0000 Subject: [PATCH] gpu: nvgpu: Handle iGPU in pci probe and remove When iGPU is probed as pci device, power and clocks are driven from the platform, hence the pci_probe and pci_remove to handle both iGPU and dGPU. Also enable the runtime PM for the PCI-iGPU device. JIRA NVGPU-9348 Change-Id: Id5dd88dc0c905655f9174ecd7936bdf2996f06e6 Signed-off-by: Ramalingam C Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2835341 Tested-by: mobile promotions Reviewed-by: mobile promotions --- drivers/gpu/nvgpu/os/linux/module.c | 10 ++-- drivers/gpu/nvgpu/os/linux/module.h | 9 +++- drivers/gpu/nvgpu/os/linux/pci.c | 83 ++++++++++++++++++++++------- 3 files changed, 76 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/nvgpu/os/linux/module.c b/drivers/gpu/nvgpu/os/linux/module.c index b82da023b..273a6cf35 100644 --- a/drivers/gpu/nvgpu/os/linux/module.c +++ b/drivers/gpu/nvgpu/os/linux/module.c @@ -143,7 +143,7 @@ static int nvgpu_wait_for_idle(struct gk20a *g) return 0; } -static int nvgpu_kernel_shutdown_notification(struct notifier_block *nb, +int nvgpu_kernel_shutdown_notification(struct notifier_block *nb, unsigned long event, void *unused) { struct nvgpu_os_linux *l = container_of(nb, struct nvgpu_os_linux, @@ -1561,7 +1561,7 @@ static const struct dev_pm_ops gk20a_pm_ops = { }; #endif -static int gk20a_pm_init(struct device *dev) +int gk20a_pm_init(struct device *dev) { struct gk20a *g = get_gk20a(dev); int err = 0; @@ -1578,7 +1578,7 @@ static int gk20a_pm_init(struct device *dev) return err; } -static int gk20a_pm_late_init(struct device *dev) +int gk20a_pm_late_init(struct device *dev) { struct gk20a *g = get_gk20a(dev); int err = 0; @@ -1603,7 +1603,7 @@ static int gk20a_pm_late_init(struct device *dev) return err; } -static int gk20a_pm_deinit(struct device *dev) +int gk20a_pm_deinit(struct device *dev) { pm_runtime_dont_use_autosuspend(dev); pm_runtime_disable(dev); @@ -1673,7 +1673,7 @@ static inline void set_gk20a(struct platform_device *pdev, struct gk20a *gk20a) gk20a_get_platform(&pdev->dev)->g = gk20a; } -static int nvgpu_read_fuse_overrides(struct gk20a *g) +int nvgpu_read_fuse_overrides(struct gk20a *g) { #ifdef CONFIG_NVGPU_TEGRA_FUSE struct device_node *np = nvgpu_get_node(g); diff --git a/drivers/gpu/nvgpu/os/linux/module.h b/drivers/gpu/nvgpu/os/linux/module.h index a1dfcc50c..27129f3e7 100644 --- a/drivers/gpu/nvgpu/os/linux/module.h +++ b/drivers/gpu/nvgpu/os/linux/module.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2021, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2011-2023, 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, @@ -18,6 +18,13 @@ struct device; struct platform_device; struct nvgpu_os_linux; +int gk20a_pm_init(struct device *dev); +int gk20a_pm_deinit(struct device *dev); +int gk20a_pm_late_init(struct device *dev); +int nvgpu_read_fuse_overrides(struct gk20a *g); +int nvgpu_kernel_shutdown_notification(struct notifier_block *nb, + unsigned long event, void *unused); + int gk20a_pm_finalize_poweron(struct device *dev); int nvgpu_finalize_poweron_linux(struct nvgpu_os_linux *l); void gk20a_remove_support(struct gk20a *g); diff --git a/drivers/gpu/nvgpu/os/linux/pci.c b/drivers/gpu/nvgpu/os/linux/pci.c index 911cf1e50..629c954cf 100644 --- a/drivers/gpu/nvgpu/os/linux/pci.c +++ b/drivers/gpu/nvgpu/os/linux/pci.c @@ -17,8 +17,11 @@ #include #include #include +#include #include #include +#include +#include #include #include @@ -575,7 +578,6 @@ static int nvgpu_pci_probe(struct pci_dev *pdev, if (err) goto err_free_platform; - g->is_pci_igpu = platform->is_pci_igpu; nvgpu_info(g, "is_pci_igpu: %s", g->is_pci_igpu ? "true" : "false"); pci_set_drvdata(pdev, platform); @@ -598,9 +600,14 @@ static int nvgpu_pci_probe(struct pci_dev *pdev, nvgpu_set_enabled(g, NVGPU_SUPPORT_IO_COHERENCE, true); } - err = pci_enable_device(pdev); - if (err) - goto err_free_platform; + if (!g->is_pci_igpu) { + err = pci_enable_device(pdev); + if (err) + goto err_free_platform; + } else { + if (nvgpu_platform_is_simulation(g)) + nvgpu_set_enabled(g, NVGPU_IS_FMODEL, true); + } pci_set_master(pdev); g->pci_vendor_id = pdev->vendor; @@ -672,6 +679,20 @@ static int nvgpu_pci_probe(struct pci_dev *pdev, if (err) goto err_free_irq; + if (g->is_pci_igpu) { + err = nvgpu_read_fuse_overrides(g); +#ifdef CONFIG_RESET_CONTROLLER + platform->reset_control = devm_reset_control_get(&pdev->dev, NULL); + if (IS_ERR(platform->reset_control)) + platform->reset_control = NULL; +#endif + err = gk20a_pm_init(&pdev->dev); + if (err) { + dev_err(&pdev->dev, "pm init failed"); + goto err_free_irq; + } + } + if (strchr(dev_name(&pdev->dev), '%')) { nvgpu_err(g, "illegal character in device name"); err = -EINVAL; @@ -682,10 +703,12 @@ static int nvgpu_pci_probe(struct pci_dev *pdev, if (err) goto err_free_irq; - err = nvgpu_pci_pm_init(&pdev->dev); - if (err) { - nvgpu_err(g, "pm init failed"); - goto err_free_irq; + if (!g->is_pci_igpu) { + err = nvgpu_pci_pm_init(&pdev->dev); + if (err) { + nvgpu_err(g, "pm init failed"); + goto err_free_irq; + } } if (!platform->disable_nvlink) { @@ -716,17 +739,29 @@ static int nvgpu_pci_probe(struct pci_dev *pdev, } #endif - err = nvgpu_get_dt_clock_limit(g, &g->dgpu_max_clk); - if (err != 0) { - nvgpu_info(g, "Missing nvgpu node"); - } + if (g->is_pci_igpu) { + err = gk20a_pm_late_init(&pdev->dev); + if (err) { + dev_err(&pdev->dev, "pm late_init failed"); + goto err_free_irq; + } - err = nvgpu_pci_add_pci_power(pdev); - if (err) { - nvgpu_err(g, "add pci power failed (%d).", err); - goto err_free_irq; - } + l->nvgpu_reboot_nb.notifier_call = + nvgpu_kernel_shutdown_notification; + err = register_reboot_notifier(&l->nvgpu_reboot_nb); + if (err) + goto err_free_irq; + } else { + err = nvgpu_get_dt_clock_limit(g, &g->dgpu_max_clk); + if (err != 0) + nvgpu_info(g, "Missing nvgpu node"); + err = nvgpu_pci_add_pci_power(pdev); + if (err) { + nvgpu_err(g, "add pci power failed (%d).", err); + goto err_free_irq; + } + } nvgpu_mutex_init(&l->dmabuf_priv_list_lock); nvgpu_init_list_node(&l->dmabuf_priv_list); @@ -749,6 +784,9 @@ err_free_errata: err_free_platform: nvgpu_kfree(g, platform); err_free_l: + + if (g->is_pci_igpu) + nvgpu_kmem_fini(g, NVGPU_KMEM_FINI_FORCE_CLEANUP); kfree(l); return err; } @@ -782,8 +820,10 @@ static void nvgpu_pci_remove(struct pci_dev *pdev) #endif nvgpu_mutex_destroy(&l->dmabuf_priv_list_lock); - err = nvgpu_pci_clear_pci_power(dev_name(dev)); - WARN(err, "gpu failed to clear pci power"); + if (!g->is_pci_igpu) { + err = nvgpu_pci_clear_pci_power(dev_name(dev)); + WARN(err, "gpu failed to clear pci power"); + } err = nvgpu_nvlink_deinit(g); /* ENODEV is a legal error if there is no NVLINK */ @@ -817,7 +857,10 @@ static void nvgpu_pci_remove(struct pci_dev *pdev) } #endif - nvgpu_pci_pm_deinit(&pdev->dev); + if (!g->is_pci_igpu) + nvgpu_pci_pm_deinit(&pdev->dev); + else + gk20a_pm_deinit(dev); /* free allocated platform data space */ gk20a_get_platform(&pdev->dev)->g = NULL;