linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Bjorn Helgaas <helgaas@kernel.org>
To: Daire.McNamara@microchip.com
Cc: robh@kernel.org, lorenzo.pieralisi@arm.com,
	linux-pci@vger.kernel.org, bhelgaas@google.com,
	robh+dt@kernel.org, devicetree@vger.kernel.org,
	david.abdurachmanov@gmail.com
Subject: Re: [PATCH v15 2/2] PCI: microchip: Add host driver for Microchip PCIe controller
Date: Thu, 20 Aug 2020 13:10:18 -0500	[thread overview]
Message-ID: <20200820181018.GA1551400@bjorn-Precision-5520> (raw)
In-Reply-To: <d007193ce73677713436c39684602f679d7623e4.camel@microchip.com>

On Wed, Aug 19, 2020 at 04:33:10PM +0000, Daire.McNamara@microchip.com wrote:

> + *	pcie-altera.c
> + */

Add a blank line here.

> +#include <linux/irqchip/chained_irq.h>
> +#include <linux/module.h>

> +static struct mc_port *port;

This file scope item is not ideal.  It might work in your situation if
you can never have more than one device, but it's not a pattern we
want other people to copy.

I think I sort of see how it works:

  mc_pci_host_probe
    pci_host_common_probe
      ops = of_device_get_match_data()              # mc_ecam_ops
      gen_pci_init(..., ops)
        pci_ecam_create(..., ops)
	  ops->init                                 # mc_ecam_ops.init
	    mc_platform_init(pci_config_window *)
	      port = devm_kzalloc(...)              # initialized
    mc_setup_windows
      bridge_base_addr = port->axi_base_addr + ...  # used

And you're using the file scope "port" because mc_platform_init()
doesn't have a pointer to the platform_device.  But I think this
abuses the pci_ecam_ops design to do host bridge initialization that
it is not intended for.

I'd suggest copying the host bridge init design from somewhere else.
tango_pcie_probe() also calls pci_host_common_probe(), so maybe that's
a good place.  But the fact that it's the *only* such caller makes me
think it might not be the best thing to copy.

Rob has been working in this area and probably has better insight.

> +static void mc_pcie_isr(struct irq_desc *desc)
> +{
> +	struct irq_chip *chip = irq_desc_get_chip(desc);
> +	struct mc_port *port = irq_desc_get_handler_data(desc);
> +	struct device *dev = port->dev;
> +	struct mc_msi *msi = &port->msi;
> +	void __iomem *bridge_base_addr = port->axi_base_addr + MC_PCIE1_BRIDGE_ADDR;
> +	unsigned long status;
> +	unsigned long intx_status;
> +	unsigned long msi_status;
> +	u32 bit;
> +	u32 virq;
> +
> +	/*
> +	 * The core provides a single interrupt for both INTx/MSI messages.
> +	 * So we'll read both INTx and MSI status.
> +	 */
> +	chained_irq_enter(chip, desc);
> +
> +	status = readl_relaxed(bridge_base_addr + MC_ISTATUS_LOCAL);

readl_relaxed() is defined to return a u32, so you might as well
declare "status" and related things as u32 instead of "unsigned long".

> +static void mc_pcie_enable_msi(struct mc_port *port, void __iomem *base)
> +{
> +	struct mc_msi *msi = &port->msi;
> +	u32 cap_offset = MC_MSI_CAP_CTRL_OFFSET;
> +

Remove this blank line.  We usually just separate the automatic
variables from the code with a blank line.

> +	u16 msg_ctrl = readw_relaxed(base + cap_offset + PCI_MSI_FLAGS);

> +static void mc_mask_intx_irq(struct irq_data *data)
> +{
> +	struct mc_port *port = irq_data_get_irq_chip_data(data);
> +	void __iomem *bridge_base_addr = port->axi_base_addr + MC_PCIE1_BRIDGE_ADDR;
> +	unsigned long flags;
> +	u32 mask, val;
> +
> +	mask = PCIE_LOCAL_INT_ENABLE;
> +	raw_spin_lock_irqsave(&port->intx_mask_lock, flags);
> +	val = readl_relaxed(bridge_base_addr + MC_IMASK_LOCAL);
> +	val &= ~mask;

Why bother with "mask" here?  It's only used once; just use
PCIE_LOCAL_INT_ENABLE directly.

> +	writel_relaxed(val, bridge_base_addr + MC_IMASK_LOCAL);
> +	raw_spin_unlock_irqrestore(&port->intx_mask_lock, flags);
> +}
> +
> +static void mc_unmask_intx_irq(struct irq_data *data)
> +{
> +	struct mc_port *port = irq_data_get_irq_chip_data(data);
> +	void __iomem *bridge_base_addr = port->axi_base_addr + MC_PCIE1_BRIDGE_ADDR;
> +	unsigned long flags;
> +	u32 mask, val;
> +
> +	mask = PCIE_LOCAL_INT_ENABLE;
> +	raw_spin_lock_irqsave(&port->intx_mask_lock, flags);
> +	val = readl_relaxed(bridge_base_addr + MC_IMASK_LOCAL);
> +	val |= mask;

Here also.

> +static int mc_platform_init(struct pci_config_window *cfg)
> +{
> +	struct device *dev = cfg->parent;
> +	struct platform_device *pdev = to_platform_device(dev);
> +	void __iomem *bridge_base_addr;
> +	void __iomem *ctrl_base_addr;
> +	int ret;
> +	u32 irq;
> +	u32 val;
> +
> +	port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
> +	if (!port)
> +		return -ENOMEM;
> +	port->dev = dev;
> +
> +	port->axi_base_addr = devm_platform_ioremap_resource(pdev, 1);
> +	if (IS_ERR(port->axi_base_addr))
> +		return PTR_ERR(port->axi_base_addr);
> +
> +	bridge_base_addr = port->axi_base_addr + MC_PCIE1_BRIDGE_ADDR;
> +	ctrl_base_addr = port->axi_base_addr + MC_PCIE1_CTRL_ADDR;
> +
> +	port->msi.vector_phy = MC_MSI_ADDR;
> +	port->msi.num_vectors = MC_NUM_MSI_IRQS;
> +	ret = mc_pcie_init_irq_domains(port);
> +	if (ret) {
> +		dev_err(dev, "failed creating IRQ domains\n");
> +		return ret;
> +	}
> +
> +	irq = platform_get_irq(pdev, 0);
> +	if (irq < 0) {

platform_get_irq() returns "int".  You declared "irq" as "u32" above,
so this check for failure won't work correctly.

> +		dev_err(dev, "unable to request IRQ%d\n", irq);
> +		return -ENODEV;
> +	}


  reply	other threads:[~2020-08-20 18:10 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-08-19 16:30 [PATCH v15 0/2] PCI: microchip: Add host driver for Microchip PCIe controller Daire.McNamara
2020-08-19 16:32 ` [PATCH v15 1/2] dt-bindings: PCI: microchip: Add Microchip PolarFire host binding Daire.McNamara
2020-08-25 22:05   ` Rob Herring
2020-08-19 16:33 ` [PATCH v15 2/2] PCI: microchip: Add host driver for Microchip PCIe controller Daire.McNamara
2020-08-20 18:10   ` Bjorn Helgaas [this message]
2020-08-21 17:57     ` Rob Herring
2020-08-21 19:03       ` Bjorn Helgaas

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=20200820181018.GA1551400@bjorn-Precision-5520 \
    --to=helgaas@kernel.org \
    --cc=Daire.McNamara@microchip.com \
    --cc=bhelgaas@google.com \
    --cc=david.abdurachmanov@gmail.com \
    --cc=devicetree@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=lorenzo.pieralisi@arm.com \
    --cc=robh+dt@kernel.org \
    --cc=robh@kernel.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;
as well as URLs for NNTP newsgroup(s).