mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-22 17:36:20 +03:00
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:
committed by
mobile promotions
parent
ebb60b7f5e
commit
7ba33f3dec
@@ -143,7 +143,7 @@ static int nvgpu_wait_for_idle(struct gk20a *g)
|
|||||||
return 0;
|
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)
|
unsigned long event, void *unused)
|
||||||
{
|
{
|
||||||
struct nvgpu_os_linux *l = container_of(nb, struct nvgpu_os_linux,
|
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
|
#endif
|
||||||
|
|
||||||
static int gk20a_pm_init(struct device *dev)
|
int gk20a_pm_init(struct device *dev)
|
||||||
{
|
{
|
||||||
struct gk20a *g = get_gk20a(dev);
|
struct gk20a *g = get_gk20a(dev);
|
||||||
int err = 0;
|
int err = 0;
|
||||||
@@ -1578,7 +1578,7 @@ static int gk20a_pm_init(struct device *dev)
|
|||||||
return err;
|
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);
|
struct gk20a *g = get_gk20a(dev);
|
||||||
int err = 0;
|
int err = 0;
|
||||||
@@ -1603,7 +1603,7 @@ static int gk20a_pm_late_init(struct device *dev)
|
|||||||
return err;
|
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_dont_use_autosuspend(dev);
|
||||||
pm_runtime_disable(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;
|
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
|
#ifdef CONFIG_NVGPU_TEGRA_FUSE
|
||||||
struct device_node *np = nvgpu_get_node(g);
|
struct device_node *np = nvgpu_get_node(g);
|
||||||
|
|||||||
@@ -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
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -18,6 +18,13 @@ struct device;
|
|||||||
struct platform_device;
|
struct platform_device;
|
||||||
struct nvgpu_os_linux;
|
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 gk20a_pm_finalize_poweron(struct device *dev);
|
||||||
int nvgpu_finalize_poweron_linux(struct nvgpu_os_linux *l);
|
int nvgpu_finalize_poweron_linux(struct nvgpu_os_linux *l);
|
||||||
void gk20a_remove_support(struct gk20a *g);
|
void gk20a_remove_support(struct gk20a *g);
|
||||||
|
|||||||
@@ -17,8 +17,11 @@
|
|||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/reset.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
#include <linux/of_address.h>
|
#include <linux/of_address.h>
|
||||||
|
#include <linux/reboot.h>
|
||||||
|
#include <linux/notifier.h>
|
||||||
|
|
||||||
#include <nvgpu/nvhost.h>
|
#include <nvgpu/nvhost.h>
|
||||||
#include <nvgpu/nvgpu_common.h>
|
#include <nvgpu/nvgpu_common.h>
|
||||||
@@ -575,7 +578,6 @@ static int nvgpu_pci_probe(struct pci_dev *pdev,
|
|||||||
if (err)
|
if (err)
|
||||||
goto err_free_platform;
|
goto err_free_platform;
|
||||||
|
|
||||||
|
|
||||||
g->is_pci_igpu = platform->is_pci_igpu;
|
g->is_pci_igpu = platform->is_pci_igpu;
|
||||||
nvgpu_info(g, "is_pci_igpu: %s", g->is_pci_igpu ? "true" : "false");
|
nvgpu_info(g, "is_pci_igpu: %s", g->is_pci_igpu ? "true" : "false");
|
||||||
pci_set_drvdata(pdev, platform);
|
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);
|
nvgpu_set_enabled(g, NVGPU_SUPPORT_IO_COHERENCE, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
err = pci_enable_device(pdev);
|
if (!g->is_pci_igpu) {
|
||||||
if (err)
|
err = pci_enable_device(pdev);
|
||||||
goto err_free_platform;
|
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);
|
pci_set_master(pdev);
|
||||||
|
|
||||||
g->pci_vendor_id = pdev->vendor;
|
g->pci_vendor_id = pdev->vendor;
|
||||||
@@ -672,6 +679,20 @@ static int nvgpu_pci_probe(struct pci_dev *pdev,
|
|||||||
if (err)
|
if (err)
|
||||||
goto err_free_irq;
|
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), '%')) {
|
if (strchr(dev_name(&pdev->dev), '%')) {
|
||||||
nvgpu_err(g, "illegal character in device name");
|
nvgpu_err(g, "illegal character in device name");
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
@@ -682,10 +703,12 @@ static int nvgpu_pci_probe(struct pci_dev *pdev,
|
|||||||
if (err)
|
if (err)
|
||||||
goto err_free_irq;
|
goto err_free_irq;
|
||||||
|
|
||||||
err = nvgpu_pci_pm_init(&pdev->dev);
|
if (!g->is_pci_igpu) {
|
||||||
if (err) {
|
err = nvgpu_pci_pm_init(&pdev->dev);
|
||||||
nvgpu_err(g, "pm init failed");
|
if (err) {
|
||||||
goto err_free_irq;
|
nvgpu_err(g, "pm init failed");
|
||||||
|
goto err_free_irq;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!platform->disable_nvlink) {
|
if (!platform->disable_nvlink) {
|
||||||
@@ -716,17 +739,29 @@ static int nvgpu_pci_probe(struct pci_dev *pdev,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
err = nvgpu_get_dt_clock_limit(g, &g->dgpu_max_clk);
|
if (g->is_pci_igpu) {
|
||||||
if (err != 0) {
|
err = gk20a_pm_late_init(&pdev->dev);
|
||||||
nvgpu_info(g, "Missing nvgpu node");
|
if (err) {
|
||||||
}
|
dev_err(&pdev->dev, "pm late_init failed");
|
||||||
|
goto err_free_irq;
|
||||||
|
}
|
||||||
|
|
||||||
err = nvgpu_pci_add_pci_power(pdev);
|
l->nvgpu_reboot_nb.notifier_call =
|
||||||
if (err) {
|
nvgpu_kernel_shutdown_notification;
|
||||||
nvgpu_err(g, "add pci power failed (%d).", err);
|
err = register_reboot_notifier(&l->nvgpu_reboot_nb);
|
||||||
goto err_free_irq;
|
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_mutex_init(&l->dmabuf_priv_list_lock);
|
||||||
nvgpu_init_list_node(&l->dmabuf_priv_list);
|
nvgpu_init_list_node(&l->dmabuf_priv_list);
|
||||||
|
|
||||||
@@ -749,6 +784,9 @@ err_free_errata:
|
|||||||
err_free_platform:
|
err_free_platform:
|
||||||
nvgpu_kfree(g, platform);
|
nvgpu_kfree(g, platform);
|
||||||
err_free_l:
|
err_free_l:
|
||||||
|
|
||||||
|
if (g->is_pci_igpu)
|
||||||
|
nvgpu_kmem_fini(g, NVGPU_KMEM_FINI_FORCE_CLEANUP);
|
||||||
kfree(l);
|
kfree(l);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -782,8 +820,10 @@ static void nvgpu_pci_remove(struct pci_dev *pdev)
|
|||||||
#endif
|
#endif
|
||||||
nvgpu_mutex_destroy(&l->dmabuf_priv_list_lock);
|
nvgpu_mutex_destroy(&l->dmabuf_priv_list_lock);
|
||||||
|
|
||||||
err = nvgpu_pci_clear_pci_power(dev_name(dev));
|
if (!g->is_pci_igpu) {
|
||||||
WARN(err, "gpu failed to clear pci power");
|
err = nvgpu_pci_clear_pci_power(dev_name(dev));
|
||||||
|
WARN(err, "gpu failed to clear pci power");
|
||||||
|
}
|
||||||
|
|
||||||
err = nvgpu_nvlink_deinit(g);
|
err = nvgpu_nvlink_deinit(g);
|
||||||
/* ENODEV is a legal error if there is no NVLINK */
|
/* ENODEV is a legal error if there is no NVLINK */
|
||||||
@@ -817,7 +857,10 @@ static void nvgpu_pci_remove(struct pci_dev *pdev)
|
|||||||
}
|
}
|
||||||
#endif
|
#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 */
|
/* free allocated platform data space */
|
||||||
gk20a_get_platform(&pdev->dev)->g = NULL;
|
gk20a_get_platform(&pdev->dev)->g = NULL;
|
||||||
|
|||||||
Reference in New Issue
Block a user