Merge branch 'pci/resource'
authorBjorn Helgaas <bhelgaas@google.com>
Mon, 23 Sep 2019 21:10:15 +0000 (16:10 -0500)
committerBjorn Helgaas <bhelgaas@google.com>
Mon, 23 Sep 2019 21:10:15 +0000 (16:10 -0500)
  - Convert pci_resource_to_user() to a weak function to remove
    HAVE_ARCH_PCI_RESOURCE_TO_USER #defines (Denis Efremov)

  - Use PCI_SRIOV_NUM_BARS for idiomatic loop structure (Denis Efremov)

  - Fix Resizable BAR size suspend/restore for 1MB BARs (Sumit Saxena)

  - Correct "pci=resource_alignment" example in documentation (Alexey
    Kardashevskiy)

* pci/resource:
  PCI: Correct pci=resource_alignment parameter example
  PCI: Restore Resizable BAR size bits correctly for 1MB BARs
  PCI: Use PCI_SRIOV_NUM_BARS in loops instead of PCI_IOV_RESOURCE_END
  PCI: Convert pci_resource_to_user() to a weak function

# Conflicts:
# drivers/pci/pci.c

42 files changed:
drivers/acpi/pci_root.c
drivers/char/xillybus/xillybus_pcie.c
drivers/infiniband/core/rw.c
drivers/net/ethernet/intel/e1000e/e1000.h
drivers/net/ethernet/jme.c
drivers/net/ethernet/realtek/r8169_main.c
drivers/net/wireless/ath/ath5k/pci.c
drivers/net/wireless/intel/iwlegacy/3945-mac.c
drivers/net/wireless/intel/iwlegacy/4965-mac.c
drivers/net/wireless/intel/iwlwifi/pcie/trans.c
drivers/nvme/host/pci.c
drivers/pci/Kconfig
drivers/pci/access.c
drivers/pci/bus.c
drivers/pci/controller/pci-host-common.c
drivers/pci/hotplug/ibmphp_res.c
drivers/pci/hotplug/pciehp.h
drivers/pci/hotplug/pciehp_core.c
drivers/pci/hotplug/pciehp_ctrl.c
drivers/pci/hotplug/pciehp_hpc.c
drivers/pci/iov.c
drivers/pci/p2pdma.c
drivers/pci/pci-acpi.c
drivers/pci/pci-bridge-emul.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/aspm.c
drivers/pci/pcie/err.c
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/pci/search.c
drivers/pci/vc.c
drivers/scsi/aacraid/linit.c
drivers/scsi/hpsa.c
drivers/scsi/mpt3sas/mpt3sas_scsih.c
include/linux/memremap.h
include/linux/pci-aspm.h [deleted file]
include/linux/pci-p2pdma.h
include/linux/pci.h
include/linux/pci_hotplug.h
include/uapi/linux/pci_regs.h

index 314a187ed5728196daea3d2469d5908c3a538626..d1e666ef3fcc886eb48772419aa891b78b039bc6 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/pm_runtime.h>
 #include <linux/pci.h>
 #include <linux/pci-acpi.h>
-#include <linux/pci-aspm.h>
 #include <linux/dmar.h>
 #include <linux/acpi.h>
 #include <linux/slab.h>
index 02c15952b1030520a70ab6e5dde96bf9aabba131..18b0c392bc9325cd378b4e23d1cb7be1ce5447ad 100644 (file)
@@ -9,7 +9,6 @@
 
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/pci-aspm.h>
 #include <linux/slab.h>
 #include "xillybus.h"
 
index dce06108c8c3fe39d9bd2d28ae9d88dd6cab82c7..5337393d4dfe78cc91728b9fb8f41378961194ea 100644 (file)
@@ -583,8 +583,10 @@ void rdma_rw_ctx_destroy(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u8 port_num,
                break;
        }
 
-       /* P2PDMA contexts do not need to be unmapped */
-       if (!is_pci_p2pdma_page(sg_page(sg)))
+       if (is_pci_p2pdma_page(sg_page(sg)))
+               pci_p2pdma_unmap_sg(qp->pd->device->dma_device, sg,
+                                   sg_cnt, dir);
+       else
                ib_dma_unmap_sg(qp->pd->device, sg, sg_cnt, dir);
 }
 EXPORT_SYMBOL(rdma_rw_ctx_destroy);
index 34cd67951aecdbb8e34382b15d1121477dc77c2d..6c51b1bad8c423ea243587446d3e5fc6705ca9ad 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/io.h>
 #include <linux/netdevice.h>
 #include <linux/pci.h>
-#include <linux/pci-aspm.h>
 #include <linux/crc32.h>
 #include <linux/if_vlan.h>
 #include <linux/timecounter.h>
index 0b668357db4dd24de638dd8a995790f482d9b95f..57e8aea98969efaaa881d86cb5627756cafa04e4 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
-#include <linux/pci-aspm.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
index 0637c6752a78e7451826f08f48d30ac97ec85765..a6d8e7f5fde700738436519924d0622cb9c12a6d 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/pm_runtime.h>
 #include <linux/prefetch.h>
-#include <linux/pci-aspm.h>
 #include <linux/ipv6.h>
 #include <net/ip6_checksum.h>
 
index c6156cc38940ada0cbe923da182a659f4e934023..d5ee32ce9eb3dac632e3ebc5bdb9118425ab729c 100644 (file)
@@ -18,7 +18,6 @@
 
 #include <linux/nl80211.h>
 #include <linux/pci.h>
-#include <linux/pci-aspm.h>
 #include <linux/etherdevice.h>
 #include <linux/module.h>
 #include "../ath.h"
index b82da75a9ae3640ef1f295b7ffe5c9683f22355a..4fbcc7fba3cc14760fa90ac9dc8baa4c8f0734d3 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-#include <linux/pci-aspm.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
index fa2c028819397934b7025e539f747cea635165d6..ffb705b18fb13bd3a44753087358e72ded6aea75 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-#include <linux/pci-aspm.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
index f5df5b370d78b585dd277b61b86c00498b8e5f74..4c308e33ee21b2f73b9b39ba7ee7f1637660fef4 100644 (file)
@@ -62,7 +62,6 @@
  *
  *****************************************************************************/
 #include <linux/pci.h>
-#include <linux/pci-aspm.h>
 #include <linux/interrupt.h>
 #include <linux/debugfs.h>
 #include <linux/sched.h>
index bb970ca82517b1213cb4922225822edb78e23b4d..2348b15f6bd0dfccf00ebd7f542f3541eb97cfc8 100644 (file)
@@ -547,8 +547,10 @@ static void nvme_unmap_data(struct nvme_dev *dev, struct request *req)
 
        WARN_ON_ONCE(!iod->nents);
 
-       /* P2PDMA requests do not need to be unmapped */
-       if (!is_pci_p2pdma_page(sg_page(iod->sg)))
+       if (is_pci_p2pdma_page(sg_page(iod->sg)))
+               pci_p2pdma_unmap_sg(dev->dev, iod->sg, iod->nents,
+                                   rq_dma_dir(req));
+       else
                dma_unmap_sg(dev->dev, iod->sg, iod->nents, rq_dma_dir(req));
 
 
@@ -832,8 +834,8 @@ static blk_status_t nvme_map_data(struct nvme_dev *dev, struct request *req,
                goto out;
 
        if (is_pci_p2pdma_page(sg_page(iod->sg)))
-               nr_mapped = pci_p2pdma_map_sg(dev->dev, iod->sg, iod->nents,
-                                             rq_dma_dir(req));
+               nr_mapped = pci_p2pdma_map_sg_attrs(dev->dev, iod->sg,
+                               iod->nents, rq_dma_dir(req), DMA_ATTR_NO_WARN);
        else
                nr_mapped = dma_map_sg_attrs(dev->dev, iod->sg, iod->nents,
                                             rq_dma_dir(req), DMA_ATTR_NO_WARN);
index 2ab92409210afc0cc8cf54da3bef2392abd7d5c3..beb3408a0272d4537870caf5bb19f679212c3853 100644 (file)
@@ -52,7 +52,7 @@ config PCI_MSI
           If you don't know what to do here, say Y.
 
 config PCI_MSI_IRQ_DOMAIN
-       def_bool ARC || ARM || ARM64 || X86
+       def_bool ARC || ARM || ARM64 || X86 || RISCV
        depends on PCI_MSI
        select GENERIC_MSI_IRQ_DOMAIN
 
index 544922f097c044a7e434d679ddddf588f72e8467..2fccb5762c762cf34a503a96e6971760d8964bfb 100644 (file)
@@ -336,15 +336,6 @@ static inline int pcie_cap_version(const struct pci_dev *dev)
        return pcie_caps_reg(dev) & PCI_EXP_FLAGS_VERS;
 }
 
-static bool pcie_downstream_port(const struct pci_dev *dev)
-{
-       int type = pci_pcie_type(dev);
-
-       return type == PCI_EXP_TYPE_ROOT_PORT ||
-              type == PCI_EXP_TYPE_DOWNSTREAM ||
-              type == PCI_EXP_TYPE_PCIE_BRIDGE;
-}
-
 bool pcie_cap_has_lnkctl(const struct pci_dev *dev)
 {
        int type = pci_pcie_type(dev);
index 495059d923f7da4e360a7689349c46260e16e797..8e40b3e6da77d14ebeaa5ce1d0e40bcc9d525413 100644 (file)
@@ -417,11 +417,9 @@ struct pci_bus *pci_bus_get(struct pci_bus *bus)
                get_device(&bus->dev);
        return bus;
 }
-EXPORT_SYMBOL(pci_bus_get);
 
 void pci_bus_put(struct pci_bus *bus)
 {
        if (bus)
                put_device(&bus->dev);
 }
-EXPORT_SYMBOL(pci_bus_put);
index c742881b5061a7be0cdae6b485c10b9d3816fa84..c8cb9c5188a415aaa9f03495c169e660404060fc 100644 (file)
@@ -43,9 +43,8 @@ static struct pci_config_window *gen_pci_init(struct device *dev,
                goto err_out;
        }
 
-       err = devm_add_action(dev, gen_pci_unmap_cfg, cfg);
+       err = devm_add_action_or_reset(dev, gen_pci_unmap_cfg, cfg);
        if (err) {
-               gen_pci_unmap_cfg(cfg);
                goto err_out;
        }
        return cfg;
index 5e8caf7a4452b2e2df2f4c9f23a5547979327200..5c93aa14f0de21ff008345037b2307fbeb7c3ed7 100644 (file)
@@ -1941,6 +1941,7 @@ static int __init update_bridge_ranges(struct bus_node **bus)
                                                break;
                                        case PCI_HEADER_TYPE_BRIDGE:
                                                function = 0x8;
+                                               /* fall through */
                                        case PCI_HEADER_TYPE_MULTIBRIDGE:
                                                /* We assume here that only 1 bus behind the bridge
                                                   TO DO: add functionality for several:
index 8c51a04b8083e1d1d7a4894b90a95b8231214199..654c972b8ea0c3f3117cd27a495a1f1dd99ee685 100644 (file)
@@ -110,9 +110,9 @@ struct controller {
  *
  * @OFF_STATE: slot is powered off, no subordinate devices are enumerated
  * @BLINKINGON_STATE: slot will be powered on after the 5 second delay,
- *     green led is blinking
+ *     Power Indicator is blinking
  * @BLINKINGOFF_STATE: slot will be powered off after the 5 second delay,
- *     green led is blinking
+ *     Power Indicator is blinking
  * @POWERON_STATE: slot is currently powering on
  * @POWEROFF_STATE: slot is currently powering off
  * @ON_STATE: slot is powered on, subordinate devices have been enumerated
@@ -167,12 +167,11 @@ int pciehp_power_on_slot(struct controller *ctrl);
 void pciehp_power_off_slot(struct controller *ctrl);
 void pciehp_get_power_status(struct controller *ctrl, u8 *status);
 
-void pciehp_set_attention_status(struct controller *ctrl, u8 status);
+#define INDICATOR_NOOP -1      /* Leave indicator unchanged */
+void pciehp_set_indicators(struct controller *ctrl, int pwr, int attn);
+
 void pciehp_get_latch_status(struct controller *ctrl, u8 *status);
 int pciehp_query_power_fault(struct controller *ctrl);
-void pciehp_green_led_on(struct controller *ctrl);
-void pciehp_green_led_off(struct controller *ctrl);
-void pciehp_green_led_blink(struct controller *ctrl);
 bool pciehp_card_present(struct controller *ctrl);
 bool pciehp_card_present_or_link_active(struct controller *ctrl);
 int pciehp_check_link_status(struct controller *ctrl);
index 6ad0d86762cb5b48a4280384ae3ecbf133bf171e..b3122c151b8035872337cc34f0195582e436b132 100644 (file)
@@ -95,15 +95,20 @@ static void cleanup_slot(struct controller *ctrl)
 }
 
 /*
- * set_attention_status - Turns the Amber LED for a slot on, off or blink
+ * set_attention_status - Turns the Attention Indicator on, off or blinking
  */
 static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
 {
        struct controller *ctrl = to_ctrl(hotplug_slot);
        struct pci_dev *pdev = ctrl->pcie->port;
 
+       if (status)
+               status <<= PCI_EXP_SLTCTL_ATTN_IND_SHIFT;
+       else
+               status = PCI_EXP_SLTCTL_ATTN_IND_OFF;
+
        pci_config_pm_runtime_get(pdev);
-       pciehp_set_attention_status(ctrl, status);
+       pciehp_set_indicators(ctrl, INDICATOR_NOOP, status);
        pci_config_pm_runtime_put(pdev);
        return 0;
 }
index 631ced0ab28a0be5fd83f7bedeb279ca3bbc1988..21af7b16d7a4f258e04d48f78a351cd88e5a9718 100644 (file)
 
 static void set_slot_off(struct controller *ctrl)
 {
-       /* turn off slot, turn on Amber LED, turn off Green LED if supported*/
+       /*
+        * Turn off slot, turn on attention indicator, turn off power
+        * indicator
+        */
        if (POWER_CTRL(ctrl)) {
                pciehp_power_off_slot(ctrl);
 
@@ -42,8 +45,8 @@ static void set_slot_off(struct controller *ctrl)
                msleep(1000);
        }
 
-       pciehp_green_led_off(ctrl);
-       pciehp_set_attention_status(ctrl, 1);
+       pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF,
+                             PCI_EXP_SLTCTL_ATTN_IND_ON);
 }
 
 /**
@@ -65,7 +68,8 @@ static int board_added(struct controller *ctrl)
                        return retval;
        }
 
-       pciehp_green_led_blink(ctrl);
+       pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_BLINK,
+                             INDICATOR_NOOP);
 
        /* Check link training status */
        retval = pciehp_check_link_status(ctrl);
@@ -90,8 +94,8 @@ static int board_added(struct controller *ctrl)
                }
        }
 
-       pciehp_green_led_on(ctrl);
-       pciehp_set_attention_status(ctrl, 0);
+       pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_ON,
+                             PCI_EXP_SLTCTL_ATTN_IND_OFF);
        return 0;
 
 err_exit:
@@ -100,7 +104,7 @@ err_exit:
 }
 
 /**
- * remove_board - Turns off slot and LEDs
+ * remove_board - Turn off slot and Power Indicator
  * @ctrl: PCIe hotplug controller where board is being removed
  * @safe_removal: whether the board is safely removed (versus surprise removed)
  */
@@ -123,8 +127,8 @@ static void remove_board(struct controller *ctrl, bool safe_removal)
                           &ctrl->pending_events);
        }
 
-       /* turn off Green LED */
-       pciehp_green_led_off(ctrl);
+       pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF,
+                             INDICATOR_NOOP);
 }
 
 static int pciehp_enable_slot(struct controller *ctrl);
@@ -171,9 +175,9 @@ void pciehp_handle_button_press(struct controller *ctrl)
                        ctrl_info(ctrl, "Slot(%s) Powering on due to button press\n",
                                  slot_name(ctrl));
                }
-               /* blink green LED and turn off amber */
-               pciehp_green_led_blink(ctrl);
-               pciehp_set_attention_status(ctrl, 0);
+               /* blink power indicator and turn off attention */
+               pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_BLINK,
+                                     PCI_EXP_SLTCTL_ATTN_IND_OFF);
                schedule_delayed_work(&ctrl->button_work, 5 * HZ);
                break;
        case BLINKINGOFF_STATE:
@@ -187,12 +191,13 @@ void pciehp_handle_button_press(struct controller *ctrl)
                cancel_delayed_work(&ctrl->button_work);
                if (ctrl->state == BLINKINGOFF_STATE) {
                        ctrl->state = ON_STATE;
-                       pciehp_green_led_on(ctrl);
+                       pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_ON,
+                                             PCI_EXP_SLTCTL_ATTN_IND_OFF);
                } else {
                        ctrl->state = OFF_STATE;
-                       pciehp_green_led_off(ctrl);
+                       pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF,
+                                             PCI_EXP_SLTCTL_ATTN_IND_OFF);
                }
-               pciehp_set_attention_status(ctrl, 0);
                ctrl_info(ctrl, "Slot(%s): Action canceled due to button press\n",
                          slot_name(ctrl));
                break;
@@ -310,7 +315,9 @@ static int pciehp_enable_slot(struct controller *ctrl)
        pm_runtime_get_sync(&ctrl->pcie->port->dev);
        ret = __pciehp_enable_slot(ctrl);
        if (ret && ATTN_BUTTN(ctrl))
-               pciehp_green_led_off(ctrl); /* may be blinking */
+               /* may be blinking */
+               pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF,
+                                     INDICATOR_NOOP);
        pm_runtime_put(&ctrl->pcie->port->dev);
 
        mutex_lock(&ctrl->state_lock);
index bd990e3371e31afa9ba130134c7741c765931b26..1a522c1c41772ed33828a366afd899356c42bd90 100644 (file)
@@ -418,65 +418,40 @@ int pciehp_set_raw_indicator_status(struct hotplug_slot *hotplug_slot,
        return 0;
 }
 
-void pciehp_set_attention_status(struct controller *ctrl, u8 value)
+/**
+ * pciehp_set_indicators() - set attention indicator, power indicator, or both
+ * @ctrl: PCIe hotplug controller
+ * @pwr: one of:
+ *     PCI_EXP_SLTCTL_PWR_IND_ON
+ *     PCI_EXP_SLTCTL_PWR_IND_BLINK
+ *     PCI_EXP_SLTCTL_PWR_IND_OFF
+ * @attn: one of:
+ *     PCI_EXP_SLTCTL_ATTN_IND_ON
+ *     PCI_EXP_SLTCTL_ATTN_IND_BLINK
+ *     PCI_EXP_SLTCTL_ATTN_IND_OFF
+ *
+ * Either @pwr or @attn can also be INDICATOR_NOOP to leave that indicator
+ * unchanged.
+ */
+void pciehp_set_indicators(struct controller *ctrl, int pwr, int attn)
 {
-       u16 slot_cmd;
+       u16 cmd = 0, mask = 0;
 
-       if (!ATTN_LED(ctrl))
-               return;
-
-       switch (value) {
-       case 0:         /* turn off */
-               slot_cmd = PCI_EXP_SLTCTL_ATTN_IND_OFF;
-               break;
-       case 1:         /* turn on */
-               slot_cmd = PCI_EXP_SLTCTL_ATTN_IND_ON;
-               break;
-       case 2:         /* turn blink */
-               slot_cmd = PCI_EXP_SLTCTL_ATTN_IND_BLINK;
-               break;
-       default:
-               return;
+       if (PWR_LED(ctrl) && pwr != INDICATOR_NOOP) {
+               cmd |= (pwr & PCI_EXP_SLTCTL_PIC);
+               mask |= PCI_EXP_SLTCTL_PIC;
        }
-       pcie_write_cmd_nowait(ctrl, slot_cmd, PCI_EXP_SLTCTL_AIC);
-       ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
-                pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
-}
 
-void pciehp_green_led_on(struct controller *ctrl)
-{
-       if (!PWR_LED(ctrl))
-               return;
-
-       pcie_write_cmd_nowait(ctrl, PCI_EXP_SLTCTL_PWR_IND_ON,
-                             PCI_EXP_SLTCTL_PIC);
-       ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
-                pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL,
-                PCI_EXP_SLTCTL_PWR_IND_ON);
-}
-
-void pciehp_green_led_off(struct controller *ctrl)
-{
-       if (!PWR_LED(ctrl))
-               return;
-
-       pcie_write_cmd_nowait(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF,
-                             PCI_EXP_SLTCTL_PIC);
-       ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
-                pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL,
-                PCI_EXP_SLTCTL_PWR_IND_OFF);
-}
-
-void pciehp_green_led_blink(struct controller *ctrl)
-{
-       if (!PWR_LED(ctrl))
-               return;
+       if (ATTN_LED(ctrl) && attn != INDICATOR_NOOP) {
+               cmd |= (attn & PCI_EXP_SLTCTL_AIC);
+               mask |= PCI_EXP_SLTCTL_AIC;
+       }
 
-       pcie_write_cmd_nowait(ctrl, PCI_EXP_SLTCTL_PWR_IND_BLINK,
-                             PCI_EXP_SLTCTL_PIC);
-       ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
-                pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL,
-                PCI_EXP_SLTCTL_PWR_IND_BLINK);
+       if (cmd) {
+               pcie_write_cmd_nowait(ctrl, cmd, mask);
+               ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
+                        pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, cmd);
+       }
 }
 
 int pciehp_power_on_slot(struct controller *ctrl)
@@ -638,8 +613,8 @@ static irqreturn_t pciehp_ist(int irq, void *dev_id)
        if ((events & PCI_EXP_SLTSTA_PFD) && !ctrl->power_fault_detected) {
                ctrl->power_fault_detected = 1;
                ctrl_err(ctrl, "Slot(%s): Power fault\n", slot_name(ctrl));
-               pciehp_set_attention_status(ctrl, 1);
-               pciehp_green_led_off(ctrl);
+               pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF,
+                                     PCI_EXP_SLTCTL_ATTN_IND_ON);
        }
 
        /*
index 9b48818ced0178cd37c4e728e5034a5fa9ef3a63..b3f972e8cfed6ed69b145c719e852a1beb8209ce 100644 (file)
@@ -240,6 +240,173 @@ void pci_iov_remove_virtfn(struct pci_dev *dev, int id)
        pci_dev_put(dev);
 }
 
+static ssize_t sriov_totalvfs_show(struct device *dev,
+                                  struct device_attribute *attr,
+                                  char *buf)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+
+       return sprintf(buf, "%u\n", pci_sriov_get_totalvfs(pdev));
+}
+
+static ssize_t sriov_numvfs_show(struct device *dev,
+                                struct device_attribute *attr,
+                                char *buf)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+
+       return sprintf(buf, "%u\n", pdev->sriov->num_VFs);
+}
+
+/*
+ * num_vfs > 0; number of VFs to enable
+ * num_vfs = 0; disable all VFs
+ *
+ * Note: SRIOV spec does not allow partial VF
+ *      disable, so it's all or none.
+ */
+static ssize_t sriov_numvfs_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t count)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       int ret;
+       u16 num_vfs;
+
+       ret = kstrtou16(buf, 0, &num_vfs);
+       if (ret < 0)
+               return ret;
+
+       if (num_vfs > pci_sriov_get_totalvfs(pdev))
+               return -ERANGE;
+
+       device_lock(&pdev->dev);
+
+       if (num_vfs == pdev->sriov->num_VFs)
+               goto exit;
+
+       /* is PF driver loaded w/callback */
+       if (!pdev->driver || !pdev->driver->sriov_configure) {
+               pci_info(pdev, "Driver does not support SRIOV configuration via sysfs\n");
+               ret = -ENOENT;
+               goto exit;
+       }
+
+       if (num_vfs == 0) {
+               /* disable VFs */
+               ret = pdev->driver->sriov_configure(pdev, 0);
+               goto exit;
+       }
+
+       /* enable VFs */
+       if (pdev->sriov->num_VFs) {
+               pci_warn(pdev, "%d VFs already enabled. Disable before enabling %d VFs\n",
+                        pdev->sriov->num_VFs, num_vfs);
+               ret = -EBUSY;
+               goto exit;
+       }
+
+       ret = pdev->driver->sriov_configure(pdev, num_vfs);
+       if (ret < 0)
+               goto exit;
+
+       if (ret != num_vfs)
+               pci_warn(pdev, "%d VFs requested; only %d enabled\n",
+                        num_vfs, ret);
+
+exit:
+       device_unlock(&pdev->dev);
+
+       if (ret < 0)
+               return ret;
+
+       return count;
+}
+
+static ssize_t sriov_offset_show(struct device *dev,
+                                struct device_attribute *attr,
+                                char *buf)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+
+       return sprintf(buf, "%u\n", pdev->sriov->offset);
+}
+
+static ssize_t sriov_stride_show(struct device *dev,
+                                struct device_attribute *attr,
+                                char *buf)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+
+       return sprintf(buf, "%u\n", pdev->sriov->stride);
+}
+
+static ssize_t sriov_vf_device_show(struct device *dev,
+                                   struct device_attribute *attr,
+                                   char *buf)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+
+       return sprintf(buf, "%x\n", pdev->sriov->vf_device);
+}
+
+static ssize_t sriov_drivers_autoprobe_show(struct device *dev,
+                                           struct device_attribute *attr,
+                                           char *buf)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+
+       return sprintf(buf, "%u\n", pdev->sriov->drivers_autoprobe);
+}
+
+static ssize_t sriov_drivers_autoprobe_store(struct device *dev,
+                                            struct device_attribute *attr,
+                                            const char *buf, size_t count)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       bool drivers_autoprobe;
+
+       if (kstrtobool(buf, &drivers_autoprobe) < 0)
+               return -EINVAL;
+
+       pdev->sriov->drivers_autoprobe = drivers_autoprobe;
+
+       return count;
+}
+
+static DEVICE_ATTR_RO(sriov_totalvfs);
+static DEVICE_ATTR_RW(sriov_numvfs);
+static DEVICE_ATTR_RO(sriov_offset);
+static DEVICE_ATTR_RO(sriov_stride);
+static DEVICE_ATTR_RO(sriov_vf_device);
+static DEVICE_ATTR_RW(sriov_drivers_autoprobe);
+
+static struct attribute *sriov_dev_attrs[] = {
+       &dev_attr_sriov_totalvfs.attr,
+       &dev_attr_sriov_numvfs.attr,
+       &dev_attr_sriov_offset.attr,
+       &dev_attr_sriov_stride.attr,
+       &dev_attr_sriov_vf_device.attr,
+       &dev_attr_sriov_drivers_autoprobe.attr,
+       NULL,
+};
+
+static umode_t sriov_attrs_are_visible(struct kobject *kobj,
+                                      struct attribute *a, int n)
+{
+       struct device *dev = kobj_to_dev(kobj);
+
+       if (!dev_is_pf(dev))
+               return 0;
+
+       return a->mode;
+}
+
+const struct attribute_group sriov_dev_attr_group = {
+       .attrs = sriov_dev_attrs,
+       .is_visible = sriov_attrs_are_visible,
+};
+
 int __weak pcibios_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
 {
        return 0;
index 23447622652924e32f30a6dfe9a85c8e5aee863c..0608aae72ccccfd67e5b4187e87a02593db19485 100644 (file)
 #include <linux/percpu-refcount.h>
 #include <linux/random.h>
 #include <linux/seq_buf.h>
-#include <linux/iommu.h>
+#include <linux/xarray.h>
+
+enum pci_p2pdma_map_type {
+       PCI_P2PDMA_MAP_UNKNOWN = 0,
+       PCI_P2PDMA_MAP_NOT_SUPPORTED,
+       PCI_P2PDMA_MAP_BUS_ADDR,
+       PCI_P2PDMA_MAP_THRU_HOST_BRIDGE,
+};
 
 struct pci_p2pdma {
        struct gen_pool *pool;
        bool p2pmem_published;
+       struct xarray map_types;
 };
 
+struct pci_p2pdma_pagemap {
+       struct dev_pagemap pgmap;
+       struct pci_dev *provider;
+       u64 bus_offset;
+};
+
+static struct pci_p2pdma_pagemap *to_p2p_pgmap(struct dev_pagemap *pgmap)
+{
+       return container_of(pgmap, struct pci_p2pdma_pagemap, pgmap);
+}
+
 static ssize_t size_show(struct device *dev, struct device_attribute *attr,
                         char *buf)
 {
@@ -87,6 +106,7 @@ static void pci_p2pdma_release(void *data)
 
        gen_pool_destroy(p2pdma->pool);
        sysfs_remove_group(&pdev->dev.kobj, &p2pmem_group);
+       xa_destroy(&p2pdma->map_types);
 }
 
 static int pci_p2pdma_setup(struct pci_dev *pdev)
@@ -98,6 +118,8 @@ static int pci_p2pdma_setup(struct pci_dev *pdev)
        if (!p2p)
                return -ENOMEM;
 
+       xa_init(&p2p->map_types);
+
        p2p->pool = gen_pool_create(PAGE_SHIFT, dev_to_node(&pdev->dev));
        if (!p2p->pool)
                goto out;
@@ -135,6 +157,7 @@ out:
 int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size,
                            u64 offset)
 {
+       struct pci_p2pdma_pagemap *p2p_pgmap;
        struct dev_pagemap *pgmap;
        void *addr;
        int error;
@@ -157,14 +180,18 @@ int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size,
                        return error;
        }
 
-       pgmap = devm_kzalloc(&pdev->dev, sizeof(*pgmap), GFP_KERNEL);
-       if (!pgmap)
+       p2p_pgmap = devm_kzalloc(&pdev->dev, sizeof(*p2p_pgmap), GFP_KERNEL);
+       if (!p2p_pgmap)
                return -ENOMEM;
+
+       pgmap = &p2p_pgmap->pgmap;
        pgmap->res.start = pci_resource_start(pdev, bar) + offset;
        pgmap->res.end = pgmap->res.start + size - 1;
        pgmap->res.flags = pci_resource_flags(pdev, bar);
        pgmap->type = MEMORY_DEVICE_PCI_P2PDMA;
-       pgmap->pci_p2pdma_bus_offset = pci_bus_address(pdev, bar) -
+
+       p2p_pgmap->provider = pdev;
+       p2p_pgmap->bus_offset = pci_bus_address(pdev, bar) -
                pci_resource_start(pdev, bar);
 
        addr = devm_memremap_pages(&pdev->dev, pgmap);
@@ -246,19 +273,32 @@ static void seq_buf_print_bus_devfn(struct seq_buf *buf, struct pci_dev *pdev)
        seq_buf_printf(buf, "%s;", pci_name(pdev));
 }
 
-/*
- * If we can't find a common upstream bridge take a look at the root
- * complex and compare it to a whitelist of known good hardware.
- */
-static bool root_complex_whitelist(struct pci_dev *dev)
+static const struct pci_p2pdma_whitelist_entry {
+       unsigned short vendor;
+       unsigned short device;
+       enum {
+               REQ_SAME_HOST_BRIDGE    = 1 << 0,
+       } flags;
+} pci_p2pdma_whitelist[] = {
+       /* AMD ZEN */
+       {PCI_VENDOR_ID_AMD,     0x1450, 0},
+
+       /* Intel Xeon E5/Core i7 */
+       {PCI_VENDOR_ID_INTEL,   0x3c00, REQ_SAME_HOST_BRIDGE},
+       {PCI_VENDOR_ID_INTEL,   0x3c01, REQ_SAME_HOST_BRIDGE},
+       /* Intel Xeon E7 v3/Xeon E5 v3/Core i7 */
+       {PCI_VENDOR_ID_INTEL,   0x2f00, REQ_SAME_HOST_BRIDGE},
+       {PCI_VENDOR_ID_INTEL,   0x2f01, REQ_SAME_HOST_BRIDGE},
+       {}
+};
+
+static bool __host_bridge_whitelist(struct pci_host_bridge *host,
+                                   bool same_host_bridge)
 {
-       struct pci_host_bridge *host = pci_find_host_bridge(dev->bus);
        struct pci_dev *root = pci_get_slot(host->bus, PCI_DEVFN(0, 0));
+       const struct pci_p2pdma_whitelist_entry *entry;
        unsigned short vendor, device;
 
-       if (iommu_present(dev->dev.bus))
-               return false;
-
        if (!root)
                return false;
 
@@ -266,65 +306,49 @@ static bool root_complex_whitelist(struct pci_dev *dev)
        device = root->device;
        pci_dev_put(root);
 
-       /* AMD ZEN host bridges can do peer to peer */
-       if (vendor == PCI_VENDOR_ID_AMD && device == 0x1450)
+       for (entry = pci_p2pdma_whitelist; entry->vendor; entry++) {
+               if (vendor != entry->vendor || device != entry->device)
+                       continue;
+               if (entry->flags & REQ_SAME_HOST_BRIDGE && !same_host_bridge)
+                       return false;
+
                return true;
+       }
 
        return false;
 }
 
 /*
- * Find the distance through the nearest common upstream bridge between
- * two PCI devices.
- *
- * If the two devices are the same device then 0 will be returned.
- *
- * If there are two virtual functions of the same device behind the same
- * bridge port then 2 will be returned (one step down to the PCIe switch,
- * then one step back to the same device).
- *
- * In the case where two devices are connected to the same PCIe switch, the
- * value 4 will be returned. This corresponds to the following PCI tree:
- *
- *     -+  Root Port
- *      \+ Switch Upstream Port
- *       +-+ Switch Downstream Port
- *       + \- Device A
- *       \-+ Switch Downstream Port
- *         \- Device B
- *
- * The distance is 4 because we traverse from Device A through the downstream
- * port of the switch, to the common upstream port, back up to the second
- * downstream port and then to Device B.
- *
- * Any two devices that don't have a common upstream bridge will return -1.
- * In this way devices on separate PCIe root ports will be rejected, which
- * is what we want for peer-to-peer seeing each PCIe root port defines a
- * separate hierarchy domain and there's no way to determine whether the root
- * complex supports forwarding between them.
- *
- * In the case where two devices are connected to different PCIe switches,
- * this function will still return a positive distance as long as both
- * switches eventually have a common upstream bridge. Note this covers
- * the case of using multiple PCIe switches to achieve a desired level of
- * fan-out from a root port. The exact distance will be a function of the
- * number of switches between Device A and Device B.
- *
- * If a bridge which has any ACS redirection bits set is in the path
- * then this functions will return -2. This is so we reject any
- * cases where the TLPs are forwarded up into the root complex.
- * In this case, a list of all infringing bridge addresses will be
- * populated in acs_list (assuming it's non-null) for printk purposes.
+ * If we can't find a common upstream bridge take a look at the root
+ * complex and compare it to a whitelist of known good hardware.
  */
-static int upstream_bridge_distance(struct pci_dev *provider,
-                                   struct pci_dev *client,
-                                   struct seq_buf *acs_list)
+static bool host_bridge_whitelist(struct pci_dev *a, struct pci_dev *b)
+{
+       struct pci_host_bridge *host_a = pci_find_host_bridge(a->bus);
+       struct pci_host_bridge *host_b = pci_find_host_bridge(b->bus);
+
+       if (host_a == host_b)
+               return __host_bridge_whitelist(host_a, true);
+
+       if (__host_bridge_whitelist(host_a, false) &&
+           __host_bridge_whitelist(host_b, false))
+               return true;
+
+       return false;
+}
+
+static enum pci_p2pdma_map_type
+__upstream_bridge_distance(struct pci_dev *provider, struct pci_dev *client,
+               int *dist, bool *acs_redirects, struct seq_buf *acs_list)
 {
        struct pci_dev *a = provider, *b = client, *bb;
        int dist_a = 0;
        int dist_b = 0;
        int acs_cnt = 0;
 
+       if (acs_redirects)
+               *acs_redirects = false;
+
        /*
         * Note, we don't need to take references to devices returned by
         * pci_upstream_bridge() seeing we hold a reference to a child
@@ -353,15 +377,10 @@ static int upstream_bridge_distance(struct pci_dev *provider,
                dist_a++;
        }
 
-       /*
-        * Allow the connection if both devices are on a whitelisted root
-        * complex, but add an arbitrary large value to the distance.
-        */
-       if (root_complex_whitelist(provider) &&
-           root_complex_whitelist(client))
-               return 0x1000 + dist_a + dist_b;
+       if (dist)
+               *dist = dist_a + dist_b;
 
-       return -1;
+       return PCI_P2PDMA_MAP_THRU_HOST_BRIDGE;
 
 check_b_path_acs:
        bb = b;
@@ -378,33 +397,110 @@ check_b_path_acs:
                bb = pci_upstream_bridge(bb);
        }
 
-       if (acs_cnt)
-               return -2;
+       if (dist)
+               *dist = dist_a + dist_b;
+
+       if (acs_cnt) {
+               if (acs_redirects)
+                       *acs_redirects = true;
+
+               return PCI_P2PDMA_MAP_THRU_HOST_BRIDGE;
+       }
+
+       return PCI_P2PDMA_MAP_BUS_ADDR;
+}
+
+static unsigned long map_types_idx(struct pci_dev *client)
+{
+       return (pci_domain_nr(client->bus) << 16) |
+               (client->bus->number << 8) | client->devfn;
+}
+
+/*
+ * Find the distance through the nearest common upstream bridge between
+ * two PCI devices.
+ *
+ * If the two devices are the same device then 0 will be returned.
+ *
+ * If there are two virtual functions of the same device behind the same
+ * bridge port then 2 will be returned (one step down to the PCIe switch,
+ * then one step back to the same device).
+ *
+ * In the case where two devices are connected to the same PCIe switch, the
+ * value 4 will be returned. This corresponds to the following PCI tree:
+ *
+ *     -+  Root Port
+ *      \+ Switch Upstream Port
+ *       +-+ Switch Downstream Port
+ *       + \- Device A
+ *       \-+ Switch Downstream Port
+ *         \- Device B
+ *
+ * The distance is 4 because we traverse from Device A through the downstream
+ * port of the switch, to the common upstream port, back up to the second
+ * downstream port and then to Device B.
+ *
+ * Any two devices that cannot communicate using p2pdma will return
+ * PCI_P2PDMA_MAP_NOT_SUPPORTED.
+ *
+ * Any two devices that have a data path that goes through the host bridge
+ * will consult a whitelist. If the host bridges are on the whitelist,
+ * this function will return PCI_P2PDMA_MAP_THRU_HOST_BRIDGE.
+ *
+ * If either bridge is not on the whitelist this function returns
+ * PCI_P2PDMA_MAP_NOT_SUPPORTED.
+ *
+ * If a bridge which has any ACS redirection bits set is in the path,
+ * acs_redirects will be set to true. In this case, a list of all infringing
+ * bridge addresses will be populated in acs_list (assuming it's non-null)
+ * for printk purposes.
+ */
+static enum pci_p2pdma_map_type
+upstream_bridge_distance(struct pci_dev *provider, struct pci_dev *client,
+               int *dist, bool *acs_redirects, struct seq_buf *acs_list)
+{
+       enum pci_p2pdma_map_type map_type;
+
+       map_type = __upstream_bridge_distance(provider, client, dist,
+                                             acs_redirects, acs_list);
+
+       if (map_type == PCI_P2PDMA_MAP_THRU_HOST_BRIDGE) {
+               if (!host_bridge_whitelist(provider, client))
+                       map_type = PCI_P2PDMA_MAP_NOT_SUPPORTED;
+       }
+
+       if (provider->p2pdma)
+               xa_store(&provider->p2pdma->map_types, map_types_idx(client),
+                        xa_mk_value(map_type), GFP_KERNEL);
 
-       return dist_a + dist_b;
+       return map_type;
 }
 
-static int upstream_bridge_distance_warn(struct pci_dev *provider,
-                                        struct pci_dev *client)
+static enum pci_p2pdma_map_type
+upstream_bridge_distance_warn(struct pci_dev *provider, struct pci_dev *client,
+                             int *dist)
 {
        struct seq_buf acs_list;
+       bool acs_redirects;
        int ret;
 
        seq_buf_init(&acs_list, kmalloc(PAGE_SIZE, GFP_KERNEL), PAGE_SIZE);
        if (!acs_list.buffer)
                return -ENOMEM;
 
-       ret = upstream_bridge_distance(provider, client, &acs_list);
-       if (ret == -2) {
-               pci_warn(client, "cannot be used for peer-to-peer DMA as ACS redirect is set between the client and provider (%s)\n",
+       ret = upstream_bridge_distance(provider, client, dist, &acs_redirects,
+                                      &acs_list);
+       if (acs_redirects) {
+               pci_warn(client, "ACS redirect is set between the client and provider (%s)\n",
                         pci_name(provider));
                /* Drop final semicolon */
                acs_list.buffer[acs_list.len-1] = 0;
                pci_warn(client, "to disable ACS redirect for this path, add the kernel parameter: pci=disable_acs_redir=%s\n",
                         acs_list.buffer);
+       }
 
-       } else if (ret < 0) {
-               pci_warn(client, "cannot be used for peer-to-peer DMA as the client and provider (%s) do not share an upstream bridge\n",
+       if (ret == PCI_P2PDMA_MAP_NOT_SUPPORTED) {
+               pci_warn(client, "cannot be used for peer-to-peer DMA as the client and provider (%s) do not share an upstream bridge or whitelisted host bridge\n",
                         pci_name(provider));
        }
 
@@ -421,22 +517,22 @@ static int upstream_bridge_distance_warn(struct pci_dev *provider,
  * @num_clients: number of clients in the array
  * @verbose: if true, print warnings for devices when we return -1
  *
- * Returns -1 if any of the clients are not compatible (behind the same
- * root port as the provider), otherwise returns a positive number where
- * a lower number is the preferable choice. (If there's one client
- * that's the same as the provider it will return 0, which is best choice).
+ * Returns -1 if any of the clients are not compatible, otherwise returns a
+ * positive number where a lower number is the preferable choice. (If there's
+ * one client that's the same as the provider it will return 0, which is best
+ * choice).
  *
- * For now, "compatible" means the provider and the clients are all behind
- * the same PCI root port. This cuts out cases that may work but is safest
- * for the user. Future work can expand this to white-list root complexes that
- * can safely forward between each ports.
+ * "compatible" means the provider and the clients are either all behind
+ * the same PCI root port or the host bridges connected to each of the devices
+ * are listed in the 'pci_p2pdma_whitelist'.
  */
 int pci_p2pdma_distance_many(struct pci_dev *provider, struct device **clients,
                             int num_clients, bool verbose)
 {
        bool not_supported = false;
        struct pci_dev *pci_client;
-       int distance = 0;
+       int total_dist = 0;
+       int distance;
        int i, ret;
 
        if (num_clients == 0)
@@ -461,26 +557,26 @@ int pci_p2pdma_distance_many(struct pci_dev *provider, struct device **clients,
 
                if (verbose)
                        ret = upstream_bridge_distance_warn(provider,
-                                                           pci_client);
+                                       pci_client, &distance);
                else
                        ret = upstream_bridge_distance(provider, pci_client,
-                                                      NULL);
+                                                      &distance, NULL, NULL);
 
                pci_dev_put(pci_client);
 
-               if (ret < 0)
+               if (ret == PCI_P2PDMA_MAP_NOT_SUPPORTED)
                        not_supported = true;
 
                if (not_supported && !verbose)
                        break;
 
-               distance += ret;
+               total_dist += distance;
        }
 
        if (not_supported)
                return -1;
 
-       return distance;
+       return total_dist;
 }
 EXPORT_SYMBOL_GPL(pci_p2pdma_distance_many);
 
@@ -706,21 +802,19 @@ void pci_p2pmem_publish(struct pci_dev *pdev, bool publish)
 }
 EXPORT_SYMBOL_GPL(pci_p2pmem_publish);
 
-/**
- * pci_p2pdma_map_sg - map a PCI peer-to-peer scatterlist for DMA
- * @dev: device doing the DMA request
- * @sg: scatter list to map
- * @nents: elements in the scatterlist
- * @dir: DMA direction
- *
- * Scatterlists mapped with this function should not be unmapped in any way.
- *
- * Returns the number of SG entries mapped or 0 on error.
- */
-int pci_p2pdma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-                     enum dma_data_direction dir)
+static enum pci_p2pdma_map_type pci_p2pdma_map_type(struct pci_dev *provider,
+                                                   struct pci_dev *client)
+{
+       if (!provider->p2pdma)
+               return PCI_P2PDMA_MAP_NOT_SUPPORTED;
+
+       return xa_to_value(xa_load(&provider->p2pdma->map_types,
+                                  map_types_idx(client)));
+}
+
+static int __pci_p2pdma_map_sg(struct pci_p2pdma_pagemap *p2p_pgmap,
+               struct device *dev, struct scatterlist *sg, int nents)
 {
-       struct dev_pagemap *pgmap;
        struct scatterlist *s;
        phys_addr_t paddr;
        int i;
@@ -736,16 +830,80 @@ int pci_p2pdma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
                return 0;
 
        for_each_sg(sg, s, nents, i) {
-               pgmap = sg_page(s)->pgmap;
                paddr = sg_phys(s);
 
-               s->dma_address = paddr - pgmap->pci_p2pdma_bus_offset;
+               s->dma_address = paddr - p2p_pgmap->bus_offset;
                sg_dma_len(s) = s->length;
        }
 
        return nents;
 }
-EXPORT_SYMBOL_GPL(pci_p2pdma_map_sg);
+
+/**
+ * pci_p2pdma_map_sg - map a PCI peer-to-peer scatterlist for DMA
+ * @dev: device doing the DMA request
+ * @sg: scatter list to map
+ * @nents: elements in the scatterlist
+ * @dir: DMA direction
+ * @attrs: DMA attributes passed to dma_map_sg() (if called)
+ *
+ * Scatterlists mapped with this function should be unmapped using
+ * pci_p2pdma_unmap_sg_attrs().
+ *
+ * Returns the number of SG entries mapped or 0 on error.
+ */
+int pci_p2pdma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
+               int nents, enum dma_data_direction dir, unsigned long attrs)
+{
+       struct pci_p2pdma_pagemap *p2p_pgmap =
+               to_p2p_pgmap(sg_page(sg)->pgmap);
+       struct pci_dev *client;
+
+       if (WARN_ON_ONCE(!dev_is_pci(dev)))
+               return 0;
+
+       client = to_pci_dev(dev);
+
+       switch (pci_p2pdma_map_type(p2p_pgmap->provider, client)) {
+       case PCI_P2PDMA_MAP_THRU_HOST_BRIDGE:
+               return dma_map_sg_attrs(dev, sg, nents, dir, attrs);
+       case PCI_P2PDMA_MAP_BUS_ADDR:
+               return __pci_p2pdma_map_sg(p2p_pgmap, dev, sg, nents);
+       default:
+               WARN_ON_ONCE(1);
+               return 0;
+       }
+}
+EXPORT_SYMBOL_GPL(pci_p2pdma_map_sg_attrs);
+
+/**
+ * pci_p2pdma_unmap_sg - unmap a PCI peer-to-peer scatterlist that was
+ *     mapped with pci_p2pdma_map_sg()
+ * @dev: device doing the DMA request
+ * @sg: scatter list to map
+ * @nents: number of elements returned by pci_p2pdma_map_sg()
+ * @dir: DMA direction
+ * @attrs: DMA attributes passed to dma_unmap_sg() (if called)
+ */
+void pci_p2pdma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg,
+               int nents, enum dma_data_direction dir, unsigned long attrs)
+{
+       struct pci_p2pdma_pagemap *p2p_pgmap =
+               to_p2p_pgmap(sg_page(sg)->pgmap);
+       enum pci_p2pdma_map_type map_type;
+       struct pci_dev *client;
+
+       if (WARN_ON_ONCE(!dev_is_pci(dev)))
+               return;
+
+       client = to_pci_dev(dev);
+
+       map_type = pci_p2pdma_map_type(p2p_pgmap->provider, client);
+
+       if (map_type == PCI_P2PDMA_MAP_THRU_HOST_BRIDGE)
+               dma_unmap_sg_attrs(dev, sg, nents, dir, attrs);
+}
+EXPORT_SYMBOL_GPL(pci_p2pdma_unmap_sg_attrs);
 
 /**
  * pci_p2pdma_enable_store - parse a configfs/sysfs attribute store
index 45049f558860bfb32ffc2447f4d060a28324d1ee..0c02d500158f066d93ceb07d6e5df32f28d2dd9c 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/msi.h>
 #include <linux/pci_hotplug.h>
 #include <linux/module.h>
-#include <linux/pci-aspm.h>
 #include <linux/pci-acpi.h>
 #include <linux/pm_runtime.h>
 #include <linux/pm_qos.h>
@@ -118,8 +117,58 @@ phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle)
        return (phys_addr_t)mcfg_addr;
 }
 
+/* _HPX PCI Setting Record (Type 0); same as _HPP */
+struct hpx_type0 {
+       u32 revision;           /* Not present in _HPP */
+       u8  cache_line_size;    /* Not applicable to PCIe */
+       u8  latency_timer;      /* Not applicable to PCIe */
+       u8  enable_serr;
+       u8  enable_perr;
+};
+
+static struct hpx_type0 pci_default_type0 = {
+       .revision = 1,
+       .cache_line_size = 8,
+       .latency_timer = 0x40,
+       .enable_serr = 0,
+       .enable_perr = 0,
+};
+
+static void program_hpx_type0(struct pci_dev *dev, struct hpx_type0 *hpx)
+{
+       u16 pci_cmd, pci_bctl;
+
+       if (!hpx)
+               hpx = &pci_default_type0;
+
+       if (hpx->revision > 1) {
+               pci_warn(dev, "PCI settings rev %d not supported; using defaults\n",
+                        hpx->revision);
+               hpx = &pci_default_type0;
+       }
+
+       pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpx->cache_line_size);
+       pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpx->latency_timer);
+       pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
+       if (hpx->enable_serr)
+               pci_cmd |= PCI_COMMAND_SERR;
+       if (hpx->enable_perr)
+               pci_cmd |= PCI_COMMAND_PARITY;
+       pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
+
+       /* Program bridge control value */
+       if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+               pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
+                                     hpx->latency_timer);
+               pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
+               if (hpx->enable_perr)
+                       pci_bctl |= PCI_BRIDGE_CTL_PARITY;
+               pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl);
+       }
+}
+
 static acpi_status decode_type0_hpx_record(union acpi_object *record,
-                                          struct hpp_type0 *hpx0)
+                                          struct hpx_type0 *hpx0)
 {
        int i;
        union acpi_object *fields = record->package.elements;
@@ -146,8 +195,30 @@ static acpi_status decode_type0_hpx_record(union acpi_object *record,
        return AE_OK;
 }
 
+/* _HPX PCI-X Setting Record (Type 1) */
+struct hpx_type1 {
+       u32 revision;
+       u8  max_mem_read;
+       u8  avg_max_split;
+       u16 tot_max_split;
+};
+
+static void program_hpx_type1(struct pci_dev *dev, struct hpx_type1 *hpx)
+{
+       int pos;
+
+       if (!hpx)
+               return;
+
+       pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
+       if (!pos)
+               return;
+
+       pci_warn(dev, "PCI-X settings not supported\n");
+}
+
 static acpi_status decode_type1_hpx_record(union acpi_object *record,
-                                          struct hpp_type1 *hpx1)
+                                          struct hpx_type1 *hpx1)
 {
        int i;
        union acpi_object *fields = record->package.elements;
@@ -173,8 +244,130 @@ static acpi_status decode_type1_hpx_record(union acpi_object *record,
        return AE_OK;
 }
 
+static bool pcie_root_rcb_set(struct pci_dev *dev)
+{
+       struct pci_dev *rp = pcie_find_root_port(dev);
+       u16 lnkctl;
+
+       if (!rp)
+               return false;
+
+       pcie_capability_read_word(rp, PCI_EXP_LNKCTL, &lnkctl);
+       if (lnkctl & PCI_EXP_LNKCTL_RCB)
+               return true;
+
+       return false;
+}
+
+/* _HPX PCI Express Setting Record (Type 2) */
+struct hpx_type2 {
+       u32 revision;
+       u32 unc_err_mask_and;
+       u32 unc_err_mask_or;
+       u32 unc_err_sever_and;
+       u32 unc_err_sever_or;
+       u32 cor_err_mask_and;
+       u32 cor_err_mask_or;
+       u32 adv_err_cap_and;
+       u32 adv_err_cap_or;
+       u16 pci_exp_devctl_and;
+       u16 pci_exp_devctl_or;
+       u16 pci_exp_lnkctl_and;
+       u16 pci_exp_lnkctl_or;
+       u32 sec_unc_err_sever_and;
+       u32 sec_unc_err_sever_or;
+       u32 sec_unc_err_mask_and;
+       u32 sec_unc_err_mask_or;
+};
+
+static void program_hpx_type2(struct pci_dev *dev, struct hpx_type2 *hpx)
+{
+       int pos;
+       u32 reg32;
+
+       if (!hpx)
+               return;
+
+       if (!pci_is_pcie(dev))
+               return;
+
+       if (hpx->revision > 1) {
+               pci_warn(dev, "PCIe settings rev %d not supported\n",
+                        hpx->revision);
+               return;
+       }
+
+       /*
+        * Don't allow _HPX to change MPS or MRRS settings.  We manage
+        * those to make sure they're consistent with the rest of the
+        * platform.
+        */
+       hpx->pci_exp_devctl_and |= PCI_EXP_DEVCTL_PAYLOAD |
+                                   PCI_EXP_DEVCTL_READRQ;
+       hpx->pci_exp_devctl_or &= ~(PCI_EXP_DEVCTL_PAYLOAD |
+                                   PCI_EXP_DEVCTL_READRQ);
+
+       /* Initialize Device Control Register */
+       pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL,
+                       ~hpx->pci_exp_devctl_and, hpx->pci_exp_devctl_or);
+
+       /* Initialize Link Control Register */
+       if (pcie_cap_has_lnkctl(dev)) {
+
+               /*
+                * If the Root Port supports Read Completion Boundary of
+                * 128, set RCB to 128.  Otherwise, clear it.
+                */
+               hpx->pci_exp_lnkctl_and |= PCI_EXP_LNKCTL_RCB;
+               hpx->pci_exp_lnkctl_or &= ~PCI_EXP_LNKCTL_RCB;
+               if (pcie_root_rcb_set(dev))
+                       hpx->pci_exp_lnkctl_or |= PCI_EXP_LNKCTL_RCB;
+
+               pcie_capability_clear_and_set_word(dev, PCI_EXP_LNKCTL,
+                       ~hpx->pci_exp_lnkctl_and, hpx->pci_exp_lnkctl_or);
+       }
+
+       /* Find Advanced Error Reporting Enhanced Capability */
+       pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
+       if (!pos)
+               return;
+
+       /* Initialize Uncorrectable Error Mask Register */
+       pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, &reg32);
+       reg32 = (reg32 & hpx->unc_err_mask_and) | hpx->unc_err_mask_or;
+       pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, reg32);
+
+       /* Initialize Uncorrectable Error Severity Register */
+       pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &reg32);
+       reg32 = (reg32 & hpx->unc_err_sever_and) | hpx->unc_err_sever_or;
+       pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, reg32);
+
+       /* Initialize Correctable Error Mask Register */
+       pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg32);
+       reg32 = (reg32 & hpx->cor_err_mask_and) | hpx->cor_err_mask_or;
+       pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg32);
+
+       /* Initialize Advanced Error Capabilities and Control Register */
+       pci_read_config_dword(dev, pos + PCI_ERR_CAP, &reg32);
+       reg32 = (reg32 & hpx->adv_err_cap_and) | hpx->adv_err_cap_or;
+
+       /* Don't enable ECRC generation or checking if unsupported */
+       if (!(reg32 & PCI_ERR_CAP_ECRC_GENC))
+               reg32 &= ~PCI_ERR_CAP_ECRC_GENE;
+       if (!(reg32 & PCI_ERR_CAP_ECRC_CHKC))
+               reg32 &= ~PCI_ERR_CAP_ECRC_CHKE;
+       pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32);
+
+       /*
+        * FIXME: The following two registers are not supported yet.
+        *
+        *   o Secondary Uncorrectable Error Severity Register
+        *   o Secondary Uncorrectable Error Mask Register
+        */
+}
+
 static acpi_status decode_type2_hpx_record(union acpi_object *record,
-                                          struct hpp_type2 *hpx2)
+                                          struct hpx_type2 *hpx2)
 {
        int i;
        union acpi_object *fields = record->package.elements;
@@ -213,6 +406,164 @@ static acpi_status decode_type2_hpx_record(union acpi_object *record,
        return AE_OK;
 }
 
+/* _HPX PCI Express Setting Record (Type 3) */
+struct hpx_type3 {
+       u16 device_type;
+       u16 function_type;
+       u16 config_space_location;
+       u16 pci_exp_cap_id;
+       u16 pci_exp_cap_ver;
+       u16 pci_exp_vendor_id;
+       u16 dvsec_id;
+       u16 dvsec_rev;
+       u16 match_offset;
+       u32 match_mask_and;
+       u32 match_value;
+       u16 reg_offset;
+       u32 reg_mask_and;
+       u32 reg_mask_or;
+};
+
+enum hpx_type3_dev_type {
+       HPX_TYPE_ENDPOINT       = BIT(0),
+       HPX_TYPE_LEG_END        = BIT(1),
+       HPX_TYPE_RC_END         = BIT(2),
+       HPX_TYPE_RC_EC          = BIT(3),
+       HPX_TYPE_ROOT_PORT      = BIT(4),
+       HPX_TYPE_UPSTREAM       = BIT(5),
+       HPX_TYPE_DOWNSTREAM     = BIT(6),
+       HPX_TYPE_PCI_BRIDGE     = BIT(7),
+       HPX_TYPE_PCIE_BRIDGE    = BIT(8),
+};
+
+static u16 hpx3_device_type(struct pci_dev *dev)
+{
+       u16 pcie_type = pci_pcie_type(dev);
+       const int pcie_to_hpx3_type[] = {
+               [PCI_EXP_TYPE_ENDPOINT]    = HPX_TYPE_ENDPOINT,
+               [PCI_EXP_TYPE_LEG_END]     = HPX_TYPE_LEG_END,
+               [PCI_EXP_TYPE_RC_END]      = HPX_TYPE_RC_END,
+               [PCI_EXP_TYPE_RC_EC]       = HPX_TYPE_RC_EC,
+               [PCI_EXP_TYPE_ROOT_PORT]   = HPX_TYPE_ROOT_PORT,
+               [PCI_EXP_TYPE_UPSTREAM]    = HPX_TYPE_UPSTREAM,
+               [PCI_EXP_TYPE_DOWNSTREAM]  = HPX_TYPE_DOWNSTREAM,
+               [PCI_EXP_TYPE_PCI_BRIDGE]  = HPX_TYPE_PCI_BRIDGE,
+               [PCI_EXP_TYPE_PCIE_BRIDGE] = HPX_TYPE_PCIE_BRIDGE,
+       };
+
+       if (pcie_type >= ARRAY_SIZE(pcie_to_hpx3_type))
+               return 0;
+
+       return pcie_to_hpx3_type[pcie_type];
+}
+
+enum hpx_type3_fn_type {
+       HPX_FN_NORMAL           = BIT(0),
+       HPX_FN_SRIOV_PHYS       = BIT(1),
+       HPX_FN_SRIOV_VIRT       = BIT(2),
+};
+
+static u8 hpx3_function_type(struct pci_dev *dev)
+{
+       if (dev->is_virtfn)
+               return HPX_FN_SRIOV_VIRT;
+       else if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV) > 0)
+               return HPX_FN_SRIOV_PHYS;
+       else
+               return HPX_FN_NORMAL;
+}
+
+static bool hpx3_cap_ver_matches(u8 pcie_cap_id, u8 hpx3_cap_id)
+{
+       u8 cap_ver = hpx3_cap_id & 0xf;
+
+       if ((hpx3_cap_id & BIT(4)) && cap_ver >= pcie_cap_id)
+               return true;
+       else if (cap_ver == pcie_cap_id)
+               return true;
+
+       return false;
+}
+
+enum hpx_type3_cfg_loc {
+       HPX_CFG_PCICFG          = 0,
+       HPX_CFG_PCIE_CAP        = 1,
+       HPX_CFG_PCIE_CAP_EXT    = 2,
+       HPX_CFG_VEND_CAP        = 3,
+       HPX_CFG_DVSEC           = 4,
+       HPX_CFG_MAX,
+};
+
+static void program_hpx_type3_register(struct pci_dev *dev,
+                                      const struct hpx_type3 *reg)
+{
+       u32 match_reg, write_reg, header, orig_value;
+       u16 pos;
+
+       if (!(hpx3_device_type(dev) & reg->device_type))
+               return;
+
+       if (!(hpx3_function_type(dev) & reg->function_type))
+               return;
+
+       switch (reg->config_space_location) {
+       case HPX_CFG_PCICFG:
+               pos = 0;
+               break;
+       case HPX_CFG_PCIE_CAP:
+               pos = pci_find_capability(dev, reg->pci_exp_cap_id);
+               if (pos == 0)
+                       return;
+
+               break;
+       case HPX_CFG_PCIE_CAP_EXT:
+               pos = pci_find_ext_capability(dev, reg->pci_exp_cap_id);
+               if (pos == 0)
+                       return;
+
+               pci_read_config_dword(dev, pos, &header);
+               if (!hpx3_cap_ver_matches(PCI_EXT_CAP_VER(header),
+                                         reg->pci_exp_cap_ver))
+                       return;
+
+               break;
+       case HPX_CFG_VEND_CAP:  /* Fall through */
+       case HPX_CFG_DVSEC:     /* Fall through */
+       default:
+               pci_warn(dev, "Encountered _HPX type 3 with unsupported config space location");
+               return;
+       }
+
+       pci_read_config_dword(dev, pos + reg->match_offset, &match_reg);
+
+       if ((match_reg & reg->match_mask_and) != reg->match_value)
+               return;
+
+       pci_read_config_dword(dev, pos + reg->reg_offset, &write_reg);
+       orig_value = write_reg;
+       write_reg &= reg->reg_mask_and;
+       write_reg |= reg->reg_mask_or;
+
+       if (orig_value == write_reg)
+               return;
+
+       pci_write_config_dword(dev, pos + reg->reg_offset, write_reg);
+
+       pci_dbg(dev, "Applied _HPX3 at [0x%x]: 0x%08x -> 0x%08x",
+               pos, orig_value, write_reg);
+}
+
+static void program_hpx_type3(struct pci_dev *dev, struct hpx_type3 *hpx)
+{
+       if (!hpx)
+               return;
+
+       if (!pci_is_pcie(dev))
+               return;
+
+       program_hpx_type3_register(dev, hpx);
+}
+
 static void parse_hpx3_register(struct hpx_type3 *hpx3_reg,
                                union acpi_object *reg_fields)
 {
@@ -233,8 +584,7 @@ static void parse_hpx3_register(struct hpx_type3 *hpx3_reg,
 }
 
 static acpi_status program_type3_hpx_record(struct pci_dev *dev,
-                                          union acpi_object *record,
-                                          const struct hotplug_program_ops *hp_ops)
+                                          union acpi_object *record)
 {
        union acpi_object *fields = record->package.elements;
        u32 desc_count, expected_length, revision;
@@ -258,7 +608,7 @@ static acpi_status program_type3_hpx_record(struct pci_dev *dev,
                for (i = 0; i < desc_count; i++) {
                        reg_fields = fields + 3 + i * 14;
                        parse_hpx3_register(&hpx3, reg_fields);
-                       hp_ops->program_type3(dev, &hpx3);
+                       program_hpx_type3(dev, &hpx3);
                }
 
                break;
@@ -271,15 +621,14 @@ static acpi_status program_type3_hpx_record(struct pci_dev *dev,
        return AE_OK;
 }
 
-static acpi_status acpi_run_hpx(struct pci_dev *dev, acpi_handle handle,
-                               const struct hotplug_program_ops *hp_ops)
+static acpi_status acpi_run_hpx(struct pci_dev *dev, acpi_handle handle)
 {
        acpi_status status;
        struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
        union acpi_object *package, *record, *fields;
-       struct hpp_type0 hpx0;
-       struct hpp_type1 hpx1;
-       struct hpp_type2 hpx2;
+       struct hpx_type0 hpx0;
+       struct hpx_type1 hpx1;
+       struct hpx_type2 hpx2;
        u32 type;
        int i;
 
@@ -314,24 +663,24 @@ static acpi_status acpi_run_hpx(struct pci_dev *dev, acpi_handle handle,
                        status = decode_type0_hpx_record(record, &hpx0);
                        if (ACPI_FAILURE(status))
                                goto exit;
-                       hp_ops->program_type0(dev, &hpx0);
+                       program_hpx_type0(dev, &hpx0);
                        break;
                case 1:
                        memset(&hpx1, 0, sizeof(hpx1));
                        status = decode_type1_hpx_record(record, &hpx1);
                        if (ACPI_FAILURE(status))
                                goto exit;
-                       hp_ops->program_type1(dev, &hpx1);
+                       program_hpx_type1(dev, &hpx1);
                        break;
                case 2:
                        memset(&hpx2, 0, sizeof(hpx2));
                        status = decode_type2_hpx_record(record, &hpx2);
                        if (ACPI_FAILURE(status))
                                goto exit;
-                       hp_ops->program_type2(dev, &hpx2);
+                       program_hpx_type2(dev, &hpx2);
                        break;
                case 3:
-                       status = program_type3_hpx_record(dev, record, hp_ops);
+                       status = program_type3_hpx_record(dev, record);
                        if (ACPI_FAILURE(status))
                                goto exit;
                        break;
@@ -347,16 +696,15 @@ static acpi_status acpi_run_hpx(struct pci_dev *dev, acpi_handle handle,
        return status;
 }
 
-static acpi_status acpi_run_hpp(struct pci_dev *dev, acpi_handle handle,
-                               const struct hotplug_program_ops *hp_ops)
+static acpi_status acpi_run_hpp(struct pci_dev *dev, acpi_handle handle)
 {
        acpi_status status;
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
        union acpi_object *package, *fields;
-       struct hpp_type0 hpp0;
+       struct hpx_type0 hpx0;
        int i;
 
-       memset(&hpp0, 0, sizeof(hpp0));
+       memset(&hpx0, 0, sizeof(hpx0));
 
        status = acpi_evaluate_object(handle, "_HPP", NULL, &buffer);
        if (ACPI_FAILURE(status))
@@ -377,26 +725,24 @@ static acpi_status acpi_run_hpp(struct pci_dev *dev, acpi_handle handle,
                }
        }
 
-       hpp0.revision        = 1;
-       hpp0.cache_line_size = fields[0].integer.value;
-       hpp0.latency_timer   = fields[1].integer.value;
-       hpp0.enable_serr     = fields[2].integer.value;
-       hpp0.enable_perr     = fields[3].integer.value;
+       hpx0.revision        = 1;
+       hpx0.cache_line_size = fields[0].integer.value;
+       hpx0.latency_timer   = fields[1].integer.value;
+       hpx0.enable_serr     = fields[2].integer.value;
+       hpx0.enable_perr     = fields[3].integer.value;
 
-       hp_ops->program_type0(dev, &hpp0);
+       program_hpx_type0(dev, &hpx0);
 
 exit:
        kfree(buffer.pointer);
        return status;
 }
 
-/* pci_get_hp_params
+/* pci_acpi_program_hp_params
  *
  * @dev - the pci_dev for which we want parameters
- * @hpp - allocated by the caller
  */
-int pci_acpi_program_hp_params(struct pci_dev *dev,
-                              const struct hotplug_program_ops *hp_ops)
+int pci_acpi_program_hp_params(struct pci_dev *dev)
 {
        acpi_status status;
        acpi_handle handle, phandle;
@@ -419,10 +765,10 @@ int pci_acpi_program_hp_params(struct pci_dev *dev,
         * this pci dev.
         */
        while (handle) {
-               status = acpi_run_hpx(dev, handle, hp_ops);
+               status = acpi_run_hpx(dev, handle);
                if (ACPI_SUCCESS(status))
                        return 0;
-               status = acpi_run_hpp(dev, handle, hp_ops);
+               status = acpi_run_hpp(dev, handle);
                if (ACPI_SUCCESS(status))
                        return 0;
                if (acpi_is_root_bridge(handle))
index 06083b86d4f45607271c318088d03bc50ddfc4b5..5fd90105510d93c89e01c5550b5cfe2c689886c5 100644 (file)
@@ -38,7 +38,7 @@ struct pci_bridge_reg_behavior {
        u32 rsvd;
 };
 
-const static struct pci_bridge_reg_behavior pci_regs_behavior[] = {
+static const struct pci_bridge_reg_behavior pci_regs_behavior[] = {
        [PCI_VENDOR_ID / 4] = { .ro = ~0 },
        [PCI_COMMAND / 4] = {
                .rw = (PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
@@ -173,7 +173,7 @@ const static struct pci_bridge_reg_behavior pci_regs_behavior[] = {
        },
 };
 
-const static struct pci_bridge_reg_behavior pcie_cap_regs_behavior[] = {
+static const struct pci_bridge_reg_behavior pcie_cap_regs_behavior[] = {
        [PCI_CAP_LIST_ID / 4] = {
                /*
                 * Capability ID, Next Capability Pointer and
index 965c721041508328702a0d97696672c692632476..868e351092844f8bf63f3c730cf50226833efea7 100644 (file)
@@ -464,9 +464,7 @@ static ssize_t dev_rescan_store(struct device *dev,
        }
        return count;
 }
-static struct device_attribute dev_rescan_attr = __ATTR(rescan,
-                                                       (S_IWUSR|S_IWGRP),
-                                                       NULL, dev_rescan_store);
+static DEVICE_ATTR_WO(dev_rescan);
 
 static ssize_t remove_store(struct device *dev, struct device_attribute *attr,
                            const char *buf, size_t count)
@@ -480,13 +478,12 @@ static ssize_t remove_store(struct device *dev, struct device_attribute *attr,
                pci_stop_and_remove_bus_device_locked(to_pci_dev(dev));
        return count;
 }
-static struct device_attribute dev_remove_attr = __ATTR_IGNORE_LOCKDEP(remove,
-                                                       (S_IWUSR|S_IWGRP),
-                                                       NULL, remove_store);
+static DEVICE_ATTR_IGNORE_LOCKDEP(remove, 0220, NULL,
+                                 remove_store);
 
-static ssize_t dev_bus_rescan_store(struct device *dev,
-                                   struct device_attribute *attr,
-                                   const char *buf, size_t count)
+static ssize_t bus_rescan_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count)
 {
        unsigned long val;
        struct pci_bus *bus = to_pci_bus(dev);
@@ -504,7 +501,7 @@ static ssize_t dev_bus_rescan_store(struct device *dev,
        }
        return count;
 }
-static DEVICE_ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_bus_rescan_store);
+static DEVICE_ATTR_WO(bus_rescan);
 
 #if defined(CONFIG_PM) && defined(CONFIG_ACPI)
 static ssize_t d3cold_allowed_store(struct device *dev,
@@ -551,154 +548,6 @@ static ssize_t devspec_show(struct device *dev,
 static DEVICE_ATTR_RO(devspec);
 #endif
 
-#ifdef CONFIG_PCI_IOV
-static ssize_t sriov_totalvfs_show(struct device *dev,
-                                  struct device_attribute *attr,
-                                  char *buf)
-{
-       struct pci_dev *pdev = to_pci_dev(dev);
-
-       return sprintf(buf, "%u\n", pci_sriov_get_totalvfs(pdev));
-}
-
-
-static ssize_t sriov_numvfs_show(struct device *dev,
-                                struct device_attribute *attr,
-                                char *buf)
-{
-       struct pci_dev *pdev = to_pci_dev(dev);
-
-       return sprintf(buf, "%u\n", pdev->sriov->num_VFs);
-}
-
-/*
- * num_vfs > 0; number of VFs to enable
- * num_vfs = 0; disable all VFs
- *
- * Note: SRIOV spec doesn't allow partial VF
- *       disable, so it's all or none.
- */
-static ssize_t sriov_numvfs_store(struct device *dev,
-                                 struct device_attribute *attr,
-                                 const char *buf, size_t count)
-{
-       struct pci_dev *pdev = to_pci_dev(dev);
-       int ret;
-       u16 num_vfs;
-
-       ret = kstrtou16(buf, 0, &num_vfs);
-       if (ret < 0)
-               return ret;
-
-       if (num_vfs > pci_sriov_get_totalvfs(pdev))
-               return -ERANGE;
-
-       device_lock(&pdev->dev);
-
-       if (num_vfs == pdev->sriov->num_VFs)
-               goto exit;
-
-       /* is PF driver loaded w/callback */
-       if (!pdev->driver || !pdev->driver->sriov_configure) {
-               pci_info(pdev, "Driver doesn't support SRIOV configuration via sysfs\n");
-               ret = -ENOENT;
-               goto exit;
-       }
-
-       if (num_vfs == 0) {
-               /* disable VFs */
-               ret = pdev->driver->sriov_configure(pdev, 0);
-               goto exit;
-       }
-
-       /* enable VFs */
-       if (pdev->sriov->num_VFs) {
-               pci_warn(pdev, "%d VFs already enabled. Disable before enabling %d VFs\n",
-                        pdev->sriov->num_VFs, num_vfs);
-               ret = -EBUSY;
-               goto exit;
-       }
-
-       ret = pdev->driver->sriov_configure(pdev, num_vfs);
-       if (ret < 0)
-               goto exit;
-
-       if (ret != num_vfs)
-               pci_warn(pdev, "%d VFs requested; only %d enabled\n",
-                        num_vfs, ret);
-
-exit:
-       device_unlock(&pdev->dev);
-
-       if (ret < 0)
-               return ret;
-
-       return count;
-}
-
-static ssize_t sriov_offset_show(struct device *dev,
-                                struct device_attribute *attr,
-                                char *buf)
-{
-       struct pci_dev *pdev = to_pci_dev(dev);
-
-       return sprintf(buf, "%u\n", pdev->sriov->offset);
-}
-
-static ssize_t sriov_stride_show(struct device *dev,
-                                struct device_attribute *attr,
-                                char *buf)
-{
-       struct pci_dev *pdev = to_pci_dev(dev);
-
-       return sprintf(buf, "%u\n", pdev->sriov->stride);
-}
-
-static ssize_t sriov_vf_device_show(struct device *dev,
-                                   struct device_attribute *attr,
-                                   char *buf)
-{
-       struct pci_dev *pdev = to_pci_dev(dev);
-
-       return sprintf(buf, "%x\n", pdev->sriov->vf_device);
-}
-
-static ssize_t sriov_drivers_autoprobe_show(struct device *dev,
-                                           struct device_attribute *attr,
-                                           char *buf)
-{
-       struct pci_dev *pdev = to_pci_dev(dev);
-
-       return sprintf(buf, "%u\n", pdev->sriov->drivers_autoprobe);
-}
-
-static ssize_t sriov_drivers_autoprobe_store(struct device *dev,
-                                            struct device_attribute *attr,
-                                            const char *buf, size_t count)
-{
-       struct pci_dev *pdev = to_pci_dev(dev);
-       bool drivers_autoprobe;
-
-       if (kstrtobool(buf, &drivers_autoprobe) < 0)
-               return -EINVAL;
-
-       pdev->sriov->drivers_autoprobe = drivers_autoprobe;
-
-       return count;
-}
-
-static struct device_attribute sriov_totalvfs_attr = __ATTR_RO(sriov_totalvfs);
-static struct device_attribute sriov_numvfs_attr =
-               __ATTR(sriov_numvfs, (S_IRUGO|S_IWUSR|S_IWGRP),
-                      sriov_numvfs_show, sriov_numvfs_store);
-static struct device_attribute sriov_offset_attr = __ATTR_RO(sriov_offset);
-static struct device_attribute sriov_stride_attr = __ATTR_RO(sriov_stride);
-static struct device_attribute sriov_vf_device_attr = __ATTR_RO(sriov_vf_device);
-static struct device_attribute sriov_drivers_autoprobe_attr =
-               __ATTR(sriov_drivers_autoprobe, (S_IRUGO|S_IWUSR|S_IWGRP),
-                      sriov_drivers_autoprobe_show, sriov_drivers_autoprobe_store);
-#endif /* CONFIG_PCI_IOV */
-
 static ssize_t driver_override_store(struct device *dev,
                                     struct device_attribute *attr,
                                     const char *buf, size_t count)
@@ -792,7 +641,7 @@ static struct attribute *pcie_dev_attrs[] = {
 };
 
 static struct attribute *pcibus_attrs[] = {
-       &dev_attr_rescan.attr,
+       &dev_attr_bus_rescan.attr,
        &dev_attr_cpuaffinity.attr,
        &dev_attr_cpulistaffinity.attr,
        NULL,
@@ -820,7 +669,7 @@ static ssize_t boot_vga_show(struct device *dev, struct device_attribute *attr,
                !!(pdev->resource[PCI_ROM_RESOURCE].flags &
                   IORESOURCE_ROM_SHADOW));
 }
-static struct device_attribute vga_attr = __ATTR_RO(boot_vga);
+static DEVICE_ATTR_RO(boot_vga);
 
 static ssize_t pci_read_config(struct file *filp, struct kobject *kobj,
                               struct bin_attribute *bin_attr, char *buf,
@@ -1085,7 +934,7 @@ void pci_create_legacy_files(struct pci_bus *b)
        sysfs_bin_attr_init(b->legacy_io);
        b->legacy_io->attr.name = "legacy_io";
        b->legacy_io->size = 0xffff;
-       b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
+       b->legacy_io->attr.mode = 0600;
        b->legacy_io->read = pci_read_legacy_io;
        b->legacy_io->write = pci_write_legacy_io;
        b->legacy_io->mmap = pci_mmap_legacy_io;
@@ -1099,7 +948,7 @@ void pci_create_legacy_files(struct pci_bus *b)
        sysfs_bin_attr_init(b->legacy_mem);
        b->legacy_mem->attr.name = "legacy_mem";
        b->legacy_mem->size = 1024*1024;
-       b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR;
+       b->legacy_mem->attr.mode = 0600;
        b->legacy_mem->mmap = pci_mmap_legacy_mem;
        pci_adjust_legacy_attr(b, pci_mmap_mem);
        error = device_create_bin_file(&b->dev, b->legacy_mem);
@@ -1306,7 +1155,7 @@ static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine)
                }
        }
        res_attr->attr.name = res_attr_name;
-       res_attr->attr.mode = S_IRUSR | S_IWUSR;
+       res_attr->attr.mode = 0600;
        res_attr->size = pci_resource_len(pdev, num);
        res_attr->private = (void *)(unsigned long)num;
        retval = sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
@@ -1419,7 +1268,7 @@ static ssize_t pci_read_rom(struct file *filp, struct kobject *kobj,
 static const struct bin_attribute pci_config_attr = {
        .attr = {
                .name = "config",
-               .mode = S_IRUGO | S_IWUSR,
+               .mode = 0644,
        },
        .size = PCI_CFG_SPACE_SIZE,
        .read = pci_read_config,
@@ -1429,7 +1278,7 @@ static const struct bin_attribute pci_config_attr = {
 static const struct bin_attribute pcie_config_attr = {
        .attr = {
                .name = "config",
-               .mode = S_IRUGO | S_IWUSR,
+               .mode = 0644,
        },
        .size = PCI_CFG_SPACE_EXP_SIZE,
        .read = pci_read_config,
@@ -1458,7 +1307,7 @@ static ssize_t reset_store(struct device *dev, struct device_attribute *attr,
        return count;
 }
 
-static struct device_attribute reset_attr = __ATTR(reset, 0200, NULL, reset_store);
+static DEVICE_ATTR(reset, 0200, NULL, reset_store);
 
 static int pci_create_capabilities_sysfs(struct pci_dev *dev)
 {
@@ -1468,7 +1317,7 @@ static int pci_create_capabilities_sysfs(struct pci_dev *dev)
        pcie_aspm_create_sysfs_dev_files(dev);
 
        if (dev->reset_fn) {
-               retval = device_create_file(&dev->dev, &reset_attr);
+               retval = device_create_file(&dev->dev, &dev_attr_reset);
                if (retval)
                        goto error;
        }
@@ -1511,7 +1360,7 @@ int __must_check pci_create_sysfs_dev_files(struct pci_dev *pdev)
                sysfs_bin_attr_init(attr);
                attr->size = rom_size;
                attr->attr.name = "rom";
-               attr->attr.mode = S_IRUSR | S_IWUSR;
+               attr->attr.mode = 0600;
                attr->read = pci_read_rom;
                attr->write = pci_write_rom;
                retval = sysfs_create_bin_file(&pdev->dev.kobj, attr);
@@ -1553,7 +1402,7 @@ static void pci_remove_capabilities_sysfs(struct pci_dev *dev)
        pcie_vpd_remove_sysfs_dev_files(dev);
        pcie_aspm_remove_sysfs_dev_files(dev);
        if (dev->reset_fn) {
-               device_remove_file(&dev->dev, &reset_attr);
+               device_remove_file(&dev->dev, &dev_attr_reset);
                dev->reset_fn = 0;
        }
 }
@@ -1606,7 +1455,7 @@ static int __init pci_sysfs_init(void)
 late_initcall(pci_sysfs_init);
 
 static struct attribute *pci_dev_dev_attrs[] = {
-       &vga_attr.attr,
+       &dev_attr_boot_vga.attr,
        NULL,
 };
 
@@ -1616,7 +1465,7 @@ static umode_t pci_dev_attrs_are_visible(struct kobject *kobj,
        struct device *dev = kobj_to_dev(kobj);
        struct pci_dev *pdev = to_pci_dev(dev);
 
-       if (a == &vga_attr.attr)
+       if (a == &dev_attr_boot_vga.attr)
                if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
                        return 0;
 
@@ -1624,8 +1473,8 @@ static umode_t pci_dev_attrs_are_visible(struct kobject *kobj,
 }
 
 static struct attribute *pci_dev_hp_attrs[] = {
-       &dev_remove_attr.attr,
-       &dev_rescan_attr.attr,
+       &dev_attr_remove.attr,
+       &dev_attr_dev_rescan.attr,
        NULL,
 };
 
@@ -1697,34 +1546,6 @@ static const struct attribute_group pci_dev_hp_attr_group = {
        .is_visible = pci_dev_hp_attrs_are_visible,
 };
 
-#ifdef CONFIG_PCI_IOV
-static struct attribute *sriov_dev_attrs[] = {
-       &sriov_totalvfs_attr.attr,
-       &sriov_numvfs_attr.attr,
-       &sriov_offset_attr.attr,
-       &sriov_stride_attr.attr,
-       &sriov_vf_device_attr.attr,
-       &sriov_drivers_autoprobe_attr.attr,
-       NULL,
-};
-
-static umode_t sriov_attrs_are_visible(struct kobject *kobj,
-                                      struct attribute *a, int n)
-{
-       struct device *dev = kobj_to_dev(kobj);
-
-       if (!dev_is_pf(dev))
-               return 0;
-
-       return a->mode;
-}
-
-static const struct attribute_group sriov_dev_attr_group = {
-       .attrs = sriov_dev_attrs,
-       .is_visible = sriov_attrs_are_visible,
-};
-#endif /* CONFIG_PCI_IOV */
-
 static const struct attribute_group pci_dev_attr_group = {
        .attrs = pci_dev_dev_attrs,
        .is_visible = pci_dev_attrs_are_visible,
index 5836eb576d961e38ae342430ac03bfafbe564efe..80fe2d24fa37afaccc1dc7ea2309e92f8940d660 100644 (file)
@@ -890,8 +890,8 @@ static int pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state)
 
        pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
        dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK);
-       if (dev->current_state != state && printk_ratelimit())
-               pci_info(dev, "Refused to change power state, currently in D%d\n",
+       if (dev->current_state != state)
+               pci_info_ratelimited(dev, "Refused to change power state, currently in D%d\n",
                         dev->current_state);
 
        /*
@@ -3576,7 +3576,7 @@ int pci_enable_atomic_ops_to_root(struct pci_dev *dev, u32 cap_mask)
                }
 
                /* Ensure upstream ports don't block AtomicOps on egress */
-               if (!bridge->has_secondary_link) {
+               if (pci_pcie_type(bridge) == PCI_EXP_TYPE_UPSTREAM) {
                        pcie_capability_read_dword(bridge, PCI_EXP_DEVCTL2,
                                                   &ctl2);
                        if (ctl2 & PCI_EXP_DEVCTL2_ATOMIC_EGRESS_BLOCK)
@@ -5944,8 +5944,7 @@ void __weak pci_resource_to_user(const struct pci_dev *dev, int bar,
        *end = rsrc->end;
 }
 
-#define RESOURCE_ALIGNMENT_PARAM_SIZE COMMAND_LINE_SIZE
-static char resource_alignment_param[RESOURCE_ALIGNMENT_PARAM_SIZE] = {0};
+static char *resource_alignment_param;
 static DEFINE_SPINLOCK(resource_alignment_lock);
 
 /**
@@ -5966,7 +5965,7 @@ static resource_size_t pci_specified_resource_alignment(struct pci_dev *dev,
 
        spin_lock(&resource_alignment_lock);
        p = resource_alignment_param;
-       if (!*p && !align)
+       if (!p || !*p)
                goto out;
        if (pci_has_flag(PCI_PROBE_ONLY)) {
                align = 0;
@@ -6130,35 +6129,41 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)
        }
 }
 
-static ssize_t pci_set_resource_alignment_param(const char *buf, size_t count)
+static ssize_t resource_alignment_show(struct bus_type *bus, char *buf)
 {
-       if (count > RESOURCE_ALIGNMENT_PARAM_SIZE - 1)
-               count = RESOURCE_ALIGNMENT_PARAM_SIZE - 1;
-       spin_lock(&resource_alignment_lock);
-       strncpy(resource_alignment_param, buf, count);
-       resource_alignment_param[count] = '\0';
-       spin_unlock(&resource_alignment_lock);
-       return count;
-}
+       size_t count = 0;
 
-static ssize_t pci_get_resource_alignment_param(char *buf, size_t size)
-{
-       size_t count;
        spin_lock(&resource_alignment_lock);
-       count = snprintf(buf, size, "%s", resource_alignment_param);
+       if (resource_alignment_param)
+               count = snprintf(buf, PAGE_SIZE, "%s", resource_alignment_param);
        spin_unlock(&resource_alignment_lock);
-       return count;
-}
 
-static ssize_t resource_alignment_show(struct bus_type *bus, char *buf)
-{
-       return pci_get_resource_alignment_param(buf, PAGE_SIZE);
+       /*
+        * When set by the command line, resource_alignment_param will not
+        * have a trailing line feed, which is ugly. So conditionally add
+        * it here.
+        */
+       if (count >= 2 && buf[count - 2] != '\n' && count < PAGE_SIZE - 1) {
+               buf[count - 1] = '\n';
+               buf[count++] = 0;
+       }
+
+       return count;
 }
 
 static ssize_t resource_alignment_store(struct bus_type *bus,
                                        const char *buf, size_t count)
 {
-       return pci_set_resource_alignment_param(buf, count);
+       char *param = kstrndup(buf, count, GFP_KERNEL);
+
+       if (!param)
+               return -ENOMEM;
+
+       spin_lock(&resource_alignment_lock);
+       kfree(resource_alignment_param);
+       resource_alignment_param = param;
+       spin_unlock(&resource_alignment_lock);
+       return count;
 }
 
 static BUS_ATTR_RW(resource_alignment);
@@ -6287,8 +6292,7 @@ static int __init pci_setup(char *str)
                        } else if (!strncmp(str, "cbmemsize=", 10)) {
                                pci_cardbus_mem_size = memparse(str + 10, &str);
                        } else if (!strncmp(str, "resource_alignment=", 19)) {
-                               pci_set_resource_alignment_param(str + 19,
-                                                       strlen(str + 19));
+                               resource_alignment_param = str + 19;
                        } else if (!strncmp(str, "ecrc=", 5)) {
                                pcie_ecrc_get_policy(str + 5);
                        } else if (!strncmp(str, "hpiosize=", 9)) {
@@ -6323,15 +6327,18 @@ static int __init pci_setup(char *str)
 early_param("pci", pci_setup);
 
 /*
- * 'disable_acs_redir_param' is initialized in pci_setup(), above, to point
- * to data in the __initdata section which will be freed after the init
- * sequence is complete. We can't allocate memory in pci_setup() because some
- * architectures do not have any memory allocation service available during
- * an early_param() call. So we allocate memory and copy the variable here
- * before the init section is freed.
+ * 'resource_alignment_param' and 'disable_acs_redir_param' are initialized
+ * in pci_setup(), above, to point to data in the __initdata section which
+ * will be freed after the init sequence is complete. We can't allocate memory
+ * in pci_setup() because some architectures do not have any memory allocation
+ * service available during an early_param() call. So we allocate memory and
+ * copy the variable here before the init section is freed.
+ *
  */
 static int __init pci_realloc_setup_params(void)
 {
+       resource_alignment_param = kstrdup(resource_alignment_param,
+                                          GFP_KERNEL);
        disable_acs_redir_param = kstrdup(disable_acs_redir_param, GFP_KERNEL);
 
        return 0;
index 1be03a97cb92c1ce9486a4b6ea0f037f7c18067f..0113343cfd1e7eae8adf7595e93a876786d96ef4 100644 (file)
@@ -39,6 +39,11 @@ int pci_probe_reset_function(struct pci_dev *dev);
 int pci_bridge_secondary_bus_reset(struct pci_dev *dev);
 int pci_bus_error_reset(struct pci_dev *dev);
 
+#define PCI_PM_D2_DELAY         200
+#define PCI_PM_D3_WAIT          10
+#define PCI_PM_D3COLD_WAIT      100
+#define PCI_PM_BUS_WAIT         50
+
 /**
  * struct pci_platform_pm_ops - Firmware PM callbacks
  *
@@ -84,6 +89,8 @@ void pci_power_up(struct pci_dev *dev);
 void pci_disable_enabled_device(struct pci_dev *dev);
 int pci_finish_runtime_suspend(struct pci_dev *dev);
 void pcie_clear_root_pme_status(struct pci_dev *dev);
+bool pci_check_pme_status(struct pci_dev *dev);
+void pci_pme_wakeup_bus(struct pci_bus *bus);
 int __pci_pme_wakeup(struct pci_dev *dev, void *ign);
 void pci_pme_restore(struct pci_dev *dev);
 bool pci_dev_need_resume(struct pci_dev *dev);
@@ -118,11 +125,25 @@ static inline bool pci_power_manageable(struct pci_dev *pci_dev)
        return !pci_has_subordinate(pci_dev) || pci_dev->bridge_d3;
 }
 
+static inline bool pcie_downstream_port(const struct pci_dev *dev)
+{
+       int type = pci_pcie_type(dev);
+
+       return type == PCI_EXP_TYPE_ROOT_PORT ||
+              type == PCI_EXP_TYPE_DOWNSTREAM ||
+              type == PCI_EXP_TYPE_PCIE_BRIDGE;
+}
+
 int pci_vpd_init(struct pci_dev *dev);
 void pci_vpd_release(struct pci_dev *dev);
 void pcie_vpd_create_sysfs_dev_files(struct pci_dev *dev);
 void pcie_vpd_remove_sysfs_dev_files(struct pci_dev *dev);
 
+/* PCI Virtual Channel */
+int pci_save_vc_state(struct pci_dev *dev);
+void pci_restore_vc_state(struct pci_dev *dev);
+void pci_allocate_vc_save_buffers(struct pci_dev *dev);
+
 /* PCI /proc functions */
 #ifdef CONFIG_PROC_FS
 int pci_proc_attach_device(struct pci_dev *dev);
@@ -196,6 +217,9 @@ extern const struct attribute_group *pcibus_groups[];
 extern const struct device_type pci_dev_type;
 extern const struct attribute_group *pci_bus_groups[];
 
+extern unsigned long pci_hotplug_io_size;
+extern unsigned long pci_hotplug_mem_size;
+extern unsigned long pci_hotplug_bus_size;
 
 /**
  * pci_match_one_device - Tell if a PCI device structure has a matching
@@ -236,6 +260,9 @@ enum pci_bar_type {
        pci_bar_mem64,          /* A 64-bit memory BAR */
 };
 
+struct device *pci_get_host_bridge_device(struct pci_dev *dev);
+void pci_put_host_bridge_device(struct device *dev);
+
 int pci_configure_extended_tags(struct pci_dev *dev, void *ign);
 bool pci_bus_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *pl,
                                int crs_timeout);
@@ -256,6 +283,8 @@ bool pci_bus_clip_resource(struct pci_dev *dev, int idx);
 
 void pci_reassigndev_resource_alignment(struct pci_dev *dev);
 void pci_disable_bridge_window(struct pci_dev *dev);
+struct pci_bus *pci_bus_get(struct pci_bus *bus);
+void pci_bus_put(struct pci_bus *bus);
 
 /* PCIe link information */
 #define PCIE_SPEED2STR(speed) \
@@ -279,6 +308,7 @@ u32 pcie_bandwidth_capable(struct pci_dev *dev, enum pci_bus_speed *speed,
                           enum pcie_link_width *width);
 void __pcie_print_link_status(struct pci_dev *dev, bool verbose);
 void pcie_report_downtraining(struct pci_dev *dev);
+void pcie_update_link_speed(struct pci_bus *bus, u16 link_status);
 
 /* Single Root I/O Virtualization */
 struct pci_sriov {
@@ -418,11 +448,12 @@ static inline void pci_restore_dpc_state(struct pci_dev *dev) {}
 #endif
 
 #ifdef CONFIG_PCI_ATS
+/* Address Translation Service */
+void pci_ats_init(struct pci_dev *dev);
 void pci_restore_ats_state(struct pci_dev *dev);
 #else
-static inline void pci_restore_ats_state(struct pci_dev *dev)
-{
-}
+static inline void pci_ats_init(struct pci_dev *d) { }
+static inline void pci_restore_ats_state(struct pci_dev *dev) { }
 #endif /* CONFIG_PCI_ATS */
 
 #ifdef CONFIG_PCI_IOV
@@ -433,7 +464,7 @@ void pci_iov_update_resource(struct pci_dev *dev, int resno);
 resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno);
 void pci_restore_iov_state(struct pci_dev *dev);
 int pci_iov_bus_range(struct pci_bus *bus);
-
+extern const struct attribute_group sriov_dev_attr_group;
 #else
 static inline int pci_iov_init(struct pci_dev *dev)
 {
@@ -519,10 +550,21 @@ static inline void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev) { }
 static inline void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev) { }
 #endif
 
+#ifdef CONFIG_PCIE_ECRC
+void pcie_set_ecrc_checking(struct pci_dev *dev);
+void pcie_ecrc_get_policy(char *str);
+#else
+static inline void pcie_set_ecrc_checking(struct pci_dev *dev) { }
+static inline void pcie_ecrc_get_policy(char *str) { }
+#endif
+
 #ifdef CONFIG_PCIE_PTM
 void pci_ptm_init(struct pci_dev *dev);
+int pci_enable_ptm(struct pci_dev *dev, u8 *granularity);
 #else
 static inline void pci_ptm_init(struct pci_dev *dev) { }
+static inline int pci_enable_ptm(struct pci_dev *dev, u8 *granularity)
+{ return -EINVAL; }
 #endif
 
 struct pci_dev_reset_methods {
@@ -559,6 +601,10 @@ struct device_node;
 int of_pci_parse_bus_range(struct device_node *node, struct resource *res);
 int of_get_pci_domain_nr(struct device_node *node);
 int of_pci_get_max_link_speed(struct device_node *node);
+void pci_set_of_node(struct pci_dev *dev);
+void pci_release_of_node(struct pci_dev *dev);
+void pci_set_bus_of_node(struct pci_bus *bus);
+void pci_release_bus_of_node(struct pci_bus *bus);
 
 #else
 static inline int
@@ -578,6 +624,11 @@ of_pci_get_max_link_speed(struct device_node *node)
 {
        return -EINVAL;
 }
+
+static inline void pci_set_of_node(struct pci_dev *dev) { }
+static inline void pci_release_of_node(struct pci_dev *dev) { }
+static inline void pci_set_bus_of_node(struct pci_bus *bus) { }
+static inline void pci_release_bus_of_node(struct pci_bus *bus) { }
 #endif /* CONFIG_OF */
 
 #if defined(CONFIG_OF_ADDRESS)
@@ -608,4 +659,13 @@ static inline void pci_aer_clear_fatal_status(struct pci_dev *dev) { }
 static inline void pci_aer_clear_device_status(struct pci_dev *dev) { }
 #endif
 
+#ifdef CONFIG_ACPI
+int pci_acpi_program_hp_params(struct pci_dev *dev);
+#else
+static inline int pci_acpi_program_hp_params(struct pci_dev *dev)
+{
+       return -ENODEV;
+}
+#endif
+
 #endif /* DRIVERS_PCI_H */
index e44af7f4d37ff48c050daeaeab33326ec1a52067..55a6951cedd167d2a26e983eef993dbb555fdb20 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/delay.h>
-#include <linux/pci-aspm.h>
 #include "../pci.h"
 
 #ifdef MODULE_PARAM_PREFIX
@@ -913,10 +912,10 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
 
        /*
         * We allocate pcie_link_state for the component on the upstream
-        * end of a Link, so there's nothing to do unless this device has a
-        * Link on its secondary side.
+        * end of a Link, so there's nothing to do unless this device is
+        * downstream port.
         */
-       if (!pdev->has_secondary_link)
+       if (!pcie_downstream_port(pdev))
                return;
 
        /* VIA has a strange chipset, root port is under a bridge */
@@ -1070,7 +1069,7 @@ static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
        if (!pci_is_pcie(pdev))
                return 0;
 
-       if (pdev->has_secondary_link)
+       if (pcie_downstream_port(pdev))
                parent = pdev;
        if (!parent || !parent->link_state)
                return -EINVAL;
index 773197a12568e1e9d2ebcb1dd4e707de059ccec5..b0e6048a9208d1eef95134a83b35ae17b8f78cf0 100644 (file)
@@ -166,7 +166,7 @@ static pci_ers_result_t reset_link(struct pci_dev *dev, u32 service)
        driver = pcie_port_find_service(dev, service);
        if (driver && driver->reset_link) {
                status = driver->reset_link(dev);
-       } else if (dev->has_secondary_link) {
+       } else if (pcie_downstream_port(dev)) {
                status = default_reset_link(dev);
        } else {
                pci_printk(KERN_DEBUG, dev, "no link-reset support at upstream device %s\n",
index a3c7338fad86413374f0f40c19df6974f82acd46..3bfa57d58402bd8a09a5a346025fa9edb03015e3 100644 (file)
@@ -1431,26 +1431,38 @@ void set_pcie_port_type(struct pci_dev *pdev)
        pci_read_config_word(pdev, pos + PCI_EXP_DEVCAP, &reg16);
        pdev->pcie_mpss = reg16 & PCI_EXP_DEVCAP_PAYLOAD;
 
+       parent = pci_upstream_bridge(pdev);
+       if (!parent)
+               return;
+
        /*
-        * A Root Port or a PCI-to-PCIe bridge is always the upstream end
-        * of a Link.  No PCIe component has two Links.  Two Links are
-        * connected by a Switch that has a Port on each Link and internal
-        * logic to connect the two Ports.
+        * Some systems do not identify their upstream/downstream ports
+        * correctly so detect impossible configurations here and correct
+        * the port type accordingly.
         */
        type = pci_pcie_type(pdev);
-       if (type == PCI_EXP_TYPE_ROOT_PORT ||
-           type == PCI_EXP_TYPE_PCIE_BRIDGE)
-               pdev->has_secondary_link = 1;
-       else if (type == PCI_EXP_TYPE_UPSTREAM ||
-                type == PCI_EXP_TYPE_DOWNSTREAM) {
-               parent = pci_upstream_bridge(pdev);
-
+       if (type == PCI_EXP_TYPE_DOWNSTREAM) {
                /*
-                * Usually there's an upstream device (Root Port or Switch
-                * Downstream Port), but we can't assume one exists.
+                * If pdev claims to be downstream port but the parent
+                * device is also downstream port assume pdev is actually
+                * upstream port.
                 */
-               if (parent && !parent->has_secondary_link)
-                       pdev->has_secondary_link = 1;
+               if (pcie_downstream_port(parent)) {
+                       pci_info(pdev, "claims to be downstream port but is acting as upstream port, correcting type\n");
+                       pdev->pcie_flags_reg &= ~PCI_EXP_FLAGS_TYPE;
+                       pdev->pcie_flags_reg |= PCI_EXP_TYPE_UPSTREAM;
+               }
+       } else if (type == PCI_EXP_TYPE_UPSTREAM) {
+               /*
+                * If pdev claims to be upstream port but the parent
+                * device is also upstream port assume pdev is actually
+                * downstream port.
+                */
+               if (pci_pcie_type(parent) == PCI_EXP_TYPE_UPSTREAM) {
+                       pci_info(pdev, "claims to be upstream port but is acting as downstream port, correcting type\n");
+                       pdev->pcie_flags_reg &= ~PCI_EXP_FLAGS_TYPE;
+                       pdev->pcie_flags_reg |= PCI_EXP_TYPE_DOWNSTREAM;
+               }
        }
 }
 
@@ -1920,275 +1932,6 @@ static void pci_configure_mps(struct pci_dev *dev)
                 p_mps, mps, mpss);
 }
 
-static struct hpp_type0 pci_default_type0 = {
-       .revision = 1,
-       .cache_line_size = 8,
-       .latency_timer = 0x40,
-       .enable_serr = 0,
-       .enable_perr = 0,
-};
-
-static void program_hpp_type0(struct pci_dev *dev, struct hpp_type0 *hpp)
-{
-       u16 pci_cmd, pci_bctl;
-
-       if (!hpp)
-               hpp = &pci_default_type0;
-
-       if (hpp->revision > 1) {
-               pci_warn(dev, "PCI settings rev %d not supported; using defaults\n",
-                        hpp->revision);
-               hpp = &pci_default_type0;
-       }
-
-       pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp->cache_line_size);
-       pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp->latency_timer);
-       pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
-       if (hpp->enable_serr)
-               pci_cmd |= PCI_COMMAND_SERR;
-       if (hpp->enable_perr)
-               pci_cmd |= PCI_COMMAND_PARITY;
-       pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
-
-       /* Program bridge control value */
-       if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
-               pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
-                                     hpp->latency_timer);
-               pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
-               if (hpp->enable_perr)
-                       pci_bctl |= PCI_BRIDGE_CTL_PARITY;
-               pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl);
-       }
-}
-
-static void program_hpp_type1(struct pci_dev *dev, struct hpp_type1 *hpp)
-{
-       int pos;
-
-       if (!hpp)
-               return;
-
-       pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
-       if (!pos)
-               return;
-
-       pci_warn(dev, "PCI-X settings not supported\n");
-}
-
-static bool pcie_root_rcb_set(struct pci_dev *dev)
-{
-       struct pci_dev *rp = pcie_find_root_port(dev);
-       u16 lnkctl;
-
-       if (!rp)
-               return false;
-
-       pcie_capability_read_word(rp, PCI_EXP_LNKCTL, &lnkctl);
-       if (lnkctl & PCI_EXP_LNKCTL_RCB)
-               return true;
-
-       return false;
-}
-
-static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
-{
-       int pos;
-       u32 reg32;
-
-       if (!hpp)
-               return;
-
-       if (!pci_is_pcie(dev))
-               return;
-
-       if (hpp->revision > 1) {
-               pci_warn(dev, "PCIe settings rev %d not supported\n",
-                        hpp->revision);
-               return;
-       }
-
-       /*
-        * Don't allow _HPX to change MPS or MRRS settings.  We manage
-        * those to make sure they're consistent with the rest of the
-        * platform.
-        */
-       hpp->pci_exp_devctl_and |= PCI_EXP_DEVCTL_PAYLOAD |
-                                   PCI_EXP_DEVCTL_READRQ;
-       hpp->pci_exp_devctl_or &= ~(PCI_EXP_DEVCTL_PAYLOAD |
-                                   PCI_EXP_DEVCTL_READRQ);
-
-       /* Initialize Device Control Register */
-       pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL,
-                       ~hpp->pci_exp_devctl_and, hpp->pci_exp_devctl_or);
-
-       /* Initialize Link Control Register */
-       if (pcie_cap_has_lnkctl(dev)) {
-
-               /*
-                * If the Root Port supports Read Completion Boundary of
-                * 128, set RCB to 128.  Otherwise, clear it.
-                */
-               hpp->pci_exp_lnkctl_and |= PCI_EXP_LNKCTL_RCB;
-               hpp->pci_exp_lnkctl_or &= ~PCI_EXP_LNKCTL_RCB;
-               if (pcie_root_rcb_set(dev))
-                       hpp->pci_exp_lnkctl_or |= PCI_EXP_LNKCTL_RCB;
-
-               pcie_capability_clear_and_set_word(dev, PCI_EXP_LNKCTL,
-                       ~hpp->pci_exp_lnkctl_and, hpp->pci_exp_lnkctl_or);
-       }
-
-       /* Find Advanced Error Reporting Enhanced Capability */
-       pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
-       if (!pos)
-               return;
-
-       /* Initialize Uncorrectable Error Mask Register */
-       pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, &reg32);
-       reg32 = (reg32 & hpp->unc_err_mask_and) | hpp->unc_err_mask_or;
-       pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, reg32);
-
-       /* Initialize Uncorrectable Error Severity Register */
-       pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &reg32);
-       reg32 = (reg32 & hpp->unc_err_sever_and) | hpp->unc_err_sever_or;
-       pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, reg32);
-
-       /* Initialize Correctable Error Mask Register */
-       pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg32);
-       reg32 = (reg32 & hpp->cor_err_mask_and) | hpp->cor_err_mask_or;
-       pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg32);
-
-       /* Initialize Advanced Error Capabilities and Control Register */
-       pci_read_config_dword(dev, pos + PCI_ERR_CAP, &reg32);
-       reg32 = (reg32 & hpp->adv_err_cap_and) | hpp->adv_err_cap_or;
-
-       /* Don't enable ECRC generation or checking if unsupported */
-       if (!(reg32 & PCI_ERR_CAP_ECRC_GENC))
-               reg32 &= ~PCI_ERR_CAP_ECRC_GENE;
-       if (!(reg32 & PCI_ERR_CAP_ECRC_CHKC))
-               reg32 &= ~PCI_ERR_CAP_ECRC_CHKE;
-       pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32);
-
-       /*
-        * FIXME: The following two registers are not supported yet.
-        *
-        *   o Secondary Uncorrectable Error Severity Register
-        *   o Secondary Uncorrectable Error Mask Register
-        */
-}
-
-static u16 hpx3_device_type(struct pci_dev *dev)
-{
-       u16 pcie_type = pci_pcie_type(dev);
-       const int pcie_to_hpx3_type[] = {
-               [PCI_EXP_TYPE_ENDPOINT]    = HPX_TYPE_ENDPOINT,
-               [PCI_EXP_TYPE_LEG_END]     = HPX_TYPE_LEG_END,
-               [PCI_EXP_TYPE_RC_END]      = HPX_TYPE_RC_END,
-               [PCI_EXP_TYPE_RC_EC]       = HPX_TYPE_RC_EC,
-               [PCI_EXP_TYPE_ROOT_PORT]   = HPX_TYPE_ROOT_PORT,
-               [PCI_EXP_TYPE_UPSTREAM]    = HPX_TYPE_UPSTREAM,
-               [PCI_EXP_TYPE_DOWNSTREAM]  = HPX_TYPE_DOWNSTREAM,
-               [PCI_EXP_TYPE_PCI_BRIDGE]  = HPX_TYPE_PCI_BRIDGE,
-               [PCI_EXP_TYPE_PCIE_BRIDGE] = HPX_TYPE_PCIE_BRIDGE,
-       };
-
-       if (pcie_type >= ARRAY_SIZE(pcie_to_hpx3_type))
-               return 0;
-
-       return pcie_to_hpx3_type[pcie_type];
-}
-
-static u8 hpx3_function_type(struct pci_dev *dev)
-{
-       if (dev->is_virtfn)
-               return HPX_FN_SRIOV_VIRT;
-       else if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV) > 0)
-               return HPX_FN_SRIOV_PHYS;
-       else
-               return HPX_FN_NORMAL;
-}
-
-static bool hpx3_cap_ver_matches(u8 pcie_cap_id, u8 hpx3_cap_id)
-{
-       u8 cap_ver = hpx3_cap_id & 0xf;
-
-       if ((hpx3_cap_id & BIT(4)) && cap_ver >= pcie_cap_id)
-               return true;
-       else if (cap_ver == pcie_cap_id)
-               return true;
-
-       return false;
-}
-
-static void program_hpx_type3_register(struct pci_dev *dev,
-                                      const struct hpx_type3 *reg)
-{
-       u32 match_reg, write_reg, header, orig_value;
-       u16 pos;
-
-       if (!(hpx3_device_type(dev) & reg->device_type))
-               return;
-
-       if (!(hpx3_function_type(dev) & reg->function_type))
-               return;
-
-       switch (reg->config_space_location) {
-       case HPX_CFG_PCICFG:
-               pos = 0;
-               break;
-       case HPX_CFG_PCIE_CAP:
-               pos = pci_find_capability(dev, reg->pci_exp_cap_id);
-               if (pos == 0)
-                       return;
-
-               break;
-       case HPX_CFG_PCIE_CAP_EXT:
-               pos = pci_find_ext_capability(dev, reg->pci_exp_cap_id);
-               if (pos == 0)
-                       return;
-
-               pci_read_config_dword(dev, pos, &header);
-               if (!hpx3_cap_ver_matches(PCI_EXT_CAP_VER(header),
-                                         reg->pci_exp_cap_ver))
-                       return;
-
-               break;
-       case HPX_CFG_VEND_CAP:  /* Fall through */
-       case HPX_CFG_DVSEC:     /* Fall through */
-       default:
-               pci_warn(dev, "Encountered _HPX type 3 with unsupported config space location");
-               return;
-       }
-
-       pci_read_config_dword(dev, pos + reg->match_offset, &match_reg);
-
-       if ((match_reg & reg->match_mask_and) != reg->match_value)
-               return;
-
-       pci_read_config_dword(dev, pos + reg->reg_offset, &write_reg);
-       orig_value = write_reg;
-       write_reg &= reg->reg_mask_and;
-       write_reg |= reg->reg_mask_or;
-
-       if (orig_value == write_reg)
-               return;
-
-       pci_write_config_dword(dev, pos + reg->reg_offset, write_reg);
-
-       pci_dbg(dev, "Applied _HPX3 at [0x%x]: 0x%08x -> 0x%08x",
-               pos, orig_value, write_reg);
-}
-
-static void program_hpx_type3(struct pci_dev *dev, struct hpx_type3 *hpx3)
-{
-       if (!hpx3)
-               return;
-
-       if (!pci_is_pcie(dev))
-               return;
-
-       program_hpx_type3_register(dev, hpx3);
-}
-
 int pci_configure_extended_tags(struct pci_dev *dev, void *ign)
 {
        struct pci_host_bridge *host;
@@ -2369,13 +2112,6 @@ static void pci_configure_serr(struct pci_dev *dev)
 
 static void pci_configure_device(struct pci_dev *dev)
 {
-       static const struct hotplug_program_ops hp_ops = {
-               .program_type0 = program_hpp_type0,
-               .program_type1 = program_hpp_type1,
-               .program_type2 = program_hpp_type2,
-               .program_type3 = program_hpx_type3,
-       };
-
        pci_configure_mps(dev);
        pci_configure_extended_tags(dev, NULL);
        pci_configure_relaxed_ordering(dev);
@@ -2383,7 +2119,7 @@ static void pci_configure_device(struct pci_dev *dev)
        pci_configure_eetlp_prefix(dev);
        pci_configure_serr(dev);
 
-       pci_acpi_program_hp_params(dev, &hp_ops);
+       pci_acpi_program_hp_params(dev);
 }
 
 static void pci_release_capabilities(struct pci_dev *dev)
@@ -2764,12 +2500,8 @@ static int only_one_child(struct pci_bus *bus)
         * A PCIe Downstream Port normally leads to a Link with only Device
         * 0 on it (PCIe spec r3.1, sec 7.3.1).  As an optimization, scan
         * only for Device 0 in that situation.
-        *
-        * Checking has_secondary_link is a hack to identify Downstream
-        * Ports because sometimes Switches are configured such that the
-        * PCIe Port Type labels are backwards.
         */
-       if (bridge && pci_is_pcie(bridge) && bridge->has_secondary_link)
+       if (bridge && pci_is_pcie(bridge) && pcie_downstream_port(bridge))
                return 1;
 
        return 0;
index 208aacf393297835f89101585b48ae5074a9f290..a5be6291ebb86e24789537dd94be12bded7d4301 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/delay.h>
 #include <linux/acpi.h>
 #include <linux/dmi.h>
-#include <linux/pci-aspm.h>
 #include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/ktime.h>
@@ -4466,6 +4465,19 @@ static int pci_quirk_mf_endpoint_acs(struct pci_dev *dev, u16 acs_flags)
        return acs_flags ? 0 : 1;
 }
 
+static int pci_quirk_brcm_acs(struct pci_dev *dev, u16 acs_flags)
+{
+       /*
+        * iProc PAXB Root Ports don't advertise an ACS capability, but
+        * they do not allow peer-to-peer transactions between Root Ports.
+        * Allow each Root Port to be in a separate IOMMU group by masking
+        * SV/RR/CR/UF bits.
+        */
+       acs_flags &= ~(PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF);
+
+       return acs_flags ? 0 : 1;
+}
+
 static const struct pci_dev_acs_enabled {
        u16 vendor;
        u16 device;
@@ -4559,6 +4571,7 @@ static const struct pci_dev_acs_enabled {
        { PCI_VENDOR_ID_AMPERE, 0xE00A, pci_quirk_xgene_acs },
        { PCI_VENDOR_ID_AMPERE, 0xE00B, pci_quirk_xgene_acs },
        { PCI_VENDOR_ID_AMPERE, 0xE00C, pci_quirk_xgene_acs },
+       { PCI_VENDOR_ID_BROADCOM, 0xD714, pci_quirk_brcm_acs },
        { 0 }
 };
 
index 7f4e65872b8daf640886d9887f9be804779f0dc4..bade14002fd8ad9afa5f3910458d4b3fcd9ea924 100644 (file)
@@ -15,7 +15,6 @@
 #include "pci.h"
 
 DECLARE_RWSEM(pci_bus_sem);
-EXPORT_SYMBOL_GPL(pci_bus_sem);
 
 /*
  * pci_for_each_dma_alias - Iterate over DMA aliases for a device
index 5acd9c02683af78dd96fffa7d8613c7fc9d582fd..9ae9fb9339e80b6136c3281bcd55cd7acbfba429 100644 (file)
@@ -13,6 +13,8 @@
 #include <linux/pci_regs.h>
 #include <linux/types.h>
 
+#include "pci.h"
+
 /**
  * pci_vc_save_restore_dwords - Save or restore a series of dwords
  * @dev: device
@@ -105,7 +107,7 @@ static void pci_vc_enable(struct pci_dev *dev, int pos, int res)
        struct pci_dev *link = NULL;
 
        /* Enable VCs from the downstream device */
-       if (!dev->has_secondary_link)
+       if (!pci_is_pcie(dev) || !pcie_downstream_port(dev))
                return;
 
        ctrl_pos = pos + PCI_VC_RES_CTRL + (res * PCI_CAP_VC_PER_VC_SIZEOF);
index 644f7f5c61a224439d1217cb3c7625f17b389cff..4a858789e6c5e32bac19172e427bc82a1013c072 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/moduleparam.h>
 #include <linux/pci.h>
 #include <linux/aer.h>
-#include <linux/pci-aspm.h>
 #include <linux/slab.h>
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
index 43a6b535077546f1d1bbabb77a15abcb7d6a8cbc..148663373f7d31961e471f594d2dcd342df7e5e9 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/interrupt.h>
 #include <linux/types.h>
 #include <linux/pci.h>
-#include <linux/pci-aspm.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
index 717ba0845a2afc379bed1ea07646f07702e39773..27fdbc1654463d0d6d50781f976771270d8005f8 100644 (file)
@@ -51,7 +51,6 @@
 #include <linux/workqueue.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
-#include <linux/pci-aspm.h>
 #include <linux/interrupt.h>
 #include <linux/aer.h>
 #include <linux/raid_class.h>
index f8a5b2a199459c71bdfa343f48a9665f34aff080..b459518ce4755db0b640d7076784cf49782e55b8 100644 (file)
@@ -112,7 +112,6 @@ struct dev_pagemap {
        struct device *dev;
        enum memory_type type;
        unsigned int flags;
-       u64 pci_p2pdma_bus_offset;
        const struct dev_pagemap_ops *ops;
 };
 
diff --git a/include/linux/pci-aspm.h b/include/linux/pci-aspm.h
deleted file mode 100644 (file)
index 6706414..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- *     aspm.h
- *
- *     PCI Express ASPM defines and function prototypes
- *
- *     Copyright (C) 2007 Intel Corp.
- *             Zhang Yanmin (yanmin.zhang@intel.com)
- *             Shaohua Li (shaohua.li@intel.com)
- *
- *     For more information, please consult the following manuals (look at
- *     http://www.pcisig.com/ for how to get them):
- *
- *     PCI Express Specification
- */
-
-#ifndef LINUX_ASPM_H
-#define LINUX_ASPM_H
-
-#include <linux/pci.h>
-
-#define PCIE_LINK_STATE_L0S    1
-#define PCIE_LINK_STATE_L1     2
-#define PCIE_LINK_STATE_CLKPM  4
-
-#ifdef CONFIG_PCIEASPM
-int pci_disable_link_state(struct pci_dev *pdev, int state);
-int pci_disable_link_state_locked(struct pci_dev *pdev, int state);
-void pcie_no_aspm(void);
-#else
-static inline int pci_disable_link_state(struct pci_dev *pdev, int state)
-{ return 0; }
-static inline void pcie_no_aspm(void) { }
-#endif
-
-#endif /* LINUX_ASPM_H */
index bca9bc3e5be7929cad7eec9987f1089173351658..8318a97c9c61e6b4caf922cce5c1da8e5a525937 100644 (file)
@@ -30,8 +30,10 @@ struct scatterlist *pci_p2pmem_alloc_sgl(struct pci_dev *pdev,
                                         unsigned int *nents, u32 length);
 void pci_p2pmem_free_sgl(struct pci_dev *pdev, struct scatterlist *sgl);
 void pci_p2pmem_publish(struct pci_dev *pdev, bool publish);
-int pci_p2pdma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-                     enum dma_data_direction dir);
+int pci_p2pdma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
+               int nents, enum dma_data_direction dir, unsigned long attrs);
+void pci_p2pdma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg,
+               int nents, enum dma_data_direction dir, unsigned long attrs);
 int pci_p2pdma_enable_store(const char *page, struct pci_dev **p2p_dev,
                            bool *use_p2pdma);
 ssize_t pci_p2pdma_enable_show(char *page, struct pci_dev *p2p_dev,
@@ -81,11 +83,17 @@ static inline void pci_p2pmem_free_sgl(struct pci_dev *pdev,
 static inline void pci_p2pmem_publish(struct pci_dev *pdev, bool publish)
 {
 }
-static inline int pci_p2pdma_map_sg(struct device *dev,
-               struct scatterlist *sg, int nents, enum dma_data_direction dir)
+static inline int pci_p2pdma_map_sg_attrs(struct device *dev,
+               struct scatterlist *sg, int nents, enum dma_data_direction dir,
+               unsigned long attrs)
 {
        return 0;
 }
+static inline void pci_p2pdma_unmap_sg_attrs(struct device *dev,
+               struct scatterlist *sg, int nents, enum dma_data_direction dir,
+               unsigned long attrs)
+{
+}
 static inline int pci_p2pdma_enable_store(const char *page,
                struct pci_dev **p2p_dev, bool *use_p2pdma)
 {
@@ -111,4 +119,16 @@ static inline struct pci_dev *pci_p2pmem_find(struct device *client)
        return pci_p2pmem_find_many(&client, 1);
 }
 
+static inline int pci_p2pdma_map_sg(struct device *dev, struct scatterlist *sg,
+                                   int nents, enum dma_data_direction dir)
+{
+       return pci_p2pdma_map_sg_attrs(dev, sg, nents, dir, 0);
+}
+
+static inline void pci_p2pdma_unmap_sg(struct device *dev,
+               struct scatterlist *sg, int nents, enum dma_data_direction dir)
+{
+       pci_p2pdma_unmap_sg_attrs(dev, sg, nents, dir, 0);
+}
+
 #endif /* _LINUX_PCI_P2P_H */
index dcc5dd310c14efe187920ef5d08ee97ff57f3a8c..c1c2e4c7242a22735c8194431e8d57416af181f5 100644 (file)
@@ -6,12 +6,18 @@
  *     Copyright 1994, Drew Eckhardt
  *     Copyright 1997--1999 Martin Mares <mj@ucw.cz>
  *
+ *     PCI Express ASPM defines and function prototypes
+ *     Copyright (c) 2007 Intel Corp.
+ *             Zhang Yanmin (yanmin.zhang@intel.com)
+ *             Shaohua Li (shaohua.li@intel.com)
+ *
  *     For more information, please consult the following manuals (look at
  *     http://www.pcisig.com/ for how to get them):
  *
  *     PCI BIOS Specification
  *     PCI Local Bus Specification
  *     PCI to PCI Bridge Specification
+ *     PCI Express Specification
  *     PCI System Design Guide
  */
 #ifndef LINUX_PCI_H
@@ -145,11 +151,6 @@ static inline const char *pci_power_name(pci_power_t state)
        return pci_power_names[1 + (__force int) state];
 }
 
-#define PCI_PM_D2_DELAY                200
-#define PCI_PM_D3_WAIT         10
-#define PCI_PM_D3COLD_WAIT     100
-#define PCI_PM_BUS_WAIT                50
-
 /**
  * typedef pci_channel_state_t
  *
@@ -418,7 +419,6 @@ struct pci_dev {
        unsigned int    broken_intx_masking:1;  /* INTx masking can't be used */
        unsigned int    io_window_1k:1;         /* Intel bridge 1K I/O windows */
        unsigned int    irq_managed:1;
-       unsigned int    has_secondary_link:1;
        unsigned int    non_compliant_bars:1;   /* Broken BARs; ignore them */
        unsigned int    is_probed:1;            /* Device probing in progress */
        unsigned int    link_active_reporting:1;/* Device capable of reporting link active */
@@ -649,9 +649,6 @@ static inline struct pci_dev *pci_upstream_bridge(struct pci_dev *dev)
        return dev->bus->self;
 }
 
-struct device *pci_get_host_bridge_device(struct pci_dev *dev);
-void pci_put_host_bridge_device(struct device *dev);
-
 #ifdef CONFIG_PCI_MSI
 static inline bool pci_dev_msi_enabled(struct pci_dev *pci_dev)
 {
@@ -925,6 +922,11 @@ enum {
        PCI_SCAN_ALL_PCIE_DEVS  = 0x00000040,   /* Scan all, not just dev 0 */
 };
 
+#define PCI_IRQ_LEGACY         (1 << 0) /* Allow legacy interrupts */
+#define PCI_IRQ_MSI            (1 << 1) /* Allow MSI interrupts */
+#define PCI_IRQ_MSIX           (1 << 2) /* Allow MSI-X interrupts */
+#define PCI_IRQ_AFFINITY       (1 << 3) /* Auto-assign affinity */
+
 /* These external functions are only available when PCI support is enabled */
 #ifdef CONFIG_PCI
 
@@ -995,7 +997,6 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
 int pci_scan_root_bus_bridge(struct pci_host_bridge *bridge);
 struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
                                int busnr);
-void pcie_update_link_speed(struct pci_bus *bus, u16 link_status);
 struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
                                 const char *name,
                                 struct hotplug_slot *hotplug);
@@ -1241,19 +1242,12 @@ int pci_wake_from_d3(struct pci_dev *dev, bool enable);
 int pci_prepare_to_sleep(struct pci_dev *dev);
 int pci_back_from_sleep(struct pci_dev *dev);
 bool pci_dev_run_wake(struct pci_dev *dev);
-bool pci_check_pme_status(struct pci_dev *dev);
-void pci_pme_wakeup_bus(struct pci_bus *bus);
 void pci_d3cold_enable(struct pci_dev *dev);
 void pci_d3cold_disable(struct pci_dev *dev);
 bool pcie_relaxed_ordering_enabled(struct pci_dev *dev);
 void pci_wakeup_bus(struct pci_bus *bus);
 void pci_bus_set_current_state(struct pci_bus *bus, pci_power_t state);
 
-/* PCI Virtual Channel */
-int pci_save_vc_state(struct pci_dev *dev);
-void pci_restore_vc_state(struct pci_dev *dev);
-void pci_allocate_vc_save_buffers(struct pci_dev *dev);
-
 /* For use by arch with custom probe code */
 void set_pcie_port_type(struct pci_dev *pdev);
 void set_pcie_hotplug_bridge(struct pci_dev *pdev);
@@ -1297,8 +1291,6 @@ int pci_request_selected_regions_exclusive(struct pci_dev *, int, const char *);
 void pci_release_selected_regions(struct pci_dev *, int);
 
 /* drivers/pci/bus.c */
-struct pci_bus *pci_bus_get(struct pci_bus *bus);
-void pci_bus_put(struct pci_bus *bus);
 void pci_add_resource(struct list_head *resources, struct resource *res);
 void pci_add_resource_offset(struct list_head *resources, struct resource *res,
                             resource_size_t offset);
@@ -1408,11 +1400,6 @@ resource_size_t pcibios_window_alignment(struct pci_bus *bus,
 int pci_set_vga_state(struct pci_dev *pdev, bool decode,
                      unsigned int command_bits, u32 flags);
 
-#define PCI_IRQ_LEGACY         (1 << 0) /* Allow legacy interrupts */
-#define PCI_IRQ_MSI            (1 << 1) /* Allow MSI interrupts */
-#define PCI_IRQ_MSIX           (1 << 2) /* Allow MSI-X interrupts */
-#define PCI_IRQ_AFFINITY       (1 << 3) /* Auto-assign affinity */
-
 /*
  * Virtual interrupts allow for more interrupts to be allocated
  * than the device has interrupts for. These are not programmed
@@ -1517,14 +1504,6 @@ static inline int pci_irq_get_node(struct pci_dev *pdev, int vec)
 }
 #endif
 
-static inline int
-pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs,
-                     unsigned int max_vecs, unsigned int flags)
-{
-       return pci_alloc_irq_vectors_affinity(dev, min_vecs, max_vecs, flags,
-                                             NULL);
-}
-
 /**
  * pci_irqd_intx_xlate() - Translate PCI INTx value to an IRQ domain hwirq
  * @d: the INTx IRQ domain
@@ -1565,9 +1544,21 @@ extern bool pcie_ports_native;
 #define pcie_ports_native      false
 #endif
 
+#define PCIE_LINK_STATE_L0S    1
+#define PCIE_LINK_STATE_L1     2
+#define PCIE_LINK_STATE_CLKPM  4
+
 #ifdef CONFIG_PCIEASPM
+int pci_disable_link_state(struct pci_dev *pdev, int state);
+int pci_disable_link_state_locked(struct pci_dev *pdev, int state);
+void pcie_no_aspm(void);
 bool pcie_aspm_support_enabled(void);
 #else
+static inline int pci_disable_link_state(struct pci_dev *pdev, int state)
+{ return 0; }
+static inline int pci_disable_link_state_locked(struct pci_dev *pdev, int state)
+{ return 0; }
+static inline void pcie_no_aspm(void) { }
 static inline bool pcie_aspm_support_enabled(void) { return false; }
 #endif
 
@@ -1577,23 +1568,8 @@ bool pci_aer_available(void);
 static inline bool pci_aer_available(void) { return false; }
 #endif
 
-#ifdef CONFIG_PCIE_ECRC
-void pcie_set_ecrc_checking(struct pci_dev *dev);
-void pcie_ecrc_get_policy(char *str);
-#else
-static inline void pcie_set_ecrc_checking(struct pci_dev *dev) { }
-static inline void pcie_ecrc_get_policy(char *str) { }
-#endif
-
 bool pci_ats_disabled(void);
 
-#ifdef CONFIG_PCIE_PTM
-int pci_enable_ptm(struct pci_dev *dev, u8 *granularity);
-#else
-static inline int pci_enable_ptm(struct pci_dev *dev, u8 *granularity)
-{ return -EINVAL; }
-#endif
-
 void pci_cfg_access_lock(struct pci_dev *dev);
 bool pci_cfg_access_trylock(struct pci_dev *dev);
 void pci_cfg_access_unlock(struct pci_dev *dev);
@@ -1747,11 +1723,6 @@ static inline void pci_release_regions(struct pci_dev *dev) { }
 
 static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; }
 
-static inline void pci_block_cfg_access(struct pci_dev *dev) { }
-static inline int pci_block_cfg_access_in_atomic(struct pci_dev *dev)
-{ return 0; }
-static inline void pci_unblock_cfg_access(struct pci_dev *dev) { }
-
 static inline struct pci_bus *pci_find_next_bus(const struct pci_bus *from)
 { return NULL; }
 static inline struct pci_dev *pci_get_slot(struct pci_bus *bus,
@@ -1780,17 +1751,36 @@ static inline const struct pci_device_id *pci_match_id(const struct pci_device_i
                                                         struct pci_dev *dev)
 { return NULL; }
 static inline bool pci_ats_disabled(void) { return true; }
+
+static inline int pci_irq_vector(struct pci_dev *dev, unsigned int nr)
+{
+       return -EINVAL;
+}
+
+static inline int
+pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,
+                              unsigned int max_vecs, unsigned int flags,
+                              struct irq_affinity *aff_desc)
+{
+       return -ENOSPC;
+}
 #endif /* CONFIG_PCI */
 
+static inline int
+pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs,
+                     unsigned int max_vecs, unsigned int flags)
+{
+       return pci_alloc_irq_vectors_affinity(dev, min_vecs, max_vecs, flags,
+                                             NULL);
+}
+
 #ifdef CONFIG_PCI_ATS
 /* Address Translation Service */
-void pci_ats_init(struct pci_dev *dev);
 int pci_enable_ats(struct pci_dev *dev, int ps);
 void pci_disable_ats(struct pci_dev *dev);
 int pci_ats_queue_depth(struct pci_dev *dev);
 int pci_ats_page_aligned(struct pci_dev *dev);
 #else
-static inline void pci_ats_init(struct pci_dev *d) { }
 static inline int pci_enable_ats(struct pci_dev *d, int ps) { return -ENODEV; }
 static inline void pci_disable_ats(struct pci_dev *d) { }
 static inline int pci_ats_queue_depth(struct pci_dev *d) { return -ENODEV; }
@@ -2014,10 +2004,6 @@ extern unsigned long pci_cardbus_mem_size;
 extern u8 pci_dfl_cache_line_size;
 extern u8 pci_cache_line_size;
 
-extern unsigned long pci_hotplug_io_size;
-extern unsigned long pci_hotplug_mem_size;
-extern unsigned long pci_hotplug_bus_size;
-
 /* Architecture-specific versions may override these (weak) */
 void pcibios_disable_device(struct pci_dev *dev);
 void pcibios_set_master(struct pci_dev *dev);
@@ -2287,10 +2273,6 @@ int pci_vpd_find_info_keyword(const u8 *buf, unsigned int off,
 #ifdef CONFIG_OF
 struct device_node;
 struct irq_domain;
-void pci_set_of_node(struct pci_dev *dev);
-void pci_release_of_node(struct pci_dev *dev);
-void pci_set_bus_of_node(struct pci_bus *bus);
-void pci_release_bus_of_node(struct pci_bus *bus);
 struct irq_domain *pci_host_bridge_of_msi_domain(struct pci_bus *bus);
 int pci_parse_request_of_pci_ranges(struct device *dev,
                                    struct list_head *resources,
@@ -2300,10 +2282,6 @@ int pci_parse_request_of_pci_ranges(struct device *dev,
 struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus);
 
 #else  /* CONFIG_OF */
-static inline void pci_set_of_node(struct pci_dev *dev) { }
-static inline void pci_release_of_node(struct pci_dev *dev) { }
-static inline void pci_set_bus_of_node(struct pci_bus *bus) { }
-static inline void pci_release_bus_of_node(struct pci_bus *bus) { }
 static inline struct irq_domain *
 pci_host_bridge_of_msi_domain(struct pci_bus *bus) { return NULL; }
 static inline int pci_parse_request_of_pci_ranges(struct device *dev,
@@ -2417,4 +2395,7 @@ void pci_uevent_ers(struct pci_dev *pdev, enum  pci_ers_result err_type);
 #define pci_notice_ratelimited(pdev, fmt, arg...) \
        dev_notice_ratelimited(&(pdev)->dev, fmt, ##arg)
 
+#define pci_info_ratelimited(pdev, fmt, arg...) \
+       dev_info_ratelimited(&(pdev)->dev, fmt, ##arg)
+
 #endif /* LINUX_PCI_H */
index f694eb2ca97815982165c0f6ba1d3757cb0a550e..b482e42d715356cd79a7f1cd1e69decac0afa985 100644 (file)
@@ -86,114 +86,14 @@ void pci_hp_deregister(struct hotplug_slot *slot);
 #define pci_hp_initialize(slot, bus, nr, name) \
        __pci_hp_initialize(slot, bus, nr, name, THIS_MODULE, KBUILD_MODNAME)
 
-/* PCI Setting Record (Type 0) */
-struct hpp_type0 {
-       u32 revision;
-       u8  cache_line_size;
-       u8  latency_timer;
-       u8  enable_serr;
-       u8  enable_perr;
-};
-
-/* PCI-X Setting Record (Type 1) */
-struct hpp_type1 {
-       u32 revision;
-       u8  max_mem_read;
-       u8  avg_max_split;
-       u16 tot_max_split;
-};
-
-/* PCI Express Setting Record (Type 2) */
-struct hpp_type2 {
-       u32 revision;
-       u32 unc_err_mask_and;
-       u32 unc_err_mask_or;
-       u32 unc_err_sever_and;
-       u32 unc_err_sever_or;
-       u32 cor_err_mask_and;
-       u32 cor_err_mask_or;
-       u32 adv_err_cap_and;
-       u32 adv_err_cap_or;
-       u16 pci_exp_devctl_and;
-       u16 pci_exp_devctl_or;
-       u16 pci_exp_lnkctl_and;
-       u16 pci_exp_lnkctl_or;
-       u32 sec_unc_err_sever_and;
-       u32 sec_unc_err_sever_or;
-       u32 sec_unc_err_mask_and;
-       u32 sec_unc_err_mask_or;
-};
-
-/*
- * _HPX PCI Express Setting Record (Type 3)
- */
-struct hpx_type3 {
-       u16 device_type;
-       u16 function_type;
-       u16 config_space_location;
-       u16 pci_exp_cap_id;
-       u16 pci_exp_cap_ver;
-       u16 pci_exp_vendor_id;
-       u16 dvsec_id;
-       u16 dvsec_rev;
-       u16 match_offset;
-       u32 match_mask_and;
-       u32 match_value;
-       u16 reg_offset;
-       u32 reg_mask_and;
-       u32 reg_mask_or;
-};
-
-struct hotplug_program_ops {
-       void (*program_type0)(struct pci_dev *dev, struct hpp_type0 *hpp);
-       void (*program_type1)(struct pci_dev *dev, struct hpp_type1 *hpp);
-       void (*program_type2)(struct pci_dev *dev, struct hpp_type2 *hpp);
-       void (*program_type3)(struct pci_dev *dev, struct hpx_type3 *hpp);
-};
-
-enum hpx_type3_dev_type {
-       HPX_TYPE_ENDPOINT       = BIT(0),
-       HPX_TYPE_LEG_END        = BIT(1),
-       HPX_TYPE_RC_END         = BIT(2),
-       HPX_TYPE_RC_EC          = BIT(3),
-       HPX_TYPE_ROOT_PORT      = BIT(4),
-       HPX_TYPE_UPSTREAM       = BIT(5),
-       HPX_TYPE_DOWNSTREAM     = BIT(6),
-       HPX_TYPE_PCI_BRIDGE     = BIT(7),
-       HPX_TYPE_PCIE_BRIDGE    = BIT(8),
-};
-
-enum hpx_type3_fn_type {
-       HPX_FN_NORMAL           = BIT(0),
-       HPX_FN_SRIOV_PHYS       = BIT(1),
-       HPX_FN_SRIOV_VIRT       = BIT(2),
-};
-
-enum hpx_type3_cfg_loc {
-       HPX_CFG_PCICFG          = 0,
-       HPX_CFG_PCIE_CAP        = 1,
-       HPX_CFG_PCIE_CAP_EXT    = 2,
-       HPX_CFG_VEND_CAP        = 3,
-       HPX_CFG_DVSEC           = 4,
-       HPX_CFG_MAX,
-};
-
 #ifdef CONFIG_ACPI
 #include <linux/acpi.h>
-int pci_acpi_program_hp_params(struct pci_dev *dev,
-                              const struct hotplug_program_ops *hp_ops);
 bool pciehp_is_native(struct pci_dev *bridge);
 int acpi_get_hp_hw_control_from_firmware(struct pci_dev *bridge);
 bool shpchp_is_native(struct pci_dev *bridge);
 int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle);
 int acpi_pci_detect_ejectable(acpi_handle handle);
 #else
-static inline int pci_acpi_program_hp_params(struct pci_dev *dev,
-                                   const struct hotplug_program_ops *hp_ops)
-{
-       return -ENODEV;
-}
-
 static inline int acpi_get_hp_hw_control_from_firmware(struct pci_dev *bridge)
 {
        return 0;
index f28e562d7ca8681b9a91bfd5c48142f0904789f2..de3e58afc564ae77b818434eb4b119ecbd8dda45 100644 (file)
 #define  PCI_EXP_SLTCTL_CCIE   0x0010  /* Command Completed Interrupt Enable */
 #define  PCI_EXP_SLTCTL_HPIE   0x0020  /* Hot-Plug Interrupt Enable */
 #define  PCI_EXP_SLTCTL_AIC    0x00c0  /* Attention Indicator Control */
+#define  PCI_EXP_SLTCTL_ATTN_IND_SHIFT 6      /* Attention Indicator shift */
 #define  PCI_EXP_SLTCTL_ATTN_IND_ON    0x0040 /* Attention Indicator on */
 #define  PCI_EXP_SLTCTL_ATTN_IND_BLINK 0x0080 /* Attention Indicator blinking */
 #define  PCI_EXP_SLTCTL_ATTN_IND_OFF   0x00c0 /* Attention Indicator off */