public inbox for linux-arm-kernel@lists.infradead.org
 help / color / mirror / Atom feed
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

  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