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:
@@ -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);
|
||||
|
Reference in New Issue
Block a user