RE: [PATCH] PCI: designware: change dw_pcie_cfg_write() and dw_pcie_cfg_read()

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

 



Hi Bjorn, thanks for your comments

> -----Original Message-----
> From: Bjorn Helgaas [mailto:bhelgaas@xxxxxxxxxx]
> Sent: Wednesday, September 09, 2015 8:45 PM
> To: Gabriele Paoloni
> Cc: Jingoo Han; Pratyush Anand Thakur; linux-pci@xxxxxxxxxxxxxxx;
> Wangzhou (B); Yuanzhichang; Zhudacai; zhangjukuo; qiuzhenfa; Liguozhu
> (Kenneth)
> Subject: Re: [PATCH] PCI: designware: change dw_pcie_cfg_write() and
> dw_pcie_cfg_read()
> 
> Hi Gabriele,
> 
> On Wed, Sep 9, 2015 at 11:51 AM, Gabriele Paoloni
> <gabriele.paoloni@xxxxxxxxxx> wrote:
> > From: gabriele paoloni <gabriele.paoloni@xxxxxxxxxx>
> >
> > This patch changes the implementation of dw_pcie_cfg_read() and
> > dw_pcie_cfg_write() to:
> > - improve the function usage from the callers perspective;
> > - make sure that the callers specify proper address offsets
> >   according to the size of the field being read/written
> > - fix a bug in pcie-spear13xx.c where the callers where passing
> >   the wrong address as they missed to add the appropriate offset
> 
> Please split this into separate patches, so each patch does one thing,
> i.e., separate the "where" usage change from the "return
> PCIBIOS_BAD_REGISTER_NUMBER for bad offsets" change.

Ok I will send out a patchset with separate patches 

> 
> I think there was a separate patch for the pcie-spear13xx.c bug,
> wasn't there?  At least, I don't see that fix in *this* patch.
> 

>From your previous comments:
********
*2) Pratyush, this one's for you :)  spear13xx_pcie_establish_link()
*   calls dw_pcie_cfg_read() and dw_pcie_cfg_write() several times like
*   this:
*
*    dw_pcie_cfg_read(pp->dbi_base, exp_cap_off + PCI_EXP_DEVCTL, 4, ...)
*    dw_pcie_cfg_write(pp->dbi_base, exp_cap_off + PCI_EXP_DEVCTL, 4, ...)
********

I think that the implementation of dw_pcie_cfg_read() and 
dw_pcie_cfg_write() that I proposed in this patch is compatible with
the previous calls in pcie-spear13xx.c. So the calls in pcie-spear13xx.c
were buggy for the previous implementations of the functions; with
the reworked functions there is no need to modify the function calls
in pcie-spear13xx.c...do you agree?

> > This patch is a follow up from the discussion in:
> > http://www.spinics.net/lists/linux-pci/msg44351.html
> >
> > Signed-off-by: Gabriele Paoloni <gabriele.paoloni@xxxxxxxxxx>
> > ---
> >  drivers/pci/host/pci-exynos.c      |  5 ++--
> >  drivers/pci/host/pci-keystone-dw.c |  4 +--
> >  drivers/pci/host/pcie-designware.c | 51 ++++++++++++++++++++++------
> ----------
> >  3 files changed, 34 insertions(+), 26 deletions(-)
> >
> > diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-
> exynos.c
> > index f9f468d..8b0e04b 100644
> > --- a/drivers/pci/host/pci-exynos.c
> > +++ b/drivers/pci/host/pci-exynos.c
> > @@ -454,7 +454,7 @@ static int exynos_pcie_rd_own_conf(struct
> pcie_port *pp, int where, int size,
> >         int ret;
> >
> >         exynos_pcie_sideband_dbi_r_mode(pp, true);
> > -       ret = dw_pcie_cfg_read(pp->dbi_base + (where & ~0x3), where,
> size, val);
> > +       ret = dw_pcie_cfg_read(pp->dbi_base, where, size, val);
> >         exynos_pcie_sideband_dbi_r_mode(pp, false);
> >         return ret;
> >  }
> > @@ -465,8 +465,7 @@ static int exynos_pcie_wr_own_conf(struct
> pcie_port *pp, int where, int size,
> >         int ret;
> >
> >         exynos_pcie_sideband_dbi_w_mode(pp, true);
> > -       ret = dw_pcie_cfg_write(pp->dbi_base + (where & ~0x3),
> > -                       where, size, val);
> > +       ret = dw_pcie_cfg_write(pp->dbi_base, where, size, val);
> >         exynos_pcie_sideband_dbi_w_mode(pp, false);
> >         return ret;
> >  }
> > diff --git a/drivers/pci/host/pci-keystone-dw.c
> b/drivers/pci/host/pci-keystone-dw.c
> > index f34892e..2b391f4 100644
> > --- a/drivers/pci/host/pci-keystone-dw.c
> > +++ b/drivers/pci/host/pci-keystone-dw.c
> > @@ -403,7 +403,7 @@ int ks_dw_pcie_rd_other_conf(struct pcie_port *pp,
> struct pci_bus *bus,
> >
> >         addr = ks_pcie_cfg_setup(ks_pcie, bus_num, devfn);
> >
> > -       return dw_pcie_cfg_read(addr + (where & ~0x3), where, size,
> val);
> > +       return dw_pcie_cfg_read(addr, where, size, val);
> >  }
> >
> >  int ks_dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus
> *bus,
> > @@ -415,7 +415,7 @@ int ks_dw_pcie_wr_other_conf(struct pcie_port *pp,
> struct pci_bus *bus,
> >
> >         addr = ks_pcie_cfg_setup(ks_pcie, bus_num, devfn);
> >
> > -       return dw_pcie_cfg_write(addr + (where & ~0x3), where, size,
> val);
> > +       return dw_pcie_cfg_write(addr, where, size, val);
> >  }
> >
> >  /**
> > diff --git a/drivers/pci/host/pcie-designware.c
> b/drivers/pci/host/pcie-designware.c
> > index 69486be..b53aa38 100644
> > --- a/drivers/pci/host/pcie-designware.c
> > +++ b/drivers/pci/host/pcie-designware.c
> > @@ -82,13 +82,20 @@ static inline struct pcie_port
> *sys_to_pcie(struct pci_sys_data *sys)
> >
> >  int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32
> *val)
> >  {
> > +       addr += (where & ~0x3);
> >         *val = readl(addr);
> > -
> > -       if (size == 1)
> > -               *val = (*val >> (8 * (where & 3))) & 0xff;
> > -       else if (size == 2)
> > -               *val = (*val >> (8 * (where & 3))) & 0xffff;
> > -       else if (size != 4)
> > +       where &= 3;
> > +
> > +       if (size == 1) {
> > +               *val = (*val >> (8 * where)) & 0xff;
> > +       } else if (size == 2) {
> > +               if (where & 1)
> > +                       return PCIBIOS_BAD_REGISTER_NUMBER;
> > +               *val = (*val >> (8 * where)) & 0xffff;
> > +       } else if (size == 4) {
> > +               if (where & 3)
> > +                       return PCIBIOS_BAD_REGISTER_NUMBER;
> > +       } else
> >                 return PCIBIOS_BAD_REGISTER_NUMBER;
> >
> >         return PCIBIOS_SUCCESSFUL;
> > @@ -96,12 +103,18 @@ int dw_pcie_cfg_read(void __iomem *addr, int
> where, int size, u32 *val)
> >
> >  int dw_pcie_cfg_write(void __iomem *addr, int where, int size, u32
> val)
> >  {
> > -       if (size == 4)
> > +       addr += where;
> > +
> > +       if (size == 4) {
> > +               if ((uintptr_t)addr & 3)
> > +                       return PCIBIOS_BAD_REGISTER_NUMBER;
> >                 writel(val, addr);
> > -       else if (size == 2)
> > -               writew(val, addr + (where & 2));
> > -       else if (size == 1)
> > -               writeb(val, addr + (where & 3));
> > +       } else if (size == 2) {
> > +               if ((uintptr_t)addr & 1)
> > +                       return PCIBIOS_BAD_REGISTER_NUMBER;
> > +               writew(val, addr);
> > +       } else if (size == 1)
> > +               writeb(val, addr);
> >         else
> >                 return PCIBIOS_BAD_REGISTER_NUMBER;
> >
> > @@ -132,8 +145,7 @@ static int dw_pcie_rd_own_conf(struct pcie_port
> *pp, int where, int size,
> >         if (pp->ops->rd_own_conf)
> >                 ret = pp->ops->rd_own_conf(pp, where, size, val);
> >         else
> > -               ret = dw_pcie_cfg_read(pp->dbi_base + (where & ~0x3),
> where,
> > -                               size, val);
> > +               ret = dw_pcie_cfg_read(pp->dbi_base, where, size,
> val);
> >
> >         return ret;
> >  }
> > @@ -146,8 +158,7 @@ static int dw_pcie_wr_own_conf(struct pcie_port
> *pp, int where, int size,
> >         if (pp->ops->wr_own_conf)
> >                 ret = pp->ops->wr_own_conf(pp, where, size, val);
> >         else
> > -               ret = dw_pcie_cfg_write(pp->dbi_base + (where & ~0x3),
> where,
> > -                               size, val);
> > +               ret = dw_pcie_cfg_write(pp->dbi_base, where, size,
> val);
> >
> >         return ret;
> >  }
> > @@ -541,13 +552,12 @@ static int dw_pcie_rd_other_conf(struct
> pcie_port *pp, struct pci_bus *bus,
> >                 u32 devfn, int where, int size, u32 *val)
> >  {
> >         int ret, type;
> > -       u32 address, busdev, cfg_size;
> > +       u32 busdev, cfg_size;
> >         u64 cpu_addr;
> >         void __iomem *va_cfg_base;
> >
> >         busdev = PCIE_ATU_BUS(bus->number) |
> PCIE_ATU_DEV(PCI_SLOT(devfn)) |
> >                  PCIE_ATU_FUNC(PCI_FUNC(devfn));
> > -       address = where & ~0x3;
> >
> >         if (bus->parent->number == pp->root_bus_nr) {
> >                 type = PCIE_ATU_TYPE_CFG0;
> > @@ -564,7 +574,7 @@ static int dw_pcie_rd_other_conf(struct pcie_port
> *pp, struct pci_bus *bus,
> >         dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> >                                   type, cpu_addr,
> >                                   busdev, cfg_size);
> > -       ret = dw_pcie_cfg_read(va_cfg_base + address, where, size,
> val);
> > +       ret = dw_pcie_cfg_read(va_cfg_base, where, size, val);
> >         dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> >                                   PCIE_ATU_TYPE_IO, pp->io_mod_base,
> >                                   pp->io_bus_addr, pp->io_size);
> > @@ -576,13 +586,12 @@ static int dw_pcie_wr_other_conf(struct
> pcie_port *pp, struct pci_bus *bus,
> >                 u32 devfn, int where, int size, u32 val)
> >  {
> >         int ret, type;
> > -       u32 address, busdev, cfg_size;
> > +       u32 busdev, cfg_size;
> >         u64 cpu_addr;
> >         void __iomem *va_cfg_base;
> >
> >         busdev = PCIE_ATU_BUS(bus->number) |
> PCIE_ATU_DEV(PCI_SLOT(devfn)) |
> >                  PCIE_ATU_FUNC(PCI_FUNC(devfn));
> > -       address = where & ~0x3;
> >
> >         if (bus->parent->number == pp->root_bus_nr) {
> >                 type = PCIE_ATU_TYPE_CFG0;
> > @@ -599,7 +608,7 @@ static int dw_pcie_wr_other_conf(struct pcie_port
> *pp, struct pci_bus *bus,
> >         dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> >                                   type, cpu_addr,
> >                                   busdev, cfg_size);
> > -       ret = dw_pcie_cfg_write(va_cfg_base + address, where, size,
> val);
> > +       ret = dw_pcie_cfg_write(va_cfg_base, where, size, val);
> >         dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
> >                                   PCIE_ATU_TYPE_IO, pp->io_mod_base,
> >                                   pp->io_bus_addr, pp->io_size);
> > --
> > 1.9.1
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-pci"
> in
> > the body of a message to majordomo@xxxxxxxxxxxxxxx
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
��.n��������+%������w��{.n�����{���"�)��jg��������ݢj����G�������j:+v���w�m������w�������h�����٥




[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