Re: [PATCH] Add pci=assign-busses quirk to Dell Latitude D505

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Sep 15, 2014 at 11:53 AM, Wei Yang <weiyang@xxxxxxxxxxxxxxxxxx> wrote:
> On Mon, Sep 15, 2014 at 12:10:27AM +0200, Andreas Noever wrote:
>>[+cc Thomas, your regression has probably the same cause]
>>
>>This looks a like it is going to be a little more complicated than anticipated.
>>
>>pci_scan_bus has two main branches. One for "broken" hardware and cardbus and
>>another one for bridges whose configuration looks sane.
>>
>>David's working 3.2 Kernel does the following:
>>pci 0000:00:1e.0: PCI bridge to [bus 01-01] (subtractive decode)
>>pci 0000:01:01.0: bridge configuration invalid ([bus 00-00]), reconfiguring
>>
>>The 00:1e bridge is deemed sane and the 01:01 (cardbus) bridge below it is
>>deemed broken. pci_scan_bridge than assigns bus [2-5] to 01:01 without touching
>>1e (so we just got 4 imaginary busses). We just print a warning:
>>pci_bus 0000:02: [bus 02-05] partially hidden behind transparent bridge 0000:01 [bus 01-01]
>>
>>After returning to 00:1e (in the sane branch) we also do not update our
>>subordinate and just return. Later yenta_socket sees that this is nuts and
>>carefully increases the subordinate of 00:1e.
>>
>>My patch series for 3.15 was trying to make sure that pci_scan_bus does not
>>overstep its resources. So now we now refuse to create bus 2 under [01-01]
>>(fc1b2531 PCI: Don't scan random busses in pci_scan_bridge()) and a little
>>later we would forbid the cardbus code in pci_scan_bridge from reserving 4 more
>>busses (1820ffdc PCI: Make sure bus number resources stay within their parents
>>bounds). At least these two would need to be reverted.
>>
>>As an alternative the following patch tries grow the bus window, if necessary
>>by growing its parents bus window (recursively). This should make the yenta
>>fixup unnecessary. I have tested the patch with normal pci bridges + setpci,
>>since I don't have access to a cardbus system.
>>
>>So if you have time please test this and/or try to revert the two mentioned
>>commits.
>>
>>Thanks,
>>Andreas
>>---
>> drivers/pci/probe.c | 45 ++++++++++++++++++++++++++++++++++++---------
>> 1 file changed, 36 insertions(+), 9 deletions(-)
>>
>>diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
>>index e3cf8a2..81dd668 100644
>>--- a/drivers/pci/probe.c
>>+++ b/drivers/pci/probe.c
>>@@ -740,6 +740,30 @@ struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
>> }
>> EXPORT_SYMBOL(pci_add_new_bus);
>>
>>+int pci_grow_bus(struct pci_bus *bus, int bus_max)
>>+{
>>+      struct resource *res = &bus->busn_res;
>>+      struct resource old_res = *res;
>>+      int ret;
>>+      if (res->end >= bus_max)
>>+              return 0;
>>+      if (!bus->self || pci_is_root_bus(bus)) {
>>+              dev_printk(KERN_DEBUG, &bus->dev,
>>+                         "root busn_res %pR cannot grow\n", &res);
>>+              return -EBUSY;
>>+      }
>>+      ret = pci_grow_bus(bus->parent, bus_max);
>>+      if (ret)
>>+              return ret;
>>+      ret = adjust_resource(res, res->start, bus_max - res->start + 1);
>>+      dev_printk(KERN_DEBUG, &bus->dev,
>>+                      "busn_res: %pR end %s grown to %02x\n",
>>+                      &old_res, ret ? "cannot be" : "has", bus_max);
>>+
>
> If adjust_resource fails, I think we can't write the bus_max into the bridge
> register.
Right, there is an if statement missing. Thanks.

>>+      pci_write_config_byte(bus->self, PCI_SUBORDINATE_BUS, bus_max);
>>+      return ret;
>>+}
>>+
>> /*
>>  * If it's a bridge, configure it and scan the bus behind it.
>>  * For CardBus bridges, we don't scan behind as the devices will
>>@@ -814,12 +838,11 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
>>               }
>>
>>               cmax = pci_scan_child_bus(child);
>>-              if (cmax > subordinate)
>>-                      dev_warn(&dev->dev, "bridge has subordinate %02x but max busn %02x\n",
>>-                               subordinate, cmax);
>>-              /* subordinate should equal child->busn_res.end */
>>-              if (subordinate > max)
>>-                      max = subordinate;
>>+              if (cmax > child->busn_res.end)
>>+                      dev_warn(&dev->dev, "bridge has bus resource %pR but max busn %02x\n",
>>+                               &child->busn_res, cmax);
>>+              if (child->busn_res.end > max)
>>+                      max = child->busn_res.end;
>
> By a quick look, I don't see some place change the busn_res.end. And in the
> pci_bus_insert_busn_res(), the child->busn_res.end is set to subordinate. So I
> don't see the reason you change it.
adjust_resource in pci_grow_bus changes busn_res.end. The value in
'subordinate' is then stale at this point.

>
> Do I miss something?
>
>>       } else {
>>               /*
>>                * We need to assign a number to this bus which we always
>>@@ -840,8 +863,10 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
>>
>>               if (max >= bus->busn_res.end) {
>>                       dev_warn(&dev->dev, "can't allocate child bus %02x from %pR\n",
>>-                               max, &bus->busn_res);
>>-                      goto out;
>>+                               max + 1, &bus->busn_res);
>>+                      /* Try to resize bus */
>>+                      if (pci_grow_bus(bus, max + 1))
>>+                              goto out;
>
> On some platforms, like powerpc, we have some limitations of the bus number a
> bridge could have. Sometimes, we need the start bus number to be power 2
> aligned.
>
> Hmm... hope I don't make a mistake, add Gavin in CC list. Gavin, is my
> understanding correct?
Hm I have not seen any code that would enforce this. Is it possible to
do pci=assign-busses on PowerPC?

>>               }
>>
>>               /* Clear errors */
>>@@ -908,6 +933,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
>>                                       break;
>>                               }
>>                       }
>>+                      dev_info(&dev->dev, "adding %02x bus numbers for cardbus\n", i);
>>                       max += i;
>>               }
>>               /*
>>@@ -916,7 +942,8 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
>>               if (max > bus->busn_res.end) {
>>                       dev_warn(&dev->dev, "max busn %02x is outside %pR\n",
>>                                max, &bus->busn_res);
>>-                      max = bus->busn_res.end;
>>+                      if (pci_grow_bus(bus, max))
>>+                              max = bus->busn_res.end;
>>               }
>>               pci_bus_update_busn_res_end(child, max);
>>               pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
>>--
>>2.1.0
>>
>>--
>>To unsubscribe from this list: send the line "unsubscribe linux-pci" in
>>the body of a message to majordomo@xxxxxxxxxxxxxxx
>>More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
> --
> Richard Yang
> Help you, Help me
>
--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux