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: 2022-12-09 01:23:36 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           0 :                 if (res->flags & IORESOURCE_IO)
     218             :                         root = &ioport_resource;
     219             :                 else
     220           0 :                         root = &iomem_resource;
     221             :         }
     222             : 
     223           0 :         pci_info(dev, "BAR %d: trying firmware assignment %pR\n",
     224             :                  resno, res);
     225           0 :         conflict = request_resource_conflict(root, res);
     226           0 :         if (conflict) {
     227           0 :                 pci_info(dev, "BAR %d: %pR conflicts with %s %pR\n",
     228             :                          resno, res, conflict->name, conflict);
     229           0 :                 res->start = start;
     230           0 :                 res->end = end;
     231           0 :                 res->flags |= IORESOURCE_UNSET;
     232           0 :                 return -EBUSY;
     233             :         }
     234             :         return 0;
     235             : }
     236             : 
     237             : /*
     238             :  * We don't have to worry about legacy ISA devices, so nothing to do here.
     239             :  * This is marked as __weak because multiple architectures define it; it should
     240             :  * eventually go away.
     241             :  */
     242           0 : resource_size_t __weak pcibios_align_resource(void *data,
     243             :                                               const struct resource *res,
     244             :                                               resource_size_t size,
     245             :                                               resource_size_t align)
     246             : {
     247           0 :        return res->start;
     248             : }
     249             : 
     250           0 : static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
     251             :                 int resno, resource_size_t size, resource_size_t align)
     252             : {
     253           0 :         struct resource *res = dev->resource + resno;
     254             :         resource_size_t min;
     255             :         int ret;
     256             : 
     257           0 :         min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
     258             : 
     259             :         /*
     260             :          * First, try exact prefetching match.  Even if a 64-bit
     261             :          * prefetchable bridge window is below 4GB, we can't put a 32-bit
     262             :          * prefetchable resource in it because pbus_size_mem() assumes a
     263             :          * 64-bit window will contain no 32-bit resources.  If we assign
     264             :          * things differently than they were sized, not everything will fit.
     265             :          */
     266           0 :         ret = pci_bus_alloc_resource(bus, res, size, align, min,
     267             :                                      IORESOURCE_PREFETCH | IORESOURCE_MEM_64,
     268             :                                      pcibios_align_resource, dev);
     269           0 :         if (ret == 0)
     270             :                 return 0;
     271             : 
     272             :         /*
     273             :          * If the prefetchable window is only 32 bits wide, we can put
     274             :          * 64-bit prefetchable resources in it.
     275             :          */
     276           0 :         if ((res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) ==
     277             :              (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) {
     278           0 :                 ret = pci_bus_alloc_resource(bus, res, size, align, min,
     279             :                                              IORESOURCE_PREFETCH,
     280             :                                              pcibios_align_resource, dev);
     281           0 :                 if (ret == 0)
     282             :                         return 0;
     283             :         }
     284             : 
     285             :         /*
     286             :          * If we didn't find a better match, we can put any memory resource
     287             :          * in a non-prefetchable window.  If this resource is 32 bits and
     288             :          * non-prefetchable, the first call already tried the only possibility
     289             :          * so we don't need to try again.
     290             :          */
     291           0 :         if (res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64))
     292           0 :                 ret = pci_bus_alloc_resource(bus, res, size, align, min, 0,
     293             :                                              pcibios_align_resource, dev);
     294             : 
     295             :         return ret;
     296             : }
     297             : 
     298           0 : static int _pci_assign_resource(struct pci_dev *dev, int resno,
     299             :                                 resource_size_t size, resource_size_t min_align)
     300             : {
     301             :         struct pci_bus *bus;
     302             :         int ret;
     303             : 
     304           0 :         bus = dev->bus;
     305           0 :         while ((ret = __pci_assign_resource(bus, dev, resno, size, min_align))) {
     306           0 :                 if (!bus->parent || !bus->self->transparent)
     307             :                         break;
     308             :                 bus = bus->parent;
     309             :         }
     310             : 
     311           0 :         return ret;
     312             : }
     313             : 
     314           0 : int pci_assign_resource(struct pci_dev *dev, int resno)
     315             : {
     316           0 :         struct resource *res = dev->resource + resno;
     317             :         resource_size_t align, size;
     318             :         int ret;
     319             : 
     320           0 :         if (res->flags & IORESOURCE_PCI_FIXED)
     321             :                 return 0;
     322             : 
     323           0 :         res->flags |= IORESOURCE_UNSET;
     324           0 :         align = pci_resource_alignment(dev, res);
     325           0 :         if (!align) {
     326           0 :                 pci_info(dev, "BAR %d: can't assign %pR (bogus alignment)\n",
     327             :                          resno, res);
     328           0 :                 return -EINVAL;
     329             :         }
     330             : 
     331           0 :         size = resource_size(res);
     332           0 :         ret = _pci_assign_resource(dev, resno, size, align);
     333             : 
     334             :         /*
     335             :          * If we failed to assign anything, let's try the address
     336             :          * where firmware left it.  That at least has a chance of
     337             :          * working, which is better than just leaving it disabled.
     338             :          */
     339           0 :         if (ret < 0) {
     340           0 :                 pci_info(dev, "BAR %d: no space for %pR\n", resno, res);
     341           0 :                 ret = pci_revert_fw_address(res, dev, resno, size);
     342             :         }
     343             : 
     344           0 :         if (ret < 0) {
     345           0 :                 pci_info(dev, "BAR %d: failed to assign %pR\n", resno, res);
     346           0 :                 return ret;
     347             :         }
     348             : 
     349           0 :         res->flags &= ~IORESOURCE_UNSET;
     350           0 :         res->flags &= ~IORESOURCE_STARTALIGN;
     351           0 :         pci_info(dev, "BAR %d: assigned %pR\n", resno, res);
     352           0 :         if (resno < PCI_BRIDGE_RESOURCES)
     353             :                 pci_update_resource(dev, resno);
     354             : 
     355             :         return 0;
     356             : }
     357             : EXPORT_SYMBOL(pci_assign_resource);
     358             : 
     359           0 : int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsize,
     360             :                         resource_size_t min_align)
     361             : {
     362           0 :         struct resource *res = dev->resource + resno;
     363             :         unsigned long flags;
     364             :         resource_size_t new_size;
     365             :         int ret;
     366             : 
     367           0 :         if (res->flags & IORESOURCE_PCI_FIXED)
     368             :                 return 0;
     369             : 
     370           0 :         flags = res->flags;
     371           0 :         res->flags |= IORESOURCE_UNSET;
     372           0 :         if (!res->parent) {
     373           0 :                 pci_info(dev, "BAR %d: can't reassign an unassigned resource %pR\n",
     374             :                          resno, res);
     375           0 :                 return -EINVAL;
     376             :         }
     377             : 
     378             :         /* already aligned with min_align */
     379           0 :         new_size = resource_size(res) + addsize;
     380           0 :         ret = _pci_assign_resource(dev, resno, new_size, min_align);
     381           0 :         if (ret) {
     382           0 :                 res->flags = flags;
     383           0 :                 pci_info(dev, "BAR %d: %pR (failed to expand by %#llx)\n",
     384             :                          resno, res, (unsigned long long) addsize);
     385           0 :                 return ret;
     386             :         }
     387             : 
     388           0 :         res->flags &= ~IORESOURCE_UNSET;
     389           0 :         res->flags &= ~IORESOURCE_STARTALIGN;
     390           0 :         pci_info(dev, "BAR %d: reassigned %pR (expanded by %#llx)\n",
     391             :                  resno, res, (unsigned long long) addsize);
     392           0 :         if (resno < PCI_BRIDGE_RESOURCES)
     393             :                 pci_update_resource(dev, resno);
     394             : 
     395             :         return 0;
     396             : }
     397             : 
     398           0 : void pci_release_resource(struct pci_dev *dev, int resno)
     399             : {
     400           0 :         struct resource *res = dev->resource + resno;
     401             : 
     402           0 :         pci_info(dev, "BAR %d: releasing %pR\n", resno, res);
     403             : 
     404           0 :         if (!res->parent)
     405             :                 return;
     406             : 
     407           0 :         release_resource(res);
     408           0 :         res->end = resource_size(res) - 1;
     409           0 :         res->start = 0;
     410           0 :         res->flags |= IORESOURCE_UNSET;
     411             : }
     412             : EXPORT_SYMBOL(pci_release_resource);
     413             : 
     414           0 : int pci_resize_resource(struct pci_dev *dev, int resno, int size)
     415             : {
     416           0 :         struct resource *res = dev->resource + resno;
     417             :         struct pci_host_bridge *host;
     418             :         int old, ret;
     419             :         u32 sizes;
     420             :         u16 cmd;
     421             : 
     422             :         /* Check if we must preserve the firmware's resource assignment */
     423           0 :         host = pci_find_host_bridge(dev->bus);
     424           0 :         if (host->preserve_config)
     425             :                 return -ENOTSUPP;
     426             : 
     427             :         /* Make sure the resource isn't assigned before resizing it. */
     428           0 :         if (!(res->flags & IORESOURCE_UNSET))
     429             :                 return -EBUSY;
     430             : 
     431           0 :         pci_read_config_word(dev, PCI_COMMAND, &cmd);
     432           0 :         if (cmd & PCI_COMMAND_MEMORY)
     433             :                 return -EBUSY;
     434             : 
     435           0 :         sizes = pci_rebar_get_possible_sizes(dev, resno);
     436           0 :         if (!sizes)
     437             :                 return -ENOTSUPP;
     438             : 
     439           0 :         if (!(sizes & BIT(size)))
     440             :                 return -EINVAL;
     441             : 
     442           0 :         old = pci_rebar_get_current_size(dev, resno);
     443           0 :         if (old < 0)
     444             :                 return old;
     445             : 
     446           0 :         ret = pci_rebar_set_size(dev, resno, size);
     447           0 :         if (ret)
     448             :                 return ret;
     449             : 
     450           0 :         res->end = res->start + pci_rebar_size_to_bytes(size) - 1;
     451             : 
     452             :         /* Check if the new config works by trying to assign everything. */
     453           0 :         if (dev->bus->self) {
     454           0 :                 ret = pci_reassign_bridge_resources(dev->bus->self, res->flags);
     455           0 :                 if (ret)
     456             :                         goto error_resize;
     457             :         }
     458             :         return 0;
     459             : 
     460             : error_resize:
     461           0 :         pci_rebar_set_size(dev, resno, old);
     462           0 :         res->end = res->start + pci_rebar_size_to_bytes(old) - 1;
     463           0 :         return ret;
     464             : }
     465             : EXPORT_SYMBOL(pci_resize_resource);
     466             : 
     467           0 : int pci_enable_resources(struct pci_dev *dev, int mask)
     468             : {
     469             :         u16 cmd, old_cmd;
     470             :         int i;
     471             :         struct resource *r;
     472             : 
     473           0 :         pci_read_config_word(dev, PCI_COMMAND, &cmd);
     474           0 :         old_cmd = cmd;
     475             : 
     476           0 :         for (i = 0; i < PCI_NUM_RESOURCES; i++) {
     477           0 :                 if (!(mask & (1 << i)))
     478           0 :                         continue;
     479             : 
     480           0 :                 r = &dev->resource[i];
     481             : 
     482           0 :                 if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
     483           0 :                         continue;
     484           0 :                 if ((i == PCI_ROM_RESOURCE) &&
     485           0 :                                 (!(r->flags & IORESOURCE_ROM_ENABLE)))
     486           0 :                         continue;
     487             : 
     488           0 :                 if (r->flags & IORESOURCE_UNSET) {
     489           0 :                         pci_err(dev, "can't enable device: BAR %d %pR not assigned\n",
     490             :                                 i, r);
     491           0 :                         return -EINVAL;
     492             :                 }
     493             : 
     494           0 :                 if (!r->parent) {
     495           0 :                         pci_err(dev, "can't enable device: BAR %d %pR not claimed\n",
     496             :                                 i, r);
     497           0 :                         return -EINVAL;
     498             :                 }
     499             : 
     500           0 :                 if (r->flags & IORESOURCE_IO)
     501           0 :                         cmd |= PCI_COMMAND_IO;
     502           0 :                 if (r->flags & IORESOURCE_MEM)
     503           0 :                         cmd |= PCI_COMMAND_MEMORY;
     504             :         }
     505             : 
     506           0 :         if (cmd != old_cmd) {
     507           0 :                 pci_info(dev, "enabling device (%04x -> %04x)\n", old_cmd, cmd);
     508           0 :                 pci_write_config_word(dev, PCI_COMMAND, cmd);
     509             :         }
     510             :         return 0;
     511             : }

Generated by: LCOV version 1.14