Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PCI: Implement devm_pci_remap_cfgspace()

The introduction of the pci_remap_cfgspace() interface allows PCI host
controller drivers to map PCI config space through a dedicated kernel
interface. Current PCI host controller drivers use the devm_ioremap_*()
devres interfaces to map PCI configuration space regions so in order to
update them to the new pci_remap_cfgspace() mapping interface a new set of
devres interfaces should be implemented so that PCI host controller drivers
can make use of them.

Introduce two new functions in the PCI kernel layer and Devres
documentation:

- devm_pci_remap_cfgspace()
- devm_pci_remap_cfg_resource()

so that PCI host controller drivers can make use of them to map PCI
configuration space regions.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Cc: Jonathan Corbet <corbet@lwn.net>

authored by

Lorenzo Pieralisi and committed by
Bjorn Helgaas
490cb6dd 6524754e

+91 -2
+4 -2
Documentation/driver-model/devres.txt
··· 342 342 devm_free_percpu() 343 343 344 344 PCI 345 - pcim_enable_device() : after success, all PCI ops become managed 346 - pcim_pin_device() : keep PCI device enabled after release 345 + devm_pci_remap_cfgspace() : ioremap PCI configuration space 346 + devm_pci_remap_cfg_resource() : ioremap PCI configuration space resource 347 + pcim_enable_device() : after success, all PCI ops become managed 348 + pcim_pin_device() : keep PCI device enabled after release 347 349 348 350 PHY 349 351 devm_usb_get_phy()
+82
drivers/pci/pci.c
··· 3401 3401 #endif 3402 3402 } 3403 3403 3404 + /** 3405 + * devm_pci_remap_cfgspace - Managed pci_remap_cfgspace() 3406 + * @dev: Generic device to remap IO address for 3407 + * @offset: Resource address to map 3408 + * @size: Size of map 3409 + * 3410 + * Managed pci_remap_cfgspace(). Map is automatically unmapped on driver 3411 + * detach. 3412 + */ 3413 + void __iomem *devm_pci_remap_cfgspace(struct device *dev, 3414 + resource_size_t offset, 3415 + resource_size_t size) 3416 + { 3417 + void __iomem **ptr, *addr; 3418 + 3419 + ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL); 3420 + if (!ptr) 3421 + return NULL; 3422 + 3423 + addr = pci_remap_cfgspace(offset, size); 3424 + if (addr) { 3425 + *ptr = addr; 3426 + devres_add(dev, ptr); 3427 + } else 3428 + devres_free(ptr); 3429 + 3430 + return addr; 3431 + } 3432 + EXPORT_SYMBOL(devm_pci_remap_cfgspace); 3433 + 3434 + /** 3435 + * devm_pci_remap_cfg_resource - check, request region and ioremap cfg resource 3436 + * @dev: generic device to handle the resource for 3437 + * @res: configuration space resource to be handled 3438 + * 3439 + * Checks that a resource is a valid memory region, requests the memory 3440 + * region and ioremaps with pci_remap_cfgspace() API that ensures the 3441 + * proper PCI configuration space memory attributes are guaranteed. 3442 + * 3443 + * All operations are managed and will be undone on driver detach. 3444 + * 3445 + * Returns a pointer to the remapped memory or an ERR_PTR() encoded error code 3446 + * on failure. Usage example: 3447 + * 3448 + * res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 3449 + * base = devm_pci_remap_cfg_resource(&pdev->dev, res); 3450 + * if (IS_ERR(base)) 3451 + * return PTR_ERR(base); 3452 + */ 3453 + void __iomem *devm_pci_remap_cfg_resource(struct device *dev, 3454 + struct resource *res) 3455 + { 3456 + resource_size_t size; 3457 + const char *name; 3458 + void __iomem *dest_ptr; 3459 + 3460 + BUG_ON(!dev); 3461 + 3462 + if (!res || resource_type(res) != IORESOURCE_MEM) { 3463 + dev_err(dev, "invalid resource\n"); 3464 + return IOMEM_ERR_PTR(-EINVAL); 3465 + } 3466 + 3467 + size = resource_size(res); 3468 + name = res->name ?: dev_name(dev); 3469 + 3470 + if (!devm_request_mem_region(dev, res->start, size, name)) { 3471 + dev_err(dev, "can't request region for resource %pR\n", res); 3472 + return IOMEM_ERR_PTR(-EBUSY); 3473 + } 3474 + 3475 + dest_ptr = devm_pci_remap_cfgspace(dev, res->start, size); 3476 + if (!dest_ptr) { 3477 + dev_err(dev, "ioremap failed for resource %pR\n", res); 3478 + devm_release_mem_region(dev, res->start, size); 3479 + dest_ptr = IOMEM_ERR_PTR(-ENOMEM); 3480 + } 3481 + 3482 + return dest_ptr; 3483 + } 3484 + EXPORT_SYMBOL(devm_pci_remap_cfg_resource); 3485 + 3404 3486 static void __pci_set_master(struct pci_dev *dev, bool enable) 3405 3487 { 3406 3488 u16 old_cmd, cmd;
+5
include/linux/pci.h
··· 1199 1199 phys_addr_t pci_pio_to_address(unsigned long pio); 1200 1200 int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr); 1201 1201 void pci_unmap_iospace(struct resource *res); 1202 + void __iomem *devm_pci_remap_cfgspace(struct device *dev, 1203 + resource_size_t offset, 1204 + resource_size_t size); 1205 + void __iomem *devm_pci_remap_cfg_resource(struct device *dev, 1206 + struct resource *res); 1202 1207 1203 1208 static inline pci_bus_addr_t pci_bus_address(struct pci_dev *pdev, int bar) 1204 1209 {