Commit 12566cc3 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'pci-v4.6-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci

Pull PCI fixes from Bjorn Helgaas:
 "These are fixes for two issues:

   - The VPD parsing code we added for v4.6 keeps some devices from
     crashing, but also keeps cxgb4 from reading non-standard extra VPD
     data that is relies on.  Hariprasad added a way for the driver to
     specify how much VPD is valid.

   - The i.MX6 active-low reset GPIO support we added in v4.5 caused
     regressions on some boards, so we're reverting that.

  VPD:
    Add pci_set_vpd_size() (Hariprasad Shenai)
    cxgb4: Set VPD size so we can read both VPD structures (Hariprasad Shenai)

  Freescale i.MX6 host bridge driver:
    Revert "PCI: imx6: Add support for active-low reset GPIO" (Fabio Estevam)"

* tag 'pci-v4.6-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci:
  cxgb4: Set VPD size so we can read both VPD structures
  PCI: Add pci_set_vpd_size() to set VPD size
  Revert "PCI: imx6: Add support for active-low reset GPIO"
parents 95d0c427 67e65879
...@@ -2557,6 +2557,7 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size) ...@@ -2557,6 +2557,7 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size)
} }
#define EEPROM_STAT_ADDR 0x7bfc #define EEPROM_STAT_ADDR 0x7bfc
#define VPD_SIZE 0x800
#define VPD_BASE 0x400 #define VPD_BASE 0x400
#define VPD_BASE_OLD 0 #define VPD_BASE_OLD 0
#define VPD_LEN 1024 #define VPD_LEN 1024
...@@ -2594,6 +2595,15 @@ int t4_get_raw_vpd_params(struct adapter *adapter, struct vpd_params *p) ...@@ -2594,6 +2595,15 @@ int t4_get_raw_vpd_params(struct adapter *adapter, struct vpd_params *p)
if (!vpd) if (!vpd)
return -ENOMEM; return -ENOMEM;
/* We have two VPD data structures stored in the adapter VPD area.
* By default, Linux calculates the size of the VPD area by traversing
* the first VPD area at offset 0x0, so we need to tell the OS what
* our real VPD size is.
*/
ret = pci_set_vpd_size(adapter->pdev, VPD_SIZE);
if (ret < 0)
goto out;
/* Card information normally starts at VPD_BASE but early cards had /* Card information normally starts at VPD_BASE but early cards had
* it at 0. * it at 0.
*/ */
......
...@@ -275,6 +275,19 @@ ssize_t pci_write_vpd(struct pci_dev *dev, loff_t pos, size_t count, const void ...@@ -275,6 +275,19 @@ ssize_t pci_write_vpd(struct pci_dev *dev, loff_t pos, size_t count, const void
} }
EXPORT_SYMBOL(pci_write_vpd); EXPORT_SYMBOL(pci_write_vpd);
/**
* pci_set_vpd_size - Set size of Vital Product Data space
* @dev: pci device struct
* @len: size of vpd space
*/
int pci_set_vpd_size(struct pci_dev *dev, size_t len)
{
if (!dev->vpd || !dev->vpd->ops)
return -ENODEV;
return dev->vpd->ops->set_size(dev, len);
}
EXPORT_SYMBOL(pci_set_vpd_size);
#define PCI_VPD_MAX_SIZE (PCI_VPD_ADDR_MASK + 1) #define PCI_VPD_MAX_SIZE (PCI_VPD_ADDR_MASK + 1)
/** /**
...@@ -498,9 +511,23 @@ static ssize_t pci_vpd_write(struct pci_dev *dev, loff_t pos, size_t count, ...@@ -498,9 +511,23 @@ static ssize_t pci_vpd_write(struct pci_dev *dev, loff_t pos, size_t count,
return ret ? ret : count; return ret ? ret : count;
} }
static int pci_vpd_set_size(struct pci_dev *dev, size_t len)
{
struct pci_vpd *vpd = dev->vpd;
if (len == 0 || len > PCI_VPD_MAX_SIZE)
return -EIO;
vpd->valid = 1;
vpd->len = len;
return 0;
}
static const struct pci_vpd_ops pci_vpd_ops = { static const struct pci_vpd_ops pci_vpd_ops = {
.read = pci_vpd_read, .read = pci_vpd_read,
.write = pci_vpd_write, .write = pci_vpd_write,
.set_size = pci_vpd_set_size,
}; };
static ssize_t pci_vpd_f0_read(struct pci_dev *dev, loff_t pos, size_t count, static ssize_t pci_vpd_f0_read(struct pci_dev *dev, loff_t pos, size_t count,
...@@ -533,9 +560,24 @@ static ssize_t pci_vpd_f0_write(struct pci_dev *dev, loff_t pos, size_t count, ...@@ -533,9 +560,24 @@ static ssize_t pci_vpd_f0_write(struct pci_dev *dev, loff_t pos, size_t count,
return ret; return ret;
} }
static int pci_vpd_f0_set_size(struct pci_dev *dev, size_t len)
{
struct pci_dev *tdev = pci_get_slot(dev->bus,
PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
int ret;
if (!tdev)
return -ENODEV;
ret = pci_set_vpd_size(tdev, len);
pci_dev_put(tdev);
return ret;
}
static const struct pci_vpd_ops pci_vpd_f0_ops = { static const struct pci_vpd_ops pci_vpd_f0_ops = {
.read = pci_vpd_f0_read, .read = pci_vpd_f0_read,
.write = pci_vpd_f0_write, .write = pci_vpd_f0_write,
.set_size = pci_vpd_f0_set_size,
}; };
int pci_vpd_init(struct pci_dev *dev) int pci_vpd_init(struct pci_dev *dev)
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
#define to_imx6_pcie(x) container_of(x, struct imx6_pcie, pp) #define to_imx6_pcie(x) container_of(x, struct imx6_pcie, pp)
struct imx6_pcie { struct imx6_pcie {
struct gpio_desc *reset_gpio; int reset_gpio;
struct clk *pcie_bus; struct clk *pcie_bus;
struct clk *pcie_phy; struct clk *pcie_phy;
struct clk *pcie; struct clk *pcie;
...@@ -309,10 +309,10 @@ static int imx6_pcie_deassert_core_reset(struct pcie_port *pp) ...@@ -309,10 +309,10 @@ static int imx6_pcie_deassert_core_reset(struct pcie_port *pp)
usleep_range(200, 500); usleep_range(200, 500);
/* Some boards don't have PCIe reset GPIO. */ /* Some boards don't have PCIe reset GPIO. */
if (imx6_pcie->reset_gpio) { if (gpio_is_valid(imx6_pcie->reset_gpio)) {
gpiod_set_value_cansleep(imx6_pcie->reset_gpio, 0); gpio_set_value_cansleep(imx6_pcie->reset_gpio, 0);
msleep(100); msleep(100);
gpiod_set_value_cansleep(imx6_pcie->reset_gpio, 1); gpio_set_value_cansleep(imx6_pcie->reset_gpio, 1);
} }
return 0; return 0;
...@@ -523,6 +523,7 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) ...@@ -523,6 +523,7 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
{ {
struct imx6_pcie *imx6_pcie; struct imx6_pcie *imx6_pcie;
struct pcie_port *pp; struct pcie_port *pp;
struct device_node *np = pdev->dev.of_node;
struct resource *dbi_base; struct resource *dbi_base;
struct device_node *node = pdev->dev.of_node; struct device_node *node = pdev->dev.of_node;
int ret; int ret;
...@@ -544,8 +545,15 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) ...@@ -544,8 +545,15 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
return PTR_ERR(pp->dbi_base); return PTR_ERR(pp->dbi_base);
/* Fetch GPIOs */ /* Fetch GPIOs */
imx6_pcie->reset_gpio = devm_gpiod_get_optional(&pdev->dev, "reset", imx6_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
GPIOD_OUT_LOW); if (gpio_is_valid(imx6_pcie->reset_gpio)) {
ret = devm_gpio_request_one(&pdev->dev, imx6_pcie->reset_gpio,
GPIOF_OUT_INIT_LOW, "PCIe reset");
if (ret) {
dev_err(&pdev->dev, "unable to get reset gpio\n");
return ret;
}
}
/* Fetch clocks */ /* Fetch clocks */
imx6_pcie->pcie_phy = devm_clk_get(&pdev->dev, "pcie_phy"); imx6_pcie->pcie_phy = devm_clk_get(&pdev->dev, "pcie_phy");
......
...@@ -97,6 +97,7 @@ static inline bool pci_has_subordinate(struct pci_dev *pci_dev) ...@@ -97,6 +97,7 @@ static inline bool pci_has_subordinate(struct pci_dev *pci_dev)
struct pci_vpd_ops { struct pci_vpd_ops {
ssize_t (*read)(struct pci_dev *dev, loff_t pos, size_t count, void *buf); ssize_t (*read)(struct pci_dev *dev, loff_t pos, size_t count, void *buf);
ssize_t (*write)(struct pci_dev *dev, loff_t pos, size_t count, const void *buf); ssize_t (*write)(struct pci_dev *dev, loff_t pos, size_t count, const void *buf);
int (*set_size)(struct pci_dev *dev, size_t len);
}; };
struct pci_vpd { struct pci_vpd {
......
...@@ -1111,6 +1111,7 @@ void pci_unlock_rescan_remove(void); ...@@ -1111,6 +1111,7 @@ void pci_unlock_rescan_remove(void);
/* Vital product data routines */ /* Vital product data routines */
ssize_t pci_read_vpd(struct pci_dev *dev, loff_t pos, size_t count, void *buf); ssize_t pci_read_vpd(struct pci_dev *dev, loff_t pos, size_t count, void *buf);
ssize_t pci_write_vpd(struct pci_dev *dev, loff_t pos, size_t count, const void *buf); ssize_t pci_write_vpd(struct pci_dev *dev, loff_t pos, size_t count, const void *buf);
int pci_set_vpd_size(struct pci_dev *dev, size_t len);
/* Helper functions for low-level code (drivers/pci/setup-[bus,res].c) */ /* Helper functions for low-level code (drivers/pci/setup-[bus,res].c) */
resource_size_t pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx); resource_size_t pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment