mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 04:34:08 +08:00
PCI changes for the v4.5 merge window:
Enumeration Simplify config space size computation (Bjorn Helgaas) Avoid iterating through ROM outside the resource window (Edward O'Callaghan) Support PCIe devices with short cfg_size (Jason S. McMullan) Add Netronome vendor and device IDs (Jason S. McMullan) Limit config space size for Netronome NFP6000 family (Jason S. McMullan) Add Netronome NFP4000 PF device ID (Simon Horman) Limit config space size for Netronome NFP4000 (Simon Horman) Print warnings for all invalid expansion ROM headers (Vladis Dronov) Resource management Fix minimum allocation address overwrite (Christoph Biedl) PCI device hotplug acpiphp_ibm: Fix null dereferences on null ibm_slot (Colin Ian King) pciehp: Always protect pciehp_disable_slot() with hotplug mutex (Guenter Roeck) shpchp: Constify hpc_ops structure (Julia Lawall) ibmphp: Remove unneeded NULL test (Julia Lawall) Power management Make ASPM sysfs link_state_store() consistent with link_state_show() (Andy Lutomirski) Virtualization Add function 1 DMA alias quirk for Lite-On/Plextor M6e/Marvell 88SS9183 (Tim Sander) MSI Remove empty pci_msi_init_pci_dev() (Bjorn Helgaas) Mark PCIe/PCI (MSI) IRQ cascade handlers as IRQF_NO_THREAD (Grygorii Strashko) Initialize MSI capability for all architectures (Guilherme G. Piccoli) Relax msi_domain_alloc() to support parentless MSI irqdomains (Liu Jiang) ARM Versatile host bridge driver Remove unused pci_sys_data structures (Lorenzo Pieralisi) Broadcom iProc host bridge driver Hide CONFIG_PCIE_IPROC (Arnd Bergmann) Do not use 0x in front of %pap (Dmitry V. Krivenok) Update iProc PCIe device tree binding (Ray Jui) Add PAXC interface support (Ray Jui) Add iProc PCIe MSI device tree binding (Ray Jui) Add iProc PCIe MSI support (Ray Jui) Freescale i.MX6 host bridge driver Use gpio_set_value_cansleep() (Fabio Estevam) Add support for active-low reset GPIO (Petr Štetiar) HiSilicon host bridge driver Add support for HiSilicon Hip06 PCIe host controllers (Gabriele Paoloni) Intel VMD host bridge driver Export irq_domain_set_info() for module use (Keith Busch) x86/PCI: Allow DMA ops specific to a PCI domain (Keith Busch) Use 32 bit PCI domain numbers (Keith Busch) Add driver for Intel Volume Management Device (VMD) (Keith Busch) Qualcomm host bridge driver Document PCIe devicetree bindings (Stanimir Varbanov) Add Qualcomm PCIe controller driver (Stanimir Varbanov) dts: apq8064: add PCIe devicetree node (Stanimir Varbanov) dts: ifc6410: enable PCIe DT node for this board (Stanimir Varbanov) Renesas R-Car host bridge driver Add support for R-Car H3 to pcie-rcar (Harunobu Kurokawa) Allow DT to override default window settings (Phil Edworthy) Convert to DT resource parsing API (Phil Edworthy) Revert "PCI: rcar: Build pcie-rcar.c only on ARM" (Phil Edworthy) Remove unused pci_sys_data struct from pcie-rcar (Phil Edworthy) Add runtime PM support to pcie-rcar (Phil Edworthy) Add Gen2 PHY setup to pcie-rcar (Phil Edworthy) Add gen2 fallback compatibility string for pci-rcar-gen2 (Simon Horman) Add gen2 fallback compatibility string for pcie-rcar (Simon Horman) Synopsys DesignWare host bridge driver Simplify control flow (Bjorn Helgaas) Make config accessor override checking symmetric (Bjorn Helgaas) Ensure ATU is enabled before IO/conf space accesses (Stanimir Varbanov) Miscellaneous Add of_pci_get_host_bridge_resources() stub (Arnd Bergmann) Check for PCI_HEADER_TYPE_BRIDGE equality, not bitmask (Bjorn Helgaas) Fix all whitespace issues (Bogicevic Sasa) x86/PCI: Simplify pci_bios_{read,write} (Geliang Tang) Use to_pci_dev() instead of open-coding it (Geliang Tang) Use kobj_to_dev() instead of open-coding it (Geliang Tang) Use list_for_each_entry() to simplify code (Geliang Tang) Fix typos in <linux/msi.h> (Thomas Petazzoni) x86/PCI: Clarify AMD Fam10h config access restrictions comment (Tomasz Nowicki) -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJWoQIuAAoJEFmIoMA60/r8ckYP/0ZrkANeN1SB5cQVi2k7aceq kQb1Hk6ifxohJvgpJ/iwmVCHoApyeBfUBfrC+fUpIC2f7ncPsE5HNyjqpAWzFzj2 sYWwY029yjBQ9g4mPhkvjBXfha+lNtLthWc+Xxcat5pdcyG63Dg4SfJKWm2ZYnbN 0GJzyRZXIwAMnNf0KIr61Aqru0nXeHvi5wblyJ08UZ7AcNzCtB0wKLmE3S6SeZVF f2fry35zcGu+TFvQ1hAYemfl3XyDBJ87nPiKzJAwYSaKcWPFWt+72PBDPO6X9squ 6prm4nmAgeG2Oo4Zu0fbkDlB2bEsWUc14/xT0i5Wfs35vcwzF+S1zirJAtVqoNir NgC7fSbEHbsS7FZOz0rBOBIvIkbb6NdfLFuZqUFv0X1M5bRFywjo8lZRfAYoGJzK Mmus0uKbklx5m6RT5adf9+Plev1YJT6XZW9XrDpGnxrwRyPjHmyvuTWsYkumxY7Q CE5Wr3p7q2I2+MtrQVv2D9Nzsb+4zQ6BgHrd2vwR/IxTsfdXLU7+B691wkUDX8No UKFxBd0FiVCn+srG96u7lWQvdoUqoNCogTZSVzGR5gFBv3zAN9gi8HS7NbV558Mg Io3Xw+6dcbG33uvWdU6jHEDLMQsohZcp05Q5esCgRQNV4cGJbPxBDtOZEO/ezvW4 FAI7lfgYTFiQK3NzE3Ng =z9mQ -----END PGP SIGNATURE----- Merge tag 'pci-v4.5-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci Pull PCI updates from Bjorn Helgaas: "PCI changes for the v4.5 merge window: Enumeration: - Simplify config space size computation (Bjorn Helgaas) - Avoid iterating through ROM outside the resource window (Edward O'Callaghan) - Support PCIe devices with short cfg_size (Jason S. McMullan) - Add Netronome vendor and device IDs (Jason S. McMullan) - Limit config space size for Netronome NFP6000 family (Jason S. McMullan) - Add Netronome NFP4000 PF device ID (Simon Horman) - Limit config space size for Netronome NFP4000 (Simon Horman) - Print warnings for all invalid expansion ROM headers (Vladis Dronov) Resource management: - Fix minimum allocation address overwrite (Christoph Biedl) PCI device hotplug: - acpiphp_ibm: Fix null dereferences on null ibm_slot (Colin Ian King) - pciehp: Always protect pciehp_disable_slot() with hotplug mutex (Guenter Roeck) - shpchp: Constify hpc_ops structure (Julia Lawall) - ibmphp: Remove unneeded NULL test (Julia Lawall) Power management: - Make ASPM sysfs link_state_store() consistent with link_state_show() (Andy Lutomirski) Virtualization - Add function 1 DMA alias quirk for Lite-On/Plextor M6e/Marvell 88SS9183 (Tim Sander) MSI: - Remove empty pci_msi_init_pci_dev() (Bjorn Helgaas) - Mark PCIe/PCI (MSI) IRQ cascade handlers as IRQF_NO_THREAD (Grygorii Strashko) - Initialize MSI capability for all architectures (Guilherme G. Piccoli) - Relax msi_domain_alloc() to support parentless MSI irqdomains (Liu Jiang) ARM Versatile host bridge driver: - Remove unused pci_sys_data structures (Lorenzo Pieralisi) Broadcom iProc host bridge driver: - Hide CONFIG_PCIE_IPROC (Arnd Bergmann) - Do not use 0x in front of %pap (Dmitry V. Krivenok) - Update iProc PCIe device tree binding (Ray Jui) - Add PAXC interface support (Ray Jui) - Add iProc PCIe MSI device tree binding (Ray Jui) - Add iProc PCIe MSI support (Ray Jui) Freescale i.MX6 host bridge driver: - Use gpio_set_value_cansleep() (Fabio Estevam) - Add support for active-low reset GPIO (Petr Štetiar) HiSilicon host bridge driver: - Add support for HiSilicon Hip06 PCIe host controllers (Gabriele Paoloni) Intel VMD host bridge driver: - Export irq_domain_set_info() for module use (Keith Busch) - x86/PCI: Allow DMA ops specific to a PCI domain (Keith Busch) - Use 32 bit PCI domain numbers (Keith Busch) - Add driver for Intel Volume Management Device (VMD) (Keith Busch) Qualcomm host bridge driver: - Document PCIe devicetree bindings (Stanimir Varbanov) - Add Qualcomm PCIe controller driver (Stanimir Varbanov) - dts: apq8064: add PCIe devicetree node (Stanimir Varbanov) - dts: ifc6410: enable PCIe DT node for this board (Stanimir Varbanov) Renesas R-Car host bridge driver: - Add support for R-Car H3 to pcie-rcar (Harunobu Kurokawa) - Allow DT to override default window settings (Phil Edworthy) - Convert to DT resource parsing API (Phil Edworthy) - Revert "PCI: rcar: Build pcie-rcar.c only on ARM" (Phil Edworthy) - Remove unused pci_sys_data struct from pcie-rcar (Phil Edworthy) - Add runtime PM support to pcie-rcar (Phil Edworthy) - Add Gen2 PHY setup to pcie-rcar (Phil Edworthy) - Add gen2 fallback compatibility string for pci-rcar-gen2 (Simon Horman) - Add gen2 fallback compatibility string for pcie-rcar (Simon Horman) Synopsys DesignWare host bridge driver: - Simplify control flow (Bjorn Helgaas) - Make config accessor override checking symmetric (Bjorn Helgaas) - Ensure ATU is enabled before IO/conf space accesses (Stanimir Varbanov) Miscellaneous: - Add of_pci_get_host_bridge_resources() stub (Arnd Bergmann) - Check for PCI_HEADER_TYPE_BRIDGE equality, not bitmask (Bjorn Helgaas) - Fix all whitespace issues (Bogicevic Sasa) - x86/PCI: Simplify pci_bios_{read,write} (Geliang Tang) - Use to_pci_dev() instead of open-coding it (Geliang Tang) - Use kobj_to_dev() instead of open-coding it (Geliang Tang) - Use list_for_each_entry() to simplify code (Geliang Tang) - Fix typos in <linux/msi.h> (Thomas Petazzoni) - x86/PCI: Clarify AMD Fam10h config access restrictions comment (Tomasz Nowicki)" * tag 'pci-v4.5-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (58 commits) PCI: Add function 1 DMA alias quirk for Lite-On/Plextor M6e/Marvell 88SS9183 PCI: Limit config space size for Netronome NFP4000 PCI: Add Netronome NFP4000 PF device ID x86/PCI: Add driver for Intel Volume Management Device (VMD) PCI/AER: Use 32 bit PCI domain numbers x86/PCI: Allow DMA ops specific to a PCI domain irqdomain: Export irq_domain_set_info() for module use PCI: host: Add of_pci_get_host_bridge_resources() stub genirq/MSI: Relax msi_domain_alloc() to support parentless MSI irqdomains PCI: rcar: Add Gen2 PHY setup to pcie-rcar PCI: rcar: Add runtime PM support to pcie-rcar PCI: designware: Make config accessor override checking symmetric PCI: ibmphp: Remove unneeded NULL test ARM: dts: ifc6410: enable PCIe DT node for this board ARM: dts: apq8064: add PCIe devicetree node PCI: hotplug: Use list_for_each_entry() to simplify code PCI: rcar: Remove unused pci_sys_data struct from pcie-rcar PCI: hisi: Add support for HiSilicon Hip06 PCIe host controllers PCI: Avoid iterating through memory outside the resource window PCI: acpiphp_ibm: Fix null dereferences on null ibm_slot ...
This commit is contained in:
commit
d43421565b
@ -1,7 +1,10 @@
|
||||
* Broadcom iProc PCIe controller with the platform bus interface
|
||||
|
||||
Required properties:
|
||||
- compatible: Must be "brcm,iproc-pcie"
|
||||
- compatible: Must be "brcm,iproc-pcie" for PAXB, or "brcm,iproc-pcie-paxc"
|
||||
for PAXC. PAXB-based root complex is used for external endpoint devices.
|
||||
PAXC-based root complex is connected to emulated endpoint devices
|
||||
internal to the ASIC
|
||||
- reg: base address and length of the PCIe controller I/O register space
|
||||
- #interrupt-cells: set to <1>
|
||||
- interrupt-map-mask and interrupt-map, standard PCI properties to define the
|
||||
@ -32,6 +35,28 @@ Optional:
|
||||
- brcm,pcie-ob-oarr-size: Some iProc SoCs need the OARR size bit to be set to
|
||||
increase the outbound window size
|
||||
|
||||
MSI support (optional):
|
||||
|
||||
For older platforms without MSI integrated in the GIC, iProc PCIe core provides
|
||||
an event queue based MSI support. The iProc MSI uses host memories to store
|
||||
MSI posted writes in the event queues
|
||||
|
||||
- msi-parent: Link to the device node of the MSI controller. On newer iProc
|
||||
platforms, the MSI controller may be gicv2m or gicv3-its. On older iProc
|
||||
platforms without MSI support in its interrupt controller, one may use the
|
||||
event queue based MSI support integrated within the iProc PCIe core.
|
||||
|
||||
When the iProc event queue based MSI is used, one needs to define the
|
||||
following properties in the MSI device node:
|
||||
- compatible: Must be "brcm,iproc-msi"
|
||||
- msi-controller: claims itself as an MSI controller
|
||||
- interrupt-parent: Link to its parent interrupt device
|
||||
- interrupts: List of interrupt IDs from its parent interrupt device
|
||||
|
||||
Optional properties:
|
||||
- brcm,pcie-msi-inten: Needs to be present for some older iProc platforms that
|
||||
require the interrupt enable registers to be set explicitly to enable MSI
|
||||
|
||||
Example:
|
||||
pcie0: pcie@18012000 {
|
||||
compatible = "brcm,iproc-pcie";
|
||||
@ -58,6 +83,19 @@ Example:
|
||||
brcm,pcie-ob-oarr-size;
|
||||
brcm,pcie-ob-axi-offset = <0x00000000>;
|
||||
brcm,pcie-ob-window-size = <256>;
|
||||
|
||||
msi-parent = <&msi0>;
|
||||
|
||||
/* iProc event queue based MSI */
|
||||
msi0: msi@18012000 {
|
||||
compatible = "brcm,iproc-msi";
|
||||
msi-controller;
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <GIC_SPI 96 IRQ_TYPE_NONE>,
|
||||
<GIC_SPI 97 IRQ_TYPE_NONE>,
|
||||
<GIC_SPI 98 IRQ_TYPE_NONE>,
|
||||
<GIC_SPI 99 IRQ_TYPE_NONE>,
|
||||
};
|
||||
};
|
||||
|
||||
pcie1: pcie@18013000 {
|
||||
|
@ -1,4 +1,4 @@
|
||||
HiSilicon PCIe host bridge DT description
|
||||
HiSilicon Hip05 and Hip06 PCIe host bridge DT description
|
||||
|
||||
HiSilicon PCIe host controller is based on Designware PCI core.
|
||||
It shares common functions with PCIe Designware core driver and inherits
|
||||
@ -7,8 +7,8 @@ Documentation/devicetree/bindings/pci/designware-pci.txt.
|
||||
|
||||
Additional properties are described here:
|
||||
|
||||
Required properties:
|
||||
- compatible: Should contain "hisilicon,hip05-pcie".
|
||||
Required properties
|
||||
- compatible: Should contain "hisilicon,hip05-pcie" or "hisilicon,hip06-pcie".
|
||||
- reg: Should contain rc_dbi, config registers location and length.
|
||||
- reg-names: Must include the following entries:
|
||||
"rc_dbi": controller configuration registers;
|
||||
@ -20,7 +20,7 @@ Optional properties:
|
||||
- status: Either "ok" or "disabled".
|
||||
- dma-coherent: Present if DMA operations are coherent.
|
||||
|
||||
Example:
|
||||
Hip05 Example (note that Hip06 is the same except compatible):
|
||||
pcie@0xb0080000 {
|
||||
compatible = "hisilicon,hip05-pcie", "snps,dw-pcie";
|
||||
reg = <0 0xb0080000 0 0x10000>, <0x220 0x00000000 0 0x2000>;
|
||||
|
@ -8,7 +8,14 @@ OHCI and EHCI controllers.
|
||||
Required properties:
|
||||
- compatible: "renesas,pci-r8a7790" for the R8A7790 SoC;
|
||||
"renesas,pci-r8a7791" for the R8A7791 SoC;
|
||||
"renesas,pci-r8a7794" for the R8A7794 SoC.
|
||||
"renesas,pci-r8a7794" for the R8A7794 SoC;
|
||||
"renesas,pci-rcar-gen2" for a generic R-Car Gen2 compatible device
|
||||
|
||||
|
||||
When compatible with the generic version, nodes must list the
|
||||
SoC-specific version corresponding to the platform first
|
||||
followed by the generic version.
|
||||
|
||||
- reg: A list of physical regions to access the device: the first is
|
||||
the operational registers for the OHCI/EHCI controllers and the
|
||||
second is for the bridge configuration and control registers.
|
||||
@ -24,10 +31,15 @@ Required properties:
|
||||
- interrupt-map-mask: standard property that helps to define the interrupt
|
||||
mapping.
|
||||
|
||||
Optional properties:
|
||||
- dma-ranges: a single range for the inbound memory region. If not supplied,
|
||||
defaults to 1GiB at 0x40000000. Note there are hardware restrictions on the
|
||||
allowed combinations of address and size.
|
||||
|
||||
Example SoC configuration:
|
||||
|
||||
pci0: pci@ee090000 {
|
||||
compatible = "renesas,pci-r8a7790";
|
||||
compatible = "renesas,pci-r8a7790", "renesas,pci-rcar-gen2";
|
||||
clocks = <&mstp7_clks R8A7790_CLK_EHCI>;
|
||||
reg = <0x0 0xee090000 0x0 0xc00>,
|
||||
<0x0 0xee080000 0x0 0x1100>;
|
||||
@ -38,6 +50,7 @@ Example SoC configuration:
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
#interrupt-cells = <1>;
|
||||
dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x40000000>;
|
||||
interrupt-map-mask = <0xff00 0 0 0x7>;
|
||||
interrupt-map = <0x0000 0 0 1 &gic 0 108 IRQ_TYPE_LEVEL_HIGH
|
||||
0x0800 0 0 1 &gic 0 108 IRQ_TYPE_LEVEL_HIGH
|
||||
|
233
Documentation/devicetree/bindings/pci/qcom,pcie.txt
Normal file
233
Documentation/devicetree/bindings/pci/qcom,pcie.txt
Normal file
@ -0,0 +1,233 @@
|
||||
* Qualcomm PCI express root complex
|
||||
|
||||
- compatible:
|
||||
Usage: required
|
||||
Value type: <stringlist>
|
||||
Definition: Value should contain
|
||||
- "qcom,pcie-ipq8064" for ipq8064
|
||||
- "qcom,pcie-apq8064" for apq8064
|
||||
- "qcom,pcie-apq8084" for apq8084
|
||||
|
||||
- reg:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: Register ranges as listed in the reg-names property
|
||||
|
||||
- reg-names:
|
||||
Usage: required
|
||||
Value type: <stringlist>
|
||||
Definition: Must include the following entries
|
||||
- "parf" Qualcomm specific registers
|
||||
- "dbi" Designware PCIe registers
|
||||
- "elbi" External local bus interface registers
|
||||
- "config" PCIe configuration space
|
||||
|
||||
- device_type:
|
||||
Usage: required
|
||||
Value type: <string>
|
||||
Definition: Should be "pci". As specified in designware-pcie.txt
|
||||
|
||||
- #address-cells:
|
||||
Usage: required
|
||||
Value type: <u32>
|
||||
Definition: Should be 3. As specified in designware-pcie.txt
|
||||
|
||||
- #size-cells:
|
||||
Usage: required
|
||||
Value type: <u32>
|
||||
Definition: Should be 2. As specified in designware-pcie.txt
|
||||
|
||||
- ranges:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: As specified in designware-pcie.txt
|
||||
|
||||
- interrupts:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: MSI interrupt
|
||||
|
||||
- interrupt-names:
|
||||
Usage: required
|
||||
Value type: <stringlist>
|
||||
Definition: Should contain "msi"
|
||||
|
||||
- #interrupt-cells:
|
||||
Usage: required
|
||||
Value type: <u32>
|
||||
Definition: Should be 1. As specified in designware-pcie.txt
|
||||
|
||||
- interrupt-map-mask:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: As specified in designware-pcie.txt
|
||||
|
||||
- interrupt-map:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: As specified in designware-pcie.txt
|
||||
|
||||
- clocks:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: List of phandle and clock specifier pairs as listed
|
||||
in clock-names property
|
||||
|
||||
- clock-names:
|
||||
Usage: required
|
||||
Value type: <stringlist>
|
||||
Definition: Should contain the following entries
|
||||
- "iface" Configuration AHB clock
|
||||
|
||||
- clock-names:
|
||||
Usage: required for ipq/apq8064
|
||||
Value type: <stringlist>
|
||||
Definition: Should contain the following entries
|
||||
- "core" Clocks the pcie hw block
|
||||
- "phy" Clocks the pcie PHY block
|
||||
- clock-names:
|
||||
Usage: required for apq8084
|
||||
Value type: <stringlist>
|
||||
Definition: Should contain the following entries
|
||||
- "aux" Auxiliary (AUX) clock
|
||||
- "bus_master" Master AXI clock
|
||||
- "bus_slave" Slave AXI clock
|
||||
- resets:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: List of phandle and reset specifier pairs as listed
|
||||
in reset-names property
|
||||
|
||||
- reset-names:
|
||||
Usage: required for ipq/apq8064
|
||||
Value type: <stringlist>
|
||||
Definition: Should contain the following entries
|
||||
- "axi" AXI reset
|
||||
- "ahb" AHB reset
|
||||
- "por" POR reset
|
||||
- "pci" PCI reset
|
||||
- "phy" PHY reset
|
||||
|
||||
- reset-names:
|
||||
Usage: required for apq8084
|
||||
Value type: <stringlist>
|
||||
Definition: Should contain the following entries
|
||||
- "core" Core reset
|
||||
|
||||
- power-domains:
|
||||
Usage: required for apq8084
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: A phandle and power domain specifier pair to the
|
||||
power domain which is responsible for collapsing
|
||||
and restoring power to the peripheral
|
||||
|
||||
- vdda-supply:
|
||||
Usage: required
|
||||
Value type: <phandle>
|
||||
Definition: A phandle to the core analog power supply
|
||||
|
||||
- vdda_phy-supply:
|
||||
Usage: required for ipq/apq8064
|
||||
Value type: <phandle>
|
||||
Definition: A phandle to the analog power supply for PHY
|
||||
|
||||
- vdda_refclk-supply:
|
||||
Usage: required for ipq/apq8064
|
||||
Value type: <phandle>
|
||||
Definition: A phandle to the analog power supply for IC which generates
|
||||
reference clock
|
||||
|
||||
- phys:
|
||||
Usage: required for apq8084
|
||||
Value type: <phandle>
|
||||
Definition: List of phandle(s) as listed in phy-names property
|
||||
|
||||
- phy-names:
|
||||
Usage: required for apq8084
|
||||
Value type: <stringlist>
|
||||
Definition: Should contain "pciephy"
|
||||
|
||||
- <name>-gpios:
|
||||
Usage: optional
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: List of phandle and gpio specifier pairs. Should contain
|
||||
- "perst-gpios" PCIe endpoint reset signal line
|
||||
- "wake-gpios" PCIe endpoint wake signal line
|
||||
|
||||
* Example for ipq/apq8064
|
||||
pcie@1b500000 {
|
||||
compatible = "qcom,pcie-apq8064", "qcom,pcie-ipq8064", "snps,dw-pcie";
|
||||
reg = <0x1b500000 0x1000
|
||||
0x1b502000 0x80
|
||||
0x1b600000 0x100
|
||||
0x0ff00000 0x100000>;
|
||||
reg-names = "dbi", "elbi", "parf", "config";
|
||||
device_type = "pci";
|
||||
linux,pci-domain = <0>;
|
||||
bus-range = <0x00 0xff>;
|
||||
num-lanes = <1>;
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
ranges = <0x81000000 0 0 0x0fe00000 0 0x00100000 /* I/O */
|
||||
0x82000000 0 0 0x08000000 0 0x07e00000>; /* memory */
|
||||
interrupts = <GIC_SPI 238 IRQ_TYPE_NONE>;
|
||||
interrupt-names = "msi";
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 0x7>;
|
||||
interrupt-map = <0 0 0 1 &intc 0 36 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
|
||||
<0 0 0 2 &intc 0 37 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
|
||||
<0 0 0 3 &intc 0 38 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
|
||||
<0 0 0 4 &intc 0 39 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
|
||||
clocks = <&gcc PCIE_A_CLK>,
|
||||
<&gcc PCIE_H_CLK>,
|
||||
<&gcc PCIE_PHY_CLK>;
|
||||
clock-names = "core", "iface", "phy";
|
||||
resets = <&gcc PCIE_ACLK_RESET>,
|
||||
<&gcc PCIE_HCLK_RESET>,
|
||||
<&gcc PCIE_POR_RESET>,
|
||||
<&gcc PCIE_PCI_RESET>,
|
||||
<&gcc PCIE_PHY_RESET>;
|
||||
reset-names = "axi", "ahb", "por", "pci", "phy";
|
||||
pinctrl-0 = <&pcie_pins_default>;
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
|
||||
* Example for apq8084
|
||||
pcie0@fc520000 {
|
||||
compatible = "qcom,pcie-apq8084", "snps,dw-pcie";
|
||||
reg = <0xfc520000 0x2000>,
|
||||
<0xff000000 0x1000>,
|
||||
<0xff001000 0x1000>,
|
||||
<0xff002000 0x2000>;
|
||||
reg-names = "parf", "dbi", "elbi", "config";
|
||||
device_type = "pci";
|
||||
linux,pci-domain = <0>;
|
||||
bus-range = <0x00 0xff>;
|
||||
num-lanes = <1>;
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
ranges = <0x81000000 0 0 0xff200000 0 0x00100000 /* I/O */
|
||||
0x82000000 0 0x00300000 0xff300000 0 0x00d00000>; /* memory */
|
||||
interrupts = <GIC_SPI 243 IRQ_TYPE_NONE>;
|
||||
interrupt-names = "msi";
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 0x7>;
|
||||
interrupt-map = <0 0 0 1 &intc 0 244 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
|
||||
<0 0 0 2 &intc 0 245 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
|
||||
<0 0 0 3 &intc 0 247 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
|
||||
<0 0 0 4 &intc 0 248 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
|
||||
clocks = <&gcc GCC_PCIE_0_CFG_AHB_CLK>,
|
||||
<&gcc GCC_PCIE_0_MSTR_AXI_CLK>,
|
||||
<&gcc GCC_PCIE_0_SLV_AXI_CLK>,
|
||||
<&gcc GCC_PCIE_0_AUX_CLK>;
|
||||
clock-names = "iface", "master_bus", "slave_bus", "aux";
|
||||
resets = <&gcc GCC_PCIE_0_BCR>;
|
||||
reset-names = "core";
|
||||
power-domains = <&gcc PCIE0_GDSC>;
|
||||
vdda-supply = <&pma8084_l3>;
|
||||
phys = <&pciephy0>;
|
||||
phy-names = "pciephy";
|
||||
perst-gpio = <&tlmm 70 GPIO_ACTIVE_LOW>;
|
||||
pinctrl-0 = <&pcie0_pins_default>;
|
||||
pinctrl-names = "default";
|
||||
};
|
@ -1,8 +1,16 @@
|
||||
* Renesas RCar PCIe interface
|
||||
|
||||
Required properties:
|
||||
- compatible: should contain one of the following
|
||||
"renesas,pcie-r8a7779", "renesas,pcie-r8a7790", "renesas,pcie-r8a7791"
|
||||
compatible: "renesas,pcie-r8a7779" for the R8A7779 SoC;
|
||||
"renesas,pcie-r8a7790" for the R8A7790 SoC;
|
||||
"renesas,pcie-r8a7791" for the R8A7791 SoC;
|
||||
"renesas,pcie-r8a7795" for the R8A7795 SoC;
|
||||
"renesas,pcie-rcar-gen2" for a generic R-Car Gen2 compatible device.
|
||||
|
||||
When compatible with the generic version, nodes must list the
|
||||
SoC-specific version corresponding to the platform first
|
||||
followed by the generic version.
|
||||
|
||||
- reg: base address and length of the pcie controller registers.
|
||||
- #address-cells: set to <3>
|
||||
- #size-cells: set to <2>
|
||||
@ -25,7 +33,7 @@ Example:
|
||||
SoC specific DT Entry:
|
||||
|
||||
pcie: pcie@fe000000 {
|
||||
compatible = "renesas,pcie-r8a7791";
|
||||
compatible = "renesas,pcie-r8a7791", "renesas,pcie-rcar-gen2";
|
||||
reg = <0 0xfe000000 0 0x80000>;
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
|
14
MAINTAINERS
14
MAINTAINERS
@ -8317,6 +8317,12 @@ S: Maintained
|
||||
F: Documentation/devicetree/bindings/pci/host-generic-pci.txt
|
||||
F: drivers/pci/host/pci-host-generic.c
|
||||
|
||||
PCI DRIVER FOR INTEL VOLUME MANAGEMENT DEVICE (VMD)
|
||||
M: Keith Busch <keith.busch@intel.com>
|
||||
L: linux-pci@vger.kernel.org
|
||||
S: Supported
|
||||
F: arch/x86/pci/vmd.c
|
||||
|
||||
PCIE DRIVER FOR ST SPEAR13XX
|
||||
M: Pratyush Anand <pratyush.anand@gmail.com>
|
||||
L: linux-pci@vger.kernel.org
|
||||
@ -8341,11 +8347,19 @@ F: drivers/pci/host/pci-xgene-msi.c
|
||||
|
||||
PCIE DRIVER FOR HISILICON
|
||||
M: Zhou Wang <wangzhou1@hisilicon.com>
|
||||
M: Gabriele Paoloni <gabriele.paoloni@huawei.com>
|
||||
L: linux-pci@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
|
||||
F: drivers/pci/host/pcie-hisi.c
|
||||
|
||||
PCIE DRIVER FOR QUALCOMM MSM
|
||||
M: Stanimir Varbanov <svarbanov@mm-sol.com>
|
||||
L: linux-pci@vger.kernel.org
|
||||
L: linux-arm-msm@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/pci/host/*qcom*
|
||||
|
||||
PCMCIA SUBSYSTEM
|
||||
P: Linux PCMCIA Team
|
||||
L: linux-pcmcia@lists.infradead.org
|
||||
|
@ -47,6 +47,18 @@
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
pcie_pins: pcie_pinmux {
|
||||
mux {
|
||||
pins = "gpio27";
|
||||
function = "gpio";
|
||||
};
|
||||
conf {
|
||||
pins = "gpio27";
|
||||
drive-strength = <12>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
rpm@108000 {
|
||||
@ -123,6 +135,10 @@
|
||||
lvs1 {
|
||||
bias-pull-down;
|
||||
};
|
||||
|
||||
lvs6 {
|
||||
bias-pull-down;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@ -231,6 +247,16 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pci@1b500000 {
|
||||
status = "ok";
|
||||
vdda-supply = <&pm8921_s3>;
|
||||
vdda_phy-supply = <&pm8921_lvs6>;
|
||||
vdda_refclk-supply = <&ext_3p3v>;
|
||||
pinctrl-0 = <&pcie_pins>;
|
||||
pinctrl-names = "default";
|
||||
perst-gpio = <&tlmm_pinmux 27 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
qcom,ssbi@500000 {
|
||||
pmic@0 {
|
||||
gpio@150 {
|
||||
|
@ -785,5 +785,41 @@
|
||||
compatible = "qcom,tcsr-apq8064", "syscon";
|
||||
reg = <0x1a400000 0x100>;
|
||||
};
|
||||
|
||||
pcie: pci@1b500000 {
|
||||
compatible = "qcom,pcie-apq8064", "snps,dw-pcie";
|
||||
reg = <0x1b500000 0x1000
|
||||
0x1b502000 0x80
|
||||
0x1b600000 0x100
|
||||
0x0ff00000 0x100000>;
|
||||
reg-names = "dbi", "elbi", "parf", "config";
|
||||
device_type = "pci";
|
||||
linux,pci-domain = <0>;
|
||||
bus-range = <0x00 0xff>;
|
||||
num-lanes = <1>;
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
ranges = <0x81000000 0 0 0x0fe00000 0 0x00100000 /* I/O */
|
||||
0x82000000 0 0 0x08000000 0 0x07e00000>; /* memory */
|
||||
interrupts = <GIC_SPI 238 IRQ_TYPE_NONE>;
|
||||
interrupt-names = "msi";
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 0x7>;
|
||||
interrupt-map = <0 0 0 1 &intc 0 36 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
|
||||
<0 0 0 2 &intc 0 37 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
|
||||
<0 0 0 3 &intc 0 38 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
|
||||
<0 0 0 4 &intc 0 39 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
|
||||
clocks = <&gcc PCIE_A_CLK>,
|
||||
<&gcc PCIE_H_CLK>,
|
||||
<&gcc PCIE_PHY_REF_CLK>;
|
||||
clock-names = "core", "iface", "phy";
|
||||
resets = <&gcc PCIE_ACLK_RESET>,
|
||||
<&gcc PCIE_HCLK_RESET>,
|
||||
<&gcc PCIE_POR_RESET>,
|
||||
<&gcc PCIE_PCI_RESET>,
|
||||
<&gcc PCIE_PHY_RESET>;
|
||||
reset-names = "axi", "ahb", "por", "pci", "phy";
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -400,7 +400,7 @@ static void *eeh_rmv_device(void *data, void *userdata)
|
||||
* support EEH. So we just care about PCI devices for
|
||||
* simplicity here.
|
||||
*/
|
||||
if (!dev || (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE))
|
||||
if (!dev || (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
|
@ -187,9 +187,6 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
|
||||
|
||||
pci_device_add(dev, bus);
|
||||
|
||||
/* Setup MSI caps & disable MSI/MSI-X interrupts */
|
||||
pci_msi_setup_pci_dev(dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
EXPORT_SYMBOL(of_create_pci_dev);
|
||||
|
@ -2699,6 +2699,19 @@ config PMC_ATOM
|
||||
def_bool y
|
||||
depends on PCI
|
||||
|
||||
config VMD
|
||||
depends on PCI_MSI
|
||||
tristate "Volume Management Device Driver"
|
||||
default N
|
||||
---help---
|
||||
Adds support for the Intel Volume Management Device (VMD). VMD is a
|
||||
secondary PCI host bridge that allows PCI Express root ports,
|
||||
and devices attached to them, to be removed from the default
|
||||
PCI domain and placed within the VMD domain. This provides
|
||||
more bus resources than are otherwise possible with a
|
||||
single domain. If you know your system provides one of these and
|
||||
has devices attached to it, say Y; if you are not sure, say N.
|
||||
|
||||
source "net/Kconfig"
|
||||
|
||||
source "drivers/Kconfig"
|
||||
|
@ -10,6 +10,16 @@ struct dev_archdata {
|
||||
#endif
|
||||
};
|
||||
|
||||
#if defined(CONFIG_X86_DEV_DMA_OPS) && defined(CONFIG_PCI_DOMAINS)
|
||||
struct dma_domain {
|
||||
struct list_head node;
|
||||
struct dma_map_ops *dma_ops;
|
||||
int domain_nr;
|
||||
};
|
||||
void add_dma_domain(struct dma_domain *domain);
|
||||
void del_dma_domain(struct dma_domain *domain);
|
||||
#endif
|
||||
|
||||
struct pdev_archdata {
|
||||
};
|
||||
|
||||
|
@ -129,6 +129,11 @@ struct irq_alloc_info {
|
||||
unsigned long uv_offset;
|
||||
char *uv_name;
|
||||
};
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_VMD)
|
||||
struct {
|
||||
struct msi_desc *desc;
|
||||
};
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
@ -151,11 +151,11 @@ extern struct list_head pci_mmcfg_list;
|
||||
#define PCI_MMCFG_BUS_OFFSET(bus) ((bus) << 20)
|
||||
|
||||
/*
|
||||
* AMD Fam10h CPUs are buggy, and cannot access MMIO config space
|
||||
* on their northbrige except through the * %eax register. As such, you MUST
|
||||
* NOT use normal IOMEM accesses, you need to only use the magic mmio-config
|
||||
* accessor functions.
|
||||
* In fact just use pci_config_*, nothing else please.
|
||||
* On AMD Fam10h CPUs, all PCI MMIO configuration space accesses must use
|
||||
* %eax. No other source or target registers may be used. The following
|
||||
* mmio_config_* accessors enforce this. See "BIOS and Kernel Developer's
|
||||
* Guide (BKDG) For AMD Family 10h Processors", rev. 3.48, sec 2.11.1,
|
||||
* "MMIO Configuration Coding Requirements".
|
||||
*/
|
||||
static inline unsigned char mmio_config_readb(void __iomem *pos)
|
||||
{
|
||||
|
@ -23,6 +23,8 @@ obj-y += bus_numa.o
|
||||
obj-$(CONFIG_AMD_NB) += amd_bus.o
|
||||
obj-$(CONFIG_PCI_CNB20LE_QUIRK) += broadcom_bus.o
|
||||
|
||||
obj-$(CONFIG_VMD) += vmd.o
|
||||
|
||||
ifeq ($(CONFIG_PCI_DEBUG),y)
|
||||
EXTRA_CFLAGS += -DDEBUG
|
||||
endif
|
||||
|
@ -641,6 +641,43 @@ unsigned int pcibios_assign_all_busses(void)
|
||||
return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_X86_DEV_DMA_OPS) && defined(CONFIG_PCI_DOMAINS)
|
||||
static LIST_HEAD(dma_domain_list);
|
||||
static DEFINE_SPINLOCK(dma_domain_list_lock);
|
||||
|
||||
void add_dma_domain(struct dma_domain *domain)
|
||||
{
|
||||
spin_lock(&dma_domain_list_lock);
|
||||
list_add(&domain->node, &dma_domain_list);
|
||||
spin_unlock(&dma_domain_list_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(add_dma_domain);
|
||||
|
||||
void del_dma_domain(struct dma_domain *domain)
|
||||
{
|
||||
spin_lock(&dma_domain_list_lock);
|
||||
list_del(&domain->node);
|
||||
spin_unlock(&dma_domain_list_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(del_dma_domain);
|
||||
|
||||
static void set_dma_domain_ops(struct pci_dev *pdev)
|
||||
{
|
||||
struct dma_domain *domain;
|
||||
|
||||
spin_lock(&dma_domain_list_lock);
|
||||
list_for_each_entry(domain, &dma_domain_list, node) {
|
||||
if (pci_domain_nr(pdev->bus) == domain->domain_nr) {
|
||||
pdev->dev.archdata.dma_ops = domain->dma_ops;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock(&dma_domain_list_lock);
|
||||
}
|
||||
#else
|
||||
static void set_dma_domain_ops(struct pci_dev *pdev) {}
|
||||
#endif
|
||||
|
||||
int pcibios_add_device(struct pci_dev *dev)
|
||||
{
|
||||
struct setup_data *data;
|
||||
@ -670,6 +707,7 @@ int pcibios_add_device(struct pci_dev *dev)
|
||||
pa_data = data->next;
|
||||
iounmap(data);
|
||||
}
|
||||
set_dma_domain_ops(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -180,6 +180,7 @@ static int pci_bios_read(unsigned int seg, unsigned int bus,
|
||||
unsigned long result = 0;
|
||||
unsigned long flags;
|
||||
unsigned long bx = (bus << 8) | devfn;
|
||||
u16 number = 0, mask = 0;
|
||||
|
||||
WARN_ON(seg);
|
||||
if (!value || (bus > 255) || (devfn > 255) || (reg > 255))
|
||||
@ -189,53 +190,35 @@ static int pci_bios_read(unsigned int seg, unsigned int bus,
|
||||
|
||||
switch (len) {
|
||||
case 1:
|
||||
__asm__("lcall *(%%esi); cld\n\t"
|
||||
"jc 1f\n\t"
|
||||
"xor %%ah, %%ah\n"
|
||||
"1:"
|
||||
: "=c" (*value),
|
||||
"=a" (result)
|
||||
: "1" (PCIBIOS_READ_CONFIG_BYTE),
|
||||
"b" (bx),
|
||||
"D" ((long)reg),
|
||||
"S" (&pci_indirect));
|
||||
/*
|
||||
* Zero-extend the result beyond 8 bits, do not trust the
|
||||
* BIOS having done it:
|
||||
*/
|
||||
*value &= 0xff;
|
||||
number = PCIBIOS_READ_CONFIG_BYTE;
|
||||
mask = 0xff;
|
||||
break;
|
||||
case 2:
|
||||
__asm__("lcall *(%%esi); cld\n\t"
|
||||
"jc 1f\n\t"
|
||||
"xor %%ah, %%ah\n"
|
||||
"1:"
|
||||
: "=c" (*value),
|
||||
"=a" (result)
|
||||
: "1" (PCIBIOS_READ_CONFIG_WORD),
|
||||
"b" (bx),
|
||||
"D" ((long)reg),
|
||||
"S" (&pci_indirect));
|
||||
/*
|
||||
* Zero-extend the result beyond 16 bits, do not trust the
|
||||
* BIOS having done it:
|
||||
*/
|
||||
*value &= 0xffff;
|
||||
number = PCIBIOS_READ_CONFIG_WORD;
|
||||
mask = 0xffff;
|
||||
break;
|
||||
case 4:
|
||||
__asm__("lcall *(%%esi); cld\n\t"
|
||||
"jc 1f\n\t"
|
||||
"xor %%ah, %%ah\n"
|
||||
"1:"
|
||||
: "=c" (*value),
|
||||
"=a" (result)
|
||||
: "1" (PCIBIOS_READ_CONFIG_DWORD),
|
||||
"b" (bx),
|
||||
"D" ((long)reg),
|
||||
"S" (&pci_indirect));
|
||||
number = PCIBIOS_READ_CONFIG_DWORD;
|
||||
break;
|
||||
}
|
||||
|
||||
__asm__("lcall *(%%esi); cld\n\t"
|
||||
"jc 1f\n\t"
|
||||
"xor %%ah, %%ah\n"
|
||||
"1:"
|
||||
: "=c" (*value),
|
||||
"=a" (result)
|
||||
: "1" (number),
|
||||
"b" (bx),
|
||||
"D" ((long)reg),
|
||||
"S" (&pci_indirect));
|
||||
/*
|
||||
* Zero-extend the result beyond 8 or 16 bits, do not trust the
|
||||
* BIOS having done it:
|
||||
*/
|
||||
if (mask)
|
||||
*value &= mask;
|
||||
|
||||
raw_spin_unlock_irqrestore(&pci_config_lock, flags);
|
||||
|
||||
return (int)((result & 0xff00) >> 8);
|
||||
@ -247,6 +230,7 @@ static int pci_bios_write(unsigned int seg, unsigned int bus,
|
||||
unsigned long result = 0;
|
||||
unsigned long flags;
|
||||
unsigned long bx = (bus << 8) | devfn;
|
||||
u16 number = 0;
|
||||
|
||||
WARN_ON(seg);
|
||||
if ((bus > 255) || (devfn > 255) || (reg > 255))
|
||||
@ -256,43 +240,27 @@ static int pci_bios_write(unsigned int seg, unsigned int bus,
|
||||
|
||||
switch (len) {
|
||||
case 1:
|
||||
__asm__("lcall *(%%esi); cld\n\t"
|
||||
"jc 1f\n\t"
|
||||
"xor %%ah, %%ah\n"
|
||||
"1:"
|
||||
: "=a" (result)
|
||||
: "0" (PCIBIOS_WRITE_CONFIG_BYTE),
|
||||
"c" (value),
|
||||
"b" (bx),
|
||||
"D" ((long)reg),
|
||||
"S" (&pci_indirect));
|
||||
number = PCIBIOS_WRITE_CONFIG_BYTE;
|
||||
break;
|
||||
case 2:
|
||||
__asm__("lcall *(%%esi); cld\n\t"
|
||||
"jc 1f\n\t"
|
||||
"xor %%ah, %%ah\n"
|
||||
"1:"
|
||||
: "=a" (result)
|
||||
: "0" (PCIBIOS_WRITE_CONFIG_WORD),
|
||||
"c" (value),
|
||||
"b" (bx),
|
||||
"D" ((long)reg),
|
||||
"S" (&pci_indirect));
|
||||
number = PCIBIOS_WRITE_CONFIG_WORD;
|
||||
break;
|
||||
case 4:
|
||||
__asm__("lcall *(%%esi); cld\n\t"
|
||||
"jc 1f\n\t"
|
||||
"xor %%ah, %%ah\n"
|
||||
"1:"
|
||||
: "=a" (result)
|
||||
: "0" (PCIBIOS_WRITE_CONFIG_DWORD),
|
||||
"c" (value),
|
||||
"b" (bx),
|
||||
"D" ((long)reg),
|
||||
"S" (&pci_indirect));
|
||||
number = PCIBIOS_WRITE_CONFIG_DWORD;
|
||||
break;
|
||||
}
|
||||
|
||||
__asm__("lcall *(%%esi); cld\n\t"
|
||||
"jc 1f\n\t"
|
||||
"xor %%ah, %%ah\n"
|
||||
"1:"
|
||||
: "=a" (result)
|
||||
: "0" (number),
|
||||
"c" (value),
|
||||
"b" (bx),
|
||||
"D" ((long)reg),
|
||||
"S" (&pci_indirect));
|
||||
|
||||
raw_spin_unlock_irqrestore(&pci_config_lock, flags);
|
||||
|
||||
return (int)((result & 0xff00) >> 8);
|
||||
|
723
arch/x86/pci/vmd.c
Normal file
723
arch/x86/pci/vmd.c
Normal file
@ -0,0 +1,723 @@
|
||||
/*
|
||||
* Volume Management Device driver
|
||||
* Copyright (c) 2015, Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/msi.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/rculist.h>
|
||||
#include <linux/rcupdate.h>
|
||||
|
||||
#include <asm/irqdomain.h>
|
||||
#include <asm/device.h>
|
||||
#include <asm/msi.h>
|
||||
#include <asm/msidef.h>
|
||||
|
||||
#define VMD_CFGBAR 0
|
||||
#define VMD_MEMBAR1 2
|
||||
#define VMD_MEMBAR2 4
|
||||
|
||||
/*
|
||||
* Lock for manipulating VMD IRQ lists.
|
||||
*/
|
||||
static DEFINE_RAW_SPINLOCK(list_lock);
|
||||
|
||||
/**
|
||||
* struct vmd_irq - private data to map driver IRQ to the VMD shared vector
|
||||
* @node: list item for parent traversal.
|
||||
* @rcu: RCU callback item for freeing.
|
||||
* @irq: back pointer to parent.
|
||||
* @virq: the virtual IRQ value provided to the requesting driver.
|
||||
*
|
||||
* Every MSI/MSI-X IRQ requested for a device in a VMD domain will be mapped to
|
||||
* a VMD IRQ using this structure.
|
||||
*/
|
||||
struct vmd_irq {
|
||||
struct list_head node;
|
||||
struct rcu_head rcu;
|
||||
struct vmd_irq_list *irq;
|
||||
unsigned int virq;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct vmd_irq_list - list of driver requested IRQs mapping to a VMD vector
|
||||
* @irq_list: the list of irq's the VMD one demuxes to.
|
||||
* @vmd_vector: the h/w IRQ assigned to the VMD.
|
||||
* @index: index into the VMD MSI-X table; used for message routing.
|
||||
* @count: number of child IRQs assigned to this vector; used to track
|
||||
* sharing.
|
||||
*/
|
||||
struct vmd_irq_list {
|
||||
struct list_head irq_list;
|
||||
struct vmd_dev *vmd;
|
||||
unsigned int vmd_vector;
|
||||
unsigned int index;
|
||||
unsigned int count;
|
||||
};
|
||||
|
||||
struct vmd_dev {
|
||||
struct pci_dev *dev;
|
||||
|
||||
spinlock_t cfg_lock;
|
||||
char __iomem *cfgbar;
|
||||
|
||||
int msix_count;
|
||||
struct msix_entry *msix_entries;
|
||||
struct vmd_irq_list *irqs;
|
||||
|
||||
struct pci_sysdata sysdata;
|
||||
struct resource resources[3];
|
||||
struct irq_domain *irq_domain;
|
||||
struct pci_bus *bus;
|
||||
|
||||
#ifdef CONFIG_X86_DEV_DMA_OPS
|
||||
struct dma_map_ops dma_ops;
|
||||
struct dma_domain dma_domain;
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline struct vmd_dev *vmd_from_bus(struct pci_bus *bus)
|
||||
{
|
||||
return container_of(bus->sysdata, struct vmd_dev, sysdata);
|
||||
}
|
||||
|
||||
/*
|
||||
* Drivers managing a device in a VMD domain allocate their own IRQs as before,
|
||||
* but the MSI entry for the hardware it's driving will be programmed with a
|
||||
* destination ID for the VMD MSI-X table. The VMD muxes interrupts in its
|
||||
* domain into one of its own, and the VMD driver de-muxes these for the
|
||||
* handlers sharing that VMD IRQ. The vmd irq_domain provides the operations
|
||||
* and irq_chip to set this up.
|
||||
*/
|
||||
static void vmd_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
|
||||
{
|
||||
struct vmd_irq *vmdirq = data->chip_data;
|
||||
struct vmd_irq_list *irq = vmdirq->irq;
|
||||
|
||||
msg->address_hi = MSI_ADDR_BASE_HI;
|
||||
msg->address_lo = MSI_ADDR_BASE_LO | MSI_ADDR_DEST_ID(irq->index);
|
||||
msg->data = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We rely on MSI_FLAG_USE_DEF_CHIP_OPS to set the IRQ mask/unmask ops.
|
||||
*/
|
||||
static void vmd_irq_enable(struct irq_data *data)
|
||||
{
|
||||
struct vmd_irq *vmdirq = data->chip_data;
|
||||
|
||||
raw_spin_lock(&list_lock);
|
||||
list_add_tail_rcu(&vmdirq->node, &vmdirq->irq->irq_list);
|
||||
raw_spin_unlock(&list_lock);
|
||||
|
||||
data->chip->irq_unmask(data);
|
||||
}
|
||||
|
||||
static void vmd_irq_disable(struct irq_data *data)
|
||||
{
|
||||
struct vmd_irq *vmdirq = data->chip_data;
|
||||
|
||||
data->chip->irq_mask(data);
|
||||
|
||||
raw_spin_lock(&list_lock);
|
||||
list_del_rcu(&vmdirq->node);
|
||||
raw_spin_unlock(&list_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: Stubbed until we develop acceptable way to not create conflicts with
|
||||
* other devices sharing the same vector.
|
||||
*/
|
||||
static int vmd_irq_set_affinity(struct irq_data *data,
|
||||
const struct cpumask *dest, bool force)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static struct irq_chip vmd_msi_controller = {
|
||||
.name = "VMD-MSI",
|
||||
.irq_enable = vmd_irq_enable,
|
||||
.irq_disable = vmd_irq_disable,
|
||||
.irq_compose_msi_msg = vmd_compose_msi_msg,
|
||||
.irq_set_affinity = vmd_irq_set_affinity,
|
||||
};
|
||||
|
||||
static irq_hw_number_t vmd_get_hwirq(struct msi_domain_info *info,
|
||||
msi_alloc_info_t *arg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: We can be even smarter selecting the best IRQ once we solve the
|
||||
* affinity problem.
|
||||
*/
|
||||
static struct vmd_irq_list *vmd_next_irq(struct vmd_dev *vmd)
|
||||
{
|
||||
int i, best = 0;
|
||||
|
||||
raw_spin_lock(&list_lock);
|
||||
for (i = 1; i < vmd->msix_count; i++)
|
||||
if (vmd->irqs[i].count < vmd->irqs[best].count)
|
||||
best = i;
|
||||
vmd->irqs[best].count++;
|
||||
raw_spin_unlock(&list_lock);
|
||||
|
||||
return &vmd->irqs[best];
|
||||
}
|
||||
|
||||
static int vmd_msi_init(struct irq_domain *domain, struct msi_domain_info *info,
|
||||
unsigned int virq, irq_hw_number_t hwirq,
|
||||
msi_alloc_info_t *arg)
|
||||
{
|
||||
struct vmd_dev *vmd = vmd_from_bus(msi_desc_to_pci_dev(arg->desc)->bus);
|
||||
struct vmd_irq *vmdirq = kzalloc(sizeof(*vmdirq), GFP_KERNEL);
|
||||
|
||||
if (!vmdirq)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_LIST_HEAD(&vmdirq->node);
|
||||
vmdirq->irq = vmd_next_irq(vmd);
|
||||
vmdirq->virq = virq;
|
||||
|
||||
irq_domain_set_info(domain, virq, vmdirq->irq->vmd_vector, info->chip,
|
||||
vmdirq, handle_simple_irq, vmd, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vmd_msi_free(struct irq_domain *domain,
|
||||
struct msi_domain_info *info, unsigned int virq)
|
||||
{
|
||||
struct vmd_irq *vmdirq = irq_get_chip_data(virq);
|
||||
|
||||
/* XXX: Potential optimization to rebalance */
|
||||
raw_spin_lock(&list_lock);
|
||||
vmdirq->irq->count--;
|
||||
raw_spin_unlock(&list_lock);
|
||||
|
||||
kfree_rcu(vmdirq, rcu);
|
||||
}
|
||||
|
||||
static int vmd_msi_prepare(struct irq_domain *domain, struct device *dev,
|
||||
int nvec, msi_alloc_info_t *arg)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct vmd_dev *vmd = vmd_from_bus(pdev->bus);
|
||||
|
||||
if (nvec > vmd->msix_count)
|
||||
return vmd->msix_count;
|
||||
|
||||
memset(arg, 0, sizeof(*arg));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vmd_set_desc(msi_alloc_info_t *arg, struct msi_desc *desc)
|
||||
{
|
||||
arg->desc = desc;
|
||||
}
|
||||
|
||||
static struct msi_domain_ops vmd_msi_domain_ops = {
|
||||
.get_hwirq = vmd_get_hwirq,
|
||||
.msi_init = vmd_msi_init,
|
||||
.msi_free = vmd_msi_free,
|
||||
.msi_prepare = vmd_msi_prepare,
|
||||
.set_desc = vmd_set_desc,
|
||||
};
|
||||
|
||||
static struct msi_domain_info vmd_msi_domain_info = {
|
||||
.flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
|
||||
MSI_FLAG_PCI_MSIX,
|
||||
.ops = &vmd_msi_domain_ops,
|
||||
.chip = &vmd_msi_controller,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_X86_DEV_DMA_OPS
|
||||
/*
|
||||
* VMD replaces the requester ID with its own. DMA mappings for devices in a
|
||||
* VMD domain need to be mapped for the VMD, not the device requiring
|
||||
* the mapping.
|
||||
*/
|
||||
static struct device *to_vmd_dev(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct vmd_dev *vmd = vmd_from_bus(pdev->bus);
|
||||
|
||||
return &vmd->dev->dev;
|
||||
}
|
||||
|
||||
static struct dma_map_ops *vmd_dma_ops(struct device *dev)
|
||||
{
|
||||
return to_vmd_dev(dev)->archdata.dma_ops;
|
||||
}
|
||||
|
||||
static void *vmd_alloc(struct device *dev, size_t size, dma_addr_t *addr,
|
||||
gfp_t flag, struct dma_attrs *attrs)
|
||||
{
|
||||
return vmd_dma_ops(dev)->alloc(to_vmd_dev(dev), size, addr, flag,
|
||||
attrs);
|
||||
}
|
||||
|
||||
static void vmd_free(struct device *dev, size_t size, void *vaddr,
|
||||
dma_addr_t addr, struct dma_attrs *attrs)
|
||||
{
|
||||
return vmd_dma_ops(dev)->free(to_vmd_dev(dev), size, vaddr, addr,
|
||||
attrs);
|
||||
}
|
||||
|
||||
static int vmd_mmap(struct device *dev, struct vm_area_struct *vma,
|
||||
void *cpu_addr, dma_addr_t addr, size_t size,
|
||||
struct dma_attrs *attrs)
|
||||
{
|
||||
return vmd_dma_ops(dev)->mmap(to_vmd_dev(dev), vma, cpu_addr, addr,
|
||||
size, attrs);
|
||||
}
|
||||
|
||||
static int vmd_get_sgtable(struct device *dev, struct sg_table *sgt,
|
||||
void *cpu_addr, dma_addr_t addr, size_t size,
|
||||
struct dma_attrs *attrs)
|
||||
{
|
||||
return vmd_dma_ops(dev)->get_sgtable(to_vmd_dev(dev), sgt, cpu_addr,
|
||||
addr, size, attrs);
|
||||
}
|
||||
|
||||
static dma_addr_t vmd_map_page(struct device *dev, struct page *page,
|
||||
unsigned long offset, size_t size,
|
||||
enum dma_data_direction dir,
|
||||
struct dma_attrs *attrs)
|
||||
{
|
||||
return vmd_dma_ops(dev)->map_page(to_vmd_dev(dev), page, offset, size,
|
||||
dir, attrs);
|
||||
}
|
||||
|
||||
static void vmd_unmap_page(struct device *dev, dma_addr_t addr, size_t size,
|
||||
enum dma_data_direction dir, struct dma_attrs *attrs)
|
||||
{
|
||||
vmd_dma_ops(dev)->unmap_page(to_vmd_dev(dev), addr, size, dir, attrs);
|
||||
}
|
||||
|
||||
static int vmd_map_sg(struct device *dev, struct scatterlist *sg, int nents,
|
||||
enum dma_data_direction dir, struct dma_attrs *attrs)
|
||||
{
|
||||
return vmd_dma_ops(dev)->map_sg(to_vmd_dev(dev), sg, nents, dir, attrs);
|
||||
}
|
||||
|
||||
static void vmd_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
|
||||
enum dma_data_direction dir, struct dma_attrs *attrs)
|
||||
{
|
||||
vmd_dma_ops(dev)->unmap_sg(to_vmd_dev(dev), sg, nents, dir, attrs);
|
||||
}
|
||||
|
||||
static void vmd_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
|
||||
size_t size, enum dma_data_direction dir)
|
||||
{
|
||||
vmd_dma_ops(dev)->sync_single_for_cpu(to_vmd_dev(dev), addr, size, dir);
|
||||
}
|
||||
|
||||
static void vmd_sync_single_for_device(struct device *dev, dma_addr_t addr,
|
||||
size_t size, enum dma_data_direction dir)
|
||||
{
|
||||
vmd_dma_ops(dev)->sync_single_for_device(to_vmd_dev(dev), addr, size,
|
||||
dir);
|
||||
}
|
||||
|
||||
static void vmd_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
|
||||
int nents, enum dma_data_direction dir)
|
||||
{
|
||||
vmd_dma_ops(dev)->sync_sg_for_cpu(to_vmd_dev(dev), sg, nents, dir);
|
||||
}
|
||||
|
||||
static void vmd_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
|
||||
int nents, enum dma_data_direction dir)
|
||||
{
|
||||
vmd_dma_ops(dev)->sync_sg_for_device(to_vmd_dev(dev), sg, nents, dir);
|
||||
}
|
||||
|
||||
static int vmd_mapping_error(struct device *dev, dma_addr_t addr)
|
||||
{
|
||||
return vmd_dma_ops(dev)->mapping_error(to_vmd_dev(dev), addr);
|
||||
}
|
||||
|
||||
static int vmd_dma_supported(struct device *dev, u64 mask)
|
||||
{
|
||||
return vmd_dma_ops(dev)->dma_supported(to_vmd_dev(dev), mask);
|
||||
}
|
||||
|
||||
#ifdef ARCH_HAS_DMA_GET_REQUIRED_MASK
|
||||
static u64 vmd_get_required_mask(struct device *dev)
|
||||
{
|
||||
return vmd_dma_ops(dev)->get_required_mask(to_vmd_dev(dev));
|
||||
}
|
||||
#endif
|
||||
|
||||
static void vmd_teardown_dma_ops(struct vmd_dev *vmd)
|
||||
{
|
||||
struct dma_domain *domain = &vmd->dma_domain;
|
||||
|
||||
if (vmd->dev->dev.archdata.dma_ops)
|
||||
del_dma_domain(domain);
|
||||
}
|
||||
|
||||
#define ASSIGN_VMD_DMA_OPS(source, dest, fn) \
|
||||
do { \
|
||||
if (source->fn) \
|
||||
dest->fn = vmd_##fn; \
|
||||
} while (0)
|
||||
|
||||
static void vmd_setup_dma_ops(struct vmd_dev *vmd)
|
||||
{
|
||||
const struct dma_map_ops *source = vmd->dev->dev.archdata.dma_ops;
|
||||
struct dma_map_ops *dest = &vmd->dma_ops;
|
||||
struct dma_domain *domain = &vmd->dma_domain;
|
||||
|
||||
domain->domain_nr = vmd->sysdata.domain;
|
||||
domain->dma_ops = dest;
|
||||
|
||||
if (!source)
|
||||
return;
|
||||
ASSIGN_VMD_DMA_OPS(source, dest, alloc);
|
||||
ASSIGN_VMD_DMA_OPS(source, dest, free);
|
||||
ASSIGN_VMD_DMA_OPS(source, dest, mmap);
|
||||
ASSIGN_VMD_DMA_OPS(source, dest, get_sgtable);
|
||||
ASSIGN_VMD_DMA_OPS(source, dest, map_page);
|
||||
ASSIGN_VMD_DMA_OPS(source, dest, unmap_page);
|
||||
ASSIGN_VMD_DMA_OPS(source, dest, map_sg);
|
||||
ASSIGN_VMD_DMA_OPS(source, dest, unmap_sg);
|
||||
ASSIGN_VMD_DMA_OPS(source, dest, sync_single_for_cpu);
|
||||
ASSIGN_VMD_DMA_OPS(source, dest, sync_single_for_device);
|
||||
ASSIGN_VMD_DMA_OPS(source, dest, sync_sg_for_cpu);
|
||||
ASSIGN_VMD_DMA_OPS(source, dest, sync_sg_for_device);
|
||||
ASSIGN_VMD_DMA_OPS(source, dest, mapping_error);
|
||||
ASSIGN_VMD_DMA_OPS(source, dest, dma_supported);
|
||||
#ifdef ARCH_HAS_DMA_GET_REQUIRED_MASK
|
||||
ASSIGN_VMD_DMA_OPS(source, dest, get_required_mask);
|
||||
#endif
|
||||
add_dma_domain(domain);
|
||||
}
|
||||
#undef ASSIGN_VMD_DMA_OPS
|
||||
#else
|
||||
static void vmd_teardown_dma_ops(struct vmd_dev *vmd) {}
|
||||
static void vmd_setup_dma_ops(struct vmd_dev *vmd) {}
|
||||
#endif
|
||||
|
||||
static char __iomem *vmd_cfg_addr(struct vmd_dev *vmd, struct pci_bus *bus,
|
||||
unsigned int devfn, int reg, int len)
|
||||
{
|
||||
char __iomem *addr = vmd->cfgbar +
|
||||
(bus->number << 20) + (devfn << 12) + reg;
|
||||
|
||||
if ((addr - vmd->cfgbar) + len >=
|
||||
resource_size(&vmd->dev->resource[VMD_CFGBAR]))
|
||||
return NULL;
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
/*
|
||||
* CPU may deadlock if config space is not serialized on some versions of this
|
||||
* hardware, so all config space access is done under a spinlock.
|
||||
*/
|
||||
static int vmd_pci_read(struct pci_bus *bus, unsigned int devfn, int reg,
|
||||
int len, u32 *value)
|
||||
{
|
||||
struct vmd_dev *vmd = vmd_from_bus(bus);
|
||||
char __iomem *addr = vmd_cfg_addr(vmd, bus, devfn, reg, len);
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
if (!addr)
|
||||
return -EFAULT;
|
||||
|
||||
spin_lock_irqsave(&vmd->cfg_lock, flags);
|
||||
switch (len) {
|
||||
case 1:
|
||||
*value = readb(addr);
|
||||
break;
|
||||
case 2:
|
||||
*value = readw(addr);
|
||||
break;
|
||||
case 4:
|
||||
*value = readl(addr);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
spin_unlock_irqrestore(&vmd->cfg_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* VMD h/w converts non-posted config writes to posted memory writes. The
|
||||
* read-back in this function forces the completion so it returns only after
|
||||
* the config space was written, as expected.
|
||||
*/
|
||||
static int vmd_pci_write(struct pci_bus *bus, unsigned int devfn, int reg,
|
||||
int len, u32 value)
|
||||
{
|
||||
struct vmd_dev *vmd = vmd_from_bus(bus);
|
||||
char __iomem *addr = vmd_cfg_addr(vmd, bus, devfn, reg, len);
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
if (!addr)
|
||||
return -EFAULT;
|
||||
|
||||
spin_lock_irqsave(&vmd->cfg_lock, flags);
|
||||
switch (len) {
|
||||
case 1:
|
||||
writeb(value, addr);
|
||||
readb(addr);
|
||||
break;
|
||||
case 2:
|
||||
writew(value, addr);
|
||||
readw(addr);
|
||||
break;
|
||||
case 4:
|
||||
writel(value, addr);
|
||||
readl(addr);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
spin_unlock_irqrestore(&vmd->cfg_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct pci_ops vmd_ops = {
|
||||
.read = vmd_pci_read,
|
||||
.write = vmd_pci_write,
|
||||
};
|
||||
|
||||
/*
|
||||
* VMD domains start at 0x1000 to not clash with ACPI _SEG domains.
|
||||
*/
|
||||
static int vmd_find_free_domain(void)
|
||||
{
|
||||
int domain = 0xffff;
|
||||
struct pci_bus *bus = NULL;
|
||||
|
||||
while ((bus = pci_find_next_bus(bus)) != NULL)
|
||||
domain = max_t(int, domain, pci_domain_nr(bus));
|
||||
return domain + 1;
|
||||
}
|
||||
|
||||
static int vmd_enable_domain(struct vmd_dev *vmd)
|
||||
{
|
||||
struct pci_sysdata *sd = &vmd->sysdata;
|
||||
struct resource *res;
|
||||
u32 upper_bits;
|
||||
unsigned long flags;
|
||||
LIST_HEAD(resources);
|
||||
|
||||
res = &vmd->dev->resource[VMD_CFGBAR];
|
||||
vmd->resources[0] = (struct resource) {
|
||||
.name = "VMD CFGBAR",
|
||||
.start = res->start,
|
||||
.end = (resource_size(res) >> 20) - 1,
|
||||
.flags = IORESOURCE_BUS | IORESOURCE_PCI_FIXED,
|
||||
};
|
||||
|
||||
res = &vmd->dev->resource[VMD_MEMBAR1];
|
||||
upper_bits = upper_32_bits(res->end);
|
||||
flags = res->flags & ~IORESOURCE_SIZEALIGN;
|
||||
if (!upper_bits)
|
||||
flags &= ~IORESOURCE_MEM_64;
|
||||
vmd->resources[1] = (struct resource) {
|
||||
.name = "VMD MEMBAR1",
|
||||
.start = res->start,
|
||||
.end = res->end,
|
||||
.flags = flags,
|
||||
};
|
||||
|
||||
res = &vmd->dev->resource[VMD_MEMBAR2];
|
||||
upper_bits = upper_32_bits(res->end);
|
||||
flags = res->flags & ~IORESOURCE_SIZEALIGN;
|
||||
if (!upper_bits)
|
||||
flags &= ~IORESOURCE_MEM_64;
|
||||
vmd->resources[2] = (struct resource) {
|
||||
.name = "VMD MEMBAR2",
|
||||
.start = res->start + 0x2000,
|
||||
.end = res->end,
|
||||
.flags = flags,
|
||||
};
|
||||
|
||||
sd->domain = vmd_find_free_domain();
|
||||
if (sd->domain < 0)
|
||||
return sd->domain;
|
||||
|
||||
sd->node = pcibus_to_node(vmd->dev->bus);
|
||||
|
||||
vmd->irq_domain = pci_msi_create_irq_domain(NULL, &vmd_msi_domain_info,
|
||||
NULL);
|
||||
if (!vmd->irq_domain)
|
||||
return -ENODEV;
|
||||
|
||||
pci_add_resource(&resources, &vmd->resources[0]);
|
||||
pci_add_resource(&resources, &vmd->resources[1]);
|
||||
pci_add_resource(&resources, &vmd->resources[2]);
|
||||
vmd->bus = pci_create_root_bus(&vmd->dev->dev, 0, &vmd_ops, sd,
|
||||
&resources);
|
||||
if (!vmd->bus) {
|
||||
pci_free_resource_list(&resources);
|
||||
irq_domain_remove(vmd->irq_domain);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
vmd_setup_dma_ops(vmd);
|
||||
dev_set_msi_domain(&vmd->bus->dev, vmd->irq_domain);
|
||||
pci_rescan_bus(vmd->bus);
|
||||
|
||||
WARN(sysfs_create_link(&vmd->dev->dev.kobj, &vmd->bus->dev.kobj,
|
||||
"domain"), "Can't create symlink to domain\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t vmd_irq(int irq, void *data)
|
||||
{
|
||||
struct vmd_irq_list *irqs = data;
|
||||
struct vmd_irq *vmdirq;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(vmdirq, &irqs->irq_list, node)
|
||||
generic_handle_irq(vmdirq->virq);
|
||||
rcu_read_unlock();
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int vmd_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
{
|
||||
struct vmd_dev *vmd;
|
||||
int i, err;
|
||||
|
||||
if (resource_size(&dev->resource[VMD_CFGBAR]) < (1 << 20))
|
||||
return -ENOMEM;
|
||||
|
||||
vmd = devm_kzalloc(&dev->dev, sizeof(*vmd), GFP_KERNEL);
|
||||
if (!vmd)
|
||||
return -ENOMEM;
|
||||
|
||||
vmd->dev = dev;
|
||||
err = pcim_enable_device(dev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
vmd->cfgbar = pcim_iomap(dev, VMD_CFGBAR, 0);
|
||||
if (!vmd->cfgbar)
|
||||
return -ENOMEM;
|
||||
|
||||
pci_set_master(dev);
|
||||
if (dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(64)) &&
|
||||
dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32)))
|
||||
return -ENODEV;
|
||||
|
||||
vmd->msix_count = pci_msix_vec_count(dev);
|
||||
if (vmd->msix_count < 0)
|
||||
return -ENODEV;
|
||||
|
||||
vmd->irqs = devm_kcalloc(&dev->dev, vmd->msix_count, sizeof(*vmd->irqs),
|
||||
GFP_KERNEL);
|
||||
if (!vmd->irqs)
|
||||
return -ENOMEM;
|
||||
|
||||
vmd->msix_entries = devm_kcalloc(&dev->dev, vmd->msix_count,
|
||||
sizeof(*vmd->msix_entries),
|
||||
GFP_KERNEL);
|
||||
if (!vmd->msix_entries)
|
||||
return -ENOMEM;
|
||||
for (i = 0; i < vmd->msix_count; i++)
|
||||
vmd->msix_entries[i].entry = i;
|
||||
|
||||
vmd->msix_count = pci_enable_msix_range(vmd->dev, vmd->msix_entries, 1,
|
||||
vmd->msix_count);
|
||||
if (vmd->msix_count < 0)
|
||||
return vmd->msix_count;
|
||||
|
||||
for (i = 0; i < vmd->msix_count; i++) {
|
||||
INIT_LIST_HEAD(&vmd->irqs[i].irq_list);
|
||||
vmd->irqs[i].vmd_vector = vmd->msix_entries[i].vector;
|
||||
vmd->irqs[i].index = i;
|
||||
|
||||
err = devm_request_irq(&dev->dev, vmd->irqs[i].vmd_vector,
|
||||
vmd_irq, 0, "vmd", &vmd->irqs[i]);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
spin_lock_init(&vmd->cfg_lock);
|
||||
pci_set_drvdata(dev, vmd);
|
||||
err = vmd_enable_domain(vmd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
dev_info(&vmd->dev->dev, "Bound to PCI domain %04x\n",
|
||||
vmd->sysdata.domain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vmd_remove(struct pci_dev *dev)
|
||||
{
|
||||
struct vmd_dev *vmd = pci_get_drvdata(dev);
|
||||
|
||||
pci_set_drvdata(dev, NULL);
|
||||
sysfs_remove_link(&vmd->dev->dev.kobj, "domain");
|
||||
pci_stop_root_bus(vmd->bus);
|
||||
pci_remove_root_bus(vmd->bus);
|
||||
vmd_teardown_dma_ops(vmd);
|
||||
irq_domain_remove(vmd->irq_domain);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int vmd_suspend(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
|
||||
pci_save_state(pdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vmd_resume(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
|
||||
pci_restore_state(pdev);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
static SIMPLE_DEV_PM_OPS(vmd_dev_pm_ops, vmd_suspend, vmd_resume);
|
||||
|
||||
static const struct pci_device_id vmd_ids[] = {
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x201d),},
|
||||
{0,}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, vmd_ids);
|
||||
|
||||
static struct pci_driver vmd_drv = {
|
||||
.name = "vmd",
|
||||
.id_table = vmd_ids,
|
||||
.probe = vmd_probe,
|
||||
.remove = vmd_remove,
|
||||
.driver = {
|
||||
.pm = &vmd_dev_pm_ops,
|
||||
},
|
||||
};
|
||||
module_pci_driver(vmd_drv);
|
||||
|
||||
MODULE_AUTHOR("Intel Corporation");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_VERSION("0.6");
|
@ -25,7 +25,7 @@ DEFINE_RAW_SPINLOCK(pci_lock);
|
||||
#define PCI_word_BAD (pos & 1)
|
||||
#define PCI_dword_BAD (pos & 3)
|
||||
|
||||
#define PCI_OP_READ(size,type,len) \
|
||||
#define PCI_OP_READ(size, type, len) \
|
||||
int pci_bus_read_config_##size \
|
||||
(struct pci_bus *bus, unsigned int devfn, int pos, type *value) \
|
||||
{ \
|
||||
@ -40,7 +40,7 @@ int pci_bus_read_config_##size \
|
||||
return res; \
|
||||
}
|
||||
|
||||
#define PCI_OP_WRITE(size,type,len) \
|
||||
#define PCI_OP_WRITE(size, type, len) \
|
||||
int pci_bus_write_config_##size \
|
||||
(struct pci_bus *bus, unsigned int devfn, int pos, type value) \
|
||||
{ \
|
||||
@ -231,7 +231,7 @@ static noinline void pci_wait_cfg(struct pci_dev *dev)
|
||||
}
|
||||
|
||||
/* Returns 0 on success, negative values indicate error. */
|
||||
#define PCI_USER_READ_CONFIG(size,type) \
|
||||
#define PCI_USER_READ_CONFIG(size, type) \
|
||||
int pci_user_read_config_##size \
|
||||
(struct pci_dev *dev, int pos, type *val) \
|
||||
{ \
|
||||
@ -251,7 +251,7 @@ int pci_user_read_config_##size \
|
||||
EXPORT_SYMBOL_GPL(pci_user_read_config_##size);
|
||||
|
||||
/* Returns 0 on success, negative values indicate error. */
|
||||
#define PCI_USER_WRITE_CONFIG(size,type) \
|
||||
#define PCI_USER_WRITE_CONFIG(size, type) \
|
||||
int pci_user_write_config_##size \
|
||||
(struct pci_dev *dev, int pos, type val) \
|
||||
{ \
|
||||
|
@ -140,6 +140,8 @@ static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
|
||||
type_mask |= IORESOURCE_TYPE_BITS;
|
||||
|
||||
pci_bus_for_each_resource(bus, r, i) {
|
||||
resource_size_t min_used = min;
|
||||
|
||||
if (!r)
|
||||
continue;
|
||||
|
||||
@ -163,12 +165,12 @@ static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
|
||||
* overrides "min".
|
||||
*/
|
||||
if (avail.start)
|
||||
min = avail.start;
|
||||
min_used = avail.start;
|
||||
|
||||
max = avail.end;
|
||||
|
||||
/* Ok, try it out.. */
|
||||
ret = allocate_resource(r, res, size, min, max,
|
||||
ret = allocate_resource(r, res, size, min_used, max,
|
||||
align, alignf, alignf_data);
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
|
@ -49,8 +49,7 @@ config PCI_RCAR_GEN2
|
||||
|
||||
config PCI_RCAR_GEN2_PCIE
|
||||
bool "Renesas R-Car PCIe controller"
|
||||
depends on ARM
|
||||
depends on ARCH_SHMOBILE || COMPILE_TEST
|
||||
depends on ARCH_SHMOBILE || (ARM && COMPILE_TEST)
|
||||
help
|
||||
Say Y here if you want PCIe controller support on R-Car Gen2 SoCs.
|
||||
|
||||
@ -119,13 +118,11 @@ config PCI_VERSATILE
|
||||
depends on ARCH_VERSATILE
|
||||
|
||||
config PCIE_IPROC
|
||||
tristate "Broadcom iProc PCIe controller"
|
||||
depends on OF && (ARM || ARM64)
|
||||
default n
|
||||
tristate
|
||||
help
|
||||
This enables the iProc PCIe core controller support for Broadcom's
|
||||
iProc family of SoCs. An appropriate bus interface driver also needs
|
||||
to be enabled
|
||||
iProc family of SoCs. An appropriate bus interface driver needs
|
||||
to be enabled to select this.
|
||||
|
||||
config PCIE_IPROC_PLATFORM
|
||||
tristate "Broadcom iProc PCIe platform bus driver"
|
||||
@ -148,6 +145,16 @@ config PCIE_IPROC_BCMA
|
||||
Say Y here if you want to use the Broadcom iProc PCIe controller
|
||||
through the BCMA bus interface
|
||||
|
||||
config PCIE_IPROC_MSI
|
||||
bool "Broadcom iProc PCIe MSI support"
|
||||
depends on PCIE_IPROC_PLATFORM || PCIE_IPROC_BCMA
|
||||
depends on PCI_MSI
|
||||
select PCI_MSI_IRQ_DOMAIN
|
||||
default ARCH_BCM_IPROC
|
||||
help
|
||||
Say Y here if you want to enable MSI support for Broadcom's iProc
|
||||
PCIe controller
|
||||
|
||||
config PCIE_ALTERA
|
||||
bool "Altera PCIe controller"
|
||||
depends on ARM || NIOS2
|
||||
@ -167,10 +174,21 @@ config PCIE_ALTERA_MSI
|
||||
|
||||
config PCI_HISI
|
||||
depends on OF && ARM64
|
||||
bool "HiSilicon SoC HIP05 PCIe controller"
|
||||
bool "HiSilicon Hip05 and Hip06 SoCs PCIe controllers"
|
||||
select PCIEPORTBUS
|
||||
select PCIE_DW
|
||||
help
|
||||
Say Y here if you want PCIe controller support on HiSilicon HIP05 SoC
|
||||
Say Y here if you want PCIe controller support on HiSilicon
|
||||
Hip05 and Hip06 SoCs
|
||||
|
||||
config PCIE_QCOM
|
||||
bool "Qualcomm PCIe controller"
|
||||
depends on ARCH_QCOM && OF
|
||||
select PCIE_DW
|
||||
select PCIEPORTBUS
|
||||
help
|
||||
Say Y here to enable PCIe controller support on Qualcomm SoCs. The
|
||||
PCIe controller uses the Designware core plus Qualcomm-specific
|
||||
hardware wrappers.
|
||||
|
||||
endmenu
|
||||
|
@ -15,8 +15,10 @@ obj-$(CONFIG_PCI_XGENE_MSI) += pci-xgene-msi.o
|
||||
obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o
|
||||
obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o
|
||||
obj-$(CONFIG_PCIE_IPROC) += pcie-iproc.o
|
||||
obj-$(CONFIG_PCIE_IPROC_MSI) += pcie-iproc-msi.o
|
||||
obj-$(CONFIG_PCIE_IPROC_PLATFORM) += pcie-iproc-platform.o
|
||||
obj-$(CONFIG_PCIE_IPROC_BCMA) += pcie-iproc-bcma.o
|
||||
obj-$(CONFIG_PCIE_ALTERA) += pcie-altera.o
|
||||
obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o
|
||||
obj-$(CONFIG_PCI_HISI) += pcie-hisi.o
|
||||
obj-$(CONFIG_PCIE_QCOM) += pcie-qcom.o
|
||||
|
@ -302,7 +302,8 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
|
||||
}
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, pp->irq,
|
||||
dra7xx_pcie_msi_irq_handler, IRQF_SHARED,
|
||||
dra7xx_pcie_msi_irq_handler,
|
||||
IRQF_SHARED | IRQF_NO_THREAD,
|
||||
"dra7-pcie-msi", pp);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to request irq\n");
|
||||
|
@ -522,7 +522,8 @@ static int __init exynos_add_pcie_port(struct pcie_port *pp,
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, pp->msi_irq,
|
||||
exynos_pcie_msi_irq_handler,
|
||||
IRQF_SHARED, "exynos-pcie", pp);
|
||||
IRQF_SHARED | IRQF_NO_THREAD,
|
||||
"exynos-pcie", pp);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to request msi irq\n");
|
||||
return ret;
|
||||
|
@ -38,16 +38,7 @@ struct gen_pci_cfg_windows {
|
||||
struct gen_pci_cfg_bus_ops *ops;
|
||||
};
|
||||
|
||||
/*
|
||||
* ARM pcibios functions expect the ARM struct pci_sys_data as the PCI
|
||||
* sysdata. Add pci_sys_data as the first element in struct gen_pci so
|
||||
* that when we use a gen_pci pointer as sysdata, it is also a pointer to
|
||||
* a struct pci_sys_data.
|
||||
*/
|
||||
struct gen_pci {
|
||||
#ifdef CONFIG_ARM
|
||||
struct pci_sys_data sys;
|
||||
#endif
|
||||
struct pci_host_bridge host;
|
||||
struct gen_pci_cfg_windows cfg;
|
||||
struct list_head resources;
|
||||
|
@ -32,7 +32,7 @@
|
||||
#define to_imx6_pcie(x) container_of(x, struct imx6_pcie, pp)
|
||||
|
||||
struct imx6_pcie {
|
||||
int reset_gpio;
|
||||
struct gpio_desc *reset_gpio;
|
||||
struct clk *pcie_bus;
|
||||
struct clk *pcie_phy;
|
||||
struct clk *pcie;
|
||||
@ -122,7 +122,7 @@ static int pcie_phy_wait_ack(void __iomem *dbi_base, int addr)
|
||||
}
|
||||
|
||||
/* Read from the 16-bit PCIe PHY control registers (not memory-mapped) */
|
||||
static int pcie_phy_read(void __iomem *dbi_base, int addr , int *data)
|
||||
static int pcie_phy_read(void __iomem *dbi_base, int addr, int *data)
|
||||
{
|
||||
u32 val, phy_ctl;
|
||||
int ret;
|
||||
@ -287,10 +287,10 @@ static int imx6_pcie_deassert_core_reset(struct pcie_port *pp)
|
||||
usleep_range(200, 500);
|
||||
|
||||
/* Some boards don't have PCIe reset GPIO. */
|
||||
if (gpio_is_valid(imx6_pcie->reset_gpio)) {
|
||||
gpio_set_value(imx6_pcie->reset_gpio, 0);
|
||||
if (imx6_pcie->reset_gpio) {
|
||||
gpiod_set_value_cansleep(imx6_pcie->reset_gpio, 0);
|
||||
msleep(100);
|
||||
gpio_set_value(imx6_pcie->reset_gpio, 1);
|
||||
gpiod_set_value_cansleep(imx6_pcie->reset_gpio, 1);
|
||||
}
|
||||
return 0;
|
||||
|
||||
@ -537,7 +537,8 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, pp->msi_irq,
|
||||
imx6_pcie_msi_handler,
|
||||
IRQF_SHARED, "mx6-pcie-msi", pp);
|
||||
IRQF_SHARED | IRQF_NO_THREAD,
|
||||
"mx6-pcie-msi", pp);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to request MSI irq\n");
|
||||
return ret;
|
||||
@ -560,7 +561,6 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct imx6_pcie *imx6_pcie;
|
||||
struct pcie_port *pp;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct resource *dbi_base;
|
||||
int ret;
|
||||
|
||||
@ -581,15 +581,8 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(pp->dbi_base);
|
||||
|
||||
/* Fetch GPIOs */
|
||||
imx6_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
|
||||
if (gpio_is_valid(imx6_pcie->reset_gpio)) {
|
||||
ret = devm_gpio_request_one(&pdev->dev, imx6_pcie->reset_gpio,
|
||||
GPIOF_OUT_INIT_LOW, "PCIe reset");
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "unable to get reset gpio\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
imx6_pcie->reset_gpio = devm_gpiod_get_optional(&pdev->dev, "reset",
|
||||
GPIOD_OUT_LOW);
|
||||
|
||||
/* Fetch clocks */
|
||||
imx6_pcie->pcie_phy = devm_clk_get(&pdev->dev, "pcie_phy");
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_pci.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/platform_device.h>
|
||||
@ -102,6 +103,8 @@ struct rcar_pci_priv {
|
||||
unsigned busnr;
|
||||
int irq;
|
||||
unsigned long window_size;
|
||||
unsigned long window_addr;
|
||||
unsigned long window_pci;
|
||||
};
|
||||
|
||||
/* PCI configuration space operations */
|
||||
@ -239,8 +242,8 @@ static int rcar_pci_setup(int nr, struct pci_sys_data *sys)
|
||||
RCAR_PCI_ARBITER_PCIBP_MODE;
|
||||
iowrite32(val, reg + RCAR_PCI_ARBITER_CTR_REG);
|
||||
|
||||
/* PCI-AHB mapping: 0x40000000 base */
|
||||
iowrite32(0x40000000 | RCAR_PCIAHB_PREFETCH16,
|
||||
/* PCI-AHB mapping */
|
||||
iowrite32(priv->window_addr | RCAR_PCIAHB_PREFETCH16,
|
||||
reg + RCAR_PCIAHB_WIN1_CTR_REG);
|
||||
|
||||
/* AHB-PCI mapping: OHCI/EHCI registers */
|
||||
@ -251,7 +254,7 @@ static int rcar_pci_setup(int nr, struct pci_sys_data *sys)
|
||||
iowrite32(RCAR_AHBPCI_WIN1_HOST | RCAR_AHBPCI_WIN_CTR_CFG,
|
||||
reg + RCAR_AHBPCI_WIN1_CTR_REG);
|
||||
/* Set PCI-AHB Window1 address */
|
||||
iowrite32(0x40000000 | PCI_BASE_ADDRESS_MEM_PREFETCH,
|
||||
iowrite32(priv->window_pci | PCI_BASE_ADDRESS_MEM_PREFETCH,
|
||||
reg + PCI_BASE_ADDRESS_1);
|
||||
/* Set AHB-PCI bridge PCI communication area address */
|
||||
val = priv->cfg_res->start + RCAR_AHBPCI_PCICOM_OFFSET;
|
||||
@ -284,6 +287,64 @@ static struct pci_ops rcar_pci_ops = {
|
||||
.write = pci_generic_config_write,
|
||||
};
|
||||
|
||||
static int pci_dma_range_parser_init(struct of_pci_range_parser *parser,
|
||||
struct device_node *node)
|
||||
{
|
||||
const int na = 3, ns = 2;
|
||||
int rlen;
|
||||
|
||||
parser->node = node;
|
||||
parser->pna = of_n_addr_cells(node);
|
||||
parser->np = parser->pna + na + ns;
|
||||
|
||||
parser->range = of_get_property(node, "dma-ranges", &rlen);
|
||||
if (!parser->range)
|
||||
return -ENOENT;
|
||||
|
||||
parser->end = parser->range + rlen / sizeof(__be32);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rcar_pci_parse_map_dma_ranges(struct rcar_pci_priv *pci,
|
||||
struct device_node *np)
|
||||
{
|
||||
struct of_pci_range range;
|
||||
struct of_pci_range_parser parser;
|
||||
int index = 0;
|
||||
|
||||
/* Failure to parse is ok as we fall back to defaults */
|
||||
if (pci_dma_range_parser_init(&parser, np))
|
||||
return 0;
|
||||
|
||||
/* Get the dma-ranges from DT */
|
||||
for_each_of_pci_range(&parser, &range) {
|
||||
/* Hardware only allows one inbound 32-bit range */
|
||||
if (index)
|
||||
return -EINVAL;
|
||||
|
||||
pci->window_addr = (unsigned long)range.cpu_addr;
|
||||
pci->window_pci = (unsigned long)range.pci_addr;
|
||||
pci->window_size = (unsigned long)range.size;
|
||||
|
||||
/* Catch HW limitations */
|
||||
if (!(range.flags & IORESOURCE_PREFETCH)) {
|
||||
dev_err(pci->dev, "window must be prefetchable\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (pci->window_addr) {
|
||||
u32 lowaddr = 1 << (ffs(pci->window_addr) - 1);
|
||||
|
||||
if (lowaddr < pci->window_size) {
|
||||
dev_err(pci->dev, "invalid window size/addr\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rcar_pci_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *cfg_res, *mem_res;
|
||||
@ -329,6 +390,9 @@ static int rcar_pci_probe(struct platform_device *pdev)
|
||||
return priv->irq;
|
||||
}
|
||||
|
||||
/* default window addr and size if not specified in DT */
|
||||
priv->window_addr = 0x40000000;
|
||||
priv->window_pci = 0x40000000;
|
||||
priv->window_size = SZ_1G;
|
||||
|
||||
if (pdev->dev.of_node) {
|
||||
@ -344,6 +408,12 @@ static int rcar_pci_probe(struct platform_device *pdev)
|
||||
priv->busnr = busnr.start;
|
||||
if (busnr.end != busnr.start)
|
||||
dev_warn(&pdev->dev, "only one bus number supported\n");
|
||||
|
||||
ret = rcar_pci_parse_map_dma_ranges(priv, pdev->dev.of_node);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed to parse dma-range\n");
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
priv->busnr = pdev->id;
|
||||
}
|
||||
@ -360,6 +430,7 @@ static int rcar_pci_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
static struct of_device_id rcar_pci_of_match[] = {
|
||||
{ .compatible = "renesas,pci-rcar-gen2", },
|
||||
{ .compatible = "renesas,pci-r8a7790", },
|
||||
{ .compatible = "renesas,pci-r8a7791", },
|
||||
{ .compatible = "renesas,pci-r8a7794", },
|
||||
|
@ -1288,7 +1288,7 @@ static int tegra_pcie_enable_msi(struct tegra_pcie *pcie)
|
||||
|
||||
msi->irq = err;
|
||||
|
||||
err = request_irq(msi->irq, tegra_pcie_msi_irq, 0,
|
||||
err = request_irq(msi->irq, tegra_pcie_msi_irq, IRQF_NO_THREAD,
|
||||
tegra_msi_irq_chip.name, pcie);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to request IRQ: %d\n", err);
|
||||
|
@ -125,9 +125,6 @@ out_release_res:
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Unused, temporary to satisfy ARM arch code */
|
||||
struct pci_sys_data sys;
|
||||
|
||||
static int versatile_pci_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res;
|
||||
@ -208,7 +205,7 @@ static int versatile_pci_probe(struct platform_device *pdev)
|
||||
pci_add_flags(PCI_ENABLE_PROC_DOMAINS);
|
||||
pci_add_flags(PCI_REASSIGN_ALL_BUS | PCI_REASSIGN_ALL_RSRC);
|
||||
|
||||
bus = pci_scan_root_bus(&pdev->dev, 0, &pci_versatile_ops, &sys, &pci_res);
|
||||
bus = pci_scan_root_bus(&pdev->dev, 0, &pci_versatile_ops, NULL, &pci_res);
|
||||
if (!bus)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -128,32 +128,26 @@ static inline void dw_pcie_writel_rc(struct pcie_port *pp, u32 val, u32 reg)
|
||||
static int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
|
||||
u32 *val)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (pp->ops->rd_own_conf)
|
||||
ret = pp->ops->rd_own_conf(pp, where, size, val);
|
||||
else
|
||||
ret = dw_pcie_cfg_read(pp->dbi_base + where, size, val);
|
||||
return pp->ops->rd_own_conf(pp, where, size, val);
|
||||
|
||||
return ret;
|
||||
return dw_pcie_cfg_read(pp->dbi_base + where, size, val);
|
||||
}
|
||||
|
||||
static int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size,
|
||||
u32 val)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (pp->ops->wr_own_conf)
|
||||
ret = pp->ops->wr_own_conf(pp, where, size, val);
|
||||
else
|
||||
ret = dw_pcie_cfg_write(pp->dbi_base + where, size, val);
|
||||
return pp->ops->wr_own_conf(pp, where, size, val);
|
||||
|
||||
return ret;
|
||||
return dw_pcie_cfg_write(pp->dbi_base + where, size, val);
|
||||
}
|
||||
|
||||
static void dw_pcie_prog_outbound_atu(struct pcie_port *pp, int index,
|
||||
int type, u64 cpu_addr, u64 pci_addr, u32 size)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | index,
|
||||
PCIE_ATU_VIEWPORT);
|
||||
dw_pcie_writel_rc(pp, lower_32_bits(cpu_addr), PCIE_ATU_LOWER_BASE);
|
||||
@ -164,6 +158,12 @@ static void dw_pcie_prog_outbound_atu(struct pcie_port *pp, int index,
|
||||
dw_pcie_writel_rc(pp, upper_32_bits(pci_addr), PCIE_ATU_UPPER_TARGET);
|
||||
dw_pcie_writel_rc(pp, type, PCIE_ATU_CR1);
|
||||
dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
|
||||
|
||||
/*
|
||||
* Make sure ATU enable takes effect before any subsequent config
|
||||
* and I/O accesses.
|
||||
*/
|
||||
dw_pcie_readl_rc(pp, PCIE_ATU_CR2, &val);
|
||||
}
|
||||
|
||||
static struct irq_chip dw_msi_irq_chip = {
|
||||
@ -384,8 +384,8 @@ int dw_pcie_link_up(struct pcie_port *pp)
|
||||
{
|
||||
if (pp->ops->link_up)
|
||||
return pp->ops->link_up(pp);
|
||||
else
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq,
|
||||
@ -571,6 +571,9 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
|
||||
u64 cpu_addr;
|
||||
void __iomem *va_cfg_base;
|
||||
|
||||
if (pp->ops->rd_other_conf)
|
||||
return pp->ops->rd_other_conf(pp, bus, devfn, where, size, val);
|
||||
|
||||
busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) |
|
||||
PCIE_ATU_FUNC(PCI_FUNC(devfn));
|
||||
|
||||
@ -605,6 +608,9 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
|
||||
u64 cpu_addr;
|
||||
void __iomem *va_cfg_base;
|
||||
|
||||
if (pp->ops->wr_other_conf)
|
||||
return pp->ops->wr_other_conf(pp, bus, devfn, where, size, val);
|
||||
|
||||
busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) |
|
||||
PCIE_ATU_FUNC(PCI_FUNC(devfn));
|
||||
|
||||
@ -658,46 +664,30 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
|
||||
int size, u32 *val)
|
||||
{
|
||||
struct pcie_port *pp = bus->sysdata;
|
||||
int ret;
|
||||
|
||||
if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
|
||||
*val = 0xffffffff;
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (bus->number != pp->root_bus_nr)
|
||||
if (pp->ops->rd_other_conf)
|
||||
ret = pp->ops->rd_other_conf(pp, bus, devfn,
|
||||
where, size, val);
|
||||
else
|
||||
ret = dw_pcie_rd_other_conf(pp, bus, devfn,
|
||||
where, size, val);
|
||||
else
|
||||
ret = dw_pcie_rd_own_conf(pp, where, size, val);
|
||||
if (bus->number == pp->root_bus_nr)
|
||||
return dw_pcie_rd_own_conf(pp, where, size, val);
|
||||
|
||||
return ret;
|
||||
return dw_pcie_rd_other_conf(pp, bus, devfn, where, size, val);
|
||||
}
|
||||
|
||||
static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
|
||||
int where, int size, u32 val)
|
||||
{
|
||||
struct pcie_port *pp = bus->sysdata;
|
||||
int ret;
|
||||
|
||||
if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
if (bus->number != pp->root_bus_nr)
|
||||
if (pp->ops->wr_other_conf)
|
||||
ret = pp->ops->wr_other_conf(pp, bus, devfn,
|
||||
where, size, val);
|
||||
else
|
||||
ret = dw_pcie_wr_other_conf(pp, bus, devfn,
|
||||
where, size, val);
|
||||
else
|
||||
ret = dw_pcie_wr_own_conf(pp, where, size, val);
|
||||
if (bus->number == pp->root_bus_nr)
|
||||
return dw_pcie_wr_own_conf(pp, where, size, val);
|
||||
|
||||
return ret;
|
||||
return dw_pcie_wr_other_conf(pp, bus, devfn, where, size, val);
|
||||
}
|
||||
|
||||
static struct pci_ops dw_pcie_ops = {
|
||||
|
@ -1,10 +1,11 @@
|
||||
/*
|
||||
* PCIe host controller driver for HiSilicon Hip05 SoC
|
||||
* PCIe host controller driver for HiSilicon SoCs
|
||||
*
|
||||
* Copyright (C) 2015 HiSilicon Co., Ltd. http://www.hisilicon.com
|
||||
*
|
||||
* Author: Zhou Wang <wangzhou1@hisilicon.com>
|
||||
* Dacai Zhu <zhudacai@hisilicon.com>
|
||||
* Authors: Zhou Wang <wangzhou1@hisilicon.com>
|
||||
* Dacai Zhu <zhudacai@hisilicon.com>
|
||||
* Gabriele Paoloni <gabriele.paoloni@huawei.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@ -16,21 +17,31 @@
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_pci.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include "pcie-designware.h"
|
||||
|
||||
#define PCIE_SUBCTRL_SYS_STATE4_REG 0x6818
|
||||
#define PCIE_LTSSM_LINKUP_STATE 0x11
|
||||
#define PCIE_LTSSM_STATE_MASK 0x3F
|
||||
#define PCIE_LTSSM_LINKUP_STATE 0x11
|
||||
#define PCIE_LTSSM_STATE_MASK 0x3F
|
||||
#define PCIE_SUBCTRL_SYS_STATE4_REG 0x6818
|
||||
#define PCIE_SYS_STATE4 0x31c
|
||||
#define PCIE_HIP06_CTRL_OFF 0x1000
|
||||
|
||||
#define to_hisi_pcie(x) container_of(x, struct hisi_pcie, pp)
|
||||
|
||||
struct hisi_pcie;
|
||||
|
||||
struct pcie_soc_ops {
|
||||
int (*hisi_pcie_link_up)(struct hisi_pcie *pcie);
|
||||
};
|
||||
|
||||
struct hisi_pcie {
|
||||
struct regmap *subctrl;
|
||||
void __iomem *reg_base;
|
||||
u32 port_id;
|
||||
struct pcie_port pp;
|
||||
struct pcie_soc_ops *soc_ops;
|
||||
};
|
||||
|
||||
static inline void hisi_pcie_apb_writel(struct hisi_pcie *pcie,
|
||||
@ -44,7 +55,7 @@ static inline u32 hisi_pcie_apb_readl(struct hisi_pcie *pcie, u32 reg)
|
||||
return readl(pcie->reg_base + reg);
|
||||
}
|
||||
|
||||
/* Hip05 PCIe host only supports 32-bit config access */
|
||||
/* HipXX PCIe host only supports 32-bit config access */
|
||||
static int hisi_pcie_cfg_read(struct pcie_port *pp, int where, int size,
|
||||
u32 *val)
|
||||
{
|
||||
@ -69,7 +80,7 @@ static int hisi_pcie_cfg_read(struct pcie_port *pp, int where, int size,
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/* Hip05 PCIe host only supports 32-bit config access */
|
||||
/* HipXX PCIe host only supports 32-bit config access */
|
||||
static int hisi_pcie_cfg_write(struct pcie_port *pp, int where, int size,
|
||||
u32 val)
|
||||
{
|
||||
@ -96,10 +107,9 @@ static int hisi_pcie_cfg_write(struct pcie_port *pp, int where, int size,
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static int hisi_pcie_link_up(struct pcie_port *pp)
|
||||
static int hisi_pcie_link_up_hip05(struct hisi_pcie *hisi_pcie)
|
||||
{
|
||||
u32 val;
|
||||
struct hisi_pcie *hisi_pcie = to_hisi_pcie(pp);
|
||||
|
||||
regmap_read(hisi_pcie->subctrl, PCIE_SUBCTRL_SYS_STATE4_REG +
|
||||
0x100 * hisi_pcie->port_id, &val);
|
||||
@ -107,6 +117,23 @@ static int hisi_pcie_link_up(struct pcie_port *pp)
|
||||
return ((val & PCIE_LTSSM_STATE_MASK) == PCIE_LTSSM_LINKUP_STATE);
|
||||
}
|
||||
|
||||
static int hisi_pcie_link_up_hip06(struct hisi_pcie *hisi_pcie)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = hisi_pcie_apb_readl(hisi_pcie, PCIE_HIP06_CTRL_OFF +
|
||||
PCIE_SYS_STATE4);
|
||||
|
||||
return ((val & PCIE_LTSSM_STATE_MASK) == PCIE_LTSSM_LINKUP_STATE);
|
||||
}
|
||||
|
||||
static int hisi_pcie_link_up(struct pcie_port *pp)
|
||||
{
|
||||
struct hisi_pcie *hisi_pcie = to_hisi_pcie(pp);
|
||||
|
||||
return hisi_pcie->soc_ops->hisi_pcie_link_up(hisi_pcie);
|
||||
}
|
||||
|
||||
static struct pcie_host_ops hisi_pcie_host_ops = {
|
||||
.rd_own_conf = hisi_pcie_cfg_read,
|
||||
.wr_own_conf = hisi_pcie_cfg_write,
|
||||
@ -145,7 +172,9 @@ static int hisi_pcie_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct hisi_pcie *hisi_pcie;
|
||||
struct pcie_port *pp;
|
||||
const struct of_device_id *match;
|
||||
struct resource *reg;
|
||||
struct device_driver *driver;
|
||||
int ret;
|
||||
|
||||
hisi_pcie = devm_kzalloc(&pdev->dev, sizeof(*hisi_pcie), GFP_KERNEL);
|
||||
@ -154,6 +183,10 @@ static int hisi_pcie_probe(struct platform_device *pdev)
|
||||
|
||||
pp = &hisi_pcie->pp;
|
||||
pp->dev = &pdev->dev;
|
||||
driver = (pdev->dev).driver;
|
||||
|
||||
match = of_match_device(driver->of_match_table, &pdev->dev);
|
||||
hisi_pcie->soc_ops = (struct pcie_soc_ops *) match->data;
|
||||
|
||||
hisi_pcie->subctrl =
|
||||
syscon_regmap_lookup_by_compatible("hisilicon,pcie-sas-subctrl");
|
||||
@ -182,11 +215,27 @@ static int hisi_pcie_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pcie_soc_ops hip05_ops = {
|
||||
&hisi_pcie_link_up_hip05
|
||||
};
|
||||
|
||||
static struct pcie_soc_ops hip06_ops = {
|
||||
&hisi_pcie_link_up_hip06
|
||||
};
|
||||
|
||||
static const struct of_device_id hisi_pcie_of_match[] = {
|
||||
{.compatible = "hisilicon,hip05-pcie",},
|
||||
{
|
||||
.compatible = "hisilicon,hip05-pcie",
|
||||
.data = (void *) &hip05_ops,
|
||||
},
|
||||
{
|
||||
.compatible = "hisilicon,hip06-pcie",
|
||||
.data = (void *) &hip06_ops,
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
|
||||
MODULE_DEVICE_TABLE(of, hisi_pcie_of_match);
|
||||
|
||||
static struct platform_driver hisi_pcie_driver = {
|
||||
@ -198,3 +247,8 @@ static struct platform_driver hisi_pcie_driver = {
|
||||
};
|
||||
|
||||
module_platform_driver(hisi_pcie_driver);
|
||||
|
||||
MODULE_AUTHOR("Zhou Wang <wangzhou1@hisilicon.com>");
|
||||
MODULE_AUTHOR("Dacai Zhu <zhudacai@hisilicon.com>");
|
||||
MODULE_AUTHOR("Gabriele Paoloni <gabriele.paoloni@huawei.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -55,6 +55,7 @@ static int iproc_pcie_bcma_probe(struct bcma_device *bdev)
|
||||
bcma_set_drvdata(bdev, pcie);
|
||||
|
||||
pcie->base = bdev->io_addr;
|
||||
pcie->base_addr = bdev->addr;
|
||||
|
||||
res_mem.start = bdev->addr_s[0];
|
||||
res_mem.end = bdev->addr_s[0] + SZ_128M - 1;
|
||||
|
675
drivers/pci/host/pcie-iproc-msi.c
Normal file
675
drivers/pci/host/pcie-iproc-msi.c
Normal file
@ -0,0 +1,675 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Broadcom Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation version 2.
|
||||
*
|
||||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
|
||||
* kind, whether express or implied; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irqchip/chained_irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/msi.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_pci.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include "pcie-iproc.h"
|
||||
|
||||
#define IPROC_MSI_INTR_EN_SHIFT 11
|
||||
#define IPROC_MSI_INTR_EN BIT(IPROC_MSI_INTR_EN_SHIFT)
|
||||
#define IPROC_MSI_INT_N_EVENT_SHIFT 1
|
||||
#define IPROC_MSI_INT_N_EVENT BIT(IPROC_MSI_INT_N_EVENT_SHIFT)
|
||||
#define IPROC_MSI_EQ_EN_SHIFT 0
|
||||
#define IPROC_MSI_EQ_EN BIT(IPROC_MSI_EQ_EN_SHIFT)
|
||||
|
||||
#define IPROC_MSI_EQ_MASK 0x3f
|
||||
|
||||
/* Max number of GIC interrupts */
|
||||
#define NR_HW_IRQS 6
|
||||
|
||||
/* Number of entries in each event queue */
|
||||
#define EQ_LEN 64
|
||||
|
||||
/* Size of each event queue memory region */
|
||||
#define EQ_MEM_REGION_SIZE SZ_4K
|
||||
|
||||
/* Size of each MSI address region */
|
||||
#define MSI_MEM_REGION_SIZE SZ_4K
|
||||
|
||||
enum iproc_msi_reg {
|
||||
IPROC_MSI_EQ_PAGE = 0,
|
||||
IPROC_MSI_EQ_PAGE_UPPER,
|
||||
IPROC_MSI_PAGE,
|
||||
IPROC_MSI_PAGE_UPPER,
|
||||
IPROC_MSI_CTRL,
|
||||
IPROC_MSI_EQ_HEAD,
|
||||
IPROC_MSI_EQ_TAIL,
|
||||
IPROC_MSI_INTS_EN,
|
||||
IPROC_MSI_REG_SIZE,
|
||||
};
|
||||
|
||||
struct iproc_msi;
|
||||
|
||||
/**
|
||||
* iProc MSI group
|
||||
*
|
||||
* One MSI group is allocated per GIC interrupt, serviced by one iProc MSI
|
||||
* event queue.
|
||||
*
|
||||
* @msi: pointer to iProc MSI data
|
||||
* @gic_irq: GIC interrupt
|
||||
* @eq: Event queue number
|
||||
*/
|
||||
struct iproc_msi_grp {
|
||||
struct iproc_msi *msi;
|
||||
int gic_irq;
|
||||
unsigned int eq;
|
||||
};
|
||||
|
||||
/**
|
||||
* iProc event queue based MSI
|
||||
*
|
||||
* Only meant to be used on platforms without MSI support integrated into the
|
||||
* GIC.
|
||||
*
|
||||
* @pcie: pointer to iProc PCIe data
|
||||
* @reg_offsets: MSI register offsets
|
||||
* @grps: MSI groups
|
||||
* @nr_irqs: number of total interrupts connected to GIC
|
||||
* @nr_cpus: number of toal CPUs
|
||||
* @has_inten_reg: indicates the MSI interrupt enable register needs to be
|
||||
* set explicitly (required for some legacy platforms)
|
||||
* @bitmap: MSI vector bitmap
|
||||
* @bitmap_lock: lock to protect access to the MSI bitmap
|
||||
* @nr_msi_vecs: total number of MSI vectors
|
||||
* @inner_domain: inner IRQ domain
|
||||
* @msi_domain: MSI IRQ domain
|
||||
* @nr_eq_region: required number of 4K aligned memory region for MSI event
|
||||
* queues
|
||||
* @nr_msi_region: required number of 4K aligned address region for MSI posted
|
||||
* writes
|
||||
* @eq_cpu: pointer to allocated memory region for MSI event queues
|
||||
* @eq_dma: DMA address of MSI event queues
|
||||
* @msi_addr: MSI address
|
||||
*/
|
||||
struct iproc_msi {
|
||||
struct iproc_pcie *pcie;
|
||||
const u16 (*reg_offsets)[IPROC_MSI_REG_SIZE];
|
||||
struct iproc_msi_grp *grps;
|
||||
int nr_irqs;
|
||||
int nr_cpus;
|
||||
bool has_inten_reg;
|
||||
unsigned long *bitmap;
|
||||
struct mutex bitmap_lock;
|
||||
unsigned int nr_msi_vecs;
|
||||
struct irq_domain *inner_domain;
|
||||
struct irq_domain *msi_domain;
|
||||
unsigned int nr_eq_region;
|
||||
unsigned int nr_msi_region;
|
||||
void *eq_cpu;
|
||||
dma_addr_t eq_dma;
|
||||
phys_addr_t msi_addr;
|
||||
};
|
||||
|
||||
static const u16 iproc_msi_reg_paxb[NR_HW_IRQS][IPROC_MSI_REG_SIZE] = {
|
||||
{ 0x200, 0x2c0, 0x204, 0x2c4, 0x210, 0x250, 0x254, 0x208 },
|
||||
{ 0x200, 0x2c0, 0x204, 0x2c4, 0x214, 0x258, 0x25c, 0x208 },
|
||||
{ 0x200, 0x2c0, 0x204, 0x2c4, 0x218, 0x260, 0x264, 0x208 },
|
||||
{ 0x200, 0x2c0, 0x204, 0x2c4, 0x21c, 0x268, 0x26c, 0x208 },
|
||||
{ 0x200, 0x2c0, 0x204, 0x2c4, 0x220, 0x270, 0x274, 0x208 },
|
||||
{ 0x200, 0x2c0, 0x204, 0x2c4, 0x224, 0x278, 0x27c, 0x208 },
|
||||
};
|
||||
|
||||
static const u16 iproc_msi_reg_paxc[NR_HW_IRQS][IPROC_MSI_REG_SIZE] = {
|
||||
{ 0xc00, 0xc04, 0xc08, 0xc0c, 0xc40, 0xc50, 0xc60 },
|
||||
{ 0xc10, 0xc14, 0xc18, 0xc1c, 0xc44, 0xc54, 0xc64 },
|
||||
{ 0xc20, 0xc24, 0xc28, 0xc2c, 0xc48, 0xc58, 0xc68 },
|
||||
{ 0xc30, 0xc34, 0xc38, 0xc3c, 0xc4c, 0xc5c, 0xc6c },
|
||||
};
|
||||
|
||||
static inline u32 iproc_msi_read_reg(struct iproc_msi *msi,
|
||||
enum iproc_msi_reg reg,
|
||||
unsigned int eq)
|
||||
{
|
||||
struct iproc_pcie *pcie = msi->pcie;
|
||||
|
||||
return readl_relaxed(pcie->base + msi->reg_offsets[eq][reg]);
|
||||
}
|
||||
|
||||
static inline void iproc_msi_write_reg(struct iproc_msi *msi,
|
||||
enum iproc_msi_reg reg,
|
||||
int eq, u32 val)
|
||||
{
|
||||
struct iproc_pcie *pcie = msi->pcie;
|
||||
|
||||
writel_relaxed(val, pcie->base + msi->reg_offsets[eq][reg]);
|
||||
}
|
||||
|
||||
static inline u32 hwirq_to_group(struct iproc_msi *msi, unsigned long hwirq)
|
||||
{
|
||||
return (hwirq % msi->nr_irqs);
|
||||
}
|
||||
|
||||
static inline unsigned int iproc_msi_addr_offset(struct iproc_msi *msi,
|
||||
unsigned long hwirq)
|
||||
{
|
||||
if (msi->nr_msi_region > 1)
|
||||
return hwirq_to_group(msi, hwirq) * MSI_MEM_REGION_SIZE;
|
||||
else
|
||||
return hwirq_to_group(msi, hwirq) * sizeof(u32);
|
||||
}
|
||||
|
||||
static inline unsigned int iproc_msi_eq_offset(struct iproc_msi *msi, u32 eq)
|
||||
{
|
||||
if (msi->nr_eq_region > 1)
|
||||
return eq * EQ_MEM_REGION_SIZE;
|
||||
else
|
||||
return eq * EQ_LEN * sizeof(u32);
|
||||
}
|
||||
|
||||
static struct irq_chip iproc_msi_irq_chip = {
|
||||
.name = "iProc-MSI",
|
||||
};
|
||||
|
||||
static struct msi_domain_info iproc_msi_domain_info = {
|
||||
.flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
|
||||
MSI_FLAG_PCI_MSIX,
|
||||
.chip = &iproc_msi_irq_chip,
|
||||
};
|
||||
|
||||
/*
|
||||
* In iProc PCIe core, each MSI group is serviced by a GIC interrupt and a
|
||||
* dedicated event queue. Each MSI group can support up to 64 MSI vectors.
|
||||
*
|
||||
* The number of MSI groups varies between different iProc SoCs. The total
|
||||
* number of CPU cores also varies. To support MSI IRQ affinity, we
|
||||
* distribute GIC interrupts across all available CPUs. MSI vector is moved
|
||||
* from one GIC interrupt to another to steer to the target CPU.
|
||||
*
|
||||
* Assuming:
|
||||
* - the number of MSI groups is M
|
||||
* - the number of CPU cores is N
|
||||
* - M is always a multiple of N
|
||||
*
|
||||
* Total number of raw MSI vectors = M * 64
|
||||
* Total number of supported MSI vectors = (M * 64) / N
|
||||
*/
|
||||
static inline int hwirq_to_cpu(struct iproc_msi *msi, unsigned long hwirq)
|
||||
{
|
||||
return (hwirq % msi->nr_cpus);
|
||||
}
|
||||
|
||||
static inline unsigned long hwirq_to_canonical_hwirq(struct iproc_msi *msi,
|
||||
unsigned long hwirq)
|
||||
{
|
||||
return (hwirq - hwirq_to_cpu(msi, hwirq));
|
||||
}
|
||||
|
||||
static int iproc_msi_irq_set_affinity(struct irq_data *data,
|
||||
const struct cpumask *mask, bool force)
|
||||
{
|
||||
struct iproc_msi *msi = irq_data_get_irq_chip_data(data);
|
||||
int target_cpu = cpumask_first(mask);
|
||||
int curr_cpu;
|
||||
|
||||
curr_cpu = hwirq_to_cpu(msi, data->hwirq);
|
||||
if (curr_cpu == target_cpu)
|
||||
return IRQ_SET_MASK_OK_DONE;
|
||||
|
||||
/* steer MSI to the target CPU */
|
||||
data->hwirq = hwirq_to_canonical_hwirq(msi, data->hwirq) + target_cpu;
|
||||
|
||||
return IRQ_SET_MASK_OK;
|
||||
}
|
||||
|
||||
static void iproc_msi_irq_compose_msi_msg(struct irq_data *data,
|
||||
struct msi_msg *msg)
|
||||
{
|
||||
struct iproc_msi *msi = irq_data_get_irq_chip_data(data);
|
||||
dma_addr_t addr;
|
||||
|
||||
addr = msi->msi_addr + iproc_msi_addr_offset(msi, data->hwirq);
|
||||
msg->address_lo = lower_32_bits(addr);
|
||||
msg->address_hi = upper_32_bits(addr);
|
||||
msg->data = data->hwirq;
|
||||
}
|
||||
|
||||
static struct irq_chip iproc_msi_bottom_irq_chip = {
|
||||
.name = "MSI",
|
||||
.irq_set_affinity = iproc_msi_irq_set_affinity,
|
||||
.irq_compose_msi_msg = iproc_msi_irq_compose_msi_msg,
|
||||
};
|
||||
|
||||
static int iproc_msi_irq_domain_alloc(struct irq_domain *domain,
|
||||
unsigned int virq, unsigned int nr_irqs,
|
||||
void *args)
|
||||
{
|
||||
struct iproc_msi *msi = domain->host_data;
|
||||
int hwirq;
|
||||
|
||||
mutex_lock(&msi->bitmap_lock);
|
||||
|
||||
/* Allocate 'nr_cpus' number of MSI vectors each time */
|
||||
hwirq = bitmap_find_next_zero_area(msi->bitmap, msi->nr_msi_vecs, 0,
|
||||
msi->nr_cpus, 0);
|
||||
if (hwirq < msi->nr_msi_vecs) {
|
||||
bitmap_set(msi->bitmap, hwirq, msi->nr_cpus);
|
||||
} else {
|
||||
mutex_unlock(&msi->bitmap_lock);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
mutex_unlock(&msi->bitmap_lock);
|
||||
|
||||
irq_domain_set_info(domain, virq, hwirq, &iproc_msi_bottom_irq_chip,
|
||||
domain->host_data, handle_simple_irq, NULL, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iproc_msi_irq_domain_free(struct irq_domain *domain,
|
||||
unsigned int virq, unsigned int nr_irqs)
|
||||
{
|
||||
struct irq_data *data = irq_domain_get_irq_data(domain, virq);
|
||||
struct iproc_msi *msi = irq_data_get_irq_chip_data(data);
|
||||
unsigned int hwirq;
|
||||
|
||||
mutex_lock(&msi->bitmap_lock);
|
||||
|
||||
hwirq = hwirq_to_canonical_hwirq(msi, data->hwirq);
|
||||
bitmap_clear(msi->bitmap, hwirq, msi->nr_cpus);
|
||||
|
||||
mutex_unlock(&msi->bitmap_lock);
|
||||
|
||||
irq_domain_free_irqs_parent(domain, virq, nr_irqs);
|
||||
}
|
||||
|
||||
static const struct irq_domain_ops msi_domain_ops = {
|
||||
.alloc = iproc_msi_irq_domain_alloc,
|
||||
.free = iproc_msi_irq_domain_free,
|
||||
};
|
||||
|
||||
static inline u32 decode_msi_hwirq(struct iproc_msi *msi, u32 eq, u32 head)
|
||||
{
|
||||
u32 *msg, hwirq;
|
||||
unsigned int offs;
|
||||
|
||||
offs = iproc_msi_eq_offset(msi, eq) + head * sizeof(u32);
|
||||
msg = (u32 *)(msi->eq_cpu + offs);
|
||||
hwirq = *msg & IPROC_MSI_EQ_MASK;
|
||||
|
||||
/*
|
||||
* Since we have multiple hwirq mapped to a single MSI vector,
|
||||
* now we need to derive the hwirq at CPU0. It can then be used to
|
||||
* mapped back to virq.
|
||||
*/
|
||||
return hwirq_to_canonical_hwirq(msi, hwirq);
|
||||
}
|
||||
|
||||
static void iproc_msi_handler(struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
struct iproc_msi_grp *grp;
|
||||
struct iproc_msi *msi;
|
||||
struct iproc_pcie *pcie;
|
||||
u32 eq, head, tail, nr_events;
|
||||
unsigned long hwirq;
|
||||
int virq;
|
||||
|
||||
chained_irq_enter(chip, desc);
|
||||
|
||||
grp = irq_desc_get_handler_data(desc);
|
||||
msi = grp->msi;
|
||||
pcie = msi->pcie;
|
||||
eq = grp->eq;
|
||||
|
||||
/*
|
||||
* iProc MSI event queue is tracked by head and tail pointers. Head
|
||||
* pointer indicates the next entry (MSI data) to be consumed by SW in
|
||||
* the queue and needs to be updated by SW. iProc MSI core uses the
|
||||
* tail pointer as the next data insertion point.
|
||||
*
|
||||
* Entries between head and tail pointers contain valid MSI data. MSI
|
||||
* data is guaranteed to be in the event queue memory before the tail
|
||||
* pointer is updated by the iProc MSI core.
|
||||
*/
|
||||
head = iproc_msi_read_reg(msi, IPROC_MSI_EQ_HEAD,
|
||||
eq) & IPROC_MSI_EQ_MASK;
|
||||
do {
|
||||
tail = iproc_msi_read_reg(msi, IPROC_MSI_EQ_TAIL,
|
||||
eq) & IPROC_MSI_EQ_MASK;
|
||||
|
||||
/*
|
||||
* Figure out total number of events (MSI data) to be
|
||||
* processed.
|
||||
*/
|
||||
nr_events = (tail < head) ?
|
||||
(EQ_LEN - (head - tail)) : (tail - head);
|
||||
if (!nr_events)
|
||||
break;
|
||||
|
||||
/* process all outstanding events */
|
||||
while (nr_events--) {
|
||||
hwirq = decode_msi_hwirq(msi, eq, head);
|
||||
virq = irq_find_mapping(msi->inner_domain, hwirq);
|
||||
generic_handle_irq(virq);
|
||||
|
||||
head++;
|
||||
head %= EQ_LEN;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now all outstanding events have been processed. Update the
|
||||
* head pointer.
|
||||
*/
|
||||
iproc_msi_write_reg(msi, IPROC_MSI_EQ_HEAD, eq, head);
|
||||
|
||||
/*
|
||||
* Now go read the tail pointer again to see if there are new
|
||||
* oustanding events that came in during the above window.
|
||||
*/
|
||||
} while (true);
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
||||
static void iproc_msi_enable(struct iproc_msi *msi)
|
||||
{
|
||||
int i, eq;
|
||||
u32 val;
|
||||
|
||||
/* Program memory region for each event queue */
|
||||
for (i = 0; i < msi->nr_eq_region; i++) {
|
||||
dma_addr_t addr = msi->eq_dma + (i * EQ_MEM_REGION_SIZE);
|
||||
|
||||
iproc_msi_write_reg(msi, IPROC_MSI_EQ_PAGE, i,
|
||||
lower_32_bits(addr));
|
||||
iproc_msi_write_reg(msi, IPROC_MSI_EQ_PAGE_UPPER, i,
|
||||
upper_32_bits(addr));
|
||||
}
|
||||
|
||||
/* Program address region for MSI posted writes */
|
||||
for (i = 0; i < msi->nr_msi_region; i++) {
|
||||
phys_addr_t addr = msi->msi_addr + (i * MSI_MEM_REGION_SIZE);
|
||||
|
||||
iproc_msi_write_reg(msi, IPROC_MSI_PAGE, i,
|
||||
lower_32_bits(addr));
|
||||
iproc_msi_write_reg(msi, IPROC_MSI_PAGE_UPPER, i,
|
||||
upper_32_bits(addr));
|
||||
}
|
||||
|
||||
for (eq = 0; eq < msi->nr_irqs; eq++) {
|
||||
/* Enable MSI event queue */
|
||||
val = IPROC_MSI_INTR_EN | IPROC_MSI_INT_N_EVENT |
|
||||
IPROC_MSI_EQ_EN;
|
||||
iproc_msi_write_reg(msi, IPROC_MSI_CTRL, eq, val);
|
||||
|
||||
/*
|
||||
* Some legacy platforms require the MSI interrupt enable
|
||||
* register to be set explicitly.
|
||||
*/
|
||||
if (msi->has_inten_reg) {
|
||||
val = iproc_msi_read_reg(msi, IPROC_MSI_INTS_EN, eq);
|
||||
val |= BIT(eq);
|
||||
iproc_msi_write_reg(msi, IPROC_MSI_INTS_EN, eq, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void iproc_msi_disable(struct iproc_msi *msi)
|
||||
{
|
||||
u32 eq, val;
|
||||
|
||||
for (eq = 0; eq < msi->nr_irqs; eq++) {
|
||||
if (msi->has_inten_reg) {
|
||||
val = iproc_msi_read_reg(msi, IPROC_MSI_INTS_EN, eq);
|
||||
val &= ~BIT(eq);
|
||||
iproc_msi_write_reg(msi, IPROC_MSI_INTS_EN, eq, val);
|
||||
}
|
||||
|
||||
val = iproc_msi_read_reg(msi, IPROC_MSI_CTRL, eq);
|
||||
val &= ~(IPROC_MSI_INTR_EN | IPROC_MSI_INT_N_EVENT |
|
||||
IPROC_MSI_EQ_EN);
|
||||
iproc_msi_write_reg(msi, IPROC_MSI_CTRL, eq, val);
|
||||
}
|
||||
}
|
||||
|
||||
static int iproc_msi_alloc_domains(struct device_node *node,
|
||||
struct iproc_msi *msi)
|
||||
{
|
||||
msi->inner_domain = irq_domain_add_linear(NULL, msi->nr_msi_vecs,
|
||||
&msi_domain_ops, msi);
|
||||
if (!msi->inner_domain)
|
||||
return -ENOMEM;
|
||||
|
||||
msi->msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(node),
|
||||
&iproc_msi_domain_info,
|
||||
msi->inner_domain);
|
||||
if (!msi->msi_domain) {
|
||||
irq_domain_remove(msi->inner_domain);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iproc_msi_free_domains(struct iproc_msi *msi)
|
||||
{
|
||||
if (msi->msi_domain)
|
||||
irq_domain_remove(msi->msi_domain);
|
||||
|
||||
if (msi->inner_domain)
|
||||
irq_domain_remove(msi->inner_domain);
|
||||
}
|
||||
|
||||
static void iproc_msi_irq_free(struct iproc_msi *msi, unsigned int cpu)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = cpu; i < msi->nr_irqs; i += msi->nr_cpus) {
|
||||
irq_set_chained_handler_and_data(msi->grps[i].gic_irq,
|
||||
NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static int iproc_msi_irq_setup(struct iproc_msi *msi, unsigned int cpu)
|
||||
{
|
||||
int i, ret;
|
||||
cpumask_var_t mask;
|
||||
struct iproc_pcie *pcie = msi->pcie;
|
||||
|
||||
for (i = cpu; i < msi->nr_irqs; i += msi->nr_cpus) {
|
||||
irq_set_chained_handler_and_data(msi->grps[i].gic_irq,
|
||||
iproc_msi_handler,
|
||||
&msi->grps[i]);
|
||||
/* Dedicate GIC interrupt to each CPU core */
|
||||
if (alloc_cpumask_var(&mask, GFP_KERNEL)) {
|
||||
cpumask_clear(mask);
|
||||
cpumask_set_cpu(cpu, mask);
|
||||
ret = irq_set_affinity(msi->grps[i].gic_irq, mask);
|
||||
if (ret)
|
||||
dev_err(pcie->dev,
|
||||
"failed to set affinity for IRQ%d\n",
|
||||
msi->grps[i].gic_irq);
|
||||
free_cpumask_var(mask);
|
||||
} else {
|
||||
dev_err(pcie->dev, "failed to alloc CPU mask\n");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
/* Free all configured/unconfigured IRQs */
|
||||
iproc_msi_irq_free(msi, cpu);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iproc_msi_init(struct iproc_pcie *pcie, struct device_node *node)
|
||||
{
|
||||
struct iproc_msi *msi;
|
||||
int i, ret;
|
||||
unsigned int cpu;
|
||||
|
||||
if (!of_device_is_compatible(node, "brcm,iproc-msi"))
|
||||
return -ENODEV;
|
||||
|
||||
if (!of_find_property(node, "msi-controller", NULL))
|
||||
return -ENODEV;
|
||||
|
||||
if (pcie->msi)
|
||||
return -EBUSY;
|
||||
|
||||
msi = devm_kzalloc(pcie->dev, sizeof(*msi), GFP_KERNEL);
|
||||
if (!msi)
|
||||
return -ENOMEM;
|
||||
|
||||
msi->pcie = pcie;
|
||||
pcie->msi = msi;
|
||||
msi->msi_addr = pcie->base_addr;
|
||||
mutex_init(&msi->bitmap_lock);
|
||||
msi->nr_cpus = num_possible_cpus();
|
||||
|
||||
msi->nr_irqs = of_irq_count(node);
|
||||
if (!msi->nr_irqs) {
|
||||
dev_err(pcie->dev, "found no MSI GIC interrupt\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (msi->nr_irqs > NR_HW_IRQS) {
|
||||
dev_warn(pcie->dev, "too many MSI GIC interrupts defined %d\n",
|
||||
msi->nr_irqs);
|
||||
msi->nr_irqs = NR_HW_IRQS;
|
||||
}
|
||||
|
||||
if (msi->nr_irqs < msi->nr_cpus) {
|
||||
dev_err(pcie->dev,
|
||||
"not enough GIC interrupts for MSI affinity\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (msi->nr_irqs % msi->nr_cpus != 0) {
|
||||
msi->nr_irqs -= msi->nr_irqs % msi->nr_cpus;
|
||||
dev_warn(pcie->dev, "Reducing number of interrupts to %d\n",
|
||||
msi->nr_irqs);
|
||||
}
|
||||
|
||||
switch (pcie->type) {
|
||||
case IPROC_PCIE_PAXB:
|
||||
msi->reg_offsets = iproc_msi_reg_paxb;
|
||||
msi->nr_eq_region = 1;
|
||||
msi->nr_msi_region = 1;
|
||||
break;
|
||||
case IPROC_PCIE_PAXC:
|
||||
msi->reg_offsets = iproc_msi_reg_paxc;
|
||||
msi->nr_eq_region = msi->nr_irqs;
|
||||
msi->nr_msi_region = msi->nr_irqs;
|
||||
break;
|
||||
default:
|
||||
dev_err(pcie->dev, "incompatible iProc PCIe interface\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (of_find_property(node, "brcm,pcie-msi-inten", NULL))
|
||||
msi->has_inten_reg = true;
|
||||
|
||||
msi->nr_msi_vecs = msi->nr_irqs * EQ_LEN;
|
||||
msi->bitmap = devm_kcalloc(pcie->dev, BITS_TO_LONGS(msi->nr_msi_vecs),
|
||||
sizeof(*msi->bitmap), GFP_KERNEL);
|
||||
if (!msi->bitmap)
|
||||
return -ENOMEM;
|
||||
|
||||
msi->grps = devm_kcalloc(pcie->dev, msi->nr_irqs, sizeof(*msi->grps),
|
||||
GFP_KERNEL);
|
||||
if (!msi->grps)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < msi->nr_irqs; i++) {
|
||||
unsigned int irq = irq_of_parse_and_map(node, i);
|
||||
|
||||
if (!irq) {
|
||||
dev_err(pcie->dev, "unable to parse/map interrupt\n");
|
||||
ret = -ENODEV;
|
||||
goto free_irqs;
|
||||
}
|
||||
msi->grps[i].gic_irq = irq;
|
||||
msi->grps[i].msi = msi;
|
||||
msi->grps[i].eq = i;
|
||||
}
|
||||
|
||||
/* Reserve memory for event queue and make sure memories are zeroed */
|
||||
msi->eq_cpu = dma_zalloc_coherent(pcie->dev,
|
||||
msi->nr_eq_region * EQ_MEM_REGION_SIZE,
|
||||
&msi->eq_dma, GFP_KERNEL);
|
||||
if (!msi->eq_cpu) {
|
||||
ret = -ENOMEM;
|
||||
goto free_irqs;
|
||||
}
|
||||
|
||||
ret = iproc_msi_alloc_domains(node, msi);
|
||||
if (ret) {
|
||||
dev_err(pcie->dev, "failed to create MSI domains\n");
|
||||
goto free_eq_dma;
|
||||
}
|
||||
|
||||
for_each_online_cpu(cpu) {
|
||||
ret = iproc_msi_irq_setup(msi, cpu);
|
||||
if (ret)
|
||||
goto free_msi_irq;
|
||||
}
|
||||
|
||||
iproc_msi_enable(msi);
|
||||
|
||||
return 0;
|
||||
|
||||
free_msi_irq:
|
||||
for_each_online_cpu(cpu)
|
||||
iproc_msi_irq_free(msi, cpu);
|
||||
iproc_msi_free_domains(msi);
|
||||
|
||||
free_eq_dma:
|
||||
dma_free_coherent(pcie->dev, msi->nr_eq_region * EQ_MEM_REGION_SIZE,
|
||||
msi->eq_cpu, msi->eq_dma);
|
||||
|
||||
free_irqs:
|
||||
for (i = 0; i < msi->nr_irqs; i++) {
|
||||
if (msi->grps[i].gic_irq)
|
||||
irq_dispose_mapping(msi->grps[i].gic_irq);
|
||||
}
|
||||
pcie->msi = NULL;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(iproc_msi_init);
|
||||
|
||||
void iproc_msi_exit(struct iproc_pcie *pcie)
|
||||
{
|
||||
struct iproc_msi *msi = pcie->msi;
|
||||
unsigned int i, cpu;
|
||||
|
||||
if (!msi)
|
||||
return;
|
||||
|
||||
iproc_msi_disable(msi);
|
||||
|
||||
for_each_online_cpu(cpu)
|
||||
iproc_msi_irq_free(msi, cpu);
|
||||
|
||||
iproc_msi_free_domains(msi);
|
||||
|
||||
dma_free_coherent(pcie->dev, msi->nr_eq_region * EQ_MEM_REGION_SIZE,
|
||||
msi->eq_cpu, msi->eq_dma);
|
||||
|
||||
for (i = 0; i < msi->nr_irqs; i++) {
|
||||
if (msi->grps[i].gic_irq)
|
||||
irq_dispose_mapping(msi->grps[i].gic_irq);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(iproc_msi_exit);
|
@ -26,8 +26,21 @@
|
||||
|
||||
#include "pcie-iproc.h"
|
||||
|
||||
static const struct of_device_id iproc_pcie_of_match_table[] = {
|
||||
{
|
||||
.compatible = "brcm,iproc-pcie",
|
||||
.data = (int *)IPROC_PCIE_PAXB,
|
||||
}, {
|
||||
.compatible = "brcm,iproc-pcie-paxc",
|
||||
.data = (int *)IPROC_PCIE_PAXC,
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, iproc_pcie_of_match_table);
|
||||
|
||||
static int iproc_pcie_pltfm_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct of_device_id *of_id;
|
||||
struct iproc_pcie *pcie;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct resource reg;
|
||||
@ -35,11 +48,16 @@ static int iproc_pcie_pltfm_probe(struct platform_device *pdev)
|
||||
LIST_HEAD(res);
|
||||
int ret;
|
||||
|
||||
of_id = of_match_device(iproc_pcie_of_match_table, &pdev->dev);
|
||||
if (!of_id)
|
||||
return -EINVAL;
|
||||
|
||||
pcie = devm_kzalloc(&pdev->dev, sizeof(struct iproc_pcie), GFP_KERNEL);
|
||||
if (!pcie)
|
||||
return -ENOMEM;
|
||||
|
||||
pcie->dev = &pdev->dev;
|
||||
pcie->type = (enum iproc_pcie_type)of_id->data;
|
||||
platform_set_drvdata(pdev, pcie);
|
||||
|
||||
ret = of_address_to_resource(np, 0, ®);
|
||||
@ -53,6 +71,7 @@ static int iproc_pcie_pltfm_probe(struct platform_device *pdev)
|
||||
dev_err(pcie->dev, "unable to map controller registers\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
pcie->base_addr = reg.start;
|
||||
|
||||
if (of_property_read_bool(np, "brcm,pcie-ob")) {
|
||||
u32 val;
|
||||
@ -114,12 +133,6 @@ static int iproc_pcie_pltfm_remove(struct platform_device *pdev)
|
||||
return iproc_pcie_remove(pcie);
|
||||
}
|
||||
|
||||
static const struct of_device_id iproc_pcie_of_match_table[] = {
|
||||
{ .compatible = "brcm,iproc-pcie", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, iproc_pcie_of_match_table);
|
||||
|
||||
static struct platform_driver iproc_pcie_pltfm_driver = {
|
||||
.driver = {
|
||||
.name = "iproc-pcie",
|
||||
|
@ -30,20 +30,16 @@
|
||||
|
||||
#include "pcie-iproc.h"
|
||||
|
||||
#define CLK_CONTROL_OFFSET 0x000
|
||||
#define EP_PERST_SOURCE_SELECT_SHIFT 2
|
||||
#define EP_PERST_SOURCE_SELECT BIT(EP_PERST_SOURCE_SELECT_SHIFT)
|
||||
#define EP_MODE_SURVIVE_PERST_SHIFT 1
|
||||
#define EP_MODE_SURVIVE_PERST BIT(EP_MODE_SURVIVE_PERST_SHIFT)
|
||||
#define RC_PCIE_RST_OUTPUT_SHIFT 0
|
||||
#define RC_PCIE_RST_OUTPUT BIT(RC_PCIE_RST_OUTPUT_SHIFT)
|
||||
#define PAXC_RESET_MASK 0x7f
|
||||
|
||||
#define CFG_IND_ADDR_OFFSET 0x120
|
||||
#define CFG_IND_ADDR_MASK 0x00001ffc
|
||||
|
||||
#define CFG_IND_DATA_OFFSET 0x124
|
||||
|
||||
#define CFG_ADDR_OFFSET 0x1f8
|
||||
#define CFG_ADDR_BUS_NUM_SHIFT 20
|
||||
#define CFG_ADDR_BUS_NUM_MASK 0x0ff00000
|
||||
#define CFG_ADDR_DEV_NUM_SHIFT 15
|
||||
@ -55,12 +51,8 @@
|
||||
#define CFG_ADDR_CFG_TYPE_SHIFT 0
|
||||
#define CFG_ADDR_CFG_TYPE_MASK 0x00000003
|
||||
|
||||
#define CFG_DATA_OFFSET 0x1fc
|
||||
|
||||
#define SYS_RC_INTX_EN 0x330
|
||||
#define SYS_RC_INTX_MASK 0xf
|
||||
|
||||
#define PCIE_LINK_STATUS_OFFSET 0xf0c
|
||||
#define PCIE_PHYLINKUP_SHIFT 3
|
||||
#define PCIE_PHYLINKUP BIT(PCIE_PHYLINKUP_SHIFT)
|
||||
#define PCIE_DL_ACTIVE_SHIFT 2
|
||||
@ -71,12 +63,54 @@
|
||||
#define OARR_SIZE_CFG_SHIFT 1
|
||||
#define OARR_SIZE_CFG BIT(OARR_SIZE_CFG_SHIFT)
|
||||
|
||||
#define OARR_LO(window) (0xd20 + (window) * 8)
|
||||
#define OARR_HI(window) (0xd24 + (window) * 8)
|
||||
#define OMAP_LO(window) (0xd40 + (window) * 8)
|
||||
#define OMAP_HI(window) (0xd44 + (window) * 8)
|
||||
|
||||
#define MAX_NUM_OB_WINDOWS 2
|
||||
#define MAX_NUM_PAXC_PF 4
|
||||
|
||||
#define IPROC_PCIE_REG_INVALID 0xffff
|
||||
|
||||
enum iproc_pcie_reg {
|
||||
IPROC_PCIE_CLK_CTRL = 0,
|
||||
IPROC_PCIE_CFG_IND_ADDR,
|
||||
IPROC_PCIE_CFG_IND_DATA,
|
||||
IPROC_PCIE_CFG_ADDR,
|
||||
IPROC_PCIE_CFG_DATA,
|
||||
IPROC_PCIE_INTX_EN,
|
||||
IPROC_PCIE_OARR_LO,
|
||||
IPROC_PCIE_OARR_HI,
|
||||
IPROC_PCIE_OMAP_LO,
|
||||
IPROC_PCIE_OMAP_HI,
|
||||
IPROC_PCIE_LINK_STATUS,
|
||||
};
|
||||
|
||||
/* iProc PCIe PAXB registers */
|
||||
static const u16 iproc_pcie_reg_paxb[] = {
|
||||
[IPROC_PCIE_CLK_CTRL] = 0x000,
|
||||
[IPROC_PCIE_CFG_IND_ADDR] = 0x120,
|
||||
[IPROC_PCIE_CFG_IND_DATA] = 0x124,
|
||||
[IPROC_PCIE_CFG_ADDR] = 0x1f8,
|
||||
[IPROC_PCIE_CFG_DATA] = 0x1fc,
|
||||
[IPROC_PCIE_INTX_EN] = 0x330,
|
||||
[IPROC_PCIE_OARR_LO] = 0xd20,
|
||||
[IPROC_PCIE_OARR_HI] = 0xd24,
|
||||
[IPROC_PCIE_OMAP_LO] = 0xd40,
|
||||
[IPROC_PCIE_OMAP_HI] = 0xd44,
|
||||
[IPROC_PCIE_LINK_STATUS] = 0xf0c,
|
||||
};
|
||||
|
||||
/* iProc PCIe PAXC v1 registers */
|
||||
static const u16 iproc_pcie_reg_paxc[] = {
|
||||
[IPROC_PCIE_CLK_CTRL] = 0x000,
|
||||
[IPROC_PCIE_CFG_IND_ADDR] = 0x1f0,
|
||||
[IPROC_PCIE_CFG_IND_DATA] = 0x1f4,
|
||||
[IPROC_PCIE_CFG_ADDR] = 0x1f8,
|
||||
[IPROC_PCIE_CFG_DATA] = 0x1fc,
|
||||
[IPROC_PCIE_INTX_EN] = IPROC_PCIE_REG_INVALID,
|
||||
[IPROC_PCIE_OARR_LO] = IPROC_PCIE_REG_INVALID,
|
||||
[IPROC_PCIE_OARR_HI] = IPROC_PCIE_REG_INVALID,
|
||||
[IPROC_PCIE_OMAP_LO] = IPROC_PCIE_REG_INVALID,
|
||||
[IPROC_PCIE_OMAP_HI] = IPROC_PCIE_REG_INVALID,
|
||||
[IPROC_PCIE_LINK_STATUS] = IPROC_PCIE_REG_INVALID,
|
||||
};
|
||||
|
||||
static inline struct iproc_pcie *iproc_data(struct pci_bus *bus)
|
||||
{
|
||||
@ -91,6 +125,65 @@ static inline struct iproc_pcie *iproc_data(struct pci_bus *bus)
|
||||
return pcie;
|
||||
}
|
||||
|
||||
static inline bool iproc_pcie_reg_is_invalid(u16 reg_offset)
|
||||
{
|
||||
return !!(reg_offset == IPROC_PCIE_REG_INVALID);
|
||||
}
|
||||
|
||||
static inline u16 iproc_pcie_reg_offset(struct iproc_pcie *pcie,
|
||||
enum iproc_pcie_reg reg)
|
||||
{
|
||||
return pcie->reg_offsets[reg];
|
||||
}
|
||||
|
||||
static inline u32 iproc_pcie_read_reg(struct iproc_pcie *pcie,
|
||||
enum iproc_pcie_reg reg)
|
||||
{
|
||||
u16 offset = iproc_pcie_reg_offset(pcie, reg);
|
||||
|
||||
if (iproc_pcie_reg_is_invalid(offset))
|
||||
return 0;
|
||||
|
||||
return readl(pcie->base + offset);
|
||||
}
|
||||
|
||||
static inline void iproc_pcie_write_reg(struct iproc_pcie *pcie,
|
||||
enum iproc_pcie_reg reg, u32 val)
|
||||
{
|
||||
u16 offset = iproc_pcie_reg_offset(pcie, reg);
|
||||
|
||||
if (iproc_pcie_reg_is_invalid(offset))
|
||||
return;
|
||||
|
||||
writel(val, pcie->base + offset);
|
||||
}
|
||||
|
||||
static inline void iproc_pcie_ob_write(struct iproc_pcie *pcie,
|
||||
enum iproc_pcie_reg reg,
|
||||
unsigned window, u32 val)
|
||||
{
|
||||
u16 offset = iproc_pcie_reg_offset(pcie, reg);
|
||||
|
||||
if (iproc_pcie_reg_is_invalid(offset))
|
||||
return;
|
||||
|
||||
writel(val, pcie->base + offset + (window * 8));
|
||||
}
|
||||
|
||||
static inline bool iproc_pcie_device_is_valid(struct iproc_pcie *pcie,
|
||||
unsigned int slot,
|
||||
unsigned int fn)
|
||||
{
|
||||
if (slot > 0)
|
||||
return false;
|
||||
|
||||
/* PAXC can only support limited number of functions */
|
||||
if (pcie->type == IPROC_PCIE_PAXC && fn >= MAX_NUM_PAXC_PF)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Note access to the configuration registers are protected at the higher layer
|
||||
* by 'pci_lock' in drivers/pci/access.c
|
||||
@ -104,28 +197,34 @@ static void __iomem *iproc_pcie_map_cfg_bus(struct pci_bus *bus,
|
||||
unsigned fn = PCI_FUNC(devfn);
|
||||
unsigned busno = bus->number;
|
||||
u32 val;
|
||||
u16 offset;
|
||||
|
||||
if (!iproc_pcie_device_is_valid(pcie, slot, fn))
|
||||
return NULL;
|
||||
|
||||
/* root complex access */
|
||||
if (busno == 0) {
|
||||
if (slot >= 1)
|
||||
iproc_pcie_write_reg(pcie, IPROC_PCIE_CFG_IND_ADDR,
|
||||
where & CFG_IND_ADDR_MASK);
|
||||
offset = iproc_pcie_reg_offset(pcie, IPROC_PCIE_CFG_IND_DATA);
|
||||
if (iproc_pcie_reg_is_invalid(offset))
|
||||
return NULL;
|
||||
writel(where & CFG_IND_ADDR_MASK,
|
||||
pcie->base + CFG_IND_ADDR_OFFSET);
|
||||
return (pcie->base + CFG_IND_DATA_OFFSET);
|
||||
else
|
||||
return (pcie->base + offset);
|
||||
}
|
||||
|
||||
if (fn > 1)
|
||||
return NULL;
|
||||
|
||||
/* EP device access */
|
||||
val = (busno << CFG_ADDR_BUS_NUM_SHIFT) |
|
||||
(slot << CFG_ADDR_DEV_NUM_SHIFT) |
|
||||
(fn << CFG_ADDR_FUNC_NUM_SHIFT) |
|
||||
(where & CFG_ADDR_REG_NUM_MASK) |
|
||||
(1 & CFG_ADDR_CFG_TYPE_MASK);
|
||||
writel(val, pcie->base + CFG_ADDR_OFFSET);
|
||||
|
||||
return (pcie->base + CFG_DATA_OFFSET);
|
||||
iproc_pcie_write_reg(pcie, IPROC_PCIE_CFG_ADDR, val);
|
||||
offset = iproc_pcie_reg_offset(pcie, IPROC_PCIE_CFG_DATA);
|
||||
if (iproc_pcie_reg_is_invalid(offset))
|
||||
return NULL;
|
||||
else
|
||||
return (pcie->base + offset);
|
||||
}
|
||||
|
||||
static struct pci_ops iproc_pcie_ops = {
|
||||
@ -138,18 +237,29 @@ static void iproc_pcie_reset(struct iproc_pcie *pcie)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (pcie->type == IPROC_PCIE_PAXC) {
|
||||
val = iproc_pcie_read_reg(pcie, IPROC_PCIE_CLK_CTRL);
|
||||
val &= ~PAXC_RESET_MASK;
|
||||
iproc_pcie_write_reg(pcie, IPROC_PCIE_CLK_CTRL, val);
|
||||
udelay(100);
|
||||
val |= PAXC_RESET_MASK;
|
||||
iproc_pcie_write_reg(pcie, IPROC_PCIE_CLK_CTRL, val);
|
||||
udelay(100);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Select perst_b signal as reset source. Put the device into reset,
|
||||
* and then bring it out of reset
|
||||
*/
|
||||
val = readl(pcie->base + CLK_CONTROL_OFFSET);
|
||||
val = iproc_pcie_read_reg(pcie, IPROC_PCIE_CLK_CTRL);
|
||||
val &= ~EP_PERST_SOURCE_SELECT & ~EP_MODE_SURVIVE_PERST &
|
||||
~RC_PCIE_RST_OUTPUT;
|
||||
writel(val, pcie->base + CLK_CONTROL_OFFSET);
|
||||
iproc_pcie_write_reg(pcie, IPROC_PCIE_CLK_CTRL, val);
|
||||
udelay(250);
|
||||
|
||||
val |= RC_PCIE_RST_OUTPUT;
|
||||
writel(val, pcie->base + CLK_CONTROL_OFFSET);
|
||||
iproc_pcie_write_reg(pcie, IPROC_PCIE_CLK_CTRL, val);
|
||||
msleep(100);
|
||||
}
|
||||
|
||||
@ -160,7 +270,14 @@ static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus)
|
||||
u16 pos, link_status;
|
||||
bool link_is_active = false;
|
||||
|
||||
val = readl(pcie->base + PCIE_LINK_STATUS_OFFSET);
|
||||
/*
|
||||
* PAXC connects to emulated endpoint devices directly and does not
|
||||
* have a Serdes. Therefore skip the link detection logic here.
|
||||
*/
|
||||
if (pcie->type == IPROC_PCIE_PAXC)
|
||||
return 0;
|
||||
|
||||
val = iproc_pcie_read_reg(pcie, IPROC_PCIE_LINK_STATUS);
|
||||
if (!(val & PCIE_PHYLINKUP) || !(val & PCIE_DL_ACTIVE)) {
|
||||
dev_err(pcie->dev, "PHY or data link is INACTIVE!\n");
|
||||
return -ENODEV;
|
||||
@ -221,7 +338,7 @@ static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus)
|
||||
|
||||
static void iproc_pcie_enable(struct iproc_pcie *pcie)
|
||||
{
|
||||
writel(SYS_RC_INTX_MASK, pcie->base + SYS_RC_INTX_EN);
|
||||
iproc_pcie_write_reg(pcie, IPROC_PCIE_INTX_EN, SYS_RC_INTX_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -245,7 +362,7 @@ static int iproc_pcie_setup_ob(struct iproc_pcie *pcie, u64 axi_addr,
|
||||
|
||||
if (size > max_size) {
|
||||
dev_err(pcie->dev,
|
||||
"res size 0x%pap exceeds max supported size 0x%llx\n",
|
||||
"res size %pap exceeds max supported size 0x%llx\n",
|
||||
&size, max_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -272,11 +389,15 @@ static int iproc_pcie_setup_ob(struct iproc_pcie *pcie, u64 axi_addr,
|
||||
axi_addr -= ob->axi_offset;
|
||||
|
||||
for (i = 0; i < MAX_NUM_OB_WINDOWS; i++) {
|
||||
writel(lower_32_bits(axi_addr) | OARR_VALID |
|
||||
(ob->set_oarr_size ? 1 : 0), pcie->base + OARR_LO(i));
|
||||
writel(upper_32_bits(axi_addr), pcie->base + OARR_HI(i));
|
||||
writel(lower_32_bits(pci_addr), pcie->base + OMAP_LO(i));
|
||||
writel(upper_32_bits(pci_addr), pcie->base + OMAP_HI(i));
|
||||
iproc_pcie_ob_write(pcie, IPROC_PCIE_OARR_LO, i,
|
||||
lower_32_bits(axi_addr) | OARR_VALID |
|
||||
(ob->set_oarr_size ? 1 : 0));
|
||||
iproc_pcie_ob_write(pcie, IPROC_PCIE_OARR_HI, i,
|
||||
upper_32_bits(axi_addr));
|
||||
iproc_pcie_ob_write(pcie, IPROC_PCIE_OMAP_LO, i,
|
||||
lower_32_bits(pci_addr));
|
||||
iproc_pcie_ob_write(pcie, IPROC_PCIE_OMAP_HI, i,
|
||||
upper_32_bits(pci_addr));
|
||||
|
||||
size -= ob->window_size;
|
||||
if (size == 0)
|
||||
@ -319,6 +440,26 @@ static int iproc_pcie_map_ranges(struct iproc_pcie *pcie,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iproc_pcie_msi_enable(struct iproc_pcie *pcie)
|
||||
{
|
||||
struct device_node *msi_node;
|
||||
|
||||
msi_node = of_parse_phandle(pcie->dev->of_node, "msi-parent", 0);
|
||||
if (!msi_node)
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* If another MSI controller is being used, the call below should fail
|
||||
* but that is okay
|
||||
*/
|
||||
return iproc_msi_init(pcie, msi_node);
|
||||
}
|
||||
|
||||
static void iproc_pcie_msi_disable(struct iproc_pcie *pcie)
|
||||
{
|
||||
iproc_msi_exit(pcie);
|
||||
}
|
||||
|
||||
int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res)
|
||||
{
|
||||
int ret;
|
||||
@ -340,6 +481,19 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res)
|
||||
goto err_exit_phy;
|
||||
}
|
||||
|
||||
switch (pcie->type) {
|
||||
case IPROC_PCIE_PAXB:
|
||||
pcie->reg_offsets = iproc_pcie_reg_paxb;
|
||||
break;
|
||||
case IPROC_PCIE_PAXC:
|
||||
pcie->reg_offsets = iproc_pcie_reg_paxc;
|
||||
break;
|
||||
default:
|
||||
dev_err(pcie->dev, "incompatible iProc PCIe interface\n");
|
||||
ret = -EINVAL;
|
||||
goto err_power_off_phy;
|
||||
}
|
||||
|
||||
iproc_pcie_reset(pcie);
|
||||
|
||||
if (pcie->need_ob_cfg) {
|
||||
@ -373,6 +527,10 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res)
|
||||
|
||||
iproc_pcie_enable(pcie);
|
||||
|
||||
if (IS_ENABLED(CONFIG_PCI_MSI))
|
||||
if (iproc_pcie_msi_enable(pcie))
|
||||
dev_info(pcie->dev, "not using iProc MSI\n");
|
||||
|
||||
pci_scan_child_bus(bus);
|
||||
pci_assign_unassigned_bus_resources(bus);
|
||||
pci_fixup_irqs(pci_common_swizzle, pcie->map_irq);
|
||||
@ -397,6 +555,8 @@ int iproc_pcie_remove(struct iproc_pcie *pcie)
|
||||
pci_stop_root_bus(pcie->root_bus);
|
||||
pci_remove_root_bus(pcie->root_bus);
|
||||
|
||||
iproc_pcie_msi_disable(pcie);
|
||||
|
||||
phy_power_off(pcie->phy);
|
||||
phy_exit(pcie->phy);
|
||||
|
||||
|
@ -14,6 +14,20 @@
|
||||
#ifndef _PCIE_IPROC_H
|
||||
#define _PCIE_IPROC_H
|
||||
|
||||
/**
|
||||
* iProc PCIe interface type
|
||||
*
|
||||
* PAXB is the wrapper used in root complex that can be connected to an
|
||||
* external endpoint device.
|
||||
*
|
||||
* PAXC is the wrapper used in root complex dedicated for internal emulated
|
||||
* endpoint devices.
|
||||
*/
|
||||
enum iproc_pcie_type {
|
||||
IPROC_PCIE_PAXB = 0,
|
||||
IPROC_PCIE_PAXC,
|
||||
};
|
||||
|
||||
/**
|
||||
* iProc PCIe outbound mapping
|
||||
* @set_oarr_size: indicates the OARR size bit needs to be set
|
||||
@ -27,21 +41,30 @@ struct iproc_pcie_ob {
|
||||
resource_size_t window_size;
|
||||
};
|
||||
|
||||
struct iproc_msi;
|
||||
|
||||
/**
|
||||
* iProc PCIe device
|
||||
*
|
||||
* @dev: pointer to device data structure
|
||||
* @type: iProc PCIe interface type
|
||||
* @reg_offsets: register offsets
|
||||
* @base: PCIe host controller I/O register base
|
||||
* @base_addr: PCIe host controller register base physical address
|
||||
* @sysdata: Per PCI controller data (ARM-specific)
|
||||
* @root_bus: pointer to root bus
|
||||
* @phy: optional PHY device that controls the Serdes
|
||||
* @irqs: interrupt IDs
|
||||
* @map_irq: function callback to map interrupts
|
||||
* @need_ob_cfg: indidates SW needs to configure the outbound mapping window
|
||||
* @need_ob_cfg: indicates SW needs to configure the outbound mapping window
|
||||
* @ob: outbound mapping parameters
|
||||
* @msi: MSI data
|
||||
*/
|
||||
struct iproc_pcie {
|
||||
struct device *dev;
|
||||
enum iproc_pcie_type type;
|
||||
const u16 *reg_offsets;
|
||||
void __iomem *base;
|
||||
phys_addr_t base_addr;
|
||||
#ifdef CONFIG_ARM
|
||||
struct pci_sys_data sysdata;
|
||||
#endif
|
||||
@ -50,9 +73,24 @@ struct iproc_pcie {
|
||||
int (*map_irq)(const struct pci_dev *, u8, u8);
|
||||
bool need_ob_cfg;
|
||||
struct iproc_pcie_ob ob;
|
||||
struct iproc_msi *msi;
|
||||
};
|
||||
|
||||
int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res);
|
||||
int iproc_pcie_remove(struct iproc_pcie *pcie);
|
||||
|
||||
#ifdef CONFIG_PCIE_IPROC_MSI
|
||||
int iproc_msi_init(struct iproc_pcie *pcie, struct device_node *node);
|
||||
void iproc_msi_exit(struct iproc_pcie *pcie);
|
||||
#else
|
||||
static inline int iproc_msi_init(struct iproc_pcie *pcie,
|
||||
struct device_node *node)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
static inline void iproc_msi_exit(struct iproc_pcie *pcie)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _PCIE_IPROC_H */
|
||||
|
616
drivers/pci/host/pcie-qcom.c
Normal file
616
drivers/pci/host/pcie-qcom.c
Normal file
@ -0,0 +1,616 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
|
||||
* Copyright 2015 Linaro Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "pcie-designware.h"
|
||||
|
||||
#define PCIE20_PARF_PHY_CTRL 0x40
|
||||
#define PCIE20_PARF_PHY_REFCLK 0x4C
|
||||
#define PCIE20_PARF_DBI_BASE_ADDR 0x168
|
||||
#define PCIE20_PARF_SLV_ADDR_SPACE_SIZE 0x16c
|
||||
#define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT 0x178
|
||||
|
||||
#define PCIE20_ELBI_SYS_CTRL 0x04
|
||||
#define PCIE20_ELBI_SYS_CTRL_LT_ENABLE BIT(0)
|
||||
|
||||
#define PCIE20_CAP 0x70
|
||||
|
||||
#define PERST_DELAY_US 1000
|
||||
|
||||
struct qcom_pcie_resources_v0 {
|
||||
struct clk *iface_clk;
|
||||
struct clk *core_clk;
|
||||
struct clk *phy_clk;
|
||||
struct reset_control *pci_reset;
|
||||
struct reset_control *axi_reset;
|
||||
struct reset_control *ahb_reset;
|
||||
struct reset_control *por_reset;
|
||||
struct reset_control *phy_reset;
|
||||
struct regulator *vdda;
|
||||
struct regulator *vdda_phy;
|
||||
struct regulator *vdda_refclk;
|
||||
};
|
||||
|
||||
struct qcom_pcie_resources_v1 {
|
||||
struct clk *iface;
|
||||
struct clk *aux;
|
||||
struct clk *master_bus;
|
||||
struct clk *slave_bus;
|
||||
struct reset_control *core;
|
||||
struct regulator *vdda;
|
||||
};
|
||||
|
||||
union qcom_pcie_resources {
|
||||
struct qcom_pcie_resources_v0 v0;
|
||||
struct qcom_pcie_resources_v1 v1;
|
||||
};
|
||||
|
||||
struct qcom_pcie;
|
||||
|
||||
struct qcom_pcie_ops {
|
||||
int (*get_resources)(struct qcom_pcie *pcie);
|
||||
int (*init)(struct qcom_pcie *pcie);
|
||||
void (*deinit)(struct qcom_pcie *pcie);
|
||||
};
|
||||
|
||||
struct qcom_pcie {
|
||||
struct pcie_port pp;
|
||||
struct device *dev;
|
||||
union qcom_pcie_resources res;
|
||||
void __iomem *parf;
|
||||
void __iomem *dbi;
|
||||
void __iomem *elbi;
|
||||
struct phy *phy;
|
||||
struct gpio_desc *reset;
|
||||
struct qcom_pcie_ops *ops;
|
||||
};
|
||||
|
||||
#define to_qcom_pcie(x) container_of(x, struct qcom_pcie, pp)
|
||||
|
||||
static void qcom_ep_reset_assert(struct qcom_pcie *pcie)
|
||||
{
|
||||
gpiod_set_value(pcie->reset, 1);
|
||||
usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500);
|
||||
}
|
||||
|
||||
static void qcom_ep_reset_deassert(struct qcom_pcie *pcie)
|
||||
{
|
||||
gpiod_set_value(pcie->reset, 0);
|
||||
usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500);
|
||||
}
|
||||
|
||||
static irqreturn_t qcom_pcie_msi_irq_handler(int irq, void *arg)
|
||||
{
|
||||
struct pcie_port *pp = arg;
|
||||
|
||||
return dw_handle_msi_irq(pp);
|
||||
}
|
||||
|
||||
static int qcom_pcie_establish_link(struct qcom_pcie *pcie)
|
||||
{
|
||||
struct device *dev = pcie->dev;
|
||||
unsigned int retries = 0;
|
||||
u32 val;
|
||||
|
||||
if (dw_pcie_link_up(&pcie->pp))
|
||||
return 0;
|
||||
|
||||
/* enable link training */
|
||||
val = readl(pcie->elbi + PCIE20_ELBI_SYS_CTRL);
|
||||
val |= PCIE20_ELBI_SYS_CTRL_LT_ENABLE;
|
||||
writel(val, pcie->elbi + PCIE20_ELBI_SYS_CTRL);
|
||||
|
||||
do {
|
||||
if (dw_pcie_link_up(&pcie->pp))
|
||||
return 0;
|
||||
usleep_range(250, 1000);
|
||||
} while (retries < 200);
|
||||
|
||||
dev_warn(dev, "phy link never came up\n");
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int qcom_pcie_get_resources_v0(struct qcom_pcie *pcie)
|
||||
{
|
||||
struct qcom_pcie_resources_v0 *res = &pcie->res.v0;
|
||||
struct device *dev = pcie->dev;
|
||||
|
||||
res->vdda = devm_regulator_get(dev, "vdda");
|
||||
if (IS_ERR(res->vdda))
|
||||
return PTR_ERR(res->vdda);
|
||||
|
||||
res->vdda_phy = devm_regulator_get(dev, "vdda_phy");
|
||||
if (IS_ERR(res->vdda_phy))
|
||||
return PTR_ERR(res->vdda_phy);
|
||||
|
||||
res->vdda_refclk = devm_regulator_get(dev, "vdda_refclk");
|
||||
if (IS_ERR(res->vdda_refclk))
|
||||
return PTR_ERR(res->vdda_refclk);
|
||||
|
||||
res->iface_clk = devm_clk_get(dev, "iface");
|
||||
if (IS_ERR(res->iface_clk))
|
||||
return PTR_ERR(res->iface_clk);
|
||||
|
||||
res->core_clk = devm_clk_get(dev, "core");
|
||||
if (IS_ERR(res->core_clk))
|
||||
return PTR_ERR(res->core_clk);
|
||||
|
||||
res->phy_clk = devm_clk_get(dev, "phy");
|
||||
if (IS_ERR(res->phy_clk))
|
||||
return PTR_ERR(res->phy_clk);
|
||||
|
||||
res->pci_reset = devm_reset_control_get(dev, "pci");
|
||||
if (IS_ERR(res->pci_reset))
|
||||
return PTR_ERR(res->pci_reset);
|
||||
|
||||
res->axi_reset = devm_reset_control_get(dev, "axi");
|
||||
if (IS_ERR(res->axi_reset))
|
||||
return PTR_ERR(res->axi_reset);
|
||||
|
||||
res->ahb_reset = devm_reset_control_get(dev, "ahb");
|
||||
if (IS_ERR(res->ahb_reset))
|
||||
return PTR_ERR(res->ahb_reset);
|
||||
|
||||
res->por_reset = devm_reset_control_get(dev, "por");
|
||||
if (IS_ERR(res->por_reset))
|
||||
return PTR_ERR(res->por_reset);
|
||||
|
||||
res->phy_reset = devm_reset_control_get(dev, "phy");
|
||||
if (IS_ERR(res->phy_reset))
|
||||
return PTR_ERR(res->phy_reset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_pcie_get_resources_v1(struct qcom_pcie *pcie)
|
||||
{
|
||||
struct qcom_pcie_resources_v1 *res = &pcie->res.v1;
|
||||
struct device *dev = pcie->dev;
|
||||
|
||||
res->vdda = devm_regulator_get(dev, "vdda");
|
||||
if (IS_ERR(res->vdda))
|
||||
return PTR_ERR(res->vdda);
|
||||
|
||||
res->iface = devm_clk_get(dev, "iface");
|
||||
if (IS_ERR(res->iface))
|
||||
return PTR_ERR(res->iface);
|
||||
|
||||
res->aux = devm_clk_get(dev, "aux");
|
||||
if (IS_ERR(res->aux))
|
||||
return PTR_ERR(res->aux);
|
||||
|
||||
res->master_bus = devm_clk_get(dev, "master_bus");
|
||||
if (IS_ERR(res->master_bus))
|
||||
return PTR_ERR(res->master_bus);
|
||||
|
||||
res->slave_bus = devm_clk_get(dev, "slave_bus");
|
||||
if (IS_ERR(res->slave_bus))
|
||||
return PTR_ERR(res->slave_bus);
|
||||
|
||||
res->core = devm_reset_control_get(dev, "core");
|
||||
if (IS_ERR(res->core))
|
||||
return PTR_ERR(res->core);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void qcom_pcie_deinit_v0(struct qcom_pcie *pcie)
|
||||
{
|
||||
struct qcom_pcie_resources_v0 *res = &pcie->res.v0;
|
||||
|
||||
reset_control_assert(res->pci_reset);
|
||||
reset_control_assert(res->axi_reset);
|
||||
reset_control_assert(res->ahb_reset);
|
||||
reset_control_assert(res->por_reset);
|
||||
reset_control_assert(res->pci_reset);
|
||||
clk_disable_unprepare(res->iface_clk);
|
||||
clk_disable_unprepare(res->core_clk);
|
||||
clk_disable_unprepare(res->phy_clk);
|
||||
regulator_disable(res->vdda);
|
||||
regulator_disable(res->vdda_phy);
|
||||
regulator_disable(res->vdda_refclk);
|
||||
}
|
||||
|
||||
static int qcom_pcie_init_v0(struct qcom_pcie *pcie)
|
||||
{
|
||||
struct qcom_pcie_resources_v0 *res = &pcie->res.v0;
|
||||
struct device *dev = pcie->dev;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
ret = regulator_enable(res->vdda);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot enable vdda regulator\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regulator_enable(res->vdda_refclk);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot enable vdda_refclk regulator\n");
|
||||
goto err_refclk;
|
||||
}
|
||||
|
||||
ret = regulator_enable(res->vdda_phy);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot enable vdda_phy regulator\n");
|
||||
goto err_vdda_phy;
|
||||
}
|
||||
|
||||
ret = reset_control_assert(res->ahb_reset);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot assert ahb reset\n");
|
||||
goto err_assert_ahb;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(res->iface_clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot prepare/enable iface clock\n");
|
||||
goto err_assert_ahb;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(res->phy_clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot prepare/enable phy clock\n");
|
||||
goto err_clk_phy;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(res->core_clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot prepare/enable core clock\n");
|
||||
goto err_clk_core;
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(res->ahb_reset);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot deassert ahb reset\n");
|
||||
goto err_deassert_ahb;
|
||||
}
|
||||
|
||||
/* enable PCIe clocks and resets */
|
||||
val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
|
||||
val &= ~BIT(0);
|
||||
writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL);
|
||||
|
||||
/* enable external reference clock */
|
||||
val = readl(pcie->parf + PCIE20_PARF_PHY_REFCLK);
|
||||
val |= BIT(16);
|
||||
writel(val, pcie->parf + PCIE20_PARF_PHY_REFCLK);
|
||||
|
||||
ret = reset_control_deassert(res->phy_reset);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot deassert phy reset\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(res->pci_reset);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot deassert pci reset\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(res->por_reset);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot deassert por reset\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(res->axi_reset);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot deassert axi reset\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* wait for clock acquisition */
|
||||
usleep_range(1000, 1500);
|
||||
|
||||
return 0;
|
||||
|
||||
err_deassert_ahb:
|
||||
clk_disable_unprepare(res->core_clk);
|
||||
err_clk_core:
|
||||
clk_disable_unprepare(res->phy_clk);
|
||||
err_clk_phy:
|
||||
clk_disable_unprepare(res->iface_clk);
|
||||
err_assert_ahb:
|
||||
regulator_disable(res->vdda_phy);
|
||||
err_vdda_phy:
|
||||
regulator_disable(res->vdda_refclk);
|
||||
err_refclk:
|
||||
regulator_disable(res->vdda);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void qcom_pcie_deinit_v1(struct qcom_pcie *pcie)
|
||||
{
|
||||
struct qcom_pcie_resources_v1 *res = &pcie->res.v1;
|
||||
|
||||
reset_control_assert(res->core);
|
||||
clk_disable_unprepare(res->slave_bus);
|
||||
clk_disable_unprepare(res->master_bus);
|
||||
clk_disable_unprepare(res->iface);
|
||||
clk_disable_unprepare(res->aux);
|
||||
regulator_disable(res->vdda);
|
||||
}
|
||||
|
||||
static int qcom_pcie_init_v1(struct qcom_pcie *pcie)
|
||||
{
|
||||
struct qcom_pcie_resources_v1 *res = &pcie->res.v1;
|
||||
struct device *dev = pcie->dev;
|
||||
int ret;
|
||||
|
||||
ret = reset_control_deassert(res->core);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot deassert core reset\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(res->aux);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot prepare/enable aux clock\n");
|
||||
goto err_res;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(res->iface);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot prepare/enable iface clock\n");
|
||||
goto err_aux;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(res->master_bus);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot prepare/enable master_bus clock\n");
|
||||
goto err_iface;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(res->slave_bus);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot prepare/enable slave_bus clock\n");
|
||||
goto err_master;
|
||||
}
|
||||
|
||||
ret = regulator_enable(res->vdda);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot enable vdda regulator\n");
|
||||
goto err_slave;
|
||||
}
|
||||
|
||||
/* change DBI base address */
|
||||
writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR);
|
||||
|
||||
if (IS_ENABLED(CONFIG_PCI_MSI)) {
|
||||
u32 val = readl(pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT);
|
||||
|
||||
val |= BIT(31);
|
||||
writel(val, pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT);
|
||||
}
|
||||
|
||||
return 0;
|
||||
err_slave:
|
||||
clk_disable_unprepare(res->slave_bus);
|
||||
err_master:
|
||||
clk_disable_unprepare(res->master_bus);
|
||||
err_iface:
|
||||
clk_disable_unprepare(res->iface);
|
||||
err_aux:
|
||||
clk_disable_unprepare(res->aux);
|
||||
err_res:
|
||||
reset_control_assert(res->core);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_pcie_link_up(struct pcie_port *pp)
|
||||
{
|
||||
struct qcom_pcie *pcie = to_qcom_pcie(pp);
|
||||
u16 val = readw(pcie->dbi + PCIE20_CAP + PCI_EXP_LNKSTA);
|
||||
|
||||
return !!(val & PCI_EXP_LNKSTA_DLLLA);
|
||||
}
|
||||
|
||||
static void qcom_pcie_host_init(struct pcie_port *pp)
|
||||
{
|
||||
struct qcom_pcie *pcie = to_qcom_pcie(pp);
|
||||
int ret;
|
||||
|
||||
qcom_ep_reset_assert(pcie);
|
||||
|
||||
ret = pcie->ops->init(pcie);
|
||||
if (ret)
|
||||
goto err_deinit;
|
||||
|
||||
ret = phy_power_on(pcie->phy);
|
||||
if (ret)
|
||||
goto err_deinit;
|
||||
|
||||
dw_pcie_setup_rc(pp);
|
||||
|
||||
if (IS_ENABLED(CONFIG_PCI_MSI))
|
||||
dw_pcie_msi_init(pp);
|
||||
|
||||
qcom_ep_reset_deassert(pcie);
|
||||
|
||||
ret = qcom_pcie_establish_link(pcie);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
return;
|
||||
err:
|
||||
qcom_ep_reset_assert(pcie);
|
||||
phy_power_off(pcie->phy);
|
||||
err_deinit:
|
||||
pcie->ops->deinit(pcie);
|
||||
}
|
||||
|
||||
static int qcom_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
|
||||
u32 *val)
|
||||
{
|
||||
/* the device class is not reported correctly from the register */
|
||||
if (where == PCI_CLASS_REVISION && size == 4) {
|
||||
*val = readl(pp->dbi_base + PCI_CLASS_REVISION);
|
||||
*val &= 0xff; /* keep revision id */
|
||||
*val |= PCI_CLASS_BRIDGE_PCI << 16;
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
return dw_pcie_cfg_read(pp->dbi_base + where, size, val);
|
||||
}
|
||||
|
||||
static struct pcie_host_ops qcom_pcie_dw_ops = {
|
||||
.link_up = qcom_pcie_link_up,
|
||||
.host_init = qcom_pcie_host_init,
|
||||
.rd_own_conf = qcom_pcie_rd_own_conf,
|
||||
};
|
||||
|
||||
static const struct qcom_pcie_ops ops_v0 = {
|
||||
.get_resources = qcom_pcie_get_resources_v0,
|
||||
.init = qcom_pcie_init_v0,
|
||||
.deinit = qcom_pcie_deinit_v0,
|
||||
};
|
||||
|
||||
static const struct qcom_pcie_ops ops_v1 = {
|
||||
.get_resources = qcom_pcie_get_resources_v1,
|
||||
.init = qcom_pcie_init_v1,
|
||||
.deinit = qcom_pcie_deinit_v1,
|
||||
};
|
||||
|
||||
static int qcom_pcie_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct resource *res;
|
||||
struct qcom_pcie *pcie;
|
||||
struct pcie_port *pp;
|
||||
int ret;
|
||||
|
||||
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
|
||||
if (!pcie)
|
||||
return -ENOMEM;
|
||||
|
||||
pcie->ops = (struct qcom_pcie_ops *)of_device_get_match_data(dev);
|
||||
pcie->dev = dev;
|
||||
|
||||
pcie->reset = devm_gpiod_get_optional(dev, "perst", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(pcie->reset))
|
||||
return PTR_ERR(pcie->reset);
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "parf");
|
||||
pcie->parf = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(pcie->parf))
|
||||
return PTR_ERR(pcie->parf);
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
|
||||
pcie->dbi = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(pcie->dbi))
|
||||
return PTR_ERR(pcie->dbi);
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "elbi");
|
||||
pcie->elbi = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(pcie->elbi))
|
||||
return PTR_ERR(pcie->elbi);
|
||||
|
||||
pcie->phy = devm_phy_optional_get(dev, "pciephy");
|
||||
if (IS_ERR(pcie->phy))
|
||||
return PTR_ERR(pcie->phy);
|
||||
|
||||
ret = pcie->ops->get_resources(pcie);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pp = &pcie->pp;
|
||||
pp->dev = dev;
|
||||
pp->dbi_base = pcie->dbi;
|
||||
pp->root_bus_nr = -1;
|
||||
pp->ops = &qcom_pcie_dw_ops;
|
||||
|
||||
if (IS_ENABLED(CONFIG_PCI_MSI)) {
|
||||
pp->msi_irq = platform_get_irq_byname(pdev, "msi");
|
||||
if (pp->msi_irq < 0)
|
||||
return pp->msi_irq;
|
||||
|
||||
ret = devm_request_irq(dev, pp->msi_irq,
|
||||
qcom_pcie_msi_irq_handler,
|
||||
IRQF_SHARED, "qcom-pcie-msi", pp);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot request msi irq\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = phy_init(pcie->phy);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = dw_pcie_host_init(pp);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot initialize host\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, pcie);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_pcie_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct qcom_pcie *pcie = platform_get_drvdata(pdev);
|
||||
|
||||
qcom_ep_reset_assert(pcie);
|
||||
phy_power_off(pcie->phy);
|
||||
phy_exit(pcie->phy);
|
||||
pcie->ops->deinit(pcie);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id qcom_pcie_match[] = {
|
||||
{ .compatible = "qcom,pcie-ipq8064", .data = &ops_v0 },
|
||||
{ .compatible = "qcom,pcie-apq8064", .data = &ops_v0 },
|
||||
{ .compatible = "qcom,pcie-apq8084", .data = &ops_v1 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, qcom_pcie_match);
|
||||
|
||||
static struct platform_driver qcom_pcie_driver = {
|
||||
.probe = qcom_pcie_probe,
|
||||
.remove = qcom_pcie_remove,
|
||||
.driver = {
|
||||
.name = "qcom-pcie",
|
||||
.of_match_table = qcom_pcie_match,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(qcom_pcie_driver);
|
||||
|
||||
MODULE_AUTHOR("Stanimir Varbanov <svarbanov@mm-sol.com>");
|
||||
MODULE_DESCRIPTION("Qualcomm PCIe root complex driver");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -26,6 +26,7 @@
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define DRV_NAME "rcar-pcie"
|
||||
@ -94,6 +95,11 @@
|
||||
#define H1_PCIEPHYDOUTR 0x040014
|
||||
#define H1_PCIEPHYSR 0x040018
|
||||
|
||||
/* R-Car Gen2 PHY */
|
||||
#define GEN2_PCIEPHYADDR 0x780
|
||||
#define GEN2_PCIEPHYDATA 0x784
|
||||
#define GEN2_PCIEPHYCTRL 0x78c
|
||||
|
||||
#define INT_PCI_MSI_NR 32
|
||||
|
||||
#define RCONF(x) (PCICONF(0)+(x))
|
||||
@ -108,8 +114,6 @@
|
||||
#define RCAR_PCI_MAX_RESOURCES 4
|
||||
#define MAX_NR_INBOUND_MAPS 6
|
||||
|
||||
static unsigned long global_io_offset;
|
||||
|
||||
struct rcar_msi {
|
||||
DECLARE_BITMAP(used, INT_PCI_MSI_NR);
|
||||
struct irq_domain *domain;
|
||||
@ -126,20 +130,10 @@ static inline struct rcar_msi *to_rcar_msi(struct msi_controller *chip)
|
||||
}
|
||||
|
||||
/* Structure representing the PCIe interface */
|
||||
/*
|
||||
* ARM pcibios functions expect the ARM struct pci_sys_data as the PCI
|
||||
* sysdata. Add pci_sys_data as the first element in struct gen_pci so
|
||||
* that when we use a gen_pci pointer as sysdata, it is also a pointer to
|
||||
* a struct pci_sys_data.
|
||||
*/
|
||||
struct rcar_pcie {
|
||||
#ifdef CONFIG_ARM
|
||||
struct pci_sys_data sys;
|
||||
#endif
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
struct resource res[RCAR_PCI_MAX_RESOURCES];
|
||||
struct resource busn;
|
||||
struct list_head resources;
|
||||
int root_bus_nr;
|
||||
struct clk *clk;
|
||||
struct clk *bus_clk;
|
||||
@ -323,10 +317,9 @@ static struct pci_ops rcar_pcie_ops = {
|
||||
.write = rcar_pcie_write_conf,
|
||||
};
|
||||
|
||||
static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie)
|
||||
static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie,
|
||||
struct resource *res)
|
||||
{
|
||||
struct resource *res = &pcie->res[win];
|
||||
|
||||
/* Setup PCIe address space mappings for each resource */
|
||||
resource_size_t size;
|
||||
resource_size_t res_start;
|
||||
@ -359,31 +352,33 @@ static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie)
|
||||
rcar_pci_write_reg(pcie, mask, PCIEPTCTLR(win));
|
||||
}
|
||||
|
||||
static int rcar_pcie_setup(struct list_head *resource, struct rcar_pcie *pcie)
|
||||
static int rcar_pcie_setup(struct list_head *resource, struct rcar_pcie *pci)
|
||||
{
|
||||
struct resource *res;
|
||||
int i;
|
||||
|
||||
pcie->root_bus_nr = pcie->busn.start;
|
||||
struct resource_entry *win;
|
||||
int i = 0;
|
||||
|
||||
/* Setup PCI resources */
|
||||
for (i = 0; i < RCAR_PCI_MAX_RESOURCES; i++) {
|
||||
resource_list_for_each_entry(win, &pci->resources) {
|
||||
struct resource *res = win->res;
|
||||
|
||||
res = &pcie->res[i];
|
||||
if (!res->flags)
|
||||
continue;
|
||||
|
||||
rcar_pcie_setup_window(i, pcie);
|
||||
|
||||
if (res->flags & IORESOURCE_IO) {
|
||||
phys_addr_t io_start = pci_pio_to_address(res->start);
|
||||
pci_ioremap_io(global_io_offset, io_start);
|
||||
global_io_offset += SZ_64K;
|
||||
switch (resource_type(res)) {
|
||||
case IORESOURCE_IO:
|
||||
case IORESOURCE_MEM:
|
||||
rcar_pcie_setup_window(i, pci, res);
|
||||
i++;
|
||||
break;
|
||||
case IORESOURCE_BUS:
|
||||
pci->root_bus_nr = res->start;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
pci_add_resource(resource, res);
|
||||
}
|
||||
pci_add_resource(resource, &pcie->busn);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -578,6 +573,26 @@ static int rcar_pcie_hw_init_h1(struct rcar_pcie *pcie)
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int rcar_pcie_hw_init_gen2(struct rcar_pcie *pcie)
|
||||
{
|
||||
/*
|
||||
* These settings come from the R-Car Series, 2nd Generation User's
|
||||
* Manual, section 50.3.1 (2) Initialization of the physical layer.
|
||||
*/
|
||||
rcar_pci_write_reg(pcie, 0x000f0030, GEN2_PCIEPHYADDR);
|
||||
rcar_pci_write_reg(pcie, 0x00381203, GEN2_PCIEPHYDATA);
|
||||
rcar_pci_write_reg(pcie, 0x00000001, GEN2_PCIEPHYCTRL);
|
||||
rcar_pci_write_reg(pcie, 0x00000006, GEN2_PCIEPHYCTRL);
|
||||
|
||||
rcar_pci_write_reg(pcie, 0x000f0054, GEN2_PCIEPHYADDR);
|
||||
/* The following value is for DC connection, no termination resistor */
|
||||
rcar_pci_write_reg(pcie, 0x13802007, GEN2_PCIEPHYDATA);
|
||||
rcar_pci_write_reg(pcie, 0x00000001, GEN2_PCIEPHYCTRL);
|
||||
rcar_pci_write_reg(pcie, 0x00000006, GEN2_PCIEPHYCTRL);
|
||||
|
||||
return rcar_pcie_hw_init(pcie);
|
||||
}
|
||||
|
||||
static int rcar_msi_alloc(struct rcar_msi *chip)
|
||||
{
|
||||
int msi;
|
||||
@ -720,14 +735,16 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
|
||||
|
||||
/* Two irqs are for MSI, but they are also used for non-MSI irqs */
|
||||
err = devm_request_irq(&pdev->dev, msi->irq1, rcar_pcie_msi_irq,
|
||||
IRQF_SHARED, rcar_msi_irq_chip.name, pcie);
|
||||
IRQF_SHARED | IRQF_NO_THREAD,
|
||||
rcar_msi_irq_chip.name, pcie);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to request IRQ: %d\n", err);
|
||||
goto err;
|
||||
}
|
||||
|
||||
err = devm_request_irq(&pdev->dev, msi->irq2, rcar_pcie_msi_irq,
|
||||
IRQF_SHARED, rcar_msi_irq_chip.name, pcie);
|
||||
IRQF_SHARED | IRQF_NO_THREAD,
|
||||
rcar_msi_irq_chip.name, pcie);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to request IRQ: %d\n", err);
|
||||
goto err;
|
||||
@ -917,20 +934,71 @@ static int rcar_pcie_parse_map_dma_ranges(struct rcar_pcie *pcie,
|
||||
|
||||
static const struct of_device_id rcar_pcie_of_match[] = {
|
||||
{ .compatible = "renesas,pcie-r8a7779", .data = rcar_pcie_hw_init_h1 },
|
||||
{ .compatible = "renesas,pcie-r8a7790", .data = rcar_pcie_hw_init },
|
||||
{ .compatible = "renesas,pcie-r8a7791", .data = rcar_pcie_hw_init },
|
||||
{ .compatible = "renesas,pcie-rcar-gen2", .data = rcar_pcie_hw_init_gen2 },
|
||||
{ .compatible = "renesas,pcie-r8a7790", .data = rcar_pcie_hw_init_gen2 },
|
||||
{ .compatible = "renesas,pcie-r8a7791", .data = rcar_pcie_hw_init_gen2 },
|
||||
{ .compatible = "renesas,pcie-r8a7795", .data = rcar_pcie_hw_init },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rcar_pcie_of_match);
|
||||
|
||||
static void rcar_pcie_release_of_pci_ranges(struct rcar_pcie *pci)
|
||||
{
|
||||
pci_free_resource_list(&pci->resources);
|
||||
}
|
||||
|
||||
static int rcar_pcie_parse_request_of_pci_ranges(struct rcar_pcie *pci)
|
||||
{
|
||||
int err;
|
||||
struct device *dev = pci->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
resource_size_t iobase;
|
||||
struct resource_entry *win;
|
||||
|
||||
err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pci->resources, &iobase);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
resource_list_for_each_entry(win, &pci->resources) {
|
||||
struct resource *parent, *res = win->res;
|
||||
|
||||
switch (resource_type(res)) {
|
||||
case IORESOURCE_IO:
|
||||
parent = &ioport_resource;
|
||||
err = pci_remap_iospace(res, iobase);
|
||||
if (err) {
|
||||
dev_warn(dev, "error %d: failed to map resource %pR\n",
|
||||
err, res);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case IORESOURCE_MEM:
|
||||
parent = &iomem_resource;
|
||||
break;
|
||||
|
||||
case IORESOURCE_BUS:
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
err = devm_request_resource(dev, parent, res);
|
||||
if (err)
|
||||
goto out_release_res;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_release_res:
|
||||
rcar_pcie_release_of_pci_ranges(pci);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int rcar_pcie_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rcar_pcie *pcie;
|
||||
unsigned int data;
|
||||
struct of_pci_range range;
|
||||
struct of_pci_range_parser parser;
|
||||
const struct of_device_id *of_id;
|
||||
int err, win = 0;
|
||||
int err;
|
||||
int (*hw_init_fn)(struct rcar_pcie *);
|
||||
|
||||
pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL);
|
||||
@ -940,16 +1008,9 @@ static int rcar_pcie_probe(struct platform_device *pdev)
|
||||
pcie->dev = &pdev->dev;
|
||||
platform_set_drvdata(pdev, pcie);
|
||||
|
||||
/* Get the bus range */
|
||||
if (of_pci_parse_bus_range(pdev->dev.of_node, &pcie->busn)) {
|
||||
dev_err(&pdev->dev, "failed to parse bus-range property\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
INIT_LIST_HEAD(&pcie->resources);
|
||||
|
||||
if (of_pci_range_parser_init(&parser, pdev->dev.of_node)) {
|
||||
dev_err(&pdev->dev, "missing ranges property\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
rcar_pcie_parse_request_of_pci_ranges(pcie);
|
||||
|
||||
err = rcar_pcie_get_resources(pdev, pcie);
|
||||
if (err < 0) {
|
||||
@ -957,46 +1018,55 @@ static int rcar_pcie_probe(struct platform_device *pdev)
|
||||
return err;
|
||||
}
|
||||
|
||||
for_each_of_pci_range(&parser, &range) {
|
||||
err = of_pci_range_to_resource(&range, pdev->dev.of_node,
|
||||
&pcie->res[win++]);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (win > RCAR_PCI_MAX_RESOURCES)
|
||||
break;
|
||||
}
|
||||
|
||||
err = rcar_pcie_parse_map_dma_ranges(pcie, pdev->dev.of_node);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
of_id = of_match_device(rcar_pcie_of_match, pcie->dev);
|
||||
if (!of_id || !of_id->data)
|
||||
return -EINVAL;
|
||||
hw_init_fn = of_id->data;
|
||||
|
||||
pm_runtime_enable(pcie->dev);
|
||||
err = pm_runtime_get_sync(pcie->dev);
|
||||
if (err < 0) {
|
||||
dev_err(pcie->dev, "pm_runtime_get_sync failed\n");
|
||||
goto err_pm_disable;
|
||||
}
|
||||
|
||||
/* Failure to get a link might just be that no cards are inserted */
|
||||
err = hw_init_fn(pcie);
|
||||
if (err) {
|
||||
dev_info(&pdev->dev, "PCIe link down\n");
|
||||
err = 0;
|
||||
goto err_pm_put;
|
||||
}
|
||||
|
||||
data = rcar_pci_read_reg(pcie, MACSR);
|
||||
dev_info(&pdev->dev, "PCIe x%d: link up\n", (data >> 20) & 0x3f);
|
||||
|
||||
if (IS_ENABLED(CONFIG_PCI_MSI)) {
|
||||
err = rcar_pcie_enable_msi(pcie);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"failed to enable MSI support: %d\n",
|
||||
err);
|
||||
return err;
|
||||
goto err_pm_put;
|
||||
}
|
||||
}
|
||||
|
||||
of_id = of_match_device(rcar_pcie_of_match, pcie->dev);
|
||||
if (!of_id || !of_id->data)
|
||||
return -EINVAL;
|
||||
hw_init_fn = of_id->data;
|
||||
err = rcar_pcie_enable(pcie);
|
||||
if (err)
|
||||
goto err_pm_put;
|
||||
|
||||
/* Failure to get a link might just be that no cards are inserted */
|
||||
err = hw_init_fn(pcie);
|
||||
if (err) {
|
||||
dev_info(&pdev->dev, "PCIe link down\n");
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
|
||||
data = rcar_pci_read_reg(pcie, MACSR);
|
||||
dev_info(&pdev->dev, "PCIe x%d: link up\n", (data >> 20) & 0x3f);
|
||||
err_pm_put:
|
||||
pm_runtime_put(pcie->dev);
|
||||
|
||||
return rcar_pcie_enable(pcie);
|
||||
err_pm_disable:
|
||||
pm_runtime_disable(pcie->dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct platform_driver rcar_pcie_driver = {
|
||||
|
@ -279,7 +279,8 @@ static int spear13xx_add_pcie_port(struct pcie_port *pp,
|
||||
return -ENODEV;
|
||||
}
|
||||
ret = devm_request_irq(dev, pp->irq, spear13xx_pcie_irq_handler,
|
||||
IRQF_SHARED, "spear1340-pcie", pp);
|
||||
IRQF_SHARED | IRQF_NO_THREAD,
|
||||
"spear1340-pcie", pp);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to request irq %d\n", pp->irq);
|
||||
return ret;
|
||||
|
@ -781,7 +781,8 @@ static int xilinx_pcie_parse_dt(struct xilinx_pcie_port *port)
|
||||
|
||||
port->irq = irq_of_parse_and_map(node, 0);
|
||||
err = devm_request_irq(dev, port->irq, xilinx_pcie_intr_handler,
|
||||
IRQF_SHARED, "xilinx-pcie", port);
|
||||
IRQF_SHARED | IRQF_NO_THREAD,
|
||||
"xilinx-pcie", port);
|
||||
if (err) {
|
||||
dev_err(dev, "unable to request irq %d\n", port->irq);
|
||||
return err;
|
||||
|
@ -36,10 +36,10 @@
|
||||
|
||||
#define MY_NAME "acpi_pcihp"
|
||||
|
||||
#define dbg(fmt, arg...) do { if (debug_acpi) printk(KERN_DEBUG "%s: %s: " fmt , MY_NAME , __func__ , ## arg); } while (0)
|
||||
#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
|
||||
#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)
|
||||
#define dbg(fmt, arg...) do { if (debug_acpi) printk(KERN_DEBUG "%s: %s: " fmt, MY_NAME, __func__, ## arg); } while (0)
|
||||
#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME, ## arg)
|
||||
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME, ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME, ## arg)
|
||||
|
||||
#define METHOD_NAME__SUN "_SUN"
|
||||
#define METHOD_NAME_OSHP "OSHP"
|
||||
@ -132,7 +132,7 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags)
|
||||
|
||||
while (handle) {
|
||||
acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
|
||||
dbg("Trying to get hotplug control for %s \n",
|
||||
dbg("Trying to get hotplug control for %s\n",
|
||||
(char *)string.pointer);
|
||||
status = acpi_run_oshp(handle);
|
||||
if (ACPI_SUCCESS(status))
|
||||
|
@ -181,7 +181,7 @@ struct acpiphp_attention_info
|
||||
/* function prototypes */
|
||||
|
||||
/* acpiphp_core.c */
|
||||
int acpiphp_register_attention(struct acpiphp_attention_info*info);
|
||||
int acpiphp_register_attention(struct acpiphp_attention_info *info);
|
||||
int acpiphp_unregister_attention(struct acpiphp_attention_info *info);
|
||||
int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot, unsigned int sun);
|
||||
void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot);
|
||||
|
@ -63,13 +63,13 @@ MODULE_LICENSE("GPL");
|
||||
MODULE_PARM_DESC(disable, "disable acpiphp driver");
|
||||
module_param_named(disable, acpiphp_disabled, bool, 0444);
|
||||
|
||||
static int enable_slot (struct hotplug_slot *slot);
|
||||
static int disable_slot (struct hotplug_slot *slot);
|
||||
static int set_attention_status (struct hotplug_slot *slot, u8 value);
|
||||
static int get_power_status (struct hotplug_slot *slot, u8 *value);
|
||||
static int get_attention_status (struct hotplug_slot *slot, u8 *value);
|
||||
static int get_latch_status (struct hotplug_slot *slot, u8 *value);
|
||||
static int get_adapter_status (struct hotplug_slot *slot, u8 *value);
|
||||
static int enable_slot(struct hotplug_slot *slot);
|
||||
static int disable_slot(struct hotplug_slot *slot);
|
||||
static int set_attention_status(struct hotplug_slot *slot, u8 value);
|
||||
static int get_power_status(struct hotplug_slot *slot, u8 *value);
|
||||
static int get_attention_status(struct hotplug_slot *slot, u8 *value);
|
||||
static int get_latch_status(struct hotplug_slot *slot, u8 *value);
|
||||
static int get_adapter_status(struct hotplug_slot *slot, u8 *value);
|
||||
|
||||
static struct hotplug_slot_ops acpi_hotplug_slot_ops = {
|
||||
.enable_slot = enable_slot,
|
||||
|
@ -707,7 +707,7 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus)
|
||||
unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM;
|
||||
|
||||
list_for_each_entry_safe_reverse(dev, tmp, &bus->devices, bus_list) {
|
||||
for (i=0; i<PCI_BRIDGE_RESOURCES; i++) {
|
||||
for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) {
|
||||
struct resource *res = &dev->resource[i];
|
||||
if ((res->flags & type_mask) && !res->start &&
|
||||
res->end) {
|
||||
|
@ -154,7 +154,8 @@ static union apci_descriptor *ibm_slot_from_id(int id)
|
||||
ibm_slot_done:
|
||||
if (ret) {
|
||||
ret = kmalloc(sizeof(union apci_descriptor), GFP_KERNEL);
|
||||
memcpy(ret, des, sizeof(union apci_descriptor));
|
||||
if (ret)
|
||||
memcpy(ret, des, sizeof(union apci_descriptor));
|
||||
}
|
||||
kfree(table);
|
||||
return ret;
|
||||
@ -175,8 +176,13 @@ static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status)
|
||||
acpi_status stat;
|
||||
unsigned long long rc;
|
||||
union apci_descriptor *ibm_slot;
|
||||
int id = hpslot_to_sun(slot);
|
||||
|
||||
ibm_slot = ibm_slot_from_id(hpslot_to_sun(slot));
|
||||
ibm_slot = ibm_slot_from_id(id);
|
||||
if (!ibm_slot) {
|
||||
pr_err("APLS null ACPI descriptor for slot %d\n", id);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pr_debug("%s: set slot %d (%d) attention status to %d\n", __func__,
|
||||
ibm_slot->slot.slot_num, ibm_slot->slot.slot_id,
|
||||
@ -215,8 +221,13 @@ static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status)
|
||||
static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status)
|
||||
{
|
||||
union apci_descriptor *ibm_slot;
|
||||
int id = hpslot_to_sun(slot);
|
||||
|
||||
ibm_slot = ibm_slot_from_id(hpslot_to_sun(slot));
|
||||
ibm_slot = ibm_slot_from_id(id);
|
||||
if (!ibm_slot) {
|
||||
pr_err("APLS null ACPI descriptor for slot %d\n", id);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (ibm_slot->slot.attn & 0xa0 || ibm_slot->slot.status[1] & 0x08)
|
||||
*status = 1;
|
||||
@ -325,7 +336,7 @@ static int ibm_get_table_from_acpi(char **bufp)
|
||||
}
|
||||
|
||||
size = 0;
|
||||
for (i=0; i<package->package.count; i++) {
|
||||
for (i = 0; i < package->package.count; i++) {
|
||||
memcpy(&lbuf[size],
|
||||
package->package.elements[i].buffer.pointer,
|
||||
package->package.elements[i].buffer.length);
|
||||
|
@ -52,13 +52,13 @@ struct slot {
|
||||
};
|
||||
|
||||
struct cpci_hp_controller_ops {
|
||||
int (*query_enum) (void);
|
||||
int (*enable_irq) (void);
|
||||
int (*disable_irq) (void);
|
||||
int (*check_irq) (void *dev_id);
|
||||
int (*hardware_test) (struct slot *slot, u32 value);
|
||||
u8 (*get_power) (struct slot *slot);
|
||||
int (*set_power) (struct slot *slot, int value);
|
||||
int (*query_enum)(void);
|
||||
int (*enable_irq)(void);
|
||||
int (*disable_irq)(void);
|
||||
int (*check_irq)(void *dev_id);
|
||||
int (*hardware_test)(struct slot *slot, u32 value);
|
||||
u8 (*get_power)(struct slot *slot);
|
||||
int (*set_power)(struct slot *slot, int value);
|
||||
};
|
||||
|
||||
struct cpci_hp_controller {
|
||||
|
@ -45,12 +45,12 @@
|
||||
#define dbg(format, arg...) \
|
||||
do { \
|
||||
if (cpci_debug) \
|
||||
printk (KERN_DEBUG "%s: " format "\n", \
|
||||
MY_NAME , ## arg); \
|
||||
printk(KERN_DEBUG "%s: " format "\n", \
|
||||
MY_NAME, ## arg); \
|
||||
} while (0)
|
||||
#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
|
||||
#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
|
||||
#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME, ## arg)
|
||||
#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME, ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME, ## arg)
|
||||
|
||||
/* local variables */
|
||||
static DECLARE_RWSEM(list_rwsem);
|
||||
@ -238,21 +238,21 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
|
||||
* with the pci_hotplug subsystem.
|
||||
*/
|
||||
for (i = first; i <= last; ++i) {
|
||||
slot = kzalloc(sizeof (struct slot), GFP_KERNEL);
|
||||
slot = kzalloc(sizeof(struct slot), GFP_KERNEL);
|
||||
if (!slot) {
|
||||
status = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
hotplug_slot =
|
||||
kzalloc(sizeof (struct hotplug_slot), GFP_KERNEL);
|
||||
kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
|
||||
if (!hotplug_slot) {
|
||||
status = -ENOMEM;
|
||||
goto error_slot;
|
||||
}
|
||||
slot->hotplug_slot = hotplug_slot;
|
||||
|
||||
info = kzalloc(sizeof (struct hotplug_slot_info), GFP_KERNEL);
|
||||
info = kzalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL);
|
||||
if (!info) {
|
||||
status = -ENOMEM;
|
||||
goto error_hpslot;
|
||||
|
@ -38,12 +38,12 @@ extern int cpci_debug;
|
||||
#define dbg(format, arg...) \
|
||||
do { \
|
||||
if (cpci_debug) \
|
||||
printk (KERN_DEBUG "%s: " format "\n", \
|
||||
MY_NAME , ## arg); \
|
||||
printk(KERN_DEBUG "%s: " format "\n", \
|
||||
MY_NAME, ## arg); \
|
||||
} while (0)
|
||||
#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
|
||||
#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
|
||||
#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME, ## arg)
|
||||
#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME, ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME, ## arg)
|
||||
|
||||
|
||||
u8 cpci_get_attention_status(struct slot *slot)
|
||||
|
@ -54,12 +54,12 @@
|
||||
#define dbg(format, arg...) \
|
||||
do { \
|
||||
if (debug) \
|
||||
printk (KERN_DEBUG "%s: " format "\n", \
|
||||
MY_NAME , ## arg); \
|
||||
printk(KERN_DEBUG "%s: " format "\n", \
|
||||
MY_NAME, ## arg); \
|
||||
} while (0)
|
||||
#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
|
||||
#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
|
||||
#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME, ## arg)
|
||||
#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME, ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME, ## arg)
|
||||
|
||||
/* local variables */
|
||||
static bool debug;
|
||||
@ -164,7 +164,7 @@ static int __init cpcihp_generic_init(void)
|
||||
bus = dev->subordinate;
|
||||
pci_dev_put(dev);
|
||||
|
||||
memset(&generic_hpc, 0, sizeof (struct cpci_hp_controller));
|
||||
memset(&generic_hpc, 0, sizeof(struct cpci_hp_controller));
|
||||
generic_hpc_ops.query_enum = query_enum;
|
||||
generic_hpc.ops = &generic_hpc_ops;
|
||||
|
||||
|
@ -49,12 +49,12 @@
|
||||
#define dbg(format, arg...) \
|
||||
do { \
|
||||
if (debug) \
|
||||
printk (KERN_DEBUG "%s: " format "\n", \
|
||||
MY_NAME , ## arg); \
|
||||
printk(KERN_DEBUG "%s: " format "\n", \
|
||||
MY_NAME, ## arg); \
|
||||
} while (0)
|
||||
#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
|
||||
#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
|
||||
#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME, ## arg)
|
||||
#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME, ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME, ## arg)
|
||||
|
||||
/* local variables */
|
||||
static bool debug;
|
||||
@ -204,7 +204,7 @@ static int zt5550_hc_disable_irq(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zt5550_hc_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
static int zt5550_hc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
int status;
|
||||
|
||||
@ -214,7 +214,7 @@ static int zt5550_hc_init_one (struct pci_dev *pdev, const struct pci_device_id
|
||||
|
||||
dbg("returned from zt5550_hc_config");
|
||||
|
||||
memset(&zt5550_hpc, 0, sizeof (struct cpci_hp_controller));
|
||||
memset(&zt5550_hpc, 0, sizeof(struct cpci_hp_controller));
|
||||
zt5550_hpc_ops.query_enum = zt5550_hc_query_enum;
|
||||
zt5550_hpc.ops = &zt5550_hpc_ops;
|
||||
if (!poll) {
|
||||
|
@ -36,10 +36,10 @@
|
||||
|
||||
#define MY_NAME "cpqphp"
|
||||
|
||||
#define dbg(fmt, arg...) do { if (cpqhp_debug) printk(KERN_DEBUG "%s: " fmt , MY_NAME , ## arg); } while (0)
|
||||
#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
|
||||
#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)
|
||||
#define dbg(fmt, arg...) do { if (cpqhp_debug) printk(KERN_DEBUG "%s: " fmt, MY_NAME, ## arg); } while (0)
|
||||
#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME, ## arg)
|
||||
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME, ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME, ## arg)
|
||||
|
||||
|
||||
|
||||
@ -424,7 +424,7 @@ int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func);
|
||||
int cpqhp_hardware_test(struct controller *ctrl, int test_num);
|
||||
|
||||
/* resource functions */
|
||||
int cpqhp_resource_sort_and_combine (struct pci_resource **head);
|
||||
int cpqhp_resource_sort_and_combine(struct pci_resource **head);
|
||||
|
||||
/* pci functions */
|
||||
int cpqhp_set_irq(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num);
|
||||
@ -685,7 +685,7 @@ static inline int cpq_get_latch_status(struct controller *ctrl,
|
||||
u8 hp_slot;
|
||||
|
||||
hp_slot = slot->device - ctrl->slot_device_offset;
|
||||
dbg("%s: slot->device = %d, ctrl->slot_device_offset = %d \n",
|
||||
dbg("%s: slot->device = %d, ctrl->slot_device_offset = %d\n",
|
||||
__func__, slot->device, ctrl->slot_device_offset);
|
||||
|
||||
status = (readl(ctrl->hpc_reg + INT_INPUT_CLEAR) & (0x01L << hp_slot));
|
||||
@ -712,7 +712,7 @@ static inline int get_presence_status(struct controller *ctrl,
|
||||
|
||||
static inline int wait_for_ctrl_irq(struct controller *ctrl)
|
||||
{
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
int retval = 0;
|
||||
|
||||
dbg("%s - start\n", __func__);
|
||||
|
@ -291,7 +291,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
|
||||
kfree(slot);
|
||||
}
|
||||
|
||||
static int ctrl_slot_cleanup (struct controller *ctrl)
|
||||
static int ctrl_slot_cleanup(struct controller *ctrl)
|
||||
{
|
||||
struct slot *old_slot, *next_slot;
|
||||
|
||||
@ -301,7 +301,7 @@ static int ctrl_slot_cleanup (struct controller *ctrl)
|
||||
while (old_slot) {
|
||||
/* memory will be freed by the release_slot callback */
|
||||
next_slot = old_slot->next;
|
||||
pci_hp_deregister (old_slot->hotplug_slot);
|
||||
pci_hp_deregister(old_slot->hotplug_slot);
|
||||
old_slot = next_slot;
|
||||
}
|
||||
|
||||
@ -413,9 +413,9 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func,
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
if (status == 1)
|
||||
amber_LED_on (ctrl, hp_slot);
|
||||
amber_LED_on(ctrl, hp_slot);
|
||||
else if (status == 0)
|
||||
amber_LED_off (ctrl, hp_slot);
|
||||
amber_LED_off(ctrl, hp_slot);
|
||||
else {
|
||||
/* Done with exclusive hardware access */
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
@ -425,7 +425,7 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func,
|
||||
set_SOGO(ctrl);
|
||||
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
wait_for_ctrl_irq(ctrl);
|
||||
|
||||
/* Done with exclusive hardware access */
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
@ -439,7 +439,7 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func,
|
||||
* @hotplug_slot: slot to change LED on
|
||||
* @status: LED control flag
|
||||
*/
|
||||
static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
|
||||
static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
|
||||
{
|
||||
struct pci_func *slot_func;
|
||||
struct slot *slot = hotplug_slot->private;
|
||||
@ -610,7 +610,7 @@ static int ctrl_slot_setup(struct controller *ctrl,
|
||||
u8 ctrl_slot;
|
||||
u32 tempdword;
|
||||
char name[SLOT_NAME_SIZE];
|
||||
void __iomem *slot_entry= NULL;
|
||||
void __iomem *slot_entry = NULL;
|
||||
int result;
|
||||
|
||||
dbg("%s\n", __func__);
|
||||
@ -755,7 +755,7 @@ static int one_time_init(void)
|
||||
if (cpqhp_debug)
|
||||
pci_print_IRQ_route();
|
||||
|
||||
dbg("Initialize + Start the notification mechanism \n");
|
||||
dbg("Initialize + Start the notification mechanism\n");
|
||||
|
||||
retval = cpqhp_event_start_thread();
|
||||
if (retval)
|
||||
@ -772,7 +772,7 @@ static int one_time_init(void)
|
||||
/* Map rom address */
|
||||
cpqhp_rom_start = ioremap(ROM_PHY_ADDR, ROM_PHY_LEN);
|
||||
if (!cpqhp_rom_start) {
|
||||
err ("Could not ioremap memory region for ROM\n");
|
||||
err("Could not ioremap memory region for ROM\n");
|
||||
retval = -EIO;
|
||||
goto error;
|
||||
}
|
||||
@ -786,7 +786,7 @@ static int one_time_init(void)
|
||||
smbios_table = detect_SMBIOS_pointer(cpqhp_rom_start,
|
||||
cpqhp_rom_start + ROM_PHY_LEN);
|
||||
if (!smbios_table) {
|
||||
err ("Could not find the SMBIOS pointer in memory\n");
|
||||
err("Could not find the SMBIOS pointer in memory\n");
|
||||
retval = -EIO;
|
||||
goto error_rom_start;
|
||||
}
|
||||
@ -794,7 +794,7 @@ static int one_time_init(void)
|
||||
smbios_start = ioremap(readl(smbios_table + ST_ADDRESS),
|
||||
readw(smbios_table + ST_LENGTH));
|
||||
if (!smbios_start) {
|
||||
err ("Could not ioremap memory region taken from SMBIOS values\n");
|
||||
err("Could not ioremap memory region taken from SMBIOS values\n");
|
||||
retval = -EIO;
|
||||
goto error_smbios_start;
|
||||
}
|
||||
@ -1181,7 +1181,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
* Finish setting up the hot plug ctrl device
|
||||
*/
|
||||
ctrl->slot_device_offset = readb(ctrl->hpc_reg + SLOT_MASK) >> 4;
|
||||
dbg("NumSlots %d \n", ctrl->slot_device_offset);
|
||||
dbg("NumSlots %d\n", ctrl->slot_device_offset);
|
||||
|
||||
ctrl->next_event = 0;
|
||||
|
||||
@ -1198,7 +1198,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
writel(0xFFFFFFFFL, ctrl->hpc_reg + INT_MASK);
|
||||
|
||||
/* set up the interrupt */
|
||||
dbg("HPC interrupt = %d \n", ctrl->interrupt);
|
||||
dbg("HPC interrupt = %d\n", ctrl->interrupt);
|
||||
if (request_irq(ctrl->interrupt, cpqhp_ctrl_intr,
|
||||
IRQF_SHARED, MY_NAME, ctrl)) {
|
||||
err("Can't get irq %d for the hotplug pci controller\n",
|
||||
@ -1321,7 +1321,7 @@ static void __exit unload_cpqphpd(void)
|
||||
while (ctrl) {
|
||||
if (ctrl->hpc_reg) {
|
||||
u16 misc;
|
||||
rc = read_slot_enable (ctrl);
|
||||
rc = read_slot_enable(ctrl);
|
||||
|
||||
writeb(0, ctrl->hpc_reg + SLOT_SERR);
|
||||
writel(0xFFFFFFC0L | ~rc, ctrl->hpc_reg + INT_MASK);
|
||||
@ -1361,7 +1361,7 @@ static void __exit unload_cpqphpd(void)
|
||||
kfree(tres);
|
||||
}
|
||||
|
||||
kfree (ctrl->pci_bus);
|
||||
kfree(ctrl->pci_bus);
|
||||
|
||||
tctrl = ctrl;
|
||||
ctrl = ctrl->next;
|
||||
@ -1446,7 +1446,7 @@ static int __init cpqhpc_init(void)
|
||||
|
||||
cpqhp_debug = debug;
|
||||
|
||||
info (DRIVER_DESC " version: " DRIVER_VERSION "\n");
|
||||
info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
|
||||
cpqhp_initialize_debugfs();
|
||||
result = pci_register_driver(&cpqhpc_driver);
|
||||
dbg("pci_register_driver = %d\n", result);
|
||||
|
@ -155,7 +155,7 @@ static u8 handle_presence_change(u16 change, struct controller *ctrl)
|
||||
* Presence Change
|
||||
*/
|
||||
dbg("cpqsbd: Presence/Notify input change.\n");
|
||||
dbg(" Changed bits are 0x%4.4x\n", change );
|
||||
dbg(" Changed bits are 0x%4.4x\n", change);
|
||||
|
||||
for (hp_slot = 0; hp_slot < 6; hp_slot++) {
|
||||
if (change & (0x0101 << hp_slot)) {
|
||||
@ -276,9 +276,9 @@ static u8 handle_power_fault(u8 change, struct controller *ctrl)
|
||||
taskInfo->event_type = INT_POWER_FAULT;
|
||||
|
||||
if (ctrl->rev < 4) {
|
||||
amber_LED_on (ctrl, hp_slot);
|
||||
green_LED_off (ctrl, hp_slot);
|
||||
set_SOGO (ctrl);
|
||||
amber_LED_on(ctrl, hp_slot);
|
||||
green_LED_off(ctrl, hp_slot);
|
||||
set_SOGO(ctrl);
|
||||
|
||||
/* this is a fatal condition, we want
|
||||
* to crash the machine to protect from
|
||||
@ -438,7 +438,7 @@ static struct pci_resource *do_pre_bridge_resource_split(struct pci_resource **h
|
||||
|
||||
node = *head;
|
||||
|
||||
if (node->length & (alignment -1)) {
|
||||
if (node->length & (alignment - 1)) {
|
||||
/* this one isn't an aligned length, so we'll make a new entry
|
||||
* and split it up.
|
||||
*/
|
||||
@ -835,13 +835,13 @@ int cpqhp_resource_sort_and_combine(struct pci_resource **head)
|
||||
if (!(*head))
|
||||
return 1;
|
||||
|
||||
dbg("*head->next = %p\n",(*head)->next);
|
||||
dbg("*head->next = %p\n", (*head)->next);
|
||||
|
||||
if (!(*head)->next)
|
||||
return 0; /* only one item on the list, already sorted! */
|
||||
|
||||
dbg("*head->base = 0x%x\n",(*head)->base);
|
||||
dbg("*head->next->base = 0x%x\n",(*head)->next->base);
|
||||
dbg("*head->base = 0x%x\n", (*head)->base);
|
||||
dbg("*head->next->base = 0x%x\n", (*head)->next->base);
|
||||
while (out_of_order) {
|
||||
out_of_order = 0;
|
||||
|
||||
@ -917,7 +917,7 @@ irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data)
|
||||
/* Read to clear posted writes */
|
||||
misc = readw(ctrl->hpc_reg + MISC);
|
||||
|
||||
dbg ("%s - waking up\n", __func__);
|
||||
dbg("%s - waking up\n", __func__);
|
||||
wake_up_interruptible(&ctrl->queue);
|
||||
}
|
||||
|
||||
@ -1285,18 +1285,18 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
|
||||
/*
|
||||
* The board is already on
|
||||
*/
|
||||
else if (is_slot_enabled (ctrl, hp_slot))
|
||||
else if (is_slot_enabled(ctrl, hp_slot))
|
||||
rc = CARD_FUNCTIONING;
|
||||
else {
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
/* turn on board without attaching to the bus */
|
||||
enable_slot_power (ctrl, hp_slot);
|
||||
enable_slot_power(ctrl, hp_slot);
|
||||
|
||||
set_SOGO(ctrl);
|
||||
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
wait_for_ctrl_irq(ctrl);
|
||||
|
||||
/* Change bits in slot power register to force another shift out
|
||||
* NOTE: this is to work around the timer bug */
|
||||
@ -1307,7 +1307,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
|
||||
set_SOGO(ctrl);
|
||||
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
wait_for_ctrl_irq(ctrl);
|
||||
|
||||
adapter_speed = get_adapter_speed(ctrl, hp_slot);
|
||||
if (bus->cur_bus_speed != adapter_speed)
|
||||
@ -1315,12 +1315,12 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
|
||||
rc = WRONG_BUS_FREQUENCY;
|
||||
|
||||
/* turn off board without attaching to the bus */
|
||||
disable_slot_power (ctrl, hp_slot);
|
||||
disable_slot_power(ctrl, hp_slot);
|
||||
|
||||
set_SOGO(ctrl);
|
||||
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
wait_for_ctrl_irq(ctrl);
|
||||
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
|
||||
@ -1329,15 +1329,15 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
|
||||
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
slot_enable (ctrl, hp_slot);
|
||||
green_LED_blink (ctrl, hp_slot);
|
||||
slot_enable(ctrl, hp_slot);
|
||||
green_LED_blink(ctrl, hp_slot);
|
||||
|
||||
amber_LED_off (ctrl, hp_slot);
|
||||
amber_LED_off(ctrl, hp_slot);
|
||||
|
||||
set_SOGO(ctrl);
|
||||
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
wait_for_ctrl_irq(ctrl);
|
||||
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
|
||||
@ -1366,14 +1366,14 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
|
||||
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
amber_LED_on (ctrl, hp_slot);
|
||||
green_LED_off (ctrl, hp_slot);
|
||||
slot_disable (ctrl, hp_slot);
|
||||
amber_LED_on(ctrl, hp_slot);
|
||||
green_LED_off(ctrl, hp_slot);
|
||||
slot_disable(ctrl, hp_slot);
|
||||
|
||||
set_SOGO(ctrl);
|
||||
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
wait_for_ctrl_irq(ctrl);
|
||||
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
|
||||
@ -1392,14 +1392,14 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
|
||||
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
amber_LED_on (ctrl, hp_slot);
|
||||
green_LED_off (ctrl, hp_slot);
|
||||
slot_disable (ctrl, hp_slot);
|
||||
amber_LED_on(ctrl, hp_slot);
|
||||
green_LED_off(ctrl, hp_slot);
|
||||
slot_disable(ctrl, hp_slot);
|
||||
|
||||
set_SOGO(ctrl);
|
||||
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
wait_for_ctrl_irq(ctrl);
|
||||
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
}
|
||||
@ -1443,7 +1443,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
|
||||
set_SOGO(ctrl);
|
||||
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
wait_for_ctrl_irq(ctrl);
|
||||
|
||||
/* Change bits in slot power register to force another shift out
|
||||
* NOTE: this is to work around the timer bug
|
||||
@ -1455,7 +1455,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
|
||||
set_SOGO(ctrl);
|
||||
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
wait_for_ctrl_irq(ctrl);
|
||||
|
||||
adapter_speed = get_adapter_speed(ctrl, hp_slot);
|
||||
if (bus->cur_bus_speed != adapter_speed)
|
||||
@ -1463,7 +1463,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
|
||||
rc = WRONG_BUS_FREQUENCY;
|
||||
|
||||
/* turn off board without attaching to the bus */
|
||||
disable_slot_power (ctrl, hp_slot);
|
||||
disable_slot_power(ctrl, hp_slot);
|
||||
|
||||
set_SOGO(ctrl);
|
||||
|
||||
@ -1484,20 +1484,20 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
|
||||
dbg("%s: after down\n", __func__);
|
||||
|
||||
dbg("%s: before slot_enable\n", __func__);
|
||||
slot_enable (ctrl, hp_slot);
|
||||
slot_enable(ctrl, hp_slot);
|
||||
|
||||
dbg("%s: before green_LED_blink\n", __func__);
|
||||
green_LED_blink (ctrl, hp_slot);
|
||||
green_LED_blink(ctrl, hp_slot);
|
||||
|
||||
dbg("%s: before amber_LED_blink\n", __func__);
|
||||
amber_LED_off (ctrl, hp_slot);
|
||||
amber_LED_off(ctrl, hp_slot);
|
||||
|
||||
dbg("%s: before set_SOGO\n", __func__);
|
||||
set_SOGO(ctrl);
|
||||
|
||||
/* Wait for SOBS to be unset */
|
||||
dbg("%s: before wait_for_ctrl_irq\n", __func__);
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
wait_for_ctrl_irq(ctrl);
|
||||
dbg("%s: after wait_for_ctrl_irq\n", __func__);
|
||||
|
||||
dbg("%s: before up\n", __func__);
|
||||
@ -1520,7 +1520,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
|
||||
} else {
|
||||
/* Get vendor/device ID u32 */
|
||||
ctrl->pci_bus->number = func->bus;
|
||||
rc = pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(func->device, func->function), PCI_VENDOR_ID, &temp_register);
|
||||
rc = pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(func->device, func->function), PCI_VENDOR_ID, &temp_register);
|
||||
dbg("%s: pci_read_config_dword returns %d\n", __func__, rc);
|
||||
dbg("%s: temp_register is %x\n", __func__, temp_register);
|
||||
|
||||
@ -1557,14 +1557,14 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
|
||||
if (rc) {
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
amber_LED_on (ctrl, hp_slot);
|
||||
green_LED_off (ctrl, hp_slot);
|
||||
slot_disable (ctrl, hp_slot);
|
||||
amber_LED_on(ctrl, hp_slot);
|
||||
green_LED_off(ctrl, hp_slot);
|
||||
slot_disable(ctrl, hp_slot);
|
||||
|
||||
set_SOGO(ctrl);
|
||||
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
wait_for_ctrl_irq(ctrl);
|
||||
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
return rc;
|
||||
@ -1589,25 +1589,25 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
|
||||
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
green_LED_on (ctrl, hp_slot);
|
||||
green_LED_on(ctrl, hp_slot);
|
||||
|
||||
set_SOGO(ctrl);
|
||||
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
wait_for_ctrl_irq(ctrl);
|
||||
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
} else {
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
amber_LED_on (ctrl, hp_slot);
|
||||
green_LED_off (ctrl, hp_slot);
|
||||
slot_disable (ctrl, hp_slot);
|
||||
amber_LED_on(ctrl, hp_slot);
|
||||
green_LED_off(ctrl, hp_slot);
|
||||
slot_disable(ctrl, hp_slot);
|
||||
|
||||
set_SOGO(ctrl);
|
||||
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
wait_for_ctrl_irq(ctrl);
|
||||
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
|
||||
@ -1672,8 +1672,8 @@ static u32 remove_board(struct pci_func *func, u32 replace_flag, struct controll
|
||||
|
||||
mutex_lock(&ctrl->crit_sect);
|
||||
|
||||
green_LED_off (ctrl, hp_slot);
|
||||
slot_disable (ctrl, hp_slot);
|
||||
green_LED_off(ctrl, hp_slot);
|
||||
slot_disable(ctrl, hp_slot);
|
||||
|
||||
set_SOGO(ctrl);
|
||||
|
||||
@ -1683,7 +1683,7 @@ static u32 remove_board(struct pci_func *func, u32 replace_flag, struct controll
|
||||
writeb(temp_byte, ctrl->hpc_reg + SLOT_SERR);
|
||||
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
wait_for_ctrl_irq(ctrl);
|
||||
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
|
||||
@ -1755,7 +1755,7 @@ static int event_thread(void *data)
|
||||
if (pushbutton_pending)
|
||||
cpqhp_pushbutton_thread(pushbutton_pending);
|
||||
else
|
||||
for (ctrl = cpqhp_ctrl_list; ctrl; ctrl=ctrl->next)
|
||||
for (ctrl = cpqhp_ctrl_list; ctrl; ctrl = ctrl->next)
|
||||
interrupt_event_handler(ctrl);
|
||||
}
|
||||
dbg("event_thread signals exit\n");
|
||||
@ -1766,7 +1766,7 @@ int cpqhp_event_start_thread(void)
|
||||
{
|
||||
cpqhp_event_thread = kthread_run(event_thread, NULL, "phpd_event");
|
||||
if (IS_ERR(cpqhp_event_thread)) {
|
||||
err ("Can't start up our event thread\n");
|
||||
err("Can't start up our event thread\n");
|
||||
return PTR_ERR(cpqhp_event_thread);
|
||||
}
|
||||
|
||||
@ -1794,7 +1794,7 @@ static int update_slot_info(struct controller *ctrl, struct slot *slot)
|
||||
info->latch_status = cpq_get_latch_status(ctrl, slot);
|
||||
info->adapter_status = get_presence_status(ctrl, slot);
|
||||
result = pci_hp_change_slot_info(slot->hotplug_slot, info);
|
||||
kfree (info);
|
||||
kfree(info);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1837,23 +1837,23 @@ static void interrupt_event_handler(struct controller *ctrl)
|
||||
if (p_slot->state == BLINKINGOFF_STATE) {
|
||||
/* slot is on */
|
||||
dbg("turn on green LED\n");
|
||||
green_LED_on (ctrl, hp_slot);
|
||||
green_LED_on(ctrl, hp_slot);
|
||||
} else if (p_slot->state == BLINKINGON_STATE) {
|
||||
/* slot is off */
|
||||
dbg("turn off green LED\n");
|
||||
green_LED_off (ctrl, hp_slot);
|
||||
green_LED_off(ctrl, hp_slot);
|
||||
}
|
||||
|
||||
info(msg_button_cancel, p_slot->number);
|
||||
|
||||
p_slot->state = STATIC_STATE;
|
||||
|
||||
amber_LED_off (ctrl, hp_slot);
|
||||
amber_LED_off(ctrl, hp_slot);
|
||||
|
||||
set_SOGO(ctrl);
|
||||
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
wait_for_ctrl_irq(ctrl);
|
||||
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
}
|
||||
@ -1861,7 +1861,7 @@ static void interrupt_event_handler(struct controller *ctrl)
|
||||
else if (ctrl->event_queue[loop].event_type == INT_BUTTON_RELEASE) {
|
||||
dbg("button release\n");
|
||||
|
||||
if (is_slot_enabled (ctrl, hp_slot)) {
|
||||
if (is_slot_enabled(ctrl, hp_slot)) {
|
||||
dbg("slot is on\n");
|
||||
p_slot->state = BLINKINGOFF_STATE;
|
||||
info(msg_button_off, p_slot->number);
|
||||
@ -1874,13 +1874,13 @@ static void interrupt_event_handler(struct controller *ctrl)
|
||||
|
||||
dbg("blink green LED and turn off amber\n");
|
||||
|
||||
amber_LED_off (ctrl, hp_slot);
|
||||
green_LED_blink (ctrl, hp_slot);
|
||||
amber_LED_off(ctrl, hp_slot);
|
||||
green_LED_blink(ctrl, hp_slot);
|
||||
|
||||
set_SOGO(ctrl);
|
||||
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
wait_for_ctrl_irq(ctrl);
|
||||
|
||||
mutex_unlock(&ctrl->crit_sect);
|
||||
init_timer(&p_slot->task_event);
|
||||
@ -1940,7 +1940,7 @@ void cpqhp_pushbutton_thread(unsigned long slot)
|
||||
dbg("In power_down_board, func = %p, ctrl = %p\n", func, ctrl);
|
||||
if (!func) {
|
||||
dbg("Error! func NULL in %s\n", __func__);
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
|
||||
if (cpqhp_process_SS(ctrl, func) != 0) {
|
||||
@ -1962,7 +1962,7 @@ void cpqhp_pushbutton_thread(unsigned long slot)
|
||||
dbg("In add_board, func = %p, ctrl = %p\n", func, ctrl);
|
||||
if (!func) {
|
||||
dbg("Error! func NULL in %s\n", __func__);
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctrl != NULL) {
|
||||
@ -1973,7 +1973,7 @@ void cpqhp_pushbutton_thread(unsigned long slot)
|
||||
set_SOGO(ctrl);
|
||||
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
wait_for_ctrl_irq(ctrl);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2086,7 +2086,7 @@ int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func)
|
||||
unsigned int devfn;
|
||||
struct slot *p_slot;
|
||||
struct pci_bus *pci_bus = ctrl->pci_bus;
|
||||
int physical_slot=0;
|
||||
int physical_slot = 0;
|
||||
|
||||
device = func->device;
|
||||
func = cpqhp_slot_find(ctrl->bus, device, index++);
|
||||
@ -2100,7 +2100,7 @@ int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func)
|
||||
devfn = PCI_DEVFN(func->device, func->function);
|
||||
|
||||
/* Check the Class Code */
|
||||
rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
|
||||
rc = pci_bus_read_config_byte(pci_bus, devfn, 0x0B, &class_code);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@ -2109,13 +2109,13 @@ int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func)
|
||||
rc = REMOVE_NOT_SUPPORTED;
|
||||
} else {
|
||||
/* See if it's a bridge */
|
||||
rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
|
||||
rc = pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* If it's a bridge, check the VGA Enable bit */
|
||||
if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
|
||||
rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR);
|
||||
rc = pci_bus_read_config_byte(pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@ -2217,7 +2217,7 @@ int cpqhp_hardware_test(struct controller *ctrl, int test_num)
|
||||
set_SOGO(ctrl);
|
||||
|
||||
/* Wait for SOGO interrupt */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
wait_for_ctrl_irq(ctrl);
|
||||
|
||||
/* Get ready for next iteration */
|
||||
long_delay((3*HZ)/10);
|
||||
@ -2227,7 +2227,7 @@ int cpqhp_hardware_test(struct controller *ctrl, int test_num)
|
||||
set_SOGO(ctrl);
|
||||
|
||||
/* Wait for SOGO interrupt */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
wait_for_ctrl_irq(ctrl);
|
||||
|
||||
/* Get ready for next iteration */
|
||||
long_delay((3*HZ)/10);
|
||||
@ -2243,7 +2243,7 @@ int cpqhp_hardware_test(struct controller *ctrl, int test_num)
|
||||
set_SOGO(ctrl);
|
||||
|
||||
/* Wait for SOBS to be unset */
|
||||
wait_for_ctrl_irq (ctrl);
|
||||
wait_for_ctrl_irq(ctrl);
|
||||
break;
|
||||
case 2:
|
||||
/* Do other stuff here! */
|
||||
@ -2279,7 +2279,7 @@ static u32 configure_new_device(struct controller *ctrl, struct pci_func *func
|
||||
dbg("%s\n", __func__);
|
||||
/* Check for Multi-function device */
|
||||
ctrl->pci_bus->number = func->bus;
|
||||
rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(func->device, func->function), 0x0E, &temp_byte);
|
||||
rc = pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(func->device, func->function), 0x0E, &temp_byte);
|
||||
if (rc) {
|
||||
dbg("%s: rc = %d\n", __func__, rc);
|
||||
return rc;
|
||||
@ -2296,7 +2296,7 @@ static u32 configure_new_device(struct controller *ctrl, struct pci_func *func
|
||||
rc = configure_new_function(ctrl, new_slot, behind_bridge, resources);
|
||||
|
||||
if (rc) {
|
||||
dbg("configure_new_function failed %d\n",rc);
|
||||
dbg("configure_new_function failed %d\n", rc);
|
||||
index = 0;
|
||||
|
||||
while (new_slot) {
|
||||
@ -2317,7 +2317,7 @@ static u32 configure_new_device(struct controller *ctrl, struct pci_func *func
|
||||
* and creates a board structure */
|
||||
|
||||
while ((function < max_functions) && (!stop_it)) {
|
||||
pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(func->device, function), 0x00, &ID);
|
||||
pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(func->device, function), 0x00, &ID);
|
||||
|
||||
if (ID == 0xFFFFFFFF) {
|
||||
function++;
|
||||
@ -2543,10 +2543,10 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
|
||||
|
||||
/* set Pre Mem base and Limit registers */
|
||||
temp_word = p_mem_node->base >> 16;
|
||||
rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
|
||||
rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
|
||||
|
||||
temp_word = (p_mem_node->base + p_mem_node->length - 1) >> 16;
|
||||
rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
|
||||
rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
|
||||
|
||||
/* Adjust this to compensate for extra adjustment in first loop
|
||||
*/
|
||||
@ -2560,7 +2560,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
|
||||
|
||||
ID = 0xFFFFFFFF;
|
||||
pci_bus->number = hold_bus_node->base;
|
||||
pci_bus_read_config_dword (pci_bus, PCI_DEVFN(device, 0), 0x00, &ID);
|
||||
pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0), 0x00, &ID);
|
||||
pci_bus->number = func->bus;
|
||||
|
||||
if (ID != 0xFFFFFFFF) { /* device present */
|
||||
@ -2579,7 +2579,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
|
||||
new_slot->status = 0;
|
||||
|
||||
rc = configure_new_device(ctrl, new_slot, 1, &temp_resources);
|
||||
dbg("configure_new_device rc=0x%x\n",rc);
|
||||
dbg("configure_new_device rc=0x%x\n", rc);
|
||||
} /* End of IF (device in slot?) */
|
||||
} /* End of FOR loop */
|
||||
|
||||
@ -2615,7 +2615,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
|
||||
temp_byte = temp_resources.bus_head->base - 1;
|
||||
|
||||
/* set subordinate bus */
|
||||
rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte);
|
||||
rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte);
|
||||
|
||||
if (temp_resources.bus_head->length == 0) {
|
||||
kfree(temp_resources.bus_head);
|
||||
@ -2636,7 +2636,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
|
||||
hold_IO_node->base = io_node->base + io_node->length;
|
||||
|
||||
temp_byte = (hold_IO_node->base) >> 8;
|
||||
rc = pci_bus_write_config_word (pci_bus, devfn, PCI_IO_BASE, temp_byte);
|
||||
rc = pci_bus_write_config_word(pci_bus, devfn, PCI_IO_BASE, temp_byte);
|
||||
|
||||
return_resource(&(resources->io_head), io_node);
|
||||
}
|
||||
@ -2655,13 +2655,13 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
|
||||
func->io_head = hold_IO_node;
|
||||
|
||||
temp_byte = (io_node->base - 1) >> 8;
|
||||
rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
|
||||
rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
|
||||
|
||||
return_resource(&(resources->io_head), io_node);
|
||||
} else {
|
||||
/* it doesn't need any IO */
|
||||
temp_word = 0x0000;
|
||||
rc = pci_bus_write_config_word (pci_bus, devfn, PCI_IO_LIMIT, temp_word);
|
||||
rc = pci_bus_write_config_word(pci_bus, devfn, PCI_IO_LIMIT, temp_word);
|
||||
|
||||
return_resource(&(resources->io_head), io_node);
|
||||
kfree(hold_IO_node);
|
||||
@ -2687,7 +2687,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
|
||||
hold_mem_node->base = mem_node->base + mem_node->length;
|
||||
|
||||
temp_word = (hold_mem_node->base) >> 16;
|
||||
rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
|
||||
rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
|
||||
|
||||
return_resource(&(resources->mem_head), mem_node);
|
||||
}
|
||||
@ -2706,14 +2706,14 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
|
||||
|
||||
/* configure end address */
|
||||
temp_word = (mem_node->base - 1) >> 16;
|
||||
rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
|
||||
rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
|
||||
|
||||
/* Return unused resources to the pool */
|
||||
return_resource(&(resources->mem_head), mem_node);
|
||||
} else {
|
||||
/* it doesn't need any Mem */
|
||||
temp_word = 0x0000;
|
||||
rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
|
||||
rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
|
||||
|
||||
return_resource(&(resources->mem_head), mem_node);
|
||||
kfree(hold_mem_node);
|
||||
@ -2739,7 +2739,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
|
||||
hold_p_mem_node->base = p_mem_node->base + p_mem_node->length;
|
||||
|
||||
temp_word = (hold_p_mem_node->base) >> 16;
|
||||
rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
|
||||
rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
|
||||
|
||||
return_resource(&(resources->p_mem_head), p_mem_node);
|
||||
}
|
||||
@ -2758,13 +2758,13 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
|
||||
func->p_mem_head = hold_p_mem_node;
|
||||
|
||||
temp_word = (p_mem_node->base - 1) >> 16;
|
||||
rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
|
||||
rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
|
||||
|
||||
return_resource(&(resources->p_mem_head), p_mem_node);
|
||||
} else {
|
||||
/* it doesn't need any PMem */
|
||||
temp_word = 0x0000;
|
||||
rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
|
||||
rc = pci_bus_write_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
|
||||
|
||||
return_resource(&(resources->p_mem_head), p_mem_node);
|
||||
kfree(hold_p_mem_node);
|
||||
@ -2790,16 +2790,16 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
|
||||
* PCI_COMMAND_INVALIDATE |
|
||||
* PCI_COMMAND_PARITY |
|
||||
* PCI_COMMAND_SERR */
|
||||
rc = pci_bus_write_config_word (pci_bus, devfn, PCI_COMMAND, command);
|
||||
rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
|
||||
|
||||
/* set Bridge Control Register */
|
||||
command = 0x07; /* = PCI_BRIDGE_CTL_PARITY |
|
||||
* PCI_BRIDGE_CTL_SERR |
|
||||
* PCI_BRIDGE_CTL_NO_ISA */
|
||||
rc = pci_bus_write_config_word (pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
|
||||
rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
|
||||
} else if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
|
||||
/* Standard device */
|
||||
rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
|
||||
rc = pci_bus_read_config_byte(pci_bus, devfn, 0x0B, &class_code);
|
||||
|
||||
if (class_code == PCI_BASE_CLASS_DISPLAY) {
|
||||
/* Display (video) adapter (not supported) */
|
||||
@ -2810,9 +2810,9 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
|
||||
temp_register = 0xFFFFFFFF;
|
||||
|
||||
dbg("CND: bus=%d, devfn=%d, offset=%d\n", pci_bus->number, devfn, cloop);
|
||||
rc = pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
|
||||
rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register);
|
||||
|
||||
rc = pci_bus_read_config_dword (pci_bus, devfn, cloop, &temp_register);
|
||||
rc = pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register);
|
||||
dbg("CND: base = 0x%x\n", temp_register);
|
||||
|
||||
if (temp_register) { /* If this register is implemented */
|
||||
@ -2891,7 +2891,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
|
||||
} /* End of base register loop */
|
||||
if (cpqhp_legacy_mode) {
|
||||
/* Figure out which interrupt pin this function uses */
|
||||
rc = pci_bus_read_config_byte (pci_bus, devfn,
|
||||
rc = pci_bus_read_config_byte(pci_bus, devfn,
|
||||
PCI_INTERRUPT_PIN, &temp_byte);
|
||||
|
||||
/* If this function needs an interrupt and we are behind
|
||||
@ -2905,7 +2905,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
|
||||
resources->irqs->barber_pole - 1) & 0x03];
|
||||
} else {
|
||||
/* Program IRQ based on card type */
|
||||
rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
|
||||
rc = pci_bus_read_config_byte(pci_bus, devfn, 0x0B, &class_code);
|
||||
|
||||
if (class_code == PCI_BASE_CLASS_STORAGE)
|
||||
IRQ = cpqhp_disk_irq;
|
||||
@ -2914,7 +2914,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
|
||||
}
|
||||
|
||||
/* IRQ Line */
|
||||
rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_INTERRUPT_LINE, IRQ);
|
||||
rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_INTERRUPT_LINE, IRQ);
|
||||
}
|
||||
|
||||
if (!behind_bridge) {
|
||||
@ -2950,7 +2950,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
|
||||
* PCI_COMMAND_INVALIDATE |
|
||||
* PCI_COMMAND_PARITY |
|
||||
* PCI_COMMAND_SERR */
|
||||
rc = pci_bus_write_config_word (pci_bus, devfn,
|
||||
rc = pci_bus_write_config_word(pci_bus, devfn,
|
||||
PCI_COMMAND, temp_word);
|
||||
} else { /* End of Not-A-Bridge else */
|
||||
/* It's some strange type of PCI adapter (Cardbus?) */
|
||||
@ -2961,11 +2961,11 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
|
||||
|
||||
return 0;
|
||||
free_and_out:
|
||||
cpqhp_destroy_resource_list (&temp_resources);
|
||||
cpqhp_destroy_resource_list(&temp_resources);
|
||||
|
||||
return_resource(&(resources-> bus_head), hold_bus_node);
|
||||
return_resource(&(resources-> io_head), hold_IO_node);
|
||||
return_resource(&(resources-> mem_head), hold_mem_node);
|
||||
return_resource(&(resources-> p_mem_head), hold_p_mem_node);
|
||||
return_resource(&(resources->bus_head), hold_bus_node);
|
||||
return_resource(&(resources->io_head), hold_IO_node);
|
||||
return_resource(&(resources->mem_head), hold_mem_node);
|
||||
return_resource(&(resources->p_mem_head), hold_p_mem_node);
|
||||
return rc;
|
||||
}
|
||||
|
@ -114,10 +114,10 @@ static u32 add_byte(u32 **p_buffer, u8 value, u32 *used, u32 *avail)
|
||||
if ((*used + 1) > *avail)
|
||||
return(1);
|
||||
|
||||
*((u8*)*p_buffer) = value;
|
||||
tByte = (u8**)p_buffer;
|
||||
*((u8 *)*p_buffer) = value;
|
||||
tByte = (u8 **)p_buffer;
|
||||
(*tByte)++;
|
||||
*used+=1;
|
||||
*used += 1;
|
||||
return(0);
|
||||
}
|
||||
|
||||
@ -129,7 +129,7 @@ static u32 add_dword(u32 **p_buffer, u32 value, u32 *used, u32 *avail)
|
||||
|
||||
**p_buffer = value;
|
||||
(*p_buffer)++;
|
||||
*used+=4;
|
||||
*used += 4;
|
||||
return(0);
|
||||
}
|
||||
|
||||
@ -141,7 +141,7 @@ static u32 add_dword(u32 **p_buffer, u32 value, u32 *used, u32 *avail)
|
||||
*
|
||||
* returns 0 for non-Compaq ROM, 1 for Compaq ROM
|
||||
*/
|
||||
static int check_for_compaq_ROM (void __iomem *rom_start)
|
||||
static int check_for_compaq_ROM(void __iomem *rom_start)
|
||||
{
|
||||
u8 temp1, temp2, temp3, temp4, temp5, temp6;
|
||||
int result = 0;
|
||||
@ -160,12 +160,12 @@ static int check_for_compaq_ROM (void __iomem *rom_start)
|
||||
(temp6 == 'Q')) {
|
||||
result = 1;
|
||||
}
|
||||
dbg ("%s - returned %d\n", __func__, result);
|
||||
dbg("%s - returned %d\n", __func__, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static u32 access_EV (u16 operation, u8 *ev_name, u8 *buffer, u32 *buf_size)
|
||||
static u32 access_EV(u16 operation, u8 *ev_name, u8 *buffer, u32 *buf_size)
|
||||
{
|
||||
unsigned long flags;
|
||||
int op = operation;
|
||||
@ -197,7 +197,7 @@ static u32 access_EV (u16 operation, u8 *ev_name, u8 *buffer, u32 *buf_size)
|
||||
*
|
||||
* Read the hot plug Resource Table from NVRAM
|
||||
*/
|
||||
static int load_HRT (void __iomem *rom_start)
|
||||
static int load_HRT(void __iomem *rom_start)
|
||||
{
|
||||
u32 available;
|
||||
u32 temp_dword;
|
||||
@ -232,7 +232,7 @@ static int load_HRT (void __iomem *rom_start)
|
||||
*
|
||||
* Save the hot plug Resource Table in NVRAM
|
||||
*/
|
||||
static u32 store_HRT (void __iomem *rom_start)
|
||||
static u32 store_HRT(void __iomem *rom_start)
|
||||
{
|
||||
u32 *buffer;
|
||||
u32 *pFill;
|
||||
@ -252,7 +252,7 @@ static u32 store_HRT (void __iomem *rom_start)
|
||||
if (!check_for_compaq_ROM(rom_start))
|
||||
return(1);
|
||||
|
||||
buffer = (u32*) evbuffer;
|
||||
buffer = (u32 *) evbuffer;
|
||||
|
||||
if (!buffer)
|
||||
return(1);
|
||||
@ -306,7 +306,7 @@ static u32 store_HRT (void __iomem *rom_start)
|
||||
loop = 0;
|
||||
|
||||
while (resNode) {
|
||||
loop ++;
|
||||
loop++;
|
||||
|
||||
/* base */
|
||||
rc = add_dword(&pFill, resNode->base, &usedbytes, &available);
|
||||
@ -331,7 +331,7 @@ static u32 store_HRT (void __iomem *rom_start)
|
||||
loop = 0;
|
||||
|
||||
while (resNode) {
|
||||
loop ++;
|
||||
loop++;
|
||||
|
||||
/* base */
|
||||
rc = add_dword(&pFill, resNode->base, &usedbytes, &available);
|
||||
@ -356,7 +356,7 @@ static u32 store_HRT (void __iomem *rom_start)
|
||||
loop = 0;
|
||||
|
||||
while (resNode) {
|
||||
loop ++;
|
||||
loop++;
|
||||
|
||||
/* base */
|
||||
rc = add_dword(&pFill, resNode->base, &usedbytes, &available);
|
||||
@ -381,7 +381,7 @@ static u32 store_HRT (void __iomem *rom_start)
|
||||
loop = 0;
|
||||
|
||||
while (resNode) {
|
||||
loop ++;
|
||||
loop++;
|
||||
|
||||
/* base */
|
||||
rc = add_dword(&pFill, resNode->base, &usedbytes, &available);
|
||||
@ -408,7 +408,7 @@ static u32 store_HRT (void __iomem *rom_start)
|
||||
|
||||
temp_dword = usedbytes;
|
||||
|
||||
rc = access_EV(WRITE_EV, "CQTHPS", (u8*) buffer, &temp_dword);
|
||||
rc = access_EV(WRITE_EV, "CQTHPS", (u8 *) buffer, &temp_dword);
|
||||
|
||||
dbg("usedbytes = 0x%x, length = 0x%x\n", usedbytes, temp_dword);
|
||||
|
||||
@ -423,7 +423,7 @@ static u32 store_HRT (void __iomem *rom_start)
|
||||
}
|
||||
|
||||
|
||||
void compaq_nvram_init (void __iomem *rom_start)
|
||||
void compaq_nvram_init(void __iomem *rom_start)
|
||||
{
|
||||
if (rom_start)
|
||||
compaq_int15_entry_point = (rom_start + ROM_INT15_PHY_ADDR - ROM_PHY_ADDR);
|
||||
@ -435,7 +435,7 @@ void compaq_nvram_init (void __iomem *rom_start)
|
||||
}
|
||||
|
||||
|
||||
int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
|
||||
int compaq_nvram_load(void __iomem *rom_start, struct controller *ctrl)
|
||||
{
|
||||
u8 bus, device, function;
|
||||
u8 nummem, numpmem, numio, numbus;
|
||||
@ -451,7 +451,7 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
|
||||
if (!evbuffer_init) {
|
||||
/* Read the resource list information in from NVRAM */
|
||||
if (load_HRT(rom_start))
|
||||
memset (evbuffer, 0, 1024);
|
||||
memset(evbuffer, 0, 1024);
|
||||
|
||||
evbuffer_init = 1;
|
||||
}
|
||||
@ -472,7 +472,7 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
|
||||
|
||||
p_byte += 3;
|
||||
|
||||
if (p_byte > ((u8*)p_EV_header + evbuffer_length))
|
||||
if (p_byte > ((u8 *)p_EV_header + evbuffer_length))
|
||||
return 2;
|
||||
|
||||
bus = p_ev_ctrl->bus;
|
||||
@ -489,20 +489,20 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
|
||||
|
||||
p_byte += 4;
|
||||
|
||||
if (p_byte > ((u8*)p_EV_header + evbuffer_length))
|
||||
if (p_byte > ((u8 *)p_EV_header + evbuffer_length))
|
||||
return 2;
|
||||
|
||||
/* Skip forward to the next entry */
|
||||
p_byte += (nummem + numpmem + numio + numbus) * 8;
|
||||
|
||||
if (p_byte > ((u8*)p_EV_header + evbuffer_length))
|
||||
if (p_byte > ((u8 *)p_EV_header + evbuffer_length))
|
||||
return 2;
|
||||
|
||||
p_ev_ctrl = (struct ev_hrt_ctrl *) p_byte;
|
||||
|
||||
p_byte += 3;
|
||||
|
||||
if (p_byte > ((u8*)p_EV_header + evbuffer_length))
|
||||
if (p_byte > ((u8 *)p_EV_header + evbuffer_length))
|
||||
return 2;
|
||||
|
||||
bus = p_ev_ctrl->bus;
|
||||
@ -517,7 +517,7 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
|
||||
|
||||
p_byte += 4;
|
||||
|
||||
if (p_byte > ((u8*)p_EV_header + evbuffer_length))
|
||||
if (p_byte > ((u8 *)p_EV_header + evbuffer_length))
|
||||
return 2;
|
||||
|
||||
while (nummem--) {
|
||||
@ -526,20 +526,20 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
|
||||
if (!mem_node)
|
||||
break;
|
||||
|
||||
mem_node->base = *(u32*)p_byte;
|
||||
dbg("mem base = %8.8x\n",mem_node->base);
|
||||
mem_node->base = *(u32 *)p_byte;
|
||||
dbg("mem base = %8.8x\n", mem_node->base);
|
||||
p_byte += 4;
|
||||
|
||||
if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
|
||||
if (p_byte > ((u8 *)p_EV_header + evbuffer_length)) {
|
||||
kfree(mem_node);
|
||||
return 2;
|
||||
}
|
||||
|
||||
mem_node->length = *(u32*)p_byte;
|
||||
dbg("mem length = %8.8x\n",mem_node->length);
|
||||
mem_node->length = *(u32 *)p_byte;
|
||||
dbg("mem length = %8.8x\n", mem_node->length);
|
||||
p_byte += 4;
|
||||
|
||||
if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
|
||||
if (p_byte > ((u8 *)p_EV_header + evbuffer_length)) {
|
||||
kfree(mem_node);
|
||||
return 2;
|
||||
}
|
||||
@ -554,20 +554,20 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
|
||||
if (!p_mem_node)
|
||||
break;
|
||||
|
||||
p_mem_node->base = *(u32*)p_byte;
|
||||
dbg("pre-mem base = %8.8x\n",p_mem_node->base);
|
||||
p_mem_node->base = *(u32 *)p_byte;
|
||||
dbg("pre-mem base = %8.8x\n", p_mem_node->base);
|
||||
p_byte += 4;
|
||||
|
||||
if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
|
||||
if (p_byte > ((u8 *)p_EV_header + evbuffer_length)) {
|
||||
kfree(p_mem_node);
|
||||
return 2;
|
||||
}
|
||||
|
||||
p_mem_node->length = *(u32*)p_byte;
|
||||
dbg("pre-mem length = %8.8x\n",p_mem_node->length);
|
||||
p_mem_node->length = *(u32 *)p_byte;
|
||||
dbg("pre-mem length = %8.8x\n", p_mem_node->length);
|
||||
p_byte += 4;
|
||||
|
||||
if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
|
||||
if (p_byte > ((u8 *)p_EV_header + evbuffer_length)) {
|
||||
kfree(p_mem_node);
|
||||
return 2;
|
||||
}
|
||||
@ -582,20 +582,20 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
|
||||
if (!io_node)
|
||||
break;
|
||||
|
||||
io_node->base = *(u32*)p_byte;
|
||||
dbg("io base = %8.8x\n",io_node->base);
|
||||
io_node->base = *(u32 *)p_byte;
|
||||
dbg("io base = %8.8x\n", io_node->base);
|
||||
p_byte += 4;
|
||||
|
||||
if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
|
||||
if (p_byte > ((u8 *)p_EV_header + evbuffer_length)) {
|
||||
kfree(io_node);
|
||||
return 2;
|
||||
}
|
||||
|
||||
io_node->length = *(u32*)p_byte;
|
||||
dbg("io length = %8.8x\n",io_node->length);
|
||||
io_node->length = *(u32 *)p_byte;
|
||||
dbg("io length = %8.8x\n", io_node->length);
|
||||
p_byte += 4;
|
||||
|
||||
if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
|
||||
if (p_byte > ((u8 *)p_EV_header + evbuffer_length)) {
|
||||
kfree(io_node);
|
||||
return 2;
|
||||
}
|
||||
@ -610,18 +610,18 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
|
||||
if (!bus_node)
|
||||
break;
|
||||
|
||||
bus_node->base = *(u32*)p_byte;
|
||||
bus_node->base = *(u32 *)p_byte;
|
||||
p_byte += 4;
|
||||
|
||||
if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
|
||||
if (p_byte > ((u8 *)p_EV_header + evbuffer_length)) {
|
||||
kfree(bus_node);
|
||||
return 2;
|
||||
}
|
||||
|
||||
bus_node->length = *(u32*)p_byte;
|
||||
bus_node->length = *(u32 *)p_byte;
|
||||
p_byte += 4;
|
||||
|
||||
if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
|
||||
if (p_byte > ((u8 *)p_EV_header + evbuffer_length)) {
|
||||
kfree(bus_node);
|
||||
return 2;
|
||||
}
|
||||
@ -650,7 +650,7 @@ int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
|
||||
}
|
||||
|
||||
|
||||
int compaq_nvram_store (void __iomem *rom_start)
|
||||
int compaq_nvram_store(void __iomem *rom_start)
|
||||
{
|
||||
int rc = 1;
|
||||
|
||||
|
@ -81,7 +81,7 @@ static void __iomem *detect_HRT_floating_pointer(void __iomem *begin, void __iom
|
||||
}
|
||||
|
||||
|
||||
int cpqhp_configure_device (struct controller *ctrl, struct pci_func *func)
|
||||
int cpqhp_configure_device(struct controller *ctrl, struct pci_func *func)
|
||||
{
|
||||
struct pci_bus *child;
|
||||
int num;
|
||||
@ -89,7 +89,7 @@ int cpqhp_configure_device (struct controller *ctrl, struct pci_func *func)
|
||||
pci_lock_rescan_remove();
|
||||
|
||||
if (func->pci_dev == NULL)
|
||||
func->pci_dev = pci_get_bus_and_slot(func->bus,PCI_DEVFN(func->device, func->function));
|
||||
func->pci_dev = pci_get_bus_and_slot(func->bus, PCI_DEVFN(func->device, func->function));
|
||||
|
||||
/* No pci device, we need to create it then */
|
||||
if (func->pci_dev == NULL) {
|
||||
@ -128,7 +128,7 @@ int cpqhp_unconfigure_device(struct pci_func *func)
|
||||
dbg("%s: bus/dev/func = %x/%x/%x\n", __func__, func->bus, func->device, func->function);
|
||||
|
||||
pci_lock_rescan_remove();
|
||||
for (j=0; j<8 ; j++) {
|
||||
for (j = 0; j < 8 ; j++) {
|
||||
struct pci_dev *temp = pci_get_bus_and_slot(func->bus, PCI_DEVFN(func->device, j));
|
||||
if (temp) {
|
||||
pci_dev_put(temp);
|
||||
@ -143,11 +143,11 @@ static int PCI_RefinedAccessConfig(struct pci_bus *bus, unsigned int devfn, u8 o
|
||||
{
|
||||
u32 vendID = 0;
|
||||
|
||||
if (pci_bus_read_config_dword (bus, devfn, PCI_VENDOR_ID, &vendID) == -1)
|
||||
if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &vendID) == -1)
|
||||
return -1;
|
||||
if (vendID == 0xffffffff)
|
||||
return -1;
|
||||
return pci_bus_read_config_dword (bus, devfn, offset, value);
|
||||
return pci_bus_read_config_dword(bus, devfn, offset, value);
|
||||
}
|
||||
|
||||
|
||||
@ -158,7 +158,7 @@ static int PCI_RefinedAccessConfig(struct pci_bus *bus, unsigned int devfn, u8 o
|
||||
* @dev_num: device number of PCI device
|
||||
* @slot: pointer to u8 where slot number will be returned
|
||||
*/
|
||||
int cpqhp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
|
||||
int cpqhp_set_irq(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
@ -230,7 +230,7 @@ static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 bus_num, u8 *dev_
|
||||
dbg("Looking for bridge bus_num %d dev_num %d\n", bus_num, tdevice);
|
||||
/* Yep we got one. bridge ? */
|
||||
if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) {
|
||||
pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(tdevice, 0), PCI_SECONDARY_BUS, &tbus);
|
||||
pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(tdevice, 0), PCI_SECONDARY_BUS, &tbus);
|
||||
/* XXX: no recursion, wtf? */
|
||||
dbg("Recurse on bus_num %d tdevice %d\n", tbus, tdevice);
|
||||
return 0;
|
||||
@ -257,16 +257,16 @@ static int PCI_GetBusDevHelper(struct controller *ctrl, u8 *bus_num, u8 *dev_num
|
||||
*bus_num = tbus;
|
||||
*dev_num = tdevice;
|
||||
ctrl->pci_bus->number = tbus;
|
||||
pci_bus_read_config_dword (ctrl->pci_bus, *dev_num, PCI_VENDOR_ID, &work);
|
||||
pci_bus_read_config_dword(ctrl->pci_bus, *dev_num, PCI_VENDOR_ID, &work);
|
||||
if (!nobridge || (work == 0xffffffff))
|
||||
return 0;
|
||||
|
||||
dbg("bus_num %d devfn %d\n", *bus_num, *dev_num);
|
||||
pci_bus_read_config_dword (ctrl->pci_bus, *dev_num, PCI_CLASS_REVISION, &work);
|
||||
pci_bus_read_config_dword(ctrl->pci_bus, *dev_num, PCI_CLASS_REVISION, &work);
|
||||
dbg("work >> 8 (%x) = BRIDGE (%x)\n", work >> 8, PCI_TO_PCI_BRIDGE_CLASS);
|
||||
|
||||
if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) {
|
||||
pci_bus_read_config_byte (ctrl->pci_bus, *dev_num, PCI_SECONDARY_BUS, &tbus);
|
||||
pci_bus_read_config_byte(ctrl->pci_bus, *dev_num, PCI_SECONDARY_BUS, &tbus);
|
||||
dbg("Scan bus for Non Bridge: bus %d\n", tbus);
|
||||
if (PCI_ScanBusForNonBridge(ctrl, tbus, dev_num) == 0) {
|
||||
*bus_num = tbus;
|
||||
@ -280,7 +280,7 @@ static int PCI_GetBusDevHelper(struct controller *ctrl, u8 *bus_num, u8 *dev_num
|
||||
}
|
||||
|
||||
|
||||
int cpqhp_get_bus_dev (struct controller *ctrl, u8 *bus_num, u8 *dev_num, u8 slot)
|
||||
int cpqhp_get_bus_dev(struct controller *ctrl, u8 *bus_num, u8 *dev_num, u8 slot)
|
||||
{
|
||||
/* plain (bridges allowed) */
|
||||
return PCI_GetBusDevHelper(ctrl, bus_num, dev_num, slot, 0);
|
||||
@ -419,7 +419,7 @@ int cpqhp_save_config(struct controller *ctrl, int busnumber, int is_hot_plug)
|
||||
new_slot->pci_dev = pci_get_bus_and_slot(new_slot->bus, (new_slot->device << 3) | new_slot->function);
|
||||
|
||||
for (cloop = 0; cloop < 0x20; cloop++) {
|
||||
rc = pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(device, function), cloop << 2, (u32 *) & (new_slot-> config_space [cloop]));
|
||||
rc = pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(device, function), cloop << 2, (u32 *) &(new_slot->config_space[cloop]));
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
@ -465,7 +465,7 @@ int cpqhp_save_config(struct controller *ctrl, int busnumber, int is_hot_plug)
|
||||
*
|
||||
* returns 0 if success
|
||||
*/
|
||||
int cpqhp_save_slot_config (struct controller *ctrl, struct pci_func *new_slot)
|
||||
int cpqhp_save_slot_config(struct controller *ctrl, struct pci_func *new_slot)
|
||||
{
|
||||
long rc;
|
||||
u8 class_code;
|
||||
@ -481,7 +481,7 @@ int cpqhp_save_slot_config (struct controller *ctrl, struct pci_func *new_slot)
|
||||
ID = 0xFFFFFFFF;
|
||||
|
||||
ctrl->pci_bus->number = new_slot->bus;
|
||||
pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_VENDOR_ID, &ID);
|
||||
pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_VENDOR_ID, &ID);
|
||||
|
||||
if (ID == 0xFFFFFFFF)
|
||||
return 2;
|
||||
@ -497,7 +497,7 @@ int cpqhp_save_slot_config (struct controller *ctrl, struct pci_func *new_slot)
|
||||
while (function < max_functions) {
|
||||
if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
|
||||
/* Recurse the subordinate bus */
|
||||
pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_SECONDARY_BUS, &secondary_bus);
|
||||
pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_SECONDARY_BUS, &secondary_bus);
|
||||
|
||||
sub_bus = (int) secondary_bus;
|
||||
|
||||
@ -514,7 +514,7 @@ int cpqhp_save_slot_config (struct controller *ctrl, struct pci_func *new_slot)
|
||||
new_slot->status = 0;
|
||||
|
||||
for (cloop = 0; cloop < 0x20; cloop++)
|
||||
pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), cloop << 2, (u32 *) & (new_slot-> config_space [cloop]));
|
||||
pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), cloop << 2, (u32 *) &(new_slot->config_space[cloop]));
|
||||
|
||||
function++;
|
||||
|
||||
@ -571,10 +571,10 @@ int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func *func)
|
||||
devfn = PCI_DEVFN(func->device, func->function);
|
||||
|
||||
/* Check for Bridge */
|
||||
pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
|
||||
pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
|
||||
|
||||
if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
|
||||
pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
|
||||
pci_bus_read_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
|
||||
|
||||
sub_bus = (int) secondary_bus;
|
||||
|
||||
@ -595,8 +595,8 @@ int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func *func)
|
||||
*/
|
||||
for (cloop = 0x10; cloop <= 0x14; cloop += 4) {
|
||||
temp_register = 0xFFFFFFFF;
|
||||
pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
|
||||
pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
|
||||
pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register);
|
||||
pci_bus_read_config_dword(pci_bus, devfn, cloop, &base);
|
||||
/* If this register is implemented */
|
||||
if (base) {
|
||||
if (base & 0x01L) {
|
||||
@ -631,8 +631,8 @@ int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func *func)
|
||||
/* Figure out IO and memory base lengths */
|
||||
for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
|
||||
temp_register = 0xFFFFFFFF;
|
||||
pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
|
||||
pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
|
||||
pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register);
|
||||
pci_bus_read_config_dword(pci_bus, devfn, cloop, &base);
|
||||
|
||||
/* If this register is implemented */
|
||||
if (base) {
|
||||
@ -686,7 +686,7 @@ int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func *func)
|
||||
*
|
||||
* returns 0 if success
|
||||
*/
|
||||
int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func *func)
|
||||
int cpqhp_save_used_resources(struct controller *ctrl, struct pci_func *func)
|
||||
{
|
||||
u8 cloop;
|
||||
u8 header_type;
|
||||
@ -791,7 +791,7 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func *func)
|
||||
}
|
||||
/* Figure out IO and memory base lengths */
|
||||
for (cloop = 0x10; cloop <= 0x14; cloop += 4) {
|
||||
pci_bus_read_config_dword (pci_bus, devfn, cloop, &save_base);
|
||||
pci_bus_read_config_dword(pci_bus, devfn, cloop, &save_base);
|
||||
|
||||
temp_register = 0xFFFFFFFF;
|
||||
pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register);
|
||||
@ -972,13 +972,13 @@ int cpqhp_configure_board(struct controller *ctrl, struct pci_func *func)
|
||||
* registers are programmed last
|
||||
*/
|
||||
for (cloop = 0x3C; cloop > 0; cloop -= 4)
|
||||
pci_bus_write_config_dword (pci_bus, devfn, cloop, func->config_space[cloop >> 2]);
|
||||
pci_bus_write_config_dword(pci_bus, devfn, cloop, func->config_space[cloop >> 2]);
|
||||
|
||||
pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
|
||||
pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
|
||||
|
||||
/* If this is a bridge device, restore subordinate devices */
|
||||
if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
|
||||
pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
|
||||
pci_bus_read_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
|
||||
|
||||
sub_bus = (int) secondary_bus;
|
||||
|
||||
@ -998,7 +998,7 @@ int cpqhp_configure_board(struct controller *ctrl, struct pci_func *func)
|
||||
*/
|
||||
|
||||
for (cloop = 16; cloop < 40; cloop += 4) {
|
||||
pci_bus_read_config_dword (pci_bus, devfn, cloop, &temp);
|
||||
pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp);
|
||||
|
||||
if (temp != func->config_space[cloop >> 2]) {
|
||||
dbg("Config space compare failure!!! offset = %x\n", cloop);
|
||||
@ -1050,7 +1050,7 @@ int cpqhp_valid_replace(struct controller *ctrl, struct pci_func *func)
|
||||
pci_bus->number = func->bus;
|
||||
devfn = PCI_DEVFN(func->device, func->function);
|
||||
|
||||
pci_bus_read_config_dword (pci_bus, devfn, PCI_VENDOR_ID, &temp_register);
|
||||
pci_bus_read_config_dword(pci_bus, devfn, PCI_VENDOR_ID, &temp_register);
|
||||
|
||||
/* No adapter present */
|
||||
if (temp_register == 0xFFFFFFFF)
|
||||
@ -1060,14 +1060,14 @@ int cpqhp_valid_replace(struct controller *ctrl, struct pci_func *func)
|
||||
return(ADAPTER_NOT_SAME);
|
||||
|
||||
/* Check for same revision number and class code */
|
||||
pci_bus_read_config_dword (pci_bus, devfn, PCI_CLASS_REVISION, &temp_register);
|
||||
pci_bus_read_config_dword(pci_bus, devfn, PCI_CLASS_REVISION, &temp_register);
|
||||
|
||||
/* Adapter not the same */
|
||||
if (temp_register != func->config_space[0x08 >> 2])
|
||||
return(ADAPTER_NOT_SAME);
|
||||
|
||||
/* Check for Bridge */
|
||||
pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
|
||||
pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
|
||||
|
||||
if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
|
||||
/* In order to continue checking, we must program the
|
||||
@ -1076,7 +1076,7 @@ int cpqhp_valid_replace(struct controller *ctrl, struct pci_func *func)
|
||||
*/
|
||||
|
||||
temp_register = func->config_space[0x18 >> 2];
|
||||
pci_bus_write_config_dword (pci_bus, devfn, PCI_PRIMARY_BUS, temp_register);
|
||||
pci_bus_write_config_dword(pci_bus, devfn, PCI_PRIMARY_BUS, temp_register);
|
||||
|
||||
secondary_bus = (temp_register >> 8) & 0xFF;
|
||||
|
||||
@ -1094,7 +1094,7 @@ int cpqhp_valid_replace(struct controller *ctrl, struct pci_func *func)
|
||||
/* Check to see if it is a standard config header */
|
||||
else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
|
||||
/* Check subsystem vendor and ID */
|
||||
pci_bus_read_config_dword (pci_bus, devfn, PCI_SUBSYSTEM_VENDOR_ID, &temp_register);
|
||||
pci_bus_read_config_dword(pci_bus, devfn, PCI_SUBSYSTEM_VENDOR_ID, &temp_register);
|
||||
|
||||
if (temp_register != func->config_space[0x2C >> 2]) {
|
||||
/* If it's a SMART-2 and the register isn't
|
||||
@ -1108,8 +1108,8 @@ int cpqhp_valid_replace(struct controller *ctrl, struct pci_func *func)
|
||||
/* Figure out IO and memory base lengths */
|
||||
for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
|
||||
temp_register = 0xFFFFFFFF;
|
||||
pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
|
||||
pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);
|
||||
pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register);
|
||||
pci_bus_read_config_dword(pci_bus, devfn, cloop, &base);
|
||||
|
||||
/* If this register is implemented */
|
||||
if (base) {
|
||||
@ -1234,7 +1234,7 @@ int cpqhp_find_available_resources(struct controller *ctrl, void __iomem *rom_st
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
one_slot = rom_resource_table + sizeof (struct hrt);
|
||||
one_slot = rom_resource_table + sizeof(struct hrt);
|
||||
|
||||
i = readb(rom_resource_table + NUMBER_OF_ENTRIES);
|
||||
dbg("number_of_entries = %d\n", i);
|
||||
@ -1263,12 +1263,12 @@ int cpqhp_find_available_resources(struct controller *ctrl, void __iomem *rom_st
|
||||
/* If this entry isn't for our controller's bus, ignore it */
|
||||
if (primary_bus != ctrl->bus) {
|
||||
i--;
|
||||
one_slot += sizeof (struct slot_rt);
|
||||
one_slot += sizeof(struct slot_rt);
|
||||
continue;
|
||||
}
|
||||
/* find out if this entry is for an occupied slot */
|
||||
ctrl->pci_bus->number = primary_bus;
|
||||
pci_bus_read_config_dword (ctrl->pci_bus, dev_func, PCI_VENDOR_ID, &temp_dword);
|
||||
pci_bus_read_config_dword(ctrl->pci_bus, dev_func, PCI_VENDOR_ID, &temp_dword);
|
||||
dbg("temp_D_word = %x\n", temp_dword);
|
||||
|
||||
if (temp_dword != 0xFFFFFFFF) {
|
||||
@ -1283,7 +1283,7 @@ int cpqhp_find_available_resources(struct controller *ctrl, void __iomem *rom_st
|
||||
/* If we can't find a match, skip this table entry */
|
||||
if (!func) {
|
||||
i--;
|
||||
one_slot += sizeof (struct slot_rt);
|
||||
one_slot += sizeof(struct slot_rt);
|
||||
continue;
|
||||
}
|
||||
/* this may not work and shouldn't be used */
|
||||
@ -1395,7 +1395,7 @@ int cpqhp_find_available_resources(struct controller *ctrl, void __iomem *rom_st
|
||||
}
|
||||
|
||||
i--;
|
||||
one_slot += sizeof (struct slot_rt);
|
||||
one_slot += sizeof(struct slot_rt);
|
||||
}
|
||||
|
||||
/* If all of the following fail, we don't have any resources for
|
||||
@ -1475,7 +1475,7 @@ int cpqhp_return_board_resources(struct pci_func *func, struct resource_lists *r
|
||||
*
|
||||
* Puts node back in the resource list pointed to by head
|
||||
*/
|
||||
void cpqhp_destroy_resource_list (struct resource_lists *resources)
|
||||
void cpqhp_destroy_resource_list(struct resource_lists *resources)
|
||||
{
|
||||
struct pci_resource *res, *tres;
|
||||
|
||||
@ -1522,7 +1522,7 @@ void cpqhp_destroy_resource_list (struct resource_lists *resources)
|
||||
*
|
||||
* Puts node back in the resource list pointed to by head
|
||||
*/
|
||||
void cpqhp_destroy_board_resources (struct pci_func *func)
|
||||
void cpqhp_destroy_board_resources(struct pci_func *func)
|
||||
{
|
||||
struct pci_resource *res, *tres;
|
||||
|
||||
|
@ -39,7 +39,7 @@
|
||||
#include "cpqphp.h"
|
||||
|
||||
static DEFINE_MUTEX(cpqphp_mutex);
|
||||
static int show_ctrl (struct controller *ctrl, char *buf)
|
||||
static int show_ctrl(struct controller *ctrl, char *buf)
|
||||
{
|
||||
char *out = buf;
|
||||
int index;
|
||||
@ -77,7 +77,7 @@ static int show_ctrl (struct controller *ctrl, char *buf)
|
||||
return out - buf;
|
||||
}
|
||||
|
||||
static int show_dev (struct controller *ctrl, char *buf)
|
||||
static int show_dev(struct controller *ctrl, char *buf)
|
||||
{
|
||||
char *out = buf;
|
||||
int index;
|
||||
@ -119,7 +119,7 @@ static int show_dev (struct controller *ctrl, char *buf)
|
||||
out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
|
||||
res = res->next;
|
||||
}
|
||||
slot=slot->next;
|
||||
slot = slot->next;
|
||||
}
|
||||
|
||||
return out - buf;
|
||||
|
@ -39,11 +39,11 @@ extern int ibmphp_debug;
|
||||
#else
|
||||
#define MY_NAME THIS_MODULE->name
|
||||
#endif
|
||||
#define debug(fmt, arg...) do { if (ibmphp_debug == 1) printk(KERN_DEBUG "%s: " fmt , MY_NAME , ## arg); } while (0)
|
||||
#define debug_pci(fmt, arg...) do { if (ibmphp_debug) printk(KERN_DEBUG "%s: " fmt , MY_NAME , ## arg); } while (0)
|
||||
#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
|
||||
#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)
|
||||
#define debug(fmt, arg...) do { if (ibmphp_debug == 1) printk(KERN_DEBUG "%s: " fmt, MY_NAME, ## arg); } while (0)
|
||||
#define debug_pci(fmt, arg...) do { if (ibmphp_debug) printk(KERN_DEBUG "%s: " fmt, MY_NAME, ## arg); } while (0)
|
||||
#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME, ## arg)
|
||||
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME, ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME, ## arg)
|
||||
|
||||
|
||||
/* EBDA stuff */
|
||||
@ -603,7 +603,7 @@ void ibmphp_hpc_stop_poll_thread(void);
|
||||
#define SLOT_CONNECT(s) ((u8) ((s & HPC_SLOT_CONNECT) \
|
||||
? HPC_SLOT_DISCONNECTED : HPC_SLOT_CONNECTED))
|
||||
|
||||
#define SLOT_ATTN(s,es) ((u8) ((es & HPC_SLOT_BLINK_ATTN) \
|
||||
#define SLOT_ATTN(s, es) ((u8) ((es & HPC_SLOT_BLINK_ATTN) \
|
||||
? HPC_SLOT_ATTN_BLINK \
|
||||
: ((s & HPC_SLOT_ATTN) ? HPC_SLOT_ATTN_ON : HPC_SLOT_ATTN_OFF)))
|
||||
|
||||
|
@ -39,11 +39,11 @@
|
||||
#include <asm/io_apic.h>
|
||||
#include "ibmphp.h"
|
||||
|
||||
#define attn_on(sl) ibmphp_hpc_writeslot (sl, HPC_SLOT_ATTNON)
|
||||
#define attn_off(sl) ibmphp_hpc_writeslot (sl, HPC_SLOT_ATTNOFF)
|
||||
#define attn_LED_blink(sl) ibmphp_hpc_writeslot (sl, HPC_SLOT_BLINKLED)
|
||||
#define get_ctrl_revision(sl, rev) ibmphp_hpc_readslot (sl, READ_REVLEVEL, rev)
|
||||
#define get_hpc_options(sl, opt) ibmphp_hpc_readslot (sl, READ_HPCOPTIONS, opt)
|
||||
#define attn_on(sl) ibmphp_hpc_writeslot(sl, HPC_SLOT_ATTNON)
|
||||
#define attn_off(sl) ibmphp_hpc_writeslot(sl, HPC_SLOT_ATTNOFF)
|
||||
#define attn_LED_blink(sl) ibmphp_hpc_writeslot(sl, HPC_SLOT_BLINKLED)
|
||||
#define get_ctrl_revision(sl, rev) ibmphp_hpc_readslot(sl, READ_REVLEVEL, rev)
|
||||
#define get_hpc_options(sl, opt) ibmphp_hpc_readslot(sl, READ_HPCOPTIONS, opt)
|
||||
|
||||
#define DRIVER_VERSION "0.6"
|
||||
#define DRIVER_DESC "IBM Hot Plug PCI Controller Driver"
|
||||
@ -52,9 +52,9 @@ int ibmphp_debug;
|
||||
|
||||
static bool debug;
|
||||
module_param(debug, bool, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC (debug, "Debugging mode enabled or not");
|
||||
MODULE_LICENSE ("GPL");
|
||||
MODULE_DESCRIPTION (DRIVER_DESC);
|
||||
MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
|
||||
struct pci_bus *ibmphp_pci_bus;
|
||||
static int max_slots;
|
||||
@ -113,14 +113,12 @@ static inline int slot_update(struct slot **sl)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __init get_max_slots (void)
|
||||
static int __init get_max_slots(void)
|
||||
{
|
||||
struct slot *slot_cur;
|
||||
struct list_head *tmp;
|
||||
u8 slot_count = 0;
|
||||
|
||||
list_for_each(tmp, &ibmphp_slot_head) {
|
||||
slot_cur = list_entry(tmp, struct slot, ibm_slot_list);
|
||||
list_for_each_entry(slot_cur, &ibmphp_slot_head, ibm_slot_list) {
|
||||
/* sometimes the hot-pluggable slots start with 4 (not always from 1) */
|
||||
slot_count = max(slot_count, slot_cur->number);
|
||||
}
|
||||
@ -459,7 +457,7 @@ static int get_max_adapter_speed_1(struct hotplug_slot *hotplug_slot, u8 *value,
|
||||
*value = SLOT_SPEED(myslot.ext_status);
|
||||
} else
|
||||
*value = MAX_ADAPTER_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flag)
|
||||
@ -501,16 +499,10 @@ static int get_bus_name(struct hotplug_slot *hotplug_slot, char *value)
|
||||
static int __init init_ops(void)
|
||||
{
|
||||
struct slot *slot_cur;
|
||||
struct list_head *tmp;
|
||||
int retval;
|
||||
int rc;
|
||||
|
||||
list_for_each(tmp, &ibmphp_slot_head) {
|
||||
slot_cur = list_entry(tmp, struct slot, ibm_slot_list);
|
||||
|
||||
if (!slot_cur)
|
||||
return -ENODEV;
|
||||
|
||||
list_for_each_entry(slot_cur, &ibmphp_slot_head, ibm_slot_list) {
|
||||
debug("BEFORE GETTING SLOT STATUS, slot # %x\n",
|
||||
slot_cur->number);
|
||||
if (slot_cur->ctrl->revision == 0xFF)
|
||||
@ -620,11 +612,11 @@ int ibmphp_update_slot_info(struct slot *slot_cur)
|
||||
info->attention_status = SLOT_ATTN(slot_cur->status,
|
||||
slot_cur->ext_status);
|
||||
info->latch_status = SLOT_LATCH(slot_cur->status);
|
||||
if (!SLOT_PRESENT(slot_cur->status)) {
|
||||
info->adapter_status = 0;
|
||||
if (!SLOT_PRESENT(slot_cur->status)) {
|
||||
info->adapter_status = 0;
|
||||
/* info->max_adapter_speed_status = MAX_ADAPTER_NONE; */
|
||||
} else {
|
||||
info->adapter_status = 1;
|
||||
info->adapter_status = 1;
|
||||
/* get_max_adapter_speed_1(slot_cur->hotplug_slot,
|
||||
&info->max_adapter_speed_status, 0); */
|
||||
}
|
||||
@ -669,9 +661,7 @@ static struct pci_func *ibm_slot_find(u8 busno, u8 device, u8 function)
|
||||
{
|
||||
struct pci_func *func_cur;
|
||||
struct slot *slot_cur;
|
||||
struct list_head *tmp;
|
||||
list_for_each(tmp, &ibmphp_slot_head) {
|
||||
slot_cur = list_entry(tmp, struct slot, ibm_slot_list);
|
||||
list_for_each_entry(slot_cur, &ibmphp_slot_head, ibm_slot_list) {
|
||||
if (slot_cur->func) {
|
||||
func_cur = slot_cur->func;
|
||||
while (func_cur) {
|
||||
@ -693,14 +683,12 @@ static struct pci_func *ibm_slot_find(u8 busno, u8 device, u8 function)
|
||||
*************************************************************/
|
||||
static void free_slots(void)
|
||||
{
|
||||
struct slot *slot_cur;
|
||||
struct list_head *tmp;
|
||||
struct list_head *next;
|
||||
struct slot *slot_cur, *next;
|
||||
|
||||
debug("%s -- enter\n", __func__);
|
||||
|
||||
list_for_each_safe(tmp, next, &ibmphp_slot_head) {
|
||||
slot_cur = list_entry(tmp, struct slot, ibm_slot_list);
|
||||
list_for_each_entry_safe(slot_cur, next, &ibmphp_slot_head,
|
||||
ibm_slot_list) {
|
||||
pci_hp_deregister(slot_cur->hotplug_slot);
|
||||
}
|
||||
debug("%s -- exit\n", __func__);
|
||||
@ -866,7 +854,7 @@ static int set_bus(struct slot *slot_cur)
|
||||
int retval;
|
||||
static struct pci_device_id ciobx[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, 0x0101) },
|
||||
{ },
|
||||
{ },
|
||||
};
|
||||
|
||||
debug("%s - entry slot # %d\n", __func__, slot_cur->number);
|
||||
@ -1182,7 +1170,7 @@ error_power:
|
||||
* HOT REMOVING ADAPTER CARD *
|
||||
* INPUT: POINTER TO THE HOTPLUG SLOT STRUCTURE *
|
||||
* OUTPUT: SUCCESS 0 ; FAILURE: UNCONFIGURE , VALIDATE *
|
||||
DISABLE POWER , *
|
||||
* DISABLE POWER , *
|
||||
**************************************************************/
|
||||
static int ibmphp_disable_slot(struct hotplug_slot *hotplug_slot)
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -40,7 +40,7 @@
|
||||
#include "ibmphp.h"
|
||||
|
||||
static int to_debug = 0;
|
||||
#define debug_polling(fmt, arg...) do { if (to_debug) debug (fmt, arg); } while (0)
|
||||
#define debug_polling(fmt, arg...) do { if (to_debug) debug(fmt, arg); } while (0)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// timeout values
|
||||
@ -110,16 +110,16 @@ static struct task_struct *ibmphp_poll_thread;
|
||||
//----------------------------------------------------------------------------
|
||||
// local function prototypes
|
||||
//----------------------------------------------------------------------------
|
||||
static u8 i2c_ctrl_read (struct controller *, void __iomem *, u8);
|
||||
static u8 i2c_ctrl_write (struct controller *, void __iomem *, u8, u8);
|
||||
static u8 hpc_writecmdtoindex (u8, u8);
|
||||
static u8 hpc_readcmdtoindex (u8, u8);
|
||||
static void get_hpc_access (void);
|
||||
static void free_hpc_access (void);
|
||||
static u8 i2c_ctrl_read(struct controller *, void __iomem *, u8);
|
||||
static u8 i2c_ctrl_write(struct controller *, void __iomem *, u8, u8);
|
||||
static u8 hpc_writecmdtoindex(u8, u8);
|
||||
static u8 hpc_readcmdtoindex(u8, u8);
|
||||
static void get_hpc_access(void);
|
||||
static void free_hpc_access(void);
|
||||
static int poll_hpc(void *data);
|
||||
static int process_changeinstatus (struct slot *, struct slot *);
|
||||
static int process_changeinlatch (u8, u8, struct controller *);
|
||||
static int hpc_wait_ctlr_notworking (int, struct controller *, void __iomem *, u8 *);
|
||||
static int process_changeinstatus(struct slot *, struct slot *);
|
||||
static int process_changeinlatch(u8, u8, struct controller *);
|
||||
static int hpc_wait_ctlr_notworking(int, struct controller *, void __iomem *, u8 *);
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
@ -128,16 +128,16 @@ static int hpc_wait_ctlr_notworking (int, struct controller *, void __iomem *, u
|
||||
*
|
||||
* Action: initialize semaphores and variables
|
||||
*---------------------------------------------------------------------*/
|
||||
void __init ibmphp_hpc_initvars (void)
|
||||
void __init ibmphp_hpc_initvars(void)
|
||||
{
|
||||
debug ("%s - Entry\n", __func__);
|
||||
debug("%s - Entry\n", __func__);
|
||||
|
||||
mutex_init(&sem_hpcaccess);
|
||||
sema_init(&semOperations, 1);
|
||||
sema_init(&sem_exit, 0);
|
||||
to_debug = 0;
|
||||
|
||||
debug ("%s - Exit\n", __func__);
|
||||
debug("%s - Exit\n", __func__);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
@ -146,7 +146,7 @@ void __init ibmphp_hpc_initvars (void)
|
||||
* Action: read from HPC over I2C
|
||||
*
|
||||
*---------------------------------------------------------------------*/
|
||||
static u8 i2c_ctrl_read (struct controller *ctlr_ptr, void __iomem *WPGBbar, u8 index)
|
||||
static u8 i2c_ctrl_read(struct controller *ctlr_ptr, void __iomem *WPGBbar, u8 index)
|
||||
{
|
||||
u8 status;
|
||||
int i;
|
||||
@ -155,7 +155,7 @@ static u8 i2c_ctrl_read (struct controller *ctlr_ptr, void __iomem *WPGBbar, u8
|
||||
unsigned long ultemp;
|
||||
unsigned long data; // actual data HILO format
|
||||
|
||||
debug_polling ("%s - Entry WPGBbar[%p] index[%x] \n", __func__, WPGBbar, index);
|
||||
debug_polling("%s - Entry WPGBbar[%p] index[%x] \n", __func__, WPGBbar, index);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// READ - step 1
|
||||
@ -178,28 +178,28 @@ static u8 i2c_ctrl_read (struct controller *ctlr_ptr, void __iomem *WPGBbar, u8
|
||||
ultemp = ultemp << 8;
|
||||
data |= ultemp;
|
||||
} else {
|
||||
err ("this controller type is not supported \n");
|
||||
err("this controller type is not supported \n");
|
||||
return HPC_ERROR;
|
||||
}
|
||||
|
||||
wpg_data = swab32 (data); // swap data before writing
|
||||
wpg_data = swab32(data); // swap data before writing
|
||||
wpg_addr = WPGBbar + WPG_I2CMOSUP_OFFSET;
|
||||
writel (wpg_data, wpg_addr);
|
||||
writel(wpg_data, wpg_addr);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// READ - step 2 : clear the message buffer
|
||||
data = 0x00000000;
|
||||
wpg_data = swab32 (data);
|
||||
wpg_data = swab32(data);
|
||||
wpg_addr = WPGBbar + WPG_I2CMBUFL_OFFSET;
|
||||
writel (wpg_data, wpg_addr);
|
||||
writel(wpg_data, wpg_addr);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// READ - step 3 : issue start operation, I2C master control bit 30:ON
|
||||
// 2020 : [20] OR operation at [20] offset 0x20
|
||||
data = WPG_I2CMCNTL_STARTOP_MASK;
|
||||
wpg_data = swab32 (data);
|
||||
wpg_data = swab32(data);
|
||||
wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET + WPG_I2C_OR;
|
||||
writel (wpg_data, wpg_addr);
|
||||
writel(wpg_data, wpg_addr);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// READ - step 4 : wait until start operation bit clears
|
||||
@ -207,14 +207,14 @@ static u8 i2c_ctrl_read (struct controller *ctlr_ptr, void __iomem *WPGBbar, u8
|
||||
while (i) {
|
||||
msleep(10);
|
||||
wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET;
|
||||
wpg_data = readl (wpg_addr);
|
||||
data = swab32 (wpg_data);
|
||||
wpg_data = readl(wpg_addr);
|
||||
data = swab32(wpg_data);
|
||||
if (!(data & WPG_I2CMCNTL_STARTOP_MASK))
|
||||
break;
|
||||
i--;
|
||||
}
|
||||
if (i == 0) {
|
||||
debug ("%s - Error : WPG timeout\n", __func__);
|
||||
debug("%s - Error : WPG timeout\n", __func__);
|
||||
return HPC_ERROR;
|
||||
}
|
||||
//--------------------------------------------------------------------
|
||||
@ -223,26 +223,26 @@ static u8 i2c_ctrl_read (struct controller *ctlr_ptr, void __iomem *WPGBbar, u8
|
||||
while (i) {
|
||||
msleep(10);
|
||||
wpg_addr = WPGBbar + WPG_I2CSTAT_OFFSET;
|
||||
wpg_data = readl (wpg_addr);
|
||||
data = swab32 (wpg_data);
|
||||
if (HPC_I2CSTATUS_CHECK (data))
|
||||
wpg_data = readl(wpg_addr);
|
||||
data = swab32(wpg_data);
|
||||
if (HPC_I2CSTATUS_CHECK(data))
|
||||
break;
|
||||
i--;
|
||||
}
|
||||
if (i == 0) {
|
||||
debug ("ctrl_read - Exit Error:I2C timeout\n");
|
||||
debug("ctrl_read - Exit Error:I2C timeout\n");
|
||||
return HPC_ERROR;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// READ - step 6 : get DATA
|
||||
wpg_addr = WPGBbar + WPG_I2CMBUFL_OFFSET;
|
||||
wpg_data = readl (wpg_addr);
|
||||
data = swab32 (wpg_data);
|
||||
wpg_data = readl(wpg_addr);
|
||||
data = swab32(wpg_data);
|
||||
|
||||
status = (u8) data;
|
||||
|
||||
debug_polling ("%s - Exit index[%x] status[%x]\n", __func__, index, status);
|
||||
debug_polling("%s - Exit index[%x] status[%x]\n", __func__, index, status);
|
||||
|
||||
return (status);
|
||||
}
|
||||
@ -254,7 +254,7 @@ static u8 i2c_ctrl_read (struct controller *ctlr_ptr, void __iomem *WPGBbar, u8
|
||||
*
|
||||
* Return 0 or error codes
|
||||
*---------------------------------------------------------------------*/
|
||||
static u8 i2c_ctrl_write (struct controller *ctlr_ptr, void __iomem *WPGBbar, u8 index, u8 cmd)
|
||||
static u8 i2c_ctrl_write(struct controller *ctlr_ptr, void __iomem *WPGBbar, u8 index, u8 cmd)
|
||||
{
|
||||
u8 rc;
|
||||
void __iomem *wpg_addr; // base addr + offset
|
||||
@ -263,7 +263,7 @@ static u8 i2c_ctrl_write (struct controller *ctlr_ptr, void __iomem *WPGBbar, u8
|
||||
unsigned long data; // actual data HILO format
|
||||
int i;
|
||||
|
||||
debug_polling ("%s - Entry WPGBbar[%p] index[%x] cmd[%x]\n", __func__, WPGBbar, index, cmd);
|
||||
debug_polling("%s - Entry WPGBbar[%p] index[%x] cmd[%x]\n", __func__, WPGBbar, index, cmd);
|
||||
|
||||
rc = 0;
|
||||
//--------------------------------------------------------------------
|
||||
@ -289,28 +289,28 @@ static u8 i2c_ctrl_write (struct controller *ctlr_ptr, void __iomem *WPGBbar, u8
|
||||
ultemp = ultemp << 8;
|
||||
data |= ultemp;
|
||||
} else {
|
||||
err ("this controller type is not supported \n");
|
||||
err("this controller type is not supported \n");
|
||||
return HPC_ERROR;
|
||||
}
|
||||
|
||||
wpg_data = swab32 (data); // swap data before writing
|
||||
wpg_data = swab32(data); // swap data before writing
|
||||
wpg_addr = WPGBbar + WPG_I2CMOSUP_OFFSET;
|
||||
writel (wpg_data, wpg_addr);
|
||||
writel(wpg_data, wpg_addr);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// WRITE - step 2 : clear the message buffer
|
||||
data = 0x00000000 | (unsigned long)cmd;
|
||||
wpg_data = swab32 (data);
|
||||
wpg_data = swab32(data);
|
||||
wpg_addr = WPGBbar + WPG_I2CMBUFL_OFFSET;
|
||||
writel (wpg_data, wpg_addr);
|
||||
writel(wpg_data, wpg_addr);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// WRITE - step 3 : issue start operation,I2C master control bit 30:ON
|
||||
// 2020 : [20] OR operation at [20] offset 0x20
|
||||
data = WPG_I2CMCNTL_STARTOP_MASK;
|
||||
wpg_data = swab32 (data);
|
||||
wpg_data = swab32(data);
|
||||
wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET + WPG_I2C_OR;
|
||||
writel (wpg_data, wpg_addr);
|
||||
writel(wpg_data, wpg_addr);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// WRITE - step 4 : wait until start operation bit clears
|
||||
@ -318,14 +318,14 @@ static u8 i2c_ctrl_write (struct controller *ctlr_ptr, void __iomem *WPGBbar, u8
|
||||
while (i) {
|
||||
msleep(10);
|
||||
wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET;
|
||||
wpg_data = readl (wpg_addr);
|
||||
data = swab32 (wpg_data);
|
||||
wpg_data = readl(wpg_addr);
|
||||
data = swab32(wpg_data);
|
||||
if (!(data & WPG_I2CMCNTL_STARTOP_MASK))
|
||||
break;
|
||||
i--;
|
||||
}
|
||||
if (i == 0) {
|
||||
debug ("%s - Exit Error:WPG timeout\n", __func__);
|
||||
debug("%s - Exit Error:WPG timeout\n", __func__);
|
||||
rc = HPC_ERROR;
|
||||
}
|
||||
|
||||
@ -335,25 +335,25 @@ static u8 i2c_ctrl_write (struct controller *ctlr_ptr, void __iomem *WPGBbar, u8
|
||||
while (i) {
|
||||
msleep(10);
|
||||
wpg_addr = WPGBbar + WPG_I2CSTAT_OFFSET;
|
||||
wpg_data = readl (wpg_addr);
|
||||
data = swab32 (wpg_data);
|
||||
if (HPC_I2CSTATUS_CHECK (data))
|
||||
wpg_data = readl(wpg_addr);
|
||||
data = swab32(wpg_data);
|
||||
if (HPC_I2CSTATUS_CHECK(data))
|
||||
break;
|
||||
i--;
|
||||
}
|
||||
if (i == 0) {
|
||||
debug ("ctrl_read - Error : I2C timeout\n");
|
||||
debug("ctrl_read - Error : I2C timeout\n");
|
||||
rc = HPC_ERROR;
|
||||
}
|
||||
|
||||
debug_polling ("%s Exit rc[%x]\n", __func__, rc);
|
||||
debug_polling("%s Exit rc[%x]\n", __func__, rc);
|
||||
return (rc);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------
|
||||
// Read from ISA type HPC
|
||||
//------------------------------------------------------------
|
||||
static u8 isa_ctrl_read (struct controller *ctlr_ptr, u8 offset)
|
||||
static u8 isa_ctrl_read(struct controller *ctlr_ptr, u8 offset)
|
||||
{
|
||||
u16 start_address;
|
||||
u16 end_address;
|
||||
@ -361,56 +361,56 @@ static u8 isa_ctrl_read (struct controller *ctlr_ptr, u8 offset)
|
||||
|
||||
start_address = ctlr_ptr->u.isa_ctlr.io_start;
|
||||
end_address = ctlr_ptr->u.isa_ctlr.io_end;
|
||||
data = inb (start_address + offset);
|
||||
data = inb(start_address + offset);
|
||||
return data;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Write to ISA type HPC
|
||||
//--------------------------------------------------------------
|
||||
static void isa_ctrl_write (struct controller *ctlr_ptr, u8 offset, u8 data)
|
||||
static void isa_ctrl_write(struct controller *ctlr_ptr, u8 offset, u8 data)
|
||||
{
|
||||
u16 start_address;
|
||||
u16 port_address;
|
||||
|
||||
start_address = ctlr_ptr->u.isa_ctlr.io_start;
|
||||
port_address = start_address + (u16) offset;
|
||||
outb (data, port_address);
|
||||
outb(data, port_address);
|
||||
}
|
||||
|
||||
static u8 pci_ctrl_read (struct controller *ctrl, u8 offset)
|
||||
static u8 pci_ctrl_read(struct controller *ctrl, u8 offset)
|
||||
{
|
||||
u8 data = 0x00;
|
||||
debug ("inside pci_ctrl_read\n");
|
||||
debug("inside pci_ctrl_read\n");
|
||||
if (ctrl->ctrl_dev)
|
||||
pci_read_config_byte (ctrl->ctrl_dev, HPC_PCI_OFFSET + offset, &data);
|
||||
pci_read_config_byte(ctrl->ctrl_dev, HPC_PCI_OFFSET + offset, &data);
|
||||
return data;
|
||||
}
|
||||
|
||||
static u8 pci_ctrl_write (struct controller *ctrl, u8 offset, u8 data)
|
||||
static u8 pci_ctrl_write(struct controller *ctrl, u8 offset, u8 data)
|
||||
{
|
||||
u8 rc = -ENODEV;
|
||||
debug ("inside pci_ctrl_write\n");
|
||||
debug("inside pci_ctrl_write\n");
|
||||
if (ctrl->ctrl_dev) {
|
||||
pci_write_config_byte (ctrl->ctrl_dev, HPC_PCI_OFFSET + offset, data);
|
||||
pci_write_config_byte(ctrl->ctrl_dev, HPC_PCI_OFFSET + offset, data);
|
||||
rc = 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static u8 ctrl_read (struct controller *ctlr, void __iomem *base, u8 offset)
|
||||
static u8 ctrl_read(struct controller *ctlr, void __iomem *base, u8 offset)
|
||||
{
|
||||
u8 rc;
|
||||
switch (ctlr->ctlr_type) {
|
||||
case 0:
|
||||
rc = isa_ctrl_read (ctlr, offset);
|
||||
rc = isa_ctrl_read(ctlr, offset);
|
||||
break;
|
||||
case 1:
|
||||
rc = pci_ctrl_read (ctlr, offset);
|
||||
rc = pci_ctrl_read(ctlr, offset);
|
||||
break;
|
||||
case 2:
|
||||
case 4:
|
||||
rc = i2c_ctrl_read (ctlr, base, offset);
|
||||
rc = i2c_ctrl_read(ctlr, base, offset);
|
||||
break;
|
||||
default:
|
||||
return -ENODEV;
|
||||
@ -418,7 +418,7 @@ static u8 ctrl_read (struct controller *ctlr, void __iomem *base, u8 offset)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static u8 ctrl_write (struct controller *ctlr, void __iomem *base, u8 offset, u8 data)
|
||||
static u8 ctrl_write(struct controller *ctlr, void __iomem *base, u8 offset, u8 data)
|
||||
{
|
||||
u8 rc = 0;
|
||||
switch (ctlr->ctlr_type) {
|
||||
@ -426,7 +426,7 @@ static u8 ctrl_write (struct controller *ctlr, void __iomem *base, u8 offset, u8
|
||||
isa_ctrl_write(ctlr, offset, data);
|
||||
break;
|
||||
case 1:
|
||||
rc = pci_ctrl_write (ctlr, offset, data);
|
||||
rc = pci_ctrl_write(ctlr, offset, data);
|
||||
break;
|
||||
case 2:
|
||||
case 4:
|
||||
@ -444,7 +444,7 @@ static u8 ctrl_write (struct controller *ctlr, void __iomem *base, u8 offset, u8
|
||||
*
|
||||
* Return index, HPC_ERROR
|
||||
*---------------------------------------------------------------------*/
|
||||
static u8 hpc_writecmdtoindex (u8 cmd, u8 index)
|
||||
static u8 hpc_writecmdtoindex(u8 cmd, u8 index)
|
||||
{
|
||||
u8 rc;
|
||||
|
||||
@ -476,7 +476,7 @@ static u8 hpc_writecmdtoindex (u8 cmd, u8 index)
|
||||
break;
|
||||
|
||||
default:
|
||||
err ("hpc_writecmdtoindex - Error invalid cmd[%x]\n", cmd);
|
||||
err("hpc_writecmdtoindex - Error invalid cmd[%x]\n", cmd);
|
||||
rc = HPC_ERROR;
|
||||
}
|
||||
|
||||
@ -490,7 +490,7 @@ static u8 hpc_writecmdtoindex (u8 cmd, u8 index)
|
||||
*
|
||||
* Return index, HPC_ERROR
|
||||
*---------------------------------------------------------------------*/
|
||||
static u8 hpc_readcmdtoindex (u8 cmd, u8 index)
|
||||
static u8 hpc_readcmdtoindex(u8 cmd, u8 index)
|
||||
{
|
||||
u8 rc;
|
||||
|
||||
@ -533,78 +533,77 @@ static u8 hpc_readcmdtoindex (u8 cmd, u8 index)
|
||||
*
|
||||
* Return 0 or error codes
|
||||
*---------------------------------------------------------------------*/
|
||||
int ibmphp_hpc_readslot (struct slot *pslot, u8 cmd, u8 *pstatus)
|
||||
int ibmphp_hpc_readslot(struct slot *pslot, u8 cmd, u8 *pstatus)
|
||||
{
|
||||
void __iomem *wpg_bbar = NULL;
|
||||
struct controller *ctlr_ptr;
|
||||
struct list_head *pslotlist;
|
||||
u8 index, status;
|
||||
int rc = 0;
|
||||
int busindex;
|
||||
|
||||
debug_polling ("%s - Entry pslot[%p] cmd[%x] pstatus[%p]\n", __func__, pslot, cmd, pstatus);
|
||||
debug_polling("%s - Entry pslot[%p] cmd[%x] pstatus[%p]\n", __func__, pslot, cmd, pstatus);
|
||||
|
||||
if ((pslot == NULL)
|
||||
|| ((pstatus == NULL) && (cmd != READ_ALLSTAT) && (cmd != READ_BUSSTATUS))) {
|
||||
rc = -EINVAL;
|
||||
err ("%s - Error invalid pointer, rc[%d]\n", __func__, rc);
|
||||
err("%s - Error invalid pointer, rc[%d]\n", __func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (cmd == READ_BUSSTATUS) {
|
||||
busindex = ibmphp_get_bus_index (pslot->bus);
|
||||
busindex = ibmphp_get_bus_index(pslot->bus);
|
||||
if (busindex < 0) {
|
||||
rc = -EINVAL;
|
||||
err ("%s - Exit Error:invalid bus, rc[%d]\n", __func__, rc);
|
||||
err("%s - Exit Error:invalid bus, rc[%d]\n", __func__, rc);
|
||||
return rc;
|
||||
} else
|
||||
index = (u8) busindex;
|
||||
} else
|
||||
index = pslot->ctlr_index;
|
||||
|
||||
index = hpc_readcmdtoindex (cmd, index);
|
||||
index = hpc_readcmdtoindex(cmd, index);
|
||||
|
||||
if (index == HPC_ERROR) {
|
||||
rc = -EINVAL;
|
||||
err ("%s - Exit Error:invalid index, rc[%d]\n", __func__, rc);
|
||||
err("%s - Exit Error:invalid index, rc[%d]\n", __func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
ctlr_ptr = pslot->ctrl;
|
||||
|
||||
get_hpc_access ();
|
||||
get_hpc_access();
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// map physical address to logical address
|
||||
//--------------------------------------------------------------------
|
||||
if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4))
|
||||
wpg_bbar = ioremap (ctlr_ptr->u.wpeg_ctlr.wpegbbar, WPG_I2C_IOREMAP_SIZE);
|
||||
wpg_bbar = ioremap(ctlr_ptr->u.wpeg_ctlr.wpegbbar, WPG_I2C_IOREMAP_SIZE);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// check controller status before reading
|
||||
//--------------------------------------------------------------------
|
||||
rc = hpc_wait_ctlr_notworking (HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar, &status);
|
||||
rc = hpc_wait_ctlr_notworking(HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar, &status);
|
||||
if (!rc) {
|
||||
switch (cmd) {
|
||||
case READ_ALLSTAT:
|
||||
// update the slot structure
|
||||
pslot->ctrl->status = status;
|
||||
pslot->status = ctrl_read (ctlr_ptr, wpg_bbar, index);
|
||||
rc = hpc_wait_ctlr_notworking (HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar,
|
||||
pslot->status = ctrl_read(ctlr_ptr, wpg_bbar, index);
|
||||
rc = hpc_wait_ctlr_notworking(HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar,
|
||||
&status);
|
||||
if (!rc)
|
||||
pslot->ext_status = ctrl_read (ctlr_ptr, wpg_bbar, index + WPG_1ST_EXTSLOT_INDEX);
|
||||
pslot->ext_status = ctrl_read(ctlr_ptr, wpg_bbar, index + WPG_1ST_EXTSLOT_INDEX);
|
||||
|
||||
break;
|
||||
|
||||
case READ_SLOTSTATUS:
|
||||
// DO NOT update the slot structure
|
||||
*pstatus = ctrl_read (ctlr_ptr, wpg_bbar, index);
|
||||
*pstatus = ctrl_read(ctlr_ptr, wpg_bbar, index);
|
||||
break;
|
||||
|
||||
case READ_EXTSLOTSTATUS:
|
||||
// DO NOT update the slot structure
|
||||
*pstatus = ctrl_read (ctlr_ptr, wpg_bbar, index);
|
||||
*pstatus = ctrl_read(ctlr_ptr, wpg_bbar, index);
|
||||
break;
|
||||
|
||||
case READ_CTLRSTATUS:
|
||||
@ -613,36 +612,36 @@ int ibmphp_hpc_readslot (struct slot *pslot, u8 cmd, u8 *pstatus)
|
||||
break;
|
||||
|
||||
case READ_BUSSTATUS:
|
||||
pslot->busstatus = ctrl_read (ctlr_ptr, wpg_bbar, index);
|
||||
pslot->busstatus = ctrl_read(ctlr_ptr, wpg_bbar, index);
|
||||
break;
|
||||
case READ_REVLEVEL:
|
||||
*pstatus = ctrl_read (ctlr_ptr, wpg_bbar, index);
|
||||
*pstatus = ctrl_read(ctlr_ptr, wpg_bbar, index);
|
||||
break;
|
||||
case READ_HPCOPTIONS:
|
||||
*pstatus = ctrl_read (ctlr_ptr, wpg_bbar, index);
|
||||
*pstatus = ctrl_read(ctlr_ptr, wpg_bbar, index);
|
||||
break;
|
||||
case READ_SLOTLATCHLOWREG:
|
||||
// DO NOT update the slot structure
|
||||
*pstatus = ctrl_read (ctlr_ptr, wpg_bbar, index);
|
||||
*pstatus = ctrl_read(ctlr_ptr, wpg_bbar, index);
|
||||
break;
|
||||
|
||||
// Not used
|
||||
case READ_ALLSLOT:
|
||||
list_for_each (pslotlist, &ibmphp_slot_head) {
|
||||
pslot = list_entry (pslotlist, struct slot, ibm_slot_list);
|
||||
list_for_each_entry(pslot, &ibmphp_slot_head,
|
||||
ibm_slot_list) {
|
||||
index = pslot->ctlr_index;
|
||||
rc = hpc_wait_ctlr_notworking (HPC_CTLR_WORKING_TOUT, ctlr_ptr,
|
||||
rc = hpc_wait_ctlr_notworking(HPC_CTLR_WORKING_TOUT, ctlr_ptr,
|
||||
wpg_bbar, &status);
|
||||
if (!rc) {
|
||||
pslot->status = ctrl_read (ctlr_ptr, wpg_bbar, index);
|
||||
rc = hpc_wait_ctlr_notworking (HPC_CTLR_WORKING_TOUT,
|
||||
pslot->status = ctrl_read(ctlr_ptr, wpg_bbar, index);
|
||||
rc = hpc_wait_ctlr_notworking(HPC_CTLR_WORKING_TOUT,
|
||||
ctlr_ptr, wpg_bbar, &status);
|
||||
if (!rc)
|
||||
pslot->ext_status =
|
||||
ctrl_read (ctlr_ptr, wpg_bbar,
|
||||
ctrl_read(ctlr_ptr, wpg_bbar,
|
||||
index + WPG_1ST_EXTSLOT_INDEX);
|
||||
} else {
|
||||
err ("%s - Error ctrl_read failed\n", __func__);
|
||||
err("%s - Error ctrl_read failed\n", __func__);
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
@ -659,11 +658,11 @@ int ibmphp_hpc_readslot (struct slot *pslot, u8 cmd, u8 *pstatus)
|
||||
|
||||
// remove physical to logical address mapping
|
||||
if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4))
|
||||
iounmap (wpg_bbar);
|
||||
iounmap(wpg_bbar);
|
||||
|
||||
free_hpc_access ();
|
||||
free_hpc_access();
|
||||
|
||||
debug_polling ("%s - Exit rc[%d]\n", __func__, rc);
|
||||
debug_polling("%s - Exit rc[%d]\n", __func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -672,7 +671,7 @@ int ibmphp_hpc_readslot (struct slot *pslot, u8 cmd, u8 *pstatus)
|
||||
*
|
||||
* Action: issue a WRITE command to HPC
|
||||
*---------------------------------------------------------------------*/
|
||||
int ibmphp_hpc_writeslot (struct slot *pslot, u8 cmd)
|
||||
int ibmphp_hpc_writeslot(struct slot *pslot, u8 cmd)
|
||||
{
|
||||
void __iomem *wpg_bbar = NULL;
|
||||
struct controller *ctlr_ptr;
|
||||
@ -682,55 +681,55 @@ int ibmphp_hpc_writeslot (struct slot *pslot, u8 cmd)
|
||||
int rc = 0;
|
||||
int timeout;
|
||||
|
||||
debug_polling ("%s - Entry pslot[%p] cmd[%x]\n", __func__, pslot, cmd);
|
||||
debug_polling("%s - Entry pslot[%p] cmd[%x]\n", __func__, pslot, cmd);
|
||||
if (pslot == NULL) {
|
||||
rc = -EINVAL;
|
||||
err ("%s - Error Exit rc[%d]\n", __func__, rc);
|
||||
err("%s - Error Exit rc[%d]\n", __func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if ((cmd == HPC_BUS_33CONVMODE) || (cmd == HPC_BUS_66CONVMODE) ||
|
||||
(cmd == HPC_BUS_66PCIXMODE) || (cmd == HPC_BUS_100PCIXMODE) ||
|
||||
(cmd == HPC_BUS_133PCIXMODE)) {
|
||||
busindex = ibmphp_get_bus_index (pslot->bus);
|
||||
busindex = ibmphp_get_bus_index(pslot->bus);
|
||||
if (busindex < 0) {
|
||||
rc = -EINVAL;
|
||||
err ("%s - Exit Error:invalid bus, rc[%d]\n", __func__, rc);
|
||||
err("%s - Exit Error:invalid bus, rc[%d]\n", __func__, rc);
|
||||
return rc;
|
||||
} else
|
||||
index = (u8) busindex;
|
||||
} else
|
||||
index = pslot->ctlr_index;
|
||||
|
||||
index = hpc_writecmdtoindex (cmd, index);
|
||||
index = hpc_writecmdtoindex(cmd, index);
|
||||
|
||||
if (index == HPC_ERROR) {
|
||||
rc = -EINVAL;
|
||||
err ("%s - Error Exit rc[%d]\n", __func__, rc);
|
||||
err("%s - Error Exit rc[%d]\n", __func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
ctlr_ptr = pslot->ctrl;
|
||||
|
||||
get_hpc_access ();
|
||||
get_hpc_access();
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// map physical address to logical address
|
||||
//--------------------------------------------------------------------
|
||||
if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4)) {
|
||||
wpg_bbar = ioremap (ctlr_ptr->u.wpeg_ctlr.wpegbbar, WPG_I2C_IOREMAP_SIZE);
|
||||
wpg_bbar = ioremap(ctlr_ptr->u.wpeg_ctlr.wpegbbar, WPG_I2C_IOREMAP_SIZE);
|
||||
|
||||
debug ("%s - ctlr id[%x] physical[%lx] logical[%lx] i2c[%x]\n", __func__,
|
||||
debug("%s - ctlr id[%x] physical[%lx] logical[%lx] i2c[%x]\n", __func__,
|
||||
ctlr_ptr->ctlr_id, (ulong) (ctlr_ptr->u.wpeg_ctlr.wpegbbar), (ulong) wpg_bbar,
|
||||
ctlr_ptr->u.wpeg_ctlr.i2c_addr);
|
||||
}
|
||||
//--------------------------------------------------------------------
|
||||
// check controller status before writing
|
||||
//--------------------------------------------------------------------
|
||||
rc = hpc_wait_ctlr_notworking (HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar, &status);
|
||||
rc = hpc_wait_ctlr_notworking(HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar, &status);
|
||||
if (!rc) {
|
||||
|
||||
ctrl_write (ctlr_ptr, wpg_bbar, index, cmd);
|
||||
ctrl_write(ctlr_ptr, wpg_bbar, index, cmd);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// check controller is still not working on the command
|
||||
@ -738,11 +737,11 @@ int ibmphp_hpc_writeslot (struct slot *pslot, u8 cmd)
|
||||
timeout = CMD_COMPLETE_TOUT_SEC;
|
||||
done = 0;
|
||||
while (!done) {
|
||||
rc = hpc_wait_ctlr_notworking (HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar,
|
||||
rc = hpc_wait_ctlr_notworking(HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar,
|
||||
&status);
|
||||
if (!rc) {
|
||||
if (NEEDTOCHECK_CMDSTATUS (cmd)) {
|
||||
if (CTLR_FINISHED (status) == HPC_CTLR_FINISHED_YES)
|
||||
if (NEEDTOCHECK_CMDSTATUS(cmd)) {
|
||||
if (CTLR_FINISHED(status) == HPC_CTLR_FINISHED_YES)
|
||||
done = 1;
|
||||
} else
|
||||
done = 1;
|
||||
@ -751,7 +750,7 @@ int ibmphp_hpc_writeslot (struct slot *pslot, u8 cmd)
|
||||
msleep(1000);
|
||||
if (timeout < 1) {
|
||||
done = 1;
|
||||
err ("%s - Error command complete timeout\n", __func__);
|
||||
err("%s - Error command complete timeout\n", __func__);
|
||||
rc = -EFAULT;
|
||||
} else
|
||||
timeout--;
|
||||
@ -763,10 +762,10 @@ int ibmphp_hpc_writeslot (struct slot *pslot, u8 cmd)
|
||||
|
||||
// remove physical to logical address mapping
|
||||
if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4))
|
||||
iounmap (wpg_bbar);
|
||||
free_hpc_access ();
|
||||
iounmap(wpg_bbar);
|
||||
free_hpc_access();
|
||||
|
||||
debug_polling ("%s - Exit rc[%d]\n", __func__, rc);
|
||||
debug_polling("%s - Exit rc[%d]\n", __func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -775,7 +774,7 @@ int ibmphp_hpc_writeslot (struct slot *pslot, u8 cmd)
|
||||
*
|
||||
* Action: make sure only one process can access HPC at one time
|
||||
*---------------------------------------------------------------------*/
|
||||
static void get_hpc_access (void)
|
||||
static void get_hpc_access(void)
|
||||
{
|
||||
mutex_lock(&sem_hpcaccess);
|
||||
}
|
||||
@ -783,7 +782,7 @@ static void get_hpc_access (void)
|
||||
/*----------------------------------------------------------------------
|
||||
* Name: free_hpc_access()
|
||||
*---------------------------------------------------------------------*/
|
||||
void free_hpc_access (void)
|
||||
void free_hpc_access(void)
|
||||
{
|
||||
mutex_unlock(&sem_hpcaccess);
|
||||
}
|
||||
@ -793,21 +792,21 @@ void free_hpc_access (void)
|
||||
*
|
||||
* Action: make sure only one process can change the data structure
|
||||
*---------------------------------------------------------------------*/
|
||||
void ibmphp_lock_operations (void)
|
||||
void ibmphp_lock_operations(void)
|
||||
{
|
||||
down (&semOperations);
|
||||
down(&semOperations);
|
||||
to_debug = 1;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
* Name: ibmphp_unlock_operations()
|
||||
*---------------------------------------------------------------------*/
|
||||
void ibmphp_unlock_operations (void)
|
||||
void ibmphp_unlock_operations(void)
|
||||
{
|
||||
debug ("%s - Entry\n", __func__);
|
||||
up (&semOperations);
|
||||
debug("%s - Entry\n", __func__);
|
||||
up(&semOperations);
|
||||
to_debug = 0;
|
||||
debug ("%s - Exit\n", __func__);
|
||||
debug("%s - Exit\n", __func__);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
@ -820,7 +819,6 @@ static int poll_hpc(void *data)
|
||||
{
|
||||
struct slot myslot;
|
||||
struct slot *pslot = NULL;
|
||||
struct list_head *pslotlist;
|
||||
int rc;
|
||||
int poll_state = POLL_LATCH_REGISTER;
|
||||
u8 oldlatchlow = 0x00;
|
||||
@ -828,28 +826,28 @@ static int poll_hpc(void *data)
|
||||
int poll_count = 0;
|
||||
u8 ctrl_count = 0x00;
|
||||
|
||||
debug ("%s - Entry\n", __func__);
|
||||
debug("%s - Entry\n", __func__);
|
||||
|
||||
while (!kthread_should_stop()) {
|
||||
/* try to get the lock to do some kind of hardware access */
|
||||
down (&semOperations);
|
||||
down(&semOperations);
|
||||
|
||||
switch (poll_state) {
|
||||
case POLL_LATCH_REGISTER:
|
||||
oldlatchlow = curlatchlow;
|
||||
ctrl_count = 0x00;
|
||||
list_for_each (pslotlist, &ibmphp_slot_head) {
|
||||
list_for_each_entry(pslot, &ibmphp_slot_head,
|
||||
ibm_slot_list) {
|
||||
if (ctrl_count >= ibmphp_get_total_controllers())
|
||||
break;
|
||||
pslot = list_entry (pslotlist, struct slot, ibm_slot_list);
|
||||
if (pslot->ctrl->ctlr_relative_id == ctrl_count) {
|
||||
ctrl_count++;
|
||||
if (READ_SLOT_LATCH (pslot->ctrl)) {
|
||||
rc = ibmphp_hpc_readslot (pslot,
|
||||
if (READ_SLOT_LATCH(pslot->ctrl)) {
|
||||
rc = ibmphp_hpc_readslot(pslot,
|
||||
READ_SLOTLATCHLOWREG,
|
||||
&curlatchlow);
|
||||
if (oldlatchlow != curlatchlow)
|
||||
process_changeinlatch (oldlatchlow,
|
||||
process_changeinlatch(oldlatchlow,
|
||||
curlatchlow,
|
||||
pslot->ctrl);
|
||||
}
|
||||
@ -859,25 +857,25 @@ static int poll_hpc(void *data)
|
||||
poll_state = POLL_SLEEP;
|
||||
break;
|
||||
case POLL_SLOTS:
|
||||
list_for_each (pslotlist, &ibmphp_slot_head) {
|
||||
pslot = list_entry (pslotlist, struct slot, ibm_slot_list);
|
||||
list_for_each_entry(pslot, &ibmphp_slot_head,
|
||||
ibm_slot_list) {
|
||||
// make a copy of the old status
|
||||
memcpy ((void *) &myslot, (void *) pslot,
|
||||
sizeof (struct slot));
|
||||
rc = ibmphp_hpc_readslot (pslot, READ_ALLSTAT, NULL);
|
||||
memcpy((void *) &myslot, (void *) pslot,
|
||||
sizeof(struct slot));
|
||||
rc = ibmphp_hpc_readslot(pslot, READ_ALLSTAT, NULL);
|
||||
if ((myslot.status != pslot->status)
|
||||
|| (myslot.ext_status != pslot->ext_status))
|
||||
process_changeinstatus (pslot, &myslot);
|
||||
process_changeinstatus(pslot, &myslot);
|
||||
}
|
||||
ctrl_count = 0x00;
|
||||
list_for_each (pslotlist, &ibmphp_slot_head) {
|
||||
list_for_each_entry(pslot, &ibmphp_slot_head,
|
||||
ibm_slot_list) {
|
||||
if (ctrl_count >= ibmphp_get_total_controllers())
|
||||
break;
|
||||
pslot = list_entry (pslotlist, struct slot, ibm_slot_list);
|
||||
if (pslot->ctrl->ctlr_relative_id == ctrl_count) {
|
||||
ctrl_count++;
|
||||
if (READ_SLOT_LATCH (pslot->ctrl))
|
||||
rc = ibmphp_hpc_readslot (pslot,
|
||||
if (READ_SLOT_LATCH(pslot->ctrl))
|
||||
rc = ibmphp_hpc_readslot(pslot,
|
||||
READ_SLOTLATCHLOWREG,
|
||||
&curlatchlow);
|
||||
}
|
||||
@ -887,13 +885,13 @@ static int poll_hpc(void *data)
|
||||
break;
|
||||
case POLL_SLEEP:
|
||||
/* don't sleep with a lock on the hardware */
|
||||
up (&semOperations);
|
||||
up(&semOperations);
|
||||
msleep(POLL_INTERVAL_SEC * 1000);
|
||||
|
||||
if (kthread_should_stop())
|
||||
goto out_sleep;
|
||||
|
||||
down (&semOperations);
|
||||
down(&semOperations);
|
||||
|
||||
if (poll_count >= POLL_LATCH_CNT) {
|
||||
poll_count = 0;
|
||||
@ -903,13 +901,13 @@ static int poll_hpc(void *data)
|
||||
break;
|
||||
}
|
||||
/* give up the hardware semaphore */
|
||||
up (&semOperations);
|
||||
up(&semOperations);
|
||||
/* sleep for a short time just for good measure */
|
||||
out_sleep:
|
||||
msleep(100);
|
||||
}
|
||||
up (&sem_exit);
|
||||
debug ("%s - Exit\n", __func__);
|
||||
up(&sem_exit);
|
||||
debug("%s - Exit\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -929,14 +927,14 @@ out_sleep:
|
||||
*
|
||||
* Notes:
|
||||
*---------------------------------------------------------------------*/
|
||||
static int process_changeinstatus (struct slot *pslot, struct slot *poldslot)
|
||||
static int process_changeinstatus(struct slot *pslot, struct slot *poldslot)
|
||||
{
|
||||
u8 status;
|
||||
int rc = 0;
|
||||
u8 disable = 0;
|
||||
u8 update = 0;
|
||||
|
||||
debug ("process_changeinstatus - Entry pslot[%p], poldslot[%p]\n", pslot, poldslot);
|
||||
debug("process_changeinstatus - Entry pslot[%p], poldslot[%p]\n", pslot, poldslot);
|
||||
|
||||
// bit 0 - HPC_SLOT_POWER
|
||||
if ((pslot->status & 0x01) != (poldslot->status & 0x01))
|
||||
@ -958,7 +956,7 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot)
|
||||
// bit 5 - HPC_SLOT_PWRGD
|
||||
if ((pslot->status & 0x20) != (poldslot->status & 0x20))
|
||||
// OFF -> ON: ignore, ON -> OFF: disable slot
|
||||
if ((poldslot->status & 0x20) && (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status)))
|
||||
if ((poldslot->status & 0x20) && (SLOT_CONNECT(poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT(poldslot->status)))
|
||||
disable = 1;
|
||||
|
||||
// bit 6 - HPC_SLOT_BUS_SPEED
|
||||
@ -969,20 +967,20 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot)
|
||||
update = 1;
|
||||
// OPEN -> CLOSE
|
||||
if (pslot->status & 0x80) {
|
||||
if (SLOT_PWRGD (pslot->status)) {
|
||||
if (SLOT_PWRGD(pslot->status)) {
|
||||
// power goes on and off after closing latch
|
||||
// check again to make sure power is still ON
|
||||
msleep(1000);
|
||||
rc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &status);
|
||||
if (SLOT_PWRGD (status))
|
||||
rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS, &status);
|
||||
if (SLOT_PWRGD(status))
|
||||
update = 1;
|
||||
else // overwrite power in pslot to OFF
|
||||
pslot->status &= ~HPC_SLOT_POWER;
|
||||
}
|
||||
}
|
||||
// CLOSE -> OPEN
|
||||
else if ((SLOT_PWRGD (poldslot->status) == HPC_SLOT_PWRGD_GOOD)
|
||||
&& (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status))) {
|
||||
else if ((SLOT_PWRGD(poldslot->status) == HPC_SLOT_PWRGD_GOOD)
|
||||
&& (SLOT_CONNECT(poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT(poldslot->status))) {
|
||||
disable = 1;
|
||||
}
|
||||
// else - ignore
|
||||
@ -992,15 +990,15 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot)
|
||||
update = 1;
|
||||
|
||||
if (disable) {
|
||||
debug ("process_changeinstatus - disable slot\n");
|
||||
debug("process_changeinstatus - disable slot\n");
|
||||
pslot->flag = 0;
|
||||
rc = ibmphp_do_disable_slot (pslot);
|
||||
rc = ibmphp_do_disable_slot(pslot);
|
||||
}
|
||||
|
||||
if (update || disable)
|
||||
ibmphp_update_slot_info (pslot);
|
||||
ibmphp_update_slot_info(pslot);
|
||||
|
||||
debug ("%s - Exit rc[%d] disable[%x] update[%x]\n", __func__, rc, disable, update);
|
||||
debug("%s - Exit rc[%d] disable[%x] update[%x]\n", __func__, rc, disable, update);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -1015,32 +1013,32 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot)
|
||||
* Return 0 or error codes
|
||||
* Value:
|
||||
*---------------------------------------------------------------------*/
|
||||
static int process_changeinlatch (u8 old, u8 new, struct controller *ctrl)
|
||||
static int process_changeinlatch(u8 old, u8 new, struct controller *ctrl)
|
||||
{
|
||||
struct slot myslot, *pslot;
|
||||
u8 i;
|
||||
u8 mask;
|
||||
int rc = 0;
|
||||
|
||||
debug ("%s - Entry old[%x], new[%x]\n", __func__, old, new);
|
||||
debug("%s - Entry old[%x], new[%x]\n", __func__, old, new);
|
||||
// bit 0 reserved, 0 is LSB, check bit 1-6 for 6 slots
|
||||
|
||||
for (i = ctrl->starting_slot_num; i <= ctrl->ending_slot_num; i++) {
|
||||
mask = 0x01 << i;
|
||||
if ((mask & old) != (mask & new)) {
|
||||
pslot = ibmphp_get_slot_from_physical_num (i);
|
||||
pslot = ibmphp_get_slot_from_physical_num(i);
|
||||
if (pslot) {
|
||||
memcpy ((void *) &myslot, (void *) pslot, sizeof (struct slot));
|
||||
rc = ibmphp_hpc_readslot (pslot, READ_ALLSTAT, NULL);
|
||||
debug ("%s - call process_changeinstatus for slot[%d]\n", __func__, i);
|
||||
process_changeinstatus (pslot, &myslot);
|
||||
memcpy((void *) &myslot, (void *) pslot, sizeof(struct slot));
|
||||
rc = ibmphp_hpc_readslot(pslot, READ_ALLSTAT, NULL);
|
||||
debug("%s - call process_changeinstatus for slot[%d]\n", __func__, i);
|
||||
process_changeinstatus(pslot, &myslot);
|
||||
} else {
|
||||
rc = -EINVAL;
|
||||
err ("%s - Error bad pointer for slot[%d]\n", __func__, i);
|
||||
err("%s - Error bad pointer for slot[%d]\n", __func__, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
debug ("%s - Exit rc[%d]\n", __func__, rc);
|
||||
debug("%s - Exit rc[%d]\n", __func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -1049,13 +1047,13 @@ static int process_changeinlatch (u8 old, u8 new, struct controller *ctrl)
|
||||
*
|
||||
* Action: start polling thread
|
||||
*---------------------------------------------------------------------*/
|
||||
int __init ibmphp_hpc_start_poll_thread (void)
|
||||
int __init ibmphp_hpc_start_poll_thread(void)
|
||||
{
|
||||
debug ("%s - Entry\n", __func__);
|
||||
debug("%s - Entry\n", __func__);
|
||||
|
||||
ibmphp_poll_thread = kthread_run(poll_hpc, NULL, "hpc_poll");
|
||||
if (IS_ERR(ibmphp_poll_thread)) {
|
||||
err ("%s - Error, thread not started\n", __func__);
|
||||
err("%s - Error, thread not started\n", __func__);
|
||||
return PTR_ERR(ibmphp_poll_thread);
|
||||
}
|
||||
return 0;
|
||||
@ -1066,30 +1064,30 @@ int __init ibmphp_hpc_start_poll_thread (void)
|
||||
*
|
||||
* Action: stop polling thread and cleanup
|
||||
*---------------------------------------------------------------------*/
|
||||
void __exit ibmphp_hpc_stop_poll_thread (void)
|
||||
void __exit ibmphp_hpc_stop_poll_thread(void)
|
||||
{
|
||||
debug ("%s - Entry\n", __func__);
|
||||
debug("%s - Entry\n", __func__);
|
||||
|
||||
kthread_stop(ibmphp_poll_thread);
|
||||
debug ("before locking operations \n");
|
||||
ibmphp_lock_operations ();
|
||||
debug ("after locking operations \n");
|
||||
debug("before locking operations\n");
|
||||
ibmphp_lock_operations();
|
||||
debug("after locking operations\n");
|
||||
|
||||
// wait for poll thread to exit
|
||||
debug ("before sem_exit down \n");
|
||||
down (&sem_exit);
|
||||
debug ("after sem_exit down \n");
|
||||
debug("before sem_exit down\n");
|
||||
down(&sem_exit);
|
||||
debug("after sem_exit down\n");
|
||||
|
||||
// cleanup
|
||||
debug ("before free_hpc_access \n");
|
||||
free_hpc_access ();
|
||||
debug ("after free_hpc_access \n");
|
||||
ibmphp_unlock_operations ();
|
||||
debug ("after unlock operations \n");
|
||||
up (&sem_exit);
|
||||
debug ("after sem exit up\n");
|
||||
debug("before free_hpc_access\n");
|
||||
free_hpc_access();
|
||||
debug("after free_hpc_access\n");
|
||||
ibmphp_unlock_operations();
|
||||
debug("after unlock operations\n");
|
||||
up(&sem_exit);
|
||||
debug("after sem exit up\n");
|
||||
|
||||
debug ("%s - Exit\n", __func__);
|
||||
debug("%s - Exit\n", __func__);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
@ -1100,32 +1098,32 @@ void __exit ibmphp_hpc_stop_poll_thread (void)
|
||||
* Return 0, HPC_ERROR
|
||||
* Value:
|
||||
*---------------------------------------------------------------------*/
|
||||
static int hpc_wait_ctlr_notworking (int timeout, struct controller *ctlr_ptr, void __iomem *wpg_bbar,
|
||||
static int hpc_wait_ctlr_notworking(int timeout, struct controller *ctlr_ptr, void __iomem *wpg_bbar,
|
||||
u8 *pstatus)
|
||||
{
|
||||
int rc = 0;
|
||||
u8 done = 0;
|
||||
|
||||
debug_polling ("hpc_wait_ctlr_notworking - Entry timeout[%d]\n", timeout);
|
||||
debug_polling("hpc_wait_ctlr_notworking - Entry timeout[%d]\n", timeout);
|
||||
|
||||
while (!done) {
|
||||
*pstatus = ctrl_read (ctlr_ptr, wpg_bbar, WPG_CTLR_INDEX);
|
||||
*pstatus = ctrl_read(ctlr_ptr, wpg_bbar, WPG_CTLR_INDEX);
|
||||
if (*pstatus == HPC_ERROR) {
|
||||
rc = HPC_ERROR;
|
||||
done = 1;
|
||||
}
|
||||
if (CTLR_WORKING (*pstatus) == HPC_CTLR_WORKING_NO)
|
||||
if (CTLR_WORKING(*pstatus) == HPC_CTLR_WORKING_NO)
|
||||
done = 1;
|
||||
if (!done) {
|
||||
msleep(1000);
|
||||
if (timeout < 1) {
|
||||
done = 1;
|
||||
err ("HPCreadslot - Error ctlr timeout\n");
|
||||
err("HPCreadslot - Error ctlr timeout\n");
|
||||
rc = HPC_ERROR;
|
||||
} else
|
||||
timeout--;
|
||||
}
|
||||
}
|
||||
debug_polling ("hpc_wait_ctlr_notworking - Exit rc[%x] status[%x]\n", rc, *pstatus);
|
||||
debug_polling("hpc_wait_ctlr_notworking - Exit rc[%x] status[%x]\n", rc, *pstatus);
|
||||
return rc;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -45,10 +45,10 @@
|
||||
|
||||
#define MY_NAME "pci_hotplug"
|
||||
|
||||
#define dbg(fmt, arg...) do { if (debug) printk(KERN_DEBUG "%s: %s: " fmt , MY_NAME , __func__ , ## arg); } while (0)
|
||||
#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
|
||||
#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)
|
||||
#define dbg(fmt, arg...) do { if (debug) printk(KERN_DEBUG "%s: %s: " fmt, MY_NAME, __func__, ## arg); } while (0)
|
||||
#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME, ## arg)
|
||||
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME, ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME, ## arg)
|
||||
|
||||
|
||||
/* local variables */
|
||||
@ -226,7 +226,7 @@ static ssize_t test_write_file(struct pci_slot *pci_slot, const char *buf,
|
||||
u32 test;
|
||||
int retval = 0;
|
||||
|
||||
ltest = simple_strtoul (buf, NULL, 10);
|
||||
ltest = simple_strtoul(buf, NULL, 10);
|
||||
test = (u32)(ltest & 0xffffffff);
|
||||
dbg("test = %d\n", test);
|
||||
|
||||
@ -396,10 +396,8 @@ static void fs_remove_slot(struct pci_slot *pci_slot)
|
||||
static struct hotplug_slot *get_slot_from_name(const char *name)
|
||||
{
|
||||
struct hotplug_slot *slot;
|
||||
struct list_head *tmp;
|
||||
|
||||
list_for_each(tmp, &pci_hotplug_slot_list) {
|
||||
slot = list_entry(tmp, struct hotplug_slot, slot_list);
|
||||
list_for_each_entry(slot, &pci_hotplug_slot_list, slot_list) {
|
||||
if (strcmp(hotplug_slot_name(slot), name) == 0)
|
||||
return slot;
|
||||
}
|
||||
|
@ -47,14 +47,14 @@ extern bool pciehp_debug;
|
||||
#define dbg(format, arg...) \
|
||||
do { \
|
||||
if (pciehp_debug) \
|
||||
printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); \
|
||||
printk(KERN_DEBUG "%s: " format, MY_NAME, ## arg); \
|
||||
} while (0)
|
||||
#define err(format, arg...) \
|
||||
printk(KERN_ERR "%s: " format, MY_NAME , ## arg)
|
||||
printk(KERN_ERR "%s: " format, MY_NAME, ## arg)
|
||||
#define info(format, arg...) \
|
||||
printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
|
||||
printk(KERN_INFO "%s: " format, MY_NAME, ## arg)
|
||||
#define warn(format, arg...) \
|
||||
printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
|
||||
printk(KERN_WARNING "%s: " format, MY_NAME, ## arg)
|
||||
|
||||
#define ctrl_dbg(ctrl, format, arg...) \
|
||||
do { \
|
||||
|
@ -62,14 +62,14 @@ MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if OSHP is missing");
|
||||
|
||||
#define PCIE_MODULE_NAME "pciehp"
|
||||
|
||||
static int set_attention_status (struct hotplug_slot *slot, u8 value);
|
||||
static int enable_slot (struct hotplug_slot *slot);
|
||||
static int disable_slot (struct hotplug_slot *slot);
|
||||
static int get_power_status (struct hotplug_slot *slot, u8 *value);
|
||||
static int get_attention_status (struct hotplug_slot *slot, u8 *value);
|
||||
static int get_latch_status (struct hotplug_slot *slot, u8 *value);
|
||||
static int get_adapter_status (struct hotplug_slot *slot, u8 *value);
|
||||
static int reset_slot (struct hotplug_slot *slot, int probe);
|
||||
static int set_attention_status(struct hotplug_slot *slot, u8 value);
|
||||
static int enable_slot(struct hotplug_slot *slot);
|
||||
static int disable_slot(struct hotplug_slot *slot);
|
||||
static int get_power_status(struct hotplug_slot *slot, u8 *value);
|
||||
static int get_attention_status(struct hotplug_slot *slot, u8 *value);
|
||||
static int get_latch_status(struct hotplug_slot *slot, u8 *value);
|
||||
static int get_adapter_status(struct hotplug_slot *slot, u8 *value);
|
||||
static int reset_slot(struct hotplug_slot *slot, int probe);
|
||||
|
||||
/**
|
||||
* release_slot - free up the memory used by a slot
|
||||
|
@ -511,7 +511,9 @@ int pciehp_sysfs_disable_slot(struct slot *p_slot)
|
||||
case STATIC_STATE:
|
||||
p_slot->state = POWEROFF_STATE;
|
||||
mutex_unlock(&p_slot->lock);
|
||||
mutex_lock(&p_slot->hotplug_lock);
|
||||
retval = pciehp_disable_slot(p_slot);
|
||||
mutex_unlock(&p_slot->hotplug_lock);
|
||||
mutex_lock(&p_slot->lock);
|
||||
p_slot->state = STATIC_STATE;
|
||||
break;
|
||||
|
@ -52,11 +52,11 @@ static LIST_HEAD(slot_list);
|
||||
do { \
|
||||
if (debug) \
|
||||
printk(KERN_DEBUG "%s: " format "\n", \
|
||||
MY_NAME , ## arg); \
|
||||
MY_NAME, ## arg); \
|
||||
} while (0)
|
||||
#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
|
||||
#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
|
||||
#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME, ## arg)
|
||||
#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME, ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME, ## arg)
|
||||
|
||||
/* local variables */
|
||||
static bool debug;
|
||||
@ -72,14 +72,14 @@ MODULE_LICENSE("GPL");
|
||||
module_param(debug, bool, 0644);
|
||||
MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
|
||||
|
||||
static int enable_slot (struct hotplug_slot *slot);
|
||||
static int disable_slot (struct hotplug_slot *slot);
|
||||
static int set_attention_status (struct hotplug_slot *slot, u8 value);
|
||||
static int hardware_test (struct hotplug_slot *slot, u32 value);
|
||||
static int get_power_status (struct hotplug_slot *slot, u8 *value);
|
||||
static int get_attention_status (struct hotplug_slot *slot, u8 *value);
|
||||
static int get_latch_status (struct hotplug_slot *slot, u8 *value);
|
||||
static int get_adapter_status (struct hotplug_slot *slot, u8 *value);
|
||||
static int enable_slot(struct hotplug_slot *slot);
|
||||
static int disable_slot(struct hotplug_slot *slot);
|
||||
static int set_attention_status(struct hotplug_slot *slot, u8 value);
|
||||
static int hardware_test(struct hotplug_slot *slot, u32 value);
|
||||
static int get_power_status(struct hotplug_slot *slot, u8 *value);
|
||||
static int get_attention_status(struct hotplug_slot *slot, u8 *value);
|
||||
static int get_latch_status(struct hotplug_slot *slot, u8 *value);
|
||||
static int get_adapter_status(struct hotplug_slot *slot, u8 *value);
|
||||
|
||||
static struct hotplug_slot_ops skel_hotplug_slot_ops = {
|
||||
.enable_slot = enable_slot,
|
||||
@ -321,17 +321,14 @@ error:
|
||||
|
||||
static void __exit cleanup_slots(void)
|
||||
{
|
||||
struct list_head *tmp;
|
||||
struct list_head *next;
|
||||
struct slot *slot;
|
||||
struct slot *slot, *next;
|
||||
|
||||
/*
|
||||
* Unregister all of our slots with the pci_hotplug subsystem.
|
||||
* Memory will be freed in release_slot() callback after slot's
|
||||
* lifespan is finished.
|
||||
*/
|
||||
list_for_each_safe(tmp, next, &slot_list) {
|
||||
slot = list_entry(tmp, struct slot, slot_list);
|
||||
list_for_each_entry_safe(slot, next, &slot_list, slot_list) {
|
||||
list_del(&slot->slot_list);
|
||||
pci_hp_deregister(slot->hotplug_slot);
|
||||
}
|
||||
|
@ -114,11 +114,10 @@ static struct device_node *find_dlpar_node(char *drc_name, int *node_type)
|
||||
*/
|
||||
static struct slot *find_php_slot(struct device_node *dn)
|
||||
{
|
||||
struct list_head *tmp, *n;
|
||||
struct slot *slot;
|
||||
struct slot *slot, *next;
|
||||
|
||||
list_for_each_safe(tmp, n, &rpaphp_slot_head) {
|
||||
slot = list_entry(tmp, struct slot, rpaphp_slot_list);
|
||||
list_for_each_entry_safe(slot, next, &rpaphp_slot_head,
|
||||
rpaphp_slot_list) {
|
||||
if (slot->dn == dn)
|
||||
return slot;
|
||||
}
|
||||
|
@ -51,11 +51,11 @@ extern bool rpaphp_debug;
|
||||
do { \
|
||||
if (rpaphp_debug) \
|
||||
printk(KERN_DEBUG "%s: " format, \
|
||||
MY_NAME , ## arg); \
|
||||
MY_NAME, ## arg); \
|
||||
} while (0)
|
||||
#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg)
|
||||
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
|
||||
#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME, ## arg)
|
||||
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME, ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME, ## arg)
|
||||
|
||||
/* slot states */
|
||||
|
||||
|
@ -94,7 +94,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
|
||||
int retval, level;
|
||||
struct slot *slot = (struct slot *)hotplug_slot->private;
|
||||
|
||||
retval = rtas_get_power_level (slot->power_domain, &level);
|
||||
retval = rtas_get_power_level(slot->power_domain, &level);
|
||||
if (!retval)
|
||||
*value = level;
|
||||
return retval;
|
||||
@ -356,8 +356,7 @@ EXPORT_SYMBOL_GPL(rpaphp_add_slot);
|
||||
|
||||
static void __exit cleanup_slots(void)
|
||||
{
|
||||
struct list_head *tmp, *n;
|
||||
struct slot *slot;
|
||||
struct slot *slot, *next;
|
||||
|
||||
/*
|
||||
* Unregister all of our slots with the pci_hotplug subsystem,
|
||||
@ -365,8 +364,8 @@ static void __exit cleanup_slots(void)
|
||||
* memory will be freed in release_slot callback.
|
||||
*/
|
||||
|
||||
list_for_each_safe(tmp, n, &rpaphp_slot_head) {
|
||||
slot = list_entry(tmp, struct slot, rpaphp_slot_list);
|
||||
list_for_each_entry_safe(slot, next, &rpaphp_slot_head,
|
||||
rpaphp_slot_list) {
|
||||
list_del(&slot->rpaphp_slot_list);
|
||||
pci_hp_deregister(slot->hotplug_slot);
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ int rpaphp_enable_slot(struct slot *slot)
|
||||
if (rpaphp_debug) {
|
||||
struct pci_dev *dev;
|
||||
dbg("%s: pci_devs of slot[%s]\n", __func__, slot->dn->full_name);
|
||||
list_for_each_entry (dev, &bus->devices, bus_list)
|
||||
list_for_each_entry(dev, &bus->devices, bus_list)
|
||||
dbg("\t%s\n", pci_name(dev));
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ void dealloc_slot_struct(struct slot *slot)
|
||||
}
|
||||
|
||||
struct slot *alloc_slot_struct(struct device_node *dn,
|
||||
int drc_index, char *drc_name, int power_domain)
|
||||
int drc_index, char *drc_name, int power_domain)
|
||||
{
|
||||
struct slot *slot;
|
||||
|
||||
|
@ -201,11 +201,10 @@ error:
|
||||
|
||||
void zpci_exit_slot(struct zpci_dev *zdev)
|
||||
{
|
||||
struct list_head *tmp, *n;
|
||||
struct slot *slot;
|
||||
struct slot *slot, *next;
|
||||
|
||||
list_for_each_safe(tmp, n, &s390_hotplug_slot_list) {
|
||||
slot = list_entry(tmp, struct slot, slot_list);
|
||||
list_for_each_entry_safe(slot, next, &s390_hotplug_slot_list,
|
||||
slot_list) {
|
||||
if (slot->zdev != zdev)
|
||||
continue;
|
||||
list_del(&slot->slot_list);
|
||||
|
@ -99,7 +99,7 @@ static ssize_t path_show(struct pci_slot *pci_slot, char *buf)
|
||||
if (!slot)
|
||||
return retval;
|
||||
|
||||
retval = sprintf (buf, "%s\n", slot->physical_path);
|
||||
retval = sprintf(buf, "%s\n", slot->physical_path);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -313,7 +313,7 @@ static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot,
|
||||
}
|
||||
|
||||
if ((action == PCI_REQ_SLOT_DISABLE) && rc) {
|
||||
dev_dbg(&slot->pci_bus->self->dev,"remove failed rc = %d\n", rc);
|
||||
dev_dbg(&slot->pci_bus->self->dev, "remove failed rc = %d\n", rc);
|
||||
}
|
||||
|
||||
return rc;
|
||||
@ -488,7 +488,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
|
||||
|
||||
/* free the ACPI resources for the slot */
|
||||
if (SN_ACPI_BASE_SUPPORT() &&
|
||||
PCI_CONTROLLER(slot->pci_bus)->companion) {
|
||||
PCI_CONTROLLER(slot->pci_bus)->companion) {
|
||||
unsigned long long adr;
|
||||
struct acpi_device *device;
|
||||
acpi_handle phandle;
|
||||
|
@ -50,14 +50,14 @@ extern bool shpchp_debug;
|
||||
#define dbg(format, arg...) \
|
||||
do { \
|
||||
if (shpchp_debug) \
|
||||
printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); \
|
||||
printk(KERN_DEBUG "%s: " format, MY_NAME, ## arg); \
|
||||
} while (0)
|
||||
#define err(format, arg...) \
|
||||
printk(KERN_ERR "%s: " format, MY_NAME , ## arg)
|
||||
printk(KERN_ERR "%s: " format, MY_NAME, ## arg)
|
||||
#define info(format, arg...) \
|
||||
printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
|
||||
printk(KERN_INFO "%s: " format, MY_NAME, ## arg)
|
||||
#define warn(format, arg...) \
|
||||
printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
|
||||
printk(KERN_WARNING "%s: " format, MY_NAME, ## arg)
|
||||
|
||||
#define ctrl_dbg(ctrl, format, arg...) \
|
||||
do { \
|
||||
@ -84,7 +84,7 @@ struct slot {
|
||||
u8 presence_save;
|
||||
u8 pwr_save;
|
||||
struct controller *ctrl;
|
||||
struct hpc_ops *hpc_ops;
|
||||
const struct hpc_ops *hpc_ops;
|
||||
struct hotplug_slot *hotplug_slot;
|
||||
struct list_head slot_list;
|
||||
struct delayed_work work; /* work for button event */
|
||||
@ -106,7 +106,7 @@ struct controller {
|
||||
int slot_num_inc; /* 1 or -1 */
|
||||
struct pci_dev *pci_dev;
|
||||
struct list_head slot_list;
|
||||
struct hpc_ops *hpc_ops;
|
||||
const struct hpc_ops *hpc_ops;
|
||||
wait_queue_head_t queue; /* sleep & wake process */
|
||||
u8 slot_device_offset;
|
||||
u32 pcix_misc2_reg; /* for amd pogo errata */
|
||||
@ -295,7 +295,7 @@ static inline void amd_pogo_errata_restore_misc_reg(struct slot *p_slot)
|
||||
pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MEM_BASE_LIMIT_OFFSET, rse_set);
|
||||
}
|
||||
/* restore MiscII register */
|
||||
pci_read_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, &pcix_misc2_temp );
|
||||
pci_read_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, &pcix_misc2_temp);
|
||||
|
||||
if (p_slot->ctrl->pcix_misc2_reg & SERRFATALENABLE_MASK)
|
||||
pcix_misc2_temp |= SERRFATALENABLE_MASK;
|
||||
|
@ -57,13 +57,13 @@ MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds");
|
||||
|
||||
#define SHPC_MODULE_NAME "shpchp"
|
||||
|
||||
static int set_attention_status (struct hotplug_slot *slot, u8 value);
|
||||
static int enable_slot (struct hotplug_slot *slot);
|
||||
static int disable_slot (struct hotplug_slot *slot);
|
||||
static int get_power_status (struct hotplug_slot *slot, u8 *value);
|
||||
static int get_attention_status (struct hotplug_slot *slot, u8 *value);
|
||||
static int get_latch_status (struct hotplug_slot *slot, u8 *value);
|
||||
static int get_adapter_status (struct hotplug_slot *slot, u8 *value);
|
||||
static int set_attention_status(struct hotplug_slot *slot, u8 value);
|
||||
static int enable_slot(struct hotplug_slot *slot);
|
||||
static int disable_slot(struct hotplug_slot *slot);
|
||||
static int get_power_status(struct hotplug_slot *slot, u8 *value);
|
||||
static int get_attention_status(struct hotplug_slot *slot, u8 *value);
|
||||
static int get_latch_status(struct hotplug_slot *slot, u8 *value);
|
||||
static int get_adapter_status(struct hotplug_slot *slot, u8 *value);
|
||||
|
||||
static struct hotplug_slot_ops shpchp_hotplug_slot_ops = {
|
||||
.set_attention_status = set_attention_status,
|
||||
@ -178,12 +178,9 @@ error:
|
||||
|
||||
void cleanup_slots(struct controller *ctrl)
|
||||
{
|
||||
struct list_head *tmp;
|
||||
struct list_head *next;
|
||||
struct slot *slot;
|
||||
struct slot *slot, *next;
|
||||
|
||||
list_for_each_safe(tmp, next, &ctrl->slot_list) {
|
||||
slot = list_entry(tmp, struct slot, slot_list);
|
||||
list_for_each_entry_safe(slot, next, &ctrl->slot_list, slot_list) {
|
||||
list_del(&slot->slot_list);
|
||||
cancel_delayed_work(&slot->work);
|
||||
destroy_workqueue(slot->wq);
|
||||
@ -194,7 +191,7 @@ void cleanup_slots(struct controller *ctrl)
|
||||
/*
|
||||
* set_attention_status - Turns the Amber LED for a slot on, off or blink
|
||||
*/
|
||||
static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
|
||||
static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
|
||||
{
|
||||
struct slot *slot = get_slot(hotplug_slot);
|
||||
|
||||
@ -207,7 +204,7 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int enable_slot (struct hotplug_slot *hotplug_slot)
|
||||
static int enable_slot(struct hotplug_slot *hotplug_slot)
|
||||
{
|
||||
struct slot *slot = get_slot(hotplug_slot);
|
||||
|
||||
@ -217,7 +214,7 @@ static int enable_slot (struct hotplug_slot *hotplug_slot)
|
||||
return shpchp_sysfs_enable_slot(slot);
|
||||
}
|
||||
|
||||
static int disable_slot (struct hotplug_slot *hotplug_slot)
|
||||
static int disable_slot(struct hotplug_slot *hotplug_slot)
|
||||
{
|
||||
struct slot *slot = get_slot(hotplug_slot);
|
||||
|
||||
@ -227,7 +224,7 @@ static int disable_slot (struct hotplug_slot *hotplug_slot)
|
||||
return shpchp_sysfs_disable_slot(slot);
|
||||
}
|
||||
|
||||
static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
|
||||
static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
|
||||
{
|
||||
struct slot *slot = get_slot(hotplug_slot);
|
||||
int retval;
|
||||
@ -242,7 +239,7 @@ static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
|
||||
static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
|
||||
{
|
||||
struct slot *slot = get_slot(hotplug_slot);
|
||||
int retval;
|
||||
@ -257,7 +254,7 @@ static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value)
|
||||
static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
|
||||
{
|
||||
struct slot *slot = get_slot(hotplug_slot);
|
||||
int retval;
|
||||
@ -272,7 +269,7 @@ static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
|
||||
static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
|
||||
{
|
||||
struct slot *slot = get_slot(hotplug_slot);
|
||||
int retval;
|
||||
|
@ -542,7 +542,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
|
||||
u8 slot_cmd = 0;
|
||||
|
||||
switch (value) {
|
||||
case 0 :
|
||||
case 0:
|
||||
slot_cmd = SET_ATTN_OFF; /* OFF */
|
||||
break;
|
||||
case 1:
|
||||
@ -910,7 +910,7 @@ static int shpc_get_max_bus_speed(struct controller *ctrl)
|
||||
return retval;
|
||||
}
|
||||
|
||||
static struct hpc_ops shpchp_hpc_ops = {
|
||||
static const struct hpc_ops shpchp_hpc_ops = {
|
||||
.power_on_slot = hpc_power_on_slot,
|
||||
.slot_enable = hpc_slot_enable,
|
||||
.slot_disable = hpc_slot_disable,
|
||||
|
@ -35,7 +35,7 @@
|
||||
|
||||
/* A few routines that create sysfs entries for the hot plug controller */
|
||||
|
||||
static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, char *buf)
|
||||
static ssize_t show_ctrl(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct pci_dev *pdev;
|
||||
char *out = buf;
|
||||
@ -43,7 +43,7 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha
|
||||
struct resource *res;
|
||||
struct pci_bus *bus;
|
||||
|
||||
pdev = container_of (dev, struct pci_dev, dev);
|
||||
pdev = to_pci_dev(dev);
|
||||
bus = pdev->subordinate;
|
||||
|
||||
out += sprintf(buf, "Free resources: memory\n");
|
||||
@ -83,11 +83,11 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha
|
||||
|
||||
return out - buf;
|
||||
}
|
||||
static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL);
|
||||
static DEVICE_ATTR(ctrl, S_IRUGO, show_ctrl, NULL);
|
||||
|
||||
int shpchp_create_ctrl_files (struct controller *ctrl)
|
||||
int shpchp_create_ctrl_files(struct controller *ctrl)
|
||||
{
|
||||
return device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl);
|
||||
return device_create_file(&ctrl->pci_dev->dev, &dev_attr_ctrl);
|
||||
}
|
||||
|
||||
void shpchp_remove_ctrl_files(struct controller *ctrl)
|
||||
|
@ -1026,10 +1026,6 @@ int pci_msi_enabled(void)
|
||||
}
|
||||
EXPORT_SYMBOL(pci_msi_enabled);
|
||||
|
||||
void pci_msi_init_pci_dev(struct pci_dev *dev)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_enable_msi_range - configure device's MSI capability structure
|
||||
* @dev: device to configure
|
||||
|
@ -77,7 +77,7 @@ static umode_t smbios_instance_string_exist(struct kobject *kobj,
|
||||
struct device *dev;
|
||||
struct pci_dev *pdev;
|
||||
|
||||
dev = container_of(kobj, struct device, kobj);
|
||||
dev = kobj_to_dev(kobj);
|
||||
pdev = to_pci_dev(dev);
|
||||
|
||||
return find_smbios_instance_string(pdev, NULL, SMBIOS_ATTR_NONE) ?
|
||||
@ -221,7 +221,7 @@ static umode_t acpi_index_string_exist(struct kobject *kobj,
|
||||
{
|
||||
struct device *dev;
|
||||
|
||||
dev = container_of(kobj, struct device, kobj);
|
||||
dev = kobj_to_dev(kobj);
|
||||
|
||||
if (device_has_dsm(dev))
|
||||
return S_IRUGO;
|
||||
|
@ -630,8 +630,7 @@ static ssize_t pci_read_config(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct pci_dev *dev = to_pci_dev(container_of(kobj, struct device,
|
||||
kobj));
|
||||
struct pci_dev *dev = to_pci_dev(kobj_to_dev(kobj));
|
||||
unsigned int size = 64;
|
||||
loff_t init_off = off;
|
||||
u8 *data = (u8 *) buf;
|
||||
@ -707,8 +706,7 @@ static ssize_t pci_write_config(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct pci_dev *dev = to_pci_dev(container_of(kobj, struct device,
|
||||
kobj));
|
||||
struct pci_dev *dev = to_pci_dev(kobj_to_dev(kobj));
|
||||
unsigned int size = count;
|
||||
loff_t init_off = off;
|
||||
u8 *data = (u8 *) buf;
|
||||
@ -769,8 +767,7 @@ static ssize_t read_vpd_attr(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct pci_dev *dev =
|
||||
to_pci_dev(container_of(kobj, struct device, kobj));
|
||||
struct pci_dev *dev = to_pci_dev(kobj_to_dev(kobj));
|
||||
|
||||
if (off > bin_attr->size)
|
||||
count = 0;
|
||||
@ -784,8 +781,7 @@ static ssize_t write_vpd_attr(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct pci_dev *dev =
|
||||
to_pci_dev(container_of(kobj, struct device, kobj));
|
||||
struct pci_dev *dev = to_pci_dev(kobj_to_dev(kobj));
|
||||
|
||||
if (off > bin_attr->size)
|
||||
count = 0;
|
||||
@ -812,8 +808,7 @@ static ssize_t pci_read_legacy_io(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct pci_bus *bus = to_pci_bus(container_of(kobj, struct device,
|
||||
kobj));
|
||||
struct pci_bus *bus = to_pci_bus(kobj_to_dev(kobj));
|
||||
|
||||
/* Only support 1, 2 or 4 byte accesses */
|
||||
if (count != 1 && count != 2 && count != 4)
|
||||
@ -838,8 +833,7 @@ static ssize_t pci_write_legacy_io(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct pci_bus *bus = to_pci_bus(container_of(kobj, struct device,
|
||||
kobj));
|
||||
struct pci_bus *bus = to_pci_bus(kobj_to_dev(kobj));
|
||||
|
||||
/* Only support 1, 2 or 4 byte accesses */
|
||||
if (count != 1 && count != 2 && count != 4)
|
||||
@ -863,8 +857,7 @@ static int pci_mmap_legacy_mem(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *attr,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
struct pci_bus *bus = to_pci_bus(container_of(kobj, struct device,
|
||||
kobj));
|
||||
struct pci_bus *bus = to_pci_bus(kobj_to_dev(kobj));
|
||||
|
||||
return pci_mmap_legacy_page_range(bus, vma, pci_mmap_mem);
|
||||
}
|
||||
@ -884,8 +877,7 @@ static int pci_mmap_legacy_io(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *attr,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
struct pci_bus *bus = to_pci_bus(container_of(kobj, struct device,
|
||||
kobj));
|
||||
struct pci_bus *bus = to_pci_bus(kobj_to_dev(kobj));
|
||||
|
||||
return pci_mmap_legacy_page_range(bus, vma, pci_mmap_io);
|
||||
}
|
||||
@ -1000,8 +992,7 @@ int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma,
|
||||
static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
|
||||
struct vm_area_struct *vma, int write_combine)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(container_of(kobj,
|
||||
struct device, kobj));
|
||||
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
|
||||
struct resource *res = attr->private;
|
||||
enum pci_mmap_state mmap_type;
|
||||
resource_size_t start, end;
|
||||
@ -1054,8 +1045,7 @@ static ssize_t pci_resource_io(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count, bool write)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(container_of(kobj,
|
||||
struct device, kobj));
|
||||
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
|
||||
struct resource *res = attr->private;
|
||||
unsigned long port = off;
|
||||
int i;
|
||||
@ -1225,7 +1215,7 @@ static ssize_t pci_write_rom(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj));
|
||||
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
|
||||
|
||||
if ((off == 0) && (*buf == '0') && (count == 2))
|
||||
pdev->rom_attr_enabled = 0;
|
||||
@ -1251,7 +1241,7 @@ static ssize_t pci_read_rom(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj));
|
||||
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
|
||||
void __iomem *rom;
|
||||
size_t size;
|
||||
|
||||
@ -1372,10 +1362,10 @@ int __must_check pci_create_sysfs_dev_files(struct pci_dev *pdev)
|
||||
if (!sysfs_initialized)
|
||||
return -EACCES;
|
||||
|
||||
if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
|
||||
retval = sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr);
|
||||
else
|
||||
if (pdev->cfg_size > PCI_CFG_SPACE_SIZE)
|
||||
retval = sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr);
|
||||
else
|
||||
retval = sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr);
|
||||
if (retval)
|
||||
goto err;
|
||||
|
||||
@ -1427,10 +1417,10 @@ err_rom_file:
|
||||
err_resource_files:
|
||||
pci_remove_resource_files(pdev);
|
||||
err_config_file:
|
||||
if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
|
||||
sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
|
||||
else
|
||||
if (pdev->cfg_size > PCI_CFG_SPACE_SIZE)
|
||||
sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr);
|
||||
else
|
||||
sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
|
||||
err:
|
||||
return retval;
|
||||
}
|
||||
@ -1464,10 +1454,10 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
|
||||
|
||||
pci_remove_capabilities_sysfs(pdev);
|
||||
|
||||
if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
|
||||
sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
|
||||
else
|
||||
if (pdev->cfg_size > PCI_CFG_SPACE_SIZE)
|
||||
sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr);
|
||||
else
|
||||
sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
|
||||
|
||||
pci_remove_resource_files(pdev);
|
||||
|
||||
@ -1511,7 +1501,7 @@ static struct attribute *pci_dev_dev_attrs[] = {
|
||||
static umode_t pci_dev_attrs_are_visible(struct kobject *kobj,
|
||||
struct attribute *a, int n)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct device *dev = kobj_to_dev(kobj);
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
|
||||
if (a == &vga_attr.attr)
|
||||
@ -1530,7 +1520,7 @@ static struct attribute *pci_dev_hp_attrs[] = {
|
||||
static umode_t pci_dev_hp_attrs_are_visible(struct kobject *kobj,
|
||||
struct attribute *a, int n)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct device *dev = kobj_to_dev(kobj);
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
|
||||
if (pdev->is_virtfn)
|
||||
@ -1554,7 +1544,7 @@ static struct attribute *sriov_dev_attrs[] = {
|
||||
static umode_t sriov_attrs_are_visible(struct kobject *kobj,
|
||||
struct attribute *a, int n)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct device *dev = kobj_to_dev(kobj);
|
||||
|
||||
if (!dev_is_pf(dev))
|
||||
return 0;
|
||||
|
@ -1417,7 +1417,7 @@ struct pci_devres {
|
||||
|
||||
static void pcim_release(struct device *gendev, void *res)
|
||||
{
|
||||
struct pci_dev *dev = container_of(gendev, struct pci_dev, dev);
|
||||
struct pci_dev *dev = to_pci_dev(gendev);
|
||||
struct pci_devres *this = res;
|
||||
int i;
|
||||
|
||||
@ -1534,7 +1534,7 @@ void __weak pcibios_release_device(struct pci_dev *dev) {}
|
||||
* is the default implementation. Architecture implementations can
|
||||
* override this.
|
||||
*/
|
||||
void __weak pcibios_disable_device (struct pci_dev *dev) {}
|
||||
void __weak pcibios_disable_device(struct pci_dev *dev) {}
|
||||
|
||||
/**
|
||||
* pcibios_penalize_isa_irq - penalize an ISA IRQ
|
||||
|
@ -144,10 +144,8 @@ extern unsigned int pci_pm_d3_delay;
|
||||
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
void pci_no_msi(void);
|
||||
void pci_msi_init_pci_dev(struct pci_dev *dev);
|
||||
#else
|
||||
static inline void pci_no_msi(void) { }
|
||||
static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { }
|
||||
#endif
|
||||
|
||||
static inline void pci_msi_set_enable(struct pci_dev *dev, int enable)
|
||||
|
@ -41,12 +41,12 @@ struct aer_error_inj {
|
||||
u32 header_log1;
|
||||
u32 header_log2;
|
||||
u32 header_log3;
|
||||
u16 domain;
|
||||
u32 domain;
|
||||
};
|
||||
|
||||
struct aer_error {
|
||||
struct list_head list;
|
||||
u16 domain;
|
||||
u32 domain;
|
||||
unsigned int bus;
|
||||
unsigned int devfn;
|
||||
int pos_cap_err;
|
||||
@ -74,7 +74,7 @@ static LIST_HEAD(pci_bus_ops_list);
|
||||
/* Protect einjected and pci_bus_ops_list */
|
||||
static DEFINE_SPINLOCK(inject_lock);
|
||||
|
||||
static void aer_error_init(struct aer_error *err, u16 domain,
|
||||
static void aer_error_init(struct aer_error *err, u32 domain,
|
||||
unsigned int bus, unsigned int devfn,
|
||||
int pos_cap_err)
|
||||
{
|
||||
@ -86,7 +86,7 @@ static void aer_error_init(struct aer_error *err, u16 domain,
|
||||
}
|
||||
|
||||
/* inject_lock must be held before calling */
|
||||
static struct aer_error *__find_aer_error(u16 domain, unsigned int bus,
|
||||
static struct aer_error *__find_aer_error(u32 domain, unsigned int bus,
|
||||
unsigned int devfn)
|
||||
{
|
||||
struct aer_error *err;
|
||||
@ -106,7 +106,7 @@ static struct aer_error *__find_aer_error_by_dev(struct pci_dev *dev)
|
||||
int domain = pci_domain_nr(dev->bus);
|
||||
if (domain < 0)
|
||||
return NULL;
|
||||
return __find_aer_error((u16)domain, dev->bus->number, dev->devfn);
|
||||
return __find_aer_error(domain, dev->bus->number, dev->devfn);
|
||||
}
|
||||
|
||||
/* inject_lock must be held before calling */
|
||||
@ -196,7 +196,7 @@ static int pci_read_aer(struct pci_bus *bus, unsigned int devfn, int where,
|
||||
domain = pci_domain_nr(bus);
|
||||
if (domain < 0)
|
||||
goto out;
|
||||
err = __find_aer_error((u16)domain, bus->number, devfn);
|
||||
err = __find_aer_error(domain, bus->number, devfn);
|
||||
if (!err)
|
||||
goto out;
|
||||
|
||||
@ -228,7 +228,7 @@ static int pci_write_aer(struct pci_bus *bus, unsigned int devfn, int where,
|
||||
domain = pci_domain_nr(bus);
|
||||
if (domain < 0)
|
||||
goto out;
|
||||
err = __find_aer_error((u16)domain, bus->number, devfn);
|
||||
err = __find_aer_error(domain, bus->number, devfn);
|
||||
if (!err)
|
||||
goto out;
|
||||
|
||||
@ -329,7 +329,7 @@ static int aer_inject(struct aer_error_inj *einj)
|
||||
u32 sever, cor_mask, uncor_mask, cor_mask_orig = 0, uncor_mask_orig = 0;
|
||||
int ret = 0;
|
||||
|
||||
dev = pci_get_domain_bus_and_slot((int)einj->domain, einj->bus, devfn);
|
||||
dev = pci_get_domain_bus_and_slot(einj->domain, einj->bus, devfn);
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
rpdev = pcie_find_root_port(dev);
|
||||
|
@ -246,7 +246,7 @@ static int report_error_detected(struct pci_dev *dev, void *data)
|
||||
!dev->driver->err_handler ||
|
||||
!dev->driver->err_handler->error_detected) {
|
||||
if (result_data->state == pci_channel_io_frozen &&
|
||||
!(dev->hdr_type & PCI_HEADER_TYPE_BRIDGE)) {
|
||||
dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
|
||||
/*
|
||||
* In case of fatal recovery, if one of down-
|
||||
* stream device has no driver. We might be
|
||||
@ -269,7 +269,7 @@ static int report_error_detected(struct pci_dev *dev, void *data)
|
||||
* without recovery.
|
||||
*/
|
||||
|
||||
if (!(dev->hdr_type & PCI_HEADER_TYPE_BRIDGE))
|
||||
if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE)
|
||||
vote = PCI_ERS_RESULT_NO_AER_DRIVER;
|
||||
else
|
||||
vote = PCI_ERS_RESULT_NONE;
|
||||
@ -369,7 +369,7 @@ static pci_ers_result_t broadcast_error_message(struct pci_dev *dev,
|
||||
else
|
||||
result_data.result = PCI_ERS_RESULT_RECOVERED;
|
||||
|
||||
if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) {
|
||||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
|
||||
/*
|
||||
* If the error is reported by a bridge, we think this error
|
||||
* is related to the downstream link of the bridge, so we
|
||||
@ -440,7 +440,7 @@ static pci_ers_result_t reset_link(struct pci_dev *dev)
|
||||
pci_ers_result_t status;
|
||||
struct pcie_port_service_driver *driver;
|
||||
|
||||
if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) {
|
||||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
|
||||
/* Reset this port for all subordinates */
|
||||
udev = dev;
|
||||
} else {
|
||||
@ -660,7 +660,7 @@ static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info)
|
||||
&info->mask);
|
||||
if (!(info->status & ~info->mask))
|
||||
return 0;
|
||||
} else if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE ||
|
||||
} else if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
|
||||
info->severity == AER_NONFATAL) {
|
||||
|
||||
/* Link is still healthy for IO reads */
|
||||
|
@ -834,21 +834,15 @@ static ssize_t link_state_store(struct device *dev,
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct pcie_link_state *link, *root = pdev->link_state->root;
|
||||
u32 val, state = 0;
|
||||
|
||||
if (kstrtouint(buf, 10, &val))
|
||||
return -EINVAL;
|
||||
u32 state;
|
||||
|
||||
if (aspm_disabled)
|
||||
return -EPERM;
|
||||
if (n < 1 || val > 3)
|
||||
return -EINVAL;
|
||||
|
||||
/* Convert requested state to ASPM state */
|
||||
if (val & PCIE_LINK_STATE_L0S)
|
||||
state |= ASPM_STATE_L0S;
|
||||
if (val & PCIE_LINK_STATE_L1)
|
||||
state |= ASPM_STATE_L1;
|
||||
if (kstrtouint(buf, 10, &state))
|
||||
return -EINVAL;
|
||||
if ((state & ~ASPM_STATE_ALL) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
down_read(&pci_bus_sem);
|
||||
mutex_lock(&aspm_lock);
|
||||
|
@ -1109,14 +1109,11 @@ static int pci_cfg_space_size_ext(struct pci_dev *dev)
|
||||
int pos = PCI_CFG_SPACE_SIZE;
|
||||
|
||||
if (pci_read_config_dword(dev, pos, &status) != PCIBIOS_SUCCESSFUL)
|
||||
goto fail;
|
||||
return PCI_CFG_SPACE_SIZE;
|
||||
if (status == 0xffffffff || pci_ext_cfg_is_aliased(dev))
|
||||
goto fail;
|
||||
return PCI_CFG_SPACE_SIZE;
|
||||
|
||||
return PCI_CFG_SPACE_EXP_SIZE;
|
||||
|
||||
fail:
|
||||
return PCI_CFG_SPACE_SIZE;
|
||||
}
|
||||
|
||||
int pci_cfg_space_size(struct pci_dev *dev)
|
||||
@ -1129,25 +1126,23 @@ int pci_cfg_space_size(struct pci_dev *dev)
|
||||
if (class == PCI_CLASS_BRIDGE_HOST)
|
||||
return pci_cfg_space_size_ext(dev);
|
||||
|
||||
if (!pci_is_pcie(dev)) {
|
||||
pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
|
||||
if (!pos)
|
||||
goto fail;
|
||||
if (pci_is_pcie(dev))
|
||||
return pci_cfg_space_size_ext(dev);
|
||||
|
||||
pci_read_config_dword(dev, pos + PCI_X_STATUS, &status);
|
||||
if (!(status & (PCI_X_STATUS_266MHZ | PCI_X_STATUS_533MHZ)))
|
||||
goto fail;
|
||||
}
|
||||
pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
|
||||
if (!pos)
|
||||
return PCI_CFG_SPACE_SIZE;
|
||||
|
||||
return pci_cfg_space_size_ext(dev);
|
||||
pci_read_config_dword(dev, pos + PCI_X_STATUS, &status);
|
||||
if (status & (PCI_X_STATUS_266MHZ | PCI_X_STATUS_533MHZ))
|
||||
return pci_cfg_space_size_ext(dev);
|
||||
|
||||
fail:
|
||||
return PCI_CFG_SPACE_SIZE;
|
||||
}
|
||||
|
||||
#define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED)
|
||||
|
||||
void pci_msi_setup_pci_dev(struct pci_dev *dev)
|
||||
static void pci_msi_setup_pci_dev(struct pci_dev *dev)
|
||||
{
|
||||
/*
|
||||
* Disable the MSI hardware to avoid screaming interrupts
|
||||
@ -1214,8 +1209,6 @@ int pci_setup_device(struct pci_dev *dev)
|
||||
/* "Unknown power state" */
|
||||
dev->current_state = PCI_UNKNOWN;
|
||||
|
||||
pci_msi_setup_pci_dev(dev);
|
||||
|
||||
/* Early fixups, before probing the BARs */
|
||||
pci_fixup_device(pci_fixup_early, dev);
|
||||
/* device class may be changed after fixup */
|
||||
@ -1605,8 +1598,8 @@ static void pci_init_capabilities(struct pci_dev *dev)
|
||||
/* Enhanced Allocation */
|
||||
pci_ea_init(dev);
|
||||
|
||||
/* MSI/MSI-X list */
|
||||
pci_msi_init_pci_dev(dev);
|
||||
/* Setup MSI caps & disable MSI/MSI-X interrupts */
|
||||
pci_msi_setup_pci_dev(dev);
|
||||
|
||||
/* Buffers for saving PCIe and PCI-X capabilities */
|
||||
pci_allocate_cap_save_buffers(dev);
|
||||
|
@ -287,6 +287,18 @@ static void quirk_citrine(struct pci_dev *dev)
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, quirk_citrine);
|
||||
|
||||
/*
|
||||
* This chip can cause bus lockups if config addresses above 0x600
|
||||
* are read or written.
|
||||
*/
|
||||
static void quirk_nfp6000(struct pci_dev *dev)
|
||||
{
|
||||
dev->cfg_size = 0x600;
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETRONOME, PCI_DEVICE_ID_NETRONOME_NFP4000, quirk_nfp6000);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETRONOME, PCI_DEVICE_ID_NETRONOME_NFP6000, quirk_nfp6000);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETRONOME, PCI_DEVICE_ID_NETRONOME_NFP6000_VF, quirk_nfp6000);
|
||||
|
||||
/* On IBM Crocodile ipr SAS adapters, expand BAR to system page size */
|
||||
static void quirk_extend_bar_to_page(struct pci_dev *dev)
|
||||
{
|
||||
@ -3622,6 +3634,10 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TTI, 0x0642,
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_JMICRON,
|
||||
PCI_DEVICE_ID_JMICRON_JMB388_ESD,
|
||||
quirk_dma_func1_alias);
|
||||
/* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c117 */
|
||||
DECLARE_PCI_FIXUP_HEADER(0x1c28, /* Lite-On */
|
||||
0x0122, /* Plextor M6E (Marvell 88SS9183)*/
|
||||
quirk_dma_func1_alias);
|
||||
|
||||
/*
|
||||
* Some devices DMA with the wrong devfn, not just the wrong function.
|
||||
|
@ -77,25 +77,24 @@ size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size)
|
||||
do {
|
||||
void __iomem *pds;
|
||||
/* Standard PCI ROMs start out with these bytes 55 AA */
|
||||
if (readb(image) != 0x55) {
|
||||
dev_err(&pdev->dev, "Invalid ROM contents\n");
|
||||
if (readw(image) != 0xAA55) {
|
||||
dev_err(&pdev->dev, "Invalid PCI ROM header signature: expecting 0xaa55, got %#06x\n",
|
||||
readw(image));
|
||||
break;
|
||||
}
|
||||
if (readb(image + 1) != 0xAA)
|
||||
break;
|
||||
/* get the PCI data structure and check its signature */
|
||||
/* get the PCI data structure and check its "PCIR" signature */
|
||||
pds = image + readw(image + 24);
|
||||
if (readb(pds) != 'P')
|
||||
break;
|
||||
if (readb(pds + 1) != 'C')
|
||||
break;
|
||||
if (readb(pds + 2) != 'I')
|
||||
break;
|
||||
if (readb(pds + 3) != 'R')
|
||||
if (readl(pds) != 0x52494350) {
|
||||
dev_err(&pdev->dev, "Invalid PCI ROM data signature: expecting 0x52494350, got %#010x\n",
|
||||
readl(pds));
|
||||
break;
|
||||
}
|
||||
last_image = readb(pds + 21) & 0x80;
|
||||
length = readw(pds + 16);
|
||||
image += length * 512;
|
||||
/* Avoid iterating through memory outside the resource window */
|
||||
if (image > rom + size)
|
||||
break;
|
||||
} while (length && !last_image);
|
||||
|
||||
/* never return a size larger than the PCI resource window */
|
||||
|
@ -442,7 +442,7 @@ static void __assign_resources_sorted(struct list_head *head,
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -187,7 +187,7 @@ struct msi_domain_info;
|
||||
* @msi_free: Domain specific function to free a MSI interrupts
|
||||
* @msi_check: Callback for verification of the domain/info/dev data
|
||||
* @msi_prepare: Prepare the allocation of the interrupts in the domain
|
||||
* @msi_finish: Optional callbacl to finalize the allocation
|
||||
* @msi_finish: Optional callback to finalize the allocation
|
||||
* @set_desc: Set the msi descriptor for an interrupt
|
||||
* @handle_error: Optional error handler if the allocation fails
|
||||
*
|
||||
@ -195,7 +195,7 @@ struct msi_domain_info;
|
||||
* msi_create_irq_domain() and related interfaces
|
||||
*
|
||||
* @msi_check, @msi_prepare, @msi_finish, @set_desc and @handle_error
|
||||
* are callbacks used by msi_irq_domain_alloc_irqs() and related
|
||||
* are callbacks used by msi_domain_alloc_irqs() and related
|
||||
* interfaces which are based on msi_desc.
|
||||
*/
|
||||
struct msi_domain_ops {
|
||||
|
@ -59,6 +59,13 @@ static inline void of_pci_check_probe_only(void) { }
|
||||
int of_pci_get_host_bridge_resources(struct device_node *dev,
|
||||
unsigned char busno, unsigned char bus_max,
|
||||
struct list_head *resources, resource_size_t *io_base);
|
||||
#else
|
||||
static inline int of_pci_get_host_bridge_resources(struct device_node *dev,
|
||||
unsigned char busno, unsigned char bus_max,
|
||||
struct list_head *resources, resource_size_t *io_base)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_OF) && defined(CONFIG_PCI_MSI)
|
||||
|
@ -1257,8 +1257,6 @@ struct msix_entry {
|
||||
u16 entry; /* driver uses to specify entry, OS writes */
|
||||
};
|
||||
|
||||
void pci_msi_setup_pci_dev(struct pci_dev *dev);
|
||||
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
int pci_msi_vec_count(struct pci_dev *dev);
|
||||
void pci_msi_shutdown(struct pci_dev *dev);
|
||||
|
@ -2496,6 +2496,11 @@
|
||||
#define PCI_DEVICE_ID_KORENIX_JETCARDF3 0x17ff
|
||||
|
||||
#define PCI_VENDOR_ID_NETRONOME 0x19ee
|
||||
#define PCI_DEVICE_ID_NETRONOME_NFP3200 0x3200
|
||||
#define PCI_DEVICE_ID_NETRONOME_NFP3240 0x3240
|
||||
#define PCI_DEVICE_ID_NETRONOME_NFP4000 0x4000
|
||||
#define PCI_DEVICE_ID_NETRONOME_NFP6000 0x6000
|
||||
#define PCI_DEVICE_ID_NETRONOME_NFP6000_VF 0x6003
|
||||
|
||||
#define PCI_VENDOR_ID_QMI 0x1a32
|
||||
|
||||
|
@ -1061,6 +1061,7 @@ void irq_domain_set_info(struct irq_domain *domain, unsigned int virq,
|
||||
__irq_set_handler(virq, handler, 0, handler_name);
|
||||
irq_set_handler_data(virq, handler_data);
|
||||
}
|
||||
EXPORT_SYMBOL(irq_domain_set_info);
|
||||
|
||||
/**
|
||||
* irq_domain_reset_irq_data - Clear hwirq, chip and chip_data in @irq_data
|
||||
|
@ -109,9 +109,11 @@ static int msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
|
||||
if (irq_find_mapping(domain, hwirq) > 0)
|
||||
return -EEXIST;
|
||||
|
||||
ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, arg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (domain->parent) {
|
||||
ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, arg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < nr_irqs; i++) {
|
||||
ret = ops->msi_init(domain, info, virq + i, hwirq + i, arg);
|
||||
|
Loading…
Reference in New Issue
Block a user