All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bjorn Helgaas <bhelgaas@google.com>
To: Jiang Liu <liuj97@gmail.com>
Cc: Don Dutile <ddutile@redhat.com>, Jiang Liu <jiang.liu@huawei.com>,
	Yinghai Lu <yinghai@kernel.org>,
	Taku Izumi <izumi.taku@jp.fujitsu.com>,
	"Rafael J . Wysocki" <rjw@sisk.pl>,
	Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>,
	Yijing Wang <wangyijing@huawei.com>,
	Keping Chen <chenkeping@huawei.com>,
	linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org
Subject: Re: [RFC PATCH 05/14] PCI: add access functions for PCIe capabilities to hide PCIe spec differences
Date: Tue, 10 Jul 2012 12:35:45 -0600	[thread overview]
Message-ID: <CAErSpo7k3=nUSTR+n1iX0Rddv2FQm+HzcqnC5VHxh1JKUdoNAw@mail.gmail.com> (raw)
In-Reply-To: <1341935655-5381-6-git-send-email-jiang.liu@huawei.com>

On Tue, Jul 10, 2012 at 9:54 AM, Jiang Liu <liuj97@gmail.com> wrote:
> From: Jiang Liu <jiang.liu@huawei.com>
>
> Introduce four configuration access functions for PCIe capabilities to
> hide difference among PCIe Base Spec versions. With these functions,
> we can remove callers responsible for using pci_pcie_cap_has_*().
>
> pci_pcie_cap_read_word/dword() functions will store the pcie cap register
> value by passed parameter val,if related pcie cap register is not implemented
> on the pcie device, the passed parameter val will be set 0 and return -EINVAL.
>
> pci_pcie_capability_write_word/dowrd() functions will write the value to pcie
> cap registers,if related pcie cap register is not implemented on the pcie
> device, it will return -EINVAL.
>
> Signed-off-by: Jiang Liu <liuj97@gmail.com>
> Signed-off-by: Yijing Wang <wangyijing@huawei.com>
> ---
>  drivers/pci/access.c     |   88 ++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/pci.h      |   10 ++++++
>  include/linux/pci_regs.h |   19 ++++++++--
>  3 files changed, 115 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/pci/access.c b/drivers/pci/access.c
> index ba91a7e..80ae022 100644
> --- a/drivers/pci/access.c
> +++ b/drivers/pci/access.c
> @@ -469,3 +469,91 @@ void pci_cfg_access_unlock(struct pci_dev *dev)
>         raw_spin_unlock_irqrestore(&pci_lock, flags);
>  }
>  EXPORT_SYMBOL_GPL(pci_cfg_access_unlock);
> +
> +static int
> +pci_pcie_cap_get_offset(struct pci_dev *dev, int where, size_t sz)
> +{
> +       bool valid;
> +
> +       if (!pci_is_pcie(dev))
> +               return -EINVAL;
> +       if (where & (sz - 1))
> +               return -EINVAL;
> +
> +       if (where < 0)
> +               valid = false;
> +       else if (where < PCI_EXP_DEVCAP)
> +               valid = true;
> +       else if (where < PCI_EXP_LNKCAP)
> +               valid = pci_pcie_cap_has_devctl(dev);
> +       else if (where < PCI_EXP_SLTCAP)
> +               valid = pci_pcie_cap_has_lnkctl(dev);
> +       else if (where < PCI_EXP_RTCTL)
> +               valid = pci_pcie_cap_has_sltctl(dev);
> +       else if (where < PCI_EXP_DEVCAP2)
> +               valid = pci_pcie_cap_has_rtctl(dev);
> +       else if (where < PCI_EXP_CAP2_SIZE)
> +               valid = pci_pcie_cap_has_cap2(dev);
> +       else
> +               valid = false;
> +
> +       return valid ? where + pci_pcie_cap(dev) : -EINVAL;
> +}
> +
> +int pci_pcie_cap_read_word(struct pci_dev *dev, int where, u16 *valp)
> +{
> +       *valp = 0;
> +       where = pci_pcie_cap_get_offset(dev, where, sizeof(u16));

This is a really slick factorization; I like it much better than my
proposal.  I would like it even *better* if it read something like
this:

    bool implemented;

    *valp = 0;
    if (!pci_is_pcie(dev) || where & 1)
        return -EINVAL;

    implemented = pci_pcie_cap_implemented(dev, where);
    if (implemented)
        return pci_read_config_word(dev, pci_pcie_cap(dev) + where, valp);

    if (pci_is_pcie(dev) && where == PCI_EXP_SLTSTA ...

because I think it's useful to have the "pos + where" visual pattern
in the pci_read_config_word() arguments.

> +       if (where >= 0)
> +               return pci_read_config_word(dev, where, valp);
> +
> +       if (pci_is_pcie(dev) && where == PCI_EXP_SLTSTA &&
> +           pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM)
> +               *valp = PCI_EXP_SLTSTA_PDS;

I think we should be returning success in this case (SLTSTA for
downstream port).  In fact, I think we should return success even when
we're emulating the read of an unimplemented register from a v1
capability.  The caller should not be aware at all that there is a
difference between v1 and v2 capabilities.

I'd put the spec reference here rather than in read_dword(), since
SLTSTA is a u16 and this is the natural way to read it.  Then maybe a
short comment in read_dword() below.

> +       return -EINVAL;
> +}
> +EXPORT_SYMBOL(pci_pcie_cap_read_word);
> +
> +int pci_pcie_cap_read_dword(struct pci_dev *dev, int where, u32 *valp)
> +{
> +       *valp = 0;
> +       where = pci_pcie_cap_get_offset(dev, where, sizeof(u32));
> +       if (where >= 0)
> +               return pci_read_config_dword(dev, where, valp);
> +
> +       /*
> +        * Quotation from PCIe Base Spec 3.0:
> +        * For Functions that do not implement the Slot Capabilities,
> +        * Slot Status, and Slot Control registers, these spaces must
> +        * be hardwired to 0b, with the exception of the Presence Detect
> +        * State bit in the Slot Status register of Downstream Ports,
> +        * which must be hardwired to 1b.
> +        */
> +       if (pci_is_pcie(dev) && where == PCI_EXP_SLTCTL &&
> +           pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM)
> +               *valp = PCI_EXP_SLTSTA_PDS << 16;

Return success here, too.

> +
> +       return -EINVAL;
> +}
> +EXPORT_SYMBOL(pci_pcie_cap_read_dword);
> +
> +int pci_pcie_cap_write_word(struct pci_dev *dev, int where, u16 val)
> +{
> +       where = pci_pcie_cap_get_offset(dev, where, sizeof(u16));
> +       if (where >= 0)
> +               return pci_write_config_word(dev, where, val);
> +
> +       return -EINVAL;
> +}
> +EXPORT_SYMBOL(pci_pcie_cap_write_word);
> +
> +int pci_pcie_cap_write_dword(struct pci_dev *dev, int where, u32 val)
> +{
> +       where = pci_pcie_cap_get_offset(dev, where, sizeof(u32));
> +       if (where >= 0)
> +               return pci_write_config_dword(dev, where, val);
> +
> +       return -EINVAL;
> +}
> +EXPORT_SYMBOL(pci_pcie_cap_write_dword);
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 346b2d9..78767b2 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -1703,6 +1703,11 @@ static inline bool pci_pcie_cap_has_rtctl(const struct pci_dev *pdev)
>                type == PCI_EXP_TYPE_RC_EC;
>  }
>
> +extern int pci_pcie_cap_read_word(struct pci_dev *dev, int where, u16 *valp);
> +extern int pci_pcie_cap_read_dword(struct pci_dev *dev, int where, u32 *valp);
> +extern int pci_pcie_cap_write_word(struct pci_dev *dev, int where, u16 val);
> +extern int pci_pcie_cap_write_dword(struct pci_dev *dev, int where, u32 val);

You don't need the "extern" here (and I think you'll probably remove
these altogether, see below).

> +
>  void pci_request_acs(void);
>  bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags);
>  bool pci_acs_path_enabled(struct pci_dev *start,
> @@ -1843,5 +1848,10 @@ static inline struct eeh_dev *pci_dev_to_eeh_dev(struct pci_dev *pdev)
>   */
>  struct pci_dev *pci_find_upstream_pcie_bridge(struct pci_dev *pdev);
>
> +int pci_pcie_capability_read_word(struct pci_dev *dev, int where, u16 *val);
> +int pci_pcie_capability_read_dword(struct pci_dev *dev, int where, u32 *val);
> +int pci_pcie_capability_write_word(struct pci_dev *dev, int where, u16 val);
> +int pci_pcie_capability_write_dword(struct pci_dev *dev, int where, u32 val);

There's some confusion here: pci_pcie_cap_* versus
pci_pcie_capability_*.  I think you only need one set, and I prefer
pci_pcie_capability_* to follow the example of
pci_bus_find_capability().

> +
>  #endif /* __KERNEL__ */
>  #endif /* LINUX_PCI_H */
> diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h
> index 53274bf..ac60e22 100644
> --- a/include/linux/pci_regs.h
> +++ b/include/linux/pci_regs.h
> @@ -542,9 +542,24 @@
>  #define  PCI_EXP_OBFF_MSGA_EN  0x2000  /* OBFF enable with Message type A */
>  #define  PCI_EXP_OBFF_MSGB_EN  0x4000  /* OBFF enable with Message type B */
>  #define  PCI_EXP_OBFF_WAKE_EN  0x6000  /* OBFF using WAKE# signaling */
> -#define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2 44      /* v2 endpoints end here */
> +#define PCI_EXP_DEVSTA2                42      /* Device Status 2 */
> +#define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2 44 /* v2 endpoints end here */
> +#define PCI_EXP_LNKCAP2                44      /* Link Capabilities 2 */
>  #define PCI_EXP_LNKCTL2                48      /* Link Control 2 */
> -#define PCI_EXP_SLTCTL2                56      /* Slot Control 2 */
> +#define  PCI_EXP_LNKCTL2_TLS   0x0f    /* Target Link Speed */
> +#define  PCI_EXP_LNKCTL2_EC    0x10    /* Enter Compliance */
> +#define  PCI_EXP_LNKCTL2_HASD  0x20    /* Hardware Autonomous Speed Disable */
> +#define  PCI_EXP_LNKCTL2_SD    0x40    /* Selectable De-emphasis */
> +#define  PCI_EXP_LNKCTL2_TM    0x380   /* Transmit Margin */
> +#define  PCI_EXP_LNKCTL2_EMC   0x400   /* Enter Modified Compliance */
> +#define  PCI_EXP_LNKCTL2_CS    0x800   /* Compliance SOS */
> +#define  PCI_EXP_LNKCTL2_CD    0x1000  /* Compliance De-emphasis */
> +#define PCI_EXP_LNKSTA2                50      /* Link Status 2 */
> +#define  PCI_EXP_LNKSTA2_CDL   0x01    /* Current De-emphasis Level */
> +#define PCI_EXP_SLTCAP2                52      /* Slot Capabilities 2 */
> +#define PCI_EXP_SLTCTL2                56      /* Slot Control 2*/
> +#define PCI_EXP_SLTSTA2                58      /* Slot Status 2*/
> +#define        PCI_EXP_CAP2_SIZE       60

Most of these changes look unrelated to the current patch.  They
should be moved to a patch that uses the symbols you're adding.

>
>  /* Extended Capabilities (PCI-X 2.0 and Express) */
>  #define PCI_EXT_CAP_ID(header)         (header & 0x0000ffff)
> --
> 1.7.9.5
>

  reply	other threads:[~2012-07-10 18:36 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-06-04  7:44 [Resend with Ack][PATCH v1] PCI: allow acpiphp to handle PCIe ports without native PCIe hotplug capability Jiang Liu
2012-06-04  8:23 ` Kenji Kaneshige
2012-07-03  4:16 ` Bjorn Helgaas
2012-07-03 15:59   ` Bjorn Helgaas
2012-07-03 19:50     ` Don Dutile
2012-07-04 18:07       ` Bjorn Helgaas
2012-07-09 10:05         ` Jiang Liu
2012-07-09 17:05           ` Bjorn Helgaas
2012-07-04  2:52     ` Jiang Liu
2012-07-10 15:54     ` [RFC PATCH 00/14] improve PCIe capabilities registers handling Jiang Liu
2012-07-10 18:44       ` Bjorn Helgaas
2012-07-10 15:54     ` [RFC PATCH 01/14] PCI: add pcie_flags into struct pci_dev to cache PCIe capabilities register Jiang Liu
2012-07-11  9:01       ` Taku Izumi
2012-07-11 14:27         ` Jiang Liu
2012-07-10 15:54     ` [RFC PATCH 02/14] PCI: introduce pci_pcie_type(dev) to replace pci_dev->pcie_type Jiang Liu
2012-07-10 15:54     ` [RFC PATCH 03/14] PCI: remove unused field pcie_type from struct pci_dev Jiang Liu
2012-07-10 15:54     ` [RFC PATCH 04/14] PCI: refine and move pcie_cap_has_*() macros to include/linux/pci.h Jiang Liu
2012-07-10 18:49       ` Bjorn Helgaas
2012-07-10 15:54     ` [RFC PATCH 05/14] PCI: add access functions for PCIe capabilities to hide PCIe spec differences Jiang Liu
2012-07-10 18:35       ` Bjorn Helgaas [this message]
2012-07-11  3:07         ` Jiang Liu
2012-07-11  3:40           ` Bjorn Helgaas
2012-07-11  6:40             ` Jiang Liu
2012-07-11 17:52               ` Bjorn Helgaas
2012-07-12  2:56                 ` Jiang Liu
2012-07-12 20:49                   ` Bjorn Helgaas
2012-07-15 16:47                     ` Jiang Liu
2012-07-16 17:29                       ` Bjorn Helgaas
2012-07-16 18:57                         ` Don Dutile
2012-07-17  0:09                         ` Jiang Liu
2012-07-17  0:14                           ` Bjorn Helgaas
2012-07-10 15:54     ` [RFC PATCH 06/14] PCI: use PCIe cap access functions to simplify PCI core implementation Jiang Liu
2012-07-10 18:35       ` Bjorn Helgaas
2012-07-11  2:49         ` Jiang Liu
2012-07-10 15:54     ` [RFC PATCH 07/14] hotplug/PCI: use PCIe cap access functions to simplify implementation Jiang Liu
2012-07-10 18:35       ` Bjorn Helgaas
2012-07-10 15:54     ` [RFC PATCH 08/14] portdrv/PCI: " Jiang Liu
2012-07-10 15:54     ` [RFC PATCH 09/14] pciehp/PCI: " Jiang Liu
2012-07-10 15:54     ` [RFC PATCH 10/14] PME/PCI: " Jiang Liu
2012-07-10 15:54     ` [RFC PATCH 11/14] AER/PCI: " Jiang Liu
2012-07-10 15:54     ` [RFC PATCH 12/14] ASPM/PCI: " Jiang Liu
2012-07-10 15:54     ` [RFC PATCH 13/14] r8169/PCI: " Jiang Liu
2012-07-10 15:54     ` [RFC PATCH 14/14] qib/PCI: " Jiang Liu
2012-08-15 19:12 ` [Resend with Ack][PATCH v1] PCI: allow acpiphp to handle PCIe ports without native PCIe hotplug capability Bjorn Helgaas
2012-08-16 15:15   ` Jiang Liu
2012-08-22 15:16   ` [PATCH v2] PCI: allow acpiphp to handle PCIe ports w/o " Jiang Liu
2012-09-24 22:10     ` Bjorn Helgaas
2012-09-25 15:16       ` Jiang Liu

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='CAErSpo7k3=nUSTR+n1iX0Rddv2FQm+HzcqnC5VHxh1JKUdoNAw@mail.gmail.com' \
    --to=bhelgaas@google.com \
    --cc=chenkeping@huawei.com \
    --cc=ddutile@redhat.com \
    --cc=izumi.taku@jp.fujitsu.com \
    --cc=jiang.liu@huawei.com \
    --cc=kaneshige.kenji@jp.fujitsu.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=liuj97@gmail.com \
    --cc=rjw@sisk.pl \
    --cc=wangyijing@huawei.com \
    --cc=yinghai@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 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.