* [PATCH 1/3] PCI: rcar: Add the initialization of PCIe link in resume_noirq
@ 2017-11-08 9:28 Marek Vasut
2017-11-08 9:28 ` [PATCH 2/3] PCI: rcar: Support runtime PM, link state L1 handling Marek Vasut
` (3 more replies)
0 siblings, 4 replies; 14+ messages in thread
From: Marek Vasut @ 2017-11-08 9:28 UTC (permalink / raw)
To: linux-pci
Cc: Kazufumi Ikeda, Gaku Inami, Marek Vasut, Geert Uytterhoeven,
Simon Horman, Wolfram Sang, linux-renesas-soc
From: Kazufumi Ikeda <kaz-ikeda@xc.jp.nec.com>
Reestablish the PCIe link very early in the resume process in case it
went down to prevent PCI accesses from hanging the bus. Such accesses
can happen early in the PCI resume process, in the resume_noirq, thus
the link must be reestablished in the resume_noirq callback of the
driver.
Signed-off-by: Kazufumi Ikeda <kaz-ikeda@xc.jp.nec.com>
Signed-off-by: Gaku Inami <gaku.inami.xw@bp.renesas.com>
Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Simon Horman <horms+renesas@verge.net.au>
Cc: Wolfram Sang <wsa@the-dreams.de>
Cc: linux-renesas-soc@vger.kernel.org
---
drivers/pci/host/pcie-rcar.c | 31 ++++++++++++++++++++++++++++---
1 file changed, 28 insertions(+), 3 deletions(-)
diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
index 889603783f01..aa588a7d4811 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/host/pcie-rcar.c
@@ -43,6 +43,7 @@
/* Transfer control */
#define PCIETCTLR 0x02000
+#define DL_DOWN (1 << 3)
#define CFINIT 1
#define PCIETSTR 0x02004
#define DATA_LINK_ACTIVE 1
@@ -529,7 +530,7 @@ static void phy_write_reg(struct rcar_pcie *pcie,
phy_wait_for_ack(pcie);
}
-static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie)
+static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie, int atomic)
{
unsigned int timeout = 10;
@@ -537,7 +538,10 @@ static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie)
if ((rcar_pci_read_reg(pcie, PCIETSTR) & DATA_LINK_ACTIVE))
return 0;
- msleep(5);
+ if (atomic)
+ mdelay(5);
+ else
+ msleep(5);
}
return -ETIMEDOUT;
@@ -595,7 +599,7 @@ static int rcar_pcie_hw_init(struct rcar_pcie *pcie)
rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
/* This will timeout if we don't have a link. */
- err = rcar_pcie_wait_for_dl(pcie);
+ err = rcar_pcie_wait_for_dl(pcie, 0);
if (err)
return err;
@@ -1110,6 +1114,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)
pcie = pci_host_bridge_priv(bridge);
pcie->dev = dev;
+ platform_set_drvdata(pdev, pcie);
INIT_LIST_HEAD(&pcie->resources);
@@ -1173,10 +1178,30 @@ static int rcar_pcie_probe(struct platform_device *pdev)
return err;
}
+static int rcar_pcie_resume_noirq(struct device *dev)
+{
+ struct rcar_pcie *pcie = dev_get_drvdata(dev);
+ u32 val = rcar_pci_read_reg(pcie, PMSR);
+ int ret = 0;
+
+ if ((val == 0) || (rcar_pci_read_reg(pcie, PCIETCTLR) & DL_DOWN)) {
+ /* Re-establish the PCIe link */
+ rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
+ ret = rcar_pcie_wait_for_dl(pcie, 1);
+ }
+
+ return ret;
+}
+
+static const struct dev_pm_ops rcar_pcie_pm_ops = {
+ .resume_noirq = rcar_pcie_resume_noirq,
+};
+
static struct platform_driver rcar_pcie_driver = {
.driver = {
.name = "rcar-pcie",
.of_match_table = rcar_pcie_of_match,
+ .pm = &rcar_pcie_pm_ops,
.suppress_bind_attrs = true,
},
.probe = rcar_pcie_probe,
--
2.11.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 2/3] PCI: rcar: Support runtime PM, link state L1 handling
2017-11-08 9:28 [PATCH 1/3] PCI: rcar: Add the initialization of PCIe link in resume_noirq Marek Vasut
@ 2017-11-08 9:28 ` Marek Vasut
2017-11-10 9:03 ` Simon Horman
2017-11-08 9:28 ` [PATCH 3/3] PCI: rcar: Add the suspend/resume for pcie-rcar driver Marek Vasut
` (2 subsequent siblings)
3 siblings, 1 reply; 14+ messages in thread
From: Marek Vasut @ 2017-11-08 9:28 UTC (permalink / raw)
To: linux-pci
Cc: Phil Edworthy, Marek Vasut, Geert Uytterhoeven, Simon Horman,
Wolfram Sang, linux-renesas-soc
From: Phil Edworthy <phil.edworthy@renesas.com>
Most PCIe host controllers support L0s and L1 power states via ASPM.
The R-Car hardware only supports L0s, so when the system suspends and
resumes we have to manually handle L1.
When the system suspends, cards can put themselves into L1 and send a
PM_ENTER_L1 DLLP to the host controller. At this point, we can no longer
access the card's config registers.
The R-Car host controller will handle taking cards out of L1 as long as
the host controller has also been transitioned to L1 link state.
Ideally, we would detect the PM_ENTER_L1 DLLP using an interrupt and
transition the host to L1 immediately. However, this patch just ensures
that we can talk to cards after they have gone into L1.
When attempting a config access, it checks to see if the card has gone
into L1, and if so, does the same for the host controller.
This is based on a patch by Hien Dang <hien.dang.eb@rvc.renesas.com>
Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Simon Horman <horms+renesas@verge.net.au>
Cc: Wolfram Sang <wsa@the-dreams.de>
Cc: linux-renesas-soc@vger.kernel.org
---
drivers/pci/host/pcie-rcar.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
index aa588a7d4811..2b28292de93a 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/host/pcie-rcar.c
@@ -92,6 +92,13 @@
#define MACCTLR 0x011058
#define SPEED_CHANGE (1 << 24)
#define SCRAMBLE_DISABLE (1 << 27)
+#define PMSR 0x01105c
+#define L1FAEG (1 << 31)
+#define PM_ENTER_L1RX (1 << 23)
+#define PMSTATE (7 << 16)
+#define PMSTATE_L1 (3 << 16)
+#define PMCTLR 0x011060
+#define L1_INIT (1 << 31)
#define MACS2R 0x011078
#define MACCGSPSETR 0x011084
#define SPCNGRSN (1 << 31)
@@ -191,6 +198,7 @@ static int rcar_pcie_config_access(struct rcar_pcie *pcie,
unsigned int devfn, int where, u32 *data)
{
int dev, func, reg, index;
+ u32 val;
dev = PCI_SLOT(devfn);
func = PCI_FUNC(devfn);
@@ -232,6 +240,22 @@ static int rcar_pcie_config_access(struct rcar_pcie *pcie,
if (pcie->root_bus_nr < 0)
return PCIBIOS_DEVICE_NOT_FOUND;
+ /*
+ * If we are not in L1 link state and we have received PM_ENTER_L1 DLLP,
+ * transition to L1 link state. The HW will handle coming of of L1.
+ */
+ val = rcar_pci_read_reg(pcie, PMSR);
+ if ((val & PM_ENTER_L1RX) && ((val & PMSTATE) != PMSTATE_L1)) {
+ rcar_pci_write_reg(pcie, L1_INIT, PMCTLR);
+
+ /* Wait until we are in L1 */
+ while (!(val & L1FAEG))
+ val = rcar_pci_read_reg(pcie, PMSR);
+
+ /* Clear flags indicating link has transitioned to L1 */
+ rcar_pci_write_reg(pcie, L1FAEG | PM_ENTER_L1RX, PMSR);
+ }
+
/* Clear errors */
rcar_pci_write_reg(pcie, rcar_pci_read_reg(pcie, PCIEERRFR), PCIEERRFR);
--
2.11.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 3/3] PCI: rcar: Add the suspend/resume for pcie-rcar driver
2017-11-08 9:28 [PATCH 1/3] PCI: rcar: Add the initialization of PCIe link in resume_noirq Marek Vasut
2017-11-08 9:28 ` [PATCH 2/3] PCI: rcar: Support runtime PM, link state L1 handling Marek Vasut
@ 2017-11-08 9:28 ` Marek Vasut
2017-11-10 9:09 ` Simon Horman
2017-11-08 11:00 ` [PATCH 1/3] PCI: rcar: Add the initialization of PCIe link in resume_noirq Sergei Shtylyov
2017-11-10 8:59 ` Simon Horman
3 siblings, 1 reply; 14+ messages in thread
From: Marek Vasut @ 2017-11-08 9:28 UTC (permalink / raw)
To: linux-pci
Cc: Kazufumi Ikeda, Gaku Inami, Marek Vasut, Geert Uytterhoeven,
Simon Horman, Wolfram Sang, linux-renesas-soc
From: Kazufumi Ikeda <kaz-ikeda@xc.jp.nec.com>
This adds the suspend/resume supports for pcie-rcar. The resume handler
reprogram the hardware based on the software state kept in specific
device structures. Also it doesn't need to save any registers.
Signed-off-by: Kazufumi Ikeda <kaz-ikeda@xc.jp.nec.com>
Signed-off-by: Gaku Inami <gaku.inami.xw@bp.renesas.com>
Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Simon Horman <horms+renesas@verge.net.au>
Cc: Wolfram Sang <wsa@the-dreams.de>
Cc: linux-renesas-soc@vger.kernel.org
---
drivers/pci/host/pcie-rcar.c | 86 +++++++++++++++++++++++++++++++++++++++-----
1 file changed, 78 insertions(+), 8 deletions(-)
diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
index 2b28292de93a..7a9e30185c79 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/host/pcie-rcar.c
@@ -471,6 +471,36 @@ static void rcar_pcie_force_speedup(struct rcar_pcie *pcie)
(macsr & LINK_SPEED) == LINK_SPEED_5_0GTS ? "5" : "2.5");
}
+static int rcar_pcie_hw_enable(struct rcar_pcie *pcie)
+{
+ struct resource_entry *win;
+ LIST_HEAD(res);
+ int i = 0;
+
+ /* Try setting 5 GT/s link speed */
+ rcar_pcie_force_speedup(pcie);
+
+ /* Setup PCI resources */
+ resource_list_for_each_entry(win, &pcie->resources) {
+ struct resource *res = win->res;
+
+ if (!res->flags)
+ continue;
+
+ switch (resource_type(res)) {
+ case IORESOURCE_IO:
+ case IORESOURCE_MEM:
+ rcar_pcie_setup_window(i, pcie, res);
+ i++;
+ break;
+ default:
+ continue;
+ }
+ }
+
+ return 0;
+}
+
static int rcar_pcie_enable(struct rcar_pcie *pcie)
{
struct device *dev = pcie->dev;
@@ -872,11 +902,25 @@ static const struct irq_domain_ops msi_domain_ops = {
.map = rcar_msi_map,
};
+static void rcar_pcie_hw_enable_msi(struct rcar_pcie *pcie)
+{
+ struct rcar_msi *msi = &pcie->msi;
+ unsigned long base;
+
+ /* setup MSI data target */
+ base = virt_to_phys((void *)msi->pages);
+
+ rcar_pci_write_reg(pcie, base | MSIFE, PCIEMSIALR);
+ rcar_pci_write_reg(pcie, 0, PCIEMSIAUR);
+
+ /* enable all MSI interrupts */
+ rcar_pci_write_reg(pcie, 0xffffffff, PCIEMSIIER);
+}
+
static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
{
struct device *dev = pcie->dev;
struct rcar_msi *msi = &pcie->msi;
- unsigned long base;
int err, i;
mutex_init(&msi->lock);
@@ -915,13 +959,7 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
/* setup MSI data target */
msi->pages = __get_free_pages(GFP_KERNEL, 0);
- base = virt_to_phys((void *)msi->pages);
-
- rcar_pci_write_reg(pcie, base | MSIFE, PCIEMSIALR);
- rcar_pci_write_reg(pcie, 0, PCIEMSIAUR);
-
- /* enable all MSI interrupts */
- rcar_pci_write_reg(pcie, 0xffffffff, PCIEMSIIER);
+ rcar_pcie_hw_enable_msi(pcie);
return 0;
@@ -1202,6 +1240,37 @@ static int rcar_pcie_probe(struct platform_device *pdev)
return err;
}
+static int rcar_pcie_resume(struct device *dev)
+{
+ struct rcar_pcie *pcie = dev_get_drvdata(dev);
+ unsigned int data;
+ int err;
+ int (*hw_init_fn)(struct rcar_pcie *);
+
+ err = rcar_pcie_parse_map_dma_ranges(pcie, dev->of_node);
+ if (err)
+ return 0;
+
+ /* Failure to get a link might just be that no cards are inserted */
+ hw_init_fn = of_device_get_match_data(dev);
+ err = hw_init_fn(pcie);
+ if (err) {
+ dev_info(dev, "PCIe link down\n");
+ return 0;
+ }
+
+ data = rcar_pci_read_reg(pcie, MACSR);
+ dev_info(dev, "PCIe x%d: link up\n", (data >> 20) & 0x3f);
+
+ /* Enable MSI */
+ if (IS_ENABLED(CONFIG_PCI_MSI))
+ rcar_pcie_hw_enable_msi(pcie);
+
+ rcar_pcie_hw_enable(pcie);
+
+ return 0;
+}
+
static int rcar_pcie_resume_noirq(struct device *dev)
{
struct rcar_pcie *pcie = dev_get_drvdata(dev);
@@ -1218,6 +1287,7 @@ static int rcar_pcie_resume_noirq(struct device *dev)
}
static const struct dev_pm_ops rcar_pcie_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(NULL, rcar_pcie_resume)
.resume_noirq = rcar_pcie_resume_noirq,
};
--
2.11.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 1/3] PCI: rcar: Add the initialization of PCIe link in resume_noirq
2017-11-08 9:28 [PATCH 1/3] PCI: rcar: Add the initialization of PCIe link in resume_noirq Marek Vasut
2017-11-08 9:28 ` [PATCH 2/3] PCI: rcar: Support runtime PM, link state L1 handling Marek Vasut
2017-11-08 9:28 ` [PATCH 3/3] PCI: rcar: Add the suspend/resume for pcie-rcar driver Marek Vasut
@ 2017-11-08 11:00 ` Sergei Shtylyov
2017-11-10 21:01 ` Marek Vasut
2017-11-10 8:59 ` Simon Horman
3 siblings, 1 reply; 14+ messages in thread
From: Sergei Shtylyov @ 2017-11-08 11:00 UTC (permalink / raw)
To: Marek Vasut, linux-pci
Cc: Kazufumi Ikeda, Gaku Inami, Marek Vasut, Geert Uytterhoeven,
Simon Horman, Wolfram Sang, linux-renesas-soc
On 11/8/2017 12:28 PM, Marek Vasut wrote:
> From: Kazufumi Ikeda <kaz-ikeda@xc.jp.nec.com>
>
> Reestablish the PCIe link very early in the resume process in case it
> went down to prevent PCI accesses from hanging the bus. Such accesses
> can happen early in the PCI resume process, in the resume_noirq, thus
> the link must be reestablished in the resume_noirq callback of the
> driver.
>
> Signed-off-by: Kazufumi Ikeda <kaz-ikeda@xc.jp.nec.com>
> Signed-off-by: Gaku Inami <gaku.inami.xw@bp.renesas.com>
> Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
> Cc: Geert Uytterhoeven <geert+renesas@glider.be>
> Cc: Simon Horman <horms+renesas@verge.net.au>
> Cc: Wolfram Sang <wsa@the-dreams.de>
> Cc: linux-renesas-soc@vger.kernel.org
> ---
> drivers/pci/host/pcie-rcar.c | 31 ++++++++++++++++++++++++++++---
> 1 file changed, 28 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
> index 889603783f01..aa588a7d4811 100644
> --- a/drivers/pci/host/pcie-rcar.c
> +++ b/drivers/pci/host/pcie-rcar.c
[...]
> @@ -529,7 +530,7 @@ static void phy_write_reg(struct rcar_pcie *pcie,
> phy_wait_for_ack(pcie);
> }
>
> -static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie)
> +static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie, int atomic)
How about *bool* atomic?
[...]
MBR, Sergei
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/3] PCI: rcar: Add the initialization of PCIe link in resume_noirq
2017-11-08 9:28 [PATCH 1/3] PCI: rcar: Add the initialization of PCIe link in resume_noirq Marek Vasut
` (2 preceding siblings ...)
2017-11-08 11:00 ` [PATCH 1/3] PCI: rcar: Add the initialization of PCIe link in resume_noirq Sergei Shtylyov
@ 2017-11-10 8:59 ` Simon Horman
2017-11-10 21:14 ` Marek Vasut
3 siblings, 1 reply; 14+ messages in thread
From: Simon Horman @ 2017-11-10 8:59 UTC (permalink / raw)
To: Marek Vasut
Cc: linux-pci, Kazufumi Ikeda, Gaku Inami, Marek Vasut,
Geert Uytterhoeven, Wolfram Sang, linux-renesas-soc
Hi Marek,
On Wed, Nov 08, 2017 at 10:28:04AM +0100, Marek Vasut wrote:
> From: Kazufumi Ikeda <kaz-ikeda@xc.jp.nec.com>
>
> Reestablish the PCIe link very early in the resume process in case it
> went down to prevent PCI accesses from hanging the bus. Such accesses
> can happen early in the PCI resume process, in the resume_noirq, thus
> the link must be reestablished in the resume_noirq callback of the
> driver.
>
> Signed-off-by: Kazufumi Ikeda <kaz-ikeda@xc.jp.nec.com>
> Signed-off-by: Gaku Inami <gaku.inami.xw@bp.renesas.com>
> Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
> Cc: Geert Uytterhoeven <geert+renesas@glider.be>
> Cc: Simon Horman <horms+renesas@verge.net.au>
> Cc: Wolfram Sang <wsa@the-dreams.de>
> Cc: linux-renesas-soc@vger.kernel.org
For patch-sets (with more than one patch) please provide a cover-letter.
The --cover-letter option to git format-patch can help.
> ---
> drivers/pci/host/pcie-rcar.c | 31 ++++++++++++++++++++++++++++---
> 1 file changed, 28 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
> index 889603783f01..aa588a7d4811 100644
> --- a/drivers/pci/host/pcie-rcar.c
> +++ b/drivers/pci/host/pcie-rcar.c
> @@ -43,6 +43,7 @@
>
> /* Transfer control */
> #define PCIETCTLR 0x02000
> +#define DL_DOWN (1 << 3)
Can you use the BIT() macro here?
> #define CFINIT 1
> #define PCIETSTR 0x02004
> #define DATA_LINK_ACTIVE 1
> @@ -529,7 +530,7 @@ static void phy_write_reg(struct rcar_pcie *pcie,
> phy_wait_for_ack(pcie);
> }
>
> -static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie)
> +static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie, int atomic)
As Sergei mentioned bool seems like a more appropriate type for atomic.
> {
> unsigned int timeout = 10;
>
> @@ -537,7 +538,10 @@ static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie)
> if ((rcar_pci_read_reg(pcie, PCIETSTR) & DATA_LINK_ACTIVE))
> return 0;
>
> - msleep(5);
> + if (atomic)
> + mdelay(5);
> + else
> + msleep(5);
If we must delay, then I suppose this is reasonable.
> }
>
> return -ETIMEDOUT;
> @@ -595,7 +599,7 @@ static int rcar_pcie_hw_init(struct rcar_pcie *pcie)
> rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
>
> /* This will timeout if we don't have a link. */
> - err = rcar_pcie_wait_for_dl(pcie);
> + err = rcar_pcie_wait_for_dl(pcie, 0);
> if (err)
> return err;
>
> @@ -1110,6 +1114,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)
> pcie = pci_host_bridge_priv(bridge);
>
> pcie->dev = dev;
> + platform_set_drvdata(pdev, pcie);
>
> INIT_LIST_HEAD(&pcie->resources);
>
> @@ -1173,10 +1178,30 @@ static int rcar_pcie_probe(struct platform_device *pdev)
> return err;
> }
>
> +static int rcar_pcie_resume_noirq(struct device *dev)
> +{
> + struct rcar_pcie *pcie = dev_get_drvdata(dev);
> + u32 val = rcar_pci_read_reg(pcie, PMSR);
> + int ret = 0;
> +
> + if ((val == 0) || (rcar_pci_read_reg(pcie, PCIETCTLR) & DL_DOWN)) {
Please remove the unnecessary parentheses from the line above.
Also, I would prefer if the function returned early.
Something like (completely untested!):
if (rcar_pci_read_reg(pcie, PMSR) &&
!(rcar_pci_read_reg(pcie, PCIETCTLR) & DL_DOWN))
return 0;
rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
return rcar_pcie_wait_for_dl(pcie, 1);
> + /* Re-establish the PCIe link */
> + rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
> + ret = rcar_pcie_wait_for_dl(pcie, 1);
> + }
> +
> + return ret;
> +}
> +
> +static const struct dev_pm_ops rcar_pcie_pm_ops = {
> + .resume_noirq = rcar_pcie_resume_noirq,
> +};
> +
> static struct platform_driver rcar_pcie_driver = {
> .driver = {
> .name = "rcar-pcie",
> .of_match_table = rcar_pcie_of_match,
> + .pm = &rcar_pcie_pm_ops,
> .suppress_bind_attrs = true,
> },
> .probe = rcar_pcie_probe,
> --
> 2.11.0
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/3] PCI: rcar: Support runtime PM, link state L1 handling
2017-11-08 9:28 ` [PATCH 2/3] PCI: rcar: Support runtime PM, link state L1 handling Marek Vasut
@ 2017-11-10 9:03 ` Simon Horman
2017-11-10 21:22 ` Marek Vasut
0 siblings, 1 reply; 14+ messages in thread
From: Simon Horman @ 2017-11-10 9:03 UTC (permalink / raw)
To: Marek Vasut
Cc: linux-pci, Phil Edworthy, Marek Vasut, Geert Uytterhoeven,
Wolfram Sang, linux-renesas-soc
On Wed, Nov 08, 2017 at 10:28:05AM +0100, Marek Vasut wrote:
> From: Phil Edworthy <phil.edworthy@renesas.com>
>
> Most PCIe host controllers support L0s and L1 power states via ASPM.
> The R-Car hardware only supports L0s, so when the system suspends and
> resumes we have to manually handle L1.
>
> When the system suspends, cards can put themselves into L1 and send a
> PM_ENTER_L1 DLLP to the host controller. At this point, we can no longer
> access the card's config registers.
>
> The R-Car host controller will handle taking cards out of L1 as long as
> the host controller has also been transitioned to L1 link state.
>
> Ideally, we would detect the PM_ENTER_L1 DLLP using an interrupt and
> transition the host to L1 immediately. However, this patch just ensures
> that we can talk to cards after they have gone into L1.
> When attempting a config access, it checks to see if the card has gone
> into L1, and if so, does the same for the host controller.
>
> This is based on a patch by Hien Dang <hien.dang.eb@rvc.renesas.com>
>
> Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
> Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
> Cc: Geert Uytterhoeven <geert+renesas@glider.be>
> Cc: Simon Horman <horms+renesas@verge.net.au>
> Cc: Wolfram Sang <wsa@the-dreams.de>
> Cc: linux-renesas-soc@vger.kernel.org
Hi Marek,
With my nit addressed please feel free to add:
Acked-by: Simon Horman <horms+renesas@verge.net.au>
> ---
> drivers/pci/host/pcie-rcar.c | 24 ++++++++++++++++++++++++
> 1 file changed, 24 insertions(+)
>
> diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
> index aa588a7d4811..2b28292de93a 100644
> --- a/drivers/pci/host/pcie-rcar.c
> +++ b/drivers/pci/host/pcie-rcar.c
> @@ -92,6 +92,13 @@
> #define MACCTLR 0x011058
> #define SPEED_CHANGE (1 << 24)
> #define SCRAMBLE_DISABLE (1 << 27)
> +#define PMSR 0x01105c
> +#define L1FAEG (1 << 31)
> +#define PM_ENTER_L1RX (1 << 23)
> +#define PMSTATE (7 << 16)
> +#define PMSTATE_L1 (3 << 16)
> +#define PMCTLR 0x011060
> +#define L1_INIT (1 << 31)
The BIT() and GENMASK() macros are nice in my opinion.
But I see what you have added follows the style of the existing code
in the driver.
> #define MACS2R 0x011078
> #define MACCGSPSETR 0x011084
> #define SPCNGRSN (1 << 31)
> @@ -191,6 +198,7 @@ static int rcar_pcie_config_access(struct rcar_pcie *pcie,
> unsigned int devfn, int where, u32 *data)
> {
> int dev, func, reg, index;
> + u32 val;
>
> dev = PCI_SLOT(devfn);
> func = PCI_FUNC(devfn);
> @@ -232,6 +240,22 @@ static int rcar_pcie_config_access(struct rcar_pcie *pcie,
> if (pcie->root_bus_nr < 0)
> return PCIBIOS_DEVICE_NOT_FOUND;
>
> + /*
> + * If we are not in L1 link state and we have received PM_ENTER_L1 DLLP,
> + * transition to L1 link state. The HW will handle coming of of L1.
> + */
> + val = rcar_pci_read_reg(pcie, PMSR);
> + if ((val & PM_ENTER_L1RX) && ((val & PMSTATE) != PMSTATE_L1)) {
nit: please remove the unnecessary parentheses from the line above.
> + rcar_pci_write_reg(pcie, L1_INIT, PMCTLR);
> +
> + /* Wait until we are in L1 */
> + while (!(val & L1FAEG))
> + val = rcar_pci_read_reg(pcie, PMSR);
> +
> + /* Clear flags indicating link has transitioned to L1 */
> + rcar_pci_write_reg(pcie, L1FAEG | PM_ENTER_L1RX, PMSR);
> + }
> +
> /* Clear errors */
> rcar_pci_write_reg(pcie, rcar_pci_read_reg(pcie, PCIEERRFR), PCIEERRFR);
>
> --
> 2.11.0
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 3/3] PCI: rcar: Add the suspend/resume for pcie-rcar driver
2017-11-08 9:28 ` [PATCH 3/3] PCI: rcar: Add the suspend/resume for pcie-rcar driver Marek Vasut
@ 2017-11-10 9:09 ` Simon Horman
2017-11-10 21:53 ` Marek Vasut
0 siblings, 1 reply; 14+ messages in thread
From: Simon Horman @ 2017-11-10 9:09 UTC (permalink / raw)
To: Marek Vasut
Cc: linux-pci, Kazufumi Ikeda, Gaku Inami, Marek Vasut,
Geert Uytterhoeven, Wolfram Sang, linux-renesas-soc
On Wed, Nov 08, 2017 at 10:28:06AM +0100, Marek Vasut wrote:
> From: Kazufumi Ikeda <kaz-ikeda@xc.jp.nec.com>
>
> This adds the suspend/resume supports for pcie-rcar. The resume handler
> reprogram the hardware based on the software state kept in specific
> device structures. Also it doesn't need to save any registers.
>
> Signed-off-by: Kazufumi Ikeda <kaz-ikeda@xc.jp.nec.com>
> Signed-off-by: Gaku Inami <gaku.inami.xw@bp.renesas.com>
> Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
> Cc: Geert Uytterhoeven <geert+renesas@glider.be>
> Cc: Simon Horman <horms+renesas@verge.net.au>
> Cc: Wolfram Sang <wsa@the-dreams.de>
> Cc: linux-renesas-soc@vger.kernel.org
> ---
> drivers/pci/host/pcie-rcar.c | 86 +++++++++++++++++++++++++++++++++++++++-----
> 1 file changed, 78 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
> index 2b28292de93a..7a9e30185c79 100644
> --- a/drivers/pci/host/pcie-rcar.c
> +++ b/drivers/pci/host/pcie-rcar.c
> @@ -471,6 +471,36 @@ static void rcar_pcie_force_speedup(struct rcar_pcie *pcie)
> (macsr & LINK_SPEED) == LINK_SPEED_5_0GTS ? "5" : "2.5");
> }
>
> +static int rcar_pcie_hw_enable(struct rcar_pcie *pcie)
This function always returns 0 and the value is not checked by the caller.
Can we change the return type to void?
> +{
> + struct resource_entry *win;
> + LIST_HEAD(res);
> + int i = 0;
> +
> + /* Try setting 5 GT/s link speed */
What if it fails?
> + rcar_pcie_force_speedup(pcie);
> +
> + /* Setup PCI resources */
> + resource_list_for_each_entry(win, &pcie->resources) {
> + struct resource *res = win->res;
> +
> + if (!res->flags)
> + continue;
> +
> + switch (resource_type(res)) {
> + case IORESOURCE_IO:
> + case IORESOURCE_MEM:
> + rcar_pcie_setup_window(i, pcie, res);
> + i++;
> + break;
> + default:
> + continue;
Can the default case be omitted?
> + }
> + }
> +
> + return 0;
> +}
> +
> static int rcar_pcie_enable(struct rcar_pcie *pcie)
> {
> struct device *dev = pcie->dev;
> @@ -872,11 +902,25 @@ static const struct irq_domain_ops msi_domain_ops = {
> .map = rcar_msi_map,
> };
>
> +static void rcar_pcie_hw_enable_msi(struct rcar_pcie *pcie)
> +{
> + struct rcar_msi *msi = &pcie->msi;
> + unsigned long base;
> +
> + /* setup MSI data target */
> + base = virt_to_phys((void *)msi->pages);
Why do you need to cast to void *?
I expect such casting can be done implicitly.
> +
> + rcar_pci_write_reg(pcie, base | MSIFE, PCIEMSIALR);
> + rcar_pci_write_reg(pcie, 0, PCIEMSIAUR);
> +
> + /* enable all MSI interrupts */
> + rcar_pci_write_reg(pcie, 0xffffffff, PCIEMSIIER);
> +}
> +
> static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
> {
> struct device *dev = pcie->dev;
> struct rcar_msi *msi = &pcie->msi;
> - unsigned long base;
> int err, i;
>
> mutex_init(&msi->lock);
> @@ -915,13 +959,7 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
>
> /* setup MSI data target */
> msi->pages = __get_free_pages(GFP_KERNEL, 0);
> - base = virt_to_phys((void *)msi->pages);
> -
> - rcar_pci_write_reg(pcie, base | MSIFE, PCIEMSIALR);
> - rcar_pci_write_reg(pcie, 0, PCIEMSIAUR);
> -
> - /* enable all MSI interrupts */
> - rcar_pci_write_reg(pcie, 0xffffffff, PCIEMSIIER);
> + rcar_pcie_hw_enable_msi(pcie);
>
> return 0;
>
> @@ -1202,6 +1240,37 @@ static int rcar_pcie_probe(struct platform_device *pdev)
> return err;
> }
>
> +static int rcar_pcie_resume(struct device *dev)
> +{
> + struct rcar_pcie *pcie = dev_get_drvdata(dev);
> + unsigned int data;
> + int err;
> + int (*hw_init_fn)(struct rcar_pcie *);
Please sort local variables in reverse xmas tree order.
> +
> + err = rcar_pcie_parse_map_dma_ranges(pcie, dev->of_node);
> + if (err)
> + return 0;
> +
> + /* Failure to get a link might just be that no cards are inserted */
> + hw_init_fn = of_device_get_match_data(dev);
> + err = hw_init_fn(pcie);
> + if (err) {
> + dev_info(dev, "PCIe link down\n");
> + return 0;
> + }
> +
> + data = rcar_pci_read_reg(pcie, MACSR);
> + dev_info(dev, "PCIe x%d: link up\n", (data >> 20) & 0x3f);
> +
> + /* Enable MSI */
> + if (IS_ENABLED(CONFIG_PCI_MSI))
> + rcar_pcie_hw_enable_msi(pcie);
> +
> + rcar_pcie_hw_enable(pcie);
> +
> + return 0;
> +}
> +
> static int rcar_pcie_resume_noirq(struct device *dev)
> {
> struct rcar_pcie *pcie = dev_get_drvdata(dev);
> @@ -1218,6 +1287,7 @@ static int rcar_pcie_resume_noirq(struct device *dev)
> }
>
> static const struct dev_pm_ops rcar_pcie_pm_ops = {
> + SET_SYSTEM_SLEEP_PM_OPS(NULL, rcar_pcie_resume)
> .resume_noirq = rcar_pcie_resume_noirq,
> };
>
> --
> 2.11.0
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/3] PCI: rcar: Add the initialization of PCIe link in resume_noirq
2017-11-08 11:00 ` [PATCH 1/3] PCI: rcar: Add the initialization of PCIe link in resume_noirq Sergei Shtylyov
@ 2017-11-10 21:01 ` Marek Vasut
0 siblings, 0 replies; 14+ messages in thread
From: Marek Vasut @ 2017-11-10 21:01 UTC (permalink / raw)
To: Sergei Shtylyov, linux-pci
Cc: Kazufumi Ikeda, Gaku Inami, Marek Vasut, Geert Uytterhoeven,
Simon Horman, Wolfram Sang, linux-renesas-soc
On 11/08/2017 12:00 PM, Sergei Shtylyov wrote:
> On 11/8/2017 12:28 PM, Marek Vasut wrote:
>
>> From: Kazufumi Ikeda <kaz-ikeda@xc.jp.nec.com>
>>
>> Reestablish the PCIe link very early in the resume process in case it
>> went down to prevent PCI accesses from hanging the bus. Such accesses
>> can happen early in the PCI resume process, in the resume_noirq, thus
>> the link must be reestablished in the resume_noirq callback of the
>> driver.
>>
>> Signed-off-by: Kazufumi Ikeda <kaz-ikeda@xc.jp.nec.com>
>> Signed-off-by: Gaku Inami <gaku.inami.xw@bp.renesas.com>
>> Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
>> Cc: Geert Uytterhoeven <geert+renesas@glider.be>
>> Cc: Simon Horman <horms+renesas@verge.net.au>
>> Cc: Wolfram Sang <wsa@the-dreams.de>
>> Cc: linux-renesas-soc@vger.kernel.org
>> ---
>> drivers/pci/host/pcie-rcar.c | 31 ++++++++++++++++++++++++++++---
>> 1 file changed, 28 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
>> index 889603783f01..aa588a7d4811 100644
>> --- a/drivers/pci/host/pcie-rcar.c
>> +++ b/drivers/pci/host/pcie-rcar.c
> [...]
>> @@ -529,7 +530,7 @@ static void phy_write_reg(struct rcar_pcie *pcie,
>> phy_wait_for_ack(pcie);
>> }
>> -static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie)
>> +static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie, int atomic)
>
> How about *bool* atomic?
Not a big fan of bool in C, but I think I can avoid this altogether.
If I poll more often, I can just use udelay(5) for such a short delay.
> [...]
>
> MBR, Sergei
--
Best regards,
Marek Vasut
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/3] PCI: rcar: Add the initialization of PCIe link in resume_noirq
2017-11-10 8:59 ` Simon Horman
@ 2017-11-10 21:14 ` Marek Vasut
2017-11-13 6:58 ` Simon Horman
0 siblings, 1 reply; 14+ messages in thread
From: Marek Vasut @ 2017-11-10 21:14 UTC (permalink / raw)
To: Simon Horman
Cc: linux-pci, Kazufumi Ikeda, Gaku Inami, Marek Vasut,
Geert Uytterhoeven, Wolfram Sang, linux-renesas-soc
On 11/10/2017 09:59 AM, Simon Horman wrote:
> Hi Marek,
Hi Simon,
> On Wed, Nov 08, 2017 at 10:28:04AM +0100, Marek Vasut wrote:
>> From: Kazufumi Ikeda <kaz-ikeda@xc.jp.nec.com>
>>
>> Reestablish the PCIe link very early in the resume process in case it
>> went down to prevent PCI accesses from hanging the bus. Such accesses
>> can happen early in the PCI resume process, in the resume_noirq, thus
>> the link must be reestablished in the resume_noirq callback of the
>> driver.
>>
>> Signed-off-by: Kazufumi Ikeda <kaz-ikeda@xc.jp.nec.com>
>> Signed-off-by: Gaku Inami <gaku.inami.xw@bp.renesas.com>
>> Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
>> Cc: Geert Uytterhoeven <geert+renesas@glider.be>
>> Cc: Simon Horman <horms+renesas@verge.net.au>
>> Cc: Wolfram Sang <wsa@the-dreams.de>
>> Cc: linux-renesas-soc@vger.kernel.org
>
> For patch-sets (with more than one patch) please provide a cover-letter.
> The --cover-letter option to git format-patch can help.
>
>> ---
>> drivers/pci/host/pcie-rcar.c | 31 ++++++++++++++++++++++++++++---
>> 1 file changed, 28 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
>> index 889603783f01..aa588a7d4811 100644
>> --- a/drivers/pci/host/pcie-rcar.c
>> +++ b/drivers/pci/host/pcie-rcar.c
>> @@ -43,6 +43,7 @@
>>
>> /* Transfer control */
>> #define PCIETCTLR 0x02000
>> +#define DL_DOWN (1 << 3)
>
> Can you use the BIT() macro here?
Yes, I'll also add a patch to the series to convert all the others to
the BIT() macro, to keep things consistent.
>> #define CFINIT 1
>> #define PCIETSTR 0x02004
>> #define DATA_LINK_ACTIVE 1
>> @@ -529,7 +530,7 @@ static void phy_write_reg(struct rcar_pcie *pcie,
>> phy_wait_for_ack(pcie);
>> }
>>
>> -static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie)
>> +static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie, int atomic)
>
> As Sergei mentioned bool seems like a more appropriate type for atomic.
I can actually get rid of this altogether.
>> {
>> unsigned int timeout = 10;
>>
>> @@ -537,7 +538,10 @@ static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie)
>> if ((rcar_pci_read_reg(pcie, PCIETSTR) & DATA_LINK_ACTIVE))
>> return 0;
>>
>> - msleep(5);
>> + if (atomic)
>> + mdelay(5);
>> + else
>> + msleep(5);
>
> If we must delay, then I suppose this is reasonable.
See above
>> }
>>
>> return -ETIMEDOUT;
>> @@ -595,7 +599,7 @@ static int rcar_pcie_hw_init(struct rcar_pcie *pcie)
>> rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
>>
>> /* This will timeout if we don't have a link. */
>> - err = rcar_pcie_wait_for_dl(pcie);
>> + err = rcar_pcie_wait_for_dl(pcie, 0);
>> if (err)
>> return err;
>>
>> @@ -1110,6 +1114,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)
>> pcie = pci_host_bridge_priv(bridge);
>>
>> pcie->dev = dev;
>> + platform_set_drvdata(pdev, pcie);
>>
>> INIT_LIST_HEAD(&pcie->resources);
>>
>> @@ -1173,10 +1178,30 @@ static int rcar_pcie_probe(struct platform_device *pdev)
>> return err;
>> }
>>
>> +static int rcar_pcie_resume_noirq(struct device *dev)
>> +{
>> + struct rcar_pcie *pcie = dev_get_drvdata(dev);
>> + u32 val = rcar_pci_read_reg(pcie, PMSR);
>> + int ret = 0;
>> +
>> + if ((val == 0) || (rcar_pci_read_reg(pcie, PCIETCTLR) & DL_DOWN)) {
>
> Please remove the unnecessary parentheses from the line above.
>
> Also, I would prefer if the function returned early.
> Something like (completely untested!):
This should work.
> if (rcar_pci_read_reg(pcie, PMSR) &&
> !(rcar_pci_read_reg(pcie, PCIETCTLR) & DL_DOWN))
> return 0;
>
> rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
> return rcar_pcie_wait_for_dl(pcie, 1);
>
>> + /* Re-establish the PCIe link */
>> + rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
>> + ret = rcar_pcie_wait_for_dl(pcie, 1);
>> + }
>> +
>> + return ret;
>> +}
>> +
>> +static const struct dev_pm_ops rcar_pcie_pm_ops = {
>> + .resume_noirq = rcar_pcie_resume_noirq,
>> +};
>> +
>> static struct platform_driver rcar_pcie_driver = {
>> .driver = {
>> .name = "rcar-pcie",
>> .of_match_table = rcar_pcie_of_match,
>> + .pm = &rcar_pcie_pm_ops,
>> .suppress_bind_attrs = true,
>> },
>> .probe = rcar_pcie_probe,
>> --
>> 2.11.0
>>
--
Best regards,
Marek Vasut
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/3] PCI: rcar: Support runtime PM, link state L1 handling
2017-11-10 9:03 ` Simon Horman
@ 2017-11-10 21:22 ` Marek Vasut
0 siblings, 0 replies; 14+ messages in thread
From: Marek Vasut @ 2017-11-10 21:22 UTC (permalink / raw)
To: Simon Horman
Cc: linux-pci, Phil Edworthy, Marek Vasut, Geert Uytterhoeven,
Wolfram Sang, linux-renesas-soc
On 11/10/2017 10:03 AM, Simon Horman wrote:
> On Wed, Nov 08, 2017 at 10:28:05AM +0100, Marek Vasut wrote:
>> From: Phil Edworthy <phil.edworthy@renesas.com>
>>
>> Most PCIe host controllers support L0s and L1 power states via ASPM.
>> The R-Car hardware only supports L0s, so when the system suspends and
>> resumes we have to manually handle L1.
>>
>> When the system suspends, cards can put themselves into L1 and send a
>> PM_ENTER_L1 DLLP to the host controller. At this point, we can no longer
>> access the card's config registers.
>>
>> The R-Car host controller will handle taking cards out of L1 as long as
>> the host controller has also been transitioned to L1 link state.
>>
>> Ideally, we would detect the PM_ENTER_L1 DLLP using an interrupt and
>> transition the host to L1 immediately. However, this patch just ensures
>> that we can talk to cards after they have gone into L1.
>> When attempting a config access, it checks to see if the card has gone
>> into L1, and if so, does the same for the host controller.
>>
>> This is based on a patch by Hien Dang <hien.dang.eb@rvc.renesas.com>
>>
>> Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
>> Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
>> Cc: Geert Uytterhoeven <geert+renesas@glider.be>
>> Cc: Simon Horman <horms+renesas@verge.net.au>
>> Cc: Wolfram Sang <wsa@the-dreams.de>
>> Cc: linux-renesas-soc@vger.kernel.org
>
> Hi Marek,
>
> With my nit addressed please feel free to add:
>
> Acked-by: Simon Horman <horms+renesas@verge.net.au>
>
>> ---
>> drivers/pci/host/pcie-rcar.c | 24 ++++++++++++++++++++++++
>> 1 file changed, 24 insertions(+)
>>
>> diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
>> index aa588a7d4811..2b28292de93a 100644
>> --- a/drivers/pci/host/pcie-rcar.c
>> +++ b/drivers/pci/host/pcie-rcar.c
>> @@ -92,6 +92,13 @@
>> #define MACCTLR 0x011058
>> #define SPEED_CHANGE (1 << 24)
>> #define SCRAMBLE_DISABLE (1 << 27)
>> +#define PMSR 0x01105c
>> +#define L1FAEG (1 << 31)
>> +#define PM_ENTER_L1RX (1 << 23)
>> +#define PMSTATE (7 << 16)
>> +#define PMSTATE_L1 (3 << 16)
>> +#define PMCTLR 0x011060
>> +#define L1_INIT (1 << 31)
>
> The BIT() and GENMASK() macros are nice in my opinion.
> But I see what you have added follows the style of the existing code
> in the driver.
I added a patch into the series to clean this up and will then use BIT()
and GENMASK() here too.
>> #define MACS2R 0x011078
>> #define MACCGSPSETR 0x011084
>> #define SPCNGRSN (1 << 31)
>> @@ -191,6 +198,7 @@ static int rcar_pcie_config_access(struct rcar_pcie *pcie,
>> unsigned int devfn, int where, u32 *data)
>> {
>> int dev, func, reg, index;
>> + u32 val;
>>
>> dev = PCI_SLOT(devfn);
>> func = PCI_FUNC(devfn);
>> @@ -232,6 +240,22 @@ static int rcar_pcie_config_access(struct rcar_pcie *pcie,
>> if (pcie->root_bus_nr < 0)
>> return PCIBIOS_DEVICE_NOT_FOUND;
>>
>> + /*
>> + * If we are not in L1 link state and we have received PM_ENTER_L1 DLLP,
>> + * transition to L1 link state. The HW will handle coming of of L1.
>> + */
>> + val = rcar_pci_read_reg(pcie, PMSR);
>> + if ((val & PM_ENTER_L1RX) && ((val & PMSTATE) != PMSTATE_L1)) {
>
> nit: please remove the unnecessary parentheses from the line above.
Fixed
>> + rcar_pci_write_reg(pcie, L1_INIT, PMCTLR);
>> +
>> + /* Wait until we are in L1 */
>> + while (!(val & L1FAEG))
>> + val = rcar_pci_read_reg(pcie, PMSR);
>> +
>> + /* Clear flags indicating link has transitioned to L1 */
>> + rcar_pci_write_reg(pcie, L1FAEG | PM_ENTER_L1RX, PMSR);
>> + }
>> +
>> /* Clear errors */
>> rcar_pci_write_reg(pcie, rcar_pci_read_reg(pcie, PCIEERRFR), PCIEERRFR);
>>
>> --
>> 2.11.0
>>
--
Best regards,
Marek Vasut
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 3/3] PCI: rcar: Add the suspend/resume for pcie-rcar driver
2017-11-10 9:09 ` Simon Horman
@ 2017-11-10 21:53 ` Marek Vasut
2017-11-13 7:00 ` Simon Horman
0 siblings, 1 reply; 14+ messages in thread
From: Marek Vasut @ 2017-11-10 21:53 UTC (permalink / raw)
To: Simon Horman
Cc: linux-pci, Kazufumi Ikeda, Gaku Inami, Marek Vasut,
Geert Uytterhoeven, Wolfram Sang, linux-renesas-soc
On 11/10/2017 10:09 AM, Simon Horman wrote:
> On Wed, Nov 08, 2017 at 10:28:06AM +0100, Marek Vasut wrote:
>> From: Kazufumi Ikeda <kaz-ikeda@xc.jp.nec.com>
>>
>> This adds the suspend/resume supports for pcie-rcar. The resume handler
>> reprogram the hardware based on the software state kept in specific
>> device structures. Also it doesn't need to save any registers.
>>
>> Signed-off-by: Kazufumi Ikeda <kaz-ikeda@xc.jp.nec.com>
>> Signed-off-by: Gaku Inami <gaku.inami.xw@bp.renesas.com>
>> Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
>> Cc: Geert Uytterhoeven <geert+renesas@glider.be>
>> Cc: Simon Horman <horms+renesas@verge.net.au>
>> Cc: Wolfram Sang <wsa@the-dreams.de>
>> Cc: linux-renesas-soc@vger.kernel.org
>> ---
>> drivers/pci/host/pcie-rcar.c | 86 +++++++++++++++++++++++++++++++++++++++-----
>> 1 file changed, 78 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
>> index 2b28292de93a..7a9e30185c79 100644
>> --- a/drivers/pci/host/pcie-rcar.c
>> +++ b/drivers/pci/host/pcie-rcar.c
>> @@ -471,6 +471,36 @@ static void rcar_pcie_force_speedup(struct rcar_pcie *pcie)
>> (macsr & LINK_SPEED) == LINK_SPEED_5_0GTS ? "5" : "2.5");
>> }
>>
>> +static int rcar_pcie_hw_enable(struct rcar_pcie *pcie)
>
> This function always returns 0 and the value is not checked by the caller.
> Can we change the return type to void?
Yes, done
>> +{
>> + struct resource_entry *win;
>> + LIST_HEAD(res);
>> + int i = 0;
>> +
>> + /* Try setting 5 GT/s link speed */
>
> What if it fails?
If it fails, we're back at 2.5 GT/s . The rcar_pcie_force_speedup()
first checks if the PCIe IP can do 5 GT/s at all. Only if so, tries to
initiate transition to 5 GT/s operation , checks whether that succeeded
and if it failed, falls back to 2.5 GT/s .
>> + rcar_pcie_force_speedup(pcie);
>> +
>> + /* Setup PCI resources */
>> + resource_list_for_each_entry(win, &pcie->resources) {
>> + struct resource *res = win->res;
>> +
>> + if (!res->flags)
>> + continue;
>> +
>> + switch (resource_type(res)) {
>> + case IORESOURCE_IO:
>> + case IORESOURCE_MEM:
>> + rcar_pcie_setup_window(i, pcie, res);
>> + i++;
>> + break;
>> + default:
>> + continue;
>
> Can the default case be omitted?
Sure
>> + }
>> + }
>> +
>> + return 0;
>> +}
>> +
>> static int rcar_pcie_enable(struct rcar_pcie *pcie)
>> {
>> struct device *dev = pcie->dev;
>> @@ -872,11 +902,25 @@ static const struct irq_domain_ops msi_domain_ops = {
>> .map = rcar_msi_map,
>> };
>>
>> +static void rcar_pcie_hw_enable_msi(struct rcar_pcie *pcie)
>> +{
>> + struct rcar_msi *msi = &pcie->msi;
>> + unsigned long base;
>> +
>> + /* setup MSI data target */
>> + base = virt_to_phys((void *)msi->pages);
>
> Why do you need to cast to void *?
> I expect such casting can be done implicitly.
Because __get_free_pages() returns unsigned long and that's what's used
to assign msi->pages . And virt_to_phys() expects void * instead, thus
the cast.
>> +
>> + rcar_pci_write_reg(pcie, base | MSIFE, PCIEMSIALR);
>> + rcar_pci_write_reg(pcie, 0, PCIEMSIAUR);
>> +
>> + /* enable all MSI interrupts */
>> + rcar_pci_write_reg(pcie, 0xffffffff, PCIEMSIIER);
>> +}
>> +
>> static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
>> {
>> struct device *dev = pcie->dev;
>> struct rcar_msi *msi = &pcie->msi;
>> - unsigned long base;
>> int err, i;
>>
>> mutex_init(&msi->lock);
>> @@ -915,13 +959,7 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
>>
>> /* setup MSI data target */
>> msi->pages = __get_free_pages(GFP_KERNEL, 0);
>> - base = virt_to_phys((void *)msi->pages);
>> -
>> - rcar_pci_write_reg(pcie, base | MSIFE, PCIEMSIALR);
>> - rcar_pci_write_reg(pcie, 0, PCIEMSIAUR);
>> -
>> - /* enable all MSI interrupts */
>> - rcar_pci_write_reg(pcie, 0xffffffff, PCIEMSIIER);
>> + rcar_pcie_hw_enable_msi(pcie);
>>
>> return 0;
>>
>> @@ -1202,6 +1240,37 @@ static int rcar_pcie_probe(struct platform_device *pdev)
>> return err;
>> }
>>
>> +static int rcar_pcie_resume(struct device *dev)
>> +{
>> + struct rcar_pcie *pcie = dev_get_drvdata(dev);
>> + unsigned int data;
>> + int err;
>> + int (*hw_init_fn)(struct rcar_pcie *);
>
> Please sort local variables in reverse xmas tree order.
OK
>> +
>> + err = rcar_pcie_parse_map_dma_ranges(pcie, dev->of_node);
>> + if (err)
>> + return 0;
>> +
>> + /* Failure to get a link might just be that no cards are inserted */
>> + hw_init_fn = of_device_get_match_data(dev);
>> + err = hw_init_fn(pcie);
>> + if (err) {
>> + dev_info(dev, "PCIe link down\n");
>> + return 0;
>> + }
>> +
>> + data = rcar_pci_read_reg(pcie, MACSR);
>> + dev_info(dev, "PCIe x%d: link up\n", (data >> 20) & 0x3f);
>> +
>> + /* Enable MSI */
>> + if (IS_ENABLED(CONFIG_PCI_MSI))
>> + rcar_pcie_hw_enable_msi(pcie);
>> +
>> + rcar_pcie_hw_enable(pcie);
>> +
>> + return 0;
>> +}
>> +
>> static int rcar_pcie_resume_noirq(struct device *dev)
>> {
>> struct rcar_pcie *pcie = dev_get_drvdata(dev);
>> @@ -1218,6 +1287,7 @@ static int rcar_pcie_resume_noirq(struct device *dev)
>> }
>>
>> static const struct dev_pm_ops rcar_pcie_pm_ops = {
>> + SET_SYSTEM_SLEEP_PM_OPS(NULL, rcar_pcie_resume)
>> .resume_noirq = rcar_pcie_resume_noirq,
>> };
>>
>> --
>> 2.11.0
>>
--
Best regards,
Marek Vasut
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/3] PCI: rcar: Add the initialization of PCIe link in resume_noirq
2017-11-10 21:14 ` Marek Vasut
@ 2017-11-13 6:58 ` Simon Horman
0 siblings, 0 replies; 14+ messages in thread
From: Simon Horman @ 2017-11-13 6:58 UTC (permalink / raw)
To: Marek Vasut
Cc: linux-pci, Kazufumi Ikeda, Gaku Inami, Marek Vasut,
Geert Uytterhoeven, Wolfram Sang, linux-renesas-soc
On Fri, Nov 10, 2017 at 10:14:33PM +0100, Marek Vasut wrote:
> On 11/10/2017 09:59 AM, Simon Horman wrote:
> > Hi Marek,
>
> Hi Simon,
>
> > On Wed, Nov 08, 2017 at 10:28:04AM +0100, Marek Vasut wrote:
> >> From: Kazufumi Ikeda <kaz-ikeda@xc.jp.nec.com>
> >>
> >> Reestablish the PCIe link very early in the resume process in case it
> >> went down to prevent PCI accesses from hanging the bus. Such accesses
> >> can happen early in the PCI resume process, in the resume_noirq, thus
> >> the link must be reestablished in the resume_noirq callback of the
> >> driver.
> >>
> >> Signed-off-by: Kazufumi Ikeda <kaz-ikeda@xc.jp.nec.com>
> >> Signed-off-by: Gaku Inami <gaku.inami.xw@bp.renesas.com>
> >> Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
> >> Cc: Geert Uytterhoeven <geert+renesas@glider.be>
> >> Cc: Simon Horman <horms+renesas@verge.net.au>
> >> Cc: Wolfram Sang <wsa@the-dreams.de>
> >> Cc: linux-renesas-soc@vger.kernel.org
> >
> > For patch-sets (with more than one patch) please provide a cover-letter.
> > The --cover-letter option to git format-patch can help.
> >
> >> ---
> >> drivers/pci/host/pcie-rcar.c | 31 ++++++++++++++++++++++++++++---
> >> 1 file changed, 28 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
> >> index 889603783f01..aa588a7d4811 100644
> >> --- a/drivers/pci/host/pcie-rcar.c
> >> +++ b/drivers/pci/host/pcie-rcar.c
> >> @@ -43,6 +43,7 @@
> >>
> >> /* Transfer control */
> >> #define PCIETCTLR 0x02000
> >> +#define DL_DOWN (1 << 3)
> >
> > Can you use the BIT() macro here?
>
> Yes, I'll also add a patch to the series to convert all the others to
> the BIT() macro, to keep things consistent.
Great, thanks.
> >> #define CFINIT 1
> >> #define PCIETSTR 0x02004
> >> #define DATA_LINK_ACTIVE 1
> >> @@ -529,7 +530,7 @@ static void phy_write_reg(struct rcar_pcie *pcie,
> >> phy_wait_for_ack(pcie);
> >> }
> >>
> >> -static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie)
> >> +static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie, int atomic)
> >
> > As Sergei mentioned bool seems like a more appropriate type for atomic.
>
> I can actually get rid of this altogether.
Nice :)
> >> {
> >> unsigned int timeout = 10;
> >>
> >> @@ -537,7 +538,10 @@ static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie)
> >> if ((rcar_pci_read_reg(pcie, PCIETSTR) & DATA_LINK_ACTIVE))
> >> return 0;
> >>
> >> - msleep(5);
> >> + if (atomic)
> >> + mdelay(5);
> >> + else
> >> + msleep(5);
> >
> > If we must delay, then I suppose this is reasonable.
>
> See above
>
> >> }
> >>
> >> return -ETIMEDOUT;
> >> @@ -595,7 +599,7 @@ static int rcar_pcie_hw_init(struct rcar_pcie *pcie)
> >> rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
> >>
> >> /* This will timeout if we don't have a link. */
> >> - err = rcar_pcie_wait_for_dl(pcie);
> >> + err = rcar_pcie_wait_for_dl(pcie, 0);
> >> if (err)
> >> return err;
> >>
> >> @@ -1110,6 +1114,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)
> >> pcie = pci_host_bridge_priv(bridge);
> >>
> >> pcie->dev = dev;
> >> + platform_set_drvdata(pdev, pcie);
> >>
> >> INIT_LIST_HEAD(&pcie->resources);
> >>
> >> @@ -1173,10 +1178,30 @@ static int rcar_pcie_probe(struct platform_device *pdev)
> >> return err;
> >> }
> >>
> >> +static int rcar_pcie_resume_noirq(struct device *dev)
> >> +{
> >> + struct rcar_pcie *pcie = dev_get_drvdata(dev);
> >> + u32 val = rcar_pci_read_reg(pcie, PMSR);
> >> + int ret = 0;
> >> +
> >> + if ((val == 0) || (rcar_pci_read_reg(pcie, PCIETCTLR) & DL_DOWN)) {
> >
> > Please remove the unnecessary parentheses from the line above.
> >
> > Also, I would prefer if the function returned early.
> > Something like (completely untested!):
>
> This should work.
>
> > if (rcar_pci_read_reg(pcie, PMSR) &&
> > !(rcar_pci_read_reg(pcie, PCIETCTLR) & DL_DOWN))
> > return 0;
> >
> > rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
> > return rcar_pcie_wait_for_dl(pcie, 1);
> >
> >> + /* Re-establish the PCIe link */
> >> + rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
> >> + ret = rcar_pcie_wait_for_dl(pcie, 1);
> >> + }
> >> +
> >> + return ret;
> >> +}
> >> +
> >> +static const struct dev_pm_ops rcar_pcie_pm_ops = {
> >> + .resume_noirq = rcar_pcie_resume_noirq,
> >> +};
> >> +
> >> static struct platform_driver rcar_pcie_driver = {
> >> .driver = {
> >> .name = "rcar-pcie",
> >> .of_match_table = rcar_pcie_of_match,
> >> + .pm = &rcar_pcie_pm_ops,
> >> .suppress_bind_attrs = true,
> >> },
> >> .probe = rcar_pcie_probe,
> >> --
> >> 2.11.0
> >>
>
>
> --
> Best regards,
> Marek Vasut
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 3/3] PCI: rcar: Add the suspend/resume for pcie-rcar driver
2017-11-10 21:53 ` Marek Vasut
@ 2017-11-13 7:00 ` Simon Horman
2017-11-13 8:05 ` Geert Uytterhoeven
0 siblings, 1 reply; 14+ messages in thread
From: Simon Horman @ 2017-11-13 7:00 UTC (permalink / raw)
To: Marek Vasut
Cc: linux-pci, Kazufumi Ikeda, Gaku Inami, Marek Vasut,
Geert Uytterhoeven, Wolfram Sang, linux-renesas-soc
On Fri, Nov 10, 2017 at 10:53:07PM +0100, Marek Vasut wrote:
> On 11/10/2017 10:09 AM, Simon Horman wrote:
> > On Wed, Nov 08, 2017 at 10:28:06AM +0100, Marek Vasut wrote:
> >> From: Kazufumi Ikeda <kaz-ikeda@xc.jp.nec.com>
> >>
> >> This adds the suspend/resume supports for pcie-rcar. The resume handler
> >> reprogram the hardware based on the software state kept in specific
> >> device structures. Also it doesn't need to save any registers.
> >>
> >> Signed-off-by: Kazufumi Ikeda <kaz-ikeda@xc.jp.nec.com>
> >> Signed-off-by: Gaku Inami <gaku.inami.xw@bp.renesas.com>
> >> Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
> >> Cc: Geert Uytterhoeven <geert+renesas@glider.be>
> >> Cc: Simon Horman <horms+renesas@verge.net.au>
> >> Cc: Wolfram Sang <wsa@the-dreams.de>
> >> Cc: linux-renesas-soc@vger.kernel.org
> >> ---
> >> drivers/pci/host/pcie-rcar.c | 86 +++++++++++++++++++++++++++++++++++++++-----
> >> 1 file changed, 78 insertions(+), 8 deletions(-)
> >>
> >> diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
> >> index 2b28292de93a..7a9e30185c79 100644
> >> --- a/drivers/pci/host/pcie-rcar.c
> >> +++ b/drivers/pci/host/pcie-rcar.c
> >> @@ -471,6 +471,36 @@ static void rcar_pcie_force_speedup(struct rcar_pcie *pcie)
> >> (macsr & LINK_SPEED) == LINK_SPEED_5_0GTS ? "5" : "2.5");
> >> }
> >>
> >> +static int rcar_pcie_hw_enable(struct rcar_pcie *pcie)
> >
> > This function always returns 0 and the value is not checked by the caller.
> > Can we change the return type to void?
>
> Yes, done
>
> >> +{
> >> + struct resource_entry *win;
> >> + LIST_HEAD(res);
> >> + int i = 0;
> >> +
> >> + /* Try setting 5 GT/s link speed */
> >
> > What if it fails?
>
> If it fails, we're back at 2.5 GT/s . The rcar_pcie_force_speedup()
> first checks if the PCIe IP can do 5 GT/s at all. Only if so, tries to
> initiate transition to 5 GT/s operation , checks whether that succeeded
> and if it failed, falls back to 2.5 GT/s .
Thanks, got it.
> >> + rcar_pcie_force_speedup(pcie);
> >> +
> >> + /* Setup PCI resources */
> >> + resource_list_for_each_entry(win, &pcie->resources) {
> >> + struct resource *res = win->res;
> >> +
> >> + if (!res->flags)
> >> + continue;
> >> +
> >> + switch (resource_type(res)) {
> >> + case IORESOURCE_IO:
> >> + case IORESOURCE_MEM:
> >> + rcar_pcie_setup_window(i, pcie, res);
> >> + i++;
> >> + break;
> >> + default:
> >> + continue;
> >
> > Can the default case be omitted?
>
> Sure
>
> >> + }
> >> + }
> >> +
> >> + return 0;
> >> +}
> >> +
> >> static int rcar_pcie_enable(struct rcar_pcie *pcie)
> >> {
> >> struct device *dev = pcie->dev;
> >> @@ -872,11 +902,25 @@ static const struct irq_domain_ops msi_domain_ops = {
> >> .map = rcar_msi_map,
> >> };
> >>
> >> +static void rcar_pcie_hw_enable_msi(struct rcar_pcie *pcie)
> >> +{
> >> + struct rcar_msi *msi = &pcie->msi;
> >> + unsigned long base;
> >> +
> >> + /* setup MSI data target */
> >> + base = virt_to_phys((void *)msi->pages);
> >
> > Why do you need to cast to void *?
> > I expect such casting can be done implicitly.
>
> Because __get_free_pages() returns unsigned long and that's what's used
> to assign msi->pages . And virt_to_phys() expects void * instead, thus
> the cast.
Right, but I don't think one should ever need to explicitly cast
to or from void *. What mean is, can you just remove "(void *)" without
changing any behaviour?
>
> >> +
> >> + rcar_pci_write_reg(pcie, base | MSIFE, PCIEMSIALR);
> >> + rcar_pci_write_reg(pcie, 0, PCIEMSIAUR);
> >> +
> >> + /* enable all MSI interrupts */
> >> + rcar_pci_write_reg(pcie, 0xffffffff, PCIEMSIIER);
> >> +}
> >> +
> >> static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
> >> {
> >> struct device *dev = pcie->dev;
> >> struct rcar_msi *msi = &pcie->msi;
> >> - unsigned long base;
> >> int err, i;
> >>
> >> mutex_init(&msi->lock);
> >> @@ -915,13 +959,7 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
> >>
> >> /* setup MSI data target */
> >> msi->pages = __get_free_pages(GFP_KERNEL, 0);
> >> - base = virt_to_phys((void *)msi->pages);
> >> -
> >> - rcar_pci_write_reg(pcie, base | MSIFE, PCIEMSIALR);
> >> - rcar_pci_write_reg(pcie, 0, PCIEMSIAUR);
> >> -
> >> - /* enable all MSI interrupts */
> >> - rcar_pci_write_reg(pcie, 0xffffffff, PCIEMSIIER);
> >> + rcar_pcie_hw_enable_msi(pcie);
> >>
> >> return 0;
> >>
> >> @@ -1202,6 +1240,37 @@ static int rcar_pcie_probe(struct platform_device *pdev)
> >> return err;
> >> }
> >>
> >> +static int rcar_pcie_resume(struct device *dev)
> >> +{
> >> + struct rcar_pcie *pcie = dev_get_drvdata(dev);
> >> + unsigned int data;
> >> + int err;
> >> + int (*hw_init_fn)(struct rcar_pcie *);
> >
> > Please sort local variables in reverse xmas tree order.
>
> OK
>
> >> +
> >> + err = rcar_pcie_parse_map_dma_ranges(pcie, dev->of_node);
> >> + if (err)
> >> + return 0;
> >> +
> >> + /* Failure to get a link might just be that no cards are inserted */
> >> + hw_init_fn = of_device_get_match_data(dev);
> >> + err = hw_init_fn(pcie);
> >> + if (err) {
> >> + dev_info(dev, "PCIe link down\n");
> >> + return 0;
> >> + }
> >> +
> >> + data = rcar_pci_read_reg(pcie, MACSR);
> >> + dev_info(dev, "PCIe x%d: link up\n", (data >> 20) & 0x3f);
> >> +
> >> + /* Enable MSI */
> >> + if (IS_ENABLED(CONFIG_PCI_MSI))
> >> + rcar_pcie_hw_enable_msi(pcie);
> >> +
> >> + rcar_pcie_hw_enable(pcie);
> >> +
> >> + return 0;
> >> +}
> >> +
> >> static int rcar_pcie_resume_noirq(struct device *dev)
> >> {
> >> struct rcar_pcie *pcie = dev_get_drvdata(dev);
> >> @@ -1218,6 +1287,7 @@ static int rcar_pcie_resume_noirq(struct device *dev)
> >> }
> >>
> >> static const struct dev_pm_ops rcar_pcie_pm_ops = {
> >> + SET_SYSTEM_SLEEP_PM_OPS(NULL, rcar_pcie_resume)
> >> .resume_noirq = rcar_pcie_resume_noirq,
> >> };
> >>
> >> --
> >> 2.11.0
> >>
>
>
> --
> Best regards,
> Marek Vasut
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 3/3] PCI: rcar: Add the suspend/resume for pcie-rcar driver
2017-11-13 7:00 ` Simon Horman
@ 2017-11-13 8:05 ` Geert Uytterhoeven
0 siblings, 0 replies; 14+ messages in thread
From: Geert Uytterhoeven @ 2017-11-13 8:05 UTC (permalink / raw)
To: Simon Horman
Cc: Marek Vasut, linux-pci, Kazufumi Ikeda, Gaku Inami, Marek Vasut,
Geert Uytterhoeven, Wolfram Sang, Linux-Renesas
Hi Simon,
On Mon, Nov 13, 2017 at 8:00 AM, Simon Horman <horms@verge.net.au> wrote:
> On Fri, Nov 10, 2017 at 10:53:07PM +0100, Marek Vasut wrote:
>> On 11/10/2017 10:09 AM, Simon Horman wrote:
>> > On Wed, Nov 08, 2017 at 10:28:06AM +0100, Marek Vasut wrote:
>> >> @@ -872,11 +902,25 @@ static const struct irq_domain_ops msi_domain_ops = {
>> >> .map = rcar_msi_map,
>> >> };
>> >>
>> >> +static void rcar_pcie_hw_enable_msi(struct rcar_pcie *pcie)
>> >> +{
>> >> + struct rcar_msi *msi = &pcie->msi;
>> >> + unsigned long base;
>> >> +
>> >> + /* setup MSI data target */
>> >> + base = virt_to_phys((void *)msi->pages);
>> >
>> > Why do you need to cast to void *?
>> > I expect such casting can be done implicitly.
>>
>> Because __get_free_pages() returns unsigned long and that's what's used
>> to assign msi->pages . And virt_to_phys() expects void * instead, thus
>> the cast.
>
> Right, but I don't think one should ever need to explicitly cast
> to or from void *. What mean is, can you just remove "(void *)" without
In general, I agree ("casts are evil").
> changing any behaviour?
In this particular case, there's no way around the cast, as __get_free_pages()
returns unsigned long because of historical reasons (if written today, it
would return a pointer for sure).
Other exceptions are storing integral types in of_device_id.data (which is
void *), and storing private data pointers in Scsi_Host.hostdata (which is
unsigned long).
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2017-11-13 8:05 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-08 9:28 [PATCH 1/3] PCI: rcar: Add the initialization of PCIe link in resume_noirq Marek Vasut
2017-11-08 9:28 ` [PATCH 2/3] PCI: rcar: Support runtime PM, link state L1 handling Marek Vasut
2017-11-10 9:03 ` Simon Horman
2017-11-10 21:22 ` Marek Vasut
2017-11-08 9:28 ` [PATCH 3/3] PCI: rcar: Add the suspend/resume for pcie-rcar driver Marek Vasut
2017-11-10 9:09 ` Simon Horman
2017-11-10 21:53 ` Marek Vasut
2017-11-13 7:00 ` Simon Horman
2017-11-13 8:05 ` Geert Uytterhoeven
2017-11-08 11:00 ` [PATCH 1/3] PCI: rcar: Add the initialization of PCIe link in resume_noirq Sergei Shtylyov
2017-11-10 21:01 ` Marek Vasut
2017-11-10 8:59 ` Simon Horman
2017-11-10 21:14 ` Marek Vasut
2017-11-13 6:58 ` Simon Horman
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.