Re: [PATCH 4/5] PCI, acpiphp: add is_hotplug_bridge detection

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

 



On Wed, Jul 11, 2012 at 01:42:15PM -0600, Bjorn Helgaas wrote:
> On Wed, Jul 11, 2012 at 11:14 AM, Jason Baron <jbaron@xxxxxxxxxx> wrote:
> > On Wed, Jul 11, 2012 at 09:50:19AM -0600, Bjorn Helgaas wrote:
> >> On Sat, Jun 23, 2012 at 1:42 AM, Yinghai Lu <yinghai@xxxxxxxxxx> wrote:
> >> > When system support hotplug bridge with children hotplug slots, we need to make sure
> >> > that parent bridge get preallocated resource so later when device is plugged into
> >> > children slot, those children devices will get resource allocated.
> >> >
> >> > We do not meet this problem, because for pcie hotplug card, when acpiphp is used,
> >> > pci_scan_bridge will set that for us when detect hotplug bit in slot cap.
> >> >
> >> > Reported-and-tested-by: Jason Baron <jbaron@xxxxxxxxxx>
> >> > Signed-off-by: Yinghai Lu <yinghai@xxxxxxxxxx>
> >> > Acked-by: Jason Baron <jbaron@xxxxxxxxxx>
> >> > ---
> >> >  drivers/pci/hotplug/acpiphp_glue.c |   27 ++++++++++++++++++++++++++-
> >> >  1 files changed, 26 insertions(+), 1 deletions(-)
> >> >
> >> > diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
> >> > index ad6fd66..0f2b72d 100644
> >> > --- a/drivers/pci/hotplug/acpiphp_glue.c
> >> > +++ b/drivers/pci/hotplug/acpiphp_glue.c
> >> > @@ -783,6 +783,29 @@ static void acpiphp_set_acpi_region(struct acpiphp_slot *slot)
> >> >         }
> >> >  }
> >> >
> >> > +static void check_hotplug_bridge(struct acpiphp_slot *slot, struct pci_dev *dev)
> >> > +{
> >> > +       struct acpiphp_func *func;
> >> > +
> >> > +       if (!dev->subordinate)
> >> > +               return;
> >> > +
> >> > +       /* quirk, or pcie could set it already */
> >> > +       if (dev->is_hotplug_bridge)
> >> > +               return;
> >> > +
> >> > +       if (PCI_SLOT(dev->devfn) != slot->device)
> >> > +               return;
> >> > +
> >> > +       list_for_each_entry(func, &slot->funcs, sibling) {
> >> > +               if (PCI_FUNC(dev->devfn) == func->function) {
> >> > +                       /* check if this bridge has ejectable slots */
> >> > +                       if ((detect_ejectable_slots(func->handle) > 0))
> >> > +                               dev->is_hotplug_bridge = 1;
> >> > +                       break;
> >> > +               }
> >> > +       }
> >> > +}
> >> >  /**
> >> >   * enable_device - enable, configure a slot
> >> >   * @slot: slot to be enabled
> >> > @@ -817,8 +840,10 @@ static int __ref enable_device(struct acpiphp_slot *slot)
> >> >                         if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
> >> >                             dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
> >> >                                 max = pci_scan_bridge(bus, dev, max, pass);
> >> > -                               if (pass && dev->subordinate)
> >> > +                               if (pass && dev->subordinate) {
> >> > +                                       check_hotplug_bridge(slot, dev);
> >>
> >> I don't like this patch because it increases the differences between
> >> the hotplug drivers, rather than decreasing them.
> >>
> >> For PCI Express devices, we set dev->is_hotplug_bridge in the
> >> pci_setup_device() path (in set_pcie_hotplug_bridge()).  I think it
> >> would make sense to try to expand that path to also handle SHPC and
> >> ACPI hotplug as well.  ACPI is harder because it's not PCI-specified,
> >> so we'd need some sort of pcibios or other optional hook.
> >>
> >> I don't have a clear picture of how this works -- if I understand
> >> correctly, the situation is that we have a bridge managed by acpiphp.
> >> That part makes sense because the bridge is on the motherboard and can
> >> have a DSDT device.  Now we plug something into the slot below the
> >> bridge.  I *think* this patch handles the case where this new
> >> hot-added thing is also a bridge managed by acpiphp.  But where does
> >> the ACPI device for this hot-added bridge come from?  It's an
> >> arbitrary device the BIOS knows nothing about, so it can't be in the
> >> DSDT.
> >>
> >
> > So this came up while I was developing pci bridge hotplug for qemu.
> > Currently, there is a top level host bus (with ACPI device definitions), where
> > devices can be hot-plugged. What I've done is added a second level
> > of hotplug pci busses (again with ACPI device definitions). Thus, we can
> > now hotplug a bridge into the top-level bus and then devices behind it.
> > Effectively increasing the hot-plug space from n -> n^2.
> >
> > Before the above pci patch, the devices behind the bridge would not
> > configure their PCI BARs properly, since there were no i/o, mem resources
> > assigned to the bridge. However, with the above patch in place things
> > work as expected.
> >
> > Using the same code base I was able to do acpi hotplug on Windows 7,
> > which correctly configured the both the bridge window and devices behind
> > it on hot-plug. So currently, the above usage pattern works on Windows
> > 7, but not on Linux.
> 
> Thanks, Jason.  Do you have "lspci -v" output and the DSDT AML handy?
> I'd like to look in more detail at what we're missing.

Hi,

Sorry for the delay...was on vacation.

Anyways, below is the patch I have to the seabios acpi table. However,
there are other pieces for seabios and qemu required. I still need to
clean them up and send them out. But this pci patch (or something
similar) is a required dependency.

What 'lspci -v' output are you looking for?

Let me know what else I can provide.

Thanks,

-Jason


--- a/src/ssdt-pcihp.dsl
+++ b/src/ssdt-pcihp.dsl
@@ -17,82 +17,162 @@ DefinitionBlock ("ssdt-pcihp.aml", "SSDT", 0x01, "BXPC", "BXSSDTPCIHP", 0x1)
         // at runtime, if the slot is detected to not support hotplug.
         // Extract the offset of the address dword and the
         // _EJ0 name to allow this patching.
-#define hotplug_slot(slot)                              \
-        Device (S##slot) {                              \
-           ACPI_EXTRACT_NAME_DWORD_CONST aml_adr_dword  \
-           Name (_ADR, 0x##slot##0000)                  \
-           ACPI_EXTRACT_METHOD_STRING aml_ej0_name      \
-           Method (_EJ0, 1) { Return(PCEJ(0x##slot)) }  \
-           Name (_SUN, 0x##slot)                        \
-        }
+#define hotplug_level2_slot(slot1, slot2)                   \
+        Device (S##slot2) {                                 \
+           Name (_ADR, 0x##slot2##0000)                     \
+           Method (_EJ0, 1) { Return(PCEJ(0x##slot1, 0x##slot2)) } \
+           Name (_SUN, 0x##slot2)                           \
+        }                                                   \
+
+#define hotplug_top_level_slot(slot)                          \
+        Device (S##slot) {                                    \
+            ACPI_EXTRACT_NAME_DWORD_CONST aml_adr_dword       \
+            Name (_ADR,0x##slot##0000)                        \
+            ACPI_EXTRACT_METHOD_STRING aml_ej0_name           \
+            Method (_EJ0, 1) { Return(PCEJ(0x##slot, 0x00)) } \
+            Name (_SUN, 0x##slot)                             \
+            hotplug_level2_slot(slot, 01)                     \
+            hotplug_level2_slot(slot, 02)                     \
+            hotplug_level2_slot(slot, 03)                     \
+            hotplug_level2_slot(slot, 04)                     \
+            hotplug_level2_slot(slot, 05)                     \
+            hotplug_level2_slot(slot, 06)                     \
+            hotplug_level2_slot(slot, 07)                     \
+            hotplug_level2_slot(slot, 08)                     \
+            hotplug_level2_slot(slot, 09)                     \
+            hotplug_level2_slot(slot, 0a)                     \
+            hotplug_level2_slot(slot, 0b)                     \
+            hotplug_level2_slot(slot, 0c)                     \
+            hotplug_level2_slot(slot, 0d)                     \
+            hotplug_level2_slot(slot, 0e)                     \
+            hotplug_level2_slot(slot, 0f)                     \
+            hotplug_level2_slot(slot, 10)                     \
+            hotplug_level2_slot(slot, 11)                     \
+            hotplug_level2_slot(slot, 12)                     \
+            hotplug_level2_slot(slot, 13)                     \
+            hotplug_level2_slot(slot, 14)                     \
+            hotplug_level2_slot(slot, 15)                     \
+            hotplug_level2_slot(slot, 16)                     \
+            hotplug_level2_slot(slot, 17)                     \
+            hotplug_level2_slot(slot, 18)                     \
+            hotplug_level2_slot(slot, 19)                     \
+            hotplug_level2_slot(slot, 1a)                     \
+            hotplug_level2_slot(slot, 1b)                     \
+            hotplug_level2_slot(slot, 1c)                     \
+            hotplug_level2_slot(slot, 1d)                     \
+            hotplug_level2_slot(slot, 1e)                     \
+            hotplug_level2_slot(slot, 1f)                     \
+        }                                                     \
+
+        hotplug_top_level_slot(01)
+        hotplug_top_level_slot(02)
+        hotplug_top_level_slot(03)
+        hotplug_top_level_slot(04)
+        hotplug_top_level_slot(05)
+        hotplug_top_level_slot(06)
+        hotplug_top_level_slot(07)
+        hotplug_top_level_slot(08)
+        hotplug_top_level_slot(09)
+        hotplug_top_level_slot(0a)
+        hotplug_top_level_slot(0b)
+        hotplug_top_level_slot(0c)
+        hotplug_top_level_slot(0d)
+        hotplug_top_level_slot(0e)
+        hotplug_top_level_slot(0f)
+        hotplug_top_level_slot(10)
+        hotplug_top_level_slot(11)
+        hotplug_top_level_slot(12)
+        hotplug_top_level_slot(13)
+        hotplug_top_level_slot(14)
+        hotplug_top_level_slot(15)
+        hotplug_top_level_slot(16)
+        hotplug_top_level_slot(17)
+        hotplug_top_level_slot(18)
+        hotplug_top_level_slot(19)
+        hotplug_top_level_slot(1a)
+        hotplug_top_level_slot(1b)
+        hotplug_top_level_slot(1c)
+        hotplug_top_level_slot(1d)
+        hotplug_top_level_slot(1e)
+        hotplug_top_level_slot(1f)
 
-        hotplug_slot(01)
-        hotplug_slot(02)
-        hotplug_slot(03)
-        hotplug_slot(04)
-        hotplug_slot(05)
-        hotplug_slot(06)
-        hotplug_slot(07)
-        hotplug_slot(08)
-        hotplug_slot(09)
-        hotplug_slot(0a)
-        hotplug_slot(0b)
-        hotplug_slot(0c)
-        hotplug_slot(0d)
-        hotplug_slot(0e)
-        hotplug_slot(0f)
-        hotplug_slot(10)
-        hotplug_slot(11)
-        hotplug_slot(12)
-        hotplug_slot(13)
-        hotplug_slot(14)
-        hotplug_slot(15)
-        hotplug_slot(16)
-        hotplug_slot(17)
-        hotplug_slot(18)
-        hotplug_slot(19)
-        hotplug_slot(1a)
-        hotplug_slot(1b)
-        hotplug_slot(1c)
-        hotplug_slot(1d)
-        hotplug_slot(1e)
-        hotplug_slot(1f)
+#define gen_pci_level2_hotplug(slot1, slot2) \
+            If (LEqual(Arg0, 0x##slot1)) { \
+                If (LEqual(Arg1, 0x##slot2)) { \
+                    Notify(\_SB.PCI0.S##slot1.S##slot2, Arg2) \
+                } \
+            } \
 
-#define gen_pci_hotplug(slot)   \
-            If (LEqual(Arg0, 0x##slot)) { Notify(S##slot, Arg1) }
+#define gen_pci_top_level_hotplug(slot)   \
+            If (LEqual(Arg1, Zero)) { \
+                If (LEqual(Arg0, 0x##slot)) { \
+                    Notify(S##slot, Arg2) \
+                } \
+            } \
+            gen_pci_level2_hotplug(slot, 01) \
+            gen_pci_level2_hotplug(slot, 02) \
+            gen_pci_level2_hotplug(slot, 03) \
+            gen_pci_level2_hotplug(slot, 04) \
+            gen_pci_level2_hotplug(slot, 05) \
+            gen_pci_level2_hotplug(slot, 06) \
+            gen_pci_level2_hotplug(slot, 07) \
+            gen_pci_level2_hotplug(slot, 08) \
+            gen_pci_level2_hotplug(slot, 09) \
+            gen_pci_level2_hotplug(slot, 0a) \
+            gen_pci_level2_hotplug(slot, 0b) \
+            gen_pci_level2_hotplug(slot, 0c) \
+            gen_pci_level2_hotplug(slot, 0d) \
+            gen_pci_level2_hotplug(slot, 0e) \
+            gen_pci_level2_hotplug(slot, 0f) \
+            gen_pci_level2_hotplug(slot, 10) \
+            gen_pci_level2_hotplug(slot, 11) \
+            gen_pci_level2_hotplug(slot, 12) \
+            gen_pci_level2_hotplug(slot, 13) \
+            gen_pci_level2_hotplug(slot, 14) \
+            gen_pci_level2_hotplug(slot, 15) \
+            gen_pci_level2_hotplug(slot, 16) \
+            gen_pci_level2_hotplug(slot, 17) \
+            gen_pci_level2_hotplug(slot, 18) \
+            gen_pci_level2_hotplug(slot, 19) \
+            gen_pci_level2_hotplug(slot, 1a) \
+            gen_pci_level2_hotplug(slot, 1b) \
+            gen_pci_level2_hotplug(slot, 1c) \
+            gen_pci_level2_hotplug(slot, 1d) \
+            gen_pci_level2_hotplug(slot, 1e) \
+            gen_pci_level2_hotplug(slot, 1f) \
 
-        Method(PCNT, 2) {
-            gen_pci_hotplug(01)
-            gen_pci_hotplug(02)
-            gen_pci_hotplug(03)
-            gen_pci_hotplug(04)
-            gen_pci_hotplug(05)
-            gen_pci_hotplug(06)
-            gen_pci_hotplug(07)
-            gen_pci_hotplug(08)
-            gen_pci_hotplug(09)
-            gen_pci_hotplug(0a)
-            gen_pci_hotplug(0b)
-            gen_pci_hotplug(0c)
-            gen_pci_hotplug(0d)
-            gen_pci_hotplug(0e)
-            gen_pci_hotplug(0f)
-            gen_pci_hotplug(10)
-            gen_pci_hotplug(11)
-            gen_pci_hotplug(12)
-            gen_pci_hotplug(13)
-            gen_pci_hotplug(14)
-            gen_pci_hotplug(15)
-            gen_pci_hotplug(16)
-            gen_pci_hotplug(17)
-            gen_pci_hotplug(18)
-            gen_pci_hotplug(19)
-            gen_pci_hotplug(1a)
-            gen_pci_hotplug(1b)
-            gen_pci_hotplug(1c)
-            gen_pci_hotplug(1d)
-            gen_pci_hotplug(1e)
-            gen_pci_hotplug(1f)
+        Method(PCNT, 3) {
+            gen_pci_top_level_hotplug(01)
+            gen_pci_top_level_hotplug(02)
+            gen_pci_top_level_hotplug(03)
+            gen_pci_top_level_hotplug(04)
+            gen_pci_top_level_hotplug(05)
+            gen_pci_top_level_hotplug(06)
+            gen_pci_top_level_hotplug(07)
+            gen_pci_top_level_hotplug(08)
+            gen_pci_top_level_hotplug(09)
+            gen_pci_top_level_hotplug(0a)
+            gen_pci_top_level_hotplug(0b)
+            gen_pci_top_level_hotplug(0c)
+            gen_pci_top_level_hotplug(0d)
+            gen_pci_top_level_hotplug(0e)
+            gen_pci_top_level_hotplug(0f)
+            gen_pci_top_level_hotplug(10)
+            gen_pci_top_level_hotplug(11)
+            gen_pci_top_level_hotplug(12)
+            gen_pci_top_level_hotplug(13)
+            gen_pci_top_level_hotplug(14)
+            gen_pci_top_level_hotplug(15)
+            gen_pci_top_level_hotplug(16)
+            gen_pci_top_level_hotplug(17)
+            gen_pci_top_level_hotplug(18)
+            gen_pci_top_level_hotplug(19)
+            gen_pci_top_level_hotplug(1a)
+            gen_pci_top_level_hotplug(1b)
+            gen_pci_top_level_hotplug(1c)
+            gen_pci_top_level_hotplug(1d)
+            gen_pci_top_level_hotplug(1e)
+            gen_pci_top_level_hotplug(1f)
         }
     }
 
--
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