Re: [PATCH v7 1/2] PCI: designware-ep: Fix DBI access before core init

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

 



On Thu, Nov 30, 2023 at 12:08:00PM +0530, Manivannan Sadhasivam wrote:
> 
> Looking at this issue again, I think your statement may not be correct. In the
> stop_link() callback, non-core_init_notifier platforms are just disabling the
> LTSSM and enabling it again in start_link(). So all the rest of the
> configurations (DBI etc...) should not be affected during EPF bind/unbind.

Sorry for confusing you.

When toggling PERST on a driver with a core_init_notifier, you will call
dw_pcie_ep_init_complete() - which will initialize DBI settings, and then
stop/start the link by deasserting/asserting LTSSM.
(perst_assert()/perst_deassert() is functionally the equivalent to start_link()/
stop_link() on non-core_init_notifier platforms.)


For drivers without a core_init_notifier, they currently don't listen to PERST
input GPIO.
Stopping and starting the link will not call dw_pcie_ep_init_complete(),
so it will not (re-)initialize DBI settings.


My problem is that a bunch of hardware registers gets reset when receiving
a link-down reset or hot reset. It would be nice to write all DBI settings
when starting the link. That way the link going down for a millisecond, and
gettting immediately reestablished, will not be so bad. A stop + start link
will rewrite the settings. (Just like toggling PERST rewrites the settings.)


Currently, doing a bind + start link + stop link + unbind + bind + start link,
will not reinitialize all DBI writes for a driver.
(This is also true for a core_init_notifier driver, but there start/stop link
is a no-op, other than enabling the GPIO irq handler.)

What this will do during the second bind:
-allocate BARs (DBI writes)
-set iATUs (DBI writes)

What it will not redo is:
-what is done by dw_pcie_ep_init() - which is fine, because this is only
 supposed to allocate stuff or get stuff from DT, not actually touch HW
 registers.
-what is done by dw_pcie_ep_init_complete() - I think this should be done
 since it does DBI writes. E.g. clearing PTM root Cap and fixing Resizable
 BAR Cap, calling dw_pcie_setup() which sets max link width etc.



I guess the counter argument could be that... if you need to re-initialize
DBI registers, you could probably do a:
stop link + unbind EPF driver + unbind PCIe-EP driver + bind PCIe-EP driver
+ bind EPF driver + start link..
(But I don't need all that if I use a .core_init_notifier and just toggle
PERST).

Of course, toggling PERST and starting/stopping the link via sysfs is not
exactly the same thing...

For me personally, the platform I use do not require an external refclk to
write DBI settings, but I would very much like the HW to be re-initialized
either when stopping/starting the link in sysfs, or by toggling PERST, or
both.

I think that I will just add a .core_init_notifier to my WIP driver,
even though I do not require an external refclk, and simply call
dw_pcie_ep_init_complete() when receiving a PERST deassert, because I want
_all_ settings (DBI writes) to be reinitialized.
(If we receive a PERST reset request, I think it does make sense to obey
and actually reset/re-write all settings.)

A sysfs stop/start link would still not reinitialize everything...
I think it would be good if the DWC EP driver actually did this too,
but I'm fine if you consider it out of scope of your patch series.


Kind regards,
Niklas




[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