Linux PCI subsystem development
 help / color / mirror / Atom feed
From: Bjorn Helgaas <helgaas@kernel.org>
To: Huacai Chen <chenhuacai@gmail.com>
Cc: "Huacai Chen" <chenhuacai@loongson.cn>,
	"Bjorn Helgaas" <bhelgaas@google.com>,
	"Lorenzo Pieralisi" <lorenzo.pieralisi@arm.com>,
	"Krzysztof Wilczyński" <kw@linux.com>,
	"Rob Herring" <robh@kernel.org>,
	linux-pci@vger.kernel.org, "Jianmin Lv" <lvjianmin@loongson.cn>,
	"Xuefeng Li" <lixuefeng@loongson.cn>,
	"Jiaxun Yang" <jiaxun.yang@flygoat.com>,
	"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>
Subject: Re: [PATCH] PCI: loongson: Add quirk for OHCI device rev 0x02
Date: Tue, 18 Mar 2025 16:50:25 -0500	[thread overview]
Message-ID: <20250318215025.GA1012479@bhelgaas> (raw)
In-Reply-To: <CAAhV-H7c9jkXqwn2STdYq-1g4jVELjKL5jaO2aASFAETW5FLHw@mail.gmail.com>

[+cc Greg, USB maintainer; I'm proposing ohci_pci_quirks for this]

On Tue, Mar 18, 2025 at 09:07:10PM +0800, Huacai Chen wrote:
> On Sat, Mar 15, 2025 at 3:59 AM Bjorn Helgaas <helgaas@kernel.org> wrote:
> > On Tue, Jan 21, 2025 at 07:42:25PM +0800, Huacai Chen wrote:
> > > The OHCI controller (rev 0x02) under LS7A PCI host has a hardware flaw.
> > > MMIO register with offset 0x60/0x64 is treated as legacy PS2-compatible
> > > keyboard/mouse interface, which confuse the OHCI controller. Since OHCI
> > > only use a 4KB BAR resource indeed, the LS7A OHCI controller's 32KB BAR
> > > is wrapped around (the second 4KB BAR space is the same as the first 4KB
> > > internally). So we can add an 4KB offset (0x1000) to the BAR resource as
> > > a workaround.
> >
> > It looks like usb_hcd_pci_probe() only uses BAR 0 in the OHCI case, so
> > I assume this OHCI controller has a single 32KB BAR?
>
> Yes.
> 
> > And you're saying that in that BAR, the 0x1000-0x1fff offsets are
> > aliases of the 0x0000-0x0fff area?
>
> Yes.
> 
> > And this causes some kind of problem because the OCHI driver looks at
> > offsets 0x60 and 0x64 into the BAR and sees something it doesn't like?
>
> Yes.
> 
> > And this quirk adds 0x1000 to the BAR start, so the OHCI driver looks
> > at offsets 0x1060 and 0x1064 of the original BAR, and that somehow
> > avoids a problem?  Even though those are aliases of 0x0060 and 0x0064
> > of the original BAR?
>
> Yes.
> 
> > > +static void loongson_ohci_quirk(struct pci_dev *dev)
> > > +{
> > > +     if (dev->revision == 0x2)
> > > +             dev->resource[0].start += 0x1000;
> >
> > What does this do to the iomem_resource tree?  IIUC, dev->resource[0]
> > no longer correctly describes the PCI address space consumed by the
> > device.
>
> In the iomem_resource tree the whole 32KB is requested for the OHCI
> controller.

I'm skeptical.  The quirk only updates the start, not the end, so I
think the resource is only 28KB after the quirk.

This is a final quirk, so I think the quirk runs after the BAR
resource has already been put in the iomem_resource tree.  We
shouldn't update the resource start/end after that point.

> > If the BAR is actually programmed with [mem 0x20000000-0x20007fff],
> > the device responds to PCI accesses in that range.  Now you update
> > resource[0] so it describes the space [mem 0x20001000-0x20008fff].  So
> > the kernel *thinks* the space at [mem 0x20000000-0x20000fff] is free
> > and available for something else, which is not true, and that the
> > device responds at [mem 0x0x20008000-0x20008fff], which is also not
> > true.
> >
> > I think the resource has already been put into the iomem_resource tree
> > by the time the final fixups are run, so this also may corrupt the
> > sorting of the tree.
> >
> > This just doesn't look safe to me.
>
> OHCI only uses 4KB io resources (hardware designer told me that this
> is from USB specification). So if the BAR is [mem
> 0x20000000-0x20007fff] and without this quirk, software will only
> use [mem 0x20000000-0x20000fff]; and if we do this quirk, software
> will only use [mem 0x20001000-0x20001fff]. Since the whole 32KB
> belongs to OHCI, there won't be corruption.

Here's the path where I think the BAR is requested.  Assume the BAR
contains 0x20000000 when we boot:

  acpi_pci_root_add
    pci_acpi_scan_root                  # loongson
      acpi_pci_root_create
        pci_scan_child_bus
          pci_scan_single_device        # details trimmed
            pci_scan_device
              pci_read_bases
                resource[0].start = 0x20000000
                resource[0].end   = 0x20007fff          # size 32KB
            pci_device_add
              pci_fixup_device(pci_fixup_header)        # <--
      pci_bus_assign_resources          # details trimmed
        pci_assign_resource
          pci_bus_alloc_resource
            allocate_resource
              __request_resource        # inserted in iomem_resource
    pci_bus_add_devices
      pci_bus_add_device
        pci_fixup_device(pci_fixup_final)
          resource[0].start += 0x1000                   # now 0x20001000

  ohci_pci_probe
    usb_hcd_pci_probe(& ohci_pci_hc_driver)
      if (driver->flags & HCD_MEMORY)
        hcd->rsrc_start = pci_resource_start(dev, 0)    # 0x20001000
        hcd->rsrc_len = pci_resource_len(dev, 0)        # now 28KB
        devm_request_mem_region
        hcd->regs = devm_ioremap
      usb_add_hcd
        hcd->driver->reset
          ohci_pci_reset                                # <--

So I suspect:

  - BAR contains 0x20000000 initially (for example)

  - pci_bus_assign_resources() inserts 0x20000000-0x20007fff in
    iomem_resource

  - final quirk updates res->start, so resource is now
    0x20001000-0x20007fff

  - OHCI driver binds and sees 0x20001000-0x20007fff

  - OHCI driver requests 0x20001000-0x20007fff (28KB)

  - OHCI may only use 4KB, but AFAICS it actually reserves the entire
    resource[0], which is now only 28KB

  - BAR still contains 0x20000000 ("lspci -b" should confirm this)

  - /proc/iomem contains something like this:

      20001000-20007fff 0000:3e:00.0
        20001000-20007fff ohci-hcd

Now the device still responds to accesses at 0x20000000 because that's
what's in the BAR, but the kernel doesn't know that anybody is using
the 0x20000000-0x20000fff region.

I think the best solution would be to add an entry in
ohci_pci_quirks[] that bumps hcd->regs up by 0x1000.  Then we wouldn't
have to touch the struct resource, it would stay 32KB, and it would
accurately reflect the hardware.

If that doesn't work, I guess you could also make this a *header*
fixup instead of a final one.  Then we would at least update the
resource before inserting it in iomem_resource.  But I don't like it
because the device still responds to an area not mentioned in
iomem_resource, and the resource is now 28KB, which is an illegal size
for a PCI BAR.

> > > +}
> > > +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, DEV_LS7A_OHCI, loongson_ohci_quirk);

  reply	other threads:[~2025-03-18 21:50 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-21 11:42 [PATCH] PCI: loongson: Add quirk for OHCI device rev 0x02 Huacai Chen
2025-01-22 15:12 ` Mingcong Bai
2025-03-14  7:53 ` Krzysztof Wilczyński
2025-03-15  3:45   ` Huacai Chen
2025-03-15  4:00     ` Krzysztof Wilczyński
2025-03-14 19:59 ` Bjorn Helgaas
2025-03-18 13:07   ` Huacai Chen
2025-03-18 21:50     ` Bjorn Helgaas [this message]
2025-03-26  9:15       ` Huacai Chen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250318215025.GA1012479@bhelgaas \
    --to=helgaas@kernel.org \
    --cc=bhelgaas@google.com \
    --cc=chenhuacai@gmail.com \
    --cc=chenhuacai@loongson.cn \
    --cc=gregkh@linuxfoundation.org \
    --cc=jiaxun.yang@flygoat.com \
    --cc=kw@linux.com \
    --cc=linux-pci@vger.kernel.org \
    --cc=lixuefeng@loongson.cn \
    --cc=lorenzo.pieralisi@arm.com \
    --cc=lvjianmin@loongson.cn \
    --cc=robh@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox