@@ -1351,7 +1351,7 @@ nouveau_platform_device_create(const struct nvkm_device_tegra_func *func,
err = nvkm_device_tegra_new(func, pdev, nouveau_config, nouveau_debug, pdevice);
if (err)
- goto err_free;
+ return ERR_PTR(err);
drm = nouveau_drm_device_new(&driver_platform, &pdev->dev, *pdevice);
if (IS_ERR(drm)) {
@@ -1633,12 +1633,9 @@ nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg,
const struct nvkm_device_pci_vendor *pciv;
const char *name = NULL;
struct nvkm_device_pci *pdev;
+ struct nvkm_device *device;
int ret, bits;
- ret = pci_enable_device(pci_dev);
- if (ret)
- return ret;
-
switch (pci_dev->vendor) {
case 0x10de: pcid = nvkm_device_pci_10de; break;
default:
@@ -1664,12 +1661,16 @@ nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg,
pcid++;
}
- if (!(pdev = kzalloc(sizeof(*pdev), GFP_KERNEL))) {
- pci_disable_device(pci_dev);
+ if (!(pdev = kzalloc(sizeof(*pdev), GFP_KERNEL)))
return -ENOMEM;
- }
- *pdevice = &pdev->device;
pdev->pdev = pci_dev;
+ device = &pdev->device;
+
+ ret = pci_enable_device(pci_dev);
+ if (ret) {
+ kfree(pdev);
+ return ret;
+ }
ret = nvkm_device_ctor(&nvkm_device_pci_func, quirk, &pci_dev->dev,
pci_is_pcie(pci_dev) ? NVKM_DEVICE_PCIE :
@@ -1682,7 +1683,7 @@ nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg,
&pdev->device);
if (ret)
- return ret;
+ goto done;
/* Set DMA mask based on capabilities reported by the MMU subdev. */
if (pdev->device.mmu && !pdev->device.pci->agp.bridge)
@@ -1696,5 +1697,12 @@ nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg,
pdev->device.mmu->dma_bits = 32;
}
+done:
+ if (ret) {
+ nvkm_device_del(&device);
+ return ret;
+ }
+
+ *pdevice = &pdev->device;
return 0;
}
@@ -240,6 +240,7 @@ nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func,
struct nvkm_device **pdevice)
{
struct nvkm_device_tegra *tdev;
+ struct nvkm_device *device;
unsigned long rate;
int ret;
@@ -248,6 +249,7 @@ nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func,
tdev->func = func;
tdev->pdev = pdev;
+ device = &tdev->device;
if (func->require_vdd) {
tdev->vdd = devm_regulator_get(&pdev->dev, "vdd");
@@ -311,15 +313,14 @@ nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func,
ret = nvkm_device_ctor(&nvkm_device_tegra_func, NULL, &pdev->dev,
NVKM_DEVICE_TEGRA, pdev->id, NULL,
&tdev->device);
- if (ret)
- goto powerdown;
+ if (ret) {
+ nvkm_device_del(&device);
+ return ret;
+ }
*pdevice = &tdev->device;
-
return 0;
-powerdown:
- nvkm_device_tegra_power_down(tdev);
remove:
nvkm_device_tegra_remove_iommu(tdev);
free:
These previously depended on the caller calling nvkm_device_del() to cleanup if nvkm_device_*_new() fails. That's a little odd for starters, but only the Tegra path cleaned up, and the PCI path would have leaked the memory, FWs etc that had been allocated as NVKM ran each subdev's ctor(). A later patch turns these into pci/platform driver probe() functions, so they need to learn how to clean up after themselves regardless. Signed-off-by: Ben Skeggs <bskeggs@nvidia.com> --- drivers/gpu/drm/nouveau/nouveau_drm.c | 2 +- drivers/gpu/drm/nouveau/nvkm/device/pci.c | 26 ++++++++++++++------- drivers/gpu/drm/nouveau/nvkm/device/tegra.c | 11 +++++---- 3 files changed, 24 insertions(+), 15 deletions(-)