]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
pci: Make auto-config code a little more robust
authorPhil Sutter <phil@nwl.cc>
Sun, 3 Jan 2021 22:06:45 +0000 (23:06 +0100)
committerStefan Roese <sr@denx.de>
Wed, 27 Jan 2021 06:29:43 +0000 (07:29 +0100)
On my DS414, some PCI devices return odd values when probing BAR sizes.
An obvious case is all-ones response, the Linux driver
(drivers/pci/probe.c) catches those explicitly and a comment explains
that either bit 0 or bit 1 must be clear (depending on MEM or IO type).
Other BARs return e.g. 0xfff0000f or 0xfff00004 and thus manage to break
size calculation due to the "middle" zeroes. Mitigate that copying more
or less what Linux does and do a "find least bit set".

Signed-off-by: Phil Sutter <phil@nwl.cc>
Reviewed-by: Stefan Roese <sr@denx.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
drivers/pci/pci_auto.c

index 68ef4e8092a91c4254a63242f239ad7562c59282..b37dd994e52d289f67205e278be2cdd4805504d2 100644 (file)
@@ -47,16 +47,17 @@ void dm_pciauto_setup_device(struct udevice *dev, int bars_num,
                        dm_pci_write_config32(dev, bar, 0xffffffff);
                dm_pci_read_config32(dev, bar, &bar_response);
 
-               /* If BAR is not implemented go to the next BAR */
-               if (!bar_response)
+               /* If BAR is not implemented (or invalid) go to the next BAR */
+               if (!bar_response || bar_response == 0xffffffff)
                        continue;
 
                found_mem64 = 0;
 
                /* Check the BAR type and set our address mask */
                if (bar_response & PCI_BASE_ADDRESS_SPACE) {
-                       bar_size = ((~(bar_response & PCI_BASE_ADDRESS_IO_MASK))
-                                  & 0xffff) + 1;
+                       bar_size = bar_response & PCI_BASE_ADDRESS_IO_MASK;
+                       bar_size &= ~(bar_size - 1);
+
                        if (!enum_only)
                                bar_res = io;