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 <ramalingamc@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2835341
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Ramalingam C
2022-12-30 10:52:53 +00:00
committed by mobile promotions
parent ebb60b7f5e
commit 7ba33f3dec
3 changed files with 76 additions and 26 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -17,8 +17,11 @@
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include <linux/of_platform.h>
#include <linux/of_address.h>
#include <linux/reboot.h>
#include <linux/notifier.h>
#include <nvgpu/nvhost.h>
#include <nvgpu/nvgpu_common.h>
@@ -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);
}
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,11 +703,13 @@ static int nvgpu_pci_probe(struct pci_dev *pdev,
if (err)
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) {
err = nvgpu_nvlink_probe(g);
@@ -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;
}
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);
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
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;