SUN3/3X Lance trivial fix improved
[firefly-linux-kernel-4.4.55.git] / drivers / pci / pci.c
index 8b44cff2c1767f3bef0287eb394b68c9988b9d60..d3eab057b2d36fb9d3a8db55194ff3a0972ba212 100644 (file)
 
 unsigned int pci_pm_d3_delay = 10;
 
+#define DEFAULT_CARDBUS_IO_SIZE                (256)
+#define DEFAULT_CARDBUS_MEM_SIZE       (64*1024*1024)
+/* pci=cbmemsize=nnM,cbiosize=nn can override this */
+unsigned long pci_cardbus_io_size = DEFAULT_CARDBUS_IO_SIZE;
+unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE;
+
 /**
  * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
  * @bus: pointer to PCI bus structure to search
@@ -545,7 +551,9 @@ static int pci_save_pcie_state(struct pci_dev *dev)
        if (pos <= 0)
                return 0;
 
-       save_state = kzalloc(sizeof(*save_state) + sizeof(u16) * 4, GFP_KERNEL);
+       save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
+       if (!save_state)
+               save_state = kzalloc(sizeof(*save_state) + sizeof(u16) * 4, GFP_KERNEL);
        if (!save_state) {
                dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n");
                return -ENOMEM;
@@ -576,8 +584,6 @@ static void pci_restore_pcie_state(struct pci_dev *dev)
        pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, cap[i++]);
        pci_write_config_word(dev, pos + PCI_EXP_SLTCTL, cap[i++]);
        pci_write_config_word(dev, pos + PCI_EXP_RTCTL, cap[i++]);
-       pci_remove_saved_cap(save_state);
-       kfree(save_state);
 }
 
 
@@ -591,7 +597,9 @@ static int pci_save_pcix_state(struct pci_dev *dev)
        if (pos <= 0)
                return 0;
 
-       save_state = kzalloc(sizeof(*save_state) + sizeof(u16), GFP_KERNEL);
+       save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
+       if (!save_state)
+               save_state = kzalloc(sizeof(*save_state) + sizeof(u16), GFP_KERNEL);
        if (!save_state) {
                dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n");
                return -ENOMEM;
@@ -616,8 +624,6 @@ static void pci_restore_pcix_state(struct pci_dev *dev)
        cap = (u16 *)&save_state->data[0];
 
        pci_write_config_word(dev, pos + PCI_X_CMD, cap[i++]);
-       pci_remove_saved_cap(save_state);
-       kfree(save_state);
 }
 
 
@@ -632,8 +638,6 @@ pci_save_state(struct pci_dev *dev)
        /* XXX: 100% dword access ok here? */
        for (i = 0; i < 16; i++)
                pci_read_config_dword(dev, i * 4,&dev->saved_config_space[i]);
-       if ((i = pci_save_msi_state(dev)) != 0)
-               return i;
        if ((i = pci_save_pcie_state(dev)) != 0)
                return i;
        if ((i = pci_save_pcix_state(dev)) != 0)
@@ -751,7 +755,8 @@ int pci_enable_device(struct pci_dev *dev)
  * when a device is enabled using managed PCI device enable interface.
  */
 struct pci_devres {
-       unsigned int disable:1;
+       unsigned int enabled:1;
+       unsigned int pinned:1;
        unsigned int orig_intx:1;
        unsigned int restore_intx:1;
        u32 region_mask;
@@ -775,7 +780,7 @@ static void pcim_release(struct device *gendev, void *res)
        if (this->restore_intx)
                pci_intx(dev, this->orig_intx);
 
-       if (this->disable)
+       if (this->enabled && !this->pinned)
                pci_disable_device(dev);
 }
 
@@ -814,12 +819,12 @@ int pcim_enable_device(struct pci_dev *pdev)
        dr = get_pci_dr(pdev);
        if (unlikely(!dr))
                return -ENOMEM;
-       WARN_ON(!!dr->disable);
+       WARN_ON(!!dr->enabled);
 
        rc = pci_enable_device(pdev);
        if (!rc) {
                pdev->is_managed = 1;
-               dr->disable = 1;
+               dr->enabled = 1;
        }
        return rc;
 }
@@ -837,9 +842,9 @@ void pcim_pin_device(struct pci_dev *pdev)
        struct pci_devres *dr;
 
        dr = find_pci_dr(pdev);
-       WARN_ON(!dr || !dr->disable);
+       WARN_ON(!dr || !dr->enabled);
        if (dr)
-               dr->disable = 0;
+               dr->pinned = 1;
 }
 
 /**
@@ -870,18 +875,11 @@ pci_disable_device(struct pci_dev *dev)
 
        dr = find_pci_dr(dev);
        if (dr)
-               dr->disable = 0;
+               dr->enabled = 0;
 
        if (atomic_sub_return(1, &dev->enable_cnt) != 0)
                return;
 
-       if (dev->msi_enabled)
-               disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI),
-                       PCI_CAP_ID_MSI);
-       if (dev->msix_enabled)
-               disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI),
-                       PCI_CAP_ID_MSIX);
-
        pci_read_config_word(dev, PCI_COMMAND, &pci_command);
        if (pci_command & PCI_COMMAND_MASTER) {
                pci_command &= ~PCI_COMMAND_MASTER;
@@ -1271,6 +1269,33 @@ pci_intx(struct pci_dev *pdev, int enable)
        }
 }
 
+/**
+ * pci_msi_off - disables any msi or msix capabilities
+ * @pdev: the PCI device to operate on
+ *
+ * If you want to use msi see pci_enable_msi and friends.
+ * This is a lower level primitive that allows us to disable
+ * msi operation at the device level.
+ */
+void pci_msi_off(struct pci_dev *dev)
+{
+       int pos;
+       u16 control;
+
+       pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+       if (pos) {
+               pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
+               control &= ~PCI_MSI_FLAGS_ENABLE;
+               pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
+       }
+       pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+       if (pos) {
+               pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control);
+               control &= ~PCI_MSIX_FLAGS_ENABLE;
+               pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
+       }
+}
+
 #ifndef HAVE_ARCH_PCI_SET_DMA_MASK
 /*
  * These can be overridden by arch-specific implementations
@@ -1300,7 +1325,7 @@ pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
 
 /**
  * pci_select_bars - Make BAR mask from the type of resource
- * @pdev: the PCI device for which BAR mask is made
+ * @dev: the PCI device for which BAR mask is made
  * @flags: resource type mask to be selected
  *
  * This helper routine makes bar mask from the type of resource.
@@ -1333,6 +1358,10 @@ static int __devinit pci_setup(char *str)
                if (*str && (str = pcibios_setup(str)) && *str) {
                        if (!strcmp(str, "nomsi")) {
                                pci_no_msi();
+                       } else if (!strncmp(str, "cbiosize=", 9)) {
+                               pci_cardbus_io_size = memparse(str + 9, &str);
+                       } else if (!strncmp(str, "cbmemsize=", 10)) {
+                               pci_cardbus_mem_size = memparse(str + 10, &str);
                        } else {
                                printk(KERN_ERR "PCI: Unknown option `%s'\n",
                                                str);