Skip to content

Commit 815a390

Browse files
Philipp Stannerbjorn-helgaas
authored andcommitted
PCI: Move devres code from pci.c to devres.c
The file pci.c is very large and contains a number of devres functions. These functions should now reside in devres.c. Move as much devres-specific code from pci.c to devres.c as possible. There are a few callers left in pci.c that do devres operations. These should be ported in the future. Add corresponding TODOs. The reason they are not moved right now in this commit is that PCI's devres currently implements a sort of "hybrid-mode": pci_request_region(), for instance, does not have a corresponding pcim_ equivalent, yet. Instead, the function can be made managed by previously calling pcim_enable_device() (instead of pci_enable_device()). This makes it unreasonable to move pci_request_region() to devres.c. Moving the functions would require changes to PCI's API and is, therefore, left for future work. In summary, this commit serves as a preparation step for a following patch series that will cleanly separate the PCI's managed and unmanaged API. Link: https://lore.kernel.org/r/[email protected] Suggested-by: Danilo Krummrich <[email protected]> Signed-off-by: Philipp Stanner <[email protected]> Signed-off-by: Bjorn Helgaas <[email protected]>
1 parent acc2364 commit 815a390

File tree

3 files changed

+262
-249
lines changed

3 files changed

+262
-249
lines changed

drivers/pci/devres.c

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// SPDX-License-Identifier: GPL-2.0
2+
#include <linux/device.h>
23
#include <linux/pci.h>
34
#include "pci.h"
45

@@ -11,6 +12,246 @@ struct pcim_iomap_devres {
1112
void __iomem *table[PCIM_IOMAP_MAX];
1213
};
1314

15+
16+
static void devm_pci_unmap_iospace(struct device *dev, void *ptr)
17+
{
18+
struct resource **res = ptr;
19+
20+
pci_unmap_iospace(*res);
21+
}
22+
23+
/**
24+
* devm_pci_remap_iospace - Managed pci_remap_iospace()
25+
* @dev: Generic device to remap IO address for
26+
* @res: Resource describing the I/O space
27+
* @phys_addr: physical address of range to be mapped
28+
*
29+
* Managed pci_remap_iospace(). Map is automatically unmapped on driver
30+
* detach.
31+
*/
32+
int devm_pci_remap_iospace(struct device *dev, const struct resource *res,
33+
phys_addr_t phys_addr)
34+
{
35+
const struct resource **ptr;
36+
int error;
37+
38+
ptr = devres_alloc(devm_pci_unmap_iospace, sizeof(*ptr), GFP_KERNEL);
39+
if (!ptr)
40+
return -ENOMEM;
41+
42+
error = pci_remap_iospace(res, phys_addr);
43+
if (error) {
44+
devres_free(ptr);
45+
} else {
46+
*ptr = res;
47+
devres_add(dev, ptr);
48+
}
49+
50+
return error;
51+
}
52+
EXPORT_SYMBOL(devm_pci_remap_iospace);
53+
54+
/**
55+
* devm_pci_remap_cfgspace - Managed pci_remap_cfgspace()
56+
* @dev: Generic device to remap IO address for
57+
* @offset: Resource address to map
58+
* @size: Size of map
59+
*
60+
* Managed pci_remap_cfgspace(). Map is automatically unmapped on driver
61+
* detach.
62+
*/
63+
void __iomem *devm_pci_remap_cfgspace(struct device *dev,
64+
resource_size_t offset,
65+
resource_size_t size)
66+
{
67+
void __iomem **ptr, *addr;
68+
69+
ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);
70+
if (!ptr)
71+
return NULL;
72+
73+
addr = pci_remap_cfgspace(offset, size);
74+
if (addr) {
75+
*ptr = addr;
76+
devres_add(dev, ptr);
77+
} else
78+
devres_free(ptr);
79+
80+
return addr;
81+
}
82+
EXPORT_SYMBOL(devm_pci_remap_cfgspace);
83+
84+
/**
85+
* devm_pci_remap_cfg_resource - check, request region and ioremap cfg resource
86+
* @dev: generic device to handle the resource for
87+
* @res: configuration space resource to be handled
88+
*
89+
* Checks that a resource is a valid memory region, requests the memory
90+
* region and ioremaps with pci_remap_cfgspace() API that ensures the
91+
* proper PCI configuration space memory attributes are guaranteed.
92+
*
93+
* All operations are managed and will be undone on driver detach.
94+
*
95+
* Returns a pointer to the remapped memory or an ERR_PTR() encoded error code
96+
* on failure. Usage example::
97+
*
98+
* res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
99+
* base = devm_pci_remap_cfg_resource(&pdev->dev, res);
100+
* if (IS_ERR(base))
101+
* return PTR_ERR(base);
102+
*/
103+
void __iomem *devm_pci_remap_cfg_resource(struct device *dev,
104+
struct resource *res)
105+
{
106+
resource_size_t size;
107+
const char *name;
108+
void __iomem *dest_ptr;
109+
110+
BUG_ON(!dev);
111+
112+
if (!res || resource_type(res) != IORESOURCE_MEM) {
113+
dev_err(dev, "invalid resource\n");
114+
return IOMEM_ERR_PTR(-EINVAL);
115+
}
116+
117+
size = resource_size(res);
118+
119+
if (res->name)
120+
name = devm_kasprintf(dev, GFP_KERNEL, "%s %s", dev_name(dev),
121+
res->name);
122+
else
123+
name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
124+
if (!name)
125+
return IOMEM_ERR_PTR(-ENOMEM);
126+
127+
if (!devm_request_mem_region(dev, res->start, size, name)) {
128+
dev_err(dev, "can't request region for resource %pR\n", res);
129+
return IOMEM_ERR_PTR(-EBUSY);
130+
}
131+
132+
dest_ptr = devm_pci_remap_cfgspace(dev, res->start, size);
133+
if (!dest_ptr) {
134+
dev_err(dev, "ioremap failed for resource %pR\n", res);
135+
devm_release_mem_region(dev, res->start, size);
136+
dest_ptr = IOMEM_ERR_PTR(-ENOMEM);
137+
}
138+
139+
return dest_ptr;
140+
}
141+
EXPORT_SYMBOL(devm_pci_remap_cfg_resource);
142+
143+
/**
144+
* pcim_set_mwi - a device-managed pci_set_mwi()
145+
* @dev: the PCI device for which MWI is enabled
146+
*
147+
* Managed pci_set_mwi().
148+
*
149+
* RETURNS: An appropriate -ERRNO error value on error, or zero for success.
150+
*/
151+
int pcim_set_mwi(struct pci_dev *dev)
152+
{
153+
struct pci_devres *dr;
154+
155+
dr = find_pci_dr(dev);
156+
if (!dr)
157+
return -ENOMEM;
158+
159+
dr->mwi = 1;
160+
return pci_set_mwi(dev);
161+
}
162+
EXPORT_SYMBOL(pcim_set_mwi);
163+
164+
165+
static void pcim_release(struct device *gendev, void *res)
166+
{
167+
struct pci_dev *dev = to_pci_dev(gendev);
168+
struct pci_devres *this = res;
169+
int i;
170+
171+
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
172+
if (this->region_mask & (1 << i))
173+
pci_release_region(dev, i);
174+
175+
if (this->mwi)
176+
pci_clear_mwi(dev);
177+
178+
if (this->restore_intx)
179+
pci_intx(dev, this->orig_intx);
180+
181+
if (this->enabled && !this->pinned)
182+
pci_disable_device(dev);
183+
}
184+
185+
/*
186+
* TODO: After the last four callers in pci.c are ported, find_pci_dr()
187+
* needs to be made static again.
188+
*/
189+
struct pci_devres *find_pci_dr(struct pci_dev *pdev)
190+
{
191+
if (pci_is_managed(pdev))
192+
return devres_find(&pdev->dev, pcim_release, NULL, NULL);
193+
return NULL;
194+
}
195+
196+
static struct pci_devres *get_pci_dr(struct pci_dev *pdev)
197+
{
198+
struct pci_devres *dr, *new_dr;
199+
200+
dr = devres_find(&pdev->dev, pcim_release, NULL, NULL);
201+
if (dr)
202+
return dr;
203+
204+
new_dr = devres_alloc(pcim_release, sizeof(*new_dr), GFP_KERNEL);
205+
if (!new_dr)
206+
return NULL;
207+
return devres_get(&pdev->dev, new_dr, NULL, NULL);
208+
}
209+
210+
/**
211+
* pcim_enable_device - Managed pci_enable_device()
212+
* @pdev: PCI device to be initialized
213+
*
214+
* Managed pci_enable_device().
215+
*/
216+
int pcim_enable_device(struct pci_dev *pdev)
217+
{
218+
struct pci_devres *dr;
219+
int rc;
220+
221+
dr = get_pci_dr(pdev);
222+
if (unlikely(!dr))
223+
return -ENOMEM;
224+
if (dr->enabled)
225+
return 0;
226+
227+
rc = pci_enable_device(pdev);
228+
if (!rc) {
229+
pdev->is_managed = 1;
230+
dr->enabled = 1;
231+
}
232+
return rc;
233+
}
234+
EXPORT_SYMBOL(pcim_enable_device);
235+
236+
/**
237+
* pcim_pin_device - Pin managed PCI device
238+
* @pdev: PCI device to pin
239+
*
240+
* Pin managed PCI device @pdev. Pinned device won't be disabled on
241+
* driver detach. @pdev must have been enabled with
242+
* pcim_enable_device().
243+
*/
244+
void pcim_pin_device(struct pci_dev *pdev)
245+
{
246+
struct pci_devres *dr;
247+
248+
dr = find_pci_dr(pdev);
249+
WARN_ON(!dr || !dr->enabled);
250+
if (dr)
251+
dr->pinned = 1;
252+
}
253+
EXPORT_SYMBOL(pcim_pin_device);
254+
14255
static void pcim_iomap_release(struct device *gendev, void *res)
15256
{
16257
struct pci_dev *dev = to_pci_dev(gendev);

0 commit comments

Comments
 (0)