LCOV - code coverage report
Current view: top level - drivers/pci - setup-res.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 197 0.0 %
Date: 2023-08-24 13:40:31 Functions: 0 14 0.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Support routines for initializing a PCI subsystem
       4             :  *
       5             :  * Extruded from code written by
       6             :  *      Dave Rusling (david.rusling@reo.mts.dec.com)
       7             :  *      David Mosberger (davidm@cs.arizona.edu)
       8             :  *      David Miller (davem@redhat.com)
       9             :  *
      10             :  * Fixed for multiple PCI buses, 1999 Andrea Arcangeli <andrea@suse.de>
      11             :  *
      12             :  * Nov 2000, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
      13             :  *           Resource sorting
      14             :  */
      15             : 
      16             : #include <linux/kernel.h>
      17             : #include <linux/export.h>
      18             : #include <linux/pci.h>
      19             : #include <linux/errno.h>
      20             : #include <linux/ioport.h>
      21             : #include <linux/cache.h>
      22             : #include <linux/slab.h>
      23             : #include "pci.h"
      24             : 
      25           0 : static void pci_std_update_resource(struct pci_dev *dev, int resno)
      26             : {
      27             :         struct pci_bus_region region;
      28             :         bool disable;
      29             :         u16 cmd;
      30             :         u32 new, check, mask;
      31             :         int reg;
      32           0 :         struct resource *res = dev->resource + resno;
      33             : 
      34             :         /* Per SR-IOV spec 3.4.1.11, VF BARs are RO zero */
      35           0 :         if (dev->is_virtfn)
      36           0 :                 return;
      37             : 
      38             :         /*
      39             :          * Ignore resources for unimplemented BARs and unused resource slots
      40             :          * for 64 bit BARs.
      41             :          */
      42           0 :         if (!res->flags)
      43             :                 return;
      44             : 
      45           0 :         if (res->flags & IORESOURCE_UNSET)
      46             :                 return;
      47             : 
      48             :         /*
      49             :          * Ignore non-moveable resources.  This might be legacy resources for
      50             :          * which no functional BAR register exists or another important
      51             :          * system resource we shouldn't move around.
      52             :          */
      53           0 :         if (res->flags & IORESOURCE_PCI_FIXED)
      54             :                 return;
      55             : 
      56           0 :         pcibios_resource_to_bus(dev->bus, &region, res);
      57           0 :         new = region.start;
      58             : 
      59           0 :         if (res->flags & IORESOURCE_IO) {
      60           0 :                 mask = (u32)PCI_BASE_ADDRESS_IO_MASK;
      61           0 :                 new |= res->flags & ~PCI_BASE_ADDRESS_IO_MASK;
      62           0 :         } else if (resno == PCI_ROM_RESOURCE) {
      63             :                 mask = PCI_ROM_ADDRESS_MASK;
      64             :         } else {
      65           0 :                 mask = (u32)PCI_BASE_ADDRESS_MEM_MASK;
      66           0 :                 new |= res->flags & ~PCI_BASE_ADDRESS_MEM_MASK;
      67             :         }
      68             : 
      69           0 :         if (resno < PCI_ROM_RESOURCE) {
      70           0 :                 reg = PCI_BASE_ADDRESS_0 + 4 * resno;
      71           0 :         } else if (resno == PCI_ROM_RESOURCE) {
      72             : 
      73             :                 /*
      74             :                  * Apparently some Matrox devices have ROM BARs that read
      75             :                  * as zero when disabled, so don't update ROM BARs unless
      76             :                  * they're enabled.  See
      77             :                  * https://lore.kernel.org/r/43147B3D.1030309@vc.cvut.cz/
      78             :                  * But we must update ROM BAR for buggy devices where even a
      79             :                  * disabled ROM can conflict with other BARs.
      80             :                  */
      81           0 :                 if (!(res->flags & IORESOURCE_ROM_ENABLE) &&
      82           0 :                     !dev->rom_bar_overlap)
      83             :                         return;
      84             : 
      85           0 :                 reg = dev->rom_base_reg;
      86           0 :                 if (res->flags & IORESOURCE_ROM_ENABLE)
      87           0 :                         new |= PCI_ROM_ADDRESS_ENABLE;
      88             :         } else
      89             :                 return;
      90             : 
      91             :         /*
      92             :          * We can't update a 64-bit BAR atomically, so when possible,
      93             :          * disable decoding so that a half-updated BAR won't conflict
      94             :          * with another device.
      95             :          */
      96           0 :         disable = (res->flags & IORESOURCE_MEM_64) && !dev->mmio_always_on;
      97           0 :         if (disable) {
      98           0 :                 pci_read_config_word(dev, PCI_COMMAND, &cmd);
      99           0 :                 pci_write_config_word(dev, PCI_COMMAND,
     100           0 :                                       cmd & ~PCI_COMMAND_MEMORY);
     101             :         }
     102             : 
     103           0 :         pci_write_config_dword(dev, reg, new);
     104           0 :         pci_read_config_dword(dev, reg, &check);
     105             : 
     106           0 :         if ((new ^ check) & mask) {
     107           0 :                 pci_err(dev, "BAR %d: error updating (%#08x != %#08x)\n",
     108             :                         resno, new, check);
     109             :         }
     110             : 
     111           0 :         if (res->flags & IORESOURCE_MEM_64) {
     112           0 :                 new = region.start >> 16 >> 16;
     113           0 :                 pci_write_config_dword(dev, reg + 4, new);
     114           0 :                 pci_read_config_dword(dev, reg + 4, &check);
     115           0 :                 if (check != new) {
     116           0 :                         pci_err(dev, "BAR %d: error updating (high %#08x != %#08x)\n",
     117             :                                 resno, new, check);
     118             :                 }
     119             :         }
     120             : 
     121           0 :         if (disable)
     122           0 :                 pci_write_config_word(dev, PCI_COMMAND, cmd);
     123             : }
     124             : 
     125           0 : void pci_update_resource(struct pci_dev *dev, int resno)
     126             : {
     127           0 :         if (resno <= PCI_ROM_RESOURCE)
     128           0 :                 pci_std_update_resource(dev, resno);
     129             : #ifdef CONFIG_PCI_IOV
     130             :         else if (resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END)
     131             :                 pci_iov_update_resource(dev, resno);
     132             : #endif
     133           0 : }
     134             : 
     135           0 : int pci_claim_resource(struct pci_dev *dev, int resource)
     136             : {
     137           0 :         struct resource *res = &dev->resource[resource];
     138             :         struct resource *root, *conflict;
     139             : 
     140           0 :         if (res->flags & IORESOURCE_UNSET) {
     141           0 :                 pci_info(dev, "can't claim BAR %d %pR: no address assigned\n",
     142             :                          resource, res);
     143           0 :                 return -EINVAL;
     144             :         }
     145             : 
     146             :         /*
     147             :          * If we have a shadow copy in RAM, the PCI device doesn't respond
     148             :          * to the shadow range, so we don't need to claim it, and upstream
     149             :          * bridges don't need to route the range to the device.
     150             :          */
     151           0 :         if (res->flags & IORESOURCE_ROM_SHADOW)
     152             :                 return 0;
     153             : 
     154           0 :         root = pci_find_parent_resource(dev, res);
     155           0 :         if (!root) {
     156           0 :                 pci_info(dev, "can't claim BAR %d %pR: no compatible bridge window\n",
     157             :                          resource, res);
     158           0 :                 res->flags |= IORESOURCE_UNSET;
     159           0 :                 return -EINVAL;
     160             :         }
     161             : 
     162           0 :         conflict = request_resource_conflict(root, res);
     163           0 :         if (conflict) {
     164           0 :                 pci_info(dev, "can't claim BAR %d %pR: address conflict with %s %pR\n",
     165             :                          resource, res, conflict->name, conflict);
     166           0 :                 res->flags |= IORESOURCE_UNSET;
     167           0 :                 return -EBUSY;
     168             :         }
     169             : 
     170             :         return 0;
     171             : }
     172             : EXPORT_SYMBOL(pci_claim_resource);
     173             : 
     174           0 : void pci_disable_bridge_window(struct pci_dev *dev)
     175             : {
     176             :         /* MMIO Base/Limit */
     177           0 :         pci_write_config_dword(dev, PCI_MEMORY_BASE, 0x0000fff0);
     178             : 
     179             :         /* Prefetchable MMIO Base/Limit */
     180           0 :         pci_write_config_dword(dev, PCI_PREF_LIMIT_UPPER32, 0);
     181           0 :         pci_write_config_dword(dev, PCI_PREF_MEMORY_BASE, 0x0000fff0);
     182           0 :         pci_write_config_dword(dev, PCI_PREF_BASE_UPPER32, 0xffffffff);
     183           0 : }
     184             : 
     185             : /*
     186             :  * Generic function that returns a value indicating that the device's
     187             :  * original BIOS BAR address was not saved and so is not available for
     188             :  * reinstatement.
     189             :  *
     190             :  * Can be over-ridden by architecture specific code that implements
     191             :  * reinstatement functionality rather than leaving it disabled when
     192             :  * normal allocation attempts fail.
     193             :  */
     194           0 : resource_size_t __weak pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx)
     195             : {
     196           0 :         return 0;
     197             : }
     198             : 
     199           0 : static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev,
     200             :                 int resno, resource_size_t size)
     201             : {
     202             :         struct resource *root, *conflict;
     203             :         resource_size_t fw_addr, start, end;
     204             : 
     205           0 :         fw_addr = pcibios_retrieve_fw_addr(dev, resno);
     206           0 :         if (!fw_addr)
     207             :                 return -ENOMEM;
     208             : 
     209           0 :         start = res->start;
     210           0 :         end = res->end;
     211           0 :         res->start = fw_addr;
     212           0 :         res->end = res->start + size - 1;
     213           0 :         res->flags &= ~IORESOURCE_UNSET;
     214             : 
     215           0 :         root = pci_find_parent_resource(dev, res);
     216           0 :         if (!root) {
     217             :                 /*
     218             :                  * If dev is behind a bridge, accesses will only reach it
     219             :                  * if res is inside the relevant bridge window.
     220             :                  */
     221           0 :                 if (pci_upstream_bridge(dev))
     222             :                         return -ENXIO;
     223             : 
     224             :                 /*
     225             :                  * On the root bus, assume the host bridge will forward
     226             :                  * everything.
     227             :                  */
     228           0 :                 if (res->flags & IORESOURCE_IO)
     229             :                         root = &ioport_resource;
     230             :                 else
     231           0 :                         root = &iomem_resource;
     232             :         }
     233             : 
     234           0 :         pci_info(dev, "BAR %d: trying firmware assignment %pR\n",
     235             :                  resno, res);
     236           0 :         conflict = request_resource_conflict(root, res);
     237           0 :         if (conflict) {
     238           0 :                 pci_info(dev, "BAR %d: %pR conflicts with %s %pR\n",
     239             :                          resno, res, conflict->name, conflict);
     240           0 :                 res->start = start;
     241           0 :                 res->end = end;
     242           0 :                 res->flags |= IORESOURCE_UNSET;
     243           0 :                 return -EBUSY;
     244             :         }
     245             :         return 0;
     246             : }
     247             : 
     248             : /*
     249             :  * We don't have to worry about legacy ISA devices, so nothing to do here.
     250             :  * This is marked as __weak because multiple architectures define it; it should
     251             :  * eventually go away.
     252             :  */
     253           0 : resource_size_t __weak pcibios_align_resource(void *data,
     254             :                                               const struct resource *res,
     255             :                                               resource_size_t size,
     256             :                                               resource_size_t align)
     257             : {
     258           0 :        return res->start;
     259             : }
     260             : 
     261           0 : static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
     262             :                 int resno, resource_size_t size, resource_size_t align)
     263             : {
     264           0 :         struct resource *res = dev->resource + resno;
     265             :         resource_size_t min;
     266             :         int ret;
     267             : 
     268           0 :         min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
     269             : 
     270             :         /*
     271             :          * First, try exact prefetching match.  Even if a 64-bit
     272             :          * prefetchable bridge window is below 4GB, we can't put a 32-bit
     273             :          * prefetchable resource in it because pbus_size_mem() assumes a
     274             :          * 64-bit window will contain no 32-bit resources.  If we assign
     275             :          * things differently than they were sized, not everything will fit.
     276             :          */
     277           0 :         ret = pci_bus_alloc_resource(bus, res, size, align, min,
     278             :                                      IORESOURCE_PREFETCH | IORESOURCE_MEM_64,
     279             :                                      pcibios_align_resource, dev);
     280           0 :         if (ret == 0)
     281             :                 return 0;
     282             : 
     283             :         /*
     284             :          * If the prefetchable window is only 32 bits wide, we can put
     285             :          * 64-bit prefetchable resources in it.
     286             :          */
     287           0 :         if ((res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) ==
     288             :              (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) {
     289           0 :                 ret = pci_bus_alloc_resource(bus, res, size, align, min,
     290             :                                              IORESOURCE_PREFETCH,
     291             :                                              pcibios_align_resource, dev);
     292           0 :                 if (ret == 0)
     293             :                         return 0;
     294             :         }
     295             : 
     296             :         /*
     297             :          * If we didn't find a better match, we can put any memory resource
     298             :          * in a non-prefetchable window.  If this resource is 32 bits and
     299             :          * non-prefetchable, the first call already tried the only possibility
     300             :          * so we don't need to try again.
     301             :          */
     302           0 :         if (res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64))
     303           0 :                 ret = pci_bus_alloc_resource(bus, res, size, align, min, 0,
     304             :                                              pcibios_align_resource, dev);
     305             : 
     306             :         return ret;
     307             : }
     308             : 
     309           0 : static int _pci_assign_resource(struct pci_dev *dev, int resno,
     310             :                                 resource_size_t size, resource_size_t min_align)
     311             : {
     312             :         struct pci_bus *bus;
     313             :         int ret;
     314             : 
     315           0 :         bus = dev->bus;
     316           0 :         while ((ret = __pci_assign_resource(bus, dev, resno, size, min_align))) {
     317           0 :                 if (!bus->parent || !bus->self->transparent)
     318             :                         break;
     319             :                 bus = bus->parent;
     320             :         }
     321             : 
     322           0 :         return ret;
     323             : }
     324             : 
     325           0 : int pci_assign_resource(struct pci_dev *dev, int resno)
     326             : {
     327           0 :         struct resource *res = dev->resource + resno;
     328             :         resource_size_t align, size;
     329             :         int ret;
     330             : 
     331           0 :         if (res->flags & IORESOURCE_PCI_FIXED)
     332             :                 return 0;
     333             : 
     334           0 :         res->flags |= IORESOURCE_UNSET;
     335           0 :         align = pci_resource_alignment(dev, res);
     336           0 :         if (!align) {
     337           0 :                 pci_info(dev, "BAR %d: can't assign %pR (bogus alignment)\n",
     338             :                          resno, res);
     339           0 :                 return -EINVAL;
     340             :         }
     341             : 
     342           0 :         size = resource_size(res);
     343           0 :         ret = _pci_assign_resource(dev, resno, size, align);
     344             : 
     345             :         /*
     346             :          * If we failed to assign anything, let's try the address
     347             :          * where firmware left it.  That at least has a chance of
     348             :          * working, which is better than just leaving it disabled.
     349             :          */
     350           0 :         if (ret < 0) {
     351           0 :                 pci_info(dev, "BAR %d: no space for %pR\n", resno, res);
     352           0 :                 ret = pci_revert_fw_address(res, dev, resno, size);
     353             :         }
     354             : 
     355           0 :         if (ret < 0) {
     356           0 :                 pci_info(dev, "BAR %d: failed to assign %pR\n", resno, res);
     357           0 :                 return ret;
     358             :         }
     359             : 
     360           0 :         res->flags &= ~IORESOURCE_UNSET;
     361           0 :         res->flags &= ~IORESOURCE_STARTALIGN;
     362           0 :         pci_info(dev, "BAR %d: assigned %pR\n", resno, res);
     363           0 :         if (resno < PCI_BRIDGE_RESOURCES)
     364             :                 pci_update_resource(dev, resno);
     365             : 
     366             :         return 0;
     367             : }
     368             : EXPORT_SYMBOL(pci_assign_resource);
     369             : 
     370           0 : int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsize,
     371             :                         resource_size_t min_align)
     372             : {
     373           0 :         struct resource *res = dev->resource + resno;
     374             :         unsigned long flags;
     375             :         resource_size_t new_size;
     376             :         int ret;
     377             : 
     378           0 :         if (res->flags & IORESOURCE_PCI_FIXED)
     379             :                 return 0;
     380             : 
     381           0 :         flags = res->flags;
     382           0 :         res->flags |= IORESOURCE_UNSET;
     383           0 :         if (!res->parent) {
     384           0 :                 pci_info(dev, "BAR %d: can't reassign an unassigned resource %pR\n",
     385             :                          resno, res);
     386           0 :                 return -EINVAL;
     387             :         }
     388             : 
     389             :         /* already aligned with min_align */
     390           0 :         new_size = resource_size(res) + addsize;
     391           0 :         ret = _pci_assign_resource(dev, resno, new_size, min_align);
     392           0 :         if (ret) {
     393           0 :                 res->flags = flags;
     394           0 :                 pci_info(dev, "BAR %d: %pR (failed to expand by %#llx)\n",
     395             :                          resno, res, (unsigned long long) addsize);
     396           0 :                 return ret;
     397             :         }
     398             : 
     399           0 :         res->flags &= ~IORESOURCE_UNSET;
     400           0 :         res->flags &= ~IORESOURCE_STARTALIGN;
     401           0 :         pci_info(dev, "BAR %d: reassigned %pR (expanded by %#llx)\n",
     402             :                  resno, res, (unsigned long long) addsize);
     403           0 :         if (resno < PCI_BRIDGE_RESOURCES)
     404             :                 pci_update_resource(dev, resno);
     405             : 
     406             :         return 0;
     407             : }
     408             : 
     409           0 : void pci_release_resource(struct pci_dev *dev, int resno)
     410             : {
     411           0 :         struct resource *res = dev->resource + resno;
     412             : 
     413           0 :         pci_info(dev, "BAR %d: releasing %pR\n", resno, res);
     414             : 
     415           0 :         if (!res->parent)
     416             :                 return;
     417             : 
     418           0 :         release_resource(res);
     419           0 :         res->end = resource_size(res) - 1;
     420           0 :         res->start = 0;
     421           0 :         res->flags |= IORESOURCE_UNSET;
     422             : }
     423             : EXPORT_SYMBOL(pci_release_resource);
     424             : 
     425           0 : int pci_resize_resource(struct pci_dev *dev, int resno, int size)
     426             : {
     427           0 :         struct resource *res = dev->resource + resno;
     428             :         struct pci_host_bridge *host;
     429             :         int old, ret;
     430             :         u32 sizes;
     431             :         u16 cmd;
     432             : 
     433             :         /* Check if we must preserve the firmware's resource assignment */
     434           0 :         host = pci_find_host_bridge(dev->bus);
     435           0 :         if (host->preserve_config)
     436             :                 return -ENOTSUPP;
     437             : 
     438             :         /* Make sure the resource isn't assigned before resizing it. */
     439           0 :         if (!(res->flags & IORESOURCE_UNSET))
     440             :                 return -EBUSY;
     441             : 
     442           0 :         pci_read_config_word(dev, PCI_COMMAND, &cmd);
     443           0 :         if (cmd & PCI_COMMAND_MEMORY)
     444             :                 return -EBUSY;
     445             : 
     446           0 :         sizes = pci_rebar_get_possible_sizes(dev, resno);
     447           0 :         if (!sizes)
     448             :                 return -ENOTSUPP;
     449             : 
     450           0 :         if (!(sizes & BIT(size)))
     451             :                 return -EINVAL;
     452             : 
     453           0 :         old = pci_rebar_get_current_size(dev, resno);
     454           0 :         if (old < 0)
     455             :                 return old;
     456             : 
     457           0 :         ret = pci_rebar_set_size(dev, resno, size);
     458           0 :         if (ret)
     459             :                 return ret;
     460             : 
     461           0 :         res->end = res->start + pci_rebar_size_to_bytes(size) - 1;
     462             : 
     463             :         /* Check if the new config works by trying to assign everything. */
     464           0 :         if (dev->bus->self) {
     465           0 :                 ret = pci_reassign_bridge_resources(dev->bus->self, res->flags);
     466           0 :                 if (ret)
     467             :                         goto error_resize;
     468             :         }
     469             :         return 0;
     470             : 
     471             : error_resize:
     472           0 :         pci_rebar_set_size(dev, resno, old);
     473           0 :         res->end = res->start + pci_rebar_size_to_bytes(old) - 1;
     474           0 :         return ret;
     475             : }
     476             : EXPORT_SYMBOL(pci_resize_resource);
     477             : 
     478           0 : int pci_enable_resources(struct pci_dev *dev, int mask)
     479             : {
     480             :         u16 cmd, old_cmd;
     481             :         int i;
     482             :         struct resource *r;
     483             : 
     484           0 :         pci_read_config_word(dev, PCI_COMMAND, &cmd);
     485           0 :         old_cmd = cmd;
     486             : 
     487           0 :         pci_dev_for_each_resource(dev, r, i) {
     488           0 :                 if (!(mask & (1 << i)))
     489           0 :                         continue;
     490             : 
     491           0 :                 if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
     492           0 :                         continue;
     493           0 :                 if ((i == PCI_ROM_RESOURCE) &&
     494           0 :                                 (!(r->flags & IORESOURCE_ROM_ENABLE)))
     495           0 :                         continue;
     496             : 
     497           0 :                 if (r->flags & IORESOURCE_UNSET) {
     498           0 :                         pci_err(dev, "can't enable device: BAR %d %pR not assigned\n",
     499             :                                 i, r);
     500           0 :                         return -EINVAL;
     501             :                 }
     502             : 
     503           0 :                 if (!r->parent) {
     504           0 :                         pci_err(dev, "can't enable device: BAR %d %pR not claimed\n",
     505             :                                 i, r);
     506           0 :                         return -EINVAL;
     507             :                 }
     508             : 
     509           0 :                 if (r->flags & IORESOURCE_IO)
     510           0 :                         cmd |= PCI_COMMAND_IO;
     511           0 :                 if (r->flags & IORESOURCE_MEM)
     512           0 :                         cmd |= PCI_COMMAND_MEMORY;
     513             :         }
     514             : 
     515           0 :         if (cmd != old_cmd) {
     516           0 :                 pci_info(dev, "enabling device (%04x -> %04x)\n", old_cmd, cmd);
     517           0 :                 pci_write_config_word(dev, PCI_COMMAND, cmd);
     518             :         }
     519             :         return 0;
     520             : }

Generated by: LCOV version 1.14