Re: [PATCH 1/2] PCI: endpoint: Introduce 'get_bar' to map fixed address BARs in EPC
From: Manivannan Sadhasivam
Date: Mon Jul 29 2024 - 12:46:16 EST
On Fri, Jul 26, 2024 at 03:41:37PM +0200, Niklas Cassel wrote:
> On Fri, Jul 26, 2024 at 01:21:32PM +0200, Rick Wertenbroek wrote:
> >
> > One thing to keep in mind is that 'struct pci_epf_bar 'conf' would be
> > an 'inout' parameter, where 'conf' gets changed in case of a fixed
> > address BAR or fixed 64-bit etc. This means the EPF code needs to
> > check 'conf' after the call. Also, if the caller sets flags and the
> > controller only handles different flags, do we return an error, or
> > configure the BAR with the only possible flags and let the caller
> > check if those flags are ok for the endpoint function ?
> >
> > This is a bit unclear for me for the moment.
>
+1 for the new API name: pci_epc_configure_bar()
> Indeed, it is quite messy at the moment, which is why we should try
> to do better, and clearly document the cases where the API should
> fail, and when it is okay for the API to set things automatically.
>
>
> How the current pci_epf_alloc_space() (which is used to allocate space
> for a BAR) works:
> - Takes a enum pci_barno bar.
>
> - Will modify the epf_bar[bar] array of structs. (For either primary
> interface array of BARs or secondary interface array of BARs.)
> Perhaps it would be better if this was an array of pointers instead,
> so that an EPF driver cannot modify a BAR that has not been allocated,
> and that the new API allocates a 'struct pci_epf_bar', and sets the
> pointer. (But perhaps better to leave it like it is to start with.)
>
I like this idea. But yeah, there is no pressing need to implement this for
the new API.
> - Uses |= to set flags, which means that if an EPF has modified
> epf_bar[bar].flags before calling pci_epf_alloc_space(), these
> flags would still be set. (I wouldn't recommend any EPF driver to do so.)
> It would be much better if we provided 'flags' to the new API, so that
> the new API can set the flags using = instead of |=.
>
Well, with the new API I'd like to allow EPF drivers to set the flags to be able
to request 32/64 bit BAR of their preference. Because, the EPF driver may know
its own limitation.
> - Flag PCI_BASE_ADDRESS_MEM_TYPE_64 will automatically get set if the BAR
> can only be a 64-bit BAR according to epc_features.
> This is a bit debatable. For some EPF drivers, getting a 64-bit BAR even
> if you only requested a 32-bit BAR, might be fine. But for some EPF
> drivers, I can imagine that it is not okay. (Perhaps we need a
> "bool strict" that gives errors more often instead of implicitly setting
> flags not that was not requested.
>
EPF drivers cannot explicitly request 32/64 bit BAR using alloc_space(). Perhaps
you are mixing set_bar() implementation?
But only if the EPF driver has explicitly set the flags, then returning error
makes sense if the EPC core cannot satisfy the requirements.
> - Will set PCI_BASE_ADDRESS_MEM_TYPE_64 if the requested size is larger
> than 2 GB. The new API should simply give an error if flag
> PCI_BASE_ADDRESS_MEM_TYPE_64 is not set when size is larger than 2 GB.
>
I would prefer to return error _only_ if EPC core cannot satisfy the requirement
from the EPF driver.
> - If the bar is a fixed size BAR according to epc_features, it will set a
> size larger than the requested size. It will however give an error if the
> requested size is larger than the fixed size BAR. (Should a possible
> "bool strict" give an error if you cannot set the exact requested size,
> or is it usually okay to have a BAR size that is larger than requested?)
>
I think it is fine. Most of the EPF drivers expose a register region and that
size is usually less than the standard BAR size.
- Mani
>
> How the current pci_epc_set_bar() works:
> - Takes 'struct pci_epf_bar *epf_bar'
>
> - This function will give an error if PCI_BASE_ADDRESS_MEM_TYPE_64 is not set
> when size is larger than 2 GB, or if you try to set BAR5 as a 64-bit BAR.
>
> - Calls epc->ops->set_bar() will should return errors if it cannot satisfy
> the 'struct pci_epf_bar *epf_bar'.
>
>
> How the epc->ops->set_bar() works:
> - A EPC might have additional restrictions that are controller specific,
> which isn't/couldn't be described in epc_features. E.g. pcie-designware-ep.c
> requires a 64-bit BAR to start at a even BAR number. (The PCIe spec allows
> a 64-bit BAR to start both at an odd or even BAR number.)
>
>
> So it seems right now, alloc_space() might result in a 'struct pci_epf_bar'
> that wasn't exactly what was requested, but set_bar() should always fail if
> an EPC driver cannot fullfil exactly what was requested in the
> 'struct pci_epf_bar' (that was returned by alloc_space()).
>
>
> We all agree that this is a good idea, but does anyone actually intend to
> take on the effort of trying to create a new API that is basically
> pci_epf_alloc_space() + pci_epc_set_bar() combined?
>
> Personally, my plan is to respin/improve Damien's "improved PCI endpoint
> memory mapping API" series:
> https://lore.kernel.org/linux-pci/20240330041928.1555578-1-dlemoal@xxxxxxxxxx/
>
> But I'm also going away on two weeks vacation starting today, so it will
> take a while before I send something out...
>
>
> Kind regards,
> Niklas
--
மணிவண்ணன் சதாசிவம்