FILE
ipu7-bus.c
File preview with syntax highlighting.
linux-6.19.14/drivers/staging/media/ipu7/ipu7-bus.c
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (C) 2013 - 2025 Intel Corporation 4 */ 5 6#include <linux/auxiliary_bus.h> 7#include <linux/device.h> 8#include <linux/dma-mapping.h> 9#include <linux/err.h> 10#include <linux/list.h> 11#include <linux/mutex.h> 12#include <linux/pci.h> 13#include <linux/pm_domain.h> 14#include <linux/pm_runtime.h> 15#include <linux/slab.h> 16 17#include "ipu7.h" 18#include "ipu7-bus.h" 19#include "ipu7-boot.h" 20#include "ipu7-dma.h" 21 22static int bus_pm_runtime_suspend(struct device *dev) 23{ 24 struct ipu7_bus_device *adev = to_ipu7_bus_device(dev); 25 int ret; 26 27 ret = pm_generic_runtime_suspend(dev); 28 if (ret) 29 return ret; 30 31 ret = ipu_buttress_powerdown(dev, adev->ctrl); 32 if (!ret) 33 return 0; 34 35 dev_err(dev, "power down failed!\n"); 36 37 /* Powering down failed, attempt to resume device now */ 38 ret = pm_generic_runtime_resume(dev); 39 if (!ret) 40 return -EBUSY; 41 42 return -EIO; 43} 44 45static int bus_pm_runtime_resume(struct device *dev) 46{ 47 struct ipu7_bus_device *adev = to_ipu7_bus_device(dev); 48 int ret; 49 50 ret = ipu_buttress_powerup(dev, adev->ctrl); 51 if (ret) 52 return ret; 53 54 ret = pm_generic_runtime_resume(dev); 55 if (ret) 56 goto out_err; 57 58 return 0; 59 60out_err: 61 ipu_buttress_powerdown(dev, adev->ctrl); 62 63 return -EBUSY; 64} 65 66static struct dev_pm_domain ipu7_bus_pm_domain = { 67 .ops = { 68 .runtime_suspend = bus_pm_runtime_suspend, 69 .runtime_resume = bus_pm_runtime_resume, 70 }, 71}; 72 73static DEFINE_MUTEX(ipu7_bus_mutex); 74static void ipu7_bus_release(struct device *dev) 75{ 76 struct ipu7_bus_device *adev = to_ipu7_bus_device(dev); 77 78 kfree(adev->pdata); 79 kfree(adev); 80} 81 82struct ipu7_bus_device * 83ipu7_bus_initialize_device(struct pci_dev *pdev, struct device *parent, 84 void *pdata, const struct ipu_buttress_ctrl *ctrl, 85 const char *name) 86{ 87 struct auxiliary_device *auxdev; 88 struct ipu7_bus_device *adev; 89 struct ipu7_device *isp = pci_get_drvdata(pdev); 90 int ret; 91 92 adev = kzalloc(sizeof(*adev), GFP_KERNEL); 93 if (!adev) 94 return ERR_PTR(-ENOMEM); 95 96 adev->isp = isp; 97 adev->ctrl = ctrl; 98 adev->pdata = pdata; 99 auxdev = &adev->auxdev; 100 auxdev->name = name; 101 auxdev->id = (pci_domain_nr(pdev->bus) << 16) | 102 PCI_DEVID(pdev->bus->number, pdev->devfn); 103 104 auxdev->dev.parent = parent; 105 auxdev->dev.release = ipu7_bus_release; 106 107 ret = auxiliary_device_init(auxdev); 108 if (ret < 0) { 109 dev_err(&isp->pdev->dev, "auxiliary device init failed (%d)\n", 110 ret); 111 kfree(adev); 112 return ERR_PTR(ret); 113 } 114 115 dev_pm_domain_set(&auxdev->dev, &ipu7_bus_pm_domain); 116 117 pm_runtime_forbid(&adev->auxdev.dev); 118 pm_runtime_enable(&adev->auxdev.dev); 119 120 return adev; 121} 122 123int ipu7_bus_add_device(struct ipu7_bus_device *adev) 124{ 125 struct auxiliary_device *auxdev = &adev->auxdev; 126 int ret; 127 128 ret = auxiliary_device_add(auxdev); 129 if (ret) { 130 auxiliary_device_uninit(auxdev); 131 return ret; 132 } 133 134 mutex_lock(&ipu7_bus_mutex); 135 list_add(&adev->list, &adev->isp->devices); 136 mutex_unlock(&ipu7_bus_mutex); 137 138 pm_runtime_allow(&auxdev->dev); 139 140 return 0; 141} 142 143void ipu7_bus_del_devices(struct pci_dev *pdev) 144{ 145 struct ipu7_device *isp = pci_get_drvdata(pdev); 146 struct ipu7_bus_device *adev, *save; 147 148 mutex_lock(&ipu7_bus_mutex); 149 150 list_for_each_entry_safe(adev, save, &isp->devices, list) { 151 pm_runtime_disable(&adev->auxdev.dev); 152 list_del(&adev->list); 153 auxiliary_device_delete(&adev->auxdev); 154 auxiliary_device_uninit(&adev->auxdev); 155 } 156 157 mutex_unlock(&ipu7_bus_mutex); 158}
~/
Read-only file preview.