From: arnd@arndb.de (Arnd Bergmann)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
Date: Thu, 24 Nov 2016 11:24:58 +0100 [thread overview]
Message-ID: <7064030.nCfbxY2Cn2@wuerfel> (raw)
In-Reply-To: <5836AF11.7060400@hisilicon.com>
On Thursday, November 24, 2016 5:12:49 PM CET zhichang.yuan wrote:
> On 2016/11/24 7:23, Arnd Bergmann wrote:
> > On Wednesday, November 23, 2016 6:07:11 PM CET Arnd Bergmann wrote:
> >> On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni wrote:
> >>> From: Arnd Bergmann [mailto:arnd at arndb.de]
> >>>> On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni wrote:
> >>
> > @@ -781,7 +778,8 @@ int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
> > else {
> > resource_list_for_each_entry_safe(entry, tmp, list) {
> > if (entry->res->flags & IORESOURCE_IO)
> > - acpi_pci_root_remap_iospace(entry);
> > + acpi_pci_root_remap_iospace(&device->fwnode,
> > + entry);
> >
> > if (entry->res->flags & IORESOURCE_DISABLED)
> > resource_list_destroy_entry(entry);
>
> I think those changes in pci_root.c is only to match the new definition of
> pci_register_io_range() and work for PCI I/O. It doesn't make sense for LPC, is
> it right?
Right, we wouldn't call acpi_pci_probe_root_resources() for LPC,
the change is just that we always pass the fwnode pointer to allow
matching based on that for any I/O space that does not have a
physical memory address associated with it.
I tried to keep this part general, so in theory that allows us to
have more than one I/O space without a CPU mapping, even though
we don't strictly need that for supporting your LPC controller.
> > diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
> > index a50025a3777f..df96955a43f8 100644
> > --- a/drivers/block/nbd.c
> > +++ b/drivers/block/nbd.c
> > @@ -760,8 +760,10 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
> > set_bit(NBD_RUNNING, &nbd->runtime_flags);
> > blk_mq_update_nr_hw_queues(&nbd->tag_set, nbd->num_connections);
> > args = kcalloc(num_connections, sizeof(*args), GFP_KERNEL);
> > - if (!args)
> > + if (!args) {
> > + error = -ENOMEM;
> > goto out_err;
> > + }
> > nbd->task_recv = current;
> > mutex_unlock(&nbd->config_lock);
> >
> I think change here is none of the business.:)
Right, sorry about that, I forgot to commit this bugfix before looking
at the I/O space stuff.
> > + *host = NULL;
> > /* Get parent & match bus type */
> > parent = of_get_parent(dev);
> > if (parent == NULL)
> > @@ -600,8 +605,9 @@ static u64 __of_translate_address(struct device_node *dev,
> > pbus = of_match_bus(parent);
> > pbus->count_cells(dev, &pna, &pns);
> > if (!OF_CHECK_COUNTS(pna, pns)) {
> > - pr_err("Bad cell count for %s\n",
> > - of_node_full_name(dev));
> > + pr_debug("Bad cell count for %s\n",
> > + of_node_full_name(dev));
> > + *host = of_node_get(parent);
> > break;
> > }
> I don't think here is the right place to fill *host. I think you want to return
> the parent where the of_translate_one() failed for the 'ranges' property
> missing. So, I think this seems better:
>
> if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop)) {
> *host = of_node_get(dev);
> break;
> }
You are right, I got the wrong place. The parent node will have
a #address-cells but won't have ranges for the I/O space.
> > @@ -3272,7 +3276,12 @@ int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
> > /* check if the range hasn't been previously recorded */
> > spin_lock(&io_range_lock);
> > list_for_each_entry(range, &io_range_list, list) {
> > - if (addr >= range->start && addr + size <= range->start + size) {
> > + if (node == range->node)
> > + goto end_register;
> > +
> I don't think it is safe to only check the node had been registered. For
> PCI/PCIE, there is only one I/O windows in bridge, it seems ok. But for non-pci
> devices, such as ISA/LPC, I wonder it is possible there are several disjoint I/O
> 'ranges' entries...
I think this part is completely safe, I can't imagine why you'd
have more than one range of I/O ports that have valid translations.
Do you have a specific example in mind where that would not be
the case, or are you just worried about the principle in general?
> What parameters are necessary for linux PIO allocation?
> 1) For those bus devices which have no MMIO( that is to say, indirectIO is
> using), I think 'addr' is not needed, but 'size' is mandatory;
Agreed.
> I am thinking for our LPC, as there is no cpu address, we should not input
> 'addr' for the io range register. With 'size' as parameter, we implement a new
> io range register function where can assign an unique linux PIO for this
> register calling. The output linux PIO can allocate from a sub-range of whole
> I/O space of [0, IO_SPACE_LIMIT]. This sub-range is specific for indirectIO, I
> want to define a new macro, such as EXTIO_LIMIT, to represent the upper limit of
> indirect IO space.
>
> #if defined(CONFIG_PCI) && defined(CONFIG_INDIRECT_PIO)
> #define EXTIO_LIMIT PCIBIOS_MIN_IO
> #elif defined(CONFIG_INDIRECT_PIO)
> #define EXTIO_LIMIT 0x1000
> #else
> #define EXTIO_LIMIT 0x00
> #end
>
> We should do some checkings to ensure EXTIO_LIMIT < IO_SPACE_LIMIT.
I think we don't need to limit the EXTIO range@all. For your
specific case of LPC, we know it is limited, but my prototype
patch leaves this part generic enough to also allow using it
for a PCI host with indirect I/O space, and that can have a larger
size.
> Then when someone call pci_register_io_range() or a new function for the linux
> PIO register, we can allocate linux PIO from [0, EXTIO_LIMIT) for indirectIO
> bus, from [EXTIO_LIMIT, IO_SPACE_LIMIT] for MMIO;
>
> But there are issues confused me yet. For example, how to know the IO size for
> the indirectIO bus? You known, there is no 'ranges' property for those buses....
Good point. We normally call pci_register_io_range() from
of_pci_range_to_resource and its ACPI equivalent.
When there is no ranges, we obviously won't call it, but there is
also no size associated with it. I think this is ok because
the host driver would already know the size based on the hardware
register layout, and it can just register that directly.
> 2) For PCI MMIO, I think 'addr' is needed
So far I assumed it was, but actually we can perhaps remove
the address if we manage to kill off pci_address_to_pio()
and pci_pio_to_address.
> As for the current pci_register_io_range()/pci_address_to_pio(), I have two doubts:
>
> 2.1) If there are multiple PCI host bridges which support I/O transaction, I
> wonder whether the first host bridge can access the downstream devices with bus
> I/O address in [0, PCIBIOS_MIN_IO)
>
> for the first host bridge, pci_address_to_pio() will return a linux PIO range
> start from 0.
> But when calling __pci_assign_resource() to allocate the linux PIO for PCI/PCIE
> devices/buses which are just children of first host bus, it can not allocate
> linux PIO less than PCIBIOS_MIN_IO, which means kernel can not called in/out()
> with port less than PCIBIOS_MIN_IO. But we had ioremap [PCI_IOBASE + 0,
> PCI_IOBASE + size) to [pci_ioadd, pci_ioadd + size) before.
>
>
> static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
> int resno, resource_size_t size, resource_size_t align)
> {
> struct resource *res = dev->resource + resno;
> resource_size_t min;
> int ret;
>
> min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
>
>
> and in the later function:
>
> static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
> resource_size_t size, resource_size_t align,
> resource_size_t min, unsigned long type_mask,
> resource_size_t (*alignf)(void *,
>
> ....
> pci_bus_for_each_resource(bus, r, i) {
> resource_size_t min_used = min;
> ....
> if (avail.start)
> min_used = avail.start;
>
> max = avail.end;
>
> /* Ok, try it out.. */
> ret = allocate_resource(r, res, size, min_used, max,
> align, alignf, alignf_data);
>
> After allocate_resource(), a IO resource is allocated, but whose 'start' is not
> less than min_used.( since avail.start is 0, min_used will keep the 'min'
> without change to avail.start; Should be PCIBIOS_MIN_IO).
I'm not completely sure I'm following here. Generally speaking, addresses
below PCIBIOS_MIN_IO are intended for PCI-ISA bridges and PCI devices with
hardcoded port numbers for ISA compatibility, while __pci_assign_resource
is meant to do dynamic assignment of I/O resources above PCIBIOS_MIN_IO
so it does not conflict with the legacy ISA ports.
Does that address your concern?
> 2.2) Is it possible the return linux PIO isn't page-aligned?
>
> When calling pci_remap_iospace(const struct resource *res, phys_addr_t
> phys_addr), if res->start is not page-aligned, it seems that
> ioremap_page_range() will meet some issues for duplication iorempa for same
> virtual page.
>
> of-course, if we always configure the I/O ranges size as page-aligned, it will
> be OK.
>
> I found PowerPC will ensure the 'vaddress' and the 'size' are page-aligned
> before ioremap, do we need to improve the current handling in
> pci_register_io_range/pci_address_to_pio?
I think it would be a good idea to enforce page-alignment here, even
though everything could still work if it's not page-aligned.
The requirement for ioremap_page_range() is that the offset within
a page must be the same for the virtual and physical addresses.
Adding page-alignment to pci_register_io_range() could be an enhancement
that we can do independent of the other patches.
Thanks a lot for your detailed analysis and feedback.
Arnd
next prev parent reply other threads:[~2016-11-24 10:24 UTC|newest]
Thread overview: 83+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-11-08 3:47 [PATCH V5 0/3] ARM64 LPC: legacy ISA I/O support zhichang.yuan
2016-11-08 3:47 ` [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced zhichang.yuan
2016-11-08 12:03 ` Mark Rutland
2016-11-08 16:09 ` Arnd Bergmann
2016-11-08 16:15 ` Arnd Bergmann
2016-11-08 23:16 ` Benjamin Herrenschmidt
2016-11-10 8:33 ` zhichang.yuan
2016-11-10 11:22 ` Mark Rutland
2016-11-10 19:32 ` Benjamin Herrenschmidt
2016-11-11 10:07 ` zhichang.yuan
2016-11-18 9:20 ` Arnd Bergmann
2016-11-18 11:12 ` zhichang.yuan
2016-11-18 11:38 ` Arnd Bergmann
2016-11-21 12:58 ` John Garry
2016-11-08 16:12 ` Will Deacon
2016-11-08 16:33 ` John Garry
2016-11-08 16:49 ` Will Deacon
2016-11-08 17:05 ` John Garry
2016-11-08 22:35 ` Arnd Bergmann
2016-11-09 11:29 ` John Garry
2016-11-09 21:33 ` Arnd Bergmann
2016-12-22 8:15 ` Ming Lei
2016-12-23 1:43 ` zhichang.yuan
2016-12-23 7:24 ` Ming Lei
2017-01-06 11:43 ` Arnd Bergmann
2016-11-08 3:47 ` [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA zhichang.yuan
2016-11-08 5:17 ` kbuild test robot
2016-11-08 5:27 ` kbuild test robot
2016-11-08 11:49 ` Mark Rutland
2016-11-08 16:19 ` Arnd Bergmann
2016-11-08 17:10 ` Mark Rutland
2016-11-09 13:54 ` One Thousand Gnomes
2016-11-09 14:51 ` Gabriele Paoloni
2016-11-09 21:38 ` Arnd Bergmann
2016-11-14 11:11 ` One Thousand Gnomes
2016-11-18 9:22 ` Arnd Bergmann
2016-11-08 23:12 ` Benjamin Herrenschmidt
2016-11-09 11:20 ` Mark Rutland
2016-11-10 7:08 ` Benjamin Herrenschmidt
2016-11-09 11:39 ` liviu.dudau at arm.com
2016-11-09 16:16 ` Gabriele Paoloni
2016-11-09 16:50 ` liviu.dudau at arm.com
2016-11-10 6:24 ` zhichang.yuan
2016-11-10 16:06 ` Gabriele Paoloni
2016-11-11 10:37 ` liviu.dudau at arm.com
2016-11-08 3:47 ` [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06 zhichang.yuan
2016-11-08 6:11 ` kbuild test robot
2016-11-08 16:24 ` Arnd Bergmann
2016-11-09 12:10 ` Gabriele Paoloni
2016-11-09 21:34 ` Arnd Bergmann
2016-11-10 6:40 ` zhichang.yuan
2016-11-10 9:12 ` Arnd Bergmann
2016-11-10 12:36 ` zhichang.yuan
2016-11-18 11:46 ` Arnd Bergmann
2016-11-10 15:36 ` Gabriele Paoloni
2016-11-10 16:07 ` Arnd Bergmann
2016-11-11 10:09 ` zhichang.yuan
2016-11-11 10:48 ` liviu.dudau at arm.com
2016-11-11 13:39 ` Gabriele Paoloni
2016-11-11 14:45 ` liviu.dudau at arm.com
2016-11-11 15:53 ` Gabriele Paoloni
2016-11-11 18:16 ` liviu.dudau at arm.com
2016-11-14 8:26 ` Gabriele Paoloni
2016-11-14 11:26 ` liviu.dudau at arm.com
2016-11-18 10:17 ` Arnd Bergmann
2016-11-18 12:07 ` Gabriele Paoloni
2016-11-18 12:24 ` Arnd Bergmann
2016-11-18 12:53 ` Gabriele Paoloni
2016-11-18 13:42 ` Arnd Bergmann
2016-11-18 16:18 ` Gabriele Paoloni
2016-11-18 16:34 ` Arnd Bergmann
2016-11-18 17:03 ` Gabriele Paoloni
2016-11-23 14:16 ` Arnd Bergmann
2016-11-23 15:22 ` Gabriele Paoloni
2016-11-23 17:07 ` Arnd Bergmann
2016-11-23 23:23 ` Arnd Bergmann
2016-11-24 9:12 ` zhichang.yuan
2016-11-24 10:24 ` Arnd Bergmann [this message]
2016-11-25 8:46 ` Gabriele Paoloni
2016-11-25 12:03 ` Arnd Bergmann
2016-11-25 16:27 ` Gabriele Paoloni
2016-11-11 16:54 ` zhichang.yuan
2016-11-14 11:06 ` One Thousand Gnomes
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=7064030.nCfbxY2Cn2@wuerfel \
--to=arnd@arndb.de \
--cc=linux-arm-kernel@lists.infradead.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