Re: [PATCH 1/2] pci: pciehp update the slot bridge res to get big range for pcie devices - v4

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

 



Kenji Kaneshige wrote:
> Yinghai Lu wrote:
>>
>> move out bus_size_bridges and assign resources out of pciehp_add_bridge()
>> and at last do them all together one time including slot bridge, to
>> avoid to
>> call assign resources several times, when there are several bridges
>> under the
>> slot bridge.
>>
>> need to introduce pci_bridge_assign_resources there.
>>
>> handle the case the slot bridge that doesn't get pre-allocated big
>> enough res
>> from FW.
>> for example pcie devices need 256M, but the bridge only get
>> preallocated 2M...
>>
>> pci_setup_bridge() will take extra check_enabled for the slot bridge,
>> otherwise
>> update res is not updated to bridge BAR. that is bridge is enabled
>> already for
>> port service.
>>
>> -v2: address Alex's concern about pci remove/rescan feature about
>> pci_setup_bridge changes.
>> -v3: Kenji pointed out that pci_config_slot need to be called before
>> pci_bus_add_devices()
>> -v4: move out pci_is_enabled checkout of pci_setup_bridge()
>>
>> Signed-off-by: Yinghai Lu <yinghai@xxxxxxxxxx>
>>
>> ---
>>  drivers/pci/hotplug/pciehp_pci.c |   29 ++++++++++++---
>>  drivers/pci/setup-bus.c          |   73
>> ++++++++++++++++++++++++++++++++++++---
>>  include/linux/pci.h              |    1  3 files changed, 93
>> insertions(+), 10 deletions(-)
>>
>> Index: linux-2.6/drivers/pci/hotplug/pciehp_pci.c
>> ===================================================================
>> --- linux-2.6.orig/drivers/pci/hotplug/pciehp_pci.c
>> +++ linux-2.6/drivers/pci/hotplug/pciehp_pci.c
>> @@ -53,19 +53,18 @@ static int __ref pciehp_add_bridge(struc
>>          busnr = pci_scan_bridge(parent, dev, busnr, pass);
>>      if (!dev->subordinate)
>>          return -1;
>> -    pci_bus_size_bridges(dev->subordinate);
>> -    pci_bus_assign_resources(parent);
>> -    pci_enable_bridges(parent);
>> -    pci_bus_add_devices(parent);
>> +
>>      return 0;
>>  }
>>  
>>  int pciehp_configure_device(struct slot *p_slot)
>>  {
>>      struct pci_dev *dev;
>> -    struct pci_bus *parent = p_slot->ctrl->pcie->port->subordinate;
>> +    struct pci_dev *bridge = p_slot->ctrl->pcie->port;
>> +    struct pci_bus *parent = bridge->subordinate;
>>      int num, fn;
>>      struct controller *ctrl = p_slot->ctrl;
>> +    int retval;
>>  
>>      dev = pci_get_slot(parent, PCI_DEVFN(0, 0));
>>      if (dev) {
>> @@ -96,12 +95,30 @@ int pciehp_configure_device(struct slot
>>                  (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
>>              pciehp_add_bridge(dev);
>>          }
>> +        pci_dev_put(dev);
>> +    }
>> +
>> +    pci_bus_size_bridges(parent);
>> +    pci_clear_master(bridge);
>> +    pci_bridge_assign_resources(bridge);
>> +    retval = pci_reenable_device(bridge);
>> +    pci_set_master(bridge);
>> +    pci_enable_bridges(parent);
>> +
>> +    for (fn = 0; fn < 8; fn++) {
>> +        dev = pci_get_slot(parent, PCI_DEVFN(0, fn));
>> +        if (!dev)
>> +            continue;
>> +        if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
>> +            pci_dev_put(dev);
>> +            continue;
>> +        }
>>          pci_configure_slot(dev);
>>          pci_dev_put(dev);
>>      }
>>  
>> -    pci_bus_assign_resources(parent);
>>      pci_bus_add_devices(parent);
>> +
>>      return 0;
>>  }
>>  
>> Index: linux-2.6/drivers/pci/setup-bus.c
>> ===================================================================
>> --- linux-2.6.orig/drivers/pci/setup-bus.c
>> +++ linux-2.6/drivers/pci/setup-bus.c
>> @@ -27,6 +27,44 @@
>>  #include <linux/slab.h>
>>  #include "pci.h"
>>  
>> +static void pdev_assign_resources_sorted(struct pci_dev *dev)
>> +{
>> +    struct resource *res;
>> +    struct resource_list head, *list, *tmp;
>> +    int idx;
>> +    u16 class = dev->class >> 8;
>> +
>> +    head.next = NULL;
>> +
>> +    /* Don't touch classless devices or host bridges or ioapics.  */
>> +    if (class == PCI_CLASS_NOT_DEFINED ||
>> +        class == PCI_CLASS_BRIDGE_HOST)
>> +        return;
>> +
>> +    /* Don't touch ioapic devices already enabled by firmware */
>> +    if (class == PCI_CLASS_SYSTEM_PIC) {
>> +        u16 command;
>> +        pci_read_config_word(dev, PCI_COMMAND, &command);
>> +        if (command & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY))
>> +            return;
>> +    }
>> +
>> +    pdev_sort_resources(dev, &head);
>> +
>> +    for (list = head.next; list;) {
>> +        res = list->res;
>> +        idx = res - &list->dev->resource[0];
>> +        if (pci_assign_resource(list->dev, idx)) {
>> +            res->start = 0;
>> +            res->end = 0;
>> +            res->flags = 0;
>> +        }
>> +        tmp = list;
>> +        list = list->next;
>> +        kfree(tmp);
>> +    }
>> +}
>> +
>>  static void pbus_assign_resources_sorted(const struct pci_bus *bus)
>>  {
>>      struct pci_dev *dev;
>> @@ -144,9 +182,6 @@ static void pci_setup_bridge(struct pci_
>>      u32 l, bu, lu, io_upper16;
>>      int pref_mem64;
>>  
>> -    if (pci_is_enabled(bridge))
>> -        return;
>> -
>>      dev_info(&bridge->dev, "PCI bridge, secondary bus %04x:%02x\n",
>>           pci_domain_nr(bus), bus->number);
>>  
>> @@ -541,6 +576,35 @@ void __ref pci_bus_size_bridges(struct p
>>  }
>>  EXPORT_SYMBOL(pci_bus_size_bridges);
>>  
>> +void __ref pci_bridge_assign_resources(const struct pci_dev *bridge)
>> +{
>> +    struct pci_bus *b;
>> +
>> +    pdev_assign_resources_sorted((struct pci_dev *)bridge);
>> +
>> +    b = bridge->subordinate;
>> +    if (!b)
>> +        return;
>> +
>> +    pci_bus_assign_resources(b);
>> +
>> +    switch (bridge->class >> 8) {
>> +    case PCI_CLASS_BRIDGE_PCI:
>> +        pci_setup_bridge(b);
>> +        break;
>> +
>> +    case PCI_CLASS_BRIDGE_CARDBUS:
>> +        pci_setup_cardbus(b);
>> +        break;
>> +
>> +    default:
>> +        dev_info(&bridge->dev, "not setting up bridge for bus "
>> +             "%04x:%02x\n", pci_domain_nr(b), b->number);
>> +        break;
>> +    }
>> +}
>> +EXPORT_SYMBOL(pci_bridge_assign_resources);
>> +
>>  void __ref pci_bus_assign_resources(const struct pci_bus *bus)
>>  {
>>      struct pci_bus *b;
>> @@ -557,7 +621,8 @@ void __ref pci_bus_assign_resources(cons
>>  
>>          switch (dev->class >> 8) {
>>          case PCI_CLASS_BRIDGE_PCI:
>> -            pci_setup_bridge(b);
>> +            if (!pci_is_enabled(dev))
>> +                pci_setup_bridge(b);
>>              break;
>>  
>>          case PCI_CLASS_BRIDGE_CARDBUS:
>> Index: linux-2.6/include/linux/pci.h
>> ===================================================================
>> --- linux-2.6.orig/include/linux/pci.h
>> +++ linux-2.6/include/linux/pci.h
>> @@ -756,6 +756,7 @@ ssize_t pci_write_vpd(struct pci_dev *de
>>  int pci_vpd_truncate(struct pci_dev *dev, size_t size);
>>  
>>  /* Helper functions for low-level code
>> (drivers/pci/setup-[bus,res].c) */
>> +void pci_bridge_assign_resources(const struct pci_dev *bridge);
>>  void pci_bus_assign_resources(const struct pci_bus *bus);
>>  void pci_bus_size_bridges(struct pci_bus *bus);
>>  int pci_claim_resource(struct pci_dev *, int);
>>
> 
> Does this patch work without [PATCH 2/2]? I don't understand who
> releases resouces? Does find_free_bus_resource() still release
> resources?

need to work with [2/2].

YH
--
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