From c2ce6f9f3dc00daca5714ef070a9a2d4e78eb336 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 10 Feb 2015 09:51:22 +1100 Subject: powerpc: Change vrX register defines to vX to match gcc and glibc As our various loops (copy, string, crypto etc) get more complicated, we want to share implementations between userspace (eg glibc) and the kernel. We also want to write userspace test harnesses to put in tools/testing/selftest. One gratuitous difference between userspace and the kernel is the VMX register definitions - the kernel uses vrX whereas both gcc and glibc use vX. Change the kernel to match userspace. Signed-off-by: Anton Blanchard Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/ppc_asm.h | 64 +++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 32 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h index 7e4612528546..c7461032b469 100644 --- a/arch/powerpc/include/asm/ppc_asm.h +++ b/arch/powerpc/include/asm/ppc_asm.h @@ -637,38 +637,38 @@ END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,945) /* AltiVec Registers (VPRs) */ -#define vr0 0 -#define vr1 1 -#define vr2 2 -#define vr3 3 -#define vr4 4 -#define vr5 5 -#define vr6 6 -#define vr7 7 -#define vr8 8 -#define vr9 9 -#define vr10 10 -#define vr11 11 -#define vr12 12 -#define vr13 13 -#define vr14 14 -#define vr15 15 -#define vr16 16 -#define vr17 17 -#define vr18 18 -#define vr19 19 -#define vr20 20 -#define vr21 21 -#define vr22 22 -#define vr23 23 -#define vr24 24 -#define vr25 25 -#define vr26 26 -#define vr27 27 -#define vr28 28 -#define vr29 29 -#define vr30 30 -#define vr31 31 +#define v0 0 +#define v1 1 +#define v2 2 +#define v3 3 +#define v4 4 +#define v5 5 +#define v6 6 +#define v7 7 +#define v8 8 +#define v9 9 +#define v10 10 +#define v11 11 +#define v12 12 +#define v13 13 +#define v14 14 +#define v15 15 +#define v16 16 +#define v17 17 +#define v18 18 +#define v19 19 +#define v20 20 +#define v21 21 +#define v22 22 +#define v23 23 +#define v24 24 +#define v25 25 +#define v26 26 +#define v27 27 +#define v28 28 +#define v29 29 +#define v30 30 +#define v31 31 /* VSX Registers (VSRs) */ -- cgit v1.2.3 From df99e6eb3f5279a211ee50b2321357c0d9ed8224 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 10 Feb 2015 09:51:23 +1100 Subject: powerpc: Change vsrX register defines to vsX to match gcc and glibc As our various loops (copy, string, crypto etc) get more complicated, we want to share implementations between userspace (eg glibc) and the kernel. We also want to write userspace test harnesses to put in tools/testing/selftest. One gratuitous difference between userspace and the kernel is the VSX register definitions - the kernel uses vsrX whereas gcc uses vsX. Change the kernel to match userspace. Signed-off-by: Anton Blanchard Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/ppc_asm.h | 128 ++++++++++++++++++------------------- arch/powerpc/lib/ldstfp.S | 6 +- 2 files changed, 67 insertions(+), 67 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h index c7461032b469..dd0fc18d8103 100644 --- a/arch/powerpc/include/asm/ppc_asm.h +++ b/arch/powerpc/include/asm/ppc_asm.h @@ -672,70 +672,70 @@ END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,945) /* VSX Registers (VSRs) */ -#define vsr0 0 -#define vsr1 1 -#define vsr2 2 -#define vsr3 3 -#define vsr4 4 -#define vsr5 5 -#define vsr6 6 -#define vsr7 7 -#define vsr8 8 -#define vsr9 9 -#define vsr10 10 -#define vsr11 11 -#define vsr12 12 -#define vsr13 13 -#define vsr14 14 -#define vsr15 15 -#define vsr16 16 -#define vsr17 17 -#define vsr18 18 -#define vsr19 19 -#define vsr20 20 -#define vsr21 21 -#define vsr22 22 -#define vsr23 23 -#define vsr24 24 -#define vsr25 25 -#define vsr26 26 -#define vsr27 27 -#define vsr28 28 -#define vsr29 29 -#define vsr30 30 -#define vsr31 31 -#define vsr32 32 -#define vsr33 33 -#define vsr34 34 -#define vsr35 35 -#define vsr36 36 -#define vsr37 37 -#define vsr38 38 -#define vsr39 39 -#define vsr40 40 -#define vsr41 41 -#define vsr42 42 -#define vsr43 43 -#define vsr44 44 -#define vsr45 45 -#define vsr46 46 -#define vsr47 47 -#define vsr48 48 -#define vsr49 49 -#define vsr50 50 -#define vsr51 51 -#define vsr52 52 -#define vsr53 53 -#define vsr54 54 -#define vsr55 55 -#define vsr56 56 -#define vsr57 57 -#define vsr58 58 -#define vsr59 59 -#define vsr60 60 -#define vsr61 61 -#define vsr62 62 -#define vsr63 63 +#define vs0 0 +#define vs1 1 +#define vs2 2 +#define vs3 3 +#define vs4 4 +#define vs5 5 +#define vs6 6 +#define vs7 7 +#define vs8 8 +#define vs9 9 +#define vs10 10 +#define vs11 11 +#define vs12 12 +#define vs13 13 +#define vs14 14 +#define vs15 15 +#define vs16 16 +#define vs17 17 +#define vs18 18 +#define vs19 19 +#define vs20 20 +#define vs21 21 +#define vs22 22 +#define vs23 23 +#define vs24 24 +#define vs25 25 +#define vs26 26 +#define vs27 27 +#define vs28 28 +#define vs29 29 +#define vs30 30 +#define vs31 31 +#define vs32 32 +#define vs33 33 +#define vs34 34 +#define vs35 35 +#define vs36 36 +#define vs37 37 +#define vs38 38 +#define vs39 39 +#define vs40 40 +#define vs41 41 +#define vs42 42 +#define vs43 43 +#define vs44 44 +#define vs45 45 +#define vs46 46 +#define vs47 47 +#define vs48 48 +#define vs49 49 +#define vs50 50 +#define vs51 51 +#define vs52 52 +#define vs53 53 +#define vs54 54 +#define vs55 55 +#define vs56 56 +#define vs57 57 +#define vs58 58 +#define vs59 59 +#define vs60 60 +#define vs61 61 +#define vs62 62 +#define vs63 63 /* SPE Registers (EVPRs) */ diff --git a/arch/powerpc/lib/ldstfp.S b/arch/powerpc/lib/ldstfp.S index 659c7ca1f4f2..5d0cdbfbe3f2 100644 --- a/arch/powerpc/lib/ldstfp.S +++ b/arch/powerpc/lib/ldstfp.S @@ -280,12 +280,12 @@ _GLOBAL(do_stvx) #endif /* CONFIG_ALTIVEC */ #ifdef CONFIG_VSX -/* Get the contents of vsrN into vsr0; N is in r3. */ +/* Get the contents of vsN into vs0; N is in r3. */ _GLOBAL(get_vsr) mflr r0 rlwinm r3,r3,3,0x1f8 bcl 20,31,1f - blr /* vsr0 is already in vsr0 */ + blr /* vs0 is already in vs0 */ nop reg = 1 .rept 63 @@ -299,7 +299,7 @@ reg = reg + 1 mtlr r0 bctr -/* Put the contents of vsr0 into vsrN; N is in r3. */ +/* Put the contents of vs0 into vsN; N is in r3. */ _GLOBAL(put_vsr) mflr r0 rlwinm r3,r3,3,0x1f8 -- cgit v1.2.3 From d800ba1218799efb07b3d11a84f38bf05a94daf5 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 17 Feb 2015 20:01:53 +1100 Subject: powerpc/powernv: Move OPAL API definitions to opal-api.h We'd like to get to the stage where the OPAL API is defined in a header that is identical between Linux and Skiboot. As step one, split the bits that actually define the API into opal-api.h. The Linux specific parts stay in opal.h. Signed-off-by: Michael Ellerman Acked-by: Stewart Smith --- arch/powerpc/include/asm/opal-api.h | 763 ++++++++++++++++++++++++++++++++++++ arch/powerpc/include/asm/opal.h | 757 +---------------------------------- 2 files changed, 769 insertions(+), 751 deletions(-) create mode 100644 arch/powerpc/include/asm/opal-api.h (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h new file mode 100644 index 000000000000..a90176a428ee --- /dev/null +++ b/arch/powerpc/include/asm/opal-api.h @@ -0,0 +1,763 @@ +/* + * PowerNV OPAL definitions. + * + * Copyright 2011 IBM Corp. + * + * 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; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef __OPAL_API_H +#define __OPAL_API_H + +/****** OPAL APIs ******/ + +/* Return codes */ +#define OPAL_SUCCESS 0 +#define OPAL_PARAMETER -1 +#define OPAL_BUSY -2 +#define OPAL_PARTIAL -3 +#define OPAL_CONSTRAINED -4 +#define OPAL_CLOSED -5 +#define OPAL_HARDWARE -6 +#define OPAL_UNSUPPORTED -7 +#define OPAL_PERMISSION -8 +#define OPAL_NO_MEM -9 +#define OPAL_RESOURCE -10 +#define OPAL_INTERNAL_ERROR -11 +#define OPAL_BUSY_EVENT -12 +#define OPAL_HARDWARE_FROZEN -13 +#define OPAL_WRONG_STATE -14 +#define OPAL_ASYNC_COMPLETION -15 +#define OPAL_I2C_TIMEOUT -17 +#define OPAL_I2C_INVALID_CMD -18 +#define OPAL_I2C_LBUS_PARITY -19 +#define OPAL_I2C_BKEND_OVERRUN -20 +#define OPAL_I2C_BKEND_ACCESS -21 +#define OPAL_I2C_ARBT_LOST -22 +#define OPAL_I2C_NACK_RCVD -23 +#define OPAL_I2C_STOP_ERR -24 + +/* API Tokens (in r0) */ +#define OPAL_INVALID_CALL -1 +#define OPAL_CONSOLE_WRITE 1 +#define OPAL_CONSOLE_READ 2 +#define OPAL_RTC_READ 3 +#define OPAL_RTC_WRITE 4 +#define OPAL_CEC_POWER_DOWN 5 +#define OPAL_CEC_REBOOT 6 +#define OPAL_READ_NVRAM 7 +#define OPAL_WRITE_NVRAM 8 +#define OPAL_HANDLE_INTERRUPT 9 +#define OPAL_POLL_EVENTS 10 +#define OPAL_PCI_SET_HUB_TCE_MEMORY 11 +#define OPAL_PCI_SET_PHB_TCE_MEMORY 12 +#define OPAL_PCI_CONFIG_READ_BYTE 13 +#define OPAL_PCI_CONFIG_READ_HALF_WORD 14 +#define OPAL_PCI_CONFIG_READ_WORD 15 +#define OPAL_PCI_CONFIG_WRITE_BYTE 16 +#define OPAL_PCI_CONFIG_WRITE_HALF_WORD 17 +#define OPAL_PCI_CONFIG_WRITE_WORD 18 +#define OPAL_SET_XIVE 19 +#define OPAL_GET_XIVE 20 +#define OPAL_GET_COMPLETION_TOKEN_STATUS 21 /* obsolete */ +#define OPAL_REGISTER_OPAL_EXCEPTION_HANDLER 22 +#define OPAL_PCI_EEH_FREEZE_STATUS 23 +#define OPAL_PCI_SHPC 24 +#define OPAL_CONSOLE_WRITE_BUFFER_SPACE 25 +#define OPAL_PCI_EEH_FREEZE_CLEAR 26 +#define OPAL_PCI_PHB_MMIO_ENABLE 27 +#define OPAL_PCI_SET_PHB_MEM_WINDOW 28 +#define OPAL_PCI_MAP_PE_MMIO_WINDOW 29 +#define OPAL_PCI_SET_PHB_TABLE_MEMORY 30 +#define OPAL_PCI_SET_PE 31 +#define OPAL_PCI_SET_PELTV 32 +#define OPAL_PCI_SET_MVE 33 +#define OPAL_PCI_SET_MVE_ENABLE 34 +#define OPAL_PCI_GET_XIVE_REISSUE 35 +#define OPAL_PCI_SET_XIVE_REISSUE 36 +#define OPAL_PCI_SET_XIVE_PE 37 +#define OPAL_GET_XIVE_SOURCE 38 +#define OPAL_GET_MSI_32 39 +#define OPAL_GET_MSI_64 40 +#define OPAL_START_CPU 41 +#define OPAL_QUERY_CPU_STATUS 42 +#define OPAL_WRITE_OPPANEL 43 +#define OPAL_PCI_MAP_PE_DMA_WINDOW 44 +#define OPAL_PCI_MAP_PE_DMA_WINDOW_REAL 45 +#define OPAL_PCI_RESET 49 +#define OPAL_PCI_GET_HUB_DIAG_DATA 50 +#define OPAL_PCI_GET_PHB_DIAG_DATA 51 +#define OPAL_PCI_FENCE_PHB 52 +#define OPAL_PCI_REINIT 53 +#define OPAL_PCI_MASK_PE_ERROR 54 +#define OPAL_SET_SLOT_LED_STATUS 55 +#define OPAL_GET_EPOW_STATUS 56 +#define OPAL_SET_SYSTEM_ATTENTION_LED 57 +#define OPAL_RESERVED1 58 +#define OPAL_RESERVED2 59 +#define OPAL_PCI_NEXT_ERROR 60 +#define OPAL_PCI_EEH_FREEZE_STATUS2 61 +#define OPAL_PCI_POLL 62 +#define OPAL_PCI_MSI_EOI 63 +#define OPAL_PCI_GET_PHB_DIAG_DATA2 64 +#define OPAL_XSCOM_READ 65 +#define OPAL_XSCOM_WRITE 66 +#define OPAL_LPC_READ 67 +#define OPAL_LPC_WRITE 68 +#define OPAL_RETURN_CPU 69 +#define OPAL_REINIT_CPUS 70 +#define OPAL_ELOG_READ 71 +#define OPAL_ELOG_WRITE 72 +#define OPAL_ELOG_ACK 73 +#define OPAL_ELOG_RESEND 74 +#define OPAL_ELOG_SIZE 75 +#define OPAL_FLASH_VALIDATE 76 +#define OPAL_FLASH_MANAGE 77 +#define OPAL_FLASH_UPDATE 78 +#define OPAL_RESYNC_TIMEBASE 79 +#define OPAL_CHECK_TOKEN 80 +#define OPAL_DUMP_INIT 81 +#define OPAL_DUMP_INFO 82 +#define OPAL_DUMP_READ 83 +#define OPAL_DUMP_ACK 84 +#define OPAL_GET_MSG 85 +#define OPAL_CHECK_ASYNC_COMPLETION 86 +#define OPAL_SYNC_HOST_REBOOT 87 +#define OPAL_SENSOR_READ 88 +#define OPAL_GET_PARAM 89 +#define OPAL_SET_PARAM 90 +#define OPAL_DUMP_RESEND 91 +#define OPAL_PCI_SET_PHB_CXL_MODE 93 +#define OPAL_DUMP_INFO2 94 +#define OPAL_PCI_ERR_INJECT 96 +#define OPAL_PCI_EEH_FREEZE_SET 97 +#define OPAL_HANDLE_HMI 98 +#define OPAL_CONFIG_CPU_IDLE_STATE 99 +#define OPAL_SLW_SET_REG 100 +#define OPAL_REGISTER_DUMP_REGION 101 +#define OPAL_UNREGISTER_DUMP_REGION 102 +#define OPAL_WRITE_TPO 103 +#define OPAL_READ_TPO 104 +#define OPAL_IPMI_SEND 107 +#define OPAL_IPMI_RECV 108 +#define OPAL_I2C_REQUEST 109 + +/* Device tree flags */ + +/* Flags set in power-mgmt nodes in device tree if + * respective idle states are supported in the platform. + */ +#define OPAL_PM_NAP_ENABLED 0x00010000 +#define OPAL_PM_SLEEP_ENABLED 0x00020000 +#define OPAL_PM_WINKLE_ENABLED 0x00040000 +#define OPAL_PM_SLEEP_ENABLED_ER1 0x00080000 + +#ifndef __ASSEMBLY__ + +/* Other enums */ +enum OpalVendorApiTokens { + OPAL_START_VENDOR_API_RANGE = 1000, OPAL_END_VENDOR_API_RANGE = 1999 +}; + +enum OpalFreezeState { + OPAL_EEH_STOPPED_NOT_FROZEN = 0, + OPAL_EEH_STOPPED_MMIO_FREEZE = 1, + OPAL_EEH_STOPPED_DMA_FREEZE = 2, + OPAL_EEH_STOPPED_MMIO_DMA_FREEZE = 3, + OPAL_EEH_STOPPED_RESET = 4, + OPAL_EEH_STOPPED_TEMP_UNAVAIL = 5, + OPAL_EEH_STOPPED_PERM_UNAVAIL = 6 +}; + +enum OpalEehFreezeActionToken { + OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO = 1, + OPAL_EEH_ACTION_CLEAR_FREEZE_DMA = 2, + OPAL_EEH_ACTION_CLEAR_FREEZE_ALL = 3, + + OPAL_EEH_ACTION_SET_FREEZE_MMIO = 1, + OPAL_EEH_ACTION_SET_FREEZE_DMA = 2, + OPAL_EEH_ACTION_SET_FREEZE_ALL = 3 +}; + +enum OpalPciStatusToken { + OPAL_EEH_NO_ERROR = 0, + OPAL_EEH_IOC_ERROR = 1, + OPAL_EEH_PHB_ERROR = 2, + OPAL_EEH_PE_ERROR = 3, + OPAL_EEH_PE_MMIO_ERROR = 4, + OPAL_EEH_PE_DMA_ERROR = 5 +}; + +enum OpalPciErrorSeverity { + OPAL_EEH_SEV_NO_ERROR = 0, + OPAL_EEH_SEV_IOC_DEAD = 1, + OPAL_EEH_SEV_PHB_DEAD = 2, + OPAL_EEH_SEV_PHB_FENCED = 3, + OPAL_EEH_SEV_PE_ER = 4, + OPAL_EEH_SEV_INF = 5 +}; + +enum OpalErrinjectType { + OPAL_ERR_INJECT_TYPE_IOA_BUS_ERR = 0, + OPAL_ERR_INJECT_TYPE_IOA_BUS_ERR64 = 1, +}; + +enum OpalErrinjectFunc { + /* IOA bus specific errors */ + OPAL_ERR_INJECT_FUNC_IOA_LD_MEM_ADDR = 0, + OPAL_ERR_INJECT_FUNC_IOA_LD_MEM_DATA = 1, + OPAL_ERR_INJECT_FUNC_IOA_LD_IO_ADDR = 2, + OPAL_ERR_INJECT_FUNC_IOA_LD_IO_DATA = 3, + OPAL_ERR_INJECT_FUNC_IOA_LD_CFG_ADDR = 4, + OPAL_ERR_INJECT_FUNC_IOA_LD_CFG_DATA = 5, + OPAL_ERR_INJECT_FUNC_IOA_ST_MEM_ADDR = 6, + OPAL_ERR_INJECT_FUNC_IOA_ST_MEM_DATA = 7, + OPAL_ERR_INJECT_FUNC_IOA_ST_IO_ADDR = 8, + OPAL_ERR_INJECT_FUNC_IOA_ST_IO_DATA = 9, + OPAL_ERR_INJECT_FUNC_IOA_ST_CFG_ADDR = 10, + OPAL_ERR_INJECT_FUNC_IOA_ST_CFG_DATA = 11, + OPAL_ERR_INJECT_FUNC_IOA_DMA_RD_ADDR = 12, + OPAL_ERR_INJECT_FUNC_IOA_DMA_RD_DATA = 13, + OPAL_ERR_INJECT_FUNC_IOA_DMA_RD_MASTER = 14, + OPAL_ERR_INJECT_FUNC_IOA_DMA_RD_TARGET = 15, + OPAL_ERR_INJECT_FUNC_IOA_DMA_WR_ADDR = 16, + OPAL_ERR_INJECT_FUNC_IOA_DMA_WR_DATA = 17, + OPAL_ERR_INJECT_FUNC_IOA_DMA_WR_MASTER = 18, + OPAL_ERR_INJECT_FUNC_IOA_DMA_WR_TARGET = 19, +}; + +enum OpalShpcAction { + OPAL_SHPC_GET_LINK_STATE = 0, + OPAL_SHPC_GET_SLOT_STATE = 1 +}; + +enum OpalShpcLinkState { + OPAL_SHPC_LINK_DOWN = 0, + OPAL_SHPC_LINK_UP = 1 +}; + +enum OpalMmioWindowType { + OPAL_M32_WINDOW_TYPE = 1, + OPAL_M64_WINDOW_TYPE = 2, + OPAL_IO_WINDOW_TYPE = 3 +}; + +enum OpalShpcSlotState { + OPAL_SHPC_DEV_NOT_PRESENT = 0, + OPAL_SHPC_DEV_PRESENT = 1 +}; + +enum OpalExceptionHandler { + OPAL_MACHINE_CHECK_HANDLER = 1, + OPAL_HYPERVISOR_MAINTENANCE_HANDLER = 2, + OPAL_SOFTPATCH_HANDLER = 3 +}; + +enum OpalPendingState { + OPAL_EVENT_OPAL_INTERNAL = 0x1, + OPAL_EVENT_NVRAM = 0x2, + OPAL_EVENT_RTC = 0x4, + OPAL_EVENT_CONSOLE_OUTPUT = 0x8, + OPAL_EVENT_CONSOLE_INPUT = 0x10, + OPAL_EVENT_ERROR_LOG_AVAIL = 0x20, + OPAL_EVENT_ERROR_LOG = 0x40, + OPAL_EVENT_EPOW = 0x80, + OPAL_EVENT_LED_STATUS = 0x100, + OPAL_EVENT_PCI_ERROR = 0x200, + OPAL_EVENT_DUMP_AVAIL = 0x400, + OPAL_EVENT_MSG_PENDING = 0x800, +}; + +enum OpalMessageType { + OPAL_MSG_ASYNC_COMP = 0, /* params[0] = token, params[1] = rc, + * additional params function-specific + */ + OPAL_MSG_MEM_ERR, + OPAL_MSG_EPOW, + OPAL_MSG_SHUTDOWN, /* params[0] = 1 reboot, 0 shutdown */ + OPAL_MSG_HMI_EVT, + OPAL_MSG_TYPE_MAX, +}; + +enum OpalThreadStatus { + OPAL_THREAD_INACTIVE = 0x0, + OPAL_THREAD_STARTED = 0x1, + OPAL_THREAD_UNAVAILABLE = 0x2 /* opal-v3 */ +}; + +enum OpalPciBusCompare { + OpalPciBusAny = 0, /* Any bus number match */ + OpalPciBus3Bits = 2, /* Match top 3 bits of bus number */ + OpalPciBus4Bits = 3, /* Match top 4 bits of bus number */ + OpalPciBus5Bits = 4, /* Match top 5 bits of bus number */ + OpalPciBus6Bits = 5, /* Match top 6 bits of bus number */ + OpalPciBus7Bits = 6, /* Match top 7 bits of bus number */ + OpalPciBusAll = 7, /* Match bus number exactly */ +}; + +enum OpalDeviceCompare { + OPAL_IGNORE_RID_DEVICE_NUMBER = 0, + OPAL_COMPARE_RID_DEVICE_NUMBER = 1 +}; + +enum OpalFuncCompare { + OPAL_IGNORE_RID_FUNCTION_NUMBER = 0, + OPAL_COMPARE_RID_FUNCTION_NUMBER = 1 +}; + +enum OpalPeAction { + OPAL_UNMAP_PE = 0, + OPAL_MAP_PE = 1 +}; + +enum OpalPeltvAction { + OPAL_REMOVE_PE_FROM_DOMAIN = 0, + OPAL_ADD_PE_TO_DOMAIN = 1 +}; + +enum OpalMveEnableAction { + OPAL_DISABLE_MVE = 0, + OPAL_ENABLE_MVE = 1 +}; + +enum OpalM64EnableAction { + OPAL_DISABLE_M64 = 0, + OPAL_ENABLE_M64_SPLIT = 1, + OPAL_ENABLE_M64_NON_SPLIT = 2 +}; + +enum OpalPciResetScope { + OPAL_RESET_PHB_COMPLETE = 1, + OPAL_RESET_PCI_LINK = 2, + OPAL_RESET_PHB_ERROR = 3, + OPAL_RESET_PCI_HOT = 4, + OPAL_RESET_PCI_FUNDAMENTAL = 5, + OPAL_RESET_PCI_IODA_TABLE = 6 +}; + +enum OpalPciReinitScope { + OPAL_REINIT_PCI_DEV = 1000 +}; + +enum OpalPciResetState { + OPAL_DEASSERT_RESET = 0, + OPAL_ASSERT_RESET = 1 +}; + +enum OpalPciMaskAction { + OPAL_UNMASK_ERROR_TYPE = 0, + OPAL_MASK_ERROR_TYPE = 1 +}; + +enum OpalSlotLedType { + OPAL_SLOT_LED_ID_TYPE = 0, + OPAL_SLOT_LED_FAULT_TYPE = 1 +}; + +enum OpalLedAction { + OPAL_TURN_OFF_LED = 0, + OPAL_TURN_ON_LED = 1, + OPAL_QUERY_LED_STATE_AFTER_BUSY = 2 +}; + +enum OpalEpowStatus { + OPAL_EPOW_NONE = 0, + OPAL_EPOW_UPS = 1, + OPAL_EPOW_OVER_AMBIENT_TEMP = 2, + OPAL_EPOW_OVER_INTERNAL_TEMP = 3 +}; + +/* + * Address cycle types for LPC accesses. These also correspond + * to the content of the first cell of the "reg" property for + * device nodes on the LPC bus + */ +enum OpalLPCAddressType { + OPAL_LPC_MEM = 0, + OPAL_LPC_IO = 1, + OPAL_LPC_FW = 2, +}; + +/* System parameter permission */ +enum OpalSysparamPerm { + OPAL_SYSPARAM_READ = 0x1, + OPAL_SYSPARAM_WRITE = 0x2, + OPAL_SYSPARAM_RW = (OPAL_SYSPARAM_READ | OPAL_SYSPARAM_WRITE), +}; + +struct opal_msg { + __be32 msg_type; + __be32 reserved; + __be64 params[8]; +}; + +enum { + OPAL_IPMI_MSG_FORMAT_VERSION_1 = 1, +}; + +struct opal_ipmi_msg { + uint8_t version; + uint8_t netfn; + uint8_t cmd; + uint8_t data[]; +}; + +/* FSP memory errors handling */ +enum OpalMemErr_Version { + OpalMemErr_V1 = 1, +}; + +enum OpalMemErrType { + OPAL_MEM_ERR_TYPE_RESILIENCE = 0, + OPAL_MEM_ERR_TYPE_DYN_DALLOC, + OPAL_MEM_ERR_TYPE_SCRUB, +}; + +/* Memory Reilience error type */ +enum OpalMemErr_ResilErrType { + OPAL_MEM_RESILIENCE_CE = 0, + OPAL_MEM_RESILIENCE_UE, + OPAL_MEM_RESILIENCE_UE_SCRUB, +}; + +/* Dynamic Memory Deallocation type */ +enum OpalMemErr_DynErrType { + OPAL_MEM_DYNAMIC_DEALLOC = 0, +}; + +/* OpalMemoryErrorData->flags */ +#define OPAL_MEM_CORRECTED_ERROR 0x0001 +#define OPAL_MEM_THRESHOLD_EXCEEDED 0x0002 +#define OPAL_MEM_ACK_REQUIRED 0x8000 + +struct OpalMemoryErrorData { + enum OpalMemErr_Version version:8; /* 0x00 */ + enum OpalMemErrType type:8; /* 0x01 */ + __be16 flags; /* 0x02 */ + uint8_t reserved_1[4]; /* 0x04 */ + + union { + /* Memory Resilience corrected/uncorrected error info */ + struct { + enum OpalMemErr_ResilErrType resil_err_type:8; + uint8_t reserved_1[7]; + __be64 physical_address_start; + __be64 physical_address_end; + } resilience; + /* Dynamic memory deallocation error info */ + struct { + enum OpalMemErr_DynErrType dyn_err_type:8; + uint8_t reserved_1[7]; + __be64 physical_address_start; + __be64 physical_address_end; + } dyn_dealloc; + } u; +}; + +/* HMI interrupt event */ +enum OpalHMI_Version { + OpalHMIEvt_V1 = 1, +}; + +enum OpalHMI_Severity { + OpalHMI_SEV_NO_ERROR = 0, + OpalHMI_SEV_WARNING = 1, + OpalHMI_SEV_ERROR_SYNC = 2, + OpalHMI_SEV_FATAL = 3, +}; + +enum OpalHMI_Disposition { + OpalHMI_DISPOSITION_RECOVERED = 0, + OpalHMI_DISPOSITION_NOT_RECOVERED = 1, +}; + +enum OpalHMI_ErrType { + OpalHMI_ERROR_MALFUNC_ALERT = 0, + OpalHMI_ERROR_PROC_RECOV_DONE, + OpalHMI_ERROR_PROC_RECOV_DONE_AGAIN, + OpalHMI_ERROR_PROC_RECOV_MASKED, + OpalHMI_ERROR_TFAC, + OpalHMI_ERROR_TFMR_PARITY, + OpalHMI_ERROR_HA_OVERFLOW_WARN, + OpalHMI_ERROR_XSCOM_FAIL, + OpalHMI_ERROR_XSCOM_DONE, + OpalHMI_ERROR_SCOM_FIR, + OpalHMI_ERROR_DEBUG_TRIG_FIR, + OpalHMI_ERROR_HYP_RESOURCE, +}; + +struct OpalHMIEvent { + uint8_t version; /* 0x00 */ + uint8_t severity; /* 0x01 */ + uint8_t type; /* 0x02 */ + uint8_t disposition; /* 0x03 */ + uint8_t reserved_1[4]; /* 0x04 */ + + __be64 hmer; + /* TFMR register. Valid only for TFAC and TFMR_PARITY error type. */ + __be64 tfmr; +}; + +enum { + OPAL_P7IOC_DIAG_TYPE_NONE = 0, + OPAL_P7IOC_DIAG_TYPE_RGC = 1, + OPAL_P7IOC_DIAG_TYPE_BI = 2, + OPAL_P7IOC_DIAG_TYPE_CI = 3, + OPAL_P7IOC_DIAG_TYPE_MISC = 4, + OPAL_P7IOC_DIAG_TYPE_I2C = 5, + OPAL_P7IOC_DIAG_TYPE_LAST = 6 +}; + +struct OpalIoP7IOCErrorData { + __be16 type; + + /* GEM */ + __be64 gemXfir; + __be64 gemRfir; + __be64 gemRirqfir; + __be64 gemMask; + __be64 gemRwof; + + /* LEM */ + __be64 lemFir; + __be64 lemErrMask; + __be64 lemAction0; + __be64 lemAction1; + __be64 lemWof; + + union { + struct OpalIoP7IOCRgcErrorData { + __be64 rgcStatus; /* 3E1C10 */ + __be64 rgcLdcp; /* 3E1C18 */ + }rgc; + struct OpalIoP7IOCBiErrorData { + __be64 biLdcp0; /* 3C0100, 3C0118 */ + __be64 biLdcp1; /* 3C0108, 3C0120 */ + __be64 biLdcp2; /* 3C0110, 3C0128 */ + __be64 biFenceStatus; /* 3C0130, 3C0130 */ + + u8 biDownbound; /* BI Downbound or Upbound */ + }bi; + struct OpalIoP7IOCCiErrorData { + __be64 ciPortStatus; /* 3Dn008 */ + __be64 ciPortLdcp; /* 3Dn010 */ + + u8 ciPort; /* Index of CI port: 0/1 */ + }ci; + }; +}; + +/** + * This structure defines the overlay which will be used to store PHB error + * data upon request. + */ +enum { + OPAL_PHB_ERROR_DATA_VERSION_1 = 1, +}; + +enum { + OPAL_PHB_ERROR_DATA_TYPE_P7IOC = 1, + OPAL_PHB_ERROR_DATA_TYPE_PHB3 = 2 +}; + +enum { + OPAL_P7IOC_NUM_PEST_REGS = 128, + OPAL_PHB3_NUM_PEST_REGS = 256 +}; + +/* CAPI modes for PHB */ +enum { + OPAL_PHB_CAPI_MODE_PCIE = 0, + OPAL_PHB_CAPI_MODE_CAPI = 1, + OPAL_PHB_CAPI_MODE_SNOOP_OFF = 2, + OPAL_PHB_CAPI_MODE_SNOOP_ON = 3, +}; + +struct OpalIoPhbErrorCommon { + __be32 version; + __be32 ioType; + __be32 len; +}; + +struct OpalIoP7IOCPhbErrorData { + struct OpalIoPhbErrorCommon common; + + __be32 brdgCtl; + + // P7IOC utl regs + __be32 portStatusReg; + __be32 rootCmplxStatus; + __be32 busAgentStatus; + + // P7IOC cfg regs + __be32 deviceStatus; + __be32 slotStatus; + __be32 linkStatus; + __be32 devCmdStatus; + __be32 devSecStatus; + + // cfg AER regs + __be32 rootErrorStatus; + __be32 uncorrErrorStatus; + __be32 corrErrorStatus; + __be32 tlpHdr1; + __be32 tlpHdr2; + __be32 tlpHdr3; + __be32 tlpHdr4; + __be32 sourceId; + + __be32 rsv3; + + // Record data about the call to allocate a buffer. + __be64 errorClass; + __be64 correlator; + + //P7IOC MMIO Error Regs + __be64 p7iocPlssr; // n120 + __be64 p7iocCsr; // n110 + __be64 lemFir; // nC00 + __be64 lemErrorMask; // nC18 + __be64 lemWOF; // nC40 + __be64 phbErrorStatus; // nC80 + __be64 phbFirstErrorStatus; // nC88 + __be64 phbErrorLog0; // nCC0 + __be64 phbErrorLog1; // nCC8 + __be64 mmioErrorStatus; // nD00 + __be64 mmioFirstErrorStatus; // nD08 + __be64 mmioErrorLog0; // nD40 + __be64 mmioErrorLog1; // nD48 + __be64 dma0ErrorStatus; // nD80 + __be64 dma0FirstErrorStatus; // nD88 + __be64 dma0ErrorLog0; // nDC0 + __be64 dma0ErrorLog1; // nDC8 + __be64 dma1ErrorStatus; // nE00 + __be64 dma1FirstErrorStatus; // nE08 + __be64 dma1ErrorLog0; // nE40 + __be64 dma1ErrorLog1; // nE48 + __be64 pestA[OPAL_P7IOC_NUM_PEST_REGS]; + __be64 pestB[OPAL_P7IOC_NUM_PEST_REGS]; +}; + +struct OpalIoPhb3ErrorData { + struct OpalIoPhbErrorCommon common; + + __be32 brdgCtl; + + /* PHB3 UTL regs */ + __be32 portStatusReg; + __be32 rootCmplxStatus; + __be32 busAgentStatus; + + /* PHB3 cfg regs */ + __be32 deviceStatus; + __be32 slotStatus; + __be32 linkStatus; + __be32 devCmdStatus; + __be32 devSecStatus; + + /* cfg AER regs */ + __be32 rootErrorStatus; + __be32 uncorrErrorStatus; + __be32 corrErrorStatus; + __be32 tlpHdr1; + __be32 tlpHdr2; + __be32 tlpHdr3; + __be32 tlpHdr4; + __be32 sourceId; + + __be32 rsv3; + + /* Record data about the call to allocate a buffer */ + __be64 errorClass; + __be64 correlator; + + __be64 nFir; /* 000 */ + __be64 nFirMask; /* 003 */ + __be64 nFirWOF; /* 008 */ + + /* PHB3 MMIO Error Regs */ + __be64 phbPlssr; /* 120 */ + __be64 phbCsr; /* 110 */ + __be64 lemFir; /* C00 */ + __be64 lemErrorMask; /* C18 */ + __be64 lemWOF; /* C40 */ + __be64 phbErrorStatus; /* C80 */ + __be64 phbFirstErrorStatus; /* C88 */ + __be64 phbErrorLog0; /* CC0 */ + __be64 phbErrorLog1; /* CC8 */ + __be64 mmioErrorStatus; /* D00 */ + __be64 mmioFirstErrorStatus; /* D08 */ + __be64 mmioErrorLog0; /* D40 */ + __be64 mmioErrorLog1; /* D48 */ + __be64 dma0ErrorStatus; /* D80 */ + __be64 dma0FirstErrorStatus; /* D88 */ + __be64 dma0ErrorLog0; /* DC0 */ + __be64 dma0ErrorLog1; /* DC8 */ + __be64 dma1ErrorStatus; /* E00 */ + __be64 dma1FirstErrorStatus; /* E08 */ + __be64 dma1ErrorLog0; /* E40 */ + __be64 dma1ErrorLog1; /* E48 */ + __be64 pestA[OPAL_PHB3_NUM_PEST_REGS]; + __be64 pestB[OPAL_PHB3_NUM_PEST_REGS]; +}; + +enum { + OPAL_REINIT_CPUS_HILE_BE = (1 << 0), + OPAL_REINIT_CPUS_HILE_LE = (1 << 1), +}; + +typedef struct oppanel_line { + const char * line; + uint64_t line_len; +} oppanel_line_t; + +/* + * SG entries + * + * WARNING: The current implementation requires each entry + * to represent a block that is 4k aligned *and* each block + * size except the last one in the list to be as well. + */ +struct opal_sg_entry { + __be64 data; + __be64 length; +}; + +/* SG list */ +struct opal_sg_list { + __be64 length; + __be64 next; + struct opal_sg_entry entry[]; +}; + +/* + * Dump region ID range usable by the OS + */ +#define OPAL_DUMP_REGION_HOST_START 0x80 +#define OPAL_DUMP_REGION_LOG_BUF 0x80 +#define OPAL_DUMP_REGION_HOST_END 0xFF + +/* OPAL I2C request */ +struct opal_i2c_request { + uint8_t type; +#define OPAL_I2C_RAW_READ 0 +#define OPAL_I2C_RAW_WRITE 1 +#define OPAL_I2C_SM_READ 2 +#define OPAL_I2C_SM_WRITE 3 + uint8_t flags; +#define OPAL_I2C_ADDR_10 0x01 /* Not supported yet */ + uint8_t subaddr_sz; /* Max 4 */ + uint8_t reserved; + __be16 addr; /* 7 or 10 bit address */ + __be16 reserved2; + __be32 subaddr; /* Sub-address if any */ + __be32 size; /* Data size */ + __be64 buffer_ra; /* Buffer real address */ +}; + +#endif /* __ASSEMBLY__ */ + +#endif /* __OPAL_API_H */ diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index 9ee0a30a02ce..65c89dd2f604 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h @@ -9,755 +9,17 @@ * 2 of the License, or (at your option) any later version. */ -#ifndef __OPAL_H -#define __OPAL_H +#ifndef _ASM_POWERPC_OPAL_H +#define _ASM_POWERPC_OPAL_H -#ifndef __ASSEMBLY__ -/* - * SG entry - * - * WARNING: The current implementation requires each entry - * to represent a block that is 4k aligned *and* each block - * size except the last one in the list to be as well. - */ -struct opal_sg_entry { - __be64 data; - __be64 length; -}; - -/* SG list */ -struct opal_sg_list { - __be64 length; - __be64 next; - struct opal_sg_entry entry[]; -}; - -/* We calculate number of sg entries based on PAGE_SIZE */ -#define SG_ENTRIES_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct opal_sg_entry)) - -#endif /* __ASSEMBLY__ */ - -/****** OPAL APIs ******/ - -/* Return codes */ -#define OPAL_SUCCESS 0 -#define OPAL_PARAMETER -1 -#define OPAL_BUSY -2 -#define OPAL_PARTIAL -3 -#define OPAL_CONSTRAINED -4 -#define OPAL_CLOSED -5 -#define OPAL_HARDWARE -6 -#define OPAL_UNSUPPORTED -7 -#define OPAL_PERMISSION -8 -#define OPAL_NO_MEM -9 -#define OPAL_RESOURCE -10 -#define OPAL_INTERNAL_ERROR -11 -#define OPAL_BUSY_EVENT -12 -#define OPAL_HARDWARE_FROZEN -13 -#define OPAL_WRONG_STATE -14 -#define OPAL_ASYNC_COMPLETION -15 -#define OPAL_I2C_TIMEOUT -17 -#define OPAL_I2C_INVALID_CMD -18 -#define OPAL_I2C_LBUS_PARITY -19 -#define OPAL_I2C_BKEND_OVERRUN -20 -#define OPAL_I2C_BKEND_ACCESS -21 -#define OPAL_I2C_ARBT_LOST -22 -#define OPAL_I2C_NACK_RCVD -23 -#define OPAL_I2C_STOP_ERR -24 - -/* API Tokens (in r0) */ -#define OPAL_INVALID_CALL -1 -#define OPAL_CONSOLE_WRITE 1 -#define OPAL_CONSOLE_READ 2 -#define OPAL_RTC_READ 3 -#define OPAL_RTC_WRITE 4 -#define OPAL_CEC_POWER_DOWN 5 -#define OPAL_CEC_REBOOT 6 -#define OPAL_READ_NVRAM 7 -#define OPAL_WRITE_NVRAM 8 -#define OPAL_HANDLE_INTERRUPT 9 -#define OPAL_POLL_EVENTS 10 -#define OPAL_PCI_SET_HUB_TCE_MEMORY 11 -#define OPAL_PCI_SET_PHB_TCE_MEMORY 12 -#define OPAL_PCI_CONFIG_READ_BYTE 13 -#define OPAL_PCI_CONFIG_READ_HALF_WORD 14 -#define OPAL_PCI_CONFIG_READ_WORD 15 -#define OPAL_PCI_CONFIG_WRITE_BYTE 16 -#define OPAL_PCI_CONFIG_WRITE_HALF_WORD 17 -#define OPAL_PCI_CONFIG_WRITE_WORD 18 -#define OPAL_SET_XIVE 19 -#define OPAL_GET_XIVE 20 -#define OPAL_GET_COMPLETION_TOKEN_STATUS 21 /* obsolete */ -#define OPAL_REGISTER_OPAL_EXCEPTION_HANDLER 22 -#define OPAL_PCI_EEH_FREEZE_STATUS 23 -#define OPAL_PCI_SHPC 24 -#define OPAL_CONSOLE_WRITE_BUFFER_SPACE 25 -#define OPAL_PCI_EEH_FREEZE_CLEAR 26 -#define OPAL_PCI_PHB_MMIO_ENABLE 27 -#define OPAL_PCI_SET_PHB_MEM_WINDOW 28 -#define OPAL_PCI_MAP_PE_MMIO_WINDOW 29 -#define OPAL_PCI_SET_PHB_TABLE_MEMORY 30 -#define OPAL_PCI_SET_PE 31 -#define OPAL_PCI_SET_PELTV 32 -#define OPAL_PCI_SET_MVE 33 -#define OPAL_PCI_SET_MVE_ENABLE 34 -#define OPAL_PCI_GET_XIVE_REISSUE 35 -#define OPAL_PCI_SET_XIVE_REISSUE 36 -#define OPAL_PCI_SET_XIVE_PE 37 -#define OPAL_GET_XIVE_SOURCE 38 -#define OPAL_GET_MSI_32 39 -#define OPAL_GET_MSI_64 40 -#define OPAL_START_CPU 41 -#define OPAL_QUERY_CPU_STATUS 42 -#define OPAL_WRITE_OPPANEL 43 -#define OPAL_PCI_MAP_PE_DMA_WINDOW 44 -#define OPAL_PCI_MAP_PE_DMA_WINDOW_REAL 45 -#define OPAL_PCI_RESET 49 -#define OPAL_PCI_GET_HUB_DIAG_DATA 50 -#define OPAL_PCI_GET_PHB_DIAG_DATA 51 -#define OPAL_PCI_FENCE_PHB 52 -#define OPAL_PCI_REINIT 53 -#define OPAL_PCI_MASK_PE_ERROR 54 -#define OPAL_SET_SLOT_LED_STATUS 55 -#define OPAL_GET_EPOW_STATUS 56 -#define OPAL_SET_SYSTEM_ATTENTION_LED 57 -#define OPAL_RESERVED1 58 -#define OPAL_RESERVED2 59 -#define OPAL_PCI_NEXT_ERROR 60 -#define OPAL_PCI_EEH_FREEZE_STATUS2 61 -#define OPAL_PCI_POLL 62 -#define OPAL_PCI_MSI_EOI 63 -#define OPAL_PCI_GET_PHB_DIAG_DATA2 64 -#define OPAL_XSCOM_READ 65 -#define OPAL_XSCOM_WRITE 66 -#define OPAL_LPC_READ 67 -#define OPAL_LPC_WRITE 68 -#define OPAL_RETURN_CPU 69 -#define OPAL_REINIT_CPUS 70 -#define OPAL_ELOG_READ 71 -#define OPAL_ELOG_WRITE 72 -#define OPAL_ELOG_ACK 73 -#define OPAL_ELOG_RESEND 74 -#define OPAL_ELOG_SIZE 75 -#define OPAL_FLASH_VALIDATE 76 -#define OPAL_FLASH_MANAGE 77 -#define OPAL_FLASH_UPDATE 78 -#define OPAL_RESYNC_TIMEBASE 79 -#define OPAL_CHECK_TOKEN 80 -#define OPAL_DUMP_INIT 81 -#define OPAL_DUMP_INFO 82 -#define OPAL_DUMP_READ 83 -#define OPAL_DUMP_ACK 84 -#define OPAL_GET_MSG 85 -#define OPAL_CHECK_ASYNC_COMPLETION 86 -#define OPAL_SYNC_HOST_REBOOT 87 -#define OPAL_SENSOR_READ 88 -#define OPAL_GET_PARAM 89 -#define OPAL_SET_PARAM 90 -#define OPAL_DUMP_RESEND 91 -#define OPAL_PCI_SET_PHB_CXL_MODE 93 -#define OPAL_DUMP_INFO2 94 -#define OPAL_PCI_ERR_INJECT 96 -#define OPAL_PCI_EEH_FREEZE_SET 97 -#define OPAL_HANDLE_HMI 98 -#define OPAL_CONFIG_CPU_IDLE_STATE 99 -#define OPAL_SLW_SET_REG 100 -#define OPAL_REGISTER_DUMP_REGION 101 -#define OPAL_UNREGISTER_DUMP_REGION 102 -#define OPAL_WRITE_TPO 103 -#define OPAL_READ_TPO 104 -#define OPAL_IPMI_SEND 107 -#define OPAL_IPMI_RECV 108 -#define OPAL_I2C_REQUEST 109 - -/* Device tree flags */ - -/* Flags set in power-mgmt nodes in device tree if - * respective idle states are supported in the platform. - */ -#define OPAL_PM_NAP_ENABLED 0x00010000 -#define OPAL_PM_SLEEP_ENABLED 0x00020000 -#define OPAL_PM_WINKLE_ENABLED 0x00040000 -#define OPAL_PM_SLEEP_ENABLED_ER1 0x00080000 +#include #ifndef __ASSEMBLY__ #include -/* Other enums */ -enum OpalVendorApiTokens { - OPAL_START_VENDOR_API_RANGE = 1000, OPAL_END_VENDOR_API_RANGE = 1999 -}; - -enum OpalFreezeState { - OPAL_EEH_STOPPED_NOT_FROZEN = 0, - OPAL_EEH_STOPPED_MMIO_FREEZE = 1, - OPAL_EEH_STOPPED_DMA_FREEZE = 2, - OPAL_EEH_STOPPED_MMIO_DMA_FREEZE = 3, - OPAL_EEH_STOPPED_RESET = 4, - OPAL_EEH_STOPPED_TEMP_UNAVAIL = 5, - OPAL_EEH_STOPPED_PERM_UNAVAIL = 6 -}; - -enum OpalEehFreezeActionToken { - OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO = 1, - OPAL_EEH_ACTION_CLEAR_FREEZE_DMA = 2, - OPAL_EEH_ACTION_CLEAR_FREEZE_ALL = 3, - - OPAL_EEH_ACTION_SET_FREEZE_MMIO = 1, - OPAL_EEH_ACTION_SET_FREEZE_DMA = 2, - OPAL_EEH_ACTION_SET_FREEZE_ALL = 3 -}; - -enum OpalPciStatusToken { - OPAL_EEH_NO_ERROR = 0, - OPAL_EEH_IOC_ERROR = 1, - OPAL_EEH_PHB_ERROR = 2, - OPAL_EEH_PE_ERROR = 3, - OPAL_EEH_PE_MMIO_ERROR = 4, - OPAL_EEH_PE_DMA_ERROR = 5 -}; - -enum OpalPciErrorSeverity { - OPAL_EEH_SEV_NO_ERROR = 0, - OPAL_EEH_SEV_IOC_DEAD = 1, - OPAL_EEH_SEV_PHB_DEAD = 2, - OPAL_EEH_SEV_PHB_FENCED = 3, - OPAL_EEH_SEV_PE_ER = 4, - OPAL_EEH_SEV_INF = 5 -}; - -enum OpalErrinjectType { - OPAL_ERR_INJECT_TYPE_IOA_BUS_ERR = 0, - OPAL_ERR_INJECT_TYPE_IOA_BUS_ERR64 = 1, -}; - -enum OpalErrinjectFunc { - /* IOA bus specific errors */ - OPAL_ERR_INJECT_FUNC_IOA_LD_MEM_ADDR = 0, - OPAL_ERR_INJECT_FUNC_IOA_LD_MEM_DATA = 1, - OPAL_ERR_INJECT_FUNC_IOA_LD_IO_ADDR = 2, - OPAL_ERR_INJECT_FUNC_IOA_LD_IO_DATA = 3, - OPAL_ERR_INJECT_FUNC_IOA_LD_CFG_ADDR = 4, - OPAL_ERR_INJECT_FUNC_IOA_LD_CFG_DATA = 5, - OPAL_ERR_INJECT_FUNC_IOA_ST_MEM_ADDR = 6, - OPAL_ERR_INJECT_FUNC_IOA_ST_MEM_DATA = 7, - OPAL_ERR_INJECT_FUNC_IOA_ST_IO_ADDR = 8, - OPAL_ERR_INJECT_FUNC_IOA_ST_IO_DATA = 9, - OPAL_ERR_INJECT_FUNC_IOA_ST_CFG_ADDR = 10, - OPAL_ERR_INJECT_FUNC_IOA_ST_CFG_DATA = 11, - OPAL_ERR_INJECT_FUNC_IOA_DMA_RD_ADDR = 12, - OPAL_ERR_INJECT_FUNC_IOA_DMA_RD_DATA = 13, - OPAL_ERR_INJECT_FUNC_IOA_DMA_RD_MASTER = 14, - OPAL_ERR_INJECT_FUNC_IOA_DMA_RD_TARGET = 15, - OPAL_ERR_INJECT_FUNC_IOA_DMA_WR_ADDR = 16, - OPAL_ERR_INJECT_FUNC_IOA_DMA_WR_DATA = 17, - OPAL_ERR_INJECT_FUNC_IOA_DMA_WR_MASTER = 18, - OPAL_ERR_INJECT_FUNC_IOA_DMA_WR_TARGET = 19, -}; - -enum OpalShpcAction { - OPAL_SHPC_GET_LINK_STATE = 0, - OPAL_SHPC_GET_SLOT_STATE = 1 -}; - -enum OpalShpcLinkState { - OPAL_SHPC_LINK_DOWN = 0, - OPAL_SHPC_LINK_UP = 1 -}; - -enum OpalMmioWindowType { - OPAL_M32_WINDOW_TYPE = 1, - OPAL_M64_WINDOW_TYPE = 2, - OPAL_IO_WINDOW_TYPE = 3 -}; - -enum OpalShpcSlotState { - OPAL_SHPC_DEV_NOT_PRESENT = 0, - OPAL_SHPC_DEV_PRESENT = 1 -}; - -enum OpalExceptionHandler { - OPAL_MACHINE_CHECK_HANDLER = 1, - OPAL_HYPERVISOR_MAINTENANCE_HANDLER = 2, - OPAL_SOFTPATCH_HANDLER = 3 -}; - -enum OpalPendingState { - OPAL_EVENT_OPAL_INTERNAL = 0x1, - OPAL_EVENT_NVRAM = 0x2, - OPAL_EVENT_RTC = 0x4, - OPAL_EVENT_CONSOLE_OUTPUT = 0x8, - OPAL_EVENT_CONSOLE_INPUT = 0x10, - OPAL_EVENT_ERROR_LOG_AVAIL = 0x20, - OPAL_EVENT_ERROR_LOG = 0x40, - OPAL_EVENT_EPOW = 0x80, - OPAL_EVENT_LED_STATUS = 0x100, - OPAL_EVENT_PCI_ERROR = 0x200, - OPAL_EVENT_DUMP_AVAIL = 0x400, - OPAL_EVENT_MSG_PENDING = 0x800, -}; - -enum OpalMessageType { - OPAL_MSG_ASYNC_COMP = 0, /* params[0] = token, params[1] = rc, - * additional params function-specific - */ - OPAL_MSG_MEM_ERR, - OPAL_MSG_EPOW, - OPAL_MSG_SHUTDOWN, /* params[0] = 1 reboot, 0 shutdown */ - OPAL_MSG_HMI_EVT, - OPAL_MSG_TYPE_MAX, -}; - -enum OpalThreadStatus { - OPAL_THREAD_INACTIVE = 0x0, - OPAL_THREAD_STARTED = 0x1, - OPAL_THREAD_UNAVAILABLE = 0x2 /* opal-v3 */ -}; - -enum OpalPciBusCompare { - OpalPciBusAny = 0, /* Any bus number match */ - OpalPciBus3Bits = 2, /* Match top 3 bits of bus number */ - OpalPciBus4Bits = 3, /* Match top 4 bits of bus number */ - OpalPciBus5Bits = 4, /* Match top 5 bits of bus number */ - OpalPciBus6Bits = 5, /* Match top 6 bits of bus number */ - OpalPciBus7Bits = 6, /* Match top 7 bits of bus number */ - OpalPciBusAll = 7, /* Match bus number exactly */ -}; - -enum OpalDeviceCompare { - OPAL_IGNORE_RID_DEVICE_NUMBER = 0, - OPAL_COMPARE_RID_DEVICE_NUMBER = 1 -}; - -enum OpalFuncCompare { - OPAL_IGNORE_RID_FUNCTION_NUMBER = 0, - OPAL_COMPARE_RID_FUNCTION_NUMBER = 1 -}; - -enum OpalPeAction { - OPAL_UNMAP_PE = 0, - OPAL_MAP_PE = 1 -}; - -enum OpalPeltvAction { - OPAL_REMOVE_PE_FROM_DOMAIN = 0, - OPAL_ADD_PE_TO_DOMAIN = 1 -}; - -enum OpalMveEnableAction { - OPAL_DISABLE_MVE = 0, - OPAL_ENABLE_MVE = 1 -}; - -enum OpalM64EnableAction { - OPAL_DISABLE_M64 = 0, - OPAL_ENABLE_M64_SPLIT = 1, - OPAL_ENABLE_M64_NON_SPLIT = 2 -}; - -enum OpalPciResetScope { - OPAL_RESET_PHB_COMPLETE = 1, - OPAL_RESET_PCI_LINK = 2, - OPAL_RESET_PHB_ERROR = 3, - OPAL_RESET_PCI_HOT = 4, - OPAL_RESET_PCI_FUNDAMENTAL = 5, - OPAL_RESET_PCI_IODA_TABLE = 6 -}; - -enum OpalPciReinitScope { - OPAL_REINIT_PCI_DEV = 1000 -}; - -enum OpalPciResetState { - OPAL_DEASSERT_RESET = 0, - OPAL_ASSERT_RESET = 1 -}; - -enum OpalPciMaskAction { - OPAL_UNMASK_ERROR_TYPE = 0, - OPAL_MASK_ERROR_TYPE = 1 -}; - -enum OpalSlotLedType { - OPAL_SLOT_LED_ID_TYPE = 0, - OPAL_SLOT_LED_FAULT_TYPE = 1 -}; - -enum OpalLedAction { - OPAL_TURN_OFF_LED = 0, - OPAL_TURN_ON_LED = 1, - OPAL_QUERY_LED_STATE_AFTER_BUSY = 2 -}; - -enum OpalEpowStatus { - OPAL_EPOW_NONE = 0, - OPAL_EPOW_UPS = 1, - OPAL_EPOW_OVER_AMBIENT_TEMP = 2, - OPAL_EPOW_OVER_INTERNAL_TEMP = 3 -}; - -/* - * Address cycle types for LPC accesses. These also correspond - * to the content of the first cell of the "reg" property for - * device nodes on the LPC bus - */ -enum OpalLPCAddressType { - OPAL_LPC_MEM = 0, - OPAL_LPC_IO = 1, - OPAL_LPC_FW = 2, -}; - -/* System parameter permission */ -enum OpalSysparamPerm { - OPAL_SYSPARAM_READ = 0x1, - OPAL_SYSPARAM_WRITE = 0x2, - OPAL_SYSPARAM_RW = (OPAL_SYSPARAM_READ | OPAL_SYSPARAM_WRITE), -}; - -struct opal_msg { - __be32 msg_type; - __be32 reserved; - __be64 params[8]; -}; - -enum { - OPAL_IPMI_MSG_FORMAT_VERSION_1 = 1, -}; - -struct opal_ipmi_msg { - uint8_t version; - uint8_t netfn; - uint8_t cmd; - uint8_t data[]; -}; - -/* FSP memory errors handling */ -enum OpalMemErr_Version { - OpalMemErr_V1 = 1, -}; - -enum OpalMemErrType { - OPAL_MEM_ERR_TYPE_RESILIENCE = 0, - OPAL_MEM_ERR_TYPE_DYN_DALLOC, - OPAL_MEM_ERR_TYPE_SCRUB, -}; - -/* Memory Reilience error type */ -enum OpalMemErr_ResilErrType { - OPAL_MEM_RESILIENCE_CE = 0, - OPAL_MEM_RESILIENCE_UE, - OPAL_MEM_RESILIENCE_UE_SCRUB, -}; - -/* Dynamic Memory Deallocation type */ -enum OpalMemErr_DynErrType { - OPAL_MEM_DYNAMIC_DEALLOC = 0, -}; - -/* OpalMemoryErrorData->flags */ -#define OPAL_MEM_CORRECTED_ERROR 0x0001 -#define OPAL_MEM_THRESHOLD_EXCEEDED 0x0002 -#define OPAL_MEM_ACK_REQUIRED 0x8000 - -struct OpalMemoryErrorData { - enum OpalMemErr_Version version:8; /* 0x00 */ - enum OpalMemErrType type:8; /* 0x01 */ - __be16 flags; /* 0x02 */ - uint8_t reserved_1[4]; /* 0x04 */ - - union { - /* Memory Resilience corrected/uncorrected error info */ - struct { - enum OpalMemErr_ResilErrType resil_err_type:8; - uint8_t reserved_1[7]; - __be64 physical_address_start; - __be64 physical_address_end; - } resilience; - /* Dynamic memory deallocation error info */ - struct { - enum OpalMemErr_DynErrType dyn_err_type:8; - uint8_t reserved_1[7]; - __be64 physical_address_start; - __be64 physical_address_end; - } dyn_dealloc; - } u; -}; - -/* HMI interrupt event */ -enum OpalHMI_Version { - OpalHMIEvt_V1 = 1, -}; - -enum OpalHMI_Severity { - OpalHMI_SEV_NO_ERROR = 0, - OpalHMI_SEV_WARNING = 1, - OpalHMI_SEV_ERROR_SYNC = 2, - OpalHMI_SEV_FATAL = 3, -}; - -enum OpalHMI_Disposition { - OpalHMI_DISPOSITION_RECOVERED = 0, - OpalHMI_DISPOSITION_NOT_RECOVERED = 1, -}; - -enum OpalHMI_ErrType { - OpalHMI_ERROR_MALFUNC_ALERT = 0, - OpalHMI_ERROR_PROC_RECOV_DONE, - OpalHMI_ERROR_PROC_RECOV_DONE_AGAIN, - OpalHMI_ERROR_PROC_RECOV_MASKED, - OpalHMI_ERROR_TFAC, - OpalHMI_ERROR_TFMR_PARITY, - OpalHMI_ERROR_HA_OVERFLOW_WARN, - OpalHMI_ERROR_XSCOM_FAIL, - OpalHMI_ERROR_XSCOM_DONE, - OpalHMI_ERROR_SCOM_FIR, - OpalHMI_ERROR_DEBUG_TRIG_FIR, - OpalHMI_ERROR_HYP_RESOURCE, -}; - -struct OpalHMIEvent { - uint8_t version; /* 0x00 */ - uint8_t severity; /* 0x01 */ - uint8_t type; /* 0x02 */ - uint8_t disposition; /* 0x03 */ - uint8_t reserved_1[4]; /* 0x04 */ - - __be64 hmer; - /* TFMR register. Valid only for TFAC and TFMR_PARITY error type. */ - __be64 tfmr; -}; - -enum { - OPAL_P7IOC_DIAG_TYPE_NONE = 0, - OPAL_P7IOC_DIAG_TYPE_RGC = 1, - OPAL_P7IOC_DIAG_TYPE_BI = 2, - OPAL_P7IOC_DIAG_TYPE_CI = 3, - OPAL_P7IOC_DIAG_TYPE_MISC = 4, - OPAL_P7IOC_DIAG_TYPE_I2C = 5, - OPAL_P7IOC_DIAG_TYPE_LAST = 6 -}; - -struct OpalIoP7IOCErrorData { - __be16 type; - - /* GEM */ - __be64 gemXfir; - __be64 gemRfir; - __be64 gemRirqfir; - __be64 gemMask; - __be64 gemRwof; - - /* LEM */ - __be64 lemFir; - __be64 lemErrMask; - __be64 lemAction0; - __be64 lemAction1; - __be64 lemWof; - - union { - struct OpalIoP7IOCRgcErrorData { - __be64 rgcStatus; /* 3E1C10 */ - __be64 rgcLdcp; /* 3E1C18 */ - }rgc; - struct OpalIoP7IOCBiErrorData { - __be64 biLdcp0; /* 3C0100, 3C0118 */ - __be64 biLdcp1; /* 3C0108, 3C0120 */ - __be64 biLdcp2; /* 3C0110, 3C0128 */ - __be64 biFenceStatus; /* 3C0130, 3C0130 */ - - u8 biDownbound; /* BI Downbound or Upbound */ - }bi; - struct OpalIoP7IOCCiErrorData { - __be64 ciPortStatus; /* 3Dn008 */ - __be64 ciPortLdcp; /* 3Dn010 */ - - u8 ciPort; /* Index of CI port: 0/1 */ - }ci; - }; -}; - -/** - * This structure defines the overlay which will be used to store PHB error - * data upon request. - */ -enum { - OPAL_PHB_ERROR_DATA_VERSION_1 = 1, -}; - -enum { - OPAL_PHB_ERROR_DATA_TYPE_P7IOC = 1, - OPAL_PHB_ERROR_DATA_TYPE_PHB3 = 2 -}; - -enum { - OPAL_P7IOC_NUM_PEST_REGS = 128, - OPAL_PHB3_NUM_PEST_REGS = 256 -}; - -/* CAPI modes for PHB */ -enum { - OPAL_PHB_CAPI_MODE_PCIE = 0, - OPAL_PHB_CAPI_MODE_CAPI = 1, - OPAL_PHB_CAPI_MODE_SNOOP_OFF = 2, - OPAL_PHB_CAPI_MODE_SNOOP_ON = 3, -}; - -struct OpalIoPhbErrorCommon { - __be32 version; - __be32 ioType; - __be32 len; -}; - -struct OpalIoP7IOCPhbErrorData { - struct OpalIoPhbErrorCommon common; - - __be32 brdgCtl; - - // P7IOC utl regs - __be32 portStatusReg; - __be32 rootCmplxStatus; - __be32 busAgentStatus; - - // P7IOC cfg regs - __be32 deviceStatus; - __be32 slotStatus; - __be32 linkStatus; - __be32 devCmdStatus; - __be32 devSecStatus; - - // cfg AER regs - __be32 rootErrorStatus; - __be32 uncorrErrorStatus; - __be32 corrErrorStatus; - __be32 tlpHdr1; - __be32 tlpHdr2; - __be32 tlpHdr3; - __be32 tlpHdr4; - __be32 sourceId; - - __be32 rsv3; - - // Record data about the call to allocate a buffer. - __be64 errorClass; - __be64 correlator; - - //P7IOC MMIO Error Regs - __be64 p7iocPlssr; // n120 - __be64 p7iocCsr; // n110 - __be64 lemFir; // nC00 - __be64 lemErrorMask; // nC18 - __be64 lemWOF; // nC40 - __be64 phbErrorStatus; // nC80 - __be64 phbFirstErrorStatus; // nC88 - __be64 phbErrorLog0; // nCC0 - __be64 phbErrorLog1; // nCC8 - __be64 mmioErrorStatus; // nD00 - __be64 mmioFirstErrorStatus; // nD08 - __be64 mmioErrorLog0; // nD40 - __be64 mmioErrorLog1; // nD48 - __be64 dma0ErrorStatus; // nD80 - __be64 dma0FirstErrorStatus; // nD88 - __be64 dma0ErrorLog0; // nDC0 - __be64 dma0ErrorLog1; // nDC8 - __be64 dma1ErrorStatus; // nE00 - __be64 dma1FirstErrorStatus; // nE08 - __be64 dma1ErrorLog0; // nE40 - __be64 dma1ErrorLog1; // nE48 - __be64 pestA[OPAL_P7IOC_NUM_PEST_REGS]; - __be64 pestB[OPAL_P7IOC_NUM_PEST_REGS]; -}; - -struct OpalIoPhb3ErrorData { - struct OpalIoPhbErrorCommon common; - - __be32 brdgCtl; - - /* PHB3 UTL regs */ - __be32 portStatusReg; - __be32 rootCmplxStatus; - __be32 busAgentStatus; - - /* PHB3 cfg regs */ - __be32 deviceStatus; - __be32 slotStatus; - __be32 linkStatus; - __be32 devCmdStatus; - __be32 devSecStatus; - - /* cfg AER regs */ - __be32 rootErrorStatus; - __be32 uncorrErrorStatus; - __be32 corrErrorStatus; - __be32 tlpHdr1; - __be32 tlpHdr2; - __be32 tlpHdr3; - __be32 tlpHdr4; - __be32 sourceId; - - __be32 rsv3; - - /* Record data about the call to allocate a buffer */ - __be64 errorClass; - __be64 correlator; - - __be64 nFir; /* 000 */ - __be64 nFirMask; /* 003 */ - __be64 nFirWOF; /* 008 */ - - /* PHB3 MMIO Error Regs */ - __be64 phbPlssr; /* 120 */ - __be64 phbCsr; /* 110 */ - __be64 lemFir; /* C00 */ - __be64 lemErrorMask; /* C18 */ - __be64 lemWOF; /* C40 */ - __be64 phbErrorStatus; /* C80 */ - __be64 phbFirstErrorStatus; /* C88 */ - __be64 phbErrorLog0; /* CC0 */ - __be64 phbErrorLog1; /* CC8 */ - __be64 mmioErrorStatus; /* D00 */ - __be64 mmioFirstErrorStatus; /* D08 */ - __be64 mmioErrorLog0; /* D40 */ - __be64 mmioErrorLog1; /* D48 */ - __be64 dma0ErrorStatus; /* D80 */ - __be64 dma0FirstErrorStatus; /* D88 */ - __be64 dma0ErrorLog0; /* DC0 */ - __be64 dma0ErrorLog1; /* DC8 */ - __be64 dma1ErrorStatus; /* E00 */ - __be64 dma1FirstErrorStatus; /* E08 */ - __be64 dma1ErrorLog0; /* E40 */ - __be64 dma1ErrorLog1; /* E48 */ - __be64 pestA[OPAL_PHB3_NUM_PEST_REGS]; - __be64 pestB[OPAL_PHB3_NUM_PEST_REGS]; -}; - -enum { - OPAL_REINIT_CPUS_HILE_BE = (1 << 0), - OPAL_REINIT_CPUS_HILE_LE = (1 << 1), -}; - -typedef struct oppanel_line { - const char * line; - uint64_t line_len; -} oppanel_line_t; - -/* OPAL I2C request */ -struct opal_i2c_request { - uint8_t type; -#define OPAL_I2C_RAW_READ 0 -#define OPAL_I2C_RAW_WRITE 1 -#define OPAL_I2C_SM_READ 2 -#define OPAL_I2C_SM_WRITE 3 - uint8_t flags; -#define OPAL_I2C_ADDR_10 0x01 /* Not supported yet */ - uint8_t subaddr_sz; /* Max 4 */ - uint8_t reserved; - __be16 addr; /* 7 or 10 bit address */ - __be16 reserved2; - __be32 subaddr; /* Sub-address if any */ - __be32 size; /* Data size */ - __be64 buffer_ra; /* Buffer real address */ -}; +/* We calculate number of sg entries based on PAGE_SIZE */ +#define SG_ENTRIES_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct opal_sg_entry)) /* /sys/firmware/opal */ extern struct kobject *opal_kobj; @@ -983,13 +245,6 @@ struct opal_sg_list *opal_vmalloc_to_sg_list(void *vmalloc_addr, unsigned long vmalloc_size); void opal_free_sg_list(struct opal_sg_list *sg); -/* - * Dump region ID range usable by the OS - */ -#define OPAL_DUMP_REGION_HOST_START 0x80 -#define OPAL_DUMP_REGION_LOG_BUF 0x80 -#define OPAL_DUMP_REGION_HOST_END 0xFF - #endif /* __ASSEMBLY__ */ -#endif /* __OPAL_H */ +#endif /* _ASM_POWERPC_OPAL_H */ -- cgit v1.2.3 From d7cf83fcaf1b1668201eae4cdd6e6fe7a2448654 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 17 Feb 2015 20:01:54 +1100 Subject: powerpc/powernv: Move opal-api.h closer to the Skiboot version This commit gets opal-api.h to mostly match the version in Skiboot as of commit ea7d806ab0ba. The exceptions are things which are not (currently) used in Linux. Most of this is just whitespace and a few things moving around. I think the diff is readable. Also OpalMessageType became opal_msg_type, requiring a change in the Linux code. Finally Skiboot and Linux disagree on CAPI vs CXL, because CAPI means something else in Linux. To handle that we just point the Linux wrapper, which is named "cxl" to the OPAL token OPAL_PCI_SET_PHB_CAPI_MODE. Signed-off-by: Michael Ellerman Reviewed-by: Stewart Smith --- arch/powerpc/include/asm/opal-api.h | 158 ++++++++++++++----------- arch/powerpc/include/asm/opal.h | 2 +- arch/powerpc/platforms/powernv/opal-wrappers.S | 2 +- arch/powerpc/platforms/powernv/opal.c | 2 +- 4 files changed, 90 insertions(+), 74 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h index a90176a428ee..2984f486f3ba 100644 --- a/arch/powerpc/include/asm/opal-api.h +++ b/arch/powerpc/include/asm/opal-api.h @@ -1,7 +1,7 @@ /* - * PowerNV OPAL definitions. + * OPAL API definitions. * - * Copyright 2011 IBM Corp. + * Copyright 2011-2015 IBM Corp. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -15,7 +15,7 @@ /****** OPAL APIs ******/ /* Return codes */ -#define OPAL_SUCCESS 0 +#define OPAL_SUCCESS 0 #define OPAL_PARAMETER -1 #define OPAL_BUSY -2 #define OPAL_PARTIAL -3 @@ -31,6 +31,7 @@ #define OPAL_HARDWARE_FROZEN -13 #define OPAL_WRONG_STATE -14 #define OPAL_ASYNC_COMPLETION -15 +#define OPAL_EMPTY -16 #define OPAL_I2C_TIMEOUT -17 #define OPAL_I2C_INVALID_CMD -18 #define OPAL_I2C_LBUS_PARITY -19 @@ -41,7 +42,8 @@ #define OPAL_I2C_STOP_ERR -24 /* API Tokens (in r0) */ -#define OPAL_INVALID_CALL -1 +#define OPAL_INVALID_CALL -1 +#define OPAL_TEST 0 #define OPAL_CONSOLE_WRITE 1 #define OPAL_CONSOLE_READ 2 #define OPAL_RTC_READ 3 @@ -84,7 +86,7 @@ #define OPAL_GET_MSI_64 40 #define OPAL_START_CPU 41 #define OPAL_QUERY_CPU_STATUS 42 -#define OPAL_WRITE_OPPANEL 43 +#define OPAL_WRITE_OPPANEL 43 /* unimplemented */ #define OPAL_PCI_MAP_PE_DMA_WINDOW 44 #define OPAL_PCI_MAP_PE_DMA_WINDOW_REAL 45 #define OPAL_PCI_RESET 49 @@ -130,8 +132,10 @@ #define OPAL_GET_PARAM 89 #define OPAL_SET_PARAM 90 #define OPAL_DUMP_RESEND 91 -#define OPAL_PCI_SET_PHB_CXL_MODE 93 +#define OPAL_ELOG_SEND 92 /* Deprecated */ +#define OPAL_PCI_SET_PHB_CAPI_MODE 93 #define OPAL_DUMP_INFO2 94 +#define OPAL_WRITE_OPPANEL_ASYNC 95 #define OPAL_PCI_ERR_INJECT 96 #define OPAL_PCI_EEH_FREEZE_SET 97 #define OPAL_HANDLE_HMI 98 @@ -141,19 +145,22 @@ #define OPAL_UNREGISTER_DUMP_REGION 102 #define OPAL_WRITE_TPO 103 #define OPAL_READ_TPO 104 +#define OPAL_GET_DPO_STATUS 105 +#define OPAL_OLD_I2C_REQUEST 106 /* Deprecated */ #define OPAL_IPMI_SEND 107 #define OPAL_IPMI_RECV 108 #define OPAL_I2C_REQUEST 109 +#define OPAL_LAST 109 /* Device tree flags */ /* Flags set in power-mgmt nodes in device tree if * respective idle states are supported in the platform. */ -#define OPAL_PM_NAP_ENABLED 0x00010000 -#define OPAL_PM_SLEEP_ENABLED 0x00020000 -#define OPAL_PM_WINKLE_ENABLED 0x00040000 -#define OPAL_PM_SLEEP_ENABLED_ER1 0x00080000 +#define OPAL_PM_NAP_ENABLED 0x00010000 +#define OPAL_PM_SLEEP_ENABLED 0x00020000 +#define OPAL_PM_WINKLE_ENABLED 0x00040000 +#define OPAL_PM_SLEEP_ENABLED_ER1 0x00080000 /* with workaround */ #ifndef __ASSEMBLY__ @@ -242,7 +249,7 @@ enum OpalShpcLinkState { enum OpalMmioWindowType { OPAL_M32_WINDOW_TYPE = 1, OPAL_M64_WINDOW_TYPE = 2, - OPAL_IO_WINDOW_TYPE = 3 + OPAL_IO_WINDOW_TYPE = 3 }; enum OpalShpcSlotState { @@ -251,35 +258,24 @@ enum OpalShpcSlotState { }; enum OpalExceptionHandler { - OPAL_MACHINE_CHECK_HANDLER = 1, + OPAL_MACHINE_CHECK_HANDLER = 1, OPAL_HYPERVISOR_MAINTENANCE_HANDLER = 2, - OPAL_SOFTPATCH_HANDLER = 3 + OPAL_SOFTPATCH_HANDLER = 3 }; enum OpalPendingState { - OPAL_EVENT_OPAL_INTERNAL = 0x1, - OPAL_EVENT_NVRAM = 0x2, - OPAL_EVENT_RTC = 0x4, - OPAL_EVENT_CONSOLE_OUTPUT = 0x8, - OPAL_EVENT_CONSOLE_INPUT = 0x10, - OPAL_EVENT_ERROR_LOG_AVAIL = 0x20, - OPAL_EVENT_ERROR_LOG = 0x40, - OPAL_EVENT_EPOW = 0x80, - OPAL_EVENT_LED_STATUS = 0x100, - OPAL_EVENT_PCI_ERROR = 0x200, - OPAL_EVENT_DUMP_AVAIL = 0x400, - OPAL_EVENT_MSG_PENDING = 0x800, -}; - -enum OpalMessageType { - OPAL_MSG_ASYNC_COMP = 0, /* params[0] = token, params[1] = rc, - * additional params function-specific - */ - OPAL_MSG_MEM_ERR, - OPAL_MSG_EPOW, - OPAL_MSG_SHUTDOWN, /* params[0] = 1 reboot, 0 shutdown */ - OPAL_MSG_HMI_EVT, - OPAL_MSG_TYPE_MAX, + OPAL_EVENT_OPAL_INTERNAL = 0x1, + OPAL_EVENT_NVRAM = 0x2, + OPAL_EVENT_RTC = 0x4, + OPAL_EVENT_CONSOLE_OUTPUT = 0x8, + OPAL_EVENT_CONSOLE_INPUT = 0x10, + OPAL_EVENT_ERROR_LOG_AVAIL = 0x20, + OPAL_EVENT_ERROR_LOG = 0x40, + OPAL_EVENT_EPOW = 0x80, + OPAL_EVENT_LED_STATUS = 0x100, + OPAL_EVENT_PCI_ERROR = 0x200, + OPAL_EVENT_DUMP_AVAIL = 0x400, + OPAL_EVENT_MSG_PENDING = 0x800, }; enum OpalThreadStatus { @@ -323,7 +319,7 @@ enum OpalMveEnableAction { OPAL_ENABLE_MVE = 1 }; -enum OpalM64EnableAction { +enum OpalM64Action { OPAL_DISABLE_M64 = 0, OPAL_ENABLE_M64_SPLIT = 1, OPAL_ENABLE_M64_NON_SPLIT = 2 @@ -339,12 +335,17 @@ enum OpalPciResetScope { }; enum OpalPciReinitScope { + /* + * Note: we chose values that do not overlap + * OpalPciResetScope as OPAL v2 used the same + * enum for both + */ OPAL_REINIT_PCI_DEV = 1000 }; enum OpalPciResetState { OPAL_DEASSERT_RESET = 0, - OPAL_ASSERT_RESET = 1 + OPAL_ASSERT_RESET = 1 }; enum OpalPciMaskAction { @@ -381,11 +382,16 @@ enum OpalLPCAddressType { OPAL_LPC_FW = 2, }; -/* System parameter permission */ -enum OpalSysparamPerm { - OPAL_SYSPARAM_READ = 0x1, - OPAL_SYSPARAM_WRITE = 0x2, - OPAL_SYSPARAM_RW = (OPAL_SYSPARAM_READ | OPAL_SYSPARAM_WRITE), +enum opal_msg_type { + OPAL_MSG_ASYNC_COMP = 0, /* params[0] = token, params[1] = rc, + * additional params function-specific + */ + OPAL_MSG_MEM_ERR, + OPAL_MSG_EPOW, + OPAL_MSG_SHUTDOWN, /* params[0] = 1 reboot, 0 shutdown */ + OPAL_MSG_HMI_EVT, + OPAL_MSG_DPO, + OPAL_MSG_TYPE_MAX, }; struct opal_msg { @@ -394,15 +400,22 @@ struct opal_msg { __be64 params[8]; }; +/* System parameter permission */ +enum OpalSysparamPerm { + OPAL_SYSPARAM_READ = 0x1, + OPAL_SYSPARAM_WRITE = 0x2, + OPAL_SYSPARAM_RW = (OPAL_SYSPARAM_READ | OPAL_SYSPARAM_WRITE), +}; + enum { OPAL_IPMI_MSG_FORMAT_VERSION_1 = 1, }; struct opal_ipmi_msg { - uint8_t version; - uint8_t netfn; - uint8_t cmd; - uint8_t data[]; + uint8_t version; + uint8_t netfn; + uint8_t cmd; + uint8_t data[]; }; /* FSP memory errors handling */ @@ -413,7 +426,6 @@ enum OpalMemErr_Version { enum OpalMemErrType { OPAL_MEM_ERR_TYPE_RESILIENCE = 0, OPAL_MEM_ERR_TYPE_DYN_DALLOC, - OPAL_MEM_ERR_TYPE_SCRUB, }; /* Memory Reilience error type */ @@ -442,17 +454,17 @@ struct OpalMemoryErrorData { union { /* Memory Resilience corrected/uncorrected error info */ struct { - enum OpalMemErr_ResilErrType resil_err_type:8; - uint8_t reserved_1[7]; - __be64 physical_address_start; - __be64 physical_address_end; + enum OpalMemErr_ResilErrType resil_err_type:8; + uint8_t reserved_1[7]; + __be64 physical_address_start; + __be64 physical_address_end; } resilience; /* Dynamic memory deallocation error info */ struct { - enum OpalMemErr_DynErrType dyn_err_type:8; - uint8_t reserved_1[7]; - __be64 physical_address_start; - __be64 physical_address_end; + enum OpalMemErr_DynErrType dyn_err_type:8; + uint8_t reserved_1[7]; + __be64 physical_address_start; + __be64 physical_address_end; } dyn_dealloc; } u; }; @@ -487,6 +499,7 @@ enum OpalHMI_ErrType { OpalHMI_ERROR_SCOM_FIR, OpalHMI_ERROR_DEBUG_TRIG_FIR, OpalHMI_ERROR_HYP_RESOURCE, + OpalHMI_ERROR_CAPP_RECOVERY, }; struct OpalHMIEvent { @@ -539,13 +552,13 @@ struct OpalIoP7IOCErrorData { __be64 biLdcp2; /* 3C0110, 3C0128 */ __be64 biFenceStatus; /* 3C0130, 3C0130 */ - u8 biDownbound; /* BI Downbound or Upbound */ + uint8_t biDownbound; /* BI Downbound or Upbound */ }bi; struct OpalIoP7IOCCiErrorData { __be64 ciPortStatus; /* 3Dn008 */ __be64 ciPortLdcp; /* 3Dn010 */ - u8 ciPort; /* Index of CI port: 0/1 */ + uint8_t ciPort; /* Index of CI port: 0/1 */ }ci; }; }; @@ -568,14 +581,6 @@ enum { OPAL_PHB3_NUM_PEST_REGS = 256 }; -/* CAPI modes for PHB */ -enum { - OPAL_PHB_CAPI_MODE_PCIE = 0, - OPAL_PHB_CAPI_MODE_CAPI = 1, - OPAL_PHB_CAPI_MODE_SNOOP_OFF = 2, - OPAL_PHB_CAPI_MODE_SNOOP_ON = 3, -}; - struct OpalIoPhbErrorCommon { __be32 version; __be32 ioType; @@ -674,11 +679,10 @@ struct OpalIoPhb3ErrorData { __be64 errorClass; __be64 correlator; + /* PHB3 MMIO Error Regs */ __be64 nFir; /* 000 */ __be64 nFirMask; /* 003 */ __be64 nFirWOF; /* 008 */ - - /* PHB3 MMIO Error Regs */ __be64 phbPlssr; /* 120 */ __be64 phbCsr; /* 110 */ __be64 lemFir; /* C00 */ @@ -710,8 +714,8 @@ enum { }; typedef struct oppanel_line { - const char * line; - uint64_t line_len; + __be64 line; + __be64 line_len; } oppanel_line_t; /* @@ -726,7 +730,11 @@ struct opal_sg_entry { __be64 length; }; -/* SG list */ +/* + * Candiate image SG list. + * + * length = VER | length + */ struct opal_sg_list { __be64 length; __be64 next; @@ -740,6 +748,14 @@ struct opal_sg_list { #define OPAL_DUMP_REGION_LOG_BUF 0x80 #define OPAL_DUMP_REGION_HOST_END 0xFF +/* CAPI modes for PHB */ +enum { + OPAL_PHB_CAPI_MODE_PCIE = 0, + OPAL_PHB_CAPI_MODE_CAPI = 1, + OPAL_PHB_CAPI_MODE_SNOOP_OFF = 2, + OPAL_PHB_CAPI_MODE_SNOOP_ON = 3, +}; + /* OPAL I2C request */ struct opal_i2c_request { uint8_t type; diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index 65c89dd2f604..0ef0fd660ac6 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h @@ -208,7 +208,7 @@ extern void hvc_opal_init_early(void); extern int opal_notifier_register(struct notifier_block *nb); extern int opal_notifier_unregister(struct notifier_block *nb); -extern int opal_message_notifier_register(enum OpalMessageType msg_type, +extern int opal_message_notifier_register(enum opal_msg_type msg_type, struct notifier_block *nb); extern void opal_notifier_enable(void); extern void opal_notifier_disable(void); diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S index 0509bca5e830..b23fe7c4bf12 100644 --- a/arch/powerpc/platforms/powernv/opal-wrappers.S +++ b/arch/powerpc/platforms/powernv/opal-wrappers.S @@ -286,7 +286,7 @@ OPAL_CALL(opal_handle_hmi, OPAL_HANDLE_HMI); OPAL_CALL(opal_slw_set_reg, OPAL_SLW_SET_REG); OPAL_CALL(opal_register_dump_region, OPAL_REGISTER_DUMP_REGION); OPAL_CALL(opal_unregister_dump_region, OPAL_UNREGISTER_DUMP_REGION); -OPAL_CALL(opal_pci_set_phb_cxl_mode, OPAL_PCI_SET_PHB_CXL_MODE); +OPAL_CALL(opal_pci_set_phb_cxl_mode, OPAL_PCI_SET_PHB_CAPI_MODE); OPAL_CALL(opal_tpo_write, OPAL_WRITE_TPO); OPAL_CALL(opal_tpo_read, OPAL_READ_TPO); OPAL_CALL(opal_ipmi_send, OPAL_IPMI_SEND); diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index 45f0d9aa3733..142a08a61bd1 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c @@ -302,7 +302,7 @@ void opal_notifier_disable(void) * Opal message notifier based on message type. Allow subscribers to get * notified for specific messgae type. */ -int opal_message_notifier_register(enum OpalMessageType msg_type, +int opal_message_notifier_register(enum opal_msg_type msg_type, struct notifier_block *nb) { if (!nb) { -- cgit v1.2.3 From b887f9e324629125fd20ce29d6a768d280572118 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 17 Feb 2015 20:01:55 +1100 Subject: powerpc/powernv: Remove unused definitions in opal-api.h This removes definitions in opal-api.h that are completely unused in Linux. For each of these I see three possibilities, 1) we *should* be using them in Linux and patches will arrive to do that, 2) they are not used but should stay in the header to document the API for some important reason, 3) they are not used and needn't be part of the API. Signed-off-by: Michael Ellerman Reviewed-by: Stewart Smith --- arch/powerpc/include/asm/opal-api.h | 47 ------------------------------------- 1 file changed, 47 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h index 2984f486f3ba..e8a6baf55e82 100644 --- a/arch/powerpc/include/asm/opal-api.h +++ b/arch/powerpc/include/asm/opal-api.h @@ -165,10 +165,6 @@ #ifndef __ASSEMBLY__ /* Other enums */ -enum OpalVendorApiTokens { - OPAL_START_VENDOR_API_RANGE = 1000, OPAL_END_VENDOR_API_RANGE = 1999 -}; - enum OpalFreezeState { OPAL_EEH_STOPPED_NOT_FROZEN = 0, OPAL_EEH_STOPPED_MMIO_FREEZE = 1, @@ -236,27 +232,12 @@ enum OpalErrinjectFunc { OPAL_ERR_INJECT_FUNC_IOA_DMA_WR_TARGET = 19, }; -enum OpalShpcAction { - OPAL_SHPC_GET_LINK_STATE = 0, - OPAL_SHPC_GET_SLOT_STATE = 1 -}; - -enum OpalShpcLinkState { - OPAL_SHPC_LINK_DOWN = 0, - OPAL_SHPC_LINK_UP = 1 -}; - enum OpalMmioWindowType { OPAL_M32_WINDOW_TYPE = 1, OPAL_M64_WINDOW_TYPE = 2, OPAL_IO_WINDOW_TYPE = 3 }; -enum OpalShpcSlotState { - OPAL_SHPC_DEV_NOT_PRESENT = 0, - OPAL_SHPC_DEV_PRESENT = 1 -}; - enum OpalExceptionHandler { OPAL_MACHINE_CHECK_HANDLER = 1, OPAL_HYPERVISOR_MAINTENANCE_HANDLER = 2, @@ -348,29 +329,6 @@ enum OpalPciResetState { OPAL_ASSERT_RESET = 1 }; -enum OpalPciMaskAction { - OPAL_UNMASK_ERROR_TYPE = 0, - OPAL_MASK_ERROR_TYPE = 1 -}; - -enum OpalSlotLedType { - OPAL_SLOT_LED_ID_TYPE = 0, - OPAL_SLOT_LED_FAULT_TYPE = 1 -}; - -enum OpalLedAction { - OPAL_TURN_OFF_LED = 0, - OPAL_TURN_ON_LED = 1, - OPAL_QUERY_LED_STATE_AFTER_BUSY = 2 -}; - -enum OpalEpowStatus { - OPAL_EPOW_NONE = 0, - OPAL_EPOW_UPS = 1, - OPAL_EPOW_OVER_AMBIENT_TEMP = 2, - OPAL_EPOW_OVER_INTERNAL_TEMP = 3 -}; - /* * Address cycle types for LPC accesses. These also correspond * to the content of the first cell of the "reg" property for @@ -440,11 +398,6 @@ enum OpalMemErr_DynErrType { OPAL_MEM_DYNAMIC_DEALLOC = 0, }; -/* OpalMemoryErrorData->flags */ -#define OPAL_MEM_CORRECTED_ERROR 0x0001 -#define OPAL_MEM_THRESHOLD_EXCEEDED 0x0002 -#define OPAL_MEM_ACK_REQUIRED 0x8000 - struct OpalMemoryErrorData { enum OpalMemErr_Version version:8; /* 0x00 */ enum OpalMemErrType type:8; /* 0x01 */ -- cgit v1.2.3 From f98e7f2fe9d7ac5851cf8cc9933993a2b74566c1 Mon Sep 17 00:00:00 2001 From: Arseny Solokha Date: Tue, 24 Feb 2015 16:05:05 +0700 Subject: powerpc/qe: drop unused ucc_slow_poll_transmitter_now Drop ucc_slow_poll_transmitter_now() which has no users since its inception in 2007 in commit 986585385131 ("[POWERPC] Add QUICC Engine (QE) infrastructure"). Signed-off-by: Arseny Solokha Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/ucc_slow.h | 13 ------------- arch/powerpc/sysdev/qe_lib/ucc_slow.c | 5 ----- 2 files changed, 18 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/ucc_slow.h b/arch/powerpc/include/asm/ucc_slow.h index c44131e68e11..233ef5fe5fde 100644 --- a/arch/powerpc/include/asm/ucc_slow.h +++ b/arch/powerpc/include/asm/ucc_slow.h @@ -251,19 +251,6 @@ void ucc_slow_enable(struct ucc_slow_private * uccs, enum comm_dir mode); */ void ucc_slow_disable(struct ucc_slow_private * uccs, enum comm_dir mode); -/* ucc_slow_poll_transmitter_now - * Immediately forces a poll of the transmitter for data to be sent. - * Typically, the hardware performs a periodic poll for data that the - * transmit routine has set up to be transmitted. In cases where - * this polling cycle is not soon enough, this optional routine can - * be invoked to force a poll right away, instead. Proper use for - * each transmission for which this functionality is desired is to - * call the transmit routine and then this routine right after. - * - * uccs - (In) pointer to the slow UCC structure. - */ -void ucc_slow_poll_transmitter_now(struct ucc_slow_private * uccs); - /* ucc_slow_graceful_stop_tx * Smoothly stops transmission on a specified slow UCC. * diff --git a/arch/powerpc/sysdev/qe_lib/ucc_slow.c b/arch/powerpc/sysdev/qe_lib/ucc_slow.c index befaf1123f7f..5f91628209eb 100644 --- a/arch/powerpc/sysdev/qe_lib/ucc_slow.c +++ b/arch/powerpc/sysdev/qe_lib/ucc_slow.c @@ -43,11 +43,6 @@ u32 ucc_slow_get_qe_cr_subblock(int uccs_num) } EXPORT_SYMBOL(ucc_slow_get_qe_cr_subblock); -void ucc_slow_poll_transmitter_now(struct ucc_slow_private * uccs) -{ - out_be16(&uccs->us_regs->utodr, UCC_SLOW_TOD); -} - void ucc_slow_graceful_stop_tx(struct ucc_slow_private * uccs) { struct ucc_slow_info *us_info = uccs->us_info; -- cgit v1.2.3 From 5e86bfde9cd93f272844c3ff6ac5f93d3666b3e7 Mon Sep 17 00:00:00 2001 From: Arseny Solokha Date: Tue, 24 Feb 2015 16:05:06 +0700 Subject: powerpc/mpic: remove unused functions Drop unused fsl_mpic_primary_get_version(), mpic_set_clk_ratio(), mpic_set_serial_int(). + fsl_mpic_primary_get_version() is just a safe wrapper around fsl_mpic_get_version() for SMP configurations. While the latter is called explicitly for handling PIC initialization and setting up error interrupt vector depending on PIC hardware version, the former isn't used for anything. + As for mpic_set_clk_ratio() and mpic_set_serial_int(), they both are almost nine years old[1] but still have no chance to be called even from out-of-tree modules because they both are __init and of course aren't exported. [1] https://lists.ozlabs.org/pipermail/linuxppc-dev/2006-June/023867.html Signed-off-by: Arseny Solokha Cc: hongtao.jia@freescale.com Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/mpic.h | 20 -------------------- arch/powerpc/sysdev/mpic.c | 35 ----------------------------------- 2 files changed, 55 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/mpic.h b/arch/powerpc/include/asm/mpic.h index 754f93d208fa..6ce63a7662f8 100644 --- a/arch/powerpc/include/asm/mpic.h +++ b/arch/powerpc/include/asm/mpic.h @@ -34,10 +34,6 @@ #define MPIC_GREG_GCONF_BASE_MASK 0x000fffff #define MPIC_GREG_GCONF_MCK 0x08000000 #define MPIC_GREG_GLOBAL_CONF_1 0x00030 -#define MPIC_GREG_GLOBAL_CONF_1_SIE 0x08000000 -#define MPIC_GREG_GLOBAL_CONF_1_CLK_RATIO_MASK 0x70000000 -#define MPIC_GREG_GLOBAL_CONF_1_CLK_RATIO(r) \ - (((r) << 28) & MPIC_GREG_GLOBAL_CONF_1_CLK_RATIO_MASK) #define MPIC_GREG_VENDOR_0 0x00040 #define MPIC_GREG_VENDOR_1 0x00050 #define MPIC_GREG_VENDOR_2 0x00060 @@ -395,16 +391,6 @@ extern struct bus_type mpic_subsys; #define MPIC_REGSET_STANDARD MPIC_REGSET(0) /* Original MPIC */ #define MPIC_REGSET_TSI108 MPIC_REGSET(1) /* Tsi108/109 PIC */ -/* Get the version of primary MPIC */ -#ifdef CONFIG_MPIC -extern u32 fsl_mpic_primary_get_version(void); -#else -static inline u32 fsl_mpic_primary_get_version(void) -{ - return 0; -} -#endif - /* Allocate the controller structure and setup the linux irq descs * for the range if interrupts passed in. No HW initialization is * actually performed. @@ -496,11 +482,5 @@ extern unsigned int mpic_get_coreint_irq(void); /* Fetch Machine Check interrupt from primary mpic */ extern unsigned int mpic_get_mcirq(void); -/* Set the EPIC clock ratio */ -void mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio); - -/* Enable/Disable EPIC serial interrupt mode */ -void mpic_set_serial_int(struct mpic *mpic, int enable); - #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_MPIC_H */ diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index bbfbbf2025fd..f72b592d60cc 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -1219,16 +1219,6 @@ static u32 fsl_mpic_get_version(struct mpic *mpic) * Exported functions */ -u32 fsl_mpic_primary_get_version(void) -{ - struct mpic *mpic = mpic_primary; - - if (mpic) - return fsl_mpic_get_version(mpic); - - return 0; -} - struct mpic * __init mpic_alloc(struct device_node *node, phys_addr_t phys_addr, unsigned int flags, @@ -1676,31 +1666,6 @@ void __init mpic_init(struct mpic *mpic) mpic_err_int_init(mpic, MPIC_FSL_ERR_INT); } -void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio) -{ - u32 v; - - v = mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1); - v &= ~MPIC_GREG_GLOBAL_CONF_1_CLK_RATIO_MASK; - v |= MPIC_GREG_GLOBAL_CONF_1_CLK_RATIO(clock_ratio); - mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1, v); -} - -void __init mpic_set_serial_int(struct mpic *mpic, int enable) -{ - unsigned long flags; - u32 v; - - raw_spin_lock_irqsave(&mpic_lock, flags); - v = mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1); - if (enable) - v |= MPIC_GREG_GLOBAL_CONF_1_SIE; - else - v &= ~MPIC_GREG_GLOBAL_CONF_1_SIE; - mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1, v); - raw_spin_unlock_irqrestore(&mpic_lock, flags); -} - void mpic_irq_set_priority(unsigned int irq, unsigned int pri) { struct mpic *mpic = mpic_find(irq); -- cgit v1.2.3 From 45706bb53d118b5340a12926e26444d73b6491f9 Mon Sep 17 00:00:00 2001 From: Mahesh Salgaonkar Date: Fri, 19 Dec 2014 08:41:05 +0530 Subject: powerpc/book3s: Fix flush_tlb cpu_spec hook to take a generic argument. The flush_tlb hook in cpu_spec was introduced as a generic function hook to invalidate TLBs. But the current implementation of flush_tlb hook takes IS (invalidation selector) as an argument which is architecture dependent. Hence, It is not right to have a generic routine where caller has to pass non-generic argument. This patch fixes this and makes flush_tlb hook as high level API. Reported-by: Benjamin Herrenschmidt Signed-off-by: Mahesh Salgaonkar Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/cputable.h | 8 +++++- arch/powerpc/include/asm/mmu-hash64.h | 1 + arch/powerpc/kernel/cpu_setup_power.S | 10 ++----- arch/powerpc/kernel/cputable.c | 4 +-- arch/powerpc/kernel/mce_power.c | 53 +++++++++++++++++++++++++++++++++-- arch/powerpc/kvm/book3s_hv_ras.c | 4 +-- 6 files changed, 65 insertions(+), 15 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index 5cf5a6d10685..6367b8347dad 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h @@ -100,7 +100,7 @@ struct cpu_spec { /* * Processor specific routine to flush tlbs. */ - void (*flush_tlb)(unsigned long inval_selector); + void (*flush_tlb)(unsigned int action); }; @@ -114,6 +114,12 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, extern const char *powerpc_base_platform; +/* TLB flush actions. Used as argument to cpu_spec.flush_tlb() hook */ +enum { + TLB_INVAL_SCOPE_GLOBAL = 0, /* invalidate all TLBs */ + TLB_INVAL_SCOPE_LPID = 1, /* invalidate TLBs for current LPID */ +}; + #endif /* __ASSEMBLY__ */ /* CPU kernel features */ diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h index 4f13c3ed7acf..1da6a81ce541 100644 --- a/arch/powerpc/include/asm/mmu-hash64.h +++ b/arch/powerpc/include/asm/mmu-hash64.h @@ -112,6 +112,7 @@ #define TLBIEL_INVAL_SET_SHIFT 12 #define POWER7_TLB_SETS 128 /* # sets in POWER7 TLB */ +#define POWER8_TLB_SETS 512 /* # sets in POWER8 TLB */ #ifndef __ASSEMBLY__ diff --git a/arch/powerpc/kernel/cpu_setup_power.S b/arch/powerpc/kernel/cpu_setup_power.S index 46733535cc0b..9c9b7411b28b 100644 --- a/arch/powerpc/kernel/cpu_setup_power.S +++ b/arch/powerpc/kernel/cpu_setup_power.S @@ -137,15 +137,11 @@ __init_HFSCR: /* * Clear the TLB using the specified IS form of tlbiel instruction * (invalidate by congruence class). P7 has 128 CCs., P8 has 512. - * - * r3 = IS field */ __init_tlb_power7: - li r3,0xc00 /* IS field = 0b11 */ -_GLOBAL(__flush_tlb_power7) li r6,128 mtctr r6 - mr r7,r3 /* IS field */ + li r7,0xc00 /* IS field = 0b11 */ ptesync 2: tlbiel r7 addi r7,r7,0x1000 @@ -154,11 +150,9 @@ _GLOBAL(__flush_tlb_power7) 1: blr __init_tlb_power8: - li r3,0xc00 /* IS field = 0b11 */ -_GLOBAL(__flush_tlb_power8) li r6,512 mtctr r6 - mr r7,r3 /* IS field */ + li r7,0xc00 /* IS field = 0b11 */ ptesync 2: tlbiel r7 addi r7,r7,0x1000 diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index f337666768a7..7ed126bc9b18 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -71,8 +71,8 @@ extern void __restore_cpu_power7(void); extern void __setup_cpu_power8(unsigned long offset, struct cpu_spec* spec); extern void __restore_cpu_power8(void); extern void __restore_cpu_a2(void); -extern void __flush_tlb_power7(unsigned long inval_selector); -extern void __flush_tlb_power8(unsigned long inval_selector); +extern void __flush_tlb_power7(unsigned int action); +extern void __flush_tlb_power8(unsigned int action); extern long __machine_check_early_realmode_p7(struct pt_regs *regs); extern long __machine_check_early_realmode_p8(struct pt_regs *regs); #endif /* CONFIG_PPC64 */ diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c index b6f123ab90ed..2c647b1e62e4 100644 --- a/arch/powerpc/kernel/mce_power.c +++ b/arch/powerpc/kernel/mce_power.c @@ -28,6 +28,55 @@ #include #include +static void flush_tlb_206(unsigned int num_sets, unsigned int action) +{ + unsigned long rb; + unsigned int i; + + switch (action) { + case TLB_INVAL_SCOPE_GLOBAL: + rb = TLBIEL_INVAL_SET; + break; + case TLB_INVAL_SCOPE_LPID: + rb = TLBIEL_INVAL_SET_LPID; + break; + default: + BUG(); + break; + } + + asm volatile("ptesync" : : : "memory"); + for (i = 0; i < num_sets; i++) { + asm volatile("tlbiel %0" : : "r" (rb)); + rb += 1 << TLBIEL_INVAL_SET_SHIFT; + } + asm volatile("ptesync" : : : "memory"); +} + +/* + * Generic routine to flush TLB on power7. This routine is used as + * flush_tlb hook in cpu_spec for Power7 processor. + * + * action => TLB_INVAL_SCOPE_GLOBAL: Invalidate all TLBs. + * TLB_INVAL_SCOPE_LPID: Invalidate TLB for current LPID. + */ +void __flush_tlb_power7(unsigned int action) +{ + flush_tlb_206(POWER7_TLB_SETS, action); +} + +/* + * Generic routine to flush TLB on power8. This routine is used as + * flush_tlb hook in cpu_spec for power8 processor. + * + * action => TLB_INVAL_SCOPE_GLOBAL: Invalidate all TLBs. + * TLB_INVAL_SCOPE_LPID: Invalidate TLB for current LPID. + */ +void __flush_tlb_power8(unsigned int action) +{ + flush_tlb_206(POWER8_TLB_SETS, action); +} + /* flush SLBs and reload */ static void flush_and_reload_slb(void) { @@ -79,7 +128,7 @@ static long mce_handle_derror(uint64_t dsisr, uint64_t slb_error_bits) } if (dsisr & P7_DSISR_MC_TLB_MULTIHIT_MFTLB) { if (cur_cpu_spec && cur_cpu_spec->flush_tlb) - cur_cpu_spec->flush_tlb(TLBIEL_INVAL_SET); + cur_cpu_spec->flush_tlb(TLB_INVAL_SCOPE_GLOBAL); /* reset error bits */ dsisr &= ~P7_DSISR_MC_TLB_MULTIHIT_MFTLB; } @@ -110,7 +159,7 @@ static long mce_handle_common_ierror(uint64_t srr1) break; case P7_SRR1_MC_IFETCH_TLB_MULTIHIT: if (cur_cpu_spec && cur_cpu_spec->flush_tlb) { - cur_cpu_spec->flush_tlb(TLBIEL_INVAL_SET); + cur_cpu_spec->flush_tlb(TLB_INVAL_SCOPE_GLOBAL); handled = 1; } break; diff --git a/arch/powerpc/kvm/book3s_hv_ras.c b/arch/powerpc/kvm/book3s_hv_ras.c index 60081bd75847..93b5f5c9b445 100644 --- a/arch/powerpc/kvm/book3s_hv_ras.c +++ b/arch/powerpc/kvm/book3s_hv_ras.c @@ -84,7 +84,7 @@ static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu) } if (dsisr & DSISR_MC_TLB_MULTI) { if (cur_cpu_spec && cur_cpu_spec->flush_tlb) - cur_cpu_spec->flush_tlb(TLBIEL_INVAL_SET_LPID); + cur_cpu_spec->flush_tlb(TLB_INVAL_SCOPE_LPID); dsisr &= ~DSISR_MC_TLB_MULTI; } /* Any other errors we don't understand? */ @@ -102,7 +102,7 @@ static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu) break; case SRR1_MC_IFETCH_TLBMULTI: if (cur_cpu_spec && cur_cpu_spec->flush_tlb) - cur_cpu_spec->flush_tlb(TLBIEL_INVAL_SET_LPID); + cur_cpu_spec->flush_tlb(TLB_INVAL_SCOPE_LPID); break; default: handled = 0; -- cgit v1.2.3 From 6ec7334304f2882b7fc13ab70a0bf58948cf6244 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Fri, 13 Feb 2015 15:16:32 +1100 Subject: powerpc/pci: Fix comments about ppc_md.pcibios_fixup The patch fixes the comments about ppc_md.pcibios_fixup(), which should be called after allocating resources. Signed-off-by: Gavin Shan Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/machdep.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index c8175a3fe560..098d51e924ea 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h @@ -125,7 +125,7 @@ struct machdep_calls { unsigned int (*get_irq)(void); /* PCI stuff */ - /* Called after scanning the bus, before allocating resources */ + /* Called after allocating resources */ void (*pcibios_fixup)(void); int (*pci_probe_mode)(struct pci_bus *); void (*pci_irq_fixup)(struct pci_dev *dev); -- cgit v1.2.3 From 366d395c8dd8f1d92f967e4a7691dadd9b9ae1bb Mon Sep 17 00:00:00 2001 From: Nathan Fontenot Date: Tue, 10 Feb 2015 13:43:24 -0600 Subject: powerpc/pseries: Define rtas hotplug event sections In order to handle device hotplug in the kernel on pseries the hotplug request will be communicated in the kernel in the form of a rtas hotplug event. This patch adds the definition of rtas hotplug event sections. Signed-off-by: Nathan Fontenot Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/rtas.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h index 2e23e92a4372..eddc8469543a 100644 --- a/arch/powerpc/include/asm/rtas.h +++ b/arch/powerpc/include/asm/rtas.h @@ -273,6 +273,7 @@ inline uint32_t rtas_ext_event_company_id(struct rtas_ext_event_log_v6 *ext_log) #define PSERIES_ELOG_SECT_ID_MANUFACT_INFO (('M' << 8) | 'I') #define PSERIES_ELOG_SECT_ID_CALL_HOME (('C' << 8) | 'H') #define PSERIES_ELOG_SECT_ID_USER_DEF (('U' << 8) | 'D') +#define PSERIES_ELOG_SECT_ID_HOTPLUG (('H' << 8) | 'P') /* Vendor specific Platform Event Log Format, Version 6, section header */ struct pseries_errorlog { @@ -296,6 +297,31 @@ inline uint16_t pseries_errorlog_length(struct pseries_errorlog *sect) return be16_to_cpu(sect->length); } +/* RTAS pseries hotplug errorlog section */ +struct pseries_hp_errorlog { + u8 resource; + u8 action; + u8 id_type; + u8 reserved; + union { + __be32 drc_index; + __be32 drc_count; + char drc_name[1]; + } _drc_u; +}; + +#define PSERIES_HP_ELOG_RESOURCE_CPU 1 +#define PSERIES_HP_ELOG_RESOURCE_MEM 2 +#define PSERIES_HP_ELOG_RESOURCE_SLOT 3 +#define PSERIES_HP_ELOG_RESOURCE_PHB 4 + +#define PSERIES_HP_ELOG_ACTION_ADD 1 +#define PSERIES_HP_ELOG_ACTION_REMOVE 2 + +#define PSERIES_HP_ELOG_ID_DRC_NAME 1 +#define PSERIES_HP_ELOG_ID_DRC_INDEX 2 +#define PSERIES_HP_ELOG_ID_DRC_COUNT 3 + struct pseries_errorlog *get_pseries_errorlog(struct rtas_error_log *log, uint16_t section_id); -- cgit v1.2.3 From b05ae4ee602b7dc90771408ccf0972e1b3801a35 Mon Sep 17 00:00:00 2001 From: Kyle Moffett Date: Mon, 14 Nov 2011 21:32:10 -0500 Subject: powerpc: Remove duplicate cacheable_memcpy/memzero functions These functions are only used from one place each. If the cacheable_* versions really are more efficient, then those changes should be migrated into the common code instead. NOTE: The old routines are just flat buggy on kernels that support hardware with different cacheline sizes. Signed-off-by: Kyle Moffett Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/cache.h | 3 - arch/powerpc/lib/copy_32.S | 127 ----------------------------------- arch/powerpc/lib/ppc_ksyms.c | 4 -- arch/powerpc/mm/ppc_mmu_32.c | 2 +- drivers/net/ethernet/ibm/emac/core.c | 12 +--- 5 files changed, 3 insertions(+), 145 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/cache.h b/arch/powerpc/include/asm/cache.h index 34a05a1a990b..0dc42c5082b7 100644 --- a/arch/powerpc/include/asm/cache.h +++ b/arch/powerpc/include/asm/cache.h @@ -76,9 +76,6 @@ extern void _set_L3CR(unsigned long); #define _set_L3CR(val) do { } while(0) #endif -extern void cacheable_memzero(void *p, unsigned int nb); -extern void *cacheable_memcpy(void *, const void *, unsigned int); - #endif /* !__ASSEMBLY__ */ #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_CACHE_H */ diff --git a/arch/powerpc/lib/copy_32.S b/arch/powerpc/lib/copy_32.S index 55f19f9fd708..6813f80d1eec 100644 --- a/arch/powerpc/lib/copy_32.S +++ b/arch/powerpc/lib/copy_32.S @@ -69,54 +69,6 @@ CACHELINE_BYTES = L1_CACHE_BYTES LG_CACHELINE_BYTES = L1_CACHE_SHIFT CACHELINE_MASK = (L1_CACHE_BYTES-1) -/* - * Use dcbz on the complete cache lines in the destination - * to set them to zero. This requires that the destination - * area is cacheable. -- paulus - */ -_GLOBAL(cacheable_memzero) - mr r5,r4 - li r4,0 - addi r6,r3,-4 - cmplwi 0,r5,4 - blt 7f - stwu r4,4(r6) - beqlr - andi. r0,r6,3 - add r5,r0,r5 - subf r6,r0,r6 - clrlwi r7,r6,32-LG_CACHELINE_BYTES - add r8,r7,r5 - srwi r9,r8,LG_CACHELINE_BYTES - addic. r9,r9,-1 /* total number of complete cachelines */ - ble 2f - xori r0,r7,CACHELINE_MASK & ~3 - srwi. r0,r0,2 - beq 3f - mtctr r0 -4: stwu r4,4(r6) - bdnz 4b -3: mtctr r9 - li r7,4 -10: dcbz r7,r6 - addi r6,r6,CACHELINE_BYTES - bdnz 10b - clrlwi r5,r8,32-LG_CACHELINE_BYTES - addi r5,r5,4 -2: srwi r0,r5,2 - mtctr r0 - bdz 6f -1: stwu r4,4(r6) - bdnz 1b -6: andi. r5,r5,3 -7: cmpwi 0,r5,0 - beqlr - mtctr r5 - addi r6,r6,3 -8: stbu r4,1(r6) - bdnz 8b - blr - _GLOBAL(memset) rlwimi r4,r4,8,16,23 rlwimi r4,r4,16,0,15 @@ -142,85 +94,6 @@ _GLOBAL(memset) bdnz 8b blr -/* - * This version uses dcbz on the complete cache lines in the - * destination area to reduce memory traffic. This requires that - * the destination area is cacheable. - * We only use this version if the source and dest don't overlap. - * -- paulus. - */ -_GLOBAL(cacheable_memcpy) - add r7,r3,r5 /* test if the src & dst overlap */ - add r8,r4,r5 - cmplw 0,r4,r7 - cmplw 1,r3,r8 - crand 0,0,4 /* cr0.lt &= cr1.lt */ - blt memcpy /* if regions overlap */ - - addi r4,r4,-4 - addi r6,r3,-4 - neg r0,r3 - andi. r0,r0,CACHELINE_MASK /* # bytes to start of cache line */ - beq 58f - - cmplw 0,r5,r0 /* is this more than total to do? */ - blt 63f /* if not much to do */ - andi. r8,r0,3 /* get it word-aligned first */ - subf r5,r0,r5 - mtctr r8 - beq+ 61f -70: lbz r9,4(r4) /* do some bytes */ - stb r9,4(r6) - addi r4,r4,1 - addi r6,r6,1 - bdnz 70b -61: srwi. r0,r0,2 - mtctr r0 - beq 58f -72: lwzu r9,4(r4) /* do some words */ - stwu r9,4(r6) - bdnz 72b - -58: srwi. r0,r5,LG_CACHELINE_BYTES /* # complete cachelines */ - clrlwi r5,r5,32-LG_CACHELINE_BYTES - li r11,4 - mtctr r0 - beq 63f -53: - dcbz r11,r6 - COPY_16_BYTES -#if L1_CACHE_BYTES >= 32 - COPY_16_BYTES -#if L1_CACHE_BYTES >= 64 - COPY_16_BYTES - COPY_16_BYTES -#if L1_CACHE_BYTES >= 128 - COPY_16_BYTES - COPY_16_BYTES - COPY_16_BYTES - COPY_16_BYTES -#endif -#endif -#endif - bdnz 53b - -63: srwi. r0,r5,2 - mtctr r0 - beq 64f -30: lwzu r0,4(r4) - stwu r0,4(r6) - bdnz 30b - -64: andi. r0,r5,3 - mtctr r0 - beq+ 65f -40: lbz r0,4(r4) - stb r0,4(r6) - addi r4,r4,1 - addi r6,r6,1 - bdnz 40b -65: blr - _GLOBAL(memmove) cmplw 0,r3,r4 bgt backwards_memcpy diff --git a/arch/powerpc/lib/ppc_ksyms.c b/arch/powerpc/lib/ppc_ksyms.c index f993959647b5..c7f8e9586316 100644 --- a/arch/powerpc/lib/ppc_ksyms.c +++ b/arch/powerpc/lib/ppc_ksyms.c @@ -8,10 +8,6 @@ EXPORT_SYMBOL(memset); EXPORT_SYMBOL(memmove); EXPORT_SYMBOL(memcmp); EXPORT_SYMBOL(memchr); -#ifdef CONFIG_PPC32 -EXPORT_SYMBOL(cacheable_memcpy); -EXPORT_SYMBOL(cacheable_memzero); -#endif EXPORT_SYMBOL(strcpy); EXPORT_SYMBOL(strncpy); diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c index 5029dc19b517..eb0e489b1bb7 100644 --- a/arch/powerpc/mm/ppc_mmu_32.c +++ b/arch/powerpc/mm/ppc_mmu_32.c @@ -224,7 +224,7 @@ void __init MMU_init_hw(void) */ if ( ppc_md.progress ) ppc_md.progress("hash:find piece", 0x322); Hash = __va(memblock_alloc(Hash_size, Hash_size)); - cacheable_memzero(Hash, Hash_size); + memset(Hash, 0, Hash_size); _SDR1 = __pa(Hash) | SDR1_LOW_BITS; Hash_end = (struct hash_pte *) ((unsigned long)Hash + Hash_size); diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c index 162762d1a12c..220bae6f5e43 100644 --- a/drivers/net/ethernet/ibm/emac/core.c +++ b/drivers/net/ethernet/ibm/emac/core.c @@ -79,13 +79,6 @@ MODULE_AUTHOR ("Eugene Surovegin or "); MODULE_LICENSE("GPL"); -/* - * PPC64 doesn't (yet) have a cacheable_memcpy - */ -#ifdef CONFIG_PPC64 -#define cacheable_memcpy(d,s,n) memcpy((d),(s),(n)) -#endif - /* minimum number of free TX descriptors required to wake up TX process */ #define EMAC_TX_WAKEUP_THRESH (NUM_TX_BUFF / 4) @@ -1673,7 +1666,7 @@ static inline int emac_rx_sg_append(struct emac_instance *dev, int slot) dev_kfree_skb(dev->rx_sg_skb); dev->rx_sg_skb = NULL; } else { - cacheable_memcpy(skb_tail_pointer(dev->rx_sg_skb), + memcpy(skb_tail_pointer(dev->rx_sg_skb), dev->rx_skb[slot]->data, len); skb_put(dev->rx_sg_skb, len); emac_recycle_rx_skb(dev, slot, len); @@ -1730,8 +1723,7 @@ static int emac_poll_rx(void *param, int budget) goto oom; skb_reserve(copy_skb, EMAC_RX_SKB_HEADROOM + 2); - cacheable_memcpy(copy_skb->data - 2, skb->data - 2, - len + 2); + memcpy(copy_skb->data - 2, skb->data - 2, len + 2); emac_recycle_rx_skb(dev, slot, len); skb = copy_skb; } else if (unlikely(emac_alloc_rx_skb(dev, slot, GFP_ATOMIC))) -- cgit v1.2.3 From 78989f0a5592182a3d45d869ddaafc71c8f673af Mon Sep 17 00:00:00 2001 From: Hari Bathini Date: Fri, 6 Feb 2015 01:06:04 +0530 Subject: powerpc/nvram: Move generic code for nvram and pstore With minor checks, we can move most of the code for nvram under pseries to a common place to be re-used by other powerpc platforms like powernv. This patch moves such common code to arch/powerpc/kernel/nvram_64.c file. Signed-off-by: Hari Bathini [mpe: Move select of ZLIB_DEFLATE to PPC64 to fix the build] Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/nvram.h | 50 ++- arch/powerpc/include/asm/rtas.h | 4 + arch/powerpc/kernel/nvram_64.c | 656 ++++++++++++++++++++++++++++++++ arch/powerpc/platforms/Kconfig.cputype | 1 + arch/powerpc/platforms/pseries/Kconfig | 1 - arch/powerpc/platforms/pseries/nvram.c | 666 +-------------------------------- 6 files changed, 715 insertions(+), 663 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/nvram.h b/arch/powerpc/include/asm/nvram.h index b0fe0fe4e626..09a518bb7c03 100644 --- a/arch/powerpc/include/asm/nvram.h +++ b/arch/powerpc/include/asm/nvram.h @@ -9,12 +9,43 @@ #ifndef _ASM_POWERPC_NVRAM_H #define _ASM_POWERPC_NVRAM_H - +#include #include #include #include +/* + * Set oops header version to distinguish between old and new format header. + * lnx,oops-log partition max size is 4000, header version > 4000 will + * help in identifying new header. + */ +#define OOPS_HDR_VERSION 5000 + +struct err_log_info { + __be32 error_type; + __be32 seq_num; +}; + +struct nvram_os_partition { + const char *name; + int req_size; /* desired size, in bytes */ + int min_size; /* minimum acceptable size (0 means req_size) */ + long size; /* size of data portion (excluding err_log_info) */ + long index; /* offset of data portion of partition */ + bool os_partition; /* partition initialized by OS, not FW */ +}; + +struct oops_log_info { + __be16 version; + __be16 report_length; + __be64 timestamp; +} __attribute__((packed)); + +extern struct nvram_os_partition oops_log_partition; + #ifdef CONFIG_PPC_PSERIES +extern struct nvram_os_partition rtas_log_partition; + extern int nvram_write_error_log(char * buff, int length, unsigned int err_type, unsigned int err_seq); extern int nvram_read_error_log(char * buff, int length, @@ -50,6 +81,23 @@ extern void pmac_xpram_write(int xpaddr, u8 data); /* Synchronize NVRAM */ extern void nvram_sync(void); +/* Initialize NVRAM OS partition */ +extern int __init nvram_init_os_partition(struct nvram_os_partition *part); + +/* Initialize NVRAM oops partition */ +extern void __init nvram_init_oops_partition(int rtas_partition_exists); + +/* Read a NVRAM partition */ +extern int nvram_read_partition(struct nvram_os_partition *part, char *buff, + int length, unsigned int *err_type, + unsigned int *error_log_cnt); + +/* Write to NVRAM OS partition */ +extern int nvram_write_os_partition(struct nvram_os_partition *part, + char *buff, int length, + unsigned int err_type, + unsigned int error_log_cnt); + /* Determine NVRAM size */ extern ssize_t nvram_get_size(void); diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h index 2e23e92a4372..d1bd001566df 100644 --- a/arch/powerpc/include/asm/rtas.h +++ b/arch/powerpc/include/asm/rtas.h @@ -343,8 +343,12 @@ extern int early_init_dt_scan_rtas(unsigned long node, extern void pSeries_log_error(char *buf, unsigned int err_type, int fatal); #ifdef CONFIG_PPC_PSERIES +extern unsigned long last_rtas_event; +extern int clobbering_unread_rtas_event(void); extern int pseries_devicetree_update(s32 scope); extern void post_mobility_fixup(void); +#else +static inline int clobbering_unread_rtas_event(void) { return 0; } #endif #ifdef CONFIG_PPC_RTAS_DAEMON diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c index 34f7c9b7cd96..42e5c6a9c214 100644 --- a/arch/powerpc/kernel/nvram_64.c +++ b/arch/powerpc/kernel/nvram_64.c @@ -26,6 +26,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -54,6 +57,659 @@ struct nvram_partition { static LIST_HEAD(nvram_partitions); +#ifdef CONFIG_PPC_PSERIES +struct nvram_os_partition rtas_log_partition = { + .name = "ibm,rtas-log", + .req_size = 2079, + .min_size = 1055, + .index = -1, + .os_partition = true +}; +#endif + +struct nvram_os_partition oops_log_partition = { + .name = "lnx,oops-log", + .req_size = 4000, + .min_size = 2000, + .index = -1, + .os_partition = true +}; + +static const char *nvram_os_partitions[] = { +#ifdef CONFIG_PPC_PSERIES + "ibm,rtas-log", +#endif + "lnx,oops-log", + NULL +}; + +static void oops_to_nvram(struct kmsg_dumper *dumper, + enum kmsg_dump_reason reason); + +static struct kmsg_dumper nvram_kmsg_dumper = { + .dump = oops_to_nvram +}; + +/* + * For capturing and compressing an oops or panic report... + + * big_oops_buf[] holds the uncompressed text we're capturing. + * + * oops_buf[] holds the compressed text, preceded by a oops header. + * oops header has u16 holding the version of oops header (to differentiate + * between old and new format header) followed by u16 holding the length of + * the compressed* text (*Or uncompressed, if compression fails.) and u64 + * holding the timestamp. oops_buf[] gets written to NVRAM. + * + * oops_log_info points to the header. oops_data points to the compressed text. + * + * +- oops_buf + * | +- oops_data + * v v + * +-----------+-----------+-----------+------------------------+ + * | version | length | timestamp | text | + * | (2 bytes) | (2 bytes) | (8 bytes) | (oops_data_sz bytes) | + * +-----------+-----------+-----------+------------------------+ + * ^ + * +- oops_log_info + * + * We preallocate these buffers during init to avoid kmalloc during oops/panic. + */ +static size_t big_oops_buf_sz; +static char *big_oops_buf, *oops_buf; +static char *oops_data; +static size_t oops_data_sz; + +/* Compression parameters */ +#define COMPR_LEVEL 6 +#define WINDOW_BITS 12 +#define MEM_LEVEL 4 +static struct z_stream_s stream; + +#ifdef CONFIG_PSTORE +#ifdef CONFIG_PPC_PSERIES +static struct nvram_os_partition of_config_partition = { + .name = "of-config", + .index = -1, + .os_partition = false +}; +#endif + +static struct nvram_os_partition common_partition = { + .name = "common", + .index = -1, + .os_partition = false +}; + +static enum pstore_type_id nvram_type_ids[] = { + PSTORE_TYPE_DMESG, + PSTORE_TYPE_PPC_COMMON, + -1, + -1, + -1 +}; +static int read_type; +#endif + +/* nvram_write_os_partition + * + * We need to buffer the error logs into nvram to ensure that we have + * the failure information to decode. If we have a severe error there + * is no way to guarantee that the OS or the machine is in a state to + * get back to user land and write the error to disk. For example if + * the SCSI device driver causes a Machine Check by writing to a bad + * IO address, there is no way of guaranteeing that the device driver + * is in any state that is would also be able to write the error data + * captured to disk, thus we buffer it in NVRAM for analysis on the + * next boot. + * + * In NVRAM the partition containing the error log buffer will looks like: + * Header (in bytes): + * +-----------+----------+--------+------------+------------------+ + * | signature | checksum | length | name | data | + * |0 |1 |2 3|4 15|16 length-1| + * +-----------+----------+--------+------------+------------------+ + * + * The 'data' section would look like (in bytes): + * +--------------+------------+-----------------------------------+ + * | event_logged | sequence # | error log | + * |0 3|4 7|8 error_log_size-1| + * +--------------+------------+-----------------------------------+ + * + * event_logged: 0 if event has not been logged to syslog, 1 if it has + * sequence #: The unique sequence # for each event. (until it wraps) + * error log: The error log from event_scan + */ +int nvram_write_os_partition(struct nvram_os_partition *part, + char *buff, int length, + unsigned int err_type, + unsigned int error_log_cnt) +{ + int rc; + loff_t tmp_index; + struct err_log_info info; + + if (part->index == -1) + return -ESPIPE; + + if (length > part->size) + length = part->size; + + info.error_type = cpu_to_be32(err_type); + info.seq_num = cpu_to_be32(error_log_cnt); + + tmp_index = part->index; + + rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info), + &tmp_index); + if (rc <= 0) { + pr_err("%s: Failed nvram_write (%d)\n", __func__, rc); + return rc; + } + + rc = ppc_md.nvram_write(buff, length, &tmp_index); + if (rc <= 0) { + pr_err("%s: Failed nvram_write (%d)\n", __func__, rc); + return rc; + } + + return 0; +} + +/* nvram_read_partition + * + * Reads nvram partition for at most 'length' + */ +int nvram_read_partition(struct nvram_os_partition *part, char *buff, + int length, unsigned int *err_type, + unsigned int *error_log_cnt) +{ + int rc; + loff_t tmp_index; + struct err_log_info info; + + if (part->index == -1) + return -1; + + if (length > part->size) + length = part->size; + + tmp_index = part->index; + + if (part->os_partition) { + rc = ppc_md.nvram_read((char *)&info, + sizeof(struct err_log_info), + &tmp_index); + if (rc <= 0) { + pr_err("%s: Failed nvram_read (%d)\n", __func__, rc); + return rc; + } + } + + rc = ppc_md.nvram_read(buff, length, &tmp_index); + if (rc <= 0) { + pr_err("%s: Failed nvram_read (%d)\n", __func__, rc); + return rc; + } + + if (part->os_partition) { + *error_log_cnt = be32_to_cpu(info.seq_num); + *err_type = be32_to_cpu(info.error_type); + } + + return 0; +} + +/* nvram_init_os_partition + * + * This sets up a partition with an "OS" signature. + * + * The general strategy is the following: + * 1.) If a partition with the indicated name already exists... + * - If it's large enough, use it. + * - Otherwise, recycle it and keep going. + * 2.) Search for a free partition that is large enough. + * 3.) If there's not a free partition large enough, recycle any obsolete + * OS partitions and try again. + * 4.) Will first try getting a chunk that will satisfy the requested size. + * 5.) If a chunk of the requested size cannot be allocated, then try finding + * a chunk that will satisfy the minum needed. + * + * Returns 0 on success, else -1. + */ +int __init nvram_init_os_partition(struct nvram_os_partition *part) +{ + loff_t p; + int size; + + /* Look for ours */ + p = nvram_find_partition(part->name, NVRAM_SIG_OS, &size); + + /* Found one but too small, remove it */ + if (p && size < part->min_size) { + pr_info("nvram: Found too small %s partition," + " removing it...\n", part->name); + nvram_remove_partition(part->name, NVRAM_SIG_OS, NULL); + p = 0; + } + + /* Create one if we didn't find */ + if (!p) { + p = nvram_create_partition(part->name, NVRAM_SIG_OS, + part->req_size, part->min_size); + if (p == -ENOSPC) { + pr_info("nvram: No room to create %s partition, " + "deleting any obsolete OS partitions...\n", + part->name); + nvram_remove_partition(NULL, NVRAM_SIG_OS, + nvram_os_partitions); + p = nvram_create_partition(part->name, NVRAM_SIG_OS, + part->req_size, part->min_size); + } + } + + if (p <= 0) { + pr_err("nvram: Failed to find or create %s" + " partition, err %d\n", part->name, (int)p); + return -1; + } + + part->index = p; + part->size = nvram_get_partition_size(p) - sizeof(struct err_log_info); + + return 0; +} + +/* Derived from logfs_compress() */ +static int nvram_compress(const void *in, void *out, size_t inlen, + size_t outlen) +{ + int err, ret; + + ret = -EIO; + err = zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS, + MEM_LEVEL, Z_DEFAULT_STRATEGY); + if (err != Z_OK) + goto error; + + stream.next_in = in; + stream.avail_in = inlen; + stream.total_in = 0; + stream.next_out = out; + stream.avail_out = outlen; + stream.total_out = 0; + + err = zlib_deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) + goto error; + + err = zlib_deflateEnd(&stream); + if (err != Z_OK) + goto error; + + if (stream.total_out >= stream.total_in) + goto error; + + ret = stream.total_out; +error: + return ret; +} + +/* Compress the text from big_oops_buf into oops_buf. */ +static int zip_oops(size_t text_len) +{ + struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf; + int zipped_len = nvram_compress(big_oops_buf, oops_data, text_len, + oops_data_sz); + if (zipped_len < 0) { + pr_err("nvram: compression failed; returned %d\n", zipped_len); + pr_err("nvram: logging uncompressed oops/panic report\n"); + return -1; + } + oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION); + oops_hdr->report_length = cpu_to_be16(zipped_len); + oops_hdr->timestamp = cpu_to_be64(get_seconds()); + return 0; +} + +#ifdef CONFIG_PSTORE +static int nvram_pstore_open(struct pstore_info *psi) +{ + /* Reset the iterator to start reading partitions again */ + read_type = -1; + return 0; +} + +/** + * nvram_pstore_write - pstore write callback for nvram + * @type: Type of message logged + * @reason: reason behind dump (oops/panic) + * @id: identifier to indicate the write performed + * @part: pstore writes data to registered buffer in parts, + * part number will indicate the same. + * @count: Indicates oops count + * @compressed: Flag to indicate the log is compressed + * @size: number of bytes written to the registered buffer + * @psi: registered pstore_info structure + * + * Called by pstore_dump() when an oops or panic report is logged in the + * printk buffer. + * Returns 0 on successful write. + */ +static int nvram_pstore_write(enum pstore_type_id type, + enum kmsg_dump_reason reason, + u64 *id, unsigned int part, int count, + bool compressed, size_t size, + struct pstore_info *psi) +{ + int rc; + unsigned int err_type = ERR_TYPE_KERNEL_PANIC; + struct oops_log_info *oops_hdr = (struct oops_log_info *) oops_buf; + + /* part 1 has the recent messages from printk buffer */ + if (part > 1 || (type != PSTORE_TYPE_DMESG)) + return -1; + + if (clobbering_unread_rtas_event()) + return -1; + + oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION); + oops_hdr->report_length = cpu_to_be16(size); + oops_hdr->timestamp = cpu_to_be64(get_seconds()); + + if (compressed) + err_type = ERR_TYPE_KERNEL_PANIC_GZ; + + rc = nvram_write_os_partition(&oops_log_partition, oops_buf, + (int) (sizeof(*oops_hdr) + size), err_type, count); + + if (rc != 0) + return rc; + + *id = part; + return 0; +} + +/* + * Reads the oops/panic report, rtas, of-config and common partition. + * Returns the length of the data we read from each partition. + * Returns 0 if we've been called before. + */ +static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type, + int *count, struct timespec *time, char **buf, + bool *compressed, struct pstore_info *psi) +{ + struct oops_log_info *oops_hdr; + unsigned int err_type, id_no, size = 0; + struct nvram_os_partition *part = NULL; + char *buff = NULL; + int sig = 0; + loff_t p; + + read_type++; + + switch (nvram_type_ids[read_type]) { + case PSTORE_TYPE_DMESG: + part = &oops_log_partition; + *type = PSTORE_TYPE_DMESG; + break; + case PSTORE_TYPE_PPC_COMMON: + sig = NVRAM_SIG_SYS; + part = &common_partition; + *type = PSTORE_TYPE_PPC_COMMON; + *id = PSTORE_TYPE_PPC_COMMON; + time->tv_sec = 0; + time->tv_nsec = 0; + break; +#ifdef CONFIG_PPC_PSERIES + case PSTORE_TYPE_PPC_RTAS: + part = &rtas_log_partition; + *type = PSTORE_TYPE_PPC_RTAS; + time->tv_sec = last_rtas_event; + time->tv_nsec = 0; + break; + case PSTORE_TYPE_PPC_OF: + sig = NVRAM_SIG_OF; + part = &of_config_partition; + *type = PSTORE_TYPE_PPC_OF; + *id = PSTORE_TYPE_PPC_OF; + time->tv_sec = 0; + time->tv_nsec = 0; + break; +#endif + default: + return 0; + } + + if (!part->os_partition) { + p = nvram_find_partition(part->name, sig, &size); + if (p <= 0) { + pr_err("nvram: Failed to find partition %s, " + "err %d\n", part->name, (int)p); + return 0; + } + part->index = p; + part->size = size; + } + + buff = kmalloc(part->size, GFP_KERNEL); + + if (!buff) + return -ENOMEM; + + if (nvram_read_partition(part, buff, part->size, &err_type, &id_no)) { + kfree(buff); + return 0; + } + + *count = 0; + + if (part->os_partition) + *id = id_no; + + if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) { + size_t length, hdr_size; + + oops_hdr = (struct oops_log_info *)buff; + if (be16_to_cpu(oops_hdr->version) < OOPS_HDR_VERSION) { + /* Old format oops header had 2-byte record size */ + hdr_size = sizeof(u16); + length = be16_to_cpu(oops_hdr->version); + time->tv_sec = 0; + time->tv_nsec = 0; + } else { + hdr_size = sizeof(*oops_hdr); + length = be16_to_cpu(oops_hdr->report_length); + time->tv_sec = be64_to_cpu(oops_hdr->timestamp); + time->tv_nsec = 0; + } + *buf = kmalloc(length, GFP_KERNEL); + if (*buf == NULL) + return -ENOMEM; + memcpy(*buf, buff + hdr_size, length); + kfree(buff); + + if (err_type == ERR_TYPE_KERNEL_PANIC_GZ) + *compressed = true; + else + *compressed = false; + return length; + } + + *buf = buff; + return part->size; +} + +static struct pstore_info nvram_pstore_info = { + .owner = THIS_MODULE, + .name = "nvram", + .open = nvram_pstore_open, + .read = nvram_pstore_read, + .write = nvram_pstore_write, +}; + +static int nvram_pstore_init(void) +{ + int rc = 0; + + nvram_type_ids[2] = PSTORE_TYPE_PPC_RTAS; + nvram_type_ids[3] = PSTORE_TYPE_PPC_OF; + + nvram_pstore_info.buf = oops_data; + nvram_pstore_info.bufsize = oops_data_sz; + + spin_lock_init(&nvram_pstore_info.buf_lock); + + rc = pstore_register(&nvram_pstore_info); + if (rc != 0) + pr_err("nvram: pstore_register() failed, defaults to " + "kmsg_dump; returned %d\n", rc); + + return rc; +} +#else +static int nvram_pstore_init(void) +{ + return -1; +} +#endif + +void __init nvram_init_oops_partition(int rtas_partition_exists) +{ + int rc; + + rc = nvram_init_os_partition(&oops_log_partition); + if (rc != 0) { +#ifdef CONFIG_PPC_PSERIES + if (!rtas_partition_exists) { + pr_err("nvram: Failed to initialize oops partition!"); + return; + } + pr_notice("nvram: Using %s partition to log both" + " RTAS errors and oops/panic reports\n", + rtas_log_partition.name); + memcpy(&oops_log_partition, &rtas_log_partition, + sizeof(rtas_log_partition)); +#else + pr_err("nvram: Failed to initialize oops partition!"); + return; +#endif + } + oops_buf = kmalloc(oops_log_partition.size, GFP_KERNEL); + if (!oops_buf) { + pr_err("nvram: No memory for %s partition\n", + oops_log_partition.name); + return; + } + oops_data = oops_buf + sizeof(struct oops_log_info); + oops_data_sz = oops_log_partition.size - sizeof(struct oops_log_info); + + rc = nvram_pstore_init(); + + if (!rc) + return; + + /* + * Figure compression (preceded by elimination of each line's + * severity prefix) will reduce the oops/panic report to at most + * 45% of its original size. + */ + big_oops_buf_sz = (oops_data_sz * 100) / 45; + big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL); + if (big_oops_buf) { + stream.workspace = kmalloc(zlib_deflate_workspacesize( + WINDOW_BITS, MEM_LEVEL), GFP_KERNEL); + if (!stream.workspace) { + pr_err("nvram: No memory for compression workspace; " + "skipping compression of %s partition data\n", + oops_log_partition.name); + kfree(big_oops_buf); + big_oops_buf = NULL; + } + } else { + pr_err("No memory for uncompressed %s data; " + "skipping compression\n", oops_log_partition.name); + stream.workspace = NULL; + } + + rc = kmsg_dump_register(&nvram_kmsg_dumper); + if (rc != 0) { + pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc); + kfree(oops_buf); + kfree(big_oops_buf); + kfree(stream.workspace); + } +} + +/* + * This is our kmsg_dump callback, called after an oops or panic report + * has been written to the printk buffer. We want to capture as much + * of the printk buffer as possible. First, capture as much as we can + * that we think will compress sufficiently to fit in the lnx,oops-log + * partition. If that's too much, go back and capture uncompressed text. + */ +static void oops_to_nvram(struct kmsg_dumper *dumper, + enum kmsg_dump_reason reason) +{ + struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf; + static unsigned int oops_count = 0; + static bool panicking = false; + static DEFINE_SPINLOCK(lock); + unsigned long flags; + size_t text_len; + unsigned int err_type = ERR_TYPE_KERNEL_PANIC_GZ; + int rc = -1; + + switch (reason) { + case KMSG_DUMP_RESTART: + case KMSG_DUMP_HALT: + case KMSG_DUMP_POWEROFF: + /* These are almost always orderly shutdowns. */ + return; + case KMSG_DUMP_OOPS: + break; + case KMSG_DUMP_PANIC: + panicking = true; + break; + case KMSG_DUMP_EMERG: + if (panicking) + /* Panic report already captured. */ + return; + break; + default: + pr_err("%s: ignoring unrecognized KMSG_DUMP_* reason %d\n", + __func__, (int) reason); + return; + } + + if (clobbering_unread_rtas_event()) + return; + + if (!spin_trylock_irqsave(&lock, flags)) + return; + + if (big_oops_buf) { + kmsg_dump_get_buffer(dumper, false, + big_oops_buf, big_oops_buf_sz, &text_len); + rc = zip_oops(text_len); + } + if (rc != 0) { + kmsg_dump_rewind(dumper); + kmsg_dump_get_buffer(dumper, false, + oops_data, oops_data_sz, &text_len); + err_type = ERR_TYPE_KERNEL_PANIC; + oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION); + oops_hdr->report_length = cpu_to_be16(text_len); + oops_hdr->timestamp = cpu_to_be64(get_seconds()); + } + + (void) nvram_write_os_partition(&oops_log_partition, oops_buf, + (int) (sizeof(*oops_hdr) + text_len), err_type, + ++oops_count); + + spin_unlock_irqrestore(&lock, flags); +} + static loff_t dev_nvram_llseek(struct file *file, loff_t offset, int origin) { int size; diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index 76483e3acd60..80614c6088bc 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype @@ -2,6 +2,7 @@ config PPC64 bool "64-bit kernel" default n select HAVE_VIRT_CPU_ACCOUNTING + select ZLIB_DEFLATE help This option selects whether a 32-bit or a 64-bit kernel will be built. diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index a758a9c3bbba..54c87d5d349d 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig @@ -16,7 +16,6 @@ config PPC_PSERIES select PPC_UDBG_16550 select PPC_NATIVE select PPC_PCI_CHOICE if EXPERT - select ZLIB_DEFLATE select PPC_DOORBELL select HAVE_CONTEXT_TRACKING select HOTPLUG_CPU if SMP diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c index 054a0ed5c7ee..533807efed61 100644 --- a/arch/powerpc/platforms/pseries/nvram.c +++ b/arch/powerpc/platforms/pseries/nvram.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -30,129 +29,17 @@ /* Max bytes to read/write in one go */ #define NVRW_CNT 0x20 -/* - * Set oops header version to distinguish between old and new format header. - * lnx,oops-log partition max size is 4000, header version > 4000 will - * help in identifying new header. - */ -#define OOPS_HDR_VERSION 5000 - static unsigned int nvram_size; static int nvram_fetch, nvram_store; static char nvram_buf[NVRW_CNT]; /* assume this is in the first 4GB */ static DEFINE_SPINLOCK(nvram_lock); -struct err_log_info { - __be32 error_type; - __be32 seq_num; -}; - -struct nvram_os_partition { - const char *name; - int req_size; /* desired size, in bytes */ - int min_size; /* minimum acceptable size (0 means req_size) */ - long size; /* size of data portion (excluding err_log_info) */ - long index; /* offset of data portion of partition */ - bool os_partition; /* partition initialized by OS, not FW */ -}; - -static struct nvram_os_partition rtas_log_partition = { - .name = "ibm,rtas-log", - .req_size = 2079, - .min_size = 1055, - .index = -1, - .os_partition = true -}; - -static struct nvram_os_partition oops_log_partition = { - .name = "lnx,oops-log", - .req_size = 4000, - .min_size = 2000, - .index = -1, - .os_partition = true -}; - -static const char *pseries_nvram_os_partitions[] = { - "ibm,rtas-log", - "lnx,oops-log", - NULL -}; - -struct oops_log_info { - __be16 version; - __be16 report_length; - __be64 timestamp; -} __attribute__((packed)); - -static void oops_to_nvram(struct kmsg_dumper *dumper, - enum kmsg_dump_reason reason); - -static struct kmsg_dumper nvram_kmsg_dumper = { - .dump = oops_to_nvram -}; - /* See clobbering_unread_rtas_event() */ #define NVRAM_RTAS_READ_TIMEOUT 5 /* seconds */ static unsigned long last_unread_rtas_event; /* timestamp */ -/* - * For capturing and compressing an oops or panic report... - - * big_oops_buf[] holds the uncompressed text we're capturing. - * - * oops_buf[] holds the compressed text, preceded by a oops header. - * oops header has u16 holding the version of oops header (to differentiate - * between old and new format header) followed by u16 holding the length of - * the compressed* text (*Or uncompressed, if compression fails.) and u64 - * holding the timestamp. oops_buf[] gets written to NVRAM. - * - * oops_log_info points to the header. oops_data points to the compressed text. - * - * +- oops_buf - * | +- oops_data - * v v - * +-----------+-----------+-----------+------------------------+ - * | version | length | timestamp | text | - * | (2 bytes) | (2 bytes) | (8 bytes) | (oops_data_sz bytes) | - * +-----------+-----------+-----------+------------------------+ - * ^ - * +- oops_log_info - * - * We preallocate these buffers during init to avoid kmalloc during oops/panic. - */ -static size_t big_oops_buf_sz; -static char *big_oops_buf, *oops_buf; -static char *oops_data; -static size_t oops_data_sz; - -/* Compression parameters */ -#define COMPR_LEVEL 6 -#define WINDOW_BITS 12 -#define MEM_LEVEL 4 -static struct z_stream_s stream; - #ifdef CONFIG_PSTORE -static struct nvram_os_partition of_config_partition = { - .name = "of-config", - .index = -1, - .os_partition = false -}; - -static struct nvram_os_partition common_partition = { - .name = "common", - .index = -1, - .os_partition = false -}; - -static enum pstore_type_id nvram_type_ids[] = { - PSTORE_TYPE_DMESG, - PSTORE_TYPE_PPC_RTAS, - PSTORE_TYPE_PPC_OF, - PSTORE_TYPE_PPC_COMMON, - -1 -}; -static int read_type; -static unsigned long last_rtas_event; +unsigned long last_rtas_event; #endif static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index) @@ -246,73 +133,11 @@ static ssize_t pSeries_nvram_get_size(void) return nvram_size ? nvram_size : -ENODEV; } - -/* nvram_write_os_partition, nvram_write_error_log +/* nvram_write_error_log * * We need to buffer the error logs into nvram to ensure that we have - * the failure information to decode. If we have a severe error there - * is no way to guarantee that the OS or the machine is in a state to - * get back to user land and write the error to disk. For example if - * the SCSI device driver causes a Machine Check by writing to a bad - * IO address, there is no way of guaranteeing that the device driver - * is in any state that is would also be able to write the error data - * captured to disk, thus we buffer it in NVRAM for analysis on the - * next boot. - * - * In NVRAM the partition containing the error log buffer will looks like: - * Header (in bytes): - * +-----------+----------+--------+------------+------------------+ - * | signature | checksum | length | name | data | - * |0 |1 |2 3|4 15|16 length-1| - * +-----------+----------+--------+------------+------------------+ - * - * The 'data' section would look like (in bytes): - * +--------------+------------+-----------------------------------+ - * | event_logged | sequence # | error log | - * |0 3|4 7|8 error_log_size-1| - * +--------------+------------+-----------------------------------+ - * - * event_logged: 0 if event has not been logged to syslog, 1 if it has - * sequence #: The unique sequence # for each event. (until it wraps) - * error log: The error log from event_scan + * the failure information to decode. */ -static int nvram_write_os_partition(struct nvram_os_partition *part, - char *buff, int length, - unsigned int err_type, - unsigned int error_log_cnt) -{ - int rc; - loff_t tmp_index; - struct err_log_info info; - - if (part->index == -1) { - return -ESPIPE; - } - - if (length > part->size) { - length = part->size; - } - - info.error_type = cpu_to_be32(err_type); - info.seq_num = cpu_to_be32(error_log_cnt); - - tmp_index = part->index; - - rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info), &tmp_index); - if (rc <= 0) { - pr_err("%s: Failed nvram_write (%d)\n", __func__, rc); - return rc; - } - - rc = ppc_md.nvram_write(buff, length, &tmp_index); - if (rc <= 0) { - pr_err("%s: Failed nvram_write (%d)\n", __func__, rc); - return rc; - } - - return 0; -} - int nvram_write_error_log(char * buff, int length, unsigned int err_type, unsigned int error_log_cnt) { @@ -328,50 +153,6 @@ int nvram_write_error_log(char * buff, int length, return rc; } -/* nvram_read_partition - * - * Reads nvram partition for at most 'length' - */ -static int nvram_read_partition(struct nvram_os_partition *part, char *buff, - int length, unsigned int *err_type, - unsigned int *error_log_cnt) -{ - int rc; - loff_t tmp_index; - struct err_log_info info; - - if (part->index == -1) - return -1; - - if (length > part->size) - length = part->size; - - tmp_index = part->index; - - if (part->os_partition) { - rc = ppc_md.nvram_read((char *)&info, - sizeof(struct err_log_info), - &tmp_index); - if (rc <= 0) { - pr_err("%s: Failed nvram_read (%d)\n", __func__, rc); - return rc; - } - } - - rc = ppc_md.nvram_read(buff, length, &tmp_index); - if (rc <= 0) { - pr_err("%s: Failed nvram_read (%d)\n", __func__, rc); - return rc; - } - - if (part->os_partition) { - *error_log_cnt = be32_to_cpu(info.seq_num); - *err_type = be32_to_cpu(info.error_type); - } - - return 0; -} - /* nvram_read_error_log * * Reads nvram for error log for at most 'length' @@ -407,67 +188,6 @@ int nvram_clear_error_log(void) return 0; } -/* pseries_nvram_init_os_partition - * - * This sets up a partition with an "OS" signature. - * - * The general strategy is the following: - * 1.) If a partition with the indicated name already exists... - * - If it's large enough, use it. - * - Otherwise, recycle it and keep going. - * 2.) Search for a free partition that is large enough. - * 3.) If there's not a free partition large enough, recycle any obsolete - * OS partitions and try again. - * 4.) Will first try getting a chunk that will satisfy the requested size. - * 5.) If a chunk of the requested size cannot be allocated, then try finding - * a chunk that will satisfy the minum needed. - * - * Returns 0 on success, else -1. - */ -static int __init pseries_nvram_init_os_partition(struct nvram_os_partition - *part) -{ - loff_t p; - int size; - - /* Look for ours */ - p = nvram_find_partition(part->name, NVRAM_SIG_OS, &size); - - /* Found one but too small, remove it */ - if (p && size < part->min_size) { - pr_info("nvram: Found too small %s partition," - " removing it...\n", part->name); - nvram_remove_partition(part->name, NVRAM_SIG_OS, NULL); - p = 0; - } - - /* Create one if we didn't find */ - if (!p) { - p = nvram_create_partition(part->name, NVRAM_SIG_OS, - part->req_size, part->min_size); - if (p == -ENOSPC) { - pr_info("nvram: No room to create %s partition, " - "deleting any obsolete OS partitions...\n", - part->name); - nvram_remove_partition(NULL, NVRAM_SIG_OS, - pseries_nvram_os_partitions); - p = nvram_create_partition(part->name, NVRAM_SIG_OS, - part->req_size, part->min_size); - } - } - - if (p <= 0) { - pr_err("nvram: Failed to find or create %s" - " partition, err %d\n", part->name, (int)p); - return -1; - } - - part->index = p; - part->size = nvram_get_partition_size(p) - sizeof(struct err_log_info); - - return 0; -} - /* * Are we using the ibm,rtas-log for oops/panic reports? And if so, * would logging this oops/panic overwrite an RTAS event that rtas_errd @@ -476,7 +196,7 @@ static int __init pseries_nvram_init_os_partition(struct nvram_os_partition * We assume that if rtas_errd hasn't read the RTAS event in * NVRAM_RTAS_READ_TIMEOUT seconds, it's probably not going to. */ -static int clobbering_unread_rtas_event(void) +int clobbering_unread_rtas_event(void) { return (oops_log_partition.index == rtas_log_partition.index && last_unread_rtas_event @@ -484,313 +204,6 @@ static int clobbering_unread_rtas_event(void) NVRAM_RTAS_READ_TIMEOUT); } -/* Derived from logfs_compress() */ -static int nvram_compress(const void *in, void *out, size_t inlen, - size_t outlen) -{ - int err, ret; - - ret = -EIO; - err = zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS, - MEM_LEVEL, Z_DEFAULT_STRATEGY); - if (err != Z_OK) - goto error; - - stream.next_in = in; - stream.avail_in = inlen; - stream.total_in = 0; - stream.next_out = out; - stream.avail_out = outlen; - stream.total_out = 0; - - err = zlib_deflate(&stream, Z_FINISH); - if (err != Z_STREAM_END) - goto error; - - err = zlib_deflateEnd(&stream); - if (err != Z_OK) - goto error; - - if (stream.total_out >= stream.total_in) - goto error; - - ret = stream.total_out; -error: - return ret; -} - -/* Compress the text from big_oops_buf into oops_buf. */ -static int zip_oops(size_t text_len) -{ - struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf; - int zipped_len = nvram_compress(big_oops_buf, oops_data, text_len, - oops_data_sz); - if (zipped_len < 0) { - pr_err("nvram: compression failed; returned %d\n", zipped_len); - pr_err("nvram: logging uncompressed oops/panic report\n"); - return -1; - } - oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION); - oops_hdr->report_length = cpu_to_be16(zipped_len); - oops_hdr->timestamp = cpu_to_be64(get_seconds()); - return 0; -} - -#ifdef CONFIG_PSTORE -static int nvram_pstore_open(struct pstore_info *psi) -{ - /* Reset the iterator to start reading partitions again */ - read_type = -1; - return 0; -} - -/** - * nvram_pstore_write - pstore write callback for nvram - * @type: Type of message logged - * @reason: reason behind dump (oops/panic) - * @id: identifier to indicate the write performed - * @part: pstore writes data to registered buffer in parts, - * part number will indicate the same. - * @count: Indicates oops count - * @compressed: Flag to indicate the log is compressed - * @size: number of bytes written to the registered buffer - * @psi: registered pstore_info structure - * - * Called by pstore_dump() when an oops or panic report is logged in the - * printk buffer. - * Returns 0 on successful write. - */ -static int nvram_pstore_write(enum pstore_type_id type, - enum kmsg_dump_reason reason, - u64 *id, unsigned int part, int count, - bool compressed, size_t size, - struct pstore_info *psi) -{ - int rc; - unsigned int err_type = ERR_TYPE_KERNEL_PANIC; - struct oops_log_info *oops_hdr = (struct oops_log_info *) oops_buf; - - /* part 1 has the recent messages from printk buffer */ - if (part > 1 || type != PSTORE_TYPE_DMESG || - clobbering_unread_rtas_event()) - return -1; - - oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION); - oops_hdr->report_length = cpu_to_be16(size); - oops_hdr->timestamp = cpu_to_be64(get_seconds()); - - if (compressed) - err_type = ERR_TYPE_KERNEL_PANIC_GZ; - - rc = nvram_write_os_partition(&oops_log_partition, oops_buf, - (int) (sizeof(*oops_hdr) + size), err_type, count); - - if (rc != 0) - return rc; - - *id = part; - return 0; -} - -/* - * Reads the oops/panic report, rtas, of-config and common partition. - * Returns the length of the data we read from each partition. - * Returns 0 if we've been called before. - */ -static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type, - int *count, struct timespec *time, char **buf, - bool *compressed, struct pstore_info *psi) -{ - struct oops_log_info *oops_hdr; - unsigned int err_type, id_no, size = 0; - struct nvram_os_partition *part = NULL; - char *buff = NULL; - int sig = 0; - loff_t p; - - read_type++; - - switch (nvram_type_ids[read_type]) { - case PSTORE_TYPE_DMESG: - part = &oops_log_partition; - *type = PSTORE_TYPE_DMESG; - break; - case PSTORE_TYPE_PPC_RTAS: - part = &rtas_log_partition; - *type = PSTORE_TYPE_PPC_RTAS; - time->tv_sec = last_rtas_event; - time->tv_nsec = 0; - break; - case PSTORE_TYPE_PPC_OF: - sig = NVRAM_SIG_OF; - part = &of_config_partition; - *type = PSTORE_TYPE_PPC_OF; - *id = PSTORE_TYPE_PPC_OF; - time->tv_sec = 0; - time->tv_nsec = 0; - break; - case PSTORE_TYPE_PPC_COMMON: - sig = NVRAM_SIG_SYS; - part = &common_partition; - *type = PSTORE_TYPE_PPC_COMMON; - *id = PSTORE_TYPE_PPC_COMMON; - time->tv_sec = 0; - time->tv_nsec = 0; - break; - default: - return 0; - } - - if (!part->os_partition) { - p = nvram_find_partition(part->name, sig, &size); - if (p <= 0) { - pr_err("nvram: Failed to find partition %s, " - "err %d\n", part->name, (int)p); - return 0; - } - part->index = p; - part->size = size; - } - - buff = kmalloc(part->size, GFP_KERNEL); - - if (!buff) - return -ENOMEM; - - if (nvram_read_partition(part, buff, part->size, &err_type, &id_no)) { - kfree(buff); - return 0; - } - - *count = 0; - - if (part->os_partition) - *id = id_no; - - if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) { - size_t length, hdr_size; - - oops_hdr = (struct oops_log_info *)buff; - if (be16_to_cpu(oops_hdr->version) < OOPS_HDR_VERSION) { - /* Old format oops header had 2-byte record size */ - hdr_size = sizeof(u16); - length = be16_to_cpu(oops_hdr->version); - time->tv_sec = 0; - time->tv_nsec = 0; - } else { - hdr_size = sizeof(*oops_hdr); - length = be16_to_cpu(oops_hdr->report_length); - time->tv_sec = be64_to_cpu(oops_hdr->timestamp); - time->tv_nsec = 0; - } - *buf = kmalloc(length, GFP_KERNEL); - if (*buf == NULL) - return -ENOMEM; - memcpy(*buf, buff + hdr_size, length); - kfree(buff); - - if (err_type == ERR_TYPE_KERNEL_PANIC_GZ) - *compressed = true; - else - *compressed = false; - return length; - } - - *buf = buff; - return part->size; -} - -static struct pstore_info nvram_pstore_info = { - .owner = THIS_MODULE, - .name = "nvram", - .open = nvram_pstore_open, - .read = nvram_pstore_read, - .write = nvram_pstore_write, -}; - -static int nvram_pstore_init(void) -{ - int rc = 0; - - nvram_pstore_info.buf = oops_data; - nvram_pstore_info.bufsize = oops_data_sz; - - spin_lock_init(&nvram_pstore_info.buf_lock); - - rc = pstore_register(&nvram_pstore_info); - if (rc != 0) - pr_err("nvram: pstore_register() failed, defaults to " - "kmsg_dump; returned %d\n", rc); - - return rc; -} -#else -static int nvram_pstore_init(void) -{ - return -1; -} -#endif - -static void __init nvram_init_oops_partition(int rtas_partition_exists) -{ - int rc; - - rc = pseries_nvram_init_os_partition(&oops_log_partition); - if (rc != 0) { - if (!rtas_partition_exists) - return; - pr_notice("nvram: Using %s partition to log both" - " RTAS errors and oops/panic reports\n", - rtas_log_partition.name); - memcpy(&oops_log_partition, &rtas_log_partition, - sizeof(rtas_log_partition)); - } - oops_buf = kmalloc(oops_log_partition.size, GFP_KERNEL); - if (!oops_buf) { - pr_err("nvram: No memory for %s partition\n", - oops_log_partition.name); - return; - } - oops_data = oops_buf + sizeof(struct oops_log_info); - oops_data_sz = oops_log_partition.size - sizeof(struct oops_log_info); - - rc = nvram_pstore_init(); - - if (!rc) - return; - - /* - * Figure compression (preceded by elimination of each line's - * severity prefix) will reduce the oops/panic report to at most - * 45% of its original size. - */ - big_oops_buf_sz = (oops_data_sz * 100) / 45; - big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL); - if (big_oops_buf) { - stream.workspace = kmalloc(zlib_deflate_workspacesize( - WINDOW_BITS, MEM_LEVEL), GFP_KERNEL); - if (!stream.workspace) { - pr_err("nvram: No memory for compression workspace; " - "skipping compression of %s partition data\n", - oops_log_partition.name); - kfree(big_oops_buf); - big_oops_buf = NULL; - } - } else { - pr_err("No memory for uncompressed %s data; " - "skipping compression\n", oops_log_partition.name); - stream.workspace = NULL; - } - - rc = kmsg_dump_register(&nvram_kmsg_dumper); - if (rc != 0) { - pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc); - kfree(oops_buf); - kfree(big_oops_buf); - kfree(stream.workspace); - } -} - static int __init pseries_nvram_init_log_partitions(void) { int rc; @@ -798,7 +211,7 @@ static int __init pseries_nvram_init_log_partitions(void) /* Scan nvram for partitions */ nvram_scan_partitions(); - rc = pseries_nvram_init_os_partition(&rtas_log_partition); + rc = nvram_init_os_partition(&rtas_log_partition); nvram_init_oops_partition(rc == 0); return 0; } @@ -834,72 +247,3 @@ int __init pSeries_nvram_init(void) return 0; } - -/* - * This is our kmsg_dump callback, called after an oops or panic report - * has been written to the printk buffer. We want to capture as much - * of the printk buffer as possible. First, capture as much as we can - * that we think will compress sufficiently to fit in the lnx,oops-log - * partition. If that's too much, go back and capture uncompressed text. - */ -static void oops_to_nvram(struct kmsg_dumper *dumper, - enum kmsg_dump_reason reason) -{ - struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf; - static unsigned int oops_count = 0; - static bool panicking = false; - static DEFINE_SPINLOCK(lock); - unsigned long flags; - size_t text_len; - unsigned int err_type = ERR_TYPE_KERNEL_PANIC_GZ; - int rc = -1; - - switch (reason) { - case KMSG_DUMP_RESTART: - case KMSG_DUMP_HALT: - case KMSG_DUMP_POWEROFF: - /* These are almost always orderly shutdowns. */ - return; - case KMSG_DUMP_OOPS: - break; - case KMSG_DUMP_PANIC: - panicking = true; - break; - case KMSG_DUMP_EMERG: - if (panicking) - /* Panic report already captured. */ - return; - break; - default: - pr_err("%s: ignoring unrecognized KMSG_DUMP_* reason %d\n", - __func__, (int) reason); - return; - } - - if (clobbering_unread_rtas_event()) - return; - - if (!spin_trylock_irqsave(&lock, flags)) - return; - - if (big_oops_buf) { - kmsg_dump_get_buffer(dumper, false, - big_oops_buf, big_oops_buf_sz, &text_len); - rc = zip_oops(text_len); - } - if (rc != 0) { - kmsg_dump_rewind(dumper); - kmsg_dump_get_buffer(dumper, false, - oops_data, oops_data_sz, &text_len); - err_type = ERR_TYPE_KERNEL_PANIC; - oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION); - oops_hdr->report_length = cpu_to_be16(text_len); - oops_hdr->timestamp = cpu_to_be64(get_seconds()); - } - - (void) nvram_write_os_partition(&oops_log_partition, oops_buf, - (int) (sizeof(*oops_hdr) + text_len), err_type, - ++oops_count); - - spin_unlock_irqrestore(&lock, flags); -} -- cgit v1.2.3 From e4a9616c548f67537a8d020a45a327f6a4d583ee Mon Sep 17 00:00:00 2001 From: Hari Bathini Date: Fri, 6 Feb 2015 01:07:17 +0530 Subject: powerpc/rtas: Make timestamp related code y2038-safe While we are here, let us make timestamp related code y2038-safe. Suggested-by: Arnd Bergmann Signed-off-by: Hari Bathini Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/rtas.h | 3 ++- arch/powerpc/kernel/nvram_64.c | 6 +++--- arch/powerpc/platforms/pseries/nvram.c | 10 +++++----- 3 files changed, 10 insertions(+), 9 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h index d1bd001566df..c3c99eb35448 100644 --- a/arch/powerpc/include/asm/rtas.h +++ b/arch/powerpc/include/asm/rtas.h @@ -4,6 +4,7 @@ #include #include +#include /* * Definitions for talking to the RTAS on CHRP machines. @@ -343,7 +344,7 @@ extern int early_init_dt_scan_rtas(unsigned long node, extern void pSeries_log_error(char *buf, unsigned int err_type, int fatal); #ifdef CONFIG_PPC_PSERIES -extern unsigned long last_rtas_event; +extern time64_t last_rtas_event; extern int clobbering_unread_rtas_event(void); extern int pseries_devicetree_update(s32 scope); extern void post_mobility_fixup(void); diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c index 293da889055b..1e703f8ebad4 100644 --- a/arch/powerpc/kernel/nvram_64.c +++ b/arch/powerpc/kernel/nvram_64.c @@ -376,7 +376,7 @@ static int zip_oops(size_t text_len) } oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION); oops_hdr->report_length = cpu_to_be16(zipped_len); - oops_hdr->timestamp = cpu_to_be64(get_seconds()); + oops_hdr->timestamp = cpu_to_be64(ktime_get_real_seconds()); return 0; } @@ -423,7 +423,7 @@ static int nvram_pstore_write(enum pstore_type_id type, oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION); oops_hdr->report_length = cpu_to_be16(size); - oops_hdr->timestamp = cpu_to_be64(get_seconds()); + oops_hdr->timestamp = cpu_to_be64(ktime_get_real_seconds()); if (compressed) err_type = ERR_TYPE_KERNEL_PANIC_GZ; @@ -721,7 +721,7 @@ static void oops_to_nvram(struct kmsg_dumper *dumper, err_type = ERR_TYPE_KERNEL_PANIC; oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION); oops_hdr->report_length = cpu_to_be16(text_len); - oops_hdr->timestamp = cpu_to_be64(get_seconds()); + oops_hdr->timestamp = cpu_to_be64(ktime_get_real_seconds()); } (void) nvram_write_os_partition(&oops_log_partition, oops_buf, diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c index 533807efed61..9f8184175c86 100644 --- a/arch/powerpc/platforms/pseries/nvram.c +++ b/arch/powerpc/platforms/pseries/nvram.c @@ -36,10 +36,10 @@ static DEFINE_SPINLOCK(nvram_lock); /* See clobbering_unread_rtas_event() */ #define NVRAM_RTAS_READ_TIMEOUT 5 /* seconds */ -static unsigned long last_unread_rtas_event; /* timestamp */ +static time64_t last_unread_rtas_event; /* timestamp */ #ifdef CONFIG_PSTORE -unsigned long last_rtas_event; +time64_t last_rtas_event; #endif static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index) @@ -144,9 +144,9 @@ int nvram_write_error_log(char * buff, int length, int rc = nvram_write_os_partition(&rtas_log_partition, buff, length, err_type, error_log_cnt); if (!rc) { - last_unread_rtas_event = get_seconds(); + last_unread_rtas_event = ktime_get_real_seconds(); #ifdef CONFIG_PSTORE - last_rtas_event = get_seconds(); + last_rtas_event = ktime_get_real_seconds(); #endif } @@ -200,7 +200,7 @@ int clobbering_unread_rtas_event(void) { return (oops_log_partition.index == rtas_log_partition.index && last_unread_rtas_event - && get_seconds() - last_unread_rtas_event <= + && ktime_get_real_seconds() - last_unread_rtas_event <= NVRAM_RTAS_READ_TIMEOUT); } -- cgit v1.2.3 From f5718726714cd6114876c4e3ca9b6992ab81176c Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 3 Feb 2015 16:36:21 +1100 Subject: powerpc: Move Power Macintosh drivers to generic byteswappers ppc has special instruction forms to efficiently load and store values in non-native endianness. These can be accessed via the arch-specific {ld,st}_le{16,32}() inlines in arch/powerpc/include/asm/swab.h. However, gcc is perfectly capable of generating the byte-reversing load/store instructions when using the normal, generic cpu_to_le*() and le*_to_cpu() functions eaning the arch-specific functions don't have much point. Worse the "le" in the names of the arch specific functions is now misleading, because they always generate byte-reversing forms, but some ppc machines can now run a little-endian kernel. To start getting rid of the arch-specific forms, this patch removes them from all the old Power Macintosh drivers, replacing them with the generic byteswappers. Signed-off-by: David Gibson Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/dbdma.h | 12 ++++---- arch/powerpc/include/asm/vga.h | 4 +-- drivers/ata/pata_macio.c | 10 +++---- drivers/block/swim3.c | 12 ++++---- drivers/ide/pmac.c | 10 +++---- drivers/macintosh/rack-meter.c | 30 ++++++++++---------- drivers/net/ethernet/apple/bmac.c | 30 ++++++++++---------- drivers/net/ethernet/apple/mace.c | 44 ++++++++++++++--------------- drivers/scsi/mac53c94.c | 10 +++---- drivers/scsi/mesh.c | 14 +++++----- drivers/video/fbdev/controlfb.c | 2 +- drivers/video/fbdev/platinumfb.c | 2 +- sound/ppc/pmac.c | 58 +++++++++++++++++++-------------------- 13 files changed, 119 insertions(+), 119 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/dbdma.h b/arch/powerpc/include/asm/dbdma.h index e23f07e73cb3..6c69836b4ec2 100644 --- a/arch/powerpc/include/asm/dbdma.h +++ b/arch/powerpc/include/asm/dbdma.h @@ -42,12 +42,12 @@ struct dbdma_regs { * DBDMA command structure. These fields are all little-endian! */ struct dbdma_cmd { - unsigned short req_count; /* requested byte transfer count */ - unsigned short command; /* command word (has bit-fields) */ - unsigned int phy_addr; /* physical data address */ - unsigned int cmd_dep; /* command-dependent field */ - unsigned short res_count; /* residual count after completion */ - unsigned short xfer_status; /* transfer status */ + __le16 req_count; /* requested byte transfer count */ + __le16 command; /* command word (has bit-fields) */ + __le32 phy_addr; /* physical data address */ + __le32 cmd_dep; /* command-dependent field */ + __le16 res_count; /* residual count after completion */ + __le16 xfer_status; /* transfer status */ }; /* DBDMA command values in command field */ diff --git a/arch/powerpc/include/asm/vga.h b/arch/powerpc/include/asm/vga.h index e5f8dd366212..ab3acd2f2786 100644 --- a/arch/powerpc/include/asm/vga.h +++ b/arch/powerpc/include/asm/vga.h @@ -25,12 +25,12 @@ static inline void scr_writew(u16 val, volatile u16 *addr) { - st_le16(addr, val); + *addr = cpu_to_le16(val); } static inline u16 scr_readw(volatile const u16 *addr) { - return ld_le16(addr); + return le16_to_cpu(*addr); } #define VT_BUF_HAVE_MEMCPYW diff --git a/drivers/ata/pata_macio.c b/drivers/ata/pata_macio.c index a02f76fdcfcd..b0028588ff1c 100644 --- a/drivers/ata/pata_macio.c +++ b/drivers/ata/pata_macio.c @@ -540,9 +540,9 @@ static void pata_macio_qc_prep(struct ata_queued_cmd *qc) BUG_ON (pi++ >= MAX_DCMDS); len = (sg_len < MAX_DBDMA_SEG) ? sg_len : MAX_DBDMA_SEG; - st_le16(&table->command, write ? OUTPUT_MORE: INPUT_MORE); - st_le16(&table->req_count, len); - st_le32(&table->phy_addr, addr); + table->command = cpu_to_le16(write ? OUTPUT_MORE: INPUT_MORE); + table->req_count = cpu_to_le16(len); + table->phy_addr = cpu_to_le32(addr); table->cmd_dep = 0; table->xfer_status = 0; table->res_count = 0; @@ -557,12 +557,12 @@ static void pata_macio_qc_prep(struct ata_queued_cmd *qc) /* Convert the last command to an input/output */ table--; - st_le16(&table->command, write ? OUTPUT_LAST: INPUT_LAST); + table->command = cpu_to_le16(write ? OUTPUT_LAST: INPUT_LAST); table++; /* Add the stop command to the end of the list */ memset(table, 0, sizeof(struct dbdma_cmd)); - st_le16(&table->command, DBDMA_STOP); + table->command = cpu_to_le16(DBDMA_STOP); dev_dbgdma(priv->dev, "%s: %d DMA list entries\n", __func__, pi); } diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index 523ee8fd4c15..c264f2d284a7 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c @@ -440,9 +440,9 @@ static inline void seek_track(struct floppy_state *fs, int n) static inline void init_dma(struct dbdma_cmd *cp, int cmd, void *buf, int count) { - st_le16(&cp->req_count, count); - st_le16(&cp->command, cmd); - st_le32(&cp->phy_addr, virt_to_bus(buf)); + cp->req_count = cpu_to_le16(count); + cp->command = cpu_to_le16(cmd); + cp->phy_addr = cpu_to_le32(virt_to_bus(buf)); cp->xfer_status = 0; } @@ -771,8 +771,8 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id) } /* turn off DMA */ out_le32(&dr->control, (RUN | PAUSE) << 16); - stat = ld_le16(&cp->xfer_status); - resid = ld_le16(&cp->res_count); + stat = le16_to_cpu(cp->xfer_status); + resid = le16_to_cpu(cp->res_count); if (intr & ERROR_INTR) { n = fs->scount - 1 - resid / 512; if (n > 0) { @@ -1170,7 +1170,7 @@ static int swim3_add_device(struct macio_dev *mdev, int index) fs->dma_cmd = (struct dbdma_cmd *) DBDMA_ALIGN(fs->dbdma_cmd_space); memset(fs->dma_cmd, 0, 2 * sizeof(struct dbdma_cmd)); - st_le16(&fs->dma_cmd[1].command, DBDMA_STOP); + fs->dma_cmd[1].command = cpu_to_le16(DBDMA_STOP); if (mdev->media_bay == NULL || check_media_bay(mdev->media_bay) == MB_FD) swim3_mb_event(mdev, MB_FD); diff --git a/drivers/ide/pmac.c b/drivers/ide/pmac.c index 2db803cd095c..d24a3f8b49bc 100644 --- a/drivers/ide/pmac.c +++ b/drivers/ide/pmac.c @@ -1497,9 +1497,9 @@ static int pmac_ide_build_dmatable(ide_drive_t *drive, struct ide_cmd *cmd) drive->name); return 0; } - st_le16(&table->command, wr? OUTPUT_MORE: INPUT_MORE); - st_le16(&table->req_count, tc); - st_le32(&table->phy_addr, cur_addr); + table->command = cpu_to_le16(wr? OUTPUT_MORE: INPUT_MORE); + table->req_count = cpu_to_le16(tc); + table->phy_addr = cpu_to_le32(cur_addr); table->cmd_dep = 0; table->xfer_status = 0; table->res_count = 0; @@ -1513,10 +1513,10 @@ static int pmac_ide_build_dmatable(ide_drive_t *drive, struct ide_cmd *cmd) /* convert the last command to an input/output last command */ if (count) { - st_le16(&table[-1].command, wr? OUTPUT_LAST: INPUT_LAST); + table[-1].command = cpu_to_le16(wr? OUTPUT_LAST: INPUT_LAST); /* add the stop command to the end of the list */ memset(table, 0, sizeof(struct dbdma_cmd)); - st_le16(&table->command, DBDMA_STOP); + table->command = cpu_to_le16(DBDMA_STOP); mb(); writel(hwif->dmatable_dma, &dma->cmdptr); return 1; diff --git a/drivers/macintosh/rack-meter.c b/drivers/macintosh/rack-meter.c index 4192901cab40..048901a1111a 100644 --- a/drivers/macintosh/rack-meter.c +++ b/drivers/macintosh/rack-meter.c @@ -182,31 +182,31 @@ static void rackmeter_setup_dbdma(struct rackmeter *rm) /* Prepare 4 dbdma commands for the 2 buffers */ memset(cmd, 0, 4 * sizeof(struct dbdma_cmd)); - st_le16(&cmd->req_count, 4); - st_le16(&cmd->command, STORE_WORD | INTR_ALWAYS | KEY_SYSTEM); - st_le32(&cmd->phy_addr, rm->dma_buf_p + + cmd->req_count = cpu_to_le16(4); + cmd->command = cpu_to_le16(STORE_WORD | INTR_ALWAYS | KEY_SYSTEM); + cmd->phy_addr = cpu_to_le32(rm->dma_buf_p + offsetof(struct rackmeter_dma, mark)); - st_le32(&cmd->cmd_dep, 0x02000000); + cmd->cmd_dep = cpu_to_le32(0x02000000); cmd++; - st_le16(&cmd->req_count, SAMPLE_COUNT * 4); - st_le16(&cmd->command, OUTPUT_MORE); - st_le32(&cmd->phy_addr, rm->dma_buf_p + + cmd->req_count = cpu_to_le16(SAMPLE_COUNT * 4); + cmd->command = cpu_to_le16(OUTPUT_MORE); + cmd->phy_addr = cpu_to_le32(rm->dma_buf_p + offsetof(struct rackmeter_dma, buf1)); cmd++; - st_le16(&cmd->req_count, 4); - st_le16(&cmd->command, STORE_WORD | INTR_ALWAYS | KEY_SYSTEM); - st_le32(&cmd->phy_addr, rm->dma_buf_p + + cmd->req_count = cpu_to_le16(4); + cmd->command = cpu_to_le16(STORE_WORD | INTR_ALWAYS | KEY_SYSTEM); + cmd->phy_addr = cpu_to_le32(rm->dma_buf_p + offsetof(struct rackmeter_dma, mark)); - st_le32(&cmd->cmd_dep, 0x01000000); + cmd->cmd_dep = cpu_to_le32(0x01000000); cmd++; - st_le16(&cmd->req_count, SAMPLE_COUNT * 4); - st_le16(&cmd->command, OUTPUT_MORE | BR_ALWAYS); - st_le32(&cmd->phy_addr, rm->dma_buf_p + + cmd->req_count = cpu_to_le16(SAMPLE_COUNT * 4); + cmd->command = cpu_to_le16(OUTPUT_MORE | BR_ALWAYS); + cmd->phy_addr = cpu_to_le32(rm->dma_buf_p + offsetof(struct rackmeter_dma, buf2)); - st_le32(&cmd->cmd_dep, rm->dma_buf_p); + cmd->cmd_dep = cpu_to_le32(rm->dma_buf_p); rackmeter_do_pause(rm, 0); } diff --git a/drivers/net/ethernet/apple/bmac.c b/drivers/net/ethernet/apple/bmac.c index daae0e016253..c0bd638f84af 100644 --- a/drivers/net/ethernet/apple/bmac.c +++ b/drivers/net/ethernet/apple/bmac.c @@ -483,8 +483,8 @@ static int bmac_suspend(struct macio_dev *mdev, pm_message_t state) bmwrite(dev, TXCFG, (config & ~TxMACEnable)); bmwrite(dev, INTDISABLE, DisableAll); /* disable all intrs */ /* disable rx and tx dma */ - st_le32(&rd->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE)); /* clear run bit */ - st_le32(&td->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE)); /* clear run bit */ + rd->control = cpu_to_le32(DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE)); /* clear run bit */ + td->control = cpu_to_le32(DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE)); /* clear run bit */ /* free some skb's */ for (i=0; irx_bufs[i] != NULL) { @@ -699,8 +699,8 @@ static irqreturn_t bmac_rxdma_intr(int irq, void *dev_id) while (1) { cp = &bp->rx_cmds[i]; - stat = ld_le16(&cp->xfer_status); - residual = ld_le16(&cp->res_count); + stat = le16_to_cpu(cp->xfer_status); + residual = le16_to_cpu(cp->res_count); if ((stat & ACTIVE) == 0) break; nb = RX_BUFLEN - residual - 2; @@ -728,8 +728,8 @@ static irqreturn_t bmac_rxdma_intr(int irq, void *dev_id) skb_reserve(bp->rx_bufs[i], 2); } bmac_construct_rxbuff(skb, &bp->rx_cmds[i]); - st_le16(&cp->res_count, 0); - st_le16(&cp->xfer_status, 0); + cp->res_count = cpu_to_le16(0); + cp->xfer_status = cpu_to_le16(0); last = i; if (++i >= N_RX_RING) i = 0; } @@ -769,7 +769,7 @@ static irqreturn_t bmac_txdma_intr(int irq, void *dev_id) while (1) { cp = &bp->tx_cmds[bp->tx_empty]; - stat = ld_le16(&cp->xfer_status); + stat = le16_to_cpu(cp->xfer_status); if (txintcount < 10) { XXDEBUG(("bmac_txdma_xfer_stat=%#0x\n", stat)); } @@ -1411,8 +1411,8 @@ static int bmac_close(struct net_device *dev) bmwrite(dev, INTDISABLE, DisableAll); /* disable all intrs */ /* disable rx and tx dma */ - st_le32(&rd->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE)); /* clear run bit */ - st_le32(&td->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE)); /* clear run bit */ + rd->control = cpu_to_le32(DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE)); /* clear run bit */ + td->control = cpu_to_le32(DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE)); /* clear run bit */ /* free some skb's */ XXDEBUG(("bmac: free rx bufs\n")); @@ -1493,7 +1493,7 @@ static void bmac_tx_timeout(unsigned long data) cp = &bp->tx_cmds[bp->tx_empty]; /* XXDEBUG((KERN_DEBUG "bmac: tx dmastat=%x %x runt=%d pr=%x fs=%x fc=%x\n", */ -/* ld_le32(&td->status), ld_le16(&cp->xfer_status), bp->tx_bad_runt, */ +/* le32_to_cpu(td->status), le16_to_cpu(cp->xfer_status), bp->tx_bad_runt, */ /* mb->pr, mb->xmtfs, mb->fifofc)); */ /* turn off both tx and rx and reset the chip */ @@ -1506,7 +1506,7 @@ static void bmac_tx_timeout(unsigned long data) bmac_enable_and_reset_chip(dev); /* restart rx dma */ - cp = bus_to_virt(ld_le32(&rd->cmdptr)); + cp = bus_to_virt(le32_to_cpu(rd->cmdptr)); out_le32(&rd->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE|ACTIVE|DEAD)); out_le16(&cp->xfer_status, 0); out_le32(&rd->cmdptr, virt_to_bus(cp)); @@ -1553,10 +1553,10 @@ static void dump_dbdma(volatile struct dbdma_cmd *cp,int count) ip = (int*)(cp+i); printk("dbdma req 0x%x addr 0x%x baddr 0x%x xfer/res 0x%x\n", - ld_le32(ip+0), - ld_le32(ip+1), - ld_le32(ip+2), - ld_le32(ip+3)); + le32_to_cpup(ip+0), + le32_to_cpup(ip+1), + le32_to_cpup(ip+2), + le32_to_cpup(ip+3)); } } diff --git a/drivers/net/ethernet/apple/mace.c b/drivers/net/ethernet/apple/mace.c index 842fe7684904..73afe49624f2 100644 --- a/drivers/net/ethernet/apple/mace.c +++ b/drivers/net/ethernet/apple/mace.c @@ -310,7 +310,7 @@ static void dbdma_reset(volatile struct dbdma_regs __iomem *dma) * way on some machines. */ for (i = 200; i > 0; --i) - if (ld_le32(&dma->control) & RUN) + if (le32_to_cpu(dma->control) & RUN) udelay(1); } @@ -452,21 +452,21 @@ static int mace_open(struct net_device *dev) data = skb->data; } mp->rx_bufs[i] = skb; - st_le16(&cp->req_count, RX_BUFLEN); - st_le16(&cp->command, INPUT_LAST + INTR_ALWAYS); - st_le32(&cp->phy_addr, virt_to_bus(data)); + cp->req_count = cpu_to_le16(RX_BUFLEN); + cp->command = cpu_to_le16(INPUT_LAST + INTR_ALWAYS); + cp->phy_addr = cpu_to_le32(virt_to_bus(data)); cp->xfer_status = 0; ++cp; } mp->rx_bufs[i] = NULL; - st_le16(&cp->command, DBDMA_STOP); + cp->command = cpu_to_le16(DBDMA_STOP); mp->rx_fill = i; mp->rx_empty = 0; /* Put a branch back to the beginning of the receive command list */ ++cp; - st_le16(&cp->command, DBDMA_NOP + BR_ALWAYS); - st_le32(&cp->cmd_dep, virt_to_bus(mp->rx_cmds)); + cp->command = cpu_to_le16(DBDMA_NOP + BR_ALWAYS); + cp->cmd_dep = cpu_to_le32(virt_to_bus(mp->rx_cmds)); /* start rx dma */ out_le32(&rd->control, (RUN|PAUSE|FLUSH|WAKE) << 16); /* clear run bit */ @@ -475,8 +475,8 @@ static int mace_open(struct net_device *dev) /* put a branch at the end of the tx command list */ cp = mp->tx_cmds + NCMDS_TX * N_TX_RING; - st_le16(&cp->command, DBDMA_NOP + BR_ALWAYS); - st_le32(&cp->cmd_dep, virt_to_bus(mp->tx_cmds)); + cp->command = cpu_to_le16(DBDMA_NOP + BR_ALWAYS); + cp->cmd_dep = cpu_to_le32(virt_to_bus(mp->tx_cmds)); /* reset tx dma */ out_le32(&td->control, (RUN|PAUSE|FLUSH|WAKE) << 16); @@ -507,8 +507,8 @@ static int mace_close(struct net_device *dev) out_8(&mb->imr, 0xff); /* disable all intrs */ /* disable rx and tx dma */ - st_le32(&rd->control, (RUN|PAUSE|FLUSH|WAKE) << 16); /* clear run bit */ - st_le32(&td->control, (RUN|PAUSE|FLUSH|WAKE) << 16); /* clear run bit */ + rd->control = cpu_to_le32((RUN|PAUSE|FLUSH|WAKE) << 16); /* clear run bit */ + td->control = cpu_to_le32((RUN|PAUSE|FLUSH|WAKE) << 16); /* clear run bit */ mace_clean_rings(mp); @@ -558,8 +558,8 @@ static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev) } mp->tx_bufs[fill] = skb; cp = mp->tx_cmds + NCMDS_TX * fill; - st_le16(&cp->req_count, len); - st_le32(&cp->phy_addr, virt_to_bus(skb->data)); + cp->req_count = cpu_to_le16(len); + cp->phy_addr = cpu_to_le32(virt_to_bus(skb->data)); np = mp->tx_cmds + NCMDS_TX * next; out_le16(&np->command, DBDMA_STOP); @@ -691,7 +691,7 @@ static irqreturn_t mace_interrupt(int irq, void *dev_id) out_8(&mb->xmtfc, AUTO_PAD_XMIT); continue; } - dstat = ld_le32(&td->status); + dstat = le32_to_cpu(td->status); /* stop DMA controller */ out_le32(&td->control, RUN << 16); /* @@ -724,7 +724,7 @@ static irqreturn_t mace_interrupt(int irq, void *dev_id) */ } cp = mp->tx_cmds + NCMDS_TX * i; - stat = ld_le16(&cp->xfer_status); + stat = le16_to_cpu(cp->xfer_status); if ((fs & (UFLO|LCOL|LCAR|RTRY)) || (dstat & DEAD) || xcount == 0) { /* * Check whether there were in fact 2 bytes written to @@ -830,7 +830,7 @@ static void mace_tx_timeout(unsigned long data) mace_reset(dev); /* restart rx dma */ - cp = bus_to_virt(ld_le32(&rd->cmdptr)); + cp = bus_to_virt(le32_to_cpu(rd->cmdptr)); dbdma_reset(rd); out_le16(&cp->xfer_status, 0); out_le32(&rd->cmdptr, virt_to_bus(cp)); @@ -889,20 +889,20 @@ static irqreturn_t mace_rxdma_intr(int irq, void *dev_id) spin_lock_irqsave(&mp->lock, flags); for (i = mp->rx_empty; i != mp->rx_fill; ) { cp = mp->rx_cmds + i; - stat = ld_le16(&cp->xfer_status); + stat = le16_to_cpu(cp->xfer_status); if ((stat & ACTIVE) == 0) { next = i + 1; if (next >= N_RX_RING) next = 0; np = mp->rx_cmds + next; if (next != mp->rx_fill && - (ld_le16(&np->xfer_status) & ACTIVE) != 0) { + (le16_to_cpu(np->xfer_status) & ACTIVE) != 0) { printk(KERN_DEBUG "mace: lost a status word\n"); ++mace_lost_status; } else break; } - nb = ld_le16(&cp->req_count) - ld_le16(&cp->res_count); + nb = le16_to_cpu(cp->req_count) - le16_to_cpu(cp->res_count); out_le16(&cp->command, DBDMA_STOP); /* got a packet, have a look at it */ skb = mp->rx_bufs[i]; @@ -962,13 +962,13 @@ static irqreturn_t mace_rxdma_intr(int irq, void *dev_id) mp->rx_bufs[i] = skb; } } - st_le16(&cp->req_count, RX_BUFLEN); + cp->req_count = cpu_to_le16(RX_BUFLEN); data = skb? skb->data: dummy_buf; - st_le32(&cp->phy_addr, virt_to_bus(data)); + cp->phy_addr = cpu_to_le32(virt_to_bus(data)); out_le16(&cp->xfer_status, 0); out_le16(&cp->command, INPUT_LAST + INTR_ALWAYS); #if 0 - if ((ld_le32(&rd->status) & ACTIVE) != 0) { + if ((le32_to_cpu(rd->status) & ACTIVE) != 0) { out_le32(&rd->control, (PAUSE << 16) | PAUSE); while ((in_le32(&rd->status) & ACTIVE) != 0) ; diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c index e5cd8d8d4ce7..0adb2e015597 100644 --- a/drivers/scsi/mac53c94.c +++ b/drivers/scsi/mac53c94.c @@ -382,16 +382,16 @@ static void set_dma_cmds(struct fsc_state *state, struct scsi_cmnd *cmd) if (dma_len > 0xffff) panic("mac53c94: scatterlist element >= 64k"); total += dma_len; - st_le16(&dcmds->req_count, dma_len); - st_le16(&dcmds->command, dma_cmd); - st_le32(&dcmds->phy_addr, dma_addr); + dcmds->req_count = cpu_to_le16(dma_len); + dcmds->command = cpu_to_le16(dma_cmd); + dcmds->phy_addr = cpu_to_le32(dma_addr); dcmds->xfer_status = 0; ++dcmds; } dma_cmd += OUTPUT_LAST - OUTPUT_MORE; - st_le16(&dcmds[-1].command, dma_cmd); - st_le16(&dcmds->command, DBDMA_STOP); + dcmds[-1].command = cpu_to_le16(dma_cmd); + dcmds->command = cpu_to_le16(DBDMA_STOP); cmd->SCp.this_residual = total; } diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c index 57a95e2c3442..555367f00228 100644 --- a/drivers/scsi/mesh.c +++ b/drivers/scsi/mesh.c @@ -1287,9 +1287,9 @@ static void set_dma_cmds(struct mesh_state *ms, struct scsi_cmnd *cmd) } if (dma_len > 0xffff) panic("mesh: scatterlist element >= 64k"); - st_le16(&dcmds->req_count, dma_len - off); - st_le16(&dcmds->command, dma_cmd); - st_le32(&dcmds->phy_addr, dma_addr + off); + dcmds->req_count = cpu_to_le16(dma_len - off); + dcmds->command = cpu_to_le16(dma_cmd); + dcmds->phy_addr = cpu_to_le32(dma_addr + off); dcmds->xfer_status = 0; ++dcmds; dtot += dma_len - off; @@ -1303,15 +1303,15 @@ static void set_dma_cmds(struct mesh_state *ms, struct scsi_cmnd *cmd) static char mesh_extra_buf[64]; dtot = sizeof(mesh_extra_buf); - st_le16(&dcmds->req_count, dtot); - st_le32(&dcmds->phy_addr, virt_to_phys(mesh_extra_buf)); + dcmds->req_count = cpu_to_le16(dtot); + dcmds->phy_addr = cpu_to_le32(virt_to_phys(mesh_extra_buf)); dcmds->xfer_status = 0; ++dcmds; } dma_cmd += OUTPUT_LAST - OUTPUT_MORE; - st_le16(&dcmds[-1].command, dma_cmd); + dcmds[-1].command = cpu_to_le16(dma_cmd); memset(dcmds, 0, sizeof(*dcmds)); - st_le16(&dcmds->command, DBDMA_STOP); + dcmds->command = cpu_to_le16(DBDMA_STOP); ms->dma_count = dtot; } diff --git a/drivers/video/fbdev/controlfb.c b/drivers/video/fbdev/controlfb.c index 080fdd2a70f3..8d14b29aafea 100644 --- a/drivers/video/fbdev/controlfb.c +++ b/drivers/video/fbdev/controlfb.c @@ -315,7 +315,7 @@ static int controlfb_blank(int blank_mode, struct fb_info *info) container_of(info, struct fb_info_control, info); unsigned ctrl; - ctrl = ld_le32(CNTRL_REG(p,ctrl)); + ctrl = le32_to_cpup(CNTRL_REG(p,ctrl)); if (blank_mode > 0) switch (blank_mode) { case FB_BLANK_VSYNC_SUSPEND: diff --git a/drivers/video/fbdev/platinumfb.c b/drivers/video/fbdev/platinumfb.c index 518d1fd38a81..377d3399a3ad 100644 --- a/drivers/video/fbdev/platinumfb.c +++ b/drivers/video/fbdev/platinumfb.c @@ -168,7 +168,7 @@ static int platinumfb_blank(int blank, struct fb_info *fb) struct fb_info_platinum *info = (struct fb_info_platinum *) fb; int ctrl; - ctrl = ld_le32(&info->platinum_regs->ctrl.r) | 0x33; + ctrl = le32_to_cpup(&info->platinum_regs->ctrl.r) | 0x33; if (blank) --blank_mode; if (blank & VESA_VSYNC_SUSPEND) diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index 13146d701413..0095a80a997f 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c @@ -240,7 +240,7 @@ static int snd_pmac_pcm_prepare(struct snd_pmac *chip, struct pmac_stream *rec, */ spin_lock_irq(&chip->reg_lock); snd_pmac_dma_stop(rec); - st_le16(&chip->extra_dma.cmds->command, DBDMA_STOP); + chip->extra_dma.cmds->command = cpu_to_le16(DBDMA_STOP); snd_pmac_dma_set_command(rec, &chip->extra_dma); snd_pmac_dma_run(rec, RUN); spin_unlock_irq(&chip->reg_lock); @@ -251,15 +251,15 @@ static int snd_pmac_pcm_prepare(struct snd_pmac *chip, struct pmac_stream *rec, */ offset = runtime->dma_addr; for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++) { - st_le32(&cp->phy_addr, offset); - st_le16(&cp->req_count, rec->period_size); - /*st_le16(&cp->res_count, 0);*/ - st_le16(&cp->xfer_status, 0); + cp->phy_addr = cpu_to_le32(offset); + cp->req_count = cpu_to_le16(rec->period_size); + /*cp->res_count = cpu_to_le16(0);*/ + cp->xfer_status = cpu_to_le16(0); offset += rec->period_size; } /* make loop */ - st_le16(&cp->command, DBDMA_NOP + BR_ALWAYS); - st_le32(&cp->cmd_dep, rec->cmd.addr); + cp->command = cpu_to_le16(DBDMA_NOP + BR_ALWAYS); + cp->cmd_dep = cpu_to_le32(rec->cmd.addr); snd_pmac_dma_stop(rec); snd_pmac_dma_set_command(rec, &rec->cmd); @@ -328,7 +328,7 @@ static snd_pcm_uframes_t snd_pmac_pcm_pointer(struct snd_pmac *chip, #if 1 /* hmm.. how can we get the current dma pointer?? */ int stat; volatile struct dbdma_cmd __iomem *cp = &rec->cmd.cmds[rec->cur_period]; - stat = ld_le16(&cp->xfer_status); + stat = le16_to_cpu(cp->xfer_status); if (stat & (ACTIVE|DEAD)) { count = in_le16(&cp->res_count); if (count) @@ -427,26 +427,26 @@ static inline void snd_pmac_pcm_dead_xfer(struct pmac_stream *rec, memcpy((void *)emergency_dbdma.cmds, (void *)cp, sizeof(struct dbdma_cmd)); emergency_in_use = 1; - st_le16(&cp->xfer_status, 0); - st_le16(&cp->req_count, rec->period_size); + cp->xfer_status = cpu_to_le16(0); + cp->req_count = cpu_to_le16(rec->period_size); cp = emergency_dbdma.cmds; } /* now bump the values to reflect the amount we haven't yet shifted */ - req = ld_le16(&cp->req_count); - res = ld_le16(&cp->res_count); - phy = ld_le32(&cp->phy_addr); + req = le16_to_cpu(cp->req_count); + res = le16_to_cpu(cp->res_count); + phy = le32_to_cpu(cp->phy_addr); phy += (req - res); - st_le16(&cp->req_count, res); - st_le16(&cp->res_count, 0); - st_le16(&cp->xfer_status, 0); - st_le32(&cp->phy_addr, phy); + cp->req_count = cpu_to_le16(res); + cp->res_count = cpu_to_le16(0); + cp->xfer_status = cpu_to_le16(0); + cp->phy_addr = cpu_to_le32(phy); - st_le32(&cp->cmd_dep, rec->cmd.addr + cp->cmd_dep = cpu_to_le32(rec->cmd.addr + sizeof(struct dbdma_cmd)*((rec->cur_period+1)%rec->nperiods)); - st_le16(&cp->command, OUTPUT_MORE | BR_ALWAYS | INTR_ALWAYS); + cp->command = cpu_to_le16(OUTPUT_MORE | BR_ALWAYS | INTR_ALWAYS); /* point at our patched up command block */ out_le32(&rec->dma->cmdptr, emergency_dbdma.addr); @@ -475,7 +475,7 @@ static void snd_pmac_pcm_update(struct snd_pmac *chip, struct pmac_stream *rec) else cp = &rec->cmd.cmds[rec->cur_period]; - stat = ld_le16(&cp->xfer_status); + stat = le16_to_cpu(cp->xfer_status); if (stat & DEAD) { snd_pmac_pcm_dead_xfer(rec, cp); @@ -489,9 +489,9 @@ static void snd_pmac_pcm_update(struct snd_pmac *chip, struct pmac_stream *rec) break; /*printk(KERN_DEBUG "update frag %d\n", rec->cur_period);*/ - st_le16(&cp->xfer_status, 0); - st_le16(&cp->req_count, rec->period_size); - /*st_le16(&cp->res_count, 0);*/ + cp->xfer_status = cpu_to_le16(0); + cp->req_count = cpu_to_le16(rec->period_size); + /*cp->res_count = cpu_to_le16(0);*/ rec->cur_period++; if (rec->cur_period >= rec->nperiods) { rec->cur_period = 0; @@ -760,11 +760,11 @@ void snd_pmac_beep_dma_start(struct snd_pmac *chip, int bytes, unsigned long add struct pmac_stream *rec = &chip->playback; snd_pmac_dma_stop(rec); - st_le16(&chip->extra_dma.cmds->req_count, bytes); - st_le16(&chip->extra_dma.cmds->xfer_status, 0); - st_le32(&chip->extra_dma.cmds->cmd_dep, chip->extra_dma.addr); - st_le32(&chip->extra_dma.cmds->phy_addr, addr); - st_le16(&chip->extra_dma.cmds->command, OUTPUT_MORE + BR_ALWAYS); + chip->extra_dma.cmds->req_count = cpu_to_le16(bytes); + chip->extra_dma.cmds->xfer_status = cpu_to_le16(0); + chip->extra_dma.cmds->cmd_dep = cpu_to_le32(chip->extra_dma.addr); + chip->extra_dma.cmds->phy_addr = cpu_to_le32(addr); + chip->extra_dma.cmds->command = cpu_to_le16(OUTPUT_MORE + BR_ALWAYS); out_le32(&chip->awacs->control, (in_le32(&chip->awacs->control) & ~0x1f00) | (speed << 8)); @@ -776,7 +776,7 @@ void snd_pmac_beep_dma_start(struct snd_pmac *chip, int bytes, unsigned long add void snd_pmac_beep_dma_stop(struct snd_pmac *chip) { snd_pmac_dma_stop(&chip->playback); - st_le16(&chip->extra_dma.cmds->command, DBDMA_STOP); + chip->extra_dma.cmds->command = cpu_to_le16(DBDMA_STOP); snd_pmac_pcm_set_format(chip); /* reset format */ } -- cgit v1.2.3 From 4d9fb711e43a45be17795df4b59c46ee59485d82 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Wed, 11 Mar 2015 20:13:34 +0100 Subject: powerpc: use kbuild generic-y where possible Replace one line asm-generic include files declared in arch/powerpc/include/asm/ by generic-y declaration which creates arch/powerpc/include/generated/asm equivalent. Signed-off-by: Fabian Frederick Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/Kbuild | 4 +++- arch/powerpc/include/asm/div64.h | 1 - arch/powerpc/include/asm/irq_regs.h | 2 -- arch/powerpc/include/asm/local64.h | 1 - 4 files changed, 3 insertions(+), 5 deletions(-) delete mode 100644 arch/powerpc/include/asm/div64.h delete mode 100644 arch/powerpc/include/asm/irq_regs.h delete mode 100644 arch/powerpc/include/asm/local64.h (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild index 382b28e364dc..4b87205c230c 100644 --- a/arch/powerpc/include/asm/Kbuild +++ b/arch/powerpc/include/asm/Kbuild @@ -1,6 +1,8 @@ - generic-y += clkdev.h +generic-y += div64.h +generic-y += irq_regs.h generic-y += irq_work.h +generic-y += local64.h generic-y += mcs_spinlock.h generic-y += preempt.h generic-y += rwsem.h diff --git a/arch/powerpc/include/asm/div64.h b/arch/powerpc/include/asm/div64.h deleted file mode 100644 index 6cd978cefb28..000000000000 --- a/arch/powerpc/include/asm/div64.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/powerpc/include/asm/irq_regs.h b/arch/powerpc/include/asm/irq_regs.h deleted file mode 100644 index ba94b51a0a70..000000000000 --- a/arch/powerpc/include/asm/irq_regs.h +++ /dev/null @@ -1,2 +0,0 @@ -#include - diff --git a/arch/powerpc/include/asm/local64.h b/arch/powerpc/include/asm/local64.h deleted file mode 100644 index 36c93b5cc239..000000000000 --- a/arch/powerpc/include/asm/local64.h +++ /dev/null @@ -1 +0,0 @@ -#include -- cgit v1.2.3 From 807d38b73b63bbbaa8e1baacf76f7874992f91e8 Mon Sep 17 00:00:00 2001 From: Hongtao Jia Date: Wed, 10 Apr 2013 10:52:55 +0800 Subject: powerpc/mpic: Add get_version API both for internal and external use MPIC version is useful information for both mpic_alloc() and mpic_init(). The patch provide an API to get MPIC version for reusing the code. Also, some other IP block may need MPIC version for their own use. The API for external use is also provided. This function had been previously added but was removed by commit 5e86bfde9cd93f2 ("powerpc/mpic: remove unused functions") due to the lack of a user. This function will be used by "powerpc/mpic: Add get_version API both for internal and external use". Signed-off-by: Jia Hongtao Signed-off-by: Li Yang [scottwood@freescale.com: changelog update] Signed-off-by: Scott Wood --- arch/powerpc/include/asm/mpic.h | 3 +++ arch/powerpc/sysdev/mpic.c | 10 ++++++++++ 2 files changed, 13 insertions(+) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/mpic.h b/arch/powerpc/include/asm/mpic.h index 6ce63a7662f8..98697611e7b3 100644 --- a/arch/powerpc/include/asm/mpic.h +++ b/arch/powerpc/include/asm/mpic.h @@ -391,6 +391,9 @@ extern struct bus_type mpic_subsys; #define MPIC_REGSET_STANDARD MPIC_REGSET(0) /* Original MPIC */ #define MPIC_REGSET_TSI108 MPIC_REGSET(1) /* Tsi108/109 PIC */ +/* Get the version of primary MPIC */ +extern u32 fsl_mpic_primary_get_version(void); + /* Allocate the controller structure and setup the linux irq descs * for the range if interrupts passed in. No HW initialization is * actually performed. diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index f72b592d60cc..2c817a736b77 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -1219,6 +1219,16 @@ static u32 fsl_mpic_get_version(struct mpic *mpic) * Exported functions */ +u32 fsl_mpic_primary_get_version(void) +{ + struct mpic *mpic = mpic_primary; + + if (mpic) + return fsl_mpic_get_version(mpic); + + return 0; +} + struct mpic * __init mpic_alloc(struct device_node *node, phys_addr_t phys_addr, unsigned int flags, -- cgit v1.2.3 From cca87d303c85b257a7b0fd34f9d6fce1c59880a2 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Tue, 17 Mar 2015 16:15:02 +1100 Subject: powerpc/pci: Refactor pci_dn Currently, the PCI config accessors are implemented based on device node. Unfortunately, SRIOV VFs won't have the corresponding device nodes. pci_dn will be used in replacement with device node for SRIOV VFs. So we have to use pci_dn in PCI config accessors. The patch refactors pci_dn in following aspects to make it ready to be used in PCI config accessors as we do in subsequent patch: * pci_dn is organized as a hierarchy tree. PCI device's pci_dn is put to the child list of pci_dn of its upstream bridge or PHB. VF's pci_dn will be put to the child list of pci_dn of PF's bridge. * For one particular PCI device (VF or not), its pci_dn can be found from pdev->dev.archdata.pci_data, PCI_DN(devnode), or parent's list. The fast path (fetching pci_dn through PCI device instance) is populated during early fixup time. [bhelgaas: changelog] Signed-off-by: Gavin Shan Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/device.h | 6 ++ arch/powerpc/include/asm/pci-bridge.h | 11 ++- arch/powerpc/kernel/pci_dn.c | 130 ++++++++++++++++++++++++++++++++-- 3 files changed, 141 insertions(+), 6 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/device.h b/arch/powerpc/include/asm/device.h index 38faeded7d59..9f1371bab5fc 100644 --- a/arch/powerpc/include/asm/device.h +++ b/arch/powerpc/include/asm/device.h @@ -8,6 +8,9 @@ struct dma_map_ops; struct device_node; +#ifdef CONFIG_PPC64 +struct pci_dn; +#endif /* * Arch extensions to struct device. @@ -34,6 +37,9 @@ struct dev_archdata { #ifdef CONFIG_SWIOTLB dma_addr_t max_direct_dma_addr; #endif +#ifdef CONFIG_PPC64 + struct pci_dn *pci_data; +#endif #ifdef CONFIG_EEH struct eeh_dev *edev; #endif diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 546d036fe925..706710b571c3 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -89,6 +89,7 @@ struct pci_controller { #ifdef CONFIG_PPC64 unsigned long buid; + struct pci_dn *pci_data; #endif /* CONFIG_PPC64 */ void *private_data; @@ -154,9 +155,12 @@ static inline int isa_vaddr_is_ioport(void __iomem *address) struct iommu_table; struct pci_dn { + int flags; + int busno; /* pci bus number */ int devfn; /* pci device and function number */ + struct pci_dn *parent; struct pci_controller *phb; /* for pci devices */ struct iommu_table *iommu_table; /* for phb's or bridges */ struct device_node *node; /* back-pointer to the device_node */ @@ -171,14 +175,17 @@ struct pci_dn { #ifdef CONFIG_PPC_POWERNV int pe_number; #endif + struct list_head child_list; + struct list_head list; }; /* Get the pointer to a device_node's pci_dn */ #define PCI_DN(dn) ((struct pci_dn *) (dn)->data) +extern struct pci_dn *pci_get_pdn_by_devfn(struct pci_bus *bus, + int devfn); extern struct pci_dn *pci_get_pdn(struct pci_dev *pdev); - -extern void * update_dn_pci_info(struct device_node *dn, void *data); +extern void *update_dn_pci_info(struct device_node *dn, void *data); static inline int pci_device_from_OF_node(struct device_node *np, u8 *bus, u8 *devfn) diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c index 83df3075d3df..0ab2dadaf842 100644 --- a/arch/powerpc/kernel/pci_dn.c +++ b/arch/powerpc/kernel/pci_dn.c @@ -32,12 +32,108 @@ #include #include +/* + * The function is used to find the firmware data of one + * specific PCI device, which is attached to the indicated + * PCI bus. For VFs, their firmware data is linked to that + * one of PF's bridge. For other devices, their firmware + * data is linked to that of their bridge. + */ +static struct pci_dn *pci_bus_to_pdn(struct pci_bus *bus) +{ + struct pci_bus *pbus; + struct device_node *dn; + struct pci_dn *pdn; + + /* + * We probably have virtual bus which doesn't + * have associated bridge. + */ + pbus = bus; + while (pbus) { + if (pci_is_root_bus(pbus) || pbus->self) + break; + + pbus = pbus->parent; + } + + /* + * Except virtual bus, all PCI buses should + * have device nodes. + */ + dn = pci_bus_to_OF_node(pbus); + pdn = dn ? PCI_DN(dn) : NULL; + + return pdn; +} + +struct pci_dn *pci_get_pdn_by_devfn(struct pci_bus *bus, + int devfn) +{ + struct device_node *dn = NULL; + struct pci_dn *parent, *pdn; + struct pci_dev *pdev = NULL; + + /* Fast path: fetch from PCI device */ + list_for_each_entry(pdev, &bus->devices, bus_list) { + if (pdev->devfn == devfn) { + if (pdev->dev.archdata.pci_data) + return pdev->dev.archdata.pci_data; + + dn = pci_device_to_OF_node(pdev); + break; + } + } + + /* Fast path: fetch from device node */ + pdn = dn ? PCI_DN(dn) : NULL; + if (pdn) + return pdn; + + /* Slow path: fetch from firmware data hierarchy */ + parent = pci_bus_to_pdn(bus); + if (!parent) + return NULL; + + list_for_each_entry(pdn, &parent->child_list, list) { + if (pdn->busno == bus->number && + pdn->devfn == devfn) + return pdn; + } + + return NULL; +} + struct pci_dn *pci_get_pdn(struct pci_dev *pdev) { - struct device_node *dn = pci_device_to_OF_node(pdev); - if (!dn) + struct device_node *dn; + struct pci_dn *parent, *pdn; + + /* Search device directly */ + if (pdev->dev.archdata.pci_data) + return pdev->dev.archdata.pci_data; + + /* Check device node */ + dn = pci_device_to_OF_node(pdev); + pdn = dn ? PCI_DN(dn) : NULL; + if (pdn) + return pdn; + + /* + * VFs don't have device nodes. We hook their + * firmware data to PF's bridge. + */ + parent = pci_bus_to_pdn(pdev->bus); + if (!parent) return NULL; - return PCI_DN(dn); + + list_for_each_entry(pdn, &parent->child_list, list) { + if (pdn->busno == pdev->bus->number && + pdn->devfn == pdev->devfn) + return pdn; + } + + return NULL; } /* @@ -49,6 +145,7 @@ void *update_dn_pci_info(struct device_node *dn, void *data) struct pci_controller *phb = data; const __be32 *type = of_get_property(dn, "ibm,pci-config-space-type", NULL); const __be32 *regs; + struct device_node *parent; struct pci_dn *pdn; pdn = zalloc_maybe_bootmem(sizeof(*pdn), GFP_KERNEL); @@ -70,6 +167,15 @@ void *update_dn_pci_info(struct device_node *dn, void *data) } pdn->pci_ext_config_space = (type && of_read_number(type, 1) == 1); + + /* Attach to parent node */ + INIT_LIST_HEAD(&pdn->child_list); + INIT_LIST_HEAD(&pdn->list); + parent = of_get_parent(dn); + pdn->parent = parent ? PCI_DN(parent) : NULL; + if (pdn->parent) + list_add_tail(&pdn->list, &pdn->parent->child_list); + return NULL; } @@ -147,8 +253,11 @@ void pci_devs_phb_init_dynamic(struct pci_controller *phb) /* PHB nodes themselves must not match */ update_dn_pci_info(dn, phb); pdn = dn->data; - if (pdn) + if (pdn) { pdn->devfn = pdn->busno = -1; + pdn->phb = phb; + phb->pci_data = pdn; + } /* Update dn->phb ptrs for new phb and children devices */ traverse_pci_devices(dn, update_dn_pci_info, phb); @@ -171,3 +280,16 @@ void __init pci_devs_phb_init(void) list_for_each_entry_safe(phb, tmp, &hose_list, list_node) pci_devs_phb_init_dynamic(phb); } + +static void pci_dev_pdn_setup(struct pci_dev *pdev) +{ + struct pci_dn *pdn; + + if (pdev->dev.archdata.pci_data) + return; + + /* Setup the fast path */ + pdn = pci_get_pdn(pdev); + pdev->dev.archdata.pci_data = pdn; +} +DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, pci_dev_pdn_setup); -- cgit v1.2.3 From c035ff1d2eaa03ab40839041e955a86a8e412eb4 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Tue, 17 Mar 2015 16:15:04 +1100 Subject: powerpc/pci: Trace more information from pci_dn Originally, EEH probes on device_node or pci_dev and populates the corresponding eeh_dev. In the subsequent patches, EEH will probes on pci_dn and populates the corresponding eeh_dev. So we have to cache some information in pci_dn, either from device_node or SRIOV PF's enablement platform hook, to populate the eeh_dev properly. The motivation to probe pci_dn, instead of device node or pci_dev, to populate eeh_dev is SRIOV VFs are dynamically created and we don't have the corresponding device nodes for them. Signed-off-by: Gavin Shan Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/pci-bridge.h | 3 +++ arch/powerpc/kernel/pci_dn.c | 10 ++++++++++ 2 files changed, 13 insertions(+) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 706710b571c3..01b730a8a5a3 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -159,6 +159,9 @@ struct pci_dn { int busno; /* pci bus number */ int devfn; /* pci device and function number */ + int vendor_id; /* Vendor ID */ + int device_id; /* Device ID */ + int class_code; /* Device class code */ struct pci_dn *parent; struct pci_controller *phb; /* for pci devices */ diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c index 0ab2dadaf842..d139f72ff9d5 100644 --- a/arch/powerpc/kernel/pci_dn.c +++ b/arch/powerpc/kernel/pci_dn.c @@ -166,6 +166,15 @@ void *update_dn_pci_info(struct device_node *dn, void *data) pdn->devfn = (addr >> 8) & 0xff; } + /* vendor/device IDs and class code */ + regs = of_get_property(dn, "vendor-id", NULL); + pdn->vendor_id = regs ? of_read_number(regs, 1) : 0; + regs = of_get_property(dn, "device-id", NULL); + pdn->device_id = regs ? of_read_number(regs, 1) : 0; + regs = of_get_property(dn, "class-code", NULL); + pdn->class_code = regs ? of_read_number(regs, 1) : 0; + + /* Extended config space */ pdn->pci_ext_config_space = (type && of_read_number(type, 1) == 1); /* Attach to parent node */ @@ -255,6 +264,7 @@ void pci_devs_phb_init_dynamic(struct pci_controller *phb) pdn = dn->data; if (pdn) { pdn->devfn = pdn->busno = -1; + pdn->vendor_id = pdn->device_id = pdn->class_code = 0; pdn->phb = phb; phb->pci_data = pdn; } -- cgit v1.2.3 From e8e9b34cef237d4d6fdc0d350cd8a95d1adb9ee9 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Tue, 17 Mar 2015 16:15:05 +1100 Subject: powerpc/eeh: Create eeh_dev from pci_dn instead of device_node The patch adds function traverse_pci_dn(), which is similar to traverse_pci_devices() except it takes pci_dn, not device_node as parameter. The pci_dev.c has been reworked to create eeh_dev from pci_dn, instead of device_node. Signed-off-by: Gavin Shan Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/eeh.h | 11 ++++++++-- arch/powerpc/include/asm/pci-bridge.h | 8 ++++++- arch/powerpc/include/asm/ppc-pci.h | 5 +++++ arch/powerpc/kernel/eeh_dev.c | 14 ++++++------ arch/powerpc/kernel/pci_dn.c | 40 ++++++++++++++++++++++++++++++++++ arch/powerpc/platforms/pseries/setup.c | 2 +- 6 files changed, 69 insertions(+), 11 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index 55abfd09e47f..2106f83da2d5 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h @@ -30,6 +30,7 @@ struct pci_dev; struct pci_bus; struct device_node; +struct pci_dn; #ifdef CONFIG_EEH @@ -137,6 +138,7 @@ struct eeh_dev { struct list_head list; /* Form link list in the PE */ struct pci_controller *phb; /* Associated PHB */ struct device_node *dn; /* Associated device node */ + struct pci_dn *pdn; /* Associated PCI device node */ struct pci_dev *pdev; /* Associated PCI device */ struct pci_bus *bus; /* PCI bus for partial hotplug */ }; @@ -146,6 +148,11 @@ static inline struct device_node *eeh_dev_to_of_node(struct eeh_dev *edev) return edev ? edev->dn : NULL; } +static inline struct pci_dn *eeh_dev_to_pdn(struct eeh_dev *edev) +{ + return edev ? edev->pdn : NULL; +} + static inline struct pci_dev *eeh_dev_to_pci_dev(struct eeh_dev *edev) { return edev ? edev->pdev : NULL; @@ -272,7 +279,7 @@ void eeh_pe_restore_bars(struct eeh_pe *pe); const char *eeh_pe_loc_get(struct eeh_pe *pe); struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe); -void *eeh_dev_init(struct device_node *dn, void *data); +void *eeh_dev_init(struct pci_dn *pdn, void *data); void eeh_dev_phb_init_dynamic(struct pci_controller *phb); int eeh_init(void); int __init eeh_ops_register(struct eeh_ops *ops); @@ -323,7 +330,7 @@ static inline int eeh_init(void) return 0; } -static inline void *eeh_dev_init(struct device_node *dn, void *data) +static inline void *eeh_dev_init(struct pci_dn *pdn, void *data) { return NULL; } diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 01b730a8a5a3..7b74499b728c 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -213,8 +213,14 @@ static inline struct eeh_dev *of_node_to_eeh_dev(struct device_node *dn) return PCI_DN(dn)->edev; } + +static inline struct eeh_dev *pdn_to_eeh_dev(struct pci_dn *pdn) +{ + return pdn ? pdn->edev : NULL; +} #else -#define of_node_to_eeh_dev(x) (NULL) +#define of_node_to_eeh_dev(x) (NULL) +#define pdn_to_eeh_dev(x) (NULL) #endif /** Find the bus corresponding to the indicated device node */ diff --git a/arch/powerpc/include/asm/ppc-pci.h b/arch/powerpc/include/asm/ppc-pci.h index db1e2b8eff3c..ade75238ceb5 100644 --- a/arch/powerpc/include/asm/ppc-pci.h +++ b/arch/powerpc/include/asm/ppc-pci.h @@ -33,9 +33,14 @@ extern struct pci_dev *isa_bridge_pcidev; /* may be NULL if no ISA bus */ /* PCI device_node operations */ struct device_node; +struct pci_dn; + typedef void *(*traverse_func)(struct device_node *me, void *data); void *traverse_pci_devices(struct device_node *start, traverse_func pre, void *data); +void *traverse_pci_dn(struct pci_dn *root, + void *(*fn)(struct pci_dn *, void *), + void *data); extern void pci_devs_phb_init(void); extern void pci_devs_phb_init_dynamic(struct pci_controller *phb); diff --git a/arch/powerpc/kernel/eeh_dev.c b/arch/powerpc/kernel/eeh_dev.c index e5274ee9a75f..aabba94ff9cb 100644 --- a/arch/powerpc/kernel/eeh_dev.c +++ b/arch/powerpc/kernel/eeh_dev.c @@ -43,13 +43,13 @@ /** * eeh_dev_init - Create EEH device according to OF node - * @dn: device node + * @pdn: PCI device node * @data: PHB * * It will create EEH device according to the given OF node. The function * might be called by PCI emunation, DR, PHB hotplug. */ -void *eeh_dev_init(struct device_node *dn, void *data) +void *eeh_dev_init(struct pci_dn *pdn, void *data) { struct pci_controller *phb = data; struct eeh_dev *edev; @@ -63,8 +63,8 @@ void *eeh_dev_init(struct device_node *dn, void *data) } /* Associate EEH device with OF node */ - PCI_DN(dn)->edev = edev; - edev->dn = dn; + pdn->edev = edev; + edev->pdn = pdn; edev->phb = phb; INIT_LIST_HEAD(&edev->list); @@ -80,16 +80,16 @@ void *eeh_dev_init(struct device_node *dn, void *data) */ void eeh_dev_phb_init_dynamic(struct pci_controller *phb) { - struct device_node *dn = phb->dn; + struct pci_dn *root = phb->pci_data; /* EEH PE for PHB */ eeh_phb_pe_create(phb); /* EEH device for PHB */ - eeh_dev_init(dn, phb); + eeh_dev_init(root, phb); /* EEH devices for children OF nodes */ - traverse_pci_devices(dn, eeh_dev_init, phb); + traverse_pci_dn(root, eeh_dev_init, phb); } /** diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c index d139f72ff9d5..65b98367005c 100644 --- a/arch/powerpc/kernel/pci_dn.c +++ b/arch/powerpc/kernel/pci_dn.c @@ -246,6 +246,46 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre, return NULL; } +static struct pci_dn *pci_dn_next_one(struct pci_dn *root, + struct pci_dn *pdn) +{ + struct list_head *next = pdn->child_list.next; + + if (next != &pdn->child_list) + return list_entry(next, struct pci_dn, list); + + while (1) { + if (pdn == root) + return NULL; + + next = pdn->list.next; + if (next != &pdn->parent->child_list) + break; + + pdn = pdn->parent; + } + + return list_entry(next, struct pci_dn, list); +} + +void *traverse_pci_dn(struct pci_dn *root, + void *(*fn)(struct pci_dn *, void *), + void *data) +{ + struct pci_dn *pdn = root; + void *ret; + + /* Only scan the child nodes */ + for (pdn = pci_dn_next_one(root, pdn); pdn; + pdn = pci_dn_next_one(root, pdn)) { + ret = fn(pdn, data); + if (ret) + return ret; + } + + return NULL; +} + /** * pci_devs_phb_init_dynamic - setup pci devices under this PHB * phb: pci-to-host bridge (top-level bridge connecting to cpu) diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index e445b6701f50..70304070a260 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -265,7 +265,7 @@ static int pci_dn_reconfig_notifier(struct notifier_block *nb, unsigned long act update_dn_pci_info(np, pci->phb); /* Create EEH device for the OF node */ - eeh_dev_init(np, pci->phb); + eeh_dev_init(PCI_DN(np), pci->phb); } break; default: -- cgit v1.2.3 From ff57b454ddb938d98d48d8df356357000fedc88c Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Tue, 17 Mar 2015 16:15:06 +1100 Subject: powerpc/eeh: Do probe on pci_dn Originally, EEH core probes on device_node or pci_dev to populate EEH devices and PEs, which conflicts with the fact: SRIOV VFs are usually enabled and created by PF's driver and they don't have the corresponding device_nodes. Instead, SRIOV VFs have dynamically created pci_dn, which can be used for EEH probe. The patch reworks EEH probe for PowerNV and pSeries platforms to do probing based on pci_dn, instead of pci_dev or device_node any more. Signed-off-by: Gavin Shan Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/eeh.h | 11 +- arch/powerpc/kernel/eeh.c | 63 ++++-------- arch/powerpc/kernel/of_platform.c | 2 +- arch/powerpc/kernel/pci-hotplug.c | 2 +- arch/powerpc/platforms/powernv/eeh-powernv.c | 146 ++++++++++++++++++++------- arch/powerpc/platforms/pseries/eeh_pseries.c | 82 ++++++--------- arch/powerpc/platforms/pseries/pci_dlpar.c | 2 +- drivers/pci/hotplug/rpadlpar_core.c | 2 +- 8 files changed, 172 insertions(+), 138 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index 2106f83da2d5..87797811808f 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h @@ -207,8 +207,7 @@ struct eeh_ops { char *name; int (*init)(void); int (*post_init)(void); - void* (*of_probe)(struct device_node *dn, void *flag); - int (*dev_probe)(struct pci_dev *dev, void *flag); + void* (*probe)(struct pci_dn *pdn, void *data); int (*set_option)(struct eeh_pe *pe, int option); int (*get_pe_addr)(struct eeh_pe *pe); int (*get_state)(struct eeh_pe *pe, int *state); @@ -287,8 +286,8 @@ int __exit eeh_ops_unregister(const char *name); int eeh_check_failure(const volatile void __iomem *token); int eeh_dev_check_failure(struct eeh_dev *edev); void eeh_addr_cache_build(void); -void eeh_add_device_early(struct device_node *); -void eeh_add_device_tree_early(struct device_node *); +void eeh_add_device_early(struct pci_dn *); +void eeh_add_device_tree_early(struct pci_dn *); void eeh_add_device_late(struct pci_dev *); void eeh_add_device_tree_late(struct pci_bus *); void eeh_add_sysfs_files(struct pci_bus *); @@ -346,9 +345,9 @@ static inline int eeh_check_failure(const volatile void __iomem *token) static inline void eeh_addr_cache_build(void) { } -static inline void eeh_add_device_early(struct device_node *dn) { } +static inline void eeh_add_device_early(struct pci_dn *pdn) { } -static inline void eeh_add_device_tree_early(struct device_node *dn) { } +static inline void eeh_add_device_tree_early(struct pci_dn *pdn) { } static inline void eeh_add_device_late(struct pci_dev *dev) { } diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index 19a897c810be..9504c2f0bb54 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c @@ -969,7 +969,7 @@ static struct notifier_block eeh_reboot_nb = { int eeh_init(void) { struct pci_controller *hose, *tmp; - struct device_node *phb; + struct pci_dn *pdn; static int cnt = 0; int ret = 0; @@ -1004,20 +1004,9 @@ int eeh_init(void) return ret; /* Enable EEH for all adapters */ - if (eeh_has_flag(EEH_PROBE_MODE_DEVTREE)) { - list_for_each_entry_safe(hose, tmp, - &hose_list, list_node) { - phb = hose->dn; - traverse_pci_devices(phb, eeh_ops->of_probe, NULL); - } - } else if (eeh_has_flag(EEH_PROBE_MODE_DEV)) { - list_for_each_entry_safe(hose, tmp, - &hose_list, list_node) - pci_walk_bus(hose->bus, eeh_ops->dev_probe, NULL); - } else { - pr_warn("%s: Invalid probe mode %x", - __func__, eeh_subsystem_flags); - return -EINVAL; + list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { + pdn = hose->pci_data; + traverse_pci_dn(pdn, eeh_ops->probe, NULL); } /* @@ -1043,7 +1032,7 @@ core_initcall_sync(eeh_init); /** * eeh_add_device_early - Enable EEH for the indicated device_node - * @dn: device node for which to set up EEH + * @pdn: PCI device node for which to set up EEH * * This routine must be used to perform EEH initialization for PCI * devices that were added after system boot (e.g. hotplug, dlpar). @@ -1053,44 +1042,41 @@ core_initcall_sync(eeh_init); * on the CEC architecture, type of the device, on earlier boot * command-line arguments & etc. */ -void eeh_add_device_early(struct device_node *dn) +void eeh_add_device_early(struct pci_dn *pdn) { struct pci_controller *phb; + struct eeh_dev *edev = pdn_to_eeh_dev(pdn); - /* - * If we're doing EEH probe based on PCI device, we - * would delay the probe until late stage because - * the PCI device isn't available this moment. - */ - if (!eeh_has_flag(EEH_PROBE_MODE_DEVTREE)) - return; - - if (!of_node_to_eeh_dev(dn)) + if (!edev) return; - phb = of_node_to_eeh_dev(dn)->phb; /* USB Bus children of PCI devices will not have BUID's */ - if (NULL == phb || 0 == phb->buid) + phb = edev->phb; + if (NULL == phb || + (eeh_has_flag(EEH_PROBE_MODE_DEVTREE) && 0 == phb->buid)) return; - eeh_ops->of_probe(dn, NULL); + eeh_ops->probe(pdn, NULL); } /** * eeh_add_device_tree_early - Enable EEH for the indicated device - * @dn: device node + * @pdn: PCI device node * * This routine must be used to perform EEH initialization for the * indicated PCI device that was added after system boot (e.g. * hotplug, dlpar). */ -void eeh_add_device_tree_early(struct device_node *dn) +void eeh_add_device_tree_early(struct pci_dn *pdn) { - struct device_node *sib; + struct pci_dn *n; + + if (!pdn) + return; - for_each_child_of_node(dn, sib) - eeh_add_device_tree_early(sib); - eeh_add_device_early(dn); + list_for_each_entry(n, &pdn->child_list, list) + eeh_add_device_tree_early(n); + eeh_add_device_early(pdn); } EXPORT_SYMBOL_GPL(eeh_add_device_tree_early); @@ -1144,13 +1130,6 @@ void eeh_add_device_late(struct pci_dev *dev) edev->pdev = dev; dev->dev.archdata.edev = edev; - /* - * We have to do the EEH probe here because the PCI device - * hasn't been created yet in the early stage. - */ - if (eeh_has_flag(EEH_PROBE_MODE_DEV)) - eeh_ops->dev_probe(dev, NULL); - eeh_addr_cache_insert_dev(dev); } diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c index 2f35a72642c6..b60a67d92ebd 100644 --- a/arch/powerpc/kernel/of_platform.c +++ b/arch/powerpc/kernel/of_platform.c @@ -72,7 +72,7 @@ static int of_pci_phb_probe(struct platform_device *dev) /* Register devices with EEH */ if (dev->dev.of_node->child) - eeh_add_device_tree_early(dev->dev.of_node); + eeh_add_device_tree_early(PCI_DN(dev->dev.of_node)); /* Scan the bus */ pcibios_scan_phb(phb); diff --git a/arch/powerpc/kernel/pci-hotplug.c b/arch/powerpc/kernel/pci-hotplug.c index 5b789177aa29..18d9575729a3 100644 --- a/arch/powerpc/kernel/pci-hotplug.c +++ b/arch/powerpc/kernel/pci-hotplug.c @@ -75,7 +75,7 @@ void pcibios_add_pci_devices(struct pci_bus * bus) struct pci_dev *dev; struct device_node *dn = pci_bus_to_OF_node(bus); - eeh_add_device_tree_early(dn); + eeh_add_device_tree_early(PCI_DN(dn)); mode = PCI_PROBE_NORMAL; if (ppc_md.pci_probe_mode) diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index 8eac8c57ee86..dcc524fe2a30 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c @@ -286,10 +286,82 @@ static int pnv_eeh_post_init(void) return ret; } +static int pnv_eeh_cap_start(struct pci_dn *pdn) +{ + u32 status; + + if (!pdn) + return 0; + + pnv_pci_cfg_read(pdn, PCI_STATUS, 2, &status); + if (!(status & PCI_STATUS_CAP_LIST)) + return 0; + + return PCI_CAPABILITY_LIST; +} + +static int pnv_eeh_find_cap(struct pci_dn *pdn, int cap) +{ + int pos = pnv_eeh_cap_start(pdn); + int cnt = 48; /* Maximal number of capabilities */ + u32 id; + + if (!pos) + return 0; + + while (cnt--) { + pnv_pci_cfg_read(pdn, pos, 1, &pos); + if (pos < 0x40) + break; + + pos &= ~3; + pnv_pci_cfg_read(pdn, pos + PCI_CAP_LIST_ID, 1, &id); + if (id == 0xff) + break; + + /* Found */ + if (id == cap) + return pos; + + /* Next one */ + pos += PCI_CAP_LIST_NEXT; + } + + return 0; +} + +static int pnv_eeh_find_ecap(struct pci_dn *pdn, int cap) +{ + struct eeh_dev *edev = pdn_to_eeh_dev(pdn); + u32 header; + int pos = 256, ttl = (4096 - 256) / 8; + + if (!edev || !edev->pcie_cap) + return 0; + if (pnv_pci_cfg_read(pdn, pos, 4, &header) != PCIBIOS_SUCCESSFUL) + return 0; + else if (!header) + return 0; + + while (ttl-- > 0) { + if (PCI_EXT_CAP_ID(header) == cap && pos) + return pos; + + pos = PCI_EXT_CAP_NEXT(header); + if (pos < 256) + break; + + if (pnv_pci_cfg_read(pdn, pos, 4, &header) != PCIBIOS_SUCCESSFUL) + break; + } + + return 0; +} + /** - * pnv_eeh_dev_probe - Do probe on PCI device - * @dev: PCI device - * @flag: unused + * pnv_eeh_probe - Do probe on PCI device + * @pdn: PCI device node + * @data: unused * * When EEH module is installed during system boot, all PCI devices * are checked one by one to see if it supports EEH. The function @@ -303,12 +375,12 @@ static int pnv_eeh_post_init(void) * was possiblly triggered by EEH core, the binding between EEH device * and the PCI device isn't built yet. */ -static int pnv_eeh_dev_probe(struct pci_dev *dev, void *flag) +static void *pnv_eeh_probe(struct pci_dn *pdn, void *data) { - struct pci_controller *hose = pci_bus_to_host(dev->bus); + struct pci_controller *hose = pdn->phb; struct pnv_phb *phb = hose->private_data; - struct device_node *dn = pci_device_to_OF_node(dev); - struct eeh_dev *edev = of_node_to_eeh_dev(dn); + struct eeh_dev *edev = pdn_to_eeh_dev(pdn); + uint32_t pcie_flags; int ret; /* @@ -317,40 +389,42 @@ static int pnv_eeh_dev_probe(struct pci_dev *dev, void *flag) * the root bridge. So it's not reasonable to continue * the probing. */ - if (!dn || !edev || edev->pe) - return 0; + if (!edev || edev->pe) + return NULL; /* Skip for PCI-ISA bridge */ - if ((dev->class >> 8) == PCI_CLASS_BRIDGE_ISA) - return 0; + if ((pdn->class_code >> 8) == PCI_CLASS_BRIDGE_ISA) + return NULL; /* Initialize eeh device */ - edev->class_code = dev->class; + edev->class_code = pdn->class_code; edev->mode &= 0xFFFFFF00; - if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) + edev->pcix_cap = pnv_eeh_find_cap(pdn, PCI_CAP_ID_PCIX); + edev->pcie_cap = pnv_eeh_find_cap(pdn, PCI_CAP_ID_EXP); + edev->aer_cap = pnv_eeh_find_ecap(pdn, PCI_EXT_CAP_ID_ERR); + if ((edev->class_code >> 8) == PCI_CLASS_BRIDGE_PCI) { edev->mode |= EEH_DEV_BRIDGE; - edev->pcix_cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); - if (pci_is_pcie(dev)) { - edev->pcie_cap = pci_pcie_cap(dev); - - if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) - edev->mode |= EEH_DEV_ROOT_PORT; - else if (pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) - edev->mode |= EEH_DEV_DS_PORT; - - edev->aer_cap = pci_find_ext_capability(dev, - PCI_EXT_CAP_ID_ERR); + if (edev->pcie_cap) { + pnv_pci_cfg_read(pdn, edev->pcie_cap + PCI_EXP_FLAGS, + 2, &pcie_flags); + pcie_flags = (pcie_flags & PCI_EXP_FLAGS_TYPE) >> 4; + if (pcie_flags == PCI_EXP_TYPE_ROOT_PORT) + edev->mode |= EEH_DEV_ROOT_PORT; + else if (pcie_flags == PCI_EXP_TYPE_DOWNSTREAM) + edev->mode |= EEH_DEV_DS_PORT; + } } - edev->config_addr = ((dev->bus->number << 8) | dev->devfn); - edev->pe_config_addr = phb->bdfn_to_pe(phb, dev->bus, dev->devfn & 0xff); + edev->config_addr = (pdn->busno << 8) | (pdn->devfn); + edev->pe_config_addr = phb->ioda.pe_rmap[edev->config_addr]; /* Create PE */ ret = eeh_add_to_parent_pe(edev); if (ret) { - pr_warn("%s: Can't add PCI dev %s to parent PE (%d)\n", - __func__, pci_name(dev), ret); - return ret; + pr_warn("%s: Can't add PCI dev %04x:%02x:%02x.%01x to parent PE (%d)\n", + __func__, hose->global_number, pdn->busno, + PCI_SLOT(pdn->devfn), PCI_FUNC(pdn->devfn), ret); + return NULL; } /* @@ -369,8 +443,10 @@ static int pnv_eeh_dev_probe(struct pci_dev *dev, void *flag) * Broadcom Austin 4-ports NICs (14e4:1657) * Broadcom Shiner 2-ports 10G NICs (14e4:168e) */ - if ((dev->vendor == PCI_VENDOR_ID_BROADCOM && dev->device == 0x1657) || - (dev->vendor == PCI_VENDOR_ID_BROADCOM && dev->device == 0x168e)) + if ((pdn->vendor_id == PCI_VENDOR_ID_BROADCOM && + pdn->device_id == 0x1657) || + (pdn->vendor_id == PCI_VENDOR_ID_BROADCOM && + pdn->device_id == 0x168e)) edev->pe->state |= EEH_PE_CFG_RESTRICTED; /* @@ -380,7 +456,8 @@ static int pnv_eeh_dev_probe(struct pci_dev *dev, void *flag) * to PE reset. */ if (!edev->pe->bus) - edev->pe->bus = dev->bus; + edev->pe->bus = pci_find_bus(hose->global_number, + pdn->busno); /* * Enable EEH explicitly so that we will do EEH check @@ -391,7 +468,7 @@ static int pnv_eeh_dev_probe(struct pci_dev *dev, void *flag) /* Save memory bars */ eeh_save_bars(edev); - return 0; + return NULL; } /** @@ -1432,8 +1509,7 @@ static struct eeh_ops pnv_eeh_ops = { .name = "powernv", .init = pnv_eeh_init, .post_init = pnv_eeh_post_init, - .of_probe = NULL, - .dev_probe = pnv_eeh_dev_probe, + .probe = pnv_eeh_probe, .set_option = pnv_eeh_set_option, .get_pe_addr = pnv_eeh_get_pe_addr, .get_state = pnv_eeh_get_state, diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c index a6c7e19f5eb3..a2946f72d5e7 100644 --- a/arch/powerpc/platforms/pseries/eeh_pseries.c +++ b/arch/powerpc/platforms/pseries/eeh_pseries.c @@ -118,9 +118,8 @@ static int pseries_eeh_init(void) return 0; } -static int pseries_eeh_cap_start(struct device_node *dn) +static int pseries_eeh_cap_start(struct pci_dn *pdn) { - struct pci_dn *pdn = PCI_DN(dn); u32 status; if (!pdn) @@ -134,10 +133,9 @@ static int pseries_eeh_cap_start(struct device_node *dn) } -static int pseries_eeh_find_cap(struct device_node *dn, int cap) +static int pseries_eeh_find_cap(struct pci_dn *pdn, int cap) { - struct pci_dn *pdn = PCI_DN(dn); - int pos = pseries_eeh_cap_start(dn); + int pos = pseries_eeh_cap_start(pdn); int cnt = 48; /* Maximal number of capabilities */ u32 id; @@ -160,10 +158,9 @@ static int pseries_eeh_find_cap(struct device_node *dn, int cap) return 0; } -static int pseries_eeh_find_ecap(struct device_node *dn, int cap) +static int pseries_eeh_find_ecap(struct pci_dn *pdn, int cap) { - struct pci_dn *pdn = PCI_DN(dn); - struct eeh_dev *edev = of_node_to_eeh_dev(dn); + struct eeh_dev *edev = pdn_to_eeh_dev(pdn); u32 header; int pos = 256; int ttl = (4096 - 256) / 8; @@ -191,53 +188,44 @@ static int pseries_eeh_find_ecap(struct device_node *dn, int cap) } /** - * pseries_eeh_of_probe - EEH probe on the given device - * @dn: OF node - * @flag: Unused + * pseries_eeh_probe - EEH probe on the given device + * @pdn: PCI device node + * @data: Unused * * When EEH module is installed during system boot, all PCI devices * are checked one by one to see if it supports EEH. The function * is introduced for the purpose. */ -static void *pseries_eeh_of_probe(struct device_node *dn, void *flag) +static void *pseries_eeh_probe(struct pci_dn *pdn, void *data) { struct eeh_dev *edev; struct eeh_pe pe; - struct pci_dn *pdn = PCI_DN(dn); - const __be32 *classp, *vendorp, *devicep; - u32 class_code; - const __be32 *regs; u32 pcie_flags; int enable = 0; int ret; /* Retrieve OF node and eeh device */ - edev = of_node_to_eeh_dev(dn); - if (edev->pe || !of_device_is_available(dn)) + edev = pdn_to_eeh_dev(pdn); + if (!edev || edev->pe) return NULL; - /* Retrieve class/vendor/device IDs */ - classp = of_get_property(dn, "class-code", NULL); - vendorp = of_get_property(dn, "vendor-id", NULL); - devicep = of_get_property(dn, "device-id", NULL); - - /* Skip for bad OF node or PCI-ISA bridge */ - if (!classp || !vendorp || !devicep) - return NULL; - if (dn->type && !strcmp(dn->type, "isa")) + /* Check class/vendor/device IDs */ + if (!pdn->vendor_id || !pdn->device_id || !pdn->class_code) return NULL; - class_code = of_read_number(classp, 1); + /* Skip for PCI-ISA bridge */ + if ((pdn->class_code >> 8) == PCI_CLASS_BRIDGE_ISA) + return NULL; /* * Update class code and mode of eeh device. We need * correctly reflects that current device is root port * or PCIe switch downstream port. */ - edev->class_code = class_code; - edev->pcix_cap = pseries_eeh_find_cap(dn, PCI_CAP_ID_PCIX); - edev->pcie_cap = pseries_eeh_find_cap(dn, PCI_CAP_ID_EXP); - edev->aer_cap = pseries_eeh_find_ecap(dn, PCI_EXT_CAP_ID_ERR); + edev->class_code = pdn->class_code; + edev->pcix_cap = pseries_eeh_find_cap(pdn, PCI_CAP_ID_PCIX); + edev->pcie_cap = pseries_eeh_find_cap(pdn, PCI_CAP_ID_EXP); + edev->aer_cap = pseries_eeh_find_ecap(pdn, PCI_EXT_CAP_ID_ERR); edev->mode &= 0xFFFFFF00; if ((edev->class_code >> 8) == PCI_CLASS_BRIDGE_PCI) { edev->mode |= EEH_DEV_BRIDGE; @@ -252,24 +240,16 @@ static void *pseries_eeh_of_probe(struct device_node *dn, void *flag) } } - /* Retrieve the device address */ - regs = of_get_property(dn, "reg", NULL); - if (!regs) { - pr_warn("%s: OF node property %s::reg not found\n", - __func__, dn->full_name); - return NULL; - } - /* Initialize the fake PE */ memset(&pe, 0, sizeof(struct eeh_pe)); pe.phb = edev->phb; - pe.config_addr = of_read_number(regs, 1); + pe.config_addr = (pdn->busno << 16) | (pdn->devfn << 8); /* Enable EEH on the device */ ret = eeh_ops->set_option(&pe, EEH_OPT_ENABLE); if (!ret) { - edev->config_addr = of_read_number(regs, 1); /* Retrieve PE address */ + edev->config_addr = (pdn->busno << 16) | (pdn->devfn << 8); edev->pe_config_addr = eeh_ops->get_pe_addr(&pe); pe.addr = edev->pe_config_addr; @@ -285,16 +265,17 @@ static void *pseries_eeh_of_probe(struct device_node *dn, void *flag) eeh_add_flag(EEH_ENABLED); eeh_add_to_parent_pe(edev); - pr_debug("%s: EEH enabled on %s PHB#%d-PE#%x, config addr#%x\n", - __func__, dn->full_name, pe.phb->global_number, - pe.addr, pe.config_addr); - } else if (dn->parent && of_node_to_eeh_dev(dn->parent) && - (of_node_to_eeh_dev(dn->parent))->pe) { + pr_debug("%s: EEH enabled on %02x:%02x.%01x PHB#%d-PE#%x\n", + __func__, pdn->busno, PCI_SLOT(pdn->devfn), + PCI_FUNC(pdn->devfn), pe.phb->global_number, + pe.addr); + } else if (pdn->parent && pdn_to_eeh_dev(pdn->parent) && + (pdn_to_eeh_dev(pdn->parent))->pe) { /* This device doesn't support EEH, but it may have an * EEH parent, in which case we mark it as supported. */ - edev->config_addr = of_node_to_eeh_dev(dn->parent)->config_addr; - edev->pe_config_addr = of_node_to_eeh_dev(dn->parent)->pe_config_addr; + edev->config_addr = pdn_to_eeh_dev(pdn->parent)->config_addr; + edev->pe_config_addr = pdn_to_eeh_dev(pdn->parent)->pe_config_addr; eeh_add_to_parent_pe(edev); } } @@ -707,8 +688,7 @@ static int pseries_eeh_write_config(struct device_node *dn, int where, int size, static struct eeh_ops pseries_eeh_ops = { .name = "pseries", .init = pseries_eeh_init, - .of_probe = pseries_eeh_of_probe, - .dev_probe = NULL, + .probe = pseries_eeh_probe, .set_option = pseries_eeh_set_option, .get_pe_addr = pseries_eeh_get_pe_addr, .get_state = pseries_eeh_get_state, diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index 89e23811199c..f735f4fee48c 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c @@ -82,7 +82,7 @@ struct pci_controller *init_phb_dynamic(struct device_node *dn) eeh_dev_phb_init_dynamic(phb); if (dn->child) - eeh_add_device_tree_early(dn); + eeh_add_device_tree_early(PCI_DN(dn)); pcibios_scan_phb(phb); pcibios_finish_adding_to_bus(phb->bus); diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index 7660232ef460..e12bafdc42e0 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c @@ -146,7 +146,7 @@ static void dlpar_pci_add_bus(struct device_node *dn) struct pci_controller *phb = pdn->phb; struct pci_dev *dev = NULL; - eeh_add_device_tree_early(dn); + eeh_add_device_tree_early(pdn); /* Add EADS device to PHB bus, adding new entry to bus->devices */ dev = of_create_pci_dev(dn, phb->bus, pdn->devfn); -- cgit v1.2.3 From 0bd785873c6a6c9bd50d2ae19862f69ee5759fb9 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Tue, 17 Mar 2015 16:15:07 +1100 Subject: powerpc/eeh: Replace device_node with pci_dn in eeh_ops There are 3 EEH operations whose arguments contain device_node: read_config(), write_config() and restore_config(). The patch replaces device_node with pci_dn. Signed-off-by: Gavin Shan Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/eeh.h | 6 +- arch/powerpc/kernel/eeh.c | 40 ++++++++------ arch/powerpc/kernel/eeh_pe.c | 82 ++++++++++++++-------------- arch/powerpc/platforms/powernv/eeh-powernv.c | 40 ++++++-------- arch/powerpc/platforms/pseries/eeh_pseries.c | 16 ++---- 5 files changed, 87 insertions(+), 97 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index 87797811808f..f847fb716653 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h @@ -217,10 +217,10 @@ struct eeh_ops { int (*configure_bridge)(struct eeh_pe *pe); int (*err_inject)(struct eeh_pe *pe, int type, int func, unsigned long addr, unsigned long mask); - int (*read_config)(struct device_node *dn, int where, int size, u32 *val); - int (*write_config)(struct device_node *dn, int where, int size, u32 val); + int (*read_config)(struct pci_dn *pdn, int where, int size, u32 *val); + int (*write_config)(struct pci_dn *pdn, int where, int size, u32 val); int (*next_error)(struct eeh_pe **pe); - int (*restore_config)(struct device_node *dn); + int (*restore_config)(struct pci_dn *pdn); }; extern int eeh_subsystem_flags; diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index 9504c2f0bb54..1fd2566c87f1 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c @@ -164,30 +164,34 @@ __setup("eeh=", eeh_setup); */ static size_t eeh_dump_dev_log(struct eeh_dev *edev, char *buf, size_t len) { - struct device_node *dn = eeh_dev_to_of_node(edev); + struct pci_dn *pdn = eeh_dev_to_pdn(edev); u32 cfg; int cap, i; int n = 0, l = 0; char buffer[128]; - n += scnprintf(buf+n, len-n, "%s\n", dn->full_name); - pr_warn("EEH: of node=%s\n", dn->full_name); + n += scnprintf(buf+n, len-n, "%04x:%02x:%02x:%01x\n", + edev->phb->global_number, pdn->busno, + PCI_SLOT(pdn->devfn), PCI_FUNC(pdn->devfn)); + pr_warn("EEH: of node=%04x:%02x:%02x:%01x\n", + edev->phb->global_number, pdn->busno, + PCI_SLOT(pdn->devfn), PCI_FUNC(pdn->devfn)); - eeh_ops->read_config(dn, PCI_VENDOR_ID, 4, &cfg); + eeh_ops->read_config(pdn, PCI_VENDOR_ID, 4, &cfg); n += scnprintf(buf+n, len-n, "dev/vend:%08x\n", cfg); pr_warn("EEH: PCI device/vendor: %08x\n", cfg); - eeh_ops->read_config(dn, PCI_COMMAND, 4, &cfg); + eeh_ops->read_config(pdn, PCI_COMMAND, 4, &cfg); n += scnprintf(buf+n, len-n, "cmd/stat:%x\n", cfg); pr_warn("EEH: PCI cmd/status register: %08x\n", cfg); /* Gather bridge-specific registers */ if (edev->mode & EEH_DEV_BRIDGE) { - eeh_ops->read_config(dn, PCI_SEC_STATUS, 2, &cfg); + eeh_ops->read_config(pdn, PCI_SEC_STATUS, 2, &cfg); n += scnprintf(buf+n, len-n, "sec stat:%x\n", cfg); pr_warn("EEH: Bridge secondary status: %04x\n", cfg); - eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &cfg); + eeh_ops->read_config(pdn, PCI_BRIDGE_CONTROL, 2, &cfg); n += scnprintf(buf+n, len-n, "brdg ctl:%x\n", cfg); pr_warn("EEH: Bridge control: %04x\n", cfg); } @@ -195,11 +199,11 @@ static size_t eeh_dump_dev_log(struct eeh_dev *edev, char *buf, size_t len) /* Dump out the PCI-X command and status regs */ cap = edev->pcix_cap; if (cap) { - eeh_ops->read_config(dn, cap, 4, &cfg); + eeh_ops->read_config(pdn, cap, 4, &cfg); n += scnprintf(buf+n, len-n, "pcix-cmd:%x\n", cfg); pr_warn("EEH: PCI-X cmd: %08x\n", cfg); - eeh_ops->read_config(dn, cap+4, 4, &cfg); + eeh_ops->read_config(pdn, cap+4, 4, &cfg); n += scnprintf(buf+n, len-n, "pcix-stat:%x\n", cfg); pr_warn("EEH: PCI-X status: %08x\n", cfg); } @@ -211,7 +215,7 @@ static size_t eeh_dump_dev_log(struct eeh_dev *edev, char *buf, size_t len) pr_warn("EEH: PCI-E capabilities and status follow:\n"); for (i=0; i<=8; i++) { - eeh_ops->read_config(dn, cap+4*i, 4, &cfg); + eeh_ops->read_config(pdn, cap+4*i, 4, &cfg); n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); if ((i % 4) == 0) { @@ -238,7 +242,7 @@ static size_t eeh_dump_dev_log(struct eeh_dev *edev, char *buf, size_t len) pr_warn("EEH: PCI-E AER capability register set follows:\n"); for (i=0; i<=13; i++) { - eeh_ops->read_config(dn, cap+4*i, 4, &cfg); + eeh_ops->read_config(pdn, cap+4*i, 4, &cfg); n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); if ((i % 4) == 0) { @@ -698,7 +702,7 @@ static void *eeh_disable_and_save_dev_state(void *data, void *userdata) static void *eeh_restore_dev_state(void *data, void *userdata) { struct eeh_dev *edev = data; - struct device_node *dn = eeh_dev_to_of_node(edev); + struct pci_dn *pdn = eeh_dev_to_pdn(edev); struct pci_dev *pdev = eeh_dev_to_pci_dev(edev); struct pci_dev *dev = userdata; @@ -706,8 +710,8 @@ static void *eeh_restore_dev_state(void *data, void *userdata) return NULL; /* Apply customization from firmware */ - if (dn && eeh_ops->restore_config) - eeh_ops->restore_config(dn); + if (pdn && eeh_ops->restore_config) + eeh_ops->restore_config(pdn); /* The caller should restore state for the specified device */ if (pdev != dev) @@ -870,15 +874,15 @@ out: */ void eeh_save_bars(struct eeh_dev *edev) { + struct pci_dn *pdn; int i; - struct device_node *dn; - if (!edev) + pdn = eeh_dev_to_pdn(edev); + if (!pdn) return; - dn = eeh_dev_to_of_node(edev); for (i = 0; i < 16; i++) - eeh_ops->read_config(dn, i * 4, 4, &edev->config_space[i]); + eeh_ops->read_config(pdn, i * 4, 4, &edev->config_space[i]); /* * For PCI bridges including root port, we need enable bus diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c index 1e4946c36f9e..209cd753bf46 100644 --- a/arch/powerpc/kernel/eeh_pe.c +++ b/arch/powerpc/kernel/eeh_pe.c @@ -291,27 +291,25 @@ struct eeh_pe *eeh_pe_get(struct eeh_dev *edev) */ static struct eeh_pe *eeh_pe_get_parent(struct eeh_dev *edev) { - struct device_node *dn; struct eeh_dev *parent; + struct pci_dn *pdn = eeh_dev_to_pdn(edev); /* * It might have the case for the indirect parent * EEH device already having associated PE, but * the direct parent EEH device doesn't have yet. */ - dn = edev->dn->parent; - while (dn) { + pdn = pdn ? pdn->parent : NULL; + while (pdn) { /* We're poking out of PCI territory */ - if (!PCI_DN(dn)) return NULL; - - parent = of_node_to_eeh_dev(dn); - /* We're poking out of PCI territory */ - if (!parent) return NULL; + parent = pdn_to_eeh_dev(pdn); + if (!parent) + return NULL; if (parent->pe) return parent->pe; - dn = dn->parent; + pdn = pdn->parent; } return NULL; @@ -653,9 +651,9 @@ void eeh_pe_state_clear(struct eeh_pe *pe, int state) * blocked on normal path during the stage. So we need utilize * eeh operations, which is always permitted. */ -static void eeh_bridge_check_link(struct eeh_dev *edev, - struct device_node *dn) +static void eeh_bridge_check_link(struct eeh_dev *edev) { + struct pci_dn *pdn = eeh_dev_to_pdn(edev); int cap; uint32_t val; int timeout = 0; @@ -675,32 +673,32 @@ static void eeh_bridge_check_link(struct eeh_dev *edev, /* Check slot status */ cap = edev->pcie_cap; - eeh_ops->read_config(dn, cap + PCI_EXP_SLTSTA, 2, &val); + eeh_ops->read_config(pdn, cap + PCI_EXP_SLTSTA, 2, &val); if (!(val & PCI_EXP_SLTSTA_PDS)) { pr_debug(" No card in the slot (0x%04x) !\n", val); return; } /* Check power status if we have the capability */ - eeh_ops->read_config(dn, cap + PCI_EXP_SLTCAP, 2, &val); + eeh_ops->read_config(pdn, cap + PCI_EXP_SLTCAP, 2, &val); if (val & PCI_EXP_SLTCAP_PCP) { - eeh_ops->read_config(dn, cap + PCI_EXP_SLTCTL, 2, &val); + eeh_ops->read_config(pdn, cap + PCI_EXP_SLTCTL, 2, &val); if (val & PCI_EXP_SLTCTL_PCC) { pr_debug(" In power-off state, power it on ...\n"); val &= ~(PCI_EXP_SLTCTL_PCC | PCI_EXP_SLTCTL_PIC); val |= (0x0100 & PCI_EXP_SLTCTL_PIC); - eeh_ops->write_config(dn, cap + PCI_EXP_SLTCTL, 2, val); + eeh_ops->write_config(pdn, cap + PCI_EXP_SLTCTL, 2, val); msleep(2 * 1000); } } /* Enable link */ - eeh_ops->read_config(dn, cap + PCI_EXP_LNKCTL, 2, &val); + eeh_ops->read_config(pdn, cap + PCI_EXP_LNKCTL, 2, &val); val &= ~PCI_EXP_LNKCTL_LD; - eeh_ops->write_config(dn, cap + PCI_EXP_LNKCTL, 2, val); + eeh_ops->write_config(pdn, cap + PCI_EXP_LNKCTL, 2, val); /* Check link */ - eeh_ops->read_config(dn, cap + PCI_EXP_LNKCAP, 4, &val); + eeh_ops->read_config(pdn, cap + PCI_EXP_LNKCAP, 4, &val); if (!(val & PCI_EXP_LNKCAP_DLLLARC)) { pr_debug(" No link reporting capability (0x%08x) \n", val); msleep(1000); @@ -713,7 +711,7 @@ static void eeh_bridge_check_link(struct eeh_dev *edev, msleep(20); timeout += 20; - eeh_ops->read_config(dn, cap + PCI_EXP_LNKSTA, 2, &val); + eeh_ops->read_config(pdn, cap + PCI_EXP_LNKSTA, 2, &val); if (val & PCI_EXP_LNKSTA_DLLLA) break; } @@ -728,9 +726,9 @@ static void eeh_bridge_check_link(struct eeh_dev *edev, #define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF)) #define SAVED_BYTE(OFF) (((u8 *)(edev->config_space))[BYTE_SWAP(OFF)]) -static void eeh_restore_bridge_bars(struct eeh_dev *edev, - struct device_node *dn) +static void eeh_restore_bridge_bars(struct eeh_dev *edev) { + struct pci_dn *pdn = eeh_dev_to_pdn(edev); int i; /* @@ -738,49 +736,49 @@ static void eeh_restore_bridge_bars(struct eeh_dev *edev, * Bus numbers and windows: 0x18 - 0x30 */ for (i = 4; i < 13; i++) - eeh_ops->write_config(dn, i*4, 4, edev->config_space[i]); + eeh_ops->write_config(pdn, i*4, 4, edev->config_space[i]); /* Rom: 0x38 */ - eeh_ops->write_config(dn, 14*4, 4, edev->config_space[14]); + eeh_ops->write_config(pdn, 14*4, 4, edev->config_space[14]); /* Cache line & Latency timer: 0xC 0xD */ - eeh_ops->write_config(dn, PCI_CACHE_LINE_SIZE, 1, + eeh_ops->write_config(pdn, PCI_CACHE_LINE_SIZE, 1, SAVED_BYTE(PCI_CACHE_LINE_SIZE)); - eeh_ops->write_config(dn, PCI_LATENCY_TIMER, 1, + eeh_ops->write_config(pdn, PCI_LATENCY_TIMER, 1, SAVED_BYTE(PCI_LATENCY_TIMER)); /* Max latency, min grant, interrupt ping and line: 0x3C */ - eeh_ops->write_config(dn, 15*4, 4, edev->config_space[15]); + eeh_ops->write_config(pdn, 15*4, 4, edev->config_space[15]); /* PCI Command: 0x4 */ - eeh_ops->write_config(dn, PCI_COMMAND, 4, edev->config_space[1]); + eeh_ops->write_config(pdn, PCI_COMMAND, 4, edev->config_space[1]); /* Check the PCIe link is ready */ - eeh_bridge_check_link(edev, dn); + eeh_bridge_check_link(edev); } -static void eeh_restore_device_bars(struct eeh_dev *edev, - struct device_node *dn) +static void eeh_restore_device_bars(struct eeh_dev *edev) { + struct pci_dn *pdn = eeh_dev_to_pdn(edev); int i; u32 cmd; for (i = 4; i < 10; i++) - eeh_ops->write_config(dn, i*4, 4, edev->config_space[i]); + eeh_ops->write_config(pdn, i*4, 4, edev->config_space[i]); /* 12 == Expansion ROM Address */ - eeh_ops->write_config(dn, 12*4, 4, edev->config_space[12]); + eeh_ops->write_config(pdn, 12*4, 4, edev->config_space[12]); - eeh_ops->write_config(dn, PCI_CACHE_LINE_SIZE, 1, + eeh_ops->write_config(pdn, PCI_CACHE_LINE_SIZE, 1, SAVED_BYTE(PCI_CACHE_LINE_SIZE)); - eeh_ops->write_config(dn, PCI_LATENCY_TIMER, 1, + eeh_ops->write_config(pdn, PCI_LATENCY_TIMER, 1, SAVED_BYTE(PCI_LATENCY_TIMER)); /* max latency, min grant, interrupt pin and line */ - eeh_ops->write_config(dn, 15*4, 4, edev->config_space[15]); + eeh_ops->write_config(pdn, 15*4, 4, edev->config_space[15]); /* * Restore PERR & SERR bits, some devices require it, * don't touch the other command bits */ - eeh_ops->read_config(dn, PCI_COMMAND, 4, &cmd); + eeh_ops->read_config(pdn, PCI_COMMAND, 4, &cmd); if (edev->config_space[1] & PCI_COMMAND_PARITY) cmd |= PCI_COMMAND_PARITY; else @@ -789,7 +787,7 @@ static void eeh_restore_device_bars(struct eeh_dev *edev, cmd |= PCI_COMMAND_SERR; else cmd &= ~PCI_COMMAND_SERR; - eeh_ops->write_config(dn, PCI_COMMAND, 4, cmd); + eeh_ops->write_config(pdn, PCI_COMMAND, 4, cmd); } /** @@ -804,16 +802,16 @@ static void eeh_restore_device_bars(struct eeh_dev *edev, static void *eeh_restore_one_device_bars(void *data, void *flag) { struct eeh_dev *edev = (struct eeh_dev *)data; - struct device_node *dn = eeh_dev_to_of_node(edev); + struct pci_dn *pdn = eeh_dev_to_pdn(edev); /* Do special restore for bridges */ if (edev->mode & EEH_DEV_BRIDGE) - eeh_restore_bridge_bars(edev, dn); + eeh_restore_bridge_bars(edev); else - eeh_restore_device_bars(edev, dn); + eeh_restore_device_bars(edev); - if (eeh_ops->restore_config) - eeh_ops->restore_config(dn); + if (eeh_ops->restore_config && pdn) + eeh_ops->restore_config(pdn); return NULL; } diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index dcc524fe2a30..ce738ab3d5a9 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c @@ -842,8 +842,8 @@ out: static int pnv_eeh_bridge_reset(struct pci_dev *dev, int option) { - struct device_node *dn = pci_device_to_OF_node(dev); - struct eeh_dev *edev = of_node_to_eeh_dev(dn); + struct pci_dn *pdn = pci_get_pdn_by_devfn(dev->bus, dev->devfn); + struct eeh_dev *edev = pdn_to_eeh_dev(pdn); int aer = edev ? edev->aer_cap : 0; u32 ctrl; @@ -856,32 +856,32 @@ static int pnv_eeh_bridge_reset(struct pci_dev *dev, int option) case EEH_RESET_HOT: /* Don't report linkDown event */ if (aer) { - eeh_ops->read_config(dn, aer + PCI_ERR_UNCOR_MASK, + eeh_ops->read_config(pdn, aer + PCI_ERR_UNCOR_MASK, 4, &ctrl); ctrl |= PCI_ERR_UNC_SURPDN; - eeh_ops->write_config(dn, aer + PCI_ERR_UNCOR_MASK, + eeh_ops->write_config(pdn, aer + PCI_ERR_UNCOR_MASK, 4, ctrl); } - eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &ctrl); + eeh_ops->read_config(pdn, PCI_BRIDGE_CONTROL, 2, &ctrl); ctrl |= PCI_BRIDGE_CTL_BUS_RESET; - eeh_ops->write_config(dn, PCI_BRIDGE_CONTROL, 2, ctrl); + eeh_ops->write_config(pdn, PCI_BRIDGE_CONTROL, 2, ctrl); msleep(EEH_PE_RST_HOLD_TIME); break; case EEH_RESET_DEACTIVATE: - eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &ctrl); + eeh_ops->read_config(pdn, PCI_BRIDGE_CONTROL, 2, &ctrl); ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET; - eeh_ops->write_config(dn, PCI_BRIDGE_CONTROL, 2, ctrl); + eeh_ops->write_config(pdn, PCI_BRIDGE_CONTROL, 2, ctrl); msleep(EEH_PE_RST_SETTLE_TIME); /* Continue reporting linkDown event */ if (aer) { - eeh_ops->read_config(dn, aer + PCI_ERR_UNCOR_MASK, + eeh_ops->read_config(pdn, aer + PCI_ERR_UNCOR_MASK, 4, &ctrl); ctrl &= ~PCI_ERR_UNC_SURPDN; - eeh_ops->write_config(dn, aer + PCI_ERR_UNCOR_MASK, + eeh_ops->write_config(pdn, aer + PCI_ERR_UNCOR_MASK, 4, ctrl); } @@ -1099,9 +1099,9 @@ static int pnv_eeh_err_inject(struct eeh_pe *pe, int type, int func, return 0; } -static inline bool pnv_eeh_cfg_blocked(struct device_node *dn) +static inline bool pnv_eeh_cfg_blocked(struct pci_dn *pdn) { - struct eeh_dev *edev = of_node_to_eeh_dev(dn); + struct eeh_dev *edev = pdn_to_eeh_dev(pdn); if (!edev || !edev->pe) return false; @@ -1112,15 +1112,13 @@ static inline bool pnv_eeh_cfg_blocked(struct device_node *dn) return false; } -static int pnv_eeh_read_config(struct device_node *dn, +static int pnv_eeh_read_config(struct pci_dn *pdn, int where, int size, u32 *val) { - struct pci_dn *pdn = PCI_DN(dn); - if (!pdn) return PCIBIOS_DEVICE_NOT_FOUND; - if (pnv_eeh_cfg_blocked(dn)) { + if (pnv_eeh_cfg_blocked(pdn)) { *val = 0xFFFFFFFF; return PCIBIOS_SET_FAILED; } @@ -1128,15 +1126,13 @@ static int pnv_eeh_read_config(struct device_node *dn, return pnv_pci_cfg_read(pdn, where, size, val); } -static int pnv_eeh_write_config(struct device_node *dn, +static int pnv_eeh_write_config(struct pci_dn *pdn, int where, int size, u32 val) { - struct pci_dn *pdn = PCI_DN(dn); - if (!pdn) return PCIBIOS_DEVICE_NOT_FOUND; - if (pnv_eeh_cfg_blocked(dn)) + if (pnv_eeh_cfg_blocked(pdn)) return PCIBIOS_SET_FAILED; return pnv_pci_cfg_write(pdn, where, size, val); @@ -1484,9 +1480,9 @@ static int pnv_eeh_next_error(struct eeh_pe **pe) return ret; } -static int pnv_eeh_restore_config(struct device_node *dn) +static int pnv_eeh_restore_config(struct pci_dn *pdn) { - struct eeh_dev *edev = of_node_to_eeh_dev(dn); + struct eeh_dev *edev = pdn_to_eeh_dev(pdn); struct pnv_phb *phb; s64 ret; diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c index a2946f72d5e7..2039397cc75d 100644 --- a/arch/powerpc/platforms/pseries/eeh_pseries.c +++ b/arch/powerpc/platforms/pseries/eeh_pseries.c @@ -651,37 +651,29 @@ static int pseries_eeh_configure_bridge(struct eeh_pe *pe) /** * pseries_eeh_read_config - Read PCI config space - * @dn: device node + * @pdn: PCI device node * @where: PCI address * @size: size to read * @val: return value * * Read config space from the speicifed device */ -static int pseries_eeh_read_config(struct device_node *dn, int where, int size, u32 *val) +static int pseries_eeh_read_config(struct pci_dn *pdn, int where, int size, u32 *val) { - struct pci_dn *pdn; - - pdn = PCI_DN(dn); - return rtas_read_config(pdn, where, size, val); } /** * pseries_eeh_write_config - Write PCI config space - * @dn: device node + * @pdn: PCI device node * @where: PCI address * @size: size to write * @val: value to be written * * Write config space to the specified device */ -static int pseries_eeh_write_config(struct device_node *dn, int where, int size, u32 val) +static int pseries_eeh_write_config(struct pci_dn *pdn, int where, int size, u32 val) { - struct pci_dn *pdn; - - pdn = PCI_DN(dn); - return rtas_write_config(pdn, where, size, val); } -- cgit v1.2.3 From c6406d8fbb014bebdfb5bf3c244548958aec7379 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Tue, 17 Mar 2015 16:15:08 +1100 Subject: powerpc/eeh: Remove device_node dependency The patch removes struct eeh_dev::dn and the corresponding helper functions: eeh_dev_to_of_node() and of_node_to_eeh_dev(). Instead, eeh_dev_to_pdn() and pdn_to_eeh_dev() should be used to get the pdn, which might contain device_node on PowerNV platform. Signed-off-by: Gavin Shan Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/eeh.h | 7 ------- arch/powerpc/include/asm/pci-bridge.h | 14 -------------- arch/powerpc/kernel/eeh.c | 24 +++++++++++++----------- arch/powerpc/kernel/eeh_cache.c | 25 +++++++++++-------------- arch/powerpc/kernel/eeh_driver.c | 22 ---------------------- arch/powerpc/kernel/eeh_pe.c | 34 +++++++++++++++++++++++++--------- arch/powerpc/kernel/pci_of_scan.c | 2 +- arch/powerpc/kernel/rtas_pci.c | 2 +- arch/powerpc/platforms/pseries/msi.c | 6 ++++-- 9 files changed, 55 insertions(+), 81 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index f847fb716653..a52db28ecc1e 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h @@ -29,7 +29,6 @@ struct pci_dev; struct pci_bus; -struct device_node; struct pci_dn; #ifdef CONFIG_EEH @@ -137,17 +136,11 @@ struct eeh_dev { struct eeh_pe *pe; /* Associated PE */ struct list_head list; /* Form link list in the PE */ struct pci_controller *phb; /* Associated PHB */ - struct device_node *dn; /* Associated device node */ struct pci_dn *pdn; /* Associated PCI device node */ struct pci_dev *pdev; /* Associated PCI device */ struct pci_bus *bus; /* PCI bus for partial hotplug */ }; -static inline struct device_node *eeh_dev_to_of_node(struct eeh_dev *edev) -{ - return edev ? edev->dn : NULL; -} - static inline struct pci_dn *eeh_dev_to_pdn(struct eeh_dev *edev) { return edev ? edev->pdn : NULL; diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 7b74499b728c..2c6dc2a3d14a 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -201,25 +201,11 @@ static inline int pci_device_from_OF_node(struct device_node *np, } #if defined(CONFIG_EEH) -static inline struct eeh_dev *of_node_to_eeh_dev(struct device_node *dn) -{ - /* - * For those OF nodes whose parent isn't PCI bridge, they - * don't have PCI_DN actually. So we have to skip them for - * any EEH operations. - */ - if (!dn || !PCI_DN(dn)) - return NULL; - - return PCI_DN(dn)->edev; -} - static inline struct eeh_dev *pdn_to_eeh_dev(struct pci_dn *pdn) { return pdn ? pdn->edev : NULL; } #else -#define of_node_to_eeh_dev(x) (NULL) #define pdn_to_eeh_dev(x) (NULL) #endif diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index 1fd2566c87f1..76253eb146be 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c @@ -418,11 +418,11 @@ int eeh_dev_check_failure(struct eeh_dev *edev) int ret; int active_flags = (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE); unsigned long flags; - struct device_node *dn; + struct pci_dn *pdn; struct pci_dev *dev; struct eeh_pe *pe, *parent_pe, *phb_pe; int rc = 0; - const char *location; + const char *location = NULL; eeh_stats.total_mmio_ffs++; @@ -433,15 +433,14 @@ int eeh_dev_check_failure(struct eeh_dev *edev) eeh_stats.no_dn++; return 0; } - dn = eeh_dev_to_of_node(edev); dev = eeh_dev_to_pci_dev(edev); pe = eeh_dev_to_pe(edev); /* Access to IO BARs might get this far and still not want checking. */ if (!pe) { eeh_stats.ignored_check++; - pr_debug("EEH: Ignored check for %s %s\n", - eeh_pci_name(dev), dn->full_name); + pr_debug("EEH: Ignored check for %s\n", + eeh_pci_name(dev)); return 0; } @@ -477,10 +476,13 @@ int eeh_dev_check_failure(struct eeh_dev *edev) if (pe->state & EEH_PE_ISOLATED) { pe->check_count++; if (pe->check_count % EEH_MAX_FAILS == 0) { - location = of_get_property(dn, "ibm,loc-code", NULL); + pdn = eeh_dev_to_pdn(edev); + if (pdn->node) + location = of_get_property(pdn->node, "ibm,loc-code", NULL); printk(KERN_ERR "EEH: %d reads ignored for recovering device at " "location=%s driver=%s pci addr=%s\n", - pe->check_count, location, + pe->check_count, + location ? location : "unknown", eeh_driver_name(dev), eeh_pci_name(dev)); printk(KERN_ERR "EEH: Might be infinite loop in %s driver\n", eeh_driver_name(dev)); @@ -1035,7 +1037,7 @@ int eeh_init(void) core_initcall_sync(eeh_init); /** - * eeh_add_device_early - Enable EEH for the indicated device_node + * eeh_add_device_early - Enable EEH for the indicated device node * @pdn: PCI device node for which to set up EEH * * This routine must be used to perform EEH initialization for PCI @@ -1093,7 +1095,7 @@ EXPORT_SYMBOL_GPL(eeh_add_device_tree_early); */ void eeh_add_device_late(struct pci_dev *dev) { - struct device_node *dn; + struct pci_dn *pdn; struct eeh_dev *edev; if (!dev || !eeh_enabled()) @@ -1101,8 +1103,8 @@ void eeh_add_device_late(struct pci_dev *dev) pr_debug("EEH: Adding device %s\n", pci_name(dev)); - dn = pci_device_to_OF_node(dev); - edev = of_node_to_eeh_dev(dn); + pdn = pci_get_pdn_by_devfn(dev->bus, dev->devfn); + edev = pdn_to_eeh_dev(pdn); if (edev->pdev == dev) { pr_debug("EEH: Already referenced !\n"); return; diff --git a/arch/powerpc/kernel/eeh_cache.c b/arch/powerpc/kernel/eeh_cache.c index 07d8a2423a61..eeabeabea49c 100644 --- a/arch/powerpc/kernel/eeh_cache.c +++ b/arch/powerpc/kernel/eeh_cache.c @@ -171,30 +171,27 @@ eeh_addr_cache_insert(struct pci_dev *dev, unsigned long alo, static void __eeh_addr_cache_insert_dev(struct pci_dev *dev) { - struct device_node *dn; + struct pci_dn *pdn; struct eeh_dev *edev; int i; - dn = pci_device_to_OF_node(dev); - if (!dn) { + pdn = pci_get_pdn_by_devfn(dev->bus, dev->devfn); + if (!pdn) { pr_warn("PCI: no pci dn found for dev=%s\n", pci_name(dev)); return; } - edev = of_node_to_eeh_dev(dn); + edev = pdn_to_eeh_dev(pdn); if (!edev) { - pr_warn("PCI: no EEH dev found for dn=%s\n", - dn->full_name); + pr_warn("PCI: no EEH dev found for %s\n", + pci_name(dev)); return; } /* Skip any devices for which EEH is not enabled. */ if (!edev->pe) { -#ifdef DEBUG - pr_info("PCI: skip building address cache for=%s - %s\n", - pci_name(dev), dn->full_name); -#endif + dev_dbg(&dev->dev, "EEH: Skip building address cache\n"); return; } @@ -282,18 +279,18 @@ void eeh_addr_cache_rmv_dev(struct pci_dev *dev) */ void eeh_addr_cache_build(void) { - struct device_node *dn; + struct pci_dn *pdn; struct eeh_dev *edev; struct pci_dev *dev = NULL; spin_lock_init(&pci_io_addr_cache_root.piar_lock); for_each_pci_dev(dev) { - dn = pci_device_to_OF_node(dev); - if (!dn) + pdn = pci_get_pdn_by_devfn(dev->bus, dev->devfn); + if (!pdn) continue; - edev = of_node_to_eeh_dev(dn); + edev = pdn_to_eeh_dev(pdn); if (!edev) continue; diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c index d099540c0f56..24768ff3cb73 100644 --- a/arch/powerpc/kernel/eeh_driver.c +++ b/arch/powerpc/kernel/eeh_driver.c @@ -83,28 +83,6 @@ static inline void eeh_pcid_put(struct pci_dev *pdev) module_put(pdev->driver->driver.owner); } -#if 0 -static void print_device_node_tree(struct pci_dn *pdn, int dent) -{ - int i; - struct device_node *pc; - - if (!pdn) - return; - for (i = 0; i < dent; i++) - printk(" "); - printk("dn=%s mode=%x \tcfg_addr=%x pe_addr=%x \tfull=%s\n", - pdn->node->name, pdn->eeh_mode, pdn->eeh_config_addr, - pdn->eeh_pe_config_addr, pdn->node->full_name); - dent += 3; - pc = pdn->node->child; - while (pc) { - print_device_node_tree(PCI_DN(pc), dent); - pc = pc->sibling; - } -} -#endif - /** * eeh_disable_irq - Disable interrupt for the recovering device * @dev: PCI device diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c index 209cd753bf46..f33ceccf6876 100644 --- a/arch/powerpc/kernel/eeh_pe.c +++ b/arch/powerpc/kernel/eeh_pe.c @@ -348,9 +348,12 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev) /* Put the edev to PE */ list_add_tail(&edev->list, &pe->edevs); - pr_debug("EEH: Add %s to Bus PE#%x\n", - edev->dn->full_name, pe->addr); - + pr_debug("EEH: Add %04x:%02x:%02x.%01x to Bus PE#%x\n", + edev->phb->global_number, + edev->config_addr >> 8, + PCI_SLOT(edev->config_addr & 0xFF), + PCI_FUNC(edev->config_addr & 0xFF), + pe->addr); return 0; } else if (pe && (pe->type & EEH_PE_INVALID)) { list_add_tail(&edev->list, &pe->edevs); @@ -366,9 +369,14 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev) parent->type &= ~(EEH_PE_INVALID | EEH_PE_KEEP); parent = parent->parent; } - pr_debug("EEH: Add %s to Device PE#%x, Parent PE#%x\n", - edev->dn->full_name, pe->addr, pe->parent->addr); + pr_debug("EEH: Add %04x:%02x:%02x.%01x to Device " + "PE#%x, Parent PE#%x\n", + edev->phb->global_number, + edev->config_addr >> 8, + PCI_SLOT(edev->config_addr & 0xFF), + PCI_FUNC(edev->config_addr & 0xFF), + pe->addr, pe->parent->addr); return 0; } @@ -407,8 +415,13 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev) list_add_tail(&pe->child, &parent->child_list); list_add_tail(&edev->list, &pe->edevs); edev->pe = pe; - pr_debug("EEH: Add %s to Device PE#%x, Parent PE#%x\n", - edev->dn->full_name, pe->addr, pe->parent->addr); + pr_debug("EEH: Add %04x:%02x:%02x.%01x to " + "Device PE#%x, Parent PE#%x\n", + edev->phb->global_number, + edev->config_addr >> 8, + PCI_SLOT(edev->config_addr & 0xFF), + PCI_FUNC(edev->config_addr & 0xFF), + pe->addr, pe->parent->addr); return 0; } @@ -428,8 +441,11 @@ int eeh_rmv_from_parent_pe(struct eeh_dev *edev) int cnt; if (!edev->pe) { - pr_debug("%s: No PE found for EEH device %s\n", - __func__, edev->dn->full_name); + pr_debug("%s: No PE found for device %04x:%02x:%02x.%01x\n", + __func__, edev->phb->global_number, + edev->config_addr >> 8, + PCI_SLOT(edev->config_addr & 0xFF), + PCI_FUNC(edev->config_addr & 0xFF)); return -EEXIST; } diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c index e6245e9c7d8d..7122dfece393 100644 --- a/arch/powerpc/kernel/pci_of_scan.c +++ b/arch/powerpc/kernel/pci_of_scan.c @@ -305,7 +305,7 @@ static struct pci_dev *of_scan_pci_dev(struct pci_bus *bus, const __be32 *reg; int reglen, devfn; #ifdef CONFIG_EEH - struct eeh_dev *edev = of_node_to_eeh_dev(dn); + struct eeh_dev *edev = pdn_to_eeh_dev(PCI_DN(dn)); #endif pr_debug(" * %s\n", dn->full_name); diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index ce230da2c015..af29df2517f7 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c @@ -113,7 +113,7 @@ static int rtas_pci_read_config(struct pci_bus *bus, ret = rtas_read_config(pdn, where, size, val); if (*val == EEH_IO_ERROR_VALUE(size) && - eeh_dev_check_failure(of_node_to_eeh_dev(dn))) + eeh_dev_check_failure(pdn_to_eeh_dev(pdn))) return PCIBIOS_DEVICE_NOT_FOUND; return ret; diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c index 691a154c286d..c8d24f9a6948 100644 --- a/arch/powerpc/platforms/pseries/msi.c +++ b/arch/powerpc/platforms/pseries/msi.c @@ -195,6 +195,7 @@ static struct device_node *find_pe_total_msi(struct pci_dev *dev, int *total) static struct device_node *find_pe_dn(struct pci_dev *dev, int *total) { struct device_node *dn; + struct pci_dn *pdn; struct eeh_dev *edev; /* Found our PE and assume 8 at that point. */ @@ -204,10 +205,11 @@ static struct device_node *find_pe_dn(struct pci_dev *dev, int *total) return NULL; /* Get the top level device in the PE */ - edev = of_node_to_eeh_dev(dn); + edev = pdn_to_eeh_dev(PCI_DN(dn)); if (edev->pe) edev = list_first_entry(&edev->pe->edevs, struct eeh_dev, list); - dn = eeh_dev_to_of_node(edev); + pdn = eeh_dev_to_pdn(edev); + dn = pdn ? pdn->node : NULL; if (!dn) return NULL; -- cgit v1.2.3 From d078eed35de3866cb4af654db87765f53edbacce Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 3 Feb 2015 16:36:24 +1100 Subject: powerpc: Cleanup KVM emulated load/store endian handling Sometimes the KVM code on powerpc needs to emulate load or store instructions from the guest, which can include both normal and byte reversed forms. We currently (AFAICT) handle this correctly, but some variable names are very misleading. In particular we use "is_bigendian" in several places to actually mean "is the IO the same endian as the host", but we now support little-endian powerpc hosts. This also ties into the misleadingly named ld_le*() and st_le*() functions, which in fact always byteswap, even on an LE host. This patch cleans this up by renaming to more accurate "host_swabbed", and uses the generic swab*() functions instead of the powerpc specific and misleadingly named ld_le*() and st_le*() functions. Signed-off-by: David Gibson Reviewed-by: Alexander Graf Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/kvm_host.h | 2 +- arch/powerpc/kvm/powerpc.c | 38 ++++++++++++++++++------------------- 2 files changed, 19 insertions(+), 21 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index 8ef05121d3cd..c610961720c7 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h @@ -585,7 +585,7 @@ struct kvm_vcpu_arch { pgd_t *pgdir; u8 io_gpr; /* GPR used as IO source/target */ - u8 mmio_is_bigendian; + u8 mmio_host_swabbed; u8 mmio_sign_extend; u8 osi_needed; u8 osi_enabled; diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 27c0face86f4..41c5f8f8a20d 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c @@ -720,7 +720,7 @@ static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu, return; } - if (vcpu->arch.mmio_is_bigendian) { + if (!vcpu->arch.mmio_host_swabbed) { switch (run->mmio.len) { case 8: gpr = *(u64 *)run->mmio.data; break; case 4: gpr = *(u32 *)run->mmio.data; break; @@ -728,10 +728,10 @@ static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu, case 1: gpr = *(u8 *)run->mmio.data; break; } } else { - /* Convert BE data from userland back to LE. */ switch (run->mmio.len) { - case 4: gpr = ld_le32((u32 *)run->mmio.data); break; - case 2: gpr = ld_le16((u16 *)run->mmio.data); break; + case 8: gpr = swab64(*(u64 *)run->mmio.data); break; + case 4: gpr = swab32(*(u32 *)run->mmio.data); break; + case 2: gpr = swab16(*(u16 *)run->mmio.data); break; case 1: gpr = *(u8 *)run->mmio.data; break; } } @@ -780,14 +780,13 @@ int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu, int is_default_endian) { int idx, ret; - int is_bigendian; + bool host_swabbed; + /* Pity C doesn't have a logical XOR operator */ if (kvmppc_need_byteswap(vcpu)) { - /* Default endianness is "little endian". */ - is_bigendian = !is_default_endian; + host_swabbed = is_default_endian; } else { - /* Default endianness is "big endian". */ - is_bigendian = is_default_endian; + host_swabbed = !is_default_endian; } if (bytes > sizeof(run->mmio.data)) { @@ -800,7 +799,7 @@ int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu, run->mmio.is_write = 0; vcpu->arch.io_gpr = rt; - vcpu->arch.mmio_is_bigendian = is_bigendian; + vcpu->arch.mmio_host_swabbed = host_swabbed; vcpu->mmio_needed = 1; vcpu->mmio_is_write = 0; vcpu->arch.mmio_sign_extend = 0; @@ -840,14 +839,13 @@ int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu, { void *data = run->mmio.data; int idx, ret; - int is_bigendian; + bool host_swabbed; + /* Pity C doesn't have a logical XOR operator */ if (kvmppc_need_byteswap(vcpu)) { - /* Default endianness is "little endian". */ - is_bigendian = !is_default_endian; + host_swabbed = is_default_endian; } else { - /* Default endianness is "big endian". */ - is_bigendian = is_default_endian; + host_swabbed = !is_default_endian; } if (bytes > sizeof(run->mmio.data)) { @@ -862,7 +860,7 @@ int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu, vcpu->mmio_is_write = 1; /* Store the value at the lowest bytes in 'data'. */ - if (is_bigendian) { + if (!host_swabbed) { switch (bytes) { case 8: *(u64 *)data = val; break; case 4: *(u32 *)data = val; break; @@ -870,11 +868,11 @@ int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu, case 1: *(u8 *)data = val; break; } } else { - /* Store LE value into 'data'. */ switch (bytes) { - case 4: st_le32(data, val); break; - case 2: st_le16(data, val); break; - case 1: *(u8 *)data = val; break; + case 8: *(u64 *)data = swab64(val); break; + case 4: *(u32 *)data = swab32(val); break; + case 2: *(u16 *)data = swab16(val); break; + case 1: *(u8 *)data = val; break; } } -- cgit v1.2.3 From 0eebf9b5d2da61f84cddd0ec2bb41be93f8fc82b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 3 Feb 2015 16:36:25 +1100 Subject: powerpc: Remove unused st_le*() and ld_le* functions The powerpc specific st_le*() and ld_le*() functions in arch/powerpc/asm/swab.h no longer have any users. They are also misleadingly named, since they always byteswap, even on a little-endian host. This patch removes them. Signed-off-by: David Gibson Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/swab.h | 26 -------------------------- 1 file changed, 26 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/swab.h b/arch/powerpc/include/asm/swab.h index 96f59de61855..487e09077a3e 100644 --- a/arch/powerpc/include/asm/swab.h +++ b/arch/powerpc/include/asm/swab.h @@ -9,30 +9,4 @@ #include -static __inline__ __u16 ld_le16(const volatile __u16 *addr) -{ - __u16 val; - - __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr)); - return val; -} - -static __inline__ void st_le16(volatile __u16 *addr, const __u16 val) -{ - __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr)); -} - -static __inline__ __u32 ld_le32(const volatile __u32 *addr) -{ - __u32 val; - - __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr)); - return val; -} - -static __inline__ void st_le32(volatile __u32 *addr, const __u32 val) -{ - __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr)); -} - #endif /* _ASM_POWERPC_SWAB_H */ -- cgit v1.2.3 From b921e90260cec1e04988bb3763491de885b67b51 Mon Sep 17 00:00:00 2001 From: Neelesh Gupta Date: Wed, 11 Feb 2015 11:57:23 +0530 Subject: powerpc/powernv: Add OPAL message notifier unregister function Provide an unregister interface for the opal message notifiers to be called when not needed like during driver unload/remove. Signed-off-by: Neelesh Gupta Reviewed-by: Vasant Hegde Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/opal.h | 2 ++ arch/powerpc/platforms/powernv/opal.c | 7 +++++++ 2 files changed, 9 insertions(+) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index 9ee0a30a02ce..4ea21ea6a999 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h @@ -948,6 +948,8 @@ extern int opal_notifier_unregister(struct notifier_block *nb); extern int opal_message_notifier_register(enum OpalMessageType msg_type, struct notifier_block *nb); +extern int opal_message_notifier_unregister(enum OpalMessageType msg_type, + struct notifier_block *nb); extern void opal_notifier_enable(void); extern void opal_notifier_disable(void); extern void opal_notifier_update_evt(uint64_t evt_mask, uint64_t evt_val); diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index b0021ac3e0a8..8b3834a095f7 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c @@ -318,6 +318,13 @@ int opal_message_notifier_register(enum OpalMessageType msg_type, &opal_msg_notifier_head[msg_type], nb); } +int opal_message_notifier_unregister(enum OpalMessageType msg_type, + struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister( + &opal_msg_notifier_head[msg_type], nb); +} + static void opal_message_do_notify(uint32_t msg_type, void *msg) { /* notify subscribers */ -- cgit v1.2.3 From c03e73740d24fbe990291cd9ac2d6ae0d95b975f Mon Sep 17 00:00:00 2001 From: Tyrel Datwyler Date: Fri, 27 Mar 2015 12:47:25 -0700 Subject: powerpc/pseries: Simplify check for suspendability during suspend/migration During suspend/migration operation we must wait for the VASI state reported by the hypervisor to become Suspending prior to making the ibm,suspend-me RTAS call. Calling routines to rtas_ibm_supend_me() pass a vasi_state variable that exposes the VASI state to the caller. This is unnecessary as the caller only really cares about the following three conditions; if there is an error we should bailout, success indicating we have suspended and woken back up so proceed to device tree update, or we are not suspendable yet so try calling rtas_ibm_suspend_me again shortly. This patch removes the extraneous vasi_state variable and simply uses the return code to communicate how to proceed. We either succeed, fail, or get -EAGAIN in which case we sleep for a second before trying to call rtas_ibm_suspend_me again. The behaviour of ppc_rtas() remains the same, but migrate_store() now returns the propogated error code on failure. Previously -1 was returned from migrate_store() in the failure case which equates to -EPERM and was clearly wrong. Signed-off-by: Tyrel Datwyler Cc: Nathan Fontenont Cc: Cyril Bur Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/rtas.h | 2 +- arch/powerpc/kernel/rtas.c | 26 +++++++++++++------------- arch/powerpc/platforms/pseries/mobility.c | 9 +++------ 3 files changed, 17 insertions(+), 20 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h index c3c99eb35448..398106f12617 100644 --- a/arch/powerpc/include/asm/rtas.h +++ b/arch/powerpc/include/asm/rtas.h @@ -328,7 +328,7 @@ extern int rtas_suspend_cpu(struct rtas_suspend_me_data *data); extern int rtas_suspend_last_cpu(struct rtas_suspend_me_data *data); extern int rtas_online_cpus_mask(cpumask_var_t cpus); extern int rtas_offline_cpus_mask(cpumask_var_t cpus); -extern int rtas_ibm_suspend_me(u64 handle, int *vasi_return); +extern int rtas_ibm_suspend_me(u64 handle); struct rtc_time; extern unsigned long rtas_get_boot_time(void); diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 21c45a2d0706..b9a7b8981ef7 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -897,7 +897,7 @@ int rtas_offline_cpus_mask(cpumask_var_t cpus) } EXPORT_SYMBOL(rtas_offline_cpus_mask); -int rtas_ibm_suspend_me(u64 handle, int *vasi_return) +int rtas_ibm_suspend_me(u64 handle) { long state; long rc; @@ -919,13 +919,11 @@ int rtas_ibm_suspend_me(u64 handle, int *vasi_return) printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned %ld\n",rc); return rc; } else if (state == H_VASI_ENABLED) { - *vasi_return = RTAS_NOT_SUSPENDABLE; - return 0; + return -EAGAIN; } else if (state != H_VASI_SUSPENDING) { printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned state %ld\n", state); - *vasi_return = -1; - return 0; + return -EIO; } if (!alloc_cpumask_var(&offline_mask, GFP_TEMPORARY)) @@ -972,7 +970,7 @@ out: return atomic_read(&data.error); } #else /* CONFIG_PPC_PSERIES */ -int rtas_ibm_suspend_me(u64 handle, int *vasi_return) +int rtas_ibm_suspend_me(u64 handle) { return -ENOSYS; } @@ -1022,7 +1020,6 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) unsigned long flags; char *buff_copy, *errbuf = NULL; int nargs, nret, token; - int rc; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -1054,15 +1051,18 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) if (token == ibm_suspend_me_token) { /* - * rtas_ibm_suspend_me assumes args are in cpu endian, or at least the - * hcall within it requires it. + * rtas_ibm_suspend_me assumes the streamid handle is in cpu + * endian, or at least the hcall within it requires it. */ - int vasi_rc = 0; + int rc = 0; u64 handle = ((u64)be32_to_cpu(args.args[0]) << 32) | be32_to_cpu(args.args[1]); - rc = rtas_ibm_suspend_me(handle, &vasi_rc); - args.rets[0] = cpu_to_be32(vasi_rc); - if (rc) + rc = rtas_ibm_suspend_me(handle); + if (rc == -EAGAIN) + args.rets[0] = cpu_to_be32(RTAS_NOT_SUSPENDABLE); + else if (rc == -EIO) + args.rets[0] = cpu_to_be32(-1); + else if (rc) return rc; goto copy_return; } diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c index 03a428e87b14..38db1b9f2ac3 100644 --- a/arch/powerpc/platforms/pseries/mobility.c +++ b/arch/powerpc/platforms/pseries/mobility.c @@ -318,22 +318,19 @@ static ssize_t migrate_store(struct class *class, struct class_attribute *attr, { u64 streamid; int rc; - int vasi_rc = 0; rc = kstrtou64(buf, 0, &streamid); if (rc) return rc; do { - rc = rtas_ibm_suspend_me(streamid, &vasi_rc); - if (!rc && vasi_rc == RTAS_NOT_SUSPENDABLE) + rc = rtas_ibm_suspend_me(streamid); + if (rc == -EAGAIN) ssleep(1); - } while (!rc && vasi_rc == RTAS_NOT_SUSPENDABLE); + } while (rc == -EAGAIN); if (rc) return rc; - if (vasi_rc) - return vasi_rc; post_mobility_fixup(); return count; -- cgit v1.2.3 From 529d235a0e190ded1d21ccc80a73e625ebcad09b Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Sat, 28 Mar 2015 21:35:16 +1100 Subject: powerpc: Add a proper syscall for switching endianness We currently have a "special" syscall for switching endianness. This is syscall number 0x1ebe, which is handled explicitly in the 64-bit syscall exception entry. That has a few problems, firstly the syscall number is outside of the usual range, which confuses various tools. For example strace doesn't recognise the syscall at all. Secondly it's handled explicitly as a special case in the syscall exception entry, which is complicated enough without it. As a first step toward removing the special syscall, we need to add a regular syscall that implements the same functionality. The logic is simple, it simply toggles the MSR_LE bit in the userspace MSR. This is the same as the special syscall, with the caveat that the special syscall clobbers fewer registers. This version clobbers r9-r12, XER, CTR, and CR0-1,5-7. Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/systbl.h | 1 + arch/powerpc/include/asm/unistd.h | 2 +- arch/powerpc/include/uapi/asm/unistd.h | 1 + arch/powerpc/kernel/entry_64.S | 5 +++++ arch/powerpc/kernel/syscalls.c | 17 +++++++++++++++++ arch/powerpc/kernel/systbl.S | 2 ++ arch/powerpc/kernel/systbl_chk.c | 2 ++ arch/powerpc/platforms/cell/spu_callbacks.c | 1 + 8 files changed, 30 insertions(+), 1 deletion(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h index 91062eef582f..f1863a138b4a 100644 --- a/arch/powerpc/include/asm/systbl.h +++ b/arch/powerpc/include/asm/systbl.h @@ -367,3 +367,4 @@ SYSCALL_SPU(getrandom) SYSCALL_SPU(memfd_create) SYSCALL_SPU(bpf) COMPAT_SYS(execveat) +PPC64ONLY(switch_endian) diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h index 36b79c31eedd..f4f8b667d75b 100644 --- a/arch/powerpc/include/asm/unistd.h +++ b/arch/powerpc/include/asm/unistd.h @@ -12,7 +12,7 @@ #include -#define __NR_syscalls 363 +#define __NR_syscalls 364 #define __NR__exit __NR_exit #define NR_syscalls __NR_syscalls diff --git a/arch/powerpc/include/uapi/asm/unistd.h b/arch/powerpc/include/uapi/asm/unistd.h index ef5b5b1f3123..e4aa173dae62 100644 --- a/arch/powerpc/include/uapi/asm/unistd.h +++ b/arch/powerpc/include/uapi/asm/unistd.h @@ -385,5 +385,6 @@ #define __NR_memfd_create 360 #define __NR_bpf 361 #define __NR_execveat 362 +#define __NR_switch_endian 363 #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */ diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index d180caf2d6de..afbc20019c2e 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -356,6 +356,11 @@ _GLOBAL(ppc64_swapcontext) bl sys_swapcontext b .Lsyscall_exit +_GLOBAL(ppc_switch_endian) + bl save_nvgprs + bl sys_switch_endian + b .Lsyscall_exit + _GLOBAL(ret_from_fork) bl schedule_tail REST_NVGPRS(r1) diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c index b2702e87db0d..5fa92706444b 100644 --- a/arch/powerpc/kernel/syscalls.c +++ b/arch/powerpc/kernel/syscalls.c @@ -121,3 +121,20 @@ long ppc_fadvise64_64(int fd, int advice, u32 offset_high, u32 offset_low, return sys_fadvise64(fd, (u64)offset_high << 32 | offset_low, (u64)len_high << 32 | len_low, advice); } + +long sys_switch_endian(void) +{ + struct thread_info *ti; + + current->thread.regs->msr ^= MSR_LE; + + /* + * Set TIF_RESTOREALL so that r3 isn't clobbered on return to + * userspace. That also has the effect of restoring the non-volatile + * GPRs, so we saved them on the way in here. + */ + ti = current_thread_info(); + ti->flags |= _TIF_RESTOREALL; + + return 0; +} diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S index 7ab5d434e2ee..4d6b1d3a747f 100644 --- a/arch/powerpc/kernel/systbl.S +++ b/arch/powerpc/kernel/systbl.S @@ -22,6 +22,7 @@ #define PPC_SYS(func) .llong DOTSYM(ppc_##func),DOTSYM(ppc_##func) #define OLDSYS(func) .llong DOTSYM(sys_ni_syscall),DOTSYM(sys_ni_syscall) #define SYS32ONLY(func) .llong DOTSYM(sys_ni_syscall),DOTSYM(compat_sys_##func) +#define PPC64ONLY(func) .llong DOTSYM(ppc_##func),DOTSYM(sys_ni_syscall) #define SYSX(f, f3264, f32) .llong DOTSYM(f),DOTSYM(f3264) #else #define SYSCALL(func) .long sys_##func @@ -29,6 +30,7 @@ #define PPC_SYS(func) .long ppc_##func #define OLDSYS(func) .long sys_##func #define SYS32ONLY(func) .long sys_##func +#define PPC64ONLY(func) .long sys_ni_syscall #define SYSX(f, f3264, f32) .long f32 #endif #define SYSCALL_SPU(func) SYSCALL(func) diff --git a/arch/powerpc/kernel/systbl_chk.c b/arch/powerpc/kernel/systbl_chk.c index 238aa63ced8f..2384129f5893 100644 --- a/arch/powerpc/kernel/systbl_chk.c +++ b/arch/powerpc/kernel/systbl_chk.c @@ -21,9 +21,11 @@ #ifdef CONFIG_PPC64 #define OLDSYS(func) -1 #define SYS32ONLY(func) -1 +#define PPC64ONLY(func) __NR_##func #else #define OLDSYS(func) __NR_old##func #define SYS32ONLY(func) __NR_##func +#define PPC64ONLY(func) -1 #endif #define SYSX(f, f3264, f32) -1 diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c index b0ec78e8ad68..a494028b2cdf 100644 --- a/arch/powerpc/platforms/cell/spu_callbacks.c +++ b/arch/powerpc/platforms/cell/spu_callbacks.c @@ -39,6 +39,7 @@ static void *spu_syscall_table[] = { #define PPC_SYS(func) sys_ni_syscall, #define OLDSYS(func) sys_ni_syscall, #define SYS32ONLY(func) sys_ni_syscall, +#define PPC64ONLY(func) sys_ni_syscall, #define SYSX(f, f3264, f32) sys_ni_syscall, #define SYSCALL_SPU(func) sys_##func, -- cgit v1.2.3 From a8b2f8288a3fdef8d93efef2b1ead7563004275e Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Wed, 25 Mar 2015 16:23:52 +0800 Subject: powerpc/pci: Create pci_dn for VFs pci_dn is the extension of PCI device node and is created from device node. Unfortunately, VFs are enabled dynamically by PF's driver and they don't have corresponding device nodes and pci_dn, which is required to access VFs' config spaces. The patch creates pci_dn for VFs in pcibios_sriov_enable() on their PF, and removes pci_dn for VFs in pcibios_sriov_disable() on their PF. When VF's pci_dn is created, it's put to the child list of the pci_dn of PF's upstream bridge. The pci_dn is linked to pci_dev during early fixup time to setup the fast path. [bhelgaas: add ifdef around add_one_dev_pci_info(), use dev_printk()] Signed-off-by: Gavin Shan Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/pci-bridge.h | 3 + arch/powerpc/kernel/pci_dn.c | 116 ++++++++++++++++++++++++++++++ arch/powerpc/platforms/powernv/pci-ioda.c | 16 +++++ 3 files changed, 135 insertions(+) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 2c6dc2a3d14a..ece30f589398 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -156,6 +156,7 @@ struct iommu_table; struct pci_dn { int flags; +#define PCI_DN_FLAG_IOV_VF 0x01 int busno; /* pci bus number */ int devfn; /* pci device and function number */ @@ -188,6 +189,8 @@ struct pci_dn { extern struct pci_dn *pci_get_pdn_by_devfn(struct pci_bus *bus, int devfn); extern struct pci_dn *pci_get_pdn(struct pci_dev *pdev); +extern struct pci_dn *add_dev_pci_data(struct pci_dev *pdev); +extern void remove_dev_pci_data(struct pci_dev *pdev); extern void *update_dn_pci_info(struct device_node *dn, void *data); static inline int pci_device_from_OF_node(struct device_node *np, diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c index 65b98367005c..e5f1d78ef7cf 100644 --- a/arch/powerpc/kernel/pci_dn.c +++ b/arch/powerpc/kernel/pci_dn.c @@ -136,6 +136,122 @@ struct pci_dn *pci_get_pdn(struct pci_dev *pdev) return NULL; } +#ifdef CONFIG_PCI_IOV +static struct pci_dn *add_one_dev_pci_data(struct pci_dn *parent, + struct pci_dev *pdev, + int busno, int devfn) +{ + struct pci_dn *pdn; + + /* Except PHB, we always have the parent */ + if (!parent) + return NULL; + + pdn = kzalloc(sizeof(*pdn), GFP_KERNEL); + if (!pdn) { + dev_warn(&pdev->dev, "%s: Out of memory!\n", __func__); + return NULL; + } + + pdn->phb = parent->phb; + pdn->parent = parent; + pdn->busno = busno; + pdn->devfn = devfn; +#ifdef CONFIG_PPC_POWERNV + pdn->pe_number = IODA_INVALID_PE; +#endif + INIT_LIST_HEAD(&pdn->child_list); + INIT_LIST_HEAD(&pdn->list); + list_add_tail(&pdn->list, &parent->child_list); + + /* + * If we already have PCI device instance, lets + * bind them. + */ + if (pdev) + pdev->dev.archdata.pci_data = pdn; + + return pdn; +} +#endif + +struct pci_dn *add_dev_pci_data(struct pci_dev *pdev) +{ +#ifdef CONFIG_PCI_IOV + struct pci_dn *parent, *pdn; + int i; + + /* Only support IOV for now */ + if (!pdev->is_physfn) + return pci_get_pdn(pdev); + + /* Check if VFs have been populated */ + pdn = pci_get_pdn(pdev); + if (!pdn || (pdn->flags & PCI_DN_FLAG_IOV_VF)) + return NULL; + + pdn->flags |= PCI_DN_FLAG_IOV_VF; + parent = pci_bus_to_pdn(pdev->bus); + if (!parent) + return NULL; + + for (i = 0; i < pci_sriov_get_totalvfs(pdev); i++) { + pdn = add_one_dev_pci_data(parent, NULL, + pci_iov_virtfn_bus(pdev, i), + pci_iov_virtfn_devfn(pdev, i)); + if (!pdn) { + dev_warn(&pdev->dev, "%s: Cannot create firmware data for VF#%d\n", + __func__, i); + return NULL; + } + } +#endif /* CONFIG_PCI_IOV */ + + return pci_get_pdn(pdev); +} + +void remove_dev_pci_data(struct pci_dev *pdev) +{ +#ifdef CONFIG_PCI_IOV + struct pci_dn *parent; + struct pci_dn *pdn, *tmp; + int i; + + /* Only support IOV PF for now */ + if (!pdev->is_physfn) + return; + + /* Check if VFs have been populated */ + pdn = pci_get_pdn(pdev); + if (!pdn || !(pdn->flags & PCI_DN_FLAG_IOV_VF)) + return; + + pdn->flags &= ~PCI_DN_FLAG_IOV_VF; + parent = pci_bus_to_pdn(pdev->bus); + if (!parent) + return; + + /* + * We might introduce flag to pci_dn in future + * so that we can release VF's firmware data in + * a batch mode. + */ + for (i = 0; i < pci_sriov_get_totalvfs(pdev); i++) { + list_for_each_entry_safe(pdn, tmp, + &parent->child_list, list) { + if (pdn->busno != pci_iov_virtfn_bus(pdev, i) || + pdn->devfn != pci_iov_virtfn_devfn(pdev, i)) + continue; + + if (!list_empty(&pdn->list)) + list_del(&pdn->list); + + kfree(pdn); + } + } +#endif /* CONFIG_PCI_IOV */ +} + /* * Traverse_func that inits the PCI fields of the device node. * NOTE: this *must* be done before read/write config to the device. diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 26fe09936935..7f58f199f2c1 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -974,6 +974,22 @@ static void pnv_pci_ioda_setup_PEs(void) } } +#ifdef CONFIG_PCI_IOV +int pcibios_sriov_disable(struct pci_dev *pdev) +{ + /* Release PCI data */ + remove_dev_pci_data(pdev); + return 0; +} + +int pcibios_sriov_enable(struct pci_dev *pdev, u16 num_vfs) +{ + /* Allocate PCI data */ + add_dev_pci_data(pdev); + return 0; +} +#endif /* CONFIG_PCI_IOV */ + static void pnv_pci_ioda_dma_dev_setup(struct pnv_phb *phb, struct pci_dev *pdev) { struct pci_dn *pdn = pci_get_pdn(pdev); -- cgit v1.2.3 From 9e8d4a19ab66ec9e132d405357b9108a4f26efd3 Mon Sep 17 00:00:00 2001 From: Wei Yang Date: Wed, 25 Mar 2015 16:23:54 +0800 Subject: powerpc/powernv: Allocate struct pnv_ioda_pe iommu_table dynamically Previously the iommu_table had the same lifetime as a struct pnv_ioda_pe and was embedded in it. The pnv_ioda_pe was assigned to a PE on the bootup stage. Since PEs are based on the hardware layout which is static in the system, they will never get released. This means the iommu_table in the pnv_ioda_pe will never get released either. This no longer works for VF PE. VF PEs are created and released dynamically when VFs are created and released. So we need to assign pnv_ioda_pe to VF PEs respectively when VFs are enabled and clean up those resources for VF PE when VFs are disabled. And iommu_table is one of the resources we need to handle dynamically. Current iommu_table is a static field in pnv_ioda_pe, which will face a problem when freeing it. During the disabling of a VF, pnv_pci_ioda2_release_dma_pe will call iommu_free_table to release the iommu_table for this PE. A static iommu_table will fail in iommu_free_table. According to these requirement, this patch allocates iommu_table dynamically. Signed-off-by: Wei Yang Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/iommu.h | 3 +++ arch/powerpc/platforms/powernv/pci-ioda.c | 26 ++++++++++++++------------ arch/powerpc/platforms/powernv/pci.h | 2 +- 3 files changed, 18 insertions(+), 13 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h index f1ea5972f6ec..e2abbe8a1f4d 100644 --- a/arch/powerpc/include/asm/iommu.h +++ b/arch/powerpc/include/asm/iommu.h @@ -78,6 +78,9 @@ struct iommu_table { struct iommu_group *it_group; #endif void (*set_bypass)(struct iommu_table *tbl, bool enable); +#ifdef CONFIG_PPC_POWERNV + void *data; +#endif }; /* Pure 2^n version of get_order */ diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 7f58f199f2c1..9447ee9b4aa3 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -916,6 +916,10 @@ static void pnv_ioda_setup_bus_PE(struct pci_bus *bus, int all) return; } + pe->tce32_table = kzalloc_node(sizeof(struct iommu_table), + GFP_KERNEL, hose->node); + pe->tce32_table->data = pe; + /* Associate it with all child devices */ pnv_ioda_setup_same_PE(bus, pe); @@ -1005,7 +1009,7 @@ static void pnv_pci_ioda_dma_dev_setup(struct pnv_phb *phb, struct pci_dev *pdev pe = &phb->ioda.pe_array[pdn->pe_number]; WARN_ON(get_dma_ops(&pdev->dev) != &dma_iommu_ops); - set_iommu_table_base_and_group(&pdev->dev, &pe->tce32_table); + set_iommu_table_base_and_group(&pdev->dev, pe->tce32_table); } static int pnv_pci_ioda_dma_set_mask(struct pnv_phb *phb, @@ -1032,7 +1036,7 @@ static int pnv_pci_ioda_dma_set_mask(struct pnv_phb *phb, } else { dev_info(&pdev->dev, "Using 32-bit DMA via iommu\n"); set_dma_ops(&pdev->dev, &dma_iommu_ops); - set_iommu_table_base(&pdev->dev, &pe->tce32_table); + set_iommu_table_base(&pdev->dev, pe->tce32_table); } *pdev->dev.dma_mask = dma_mask; return 0; @@ -1069,9 +1073,9 @@ static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe, list_for_each_entry(dev, &bus->devices, bus_list) { if (add_to_iommu_group) set_iommu_table_base_and_group(&dev->dev, - &pe->tce32_table); + pe->tce32_table); else - set_iommu_table_base(&dev->dev, &pe->tce32_table); + set_iommu_table_base(&dev->dev, pe->tce32_table); if (dev->subordinate) pnv_ioda_setup_bus_dma(pe, dev->subordinate, @@ -1161,8 +1165,7 @@ static void pnv_pci_ioda2_tce_invalidate(struct pnv_ioda_pe *pe, void pnv_pci_ioda_tce_invalidate(struct iommu_table *tbl, __be64 *startp, __be64 *endp, bool rm) { - struct pnv_ioda_pe *pe = container_of(tbl, struct pnv_ioda_pe, - tce32_table); + struct pnv_ioda_pe *pe = tbl->data; struct pnv_phb *phb = pe->phb; if (phb->type == PNV_PHB_IODA1) @@ -1228,7 +1231,7 @@ static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb, } /* Setup linux iommu table */ - tbl = &pe->tce32_table; + tbl = pe->tce32_table; pnv_pci_setup_iommu_table(tbl, addr, TCE32_TABLE_SIZE * segs, base << 28, IOMMU_PAGE_SHIFT_4K); @@ -1266,8 +1269,7 @@ static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb, static void pnv_pci_ioda2_set_bypass(struct iommu_table *tbl, bool enable) { - struct pnv_ioda_pe *pe = container_of(tbl, struct pnv_ioda_pe, - tce32_table); + struct pnv_ioda_pe *pe = tbl->data; uint16_t window_id = (pe->pe_number << 1 ) + 1; int64_t rc; @@ -1312,10 +1314,10 @@ static void pnv_pci_ioda2_setup_bypass_pe(struct pnv_phb *phb, pe->tce_bypass_base = 1ull << 59; /* Install set_bypass callback for VFIO */ - pe->tce32_table.set_bypass = pnv_pci_ioda2_set_bypass; + pe->tce32_table->set_bypass = pnv_pci_ioda2_set_bypass; /* Enable bypass by default */ - pnv_pci_ioda2_set_bypass(&pe->tce32_table, true); + pnv_pci_ioda2_set_bypass(pe->tce32_table, true); } static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb, @@ -1363,7 +1365,7 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb, } /* Setup linux iommu table */ - tbl = &pe->tce32_table; + tbl = pe->tce32_table; pnv_pci_setup_iommu_table(tbl, addr, tce_table_size, 0, IOMMU_PAGE_SHIFT_4K); diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index 1f0cb66133a1..84280474e18f 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h @@ -53,7 +53,7 @@ struct pnv_ioda_pe { /* "Base" iommu table, ie, 4K TCEs, 32-bit DMA */ int tce32_seg; int tce32_segcount; - struct iommu_table tce32_table; + struct iommu_table *tce32_table; phys_addr_t tce_inval_reg_phys; /* 64-bit TCE bypass region */ -- cgit v1.2.3 From 6e628c7d33d99406cef374972c89389edcc3570f Mon Sep 17 00:00:00 2001 From: Wei Yang Date: Wed, 25 Mar 2015 16:23:55 +0800 Subject: powerpc/powernv: Reserve additional space for IOV BAR according to the number of total_pe On PHB3, PF IOV BAR will be covered by M64 BAR to have better PE isolation. M64 BAR is a type of hardware resource in PHB3, which could map a range of MMIO to PE numbers on powernv platform. And this range is divided equally by the number of total_pe with each divided range mapping to a PE number. Also, the M64 BAR must map a MMIO range with power-of-two size. The total_pe number is usually different from total_VFs, which can lead to a conflict between MMIO space and the PE number. For example, if total_VFs is 128 and total_pe is 256, the second half of M64 BAR will be part of other PCI device, which may already belong to other PEs. This patch prevents the conflict by reserving additional space for the PF IOV BAR, which is total_pe number of VF's BAR size. [bhelgaas: make dev_printk() output more consistent, index resource[] conventionally] Signed-off-by: Wei Yang Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/machdep.h | 4 +++ arch/powerpc/include/asm/pci-bridge.h | 3 +++ arch/powerpc/kernel/pci-common.c | 6 +++++ arch/powerpc/platforms/powernv/pci-ioda.c | 43 +++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index 098d51e924ea..b303833fa3fb 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h @@ -250,6 +250,10 @@ struct machdep_calls { /* Reset the secondary bus of bridge */ void (*pcibios_reset_secondary_bus)(struct pci_dev *dev); +#ifdef CONFIG_PCI_IOV + void (*pcibios_fixup_sriov)(struct pci_dev *pdev); +#endif /* CONFIG_PCI_IOV */ + /* Called to shutdown machine specific hardware not already controlled * by other drivers. */ diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index ece30f589398..7b8ebc5929ff 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -178,6 +178,9 @@ struct pci_dn { #define IODA_INVALID_PE (-1) #ifdef CONFIG_PPC_POWERNV int pe_number; +#ifdef CONFIG_PCI_IOV + u16 vfs_expanded; /* number of VFs IOV BAR expanded */ +#endif /* CONFIG_PCI_IOV */ #endif struct list_head child_list; struct list_head list; diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 82031011522f..375bf7099912 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -990,6 +990,12 @@ int pcibios_add_device(struct pci_dev *dev) */ if (dev->bus->is_added) pcibios_setup_device(dev); + +#ifdef CONFIG_PCI_IOV + if (ppc_md.pcibios_fixup_sriov) + ppc_md.pcibios_fixup_sriov(dev); +#endif /* CONFIG_PCI_IOV */ + return 0; } diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 9447ee9b4aa3..1da45aa76a03 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -1749,6 +1749,46 @@ static void pnv_pci_init_ioda_msis(struct pnv_phb *phb) static void pnv_pci_init_ioda_msis(struct pnv_phb *phb) { } #endif /* CONFIG_PCI_MSI */ +#ifdef CONFIG_PCI_IOV +static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev) +{ + struct pci_controller *hose; + struct pnv_phb *phb; + struct resource *res; + int i; + resource_size_t size; + struct pci_dn *pdn; + + if (!pdev->is_physfn || pdev->is_added) + return; + + hose = pci_bus_to_host(pdev->bus); + phb = hose->private_data; + + pdn = pci_get_pdn(pdev); + pdn->vfs_expanded = 0; + + for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { + res = &pdev->resource[i + PCI_IOV_RESOURCES]; + if (!res->flags || res->parent) + continue; + if (!pnv_pci_is_mem_pref_64(res->flags)) { + dev_warn(&pdev->dev, "Skipping expanding VF BAR%d: %pR\n", + i, res); + continue; + } + + dev_dbg(&pdev->dev, " Fixing VF BAR%d: %pR to\n", i, res); + size = pci_iov_resource_size(pdev, i + PCI_IOV_RESOURCES); + res->end = res->start + size * phb->ioda.total_pe - 1; + dev_dbg(&pdev->dev, " %pR\n", res); + dev_info(&pdev->dev, "VF BAR%d: %pR (expanded to %d VFs for PE alignment)", + i, res, phb->ioda.total_pe); + } + pdn->vfs_expanded = phb->ioda.total_pe; +} +#endif /* CONFIG_PCI_IOV */ + /* * This function is supposed to be called on basis of PE from top * to bottom style. So the the I/O or MMIO segment assigned to @@ -2122,6 +2162,9 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, ppc_md.pcibios_enable_device_hook = pnv_pci_enable_device_hook; ppc_md.pcibios_window_alignment = pnv_pci_window_alignment; ppc_md.pcibios_reset_secondary_bus = pnv_pci_reset_secondary_bus; +#ifdef CONFIG_PCI_IOV + ppc_md.pcibios_fixup_sriov = pnv_pci_ioda_fixup_iov_resources; +#endif /* CONFIG_PCI_IOV */ pci_add_flags(PCI_REASSIGN_ALL_RSRC); /* Reset IODA tables to a clean state */ -- cgit v1.2.3 From 5350ab3fd794f899079d9f6b2b6fe1a7917087ef Mon Sep 17 00:00:00 2001 From: Wei Yang Date: Wed, 25 Mar 2015 16:23:56 +0800 Subject: powerpc/powernv: Implement pcibios_iov_resource_alignment() on powernv Implement pcibios_iov_resource_alignment() on powernv platform. On PowerNV platform, there are 3 cases for the IOV BAR: 1. initial state, the IOV BAR size is multiple times of VF BAR size 2. after expanded, the IOV BAR size is expanded to meet the M64 segment size 3. sizing stage, the IOV BAR is truncated to 0 pnv_pci_iov_resource_alignment() handle these three cases respectively. [bhelgaas: adjust to drop "align" parameter, return pci_iov_resource_size() if no ppc_md machdep_call version] Signed-off-by: Wei Yang Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/machdep.h | 1 + arch/powerpc/kernel/pci-common.c | 10 ++++++++++ arch/powerpc/platforms/powernv/pci-ioda.c | 20 ++++++++++++++++++++ 3 files changed, 31 insertions(+) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index b303833fa3fb..1b268044f290 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h @@ -252,6 +252,7 @@ struct machdep_calls { #ifdef CONFIG_PCI_IOV void (*pcibios_fixup_sriov)(struct pci_dev *pdev); + resource_size_t (*pcibios_iov_resource_alignment)(struct pci_dev *, int resno); #endif /* CONFIG_PCI_IOV */ /* Called to shutdown machine specific hardware not already controlled diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 375bf7099912..9a306ff304ae 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -130,6 +130,16 @@ void pcibios_reset_secondary_bus(struct pci_dev *dev) pci_reset_secondary_bus(dev); } +#ifdef CONFIG_PCI_IOV +resource_size_t pcibios_iov_resource_alignment(struct pci_dev *pdev, int resno) +{ + if (ppc_md.pcibios_iov_resource_alignment) + return ppc_md.pcibios_iov_resource_alignment(pdev, resno); + + return pci_iov_resource_size(pdev, resno); +} +#endif /* CONFIG_PCI_IOV */ + static resource_size_t pcibios_io_size(const struct pci_controller *hose) { #ifdef CONFIG_PPC64 diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 1da45aa76a03..217eaad23cde 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -1965,6 +1965,25 @@ static resource_size_t pnv_pci_window_alignment(struct pci_bus *bus, return phb->ioda.io_segsize; } +#ifdef CONFIG_PCI_IOV +static resource_size_t pnv_pci_iov_resource_alignment(struct pci_dev *pdev, + int resno) +{ + struct pci_dn *pdn = pci_get_pdn(pdev); + resource_size_t align, iov_align; + + iov_align = resource_size(&pdev->resource[resno]); + if (iov_align) + return iov_align; + + align = pci_iov_resource_size(pdev, resno); + if (pdn->vfs_expanded) + return pdn->vfs_expanded * align; + + return align; +} +#endif /* CONFIG_PCI_IOV */ + /* Prevent enabling devices for which we couldn't properly * assign a PE */ @@ -2164,6 +2183,7 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, ppc_md.pcibios_reset_secondary_bus = pnv_pci_reset_secondary_bus; #ifdef CONFIG_PCI_IOV ppc_md.pcibios_fixup_sriov = pnv_pci_ioda_fixup_iov_resources; + ppc_md.pcibios_iov_resource_alignment = pnv_pci_iov_resource_alignment; #endif /* CONFIG_PCI_IOV */ pci_add_flags(PCI_REASSIGN_ALL_RSRC); -- cgit v1.2.3 From 781a868f3136c6eb8e8c5c19d148416d7da86610 Mon Sep 17 00:00:00 2001 From: Wei Yang Date: Wed, 25 Mar 2015 16:23:57 +0800 Subject: powerpc/powernv: Shift VF resource with an offset On PowerNV platform, resource position in M64 BAR implies the PE# the resource belongs to. In some cases, adjustment of a resource is necessary to locate it to a correct position in M64 BAR . This patch adds pnv_pci_vf_resource_shift() to shift the 'real' PF IOV BAR address according to an offset. Note: After doing so, there would be a "hole" in the /proc/iomem when offset is a positive value. It looks like the device return some mmio back to the system, which actually no one could use it. [bhelgaas: rework loops, rework overlap check, index resource[] conventionally, remove pci_regs.h include, squashed with next patch] Signed-off-by: Wei Yang Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/pci-bridge.h | 4 + arch/powerpc/kernel/pci_dn.c | 13 + arch/powerpc/platforms/powernv/pci-ioda.c | 528 +++++++++++++++++++++++++++++- arch/powerpc/platforms/powernv/pci.c | 18 + arch/powerpc/platforms/powernv/pci.h | 7 + 5 files changed, 553 insertions(+), 17 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 7b8ebc5929ff..8716db48e946 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -180,6 +180,10 @@ struct pci_dn { int pe_number; #ifdef CONFIG_PCI_IOV u16 vfs_expanded; /* number of VFs IOV BAR expanded */ + u16 num_vfs; /* number of VFs enabled*/ + int offset; /* PE# for the first VF PE */ +#define IODA_INVALID_M64 (-1) + int m64_wins[PCI_SRIOV_NUM_BARS]; #endif /* CONFIG_PCI_IOV */ #endif struct list_head child_list; diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c index e5f1d78ef7cf..b3b4df91b792 100644 --- a/arch/powerpc/kernel/pci_dn.c +++ b/arch/powerpc/kernel/pci_dn.c @@ -217,6 +217,19 @@ void remove_dev_pci_data(struct pci_dev *pdev) struct pci_dn *pdn, *tmp; int i; + /* + * VF and VF PE are created/released dynamically, so we need to + * bind/unbind them. Otherwise the VF and VF PE would be mismatched + * when re-enabling SR-IOV. + */ + if (pdev->is_virtfn) { + pdn = pci_get_pdn(pdev); +#ifdef CONFIG_PPC_POWERNV + pdn->pe_number = IODA_INVALID_PE; +#endif + return; + } + /* Only support IOV PF for now */ if (!pdev->is_physfn) return; diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 217eaad23cde..5187d164cfe1 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -44,6 +44,9 @@ #include "powernv.h" #include "pci.h" +/* 256M DMA window, 4K TCE pages, 8 bytes TCE */ +#define TCE32_TABLE_SIZE ((0x10000000 / 0x1000) * 8) + static void pe_level_printk(const struct pnv_ioda_pe *pe, const char *level, const char *fmt, ...) { @@ -56,11 +59,18 @@ static void pe_level_printk(const struct pnv_ioda_pe *pe, const char *level, vaf.fmt = fmt; vaf.va = &args; - if (pe->pdev) + if (pe->flags & PNV_IODA_PE_DEV) strlcpy(pfix, dev_name(&pe->pdev->dev), sizeof(pfix)); - else + else if (pe->flags & (PNV_IODA_PE_BUS | PNV_IODA_PE_BUS_ALL)) sprintf(pfix, "%04x:%02x ", pci_domain_nr(pe->pbus), pe->pbus->number); +#ifdef CONFIG_PCI_IOV + else if (pe->flags & PNV_IODA_PE_VF) + sprintf(pfix, "%04x:%02x:%2x.%d", + pci_domain_nr(pe->parent_dev->bus), + (pe->rid & 0xff00) >> 8, + PCI_SLOT(pe->rid), PCI_FUNC(pe->rid)); +#endif /* CONFIG_PCI_IOV*/ printk("%spci %s: [PE# %.3d] %pV", level, pfix, pe->pe_number, &vaf); @@ -591,7 +601,7 @@ static int pnv_ioda_set_peltv(struct pnv_phb *phb, bool is_add) { struct pnv_ioda_pe *slave; - struct pci_dev *pdev; + struct pci_dev *pdev = NULL; int ret; /* @@ -630,8 +640,12 @@ static int pnv_ioda_set_peltv(struct pnv_phb *phb, if (pe->flags & (PNV_IODA_PE_BUS_ALL | PNV_IODA_PE_BUS)) pdev = pe->pbus->self; - else + else if (pe->flags & PNV_IODA_PE_DEV) pdev = pe->pdev->bus->self; +#ifdef CONFIG_PCI_IOV + else if (pe->flags & PNV_IODA_PE_VF) + pdev = pe->parent_dev->bus->self; +#endif /* CONFIG_PCI_IOV */ while (pdev) { struct pci_dn *pdn = pci_get_pdn(pdev); struct pnv_ioda_pe *parent; @@ -649,6 +663,87 @@ static int pnv_ioda_set_peltv(struct pnv_phb *phb, return 0; } +#ifdef CONFIG_PCI_IOV +static int pnv_ioda_deconfigure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe) +{ + struct pci_dev *parent; + uint8_t bcomp, dcomp, fcomp; + int64_t rc; + long rid_end, rid; + + /* Currently, we just deconfigure VF PE. Bus PE will always there.*/ + if (pe->pbus) { + int count; + + dcomp = OPAL_IGNORE_RID_DEVICE_NUMBER; + fcomp = OPAL_IGNORE_RID_FUNCTION_NUMBER; + parent = pe->pbus->self; + if (pe->flags & PNV_IODA_PE_BUS_ALL) + count = pe->pbus->busn_res.end - pe->pbus->busn_res.start + 1; + else + count = 1; + + switch(count) { + case 1: bcomp = OpalPciBusAll; break; + case 2: bcomp = OpalPciBus7Bits; break; + case 4: bcomp = OpalPciBus6Bits; break; + case 8: bcomp = OpalPciBus5Bits; break; + case 16: bcomp = OpalPciBus4Bits; break; + case 32: bcomp = OpalPciBus3Bits; break; + default: + dev_err(&pe->pbus->dev, "Number of subordinate buses %d unsupported\n", + count); + /* Do an exact match only */ + bcomp = OpalPciBusAll; + } + rid_end = pe->rid + (count << 8); + } else { + if (pe->flags & PNV_IODA_PE_VF) + parent = pe->parent_dev; + else + parent = pe->pdev->bus->self; + bcomp = OpalPciBusAll; + dcomp = OPAL_COMPARE_RID_DEVICE_NUMBER; + fcomp = OPAL_COMPARE_RID_FUNCTION_NUMBER; + rid_end = pe->rid + 1; + } + + /* Clear the reverse map */ + for (rid = pe->rid; rid < rid_end; rid++) + phb->ioda.pe_rmap[rid] = 0; + + /* Release from all parents PELT-V */ + while (parent) { + struct pci_dn *pdn = pci_get_pdn(parent); + if (pdn && pdn->pe_number != IODA_INVALID_PE) { + rc = opal_pci_set_peltv(phb->opal_id, pdn->pe_number, + pe->pe_number, OPAL_REMOVE_PE_FROM_DOMAIN); + /* XXX What to do in case of error ? */ + } + parent = parent->bus->self; + } + + opal_pci_eeh_freeze_set(phb->opal_id, pe->pe_number, + OPAL_EEH_ACTION_CLEAR_FREEZE_ALL); + + /* Disassociate PE in PELT */ + rc = opal_pci_set_peltv(phb->opal_id, pe->pe_number, + pe->pe_number, OPAL_REMOVE_PE_FROM_DOMAIN); + if (rc) + pe_warn(pe, "OPAL error %ld remove self from PELTV\n", rc); + rc = opal_pci_set_pe(phb->opal_id, pe->pe_number, pe->rid, + bcomp, dcomp, fcomp, OPAL_UNMAP_PE); + if (rc) + pe_err(pe, "OPAL error %ld trying to setup PELT table\n", rc); + + pe->pbus = NULL; + pe->pdev = NULL; + pe->parent_dev = NULL; + + return 0; +} +#endif /* CONFIG_PCI_IOV */ + static int pnv_ioda_configure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe) { struct pci_dev *parent; @@ -675,15 +770,19 @@ static int pnv_ioda_configure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe) case 16: bcomp = OpalPciBus4Bits; break; case 32: bcomp = OpalPciBus3Bits; break; default: - pr_err("%s: Number of subordinate busses %d" - " unsupported\n", - pci_name(pe->pbus->self), count); + dev_err(&pe->pbus->dev, "Number of subordinate buses %d unsupported\n", + count); /* Do an exact match only */ bcomp = OpalPciBusAll; } rid_end = pe->rid + (count << 8); } else { - parent = pe->pdev->bus->self; +#ifdef CONFIG_PCI_IOV + if (pe->flags & PNV_IODA_PE_VF) + parent = pe->parent_dev; + else +#endif /* CONFIG_PCI_IOV */ + parent = pe->pdev->bus->self; bcomp = OpalPciBusAll; dcomp = OPAL_COMPARE_RID_DEVICE_NUMBER; fcomp = OPAL_COMPARE_RID_FUNCTION_NUMBER; @@ -774,6 +873,78 @@ static unsigned int pnv_ioda_dma_weight(struct pci_dev *dev) return 10; } +#ifdef CONFIG_PCI_IOV +static int pnv_pci_vf_resource_shift(struct pci_dev *dev, int offset) +{ + struct pci_dn *pdn = pci_get_pdn(dev); + int i; + struct resource *res, res2; + resource_size_t size; + u16 num_vfs; + + if (!dev->is_physfn) + return -EINVAL; + + /* + * "offset" is in VFs. The M64 windows are sized so that when they + * are segmented, each segment is the same size as the IOV BAR. + * Each segment is in a separate PE, and the high order bits of the + * address are the PE number. Therefore, each VF's BAR is in a + * separate PE, and changing the IOV BAR start address changes the + * range of PEs the VFs are in. + */ + num_vfs = pdn->num_vfs; + for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { + res = &dev->resource[i + PCI_IOV_RESOURCES]; + if (!res->flags || !res->parent) + continue; + + if (!pnv_pci_is_mem_pref_64(res->flags)) + continue; + + /* + * The actual IOV BAR range is determined by the start address + * and the actual size for num_vfs VFs BAR. This check is to + * make sure that after shifting, the range will not overlap + * with another device. + */ + size = pci_iov_resource_size(dev, i + PCI_IOV_RESOURCES); + res2.flags = res->flags; + res2.start = res->start + (size * offset); + res2.end = res2.start + (size * num_vfs) - 1; + + if (res2.end > res->end) { + dev_err(&dev->dev, "VF BAR%d: %pR would extend past %pR (trying to enable %d VFs shifted by %d)\n", + i, &res2, res, num_vfs, offset); + return -EBUSY; + } + } + + /* + * After doing so, there would be a "hole" in the /proc/iomem when + * offset is a positive value. It looks like the device return some + * mmio back to the system, which actually no one could use it. + */ + for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { + res = &dev->resource[i + PCI_IOV_RESOURCES]; + if (!res->flags || !res->parent) + continue; + + if (!pnv_pci_is_mem_pref_64(res->flags)) + continue; + + size = pci_iov_resource_size(dev, i + PCI_IOV_RESOURCES); + res2 = *res; + res->start += size * offset; + + dev_info(&dev->dev, "VF BAR%d: %pR shifted to %pR (enabling %d VFs shifted by %d)\n", + i, &res2, res, num_vfs, offset); + pci_update_resource(dev, i + PCI_IOV_RESOURCES); + } + return 0; +} +#endif /* CONFIG_PCI_IOV */ + #if 0 static struct pnv_ioda_pe *pnv_ioda_setup_dev_PE(struct pci_dev *dev) { @@ -979,8 +1150,316 @@ static void pnv_pci_ioda_setup_PEs(void) } #ifdef CONFIG_PCI_IOV +static int pnv_pci_vf_release_m64(struct pci_dev *pdev) +{ + struct pci_bus *bus; + struct pci_controller *hose; + struct pnv_phb *phb; + struct pci_dn *pdn; + int i; + + bus = pdev->bus; + hose = pci_bus_to_host(bus); + phb = hose->private_data; + pdn = pci_get_pdn(pdev); + + for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { + if (pdn->m64_wins[i] == IODA_INVALID_M64) + continue; + opal_pci_phb_mmio_enable(phb->opal_id, + OPAL_M64_WINDOW_TYPE, pdn->m64_wins[i], 0); + clear_bit(pdn->m64_wins[i], &phb->ioda.m64_bar_alloc); + pdn->m64_wins[i] = IODA_INVALID_M64; + } + + return 0; +} + +static int pnv_pci_vf_assign_m64(struct pci_dev *pdev) +{ + struct pci_bus *bus; + struct pci_controller *hose; + struct pnv_phb *phb; + struct pci_dn *pdn; + unsigned int win; + struct resource *res; + int i; + int64_t rc; + + bus = pdev->bus; + hose = pci_bus_to_host(bus); + phb = hose->private_data; + pdn = pci_get_pdn(pdev); + + /* Initialize the m64_wins to IODA_INVALID_M64 */ + for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) + pdn->m64_wins[i] = IODA_INVALID_M64; + + for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { + res = &pdev->resource[i + PCI_IOV_RESOURCES]; + if (!res->flags || !res->parent) + continue; + + if (!pnv_pci_is_mem_pref_64(res->flags)) + continue; + + do { + win = find_next_zero_bit(&phb->ioda.m64_bar_alloc, + phb->ioda.m64_bar_idx + 1, 0); + + if (win >= phb->ioda.m64_bar_idx + 1) + goto m64_failed; + } while (test_and_set_bit(win, &phb->ioda.m64_bar_alloc)); + + pdn->m64_wins[i] = win; + + /* Map the M64 here */ + rc = opal_pci_set_phb_mem_window(phb->opal_id, + OPAL_M64_WINDOW_TYPE, + pdn->m64_wins[i], + res->start, + 0, /* unused */ + resource_size(res)); + if (rc != OPAL_SUCCESS) { + dev_err(&pdev->dev, "Failed to map M64 window #%d: %lld\n", + win, rc); + goto m64_failed; + } + + rc = opal_pci_phb_mmio_enable(phb->opal_id, + OPAL_M64_WINDOW_TYPE, pdn->m64_wins[i], 1); + if (rc != OPAL_SUCCESS) { + dev_err(&pdev->dev, "Failed to enable M64 window #%d: %llx\n", + win, rc); + goto m64_failed; + } + } + return 0; + +m64_failed: + pnv_pci_vf_release_m64(pdev); + return -EBUSY; +} + +static void pnv_pci_ioda2_release_dma_pe(struct pci_dev *dev, struct pnv_ioda_pe *pe) +{ + struct pci_bus *bus; + struct pci_controller *hose; + struct pnv_phb *phb; + struct iommu_table *tbl; + unsigned long addr; + int64_t rc; + + bus = dev->bus; + hose = pci_bus_to_host(bus); + phb = hose->private_data; + tbl = pe->tce32_table; + addr = tbl->it_base; + + opal_pci_map_pe_dma_window(phb->opal_id, pe->pe_number, + pe->pe_number << 1, 1, __pa(addr), + 0, 0x1000); + + rc = opal_pci_map_pe_dma_window_real(pe->phb->opal_id, + pe->pe_number, + (pe->pe_number << 1) + 1, + pe->tce_bypass_base, + 0); + if (rc) + pe_warn(pe, "OPAL error %ld release DMA window\n", rc); + + iommu_free_table(tbl, of_node_full_name(dev->dev.of_node)); + free_pages(addr, get_order(TCE32_TABLE_SIZE)); + pe->tce32_table = NULL; +} + +static void pnv_ioda_release_vf_PE(struct pci_dev *pdev) +{ + struct pci_bus *bus; + struct pci_controller *hose; + struct pnv_phb *phb; + struct pnv_ioda_pe *pe, *pe_n; + struct pci_dn *pdn; + + bus = pdev->bus; + hose = pci_bus_to_host(bus); + phb = hose->private_data; + + if (!pdev->is_physfn) + return; + + pdn = pci_get_pdn(pdev); + list_for_each_entry_safe(pe, pe_n, &phb->ioda.pe_list, list) { + if (pe->parent_dev != pdev) + continue; + + pnv_pci_ioda2_release_dma_pe(pdev, pe); + + /* Remove from list */ + mutex_lock(&phb->ioda.pe_list_mutex); + list_del(&pe->list); + mutex_unlock(&phb->ioda.pe_list_mutex); + + pnv_ioda_deconfigure_pe(phb, pe); + + pnv_ioda_free_pe(phb, pe->pe_number); + } +} + +void pnv_pci_sriov_disable(struct pci_dev *pdev) +{ + struct pci_bus *bus; + struct pci_controller *hose; + struct pnv_phb *phb; + struct pci_dn *pdn; + struct pci_sriov *iov; + u16 num_vfs; + + bus = pdev->bus; + hose = pci_bus_to_host(bus); + phb = hose->private_data; + pdn = pci_get_pdn(pdev); + iov = pdev->sriov; + num_vfs = pdn->num_vfs; + + /* Release VF PEs */ + pnv_ioda_release_vf_PE(pdev); + + if (phb->type == PNV_PHB_IODA2) { + pnv_pci_vf_resource_shift(pdev, -pdn->offset); + + /* Release M64 windows */ + pnv_pci_vf_release_m64(pdev); + + /* Release PE numbers */ + bitmap_clear(phb->ioda.pe_alloc, pdn->offset, num_vfs); + pdn->offset = 0; + } +} + +static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb, + struct pnv_ioda_pe *pe); +static void pnv_ioda_setup_vf_PE(struct pci_dev *pdev, u16 num_vfs) +{ + struct pci_bus *bus; + struct pci_controller *hose; + struct pnv_phb *phb; + struct pnv_ioda_pe *pe; + int pe_num; + u16 vf_index; + struct pci_dn *pdn; + + bus = pdev->bus; + hose = pci_bus_to_host(bus); + phb = hose->private_data; + pdn = pci_get_pdn(pdev); + + if (!pdev->is_physfn) + return; + + /* Reserve PE for each VF */ + for (vf_index = 0; vf_index < num_vfs; vf_index++) { + pe_num = pdn->offset + vf_index; + + pe = &phb->ioda.pe_array[pe_num]; + pe->pe_number = pe_num; + pe->phb = phb; + pe->flags = PNV_IODA_PE_VF; + pe->pbus = NULL; + pe->parent_dev = pdev; + pe->tce32_seg = -1; + pe->mve_number = -1; + pe->rid = (pci_iov_virtfn_bus(pdev, vf_index) << 8) | + pci_iov_virtfn_devfn(pdev, vf_index); + + pe_info(pe, "VF %04d:%02d:%02d.%d associated with PE#%d\n", + hose->global_number, pdev->bus->number, + PCI_SLOT(pci_iov_virtfn_devfn(pdev, vf_index)), + PCI_FUNC(pci_iov_virtfn_devfn(pdev, vf_index)), pe_num); + + if (pnv_ioda_configure_pe(phb, pe)) { + /* XXX What do we do here ? */ + if (pe_num) + pnv_ioda_free_pe(phb, pe_num); + pe->pdev = NULL; + continue; + } + + pe->tce32_table = kzalloc_node(sizeof(struct iommu_table), + GFP_KERNEL, hose->node); + pe->tce32_table->data = pe; + + /* Put PE to the list */ + mutex_lock(&phb->ioda.pe_list_mutex); + list_add_tail(&pe->list, &phb->ioda.pe_list); + mutex_unlock(&phb->ioda.pe_list_mutex); + + pnv_pci_ioda2_setup_dma_pe(phb, pe); + } +} + +int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs) +{ + struct pci_bus *bus; + struct pci_controller *hose; + struct pnv_phb *phb; + struct pci_dn *pdn; + int ret; + + bus = pdev->bus; + hose = pci_bus_to_host(bus); + phb = hose->private_data; + pdn = pci_get_pdn(pdev); + + if (phb->type == PNV_PHB_IODA2) { + /* Calculate available PE for required VFs */ + mutex_lock(&phb->ioda.pe_alloc_mutex); + pdn->offset = bitmap_find_next_zero_area( + phb->ioda.pe_alloc, phb->ioda.total_pe, + 0, num_vfs, 0); + if (pdn->offset >= phb->ioda.total_pe) { + mutex_unlock(&phb->ioda.pe_alloc_mutex); + dev_info(&pdev->dev, "Failed to enable VF%d\n", num_vfs); + pdn->offset = 0; + return -EBUSY; + } + bitmap_set(phb->ioda.pe_alloc, pdn->offset, num_vfs); + pdn->num_vfs = num_vfs; + mutex_unlock(&phb->ioda.pe_alloc_mutex); + + /* Assign M64 window accordingly */ + ret = pnv_pci_vf_assign_m64(pdev); + if (ret) { + dev_info(&pdev->dev, "Not enough M64 window resources\n"); + goto m64_failed; + } + + /* + * When using one M64 BAR to map one IOV BAR, we need to shift + * the IOV BAR according to the PE# allocated to the VFs. + * Otherwise, the PE# for the VF will conflict with others. + */ + ret = pnv_pci_vf_resource_shift(pdev, pdn->offset); + if (ret) + goto m64_failed; + } + + /* Setup VF PEs */ + pnv_ioda_setup_vf_PE(pdev, num_vfs); + + return 0; + +m64_failed: + bitmap_clear(phb->ioda.pe_alloc, pdn->offset, num_vfs); + pdn->offset = 0; + + return ret; +} + int pcibios_sriov_disable(struct pci_dev *pdev) { + pnv_pci_sriov_disable(pdev); + /* Release PCI data */ remove_dev_pci_data(pdev); return 0; @@ -990,6 +1469,8 @@ int pcibios_sriov_enable(struct pci_dev *pdev, u16 num_vfs) { /* Allocate PCI data */ add_dev_pci_data(pdev); + + pnv_pci_sriov_enable(pdev, num_vfs); return 0; } #endif /* CONFIG_PCI_IOV */ @@ -1186,9 +1667,6 @@ static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb, int64_t rc; void *addr; - /* 256M DMA window, 4K TCE pages, 8 bytes TCE */ -#define TCE32_TABLE_SIZE ((0x10000000 / 0x1000) * 8) - /* XXX FIXME: Handle 64-bit only DMA devices */ /* XXX FIXME: Provide 64-bit DMA facilities & non-4K TCE tables etc.. */ /* XXX FIXME: Allocate multi-level tables on PHB3 */ @@ -1251,12 +1729,19 @@ static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb, TCE_PCI_SWINV_PAIR); } iommu_init_table(tbl, phb->hose->node); - iommu_register_group(tbl, phb->hose->global_number, pe->pe_number); - if (pe->pdev) + if (pe->flags & PNV_IODA_PE_DEV) { + iommu_register_group(tbl, phb->hose->global_number, + pe->pe_number); set_iommu_table_base_and_group(&pe->pdev->dev, tbl); - else + } else if (pe->flags & (PNV_IODA_PE_BUS | PNV_IODA_PE_BUS_ALL)) { + iommu_register_group(tbl, phb->hose->global_number, + pe->pe_number); pnv_ioda_setup_bus_dma(pe, pe->pbus, true); + } else if (pe->flags & PNV_IODA_PE_VF) { + iommu_register_group(tbl, phb->hose->global_number, + pe->pe_number); + } return; fail: @@ -1383,12 +1868,19 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb, tbl->it_type |= (TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE); } iommu_init_table(tbl, phb->hose->node); - iommu_register_group(tbl, phb->hose->global_number, pe->pe_number); - if (pe->pdev) + if (pe->flags & PNV_IODA_PE_DEV) { + iommu_register_group(tbl, phb->hose->global_number, + pe->pe_number); set_iommu_table_base_and_group(&pe->pdev->dev, tbl); - else + } else if (pe->flags & (PNV_IODA_PE_BUS | PNV_IODA_PE_BUS_ALL)) { + iommu_register_group(tbl, phb->hose->global_number, + pe->pe_number); pnv_ioda_setup_bus_dma(pe, pe->pbus, true); + } else if (pe->flags & PNV_IODA_PE_VF) { + iommu_register_group(tbl, phb->hose->global_number, + pe->pe_number); + } /* Also create a bypass window */ if (!pnv_iommu_bypass_disabled) @@ -2068,6 +2560,7 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, phb->hub_id = hub_id; phb->opal_id = phb_id; phb->type = ioda_type; + mutex_init(&phb->ioda.pe_alloc_mutex); /* Detect specific models for error handling */ if (of_device_is_compatible(np, "ibm,p7ioc-pciex")) @@ -2127,6 +2620,7 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, INIT_LIST_HEAD(&phb->ioda.pe_dma_list); INIT_LIST_HEAD(&phb->ioda.pe_list); + mutex_init(&phb->ioda.pe_list_mutex); /* Calculate how many 32-bit TCE segments we have */ phb->ioda.tce32_count = phb->ioda.m32_pci_base >> 28; diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index 946aa3d62c3c..02badcef5cea 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c @@ -714,6 +714,24 @@ static void pnv_pci_dma_dev_setup(struct pci_dev *pdev) { struct pci_controller *hose = pci_bus_to_host(pdev->bus); struct pnv_phb *phb = hose->private_data; +#ifdef CONFIG_PCI_IOV + struct pnv_ioda_pe *pe; + struct pci_dn *pdn; + + /* Fix the VF pdn PE number */ + if (pdev->is_virtfn) { + pdn = pci_get_pdn(pdev); + WARN_ON(pdn->pe_number != IODA_INVALID_PE); + list_for_each_entry(pe, &phb->ioda.pe_list, list) { + if (pe->rid == ((pdev->bus->number << 8) | + (pdev->devfn & 0xff))) { + pdn->pe_number = pe->pe_number; + pe->pdev = pdev; + break; + } + } + } +#endif /* CONFIG_PCI_IOV */ /* If we have no phb structure, try to setup a fallback based on * the device-tree (RTAS PCI for example) diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index 84280474e18f..070ee888fc95 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h @@ -23,6 +23,7 @@ enum pnv_phb_model { #define PNV_IODA_PE_BUS_ALL (1 << 2) /* PE has subordinate buses */ #define PNV_IODA_PE_MASTER (1 << 3) /* Master PE in compound case */ #define PNV_IODA_PE_SLAVE (1 << 4) /* Slave PE in compound case */ +#define PNV_IODA_PE_VF (1 << 5) /* PE for one VF */ /* Data associated with a PE, including IOMMU tracking etc.. */ struct pnv_phb; @@ -34,6 +35,9 @@ struct pnv_ioda_pe { * entire bus (& children). In the former case, pdev * is populated, in the later case, pbus is. */ +#ifdef CONFIG_PCI_IOV + struct pci_dev *parent_dev; +#endif struct pci_dev *pdev; struct pci_bus *pbus; @@ -145,6 +149,8 @@ struct pnv_phb { /* PE allocation bitmap */ unsigned long *pe_alloc; + /* PE allocation mutex */ + struct mutex pe_alloc_mutex; /* M32 & IO segment maps */ unsigned int *m32_segmap; @@ -159,6 +165,7 @@ struct pnv_phb { * on the sequence of creation */ struct list_head pe_list; + struct mutex pe_list_mutex; /* Reverse map of PEs, will have to extend if * we are to support more than 256 PEs, indexed -- cgit v1.2.3 From 5b88ec228498b7d41de6599eca12cc0032056e3f Mon Sep 17 00:00:00 2001 From: Wei Yang Date: Wed, 25 Mar 2015 16:23:58 +0800 Subject: powerpc/powernv: Reserve additional space for IOV BAR, with m64_per_iov supported M64 aperture size is limited on PHB3. When the IOV BAR is too big, this will exceed the limitation and failed to be assigned. Introduce a different mechanism based on the IOV BAR size: - if IOV BAR size is smaller than 64MB, expand to total_pe - if IOV BAR size is bigger than 64MB, roundup power2 [bhelgaas: make dev_printk() output more consistent, use PCI_SRIOV_NUM_BARS] Signed-off-by: Wei Yang Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/pci-bridge.h | 2 ++ arch/powerpc/platforms/powernv/pci-ioda.c | 33 ++++++++++++++++++++++++++++--- 2 files changed, 32 insertions(+), 3 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 8716db48e946..415df8509f52 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -182,6 +182,8 @@ struct pci_dn { u16 vfs_expanded; /* number of VFs IOV BAR expanded */ u16 num_vfs; /* number of VFs enabled*/ int offset; /* PE# for the first VF PE */ +#define M64_PER_IOV 4 + int m64_per_iov; #define IODA_INVALID_M64 (-1) int m64_wins[PCI_SRIOV_NUM_BARS]; #endif /* CONFIG_PCI_IOV */ diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 5187d164cfe1..b63925f483fc 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -2250,6 +2250,7 @@ static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev) int i; resource_size_t size; struct pci_dn *pdn; + int mul, total_vfs; if (!pdev->is_physfn || pdev->is_added) return; @@ -2260,6 +2261,32 @@ static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev) pdn = pci_get_pdn(pdev); pdn->vfs_expanded = 0; + total_vfs = pci_sriov_get_totalvfs(pdev); + pdn->m64_per_iov = 1; + mul = phb->ioda.total_pe; + + for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { + res = &pdev->resource[i + PCI_IOV_RESOURCES]; + if (!res->flags || res->parent) + continue; + if (!pnv_pci_is_mem_pref_64(res->flags)) { + dev_warn(&pdev->dev, " non M64 VF BAR%d: %pR\n", + i, res); + continue; + } + + size = pci_iov_resource_size(pdev, i + PCI_IOV_RESOURCES); + + /* bigger than 64M */ + if (size > (1 << 26)) { + dev_info(&pdev->dev, "PowerNV: VF BAR%d: %pR IOV size is bigger than 64M, roundup power2\n", + i, res); + pdn->m64_per_iov = M64_PER_IOV; + mul = roundup_pow_of_two(total_vfs); + break; + } + } + for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { res = &pdev->resource[i + PCI_IOV_RESOURCES]; if (!res->flags || res->parent) @@ -2272,12 +2299,12 @@ static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev) dev_dbg(&pdev->dev, " Fixing VF BAR%d: %pR to\n", i, res); size = pci_iov_resource_size(pdev, i + PCI_IOV_RESOURCES); - res->end = res->start + size * phb->ioda.total_pe - 1; + res->end = res->start + size * mul - 1; dev_dbg(&pdev->dev, " %pR\n", res); dev_info(&pdev->dev, "VF BAR%d: %pR (expanded to %d VFs for PE alignment)", - i, res, phb->ioda.total_pe); + i, res, mul); } - pdn->vfs_expanded = phb->ioda.total_pe; + pdn->vfs_expanded = mul; } #endif /* CONFIG_PCI_IOV */ -- cgit v1.2.3 From 02639b0e1326c3eff88d74fde6b5dbd04ace564e Mon Sep 17 00:00:00 2001 From: Wei Yang Date: Wed, 25 Mar 2015 16:23:59 +0800 Subject: powerpc/powernv: Group VF PE when IOV BAR is big on PHB3 When IOV BAR is big, each is covered by 4 M64 windows. This leads to several VF PE sits in one PE in terms of M64. Group VF PEs according to the M64 allocation. [bhelgaas: use dev_printk() when possible] Signed-off-by: Wei Yang Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/pci-bridge.h | 2 +- arch/powerpc/platforms/powernv/pci-ioda.c | 197 +++++++++++++++++++++++------- 2 files changed, 154 insertions(+), 45 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 415df8509f52..560c73996474 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -185,7 +185,7 @@ struct pci_dn { #define M64_PER_IOV 4 int m64_per_iov; #define IODA_INVALID_M64 (-1) - int m64_wins[PCI_SRIOV_NUM_BARS]; + int m64_wins[PCI_SRIOV_NUM_BARS][M64_PER_IOV]; #endif /* CONFIG_PCI_IOV */ #endif struct list_head child_list; diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index b63925f483fc..33088f6f7328 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -1156,26 +1156,27 @@ static int pnv_pci_vf_release_m64(struct pci_dev *pdev) struct pci_controller *hose; struct pnv_phb *phb; struct pci_dn *pdn; - int i; + int i, j; bus = pdev->bus; hose = pci_bus_to_host(bus); phb = hose->private_data; pdn = pci_get_pdn(pdev); - for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { - if (pdn->m64_wins[i] == IODA_INVALID_M64) - continue; - opal_pci_phb_mmio_enable(phb->opal_id, - OPAL_M64_WINDOW_TYPE, pdn->m64_wins[i], 0); - clear_bit(pdn->m64_wins[i], &phb->ioda.m64_bar_alloc); - pdn->m64_wins[i] = IODA_INVALID_M64; - } + for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) + for (j = 0; j < M64_PER_IOV; j++) { + if (pdn->m64_wins[i][j] == IODA_INVALID_M64) + continue; + opal_pci_phb_mmio_enable(phb->opal_id, + OPAL_M64_WINDOW_TYPE, pdn->m64_wins[i][j], 0); + clear_bit(pdn->m64_wins[i][j], &phb->ioda.m64_bar_alloc); + pdn->m64_wins[i][j] = IODA_INVALID_M64; + } return 0; } -static int pnv_pci_vf_assign_m64(struct pci_dev *pdev) +static int pnv_pci_vf_assign_m64(struct pci_dev *pdev, u16 num_vfs) { struct pci_bus *bus; struct pci_controller *hose; @@ -1183,17 +1184,33 @@ static int pnv_pci_vf_assign_m64(struct pci_dev *pdev) struct pci_dn *pdn; unsigned int win; struct resource *res; - int i; + int i, j; int64_t rc; + int total_vfs; + resource_size_t size, start; + int pe_num; + int vf_groups; + int vf_per_group; bus = pdev->bus; hose = pci_bus_to_host(bus); phb = hose->private_data; pdn = pci_get_pdn(pdev); + total_vfs = pci_sriov_get_totalvfs(pdev); /* Initialize the m64_wins to IODA_INVALID_M64 */ for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) - pdn->m64_wins[i] = IODA_INVALID_M64; + for (j = 0; j < M64_PER_IOV; j++) + pdn->m64_wins[i][j] = IODA_INVALID_M64; + + if (pdn->m64_per_iov == M64_PER_IOV) { + vf_groups = (num_vfs <= M64_PER_IOV) ? num_vfs: M64_PER_IOV; + vf_per_group = (num_vfs <= M64_PER_IOV)? 1: + roundup_pow_of_two(num_vfs) / pdn->m64_per_iov; + } else { + vf_groups = 1; + vf_per_group = 1; + } for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { res = &pdev->resource[i + PCI_IOV_RESOURCES]; @@ -1203,35 +1220,61 @@ static int pnv_pci_vf_assign_m64(struct pci_dev *pdev) if (!pnv_pci_is_mem_pref_64(res->flags)) continue; - do { - win = find_next_zero_bit(&phb->ioda.m64_bar_alloc, - phb->ioda.m64_bar_idx + 1, 0); - - if (win >= phb->ioda.m64_bar_idx + 1) - goto m64_failed; - } while (test_and_set_bit(win, &phb->ioda.m64_bar_alloc)); + for (j = 0; j < vf_groups; j++) { + do { + win = find_next_zero_bit(&phb->ioda.m64_bar_alloc, + phb->ioda.m64_bar_idx + 1, 0); + + if (win >= phb->ioda.m64_bar_idx + 1) + goto m64_failed; + } while (test_and_set_bit(win, &phb->ioda.m64_bar_alloc)); + + pdn->m64_wins[i][j] = win; + + if (pdn->m64_per_iov == M64_PER_IOV) { + size = pci_iov_resource_size(pdev, + PCI_IOV_RESOURCES + i); + size = size * vf_per_group; + start = res->start + size * j; + } else { + size = resource_size(res); + start = res->start; + } - pdn->m64_wins[i] = win; + /* Map the M64 here */ + if (pdn->m64_per_iov == M64_PER_IOV) { + pe_num = pdn->offset + j; + rc = opal_pci_map_pe_mmio_window(phb->opal_id, + pe_num, OPAL_M64_WINDOW_TYPE, + pdn->m64_wins[i][j], 0); + } - /* Map the M64 here */ - rc = opal_pci_set_phb_mem_window(phb->opal_id, + rc = opal_pci_set_phb_mem_window(phb->opal_id, OPAL_M64_WINDOW_TYPE, - pdn->m64_wins[i], - res->start, + pdn->m64_wins[i][j], + start, 0, /* unused */ - resource_size(res)); - if (rc != OPAL_SUCCESS) { - dev_err(&pdev->dev, "Failed to map M64 window #%d: %lld\n", - win, rc); - goto m64_failed; - } + size); - rc = opal_pci_phb_mmio_enable(phb->opal_id, - OPAL_M64_WINDOW_TYPE, pdn->m64_wins[i], 1); - if (rc != OPAL_SUCCESS) { - dev_err(&pdev->dev, "Failed to enable M64 window #%d: %llx\n", - win, rc); - goto m64_failed; + + if (rc != OPAL_SUCCESS) { + dev_err(&pdev->dev, "Failed to map M64 window #%d: %lld\n", + win, rc); + goto m64_failed; + } + + if (pdn->m64_per_iov == M64_PER_IOV) + rc = opal_pci_phb_mmio_enable(phb->opal_id, + OPAL_M64_WINDOW_TYPE, pdn->m64_wins[i][j], 2); + else + rc = opal_pci_phb_mmio_enable(phb->opal_id, + OPAL_M64_WINDOW_TYPE, pdn->m64_wins[i][j], 1); + + if (rc != OPAL_SUCCESS) { + dev_err(&pdev->dev, "Failed to enable M64 window #%d: %llx\n", + win, rc); + goto m64_failed; + } } } return 0; @@ -1273,22 +1316,53 @@ static void pnv_pci_ioda2_release_dma_pe(struct pci_dev *dev, struct pnv_ioda_pe pe->tce32_table = NULL; } -static void pnv_ioda_release_vf_PE(struct pci_dev *pdev) +static void pnv_ioda_release_vf_PE(struct pci_dev *pdev, u16 num_vfs) { struct pci_bus *bus; struct pci_controller *hose; struct pnv_phb *phb; struct pnv_ioda_pe *pe, *pe_n; struct pci_dn *pdn; + u16 vf_index; + int64_t rc; bus = pdev->bus; hose = pci_bus_to_host(bus); phb = hose->private_data; + pdn = pci_get_pdn(pdev); if (!pdev->is_physfn) return; - pdn = pci_get_pdn(pdev); + if (pdn->m64_per_iov == M64_PER_IOV && num_vfs > M64_PER_IOV) { + int vf_group; + int vf_per_group; + int vf_index1; + + vf_per_group = roundup_pow_of_two(num_vfs) / pdn->m64_per_iov; + + for (vf_group = 0; vf_group < M64_PER_IOV; vf_group++) + for (vf_index = vf_group * vf_per_group; + vf_index < (vf_group + 1) * vf_per_group && + vf_index < num_vfs; + vf_index++) + for (vf_index1 = vf_group * vf_per_group; + vf_index1 < (vf_group + 1) * vf_per_group && + vf_index1 < num_vfs; + vf_index1++){ + + rc = opal_pci_set_peltv(phb->opal_id, + pdn->offset + vf_index, + pdn->offset + vf_index1, + OPAL_REMOVE_PE_FROM_DOMAIN); + + if (rc) + dev_warn(&pdev->dev, "%s: Failed to unlink same group PE#%d(%lld)\n", + __func__, + pdn->offset + vf_index1, rc); + } + } + list_for_each_entry_safe(pe, pe_n, &phb->ioda.pe_list, list) { if (pe->parent_dev != pdev) continue; @@ -1323,10 +1397,11 @@ void pnv_pci_sriov_disable(struct pci_dev *pdev) num_vfs = pdn->num_vfs; /* Release VF PEs */ - pnv_ioda_release_vf_PE(pdev); + pnv_ioda_release_vf_PE(pdev, num_vfs); if (phb->type == PNV_PHB_IODA2) { - pnv_pci_vf_resource_shift(pdev, -pdn->offset); + if (pdn->m64_per_iov == 1) + pnv_pci_vf_resource_shift(pdev, -pdn->offset); /* Release M64 windows */ pnv_pci_vf_release_m64(pdev); @@ -1348,6 +1423,7 @@ static void pnv_ioda_setup_vf_PE(struct pci_dev *pdev, u16 num_vfs) int pe_num; u16 vf_index; struct pci_dn *pdn; + int64_t rc; bus = pdev->bus; hose = pci_bus_to_host(bus); @@ -1396,6 +1472,37 @@ static void pnv_ioda_setup_vf_PE(struct pci_dev *pdev, u16 num_vfs) pnv_pci_ioda2_setup_dma_pe(phb, pe); } + + if (pdn->m64_per_iov == M64_PER_IOV && num_vfs > M64_PER_IOV) { + int vf_group; + int vf_per_group; + int vf_index1; + + vf_per_group = roundup_pow_of_two(num_vfs) / pdn->m64_per_iov; + + for (vf_group = 0; vf_group < M64_PER_IOV; vf_group++) { + for (vf_index = vf_group * vf_per_group; + vf_index < (vf_group + 1) * vf_per_group && + vf_index < num_vfs; + vf_index++) { + for (vf_index1 = vf_group * vf_per_group; + vf_index1 < (vf_group + 1) * vf_per_group && + vf_index1 < num_vfs; + vf_index1++) { + + rc = opal_pci_set_peltv(phb->opal_id, + pdn->offset + vf_index, + pdn->offset + vf_index1, + OPAL_ADD_PE_TO_DOMAIN); + + if (rc) + dev_warn(&pdev->dev, "%s: Failed to link same group PE#%d(%lld)\n", + __func__, + pdn->offset + vf_index1, rc); + } + } + } + } } int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs) @@ -1428,7 +1535,7 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs) mutex_unlock(&phb->ioda.pe_alloc_mutex); /* Assign M64 window accordingly */ - ret = pnv_pci_vf_assign_m64(pdev); + ret = pnv_pci_vf_assign_m64(pdev, num_vfs); if (ret) { dev_info(&pdev->dev, "Not enough M64 window resources\n"); goto m64_failed; @@ -1439,9 +1546,11 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs) * the IOV BAR according to the PE# allocated to the VFs. * Otherwise, the PE# for the VF will conflict with others. */ - ret = pnv_pci_vf_resource_shift(pdev, pdn->offset); - if (ret) - goto m64_failed; + if (pdn->m64_per_iov == 1) { + ret = pnv_pci_vf_resource_shift(pdev, pdn->offset); + if (ret) + goto m64_failed; + } } /* Setup VF PEs */ -- cgit v1.2.3 From 250c7b277c65e801a3312061dc2e919233468916 Mon Sep 17 00:00:00 2001 From: Wei Yang Date: Wed, 25 Mar 2015 16:24:00 +0800 Subject: powerpc/pci: Remove unused struct pci_dn.pcidev field In struct pci_dn, the pcidev field is assigned but not used, so remove it. Signed-off-by: Wei Yang Acked-by: Gavin Shan Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/pci-bridge.h | 1 - arch/powerpc/platforms/powernv/pci-ioda.c | 1 - 2 files changed, 2 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 560c73996474..a39270e85beb 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -171,7 +171,6 @@ struct pci_dn { int pci_ext_config_space; /* for pci devices */ - struct pci_dev *pcidev; /* back-pointer to the pci device */ #ifdef CONFIG_EEH struct eeh_dev *edev; /* eeh device */ #endif diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 33088f6f7328..b1387ea6d10a 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -1028,7 +1028,6 @@ static void pnv_ioda_setup_same_PE(struct pci_bus *bus, struct pnv_ioda_pe *pe) pci_name(dev)); continue; } - pdn->pcidev = dev; pdn->pe_number = pe->pe_number; pe->dma_weight += pnv_ioda_dma_weight(dev); if ((pe->flags & PNV_IODA_PE_BUS_ALL) && dev->subordinate) -- cgit v1.2.3 From acdb66857fb9a713c93bb3e6edba5ee478ba0678 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 30 Mar 2015 16:46:04 -0700 Subject: powerpc: Use bool function return values of true/false not 1/0 Use the normal return values for bool functions Signed-off-by: Joe Perches Acked-by: Benjamin Herrenschmidt Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/dcr-native.h | 2 +- arch/powerpc/include/asm/dma-mapping.h | 4 ++-- arch/powerpc/include/asm/kvm_book3s_64.h | 4 ++-- arch/powerpc/sysdev/dcr.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/dcr-native.h b/arch/powerpc/include/asm/dcr-native.h index 7d2e6235726d..4efc11dacb98 100644 --- a/arch/powerpc/include/asm/dcr-native.h +++ b/arch/powerpc/include/asm/dcr-native.h @@ -31,7 +31,7 @@ typedef struct { static inline bool dcr_map_ok_native(dcr_host_native_t host) { - return 1; + return true; } #define dcr_map_native(dev, dcr_n, dcr_c) \ diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h index 894d538f3567..9103687b0436 100644 --- a/arch/powerpc/include/asm/dma-mapping.h +++ b/arch/powerpc/include/asm/dma-mapping.h @@ -191,11 +191,11 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) struct dev_archdata *sd = &dev->archdata; if (sd->max_direct_dma_addr && addr + size > sd->max_direct_dma_addr) - return 0; + return false; #endif if (!dev->dma_mask) - return 0; + return false; return addr + size - 1 <= *dev->dma_mask; } diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h index 2d81e202bdcc..2a244bf869c0 100644 --- a/arch/powerpc/include/asm/kvm_book3s_64.h +++ b/arch/powerpc/include/asm/kvm_book3s_64.h @@ -335,7 +335,7 @@ static inline bool hpte_read_permission(unsigned long pp, unsigned long key) { if (key) return PP_RWRX <= pp && pp <= PP_RXRX; - return 1; + return true; } static inline bool hpte_write_permission(unsigned long pp, unsigned long key) @@ -373,7 +373,7 @@ static inline bool slot_is_aligned(struct kvm_memory_slot *memslot, unsigned long mask = (pagesize >> PAGE_SHIFT) - 1; if (pagesize <= PAGE_SIZE) - return 1; + return true; return !(memslot->base_gfn & mask) && !(memslot->npages & mask); } diff --git a/arch/powerpc/sysdev/dcr.c b/arch/powerpc/sysdev/dcr.c index 2d8a101b6b9e..121e26fffd50 100644 --- a/arch/powerpc/sysdev/dcr.c +++ b/arch/powerpc/sysdev/dcr.c @@ -54,7 +54,7 @@ bool dcr_map_ok_generic(dcr_host_t host) else if (host.type == DCR_HOST_MMIO) return dcr_map_ok_mmio(host.host.mmio); else - return 0; + return false; } EXPORT_SYMBOL_GPL(dcr_map_ok_generic); -- cgit v1.2.3 From e3c5c2e0bc857c7cbdb81f35a6b90236c5f330e9 Mon Sep 17 00:00:00 2001 From: Cédric Le Goater Date: Mon, 30 Mar 2015 12:06:09 +0200 Subject: powerpc/powernv: convert codes returned by OPAL calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OPAL has its own list of return codes. The patch provides a translation of such codes in errnos for the opal_sensor_read call, and possibly others if needed. Signed-off-by: Cédric Le Goater Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/opal.h | 2 ++ arch/powerpc/platforms/powernv/opal-sensor.c | 6 ++++-- arch/powerpc/platforms/powernv/opal.c | 19 +++++++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index c08de77f398a..fde90bacc65e 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h @@ -247,6 +247,8 @@ struct opal_sg_list *opal_vmalloc_to_sg_list(void *vmalloc_addr, unsigned long vmalloc_size); void opal_free_sg_list(struct opal_sg_list *sg); +extern int opal_error_code(int rc); + #endif /* __ASSEMBLY__ */ #endif /* _ASM_POWERPC_OPAL_H */ diff --git a/arch/powerpc/platforms/powernv/opal-sensor.c b/arch/powerpc/platforms/powernv/opal-sensor.c index 4ab67ef7abc9..e9c5d8f33d4c 100644 --- a/arch/powerpc/platforms/powernv/opal-sensor.c +++ b/arch/powerpc/platforms/powernv/opal-sensor.c @@ -46,8 +46,10 @@ int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data) mutex_lock(&opal_sensor_mutex); ret = opal_sensor_read(sensor_hndl, token, &data); - if (ret != OPAL_ASYNC_COMPLETION) + if (ret != OPAL_ASYNC_COMPLETION) { + ret = opal_error_code(ret); goto out_token; + } ret = opal_async_wait_response(token, &msg); if (ret) { @@ -57,7 +59,7 @@ int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data) } *sensor_data = be32_to_cpu(data); - ret = be64_to_cpu(msg.params[1]); + ret = opal_error_code(be64_to_cpu(msg.params[1])); out_token: mutex_unlock(&opal_sensor_mutex); diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index d403b2b08626..3fb981c0ca80 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c @@ -931,6 +931,25 @@ void opal_free_sg_list(struct opal_sg_list *sg) } } +int opal_error_code(int rc) +{ + switch (rc) { + case OPAL_SUCCESS: return 0; + + case OPAL_PARAMETER: return -EINVAL; + case OPAL_ASYNC_COMPLETION: return -EINPROGRESS; + case OPAL_BUSY_EVENT: return -EBUSY; + case OPAL_NO_MEM: return -ENOMEM; + + case OPAL_UNSUPPORTED: return -EIO; + case OPAL_HARDWARE: return -EIO; + case OPAL_INTERNAL_ERROR: return -EIO; + default: + pr_err("%s: unexpected OPAL error %d\n", __func__, rc); + return -EIO; + } +} + EXPORT_SYMBOL_GPL(opal_poll_events); EXPORT_SYMBOL_GPL(opal_rtc_read); EXPORT_SYMBOL_GPL(opal_rtc_write); -- cgit v1.2.3 From 2e51563d07cf0caae03dd7f693d7545825326c29 Mon Sep 17 00:00:00 2001 From: Madalin Bucur Date: Tue, 10 Mar 2015 15:19:42 +0200 Subject: powerpc/fsl-booke: Add T4080 SVR value Signed-off-by: Madalin Bucur Signed-off-by: Scott Wood --- arch/powerpc/include/asm/mpc85xx.h | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/mpc85xx.h b/arch/powerpc/include/asm/mpc85xx.h index 3bef74a9914b..213f3a81593d 100644 --- a/arch/powerpc/include/asm/mpc85xx.h +++ b/arch/powerpc/include/asm/mpc85xx.h @@ -61,6 +61,7 @@ #define SVR_T4240 0x824000 #define SVR_T4120 0x824001 #define SVR_T4160 0x824100 +#define SVR_T4080 0x824102 #define SVR_C291 0x850000 #define SVR_C292 0x850020 #define SVR_C293 0x850030 -- cgit v1.2.3 From 016f8cf0d87bb2bda15ccb8708748a013c27423f Mon Sep 17 00:00:00 2001 From: Kevin Hao Date: Tue, 10 Mar 2015 20:41:31 +0800 Subject: powerpc: book3e_64: fix the align size for paca_struct All the cache line size of the current book3e 64bit SoCs are 64 bytes. So we should use this size to align the member of paca_struct. This only change the paca_struct's members which are private to book3e CPUs, and should not have any effect to book3s ones. With this, we save 192 bytes. Also change it to __aligned(size) since it is preferred over __attribute__((aligned(size))). Before: /* size: 1920, cachelines: 30, members: 46 */ /* sum members: 1667, holes: 6, sum holes: 141 */ /* padding: 112 */ After: /* size: 1728, cachelines: 27, members: 46 */ /* sum members: 1667, holes: 4, sum holes: 13 */ /* padding: 48 */ Signed-off-by: Kevin Hao Signed-off-by: Scott Wood --- arch/powerpc/include/asm/paca.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index e5f22c6c4bf9..70bd4381f8e6 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h @@ -106,9 +106,9 @@ struct paca_struct { #endif /* CONFIG_PPC_STD_MMU_64 */ #ifdef CONFIG_PPC_BOOK3E - u64 exgen[8] __attribute__((aligned(0x80))); + u64 exgen[8] __aligned(0x40); /* Keep pgd in the same cacheline as the start of extlb */ - pgd_t *pgd __attribute__((aligned(0x80))); /* Current PGD */ + pgd_t *pgd __aligned(0x40); /* Current PGD */ pgd_t *kernel_pgd; /* Kernel PGD */ /* Shared by all threads of a core -- points to tcd of first thread */ -- cgit v1.2.3 From bf4981a00636347ddcef3fc008e4dd979380a851 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 19 Mar 2015 15:15:20 +1100 Subject: powerpc: Remove the celleb support The celleb code has seen no actual development for ~7 years. We (maintainers) have no access to test hardware, and it is highly likely the code has bit-rotted. As far as we're aware the hardware was never widely available, and is certainly no longer available, and no one on the list has shown any interest in it over the years. So remove it. If anyone has one and cares please speak up. Signed-off-by: Michael Ellerman Acked-by: Benjamin Herrenschmidt Acked-by: Jeremy Kerr --- arch/powerpc/Kconfig.debug | 7 - arch/powerpc/boot/Makefile | 2 - arch/powerpc/configs/cell_defconfig | 3 - arch/powerpc/configs/celleb_defconfig | 152 ------- arch/powerpc/configs/ppc64_defconfig | 3 - arch/powerpc/include/asm/firmware.h | 10 +- arch/powerpc/include/asm/smp.h | 1 - arch/powerpc/kernel/udbg.c | 2 - arch/powerpc/platforms/Kconfig | 5 - arch/powerpc/platforms/cell/Kconfig | 11 - arch/powerpc/platforms/cell/Makefile | 15 - arch/powerpc/platforms/cell/beat.c | 264 ------------ arch/powerpc/platforms/cell/beat.h | 39 -- arch/powerpc/platforms/cell/beat_htab.c | 445 -------------------- arch/powerpc/platforms/cell/beat_hvCall.S | 285 ------------- arch/powerpc/platforms/cell/beat_interrupt.c | 253 ------------ arch/powerpc/platforms/cell/beat_interrupt.h | 30 -- arch/powerpc/platforms/cell/beat_iommu.c | 115 ------ arch/powerpc/platforms/cell/beat_spu_priv1.c | 205 ---------- arch/powerpc/platforms/cell/beat_syscall.h | 164 -------- arch/powerpc/platforms/cell/beat_udbg.c | 98 ----- arch/powerpc/platforms/cell/beat_wrapper.h | 290 ------------- arch/powerpc/platforms/cell/celleb_pci.c | 499 ----------------------- arch/powerpc/platforms/cell/celleb_pci.h | 46 --- arch/powerpc/platforms/cell/celleb_scc.h | 232 ----------- arch/powerpc/platforms/cell/celleb_scc_epci.c | 428 -------------------- arch/powerpc/platforms/cell/celleb_scc_pciex.c | 538 ------------------------- arch/powerpc/platforms/cell/celleb_scc_sio.c | 99 ----- arch/powerpc/platforms/cell/celleb_scc_uhc.c | 95 ----- arch/powerpc/platforms/cell/celleb_setup.c | 243 ----------- arch/powerpc/platforms/cell/iommu.c | 2 - 31 files changed, 1 insertion(+), 4580 deletions(-) delete mode 100644 arch/powerpc/configs/celleb_defconfig delete mode 100644 arch/powerpc/platforms/cell/beat.c delete mode 100644 arch/powerpc/platforms/cell/beat.h delete mode 100644 arch/powerpc/platforms/cell/beat_htab.c delete mode 100644 arch/powerpc/platforms/cell/beat_hvCall.S delete mode 100644 arch/powerpc/platforms/cell/beat_interrupt.c delete mode 100644 arch/powerpc/platforms/cell/beat_interrupt.h delete mode 100644 arch/powerpc/platforms/cell/beat_iommu.c delete mode 100644 arch/powerpc/platforms/cell/beat_spu_priv1.c delete mode 100644 arch/powerpc/platforms/cell/beat_syscall.h delete mode 100644 arch/powerpc/platforms/cell/beat_udbg.c delete mode 100644 arch/powerpc/platforms/cell/beat_wrapper.h delete mode 100644 arch/powerpc/platforms/cell/celleb_pci.c delete mode 100644 arch/powerpc/platforms/cell/celleb_pci.h delete mode 100644 arch/powerpc/platforms/cell/celleb_scc.h delete mode 100644 arch/powerpc/platforms/cell/celleb_scc_epci.c delete mode 100644 arch/powerpc/platforms/cell/celleb_scc_pciex.c delete mode 100644 arch/powerpc/platforms/cell/celleb_scc_sio.c delete mode 100644 arch/powerpc/platforms/cell/celleb_scc_uhc.c delete mode 100644 arch/powerpc/platforms/cell/celleb_setup.c (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index bfd823abff93..0efa8f90a8f1 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug @@ -193,13 +193,6 @@ config PPC_EARLY_DEBUG_PAS_REALMODE Select this to enable early debugging for PA Semi. Output will be on UART0. -config PPC_EARLY_DEBUG_BEAT - bool "Beat HV Console" - depends on PPC_CELLEB - select PPC_UDBG_BEAT - help - Select this to enable early debugging for Celleb with Beat. - config PPC_EARLY_DEBUG_44x bool "Early serial debugging for IBM/AMCC 44x CPUs" depends on 44x diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 73a19fac4850..73eddda53b8e 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -110,7 +110,6 @@ src-plat-$(CONFIG_EPAPR_BOOT) += epapr.c epapr-wrapper.c src-plat-$(CONFIG_PPC_PSERIES) += pseries-head.S src-plat-$(CONFIG_PPC_POWERNV) += pseries-head.S src-plat-$(CONFIG_PPC_IBM_CELL_BLADE) += pseries-head.S -src-plat-$(CONFIG_PPC_CELLEB) += pseries-head.S src-plat-$(CONFIG_PPC_CELL_QPACE) += pseries-head.S src-wlib := $(sort $(src-wlib-y)) @@ -215,7 +214,6 @@ image-$(CONFIG_PPC_POWERNV) += zImage.pseries image-$(CONFIG_PPC_MAPLE) += zImage.maple image-$(CONFIG_PPC_IBM_CELL_BLADE) += zImage.pseries image-$(CONFIG_PPC_PS3) += dtbImage.ps3 -image-$(CONFIG_PPC_CELLEB) += zImage.pseries image-$(CONFIG_PPC_CELL_QPACE) += zImage.pseries image-$(CONFIG_PPC_CHRP) += zImage.chrp image-$(CONFIG_PPC_EFIKA) += zImage.chrp diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig index 9788b3c2d563..9227b517560a 100644 --- a/arch/powerpc/configs/cell_defconfig +++ b/arch/powerpc/configs/cell_defconfig @@ -28,7 +28,6 @@ CONFIG_PS3_ROM=m CONFIG_PS3_FLASH=m CONFIG_PS3_LPM=m CONFIG_PPC_IBM_CELL_BLADE=y -CONFIG_PPC_CELLEB=y CONFIG_RTAS_FLASH=y CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_GOV_POWERSAVE=y @@ -113,7 +112,6 @@ CONFIG_IDE=y CONFIG_BLK_DEV_GENERIC=y CONFIG_BLK_DEV_AEC62XX=y CONFIG_BLK_DEV_SIIMAGE=y -CONFIG_BLK_DEV_CELLEB=y CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=m CONFIG_CHR_DEV_SG=y @@ -156,7 +154,6 @@ CONFIG_SERIAL_TXX9_NR_UARTS=2 CONFIG_SERIAL_TXX9_CONSOLE=y CONFIG_SERIAL_OF_PLATFORM=y CONFIG_HVC_RTAS=y -CONFIG_HVC_BEAT=y CONFIG_IPMI_HANDLER=m CONFIG_IPMI_DEVICE_INTERFACE=m CONFIG_IPMI_SI=m diff --git a/arch/powerpc/configs/celleb_defconfig b/arch/powerpc/configs/celleb_defconfig deleted file mode 100644 index ff454dcd2dd3..000000000000 --- a/arch/powerpc/configs/celleb_defconfig +++ /dev/null @@ -1,152 +0,0 @@ -CONFIG_PPC64=y -CONFIG_TUNE_CELL=y -CONFIG_ALTIVEC=y -CONFIG_SMP=y -CONFIG_NR_CPUS=4 -CONFIG_SYSVIPC=y -CONFIG_FHANDLE=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=15 -CONFIG_BLK_DEV_INITRD=y -# CONFIG_COMPAT_BRK is not set -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -CONFIG_MODVERSIONS=y -CONFIG_MODULE_SRCVERSION_ALL=y -CONFIG_PARTITION_ADVANCED=y -# CONFIG_PPC_POWERNV is not set -# CONFIG_PPC_PSERIES is not set -# CONFIG_PPC_PMAC is not set -CONFIG_PPC_CELLEB=y -CONFIG_SPU_FS=y -# CONFIG_CBE_THERM is not set -CONFIG_UDBG_RTAS_CONSOLE=y -# CONFIG_RTAS_PROC is not set -CONFIG_BINFMT_MISC=m -CONFIG_KEXEC=y -CONFIG_NUMA=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_SYN_COOKIES=y -CONFIG_IPV6=y -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -CONFIG_IPV6_TUNNEL=m -CONFIG_NETFILTER=y -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=131072 -CONFIG_IDE=y -CONFIG_BLK_DEV_IDECD=m -CONFIG_BLK_DEV_GENERIC=y -CONFIG_BLK_DEV_CELLEB=y -CONFIG_SCSI=m -# CONFIG_SCSI_PROC_FS is not set -CONFIG_BLK_DEV_SD=m -CONFIG_BLK_DEV_SR=m -CONFIG_CHR_DEV_SG=m -CONFIG_MD=y -CONFIG_BLK_DEV_MD=m -CONFIG_MD_LINEAR=m -CONFIG_MD_RAID0=m -CONFIG_MD_RAID1=m -CONFIG_BLK_DEV_DM=m -CONFIG_DM_CRYPT=m -CONFIG_DM_SNAPSHOT=m -CONFIG_DM_MIRROR=m -CONFIG_DM_ZERO=m -CONFIG_DM_MULTIPATH=m -CONFIG_NETDEVICES=y -CONFIG_SPIDER_NET=y -# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_SERIO_I8042 is not set -# CONFIG_LEGACY_PTYS is not set -CONFIG_SERIAL_NONSTANDARD=y -CONFIG_SERIAL_TXX9_NR_UARTS=3 -CONFIG_SERIAL_TXX9_CONSOLE=y -CONFIG_HVC_RTAS=y -CONFIG_HVC_BEAT=y -# CONFIG_HW_RANDOM is not set -CONFIG_GEN_RTC=y -CONFIG_I2C=y -# CONFIG_HWMON is not set -CONFIG_WATCHDOG=y -# CONFIG_VGA_CONSOLE is not set -CONFIG_USB_HIDDEV=y -CONFIG_USB=y -CONFIG_USB_MON=y -CONFIG_USB_EHCI_HCD=m -# CONFIG_USB_EHCI_HCD_PPC_OF is not set -CONFIG_USB_OHCI_HCD=m -CONFIG_USB_STORAGE=m -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_POSIX_ACL=y -CONFIG_EXT2_FS_SECURITY=y -CONFIG_EXT2_FS_XIP=y -CONFIG_EXT3_FS=y -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_EXT3_FS_SECURITY=y -CONFIG_ISO9660_FS=m -CONFIG_JOLIET=y -CONFIG_UDF_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m -CONFIG_PROC_KCORE=y -CONFIG_TMPFS=y -CONFIG_HUGETLBFS=y -CONFIG_NFS_FS=m -CONFIG_NFS_V3_ACL=y -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -CONFIG_NFSD_V3_ACL=y -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_ISO8859_2=m -CONFIG_NLS_ISO8859_3=m -CONFIG_NLS_ISO8859_4=m -CONFIG_NLS_ISO8859_5=m -CONFIG_NLS_ISO8859_6=m -CONFIG_NLS_ISO8859_7=m -CONFIG_NLS_ISO8859_9=m -CONFIG_NLS_ISO8859_13=m -CONFIG_NLS_ISO8859_14=m -CONFIG_NLS_ISO8859_15=m -CONFIG_LIBCRC32C=m -CONFIG_DEBUG_FS=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_DEBUG_KERNEL=y -CONFIG_DEBUG_MUTEXES=y -CONFIG_XMON=y -CONFIG_XMON_DEFAULT=y -CONFIG_CRYPTO_NULL=m -CONFIG_CRYPTO_TEST=m -CONFIG_CRYPTO_ECB=m -CONFIG_CRYPTO_PCBC=m -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_MD4=m -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_MICHAEL_MIC=m -CONFIG_CRYPTO_SHA256=m -CONFIG_CRYPTO_SHA512=m -CONFIG_CRYPTO_TGR192=m -CONFIG_CRYPTO_WP512=m -CONFIG_CRYPTO_ANUBIS=m -CONFIG_CRYPTO_ARC4=m -CONFIG_CRYPTO_BLOWFISH=m -CONFIG_CRYPTO_CAST5=m -CONFIG_CRYPTO_CAST6=m -CONFIG_CRYPTO_KHAZAD=m -CONFIG_CRYPTO_SERPENT=m -CONFIG_CRYPTO_TEA=m -CONFIG_CRYPTO_TWOFISH=m -# CONFIG_CRYPTO_HW is not set diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index 3315c9f0828a..aad501ae3834 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig @@ -36,7 +36,6 @@ CONFIG_PS3_ROM=m CONFIG_PS3_FLASH=m CONFIG_PS3_LPM=m CONFIG_PPC_IBM_CELL_BLADE=y -CONFIG_PPC_CELLEB=y CONFIG_PPC_CELL_QPACE=y CONFIG_RTAS_FLASH=m CONFIG_IBMEBUS=y @@ -89,7 +88,6 @@ CONFIG_IDE=y CONFIG_BLK_DEV_IDECD=y CONFIG_BLK_DEV_GENERIC=y CONFIG_BLK_DEV_AMD74XX=y -CONFIG_BLK_DEV_CELLEB=y CONFIG_BLK_DEV_IDE_PMAC=y CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y CONFIG_BLK_DEV_SD=y @@ -196,7 +194,6 @@ CONFIG_SERIAL_TXX9_CONSOLE=y CONFIG_SERIAL_JSM=m CONFIG_HVC_CONSOLE=y CONFIG_HVC_RTAS=y -CONFIG_HVC_BEAT=y CONFIG_HVCS=m CONFIG_VIRTIO_CONSOLE=m CONFIG_IBM_BSR=m diff --git a/arch/powerpc/include/asm/firmware.h b/arch/powerpc/include/asm/firmware.h index 681bc0314b6b..e05808a328db 100644 --- a/arch/powerpc/include/asm/firmware.h +++ b/arch/powerpc/include/asm/firmware.h @@ -42,7 +42,7 @@ #define FW_FEATURE_SPLPAR ASM_CONST(0x0000000000100000) #define FW_FEATURE_LPAR ASM_CONST(0x0000000000400000) #define FW_FEATURE_PS3_LV1 ASM_CONST(0x0000000000800000) -#define FW_FEATURE_BEAT ASM_CONST(0x0000000001000000) +/* Free ASM_CONST(0x0000000001000000) */ #define FW_FEATURE_CMO ASM_CONST(0x0000000002000000) #define FW_FEATURE_VPHN ASM_CONST(0x0000000004000000) #define FW_FEATURE_XCMO ASM_CONST(0x0000000008000000) @@ -75,8 +75,6 @@ enum { FW_FEATURE_POWERNV_ALWAYS = 0, FW_FEATURE_PS3_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1, FW_FEATURE_PS3_ALWAYS = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1, - FW_FEATURE_CELLEB_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_BEAT, - FW_FEATURE_CELLEB_ALWAYS = 0, FW_FEATURE_NATIVE_POSSIBLE = 0, FW_FEATURE_NATIVE_ALWAYS = 0, FW_FEATURE_POSSIBLE = @@ -89,9 +87,6 @@ enum { #ifdef CONFIG_PPC_PS3 FW_FEATURE_PS3_POSSIBLE | #endif -#ifdef CONFIG_PPC_CELLEB - FW_FEATURE_CELLEB_POSSIBLE | -#endif #ifdef CONFIG_PPC_NATIVE FW_FEATURE_NATIVE_ALWAYS | #endif @@ -106,9 +101,6 @@ enum { #ifdef CONFIG_PPC_PS3 FW_FEATURE_PS3_ALWAYS & #endif -#ifdef CONFIG_PPC_CELLEB - FW_FEATURE_CELLEB_ALWAYS & -#endif #ifdef CONFIG_PPC_NATIVE FW_FEATURE_NATIVE_ALWAYS & #endif diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h index d607df5081a7..7c19959cd705 100644 --- a/arch/powerpc/include/asm/smp.h +++ b/arch/powerpc/include/asm/smp.h @@ -125,7 +125,6 @@ extern irqreturn_t smp_ipi_demux(void); void smp_init_pSeries(void); void smp_init_cell(void); -void smp_init_celleb(void); void smp_setup_cpu_maps(void); extern int __cpu_disable(void); diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c index b7aa07279a63..7cc38b5b58bc 100644 --- a/arch/powerpc/kernel/udbg.c +++ b/arch/powerpc/kernel/udbg.c @@ -46,8 +46,6 @@ void __init udbg_early_init(void) #elif defined(CONFIG_PPC_EARLY_DEBUG_MAPLE) /* Maple real mode debug */ udbg_init_maple_realmode(); -#elif defined(CONFIG_PPC_EARLY_DEBUG_BEAT) - udbg_init_debug_beat(); #elif defined(CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE) udbg_init_pas_realmode(); #elif defined(CONFIG_PPC_EARLY_DEBUG_BOOTX) diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index 391b3f6b54a3..b7f9c408bf24 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig @@ -72,11 +72,6 @@ config PPC_SMP_MUXED_IPI cpu. This will enable the generic code to multiplex the 4 messages on to one ipi. -config PPC_UDBG_BEAT - bool "BEAT based debug console" - depends on PPC_CELLEB - default n - config IPIC bool default n diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig index 870b6dbd4d18..2f23133ab3d1 100644 --- a/arch/powerpc/platforms/cell/Kconfig +++ b/arch/powerpc/platforms/cell/Kconfig @@ -33,17 +33,6 @@ config PPC_IBM_CELL_BLADE select PPC_UDBG_16550 select UDBG_RTAS_CONSOLE -config PPC_CELLEB - bool "Toshiba's Cell Reference Set 'Celleb' Architecture" - depends on PPC64 && PPC_BOOK3S - select PPC_CELL_NATIVE - select PPC_OF_PLATFORM_PCI - select PCI - select HAS_TXX9_SERIAL - select PPC_UDBG_BEAT - select USB_OHCI_BIG_ENDIAN_MMIO - select USB_EHCI_BIG_ENDIAN_MMIO - config PPC_CELL_QPACE bool "IBM Cell - QPACE" depends on PPC64 && PPC_BOOK3S diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile index 2d16884f67b9..34699bddfddd 100644 --- a/arch/powerpc/platforms/cell/Makefile +++ b/arch/powerpc/platforms/cell/Makefile @@ -29,18 +29,3 @@ obj-$(CONFIG_AXON_MSI) += axon_msi.o # qpace setup obj-$(CONFIG_PPC_CELL_QPACE) += qpace_setup.o - -# celleb stuff -ifeq ($(CONFIG_PPC_CELLEB),y) -obj-y += celleb_setup.o \ - celleb_pci.o celleb_scc_epci.o \ - celleb_scc_pciex.o \ - celleb_scc_uhc.o \ - spider-pci.o beat.o beat_htab.o \ - beat_hvCall.o beat_interrupt.o \ - beat_iommu.o - -obj-$(CONFIG_PPC_UDBG_BEAT) += beat_udbg.o -obj-$(CONFIG_SERIAL_TXX9) += celleb_scc_sio.o -obj-$(CONFIG_SPU_BASE) += beat_spu_priv1.o -endif diff --git a/arch/powerpc/platforms/cell/beat.c b/arch/powerpc/platforms/cell/beat.c deleted file mode 100644 index affcf566d460..000000000000 --- a/arch/powerpc/platforms/cell/beat.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Simple routines for Celleb/Beat - * - * (C) Copyright 2006-2007 TOSHIBA 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "beat_wrapper.h" -#include "beat.h" -#include "beat_interrupt.h" - -static int beat_pm_poweroff_flag; - -void beat_restart(char *cmd) -{ - beat_shutdown_logical_partition(!beat_pm_poweroff_flag); -} - -void beat_power_off(void) -{ - beat_shutdown_logical_partition(0); -} - -u64 beat_halt_code = 0x1000000000000000UL; -EXPORT_SYMBOL(beat_halt_code); - -void beat_halt(void) -{ - beat_shutdown_logical_partition(beat_halt_code); -} - -int beat_set_rtc_time(struct rtc_time *rtc_time) -{ - u64 tim; - tim = mktime(rtc_time->tm_year+1900, - rtc_time->tm_mon+1, rtc_time->tm_mday, - rtc_time->tm_hour, rtc_time->tm_min, rtc_time->tm_sec); - if (beat_rtc_write(tim)) - return -1; - return 0; -} - -void beat_get_rtc_time(struct rtc_time *rtc_time) -{ - u64 tim; - - if (beat_rtc_read(&tim)) - tim = 0; - to_tm(tim, rtc_time); - rtc_time->tm_year -= 1900; - rtc_time->tm_mon -= 1; -} - -#define BEAT_NVRAM_SIZE 4096 - -ssize_t beat_nvram_read(char *buf, size_t count, loff_t *index) -{ - unsigned int i; - unsigned long len; - char *p = buf; - - if (*index >= BEAT_NVRAM_SIZE) - return -ENODEV; - i = *index; - if (i + count > BEAT_NVRAM_SIZE) - count = BEAT_NVRAM_SIZE - i; - - for (; count != 0; count -= len) { - len = count; - if (len > BEAT_NVRW_CNT) - len = BEAT_NVRW_CNT; - if (beat_eeprom_read(i, len, p)) - return -EIO; - - p += len; - i += len; - } - *index = i; - return p - buf; -} - -ssize_t beat_nvram_write(char *buf, size_t count, loff_t *index) -{ - unsigned int i; - unsigned long len; - char *p = buf; - - if (*index >= BEAT_NVRAM_SIZE) - return -ENODEV; - i = *index; - if (i + count > BEAT_NVRAM_SIZE) - count = BEAT_NVRAM_SIZE - i; - - for (; count != 0; count -= len) { - len = count; - if (len > BEAT_NVRW_CNT) - len = BEAT_NVRW_CNT; - if (beat_eeprom_write(i, len, p)) - return -EIO; - - p += len; - i += len; - } - *index = i; - return p - buf; -} - -ssize_t beat_nvram_get_size(void) -{ - return BEAT_NVRAM_SIZE; -} - -int beat_set_xdabr(unsigned long dabr, unsigned long dabrx) -{ - if (beat_set_dabr(dabr, dabrx)) - return -1; - return 0; -} - -int64_t beat_get_term_char(u64 vterm, u64 *len, u64 *t1, u64 *t2) -{ - u64 db[2]; - s64 ret; - - ret = beat_get_characters_from_console(vterm, len, (u8 *)db); - if (ret == 0) { - *t1 = db[0]; - *t2 = db[1]; - } - return ret; -} -EXPORT_SYMBOL(beat_get_term_char); - -int64_t beat_put_term_char(u64 vterm, u64 len, u64 t1, u64 t2) -{ - u64 db[2]; - - db[0] = t1; - db[1] = t2; - return beat_put_characters_to_console(vterm, len, (u8 *)db); -} -EXPORT_SYMBOL(beat_put_term_char); - -void beat_power_save(void) -{ - beat_pause(0); -} - -#ifdef CONFIG_KEXEC -void beat_kexec_cpu_down(int crash, int secondary) -{ - beatic_deinit_IRQ(); -} -#endif - -static irqreturn_t beat_power_event(int virq, void *arg) -{ - printk(KERN_DEBUG "Beat: power button pressed\n"); - beat_pm_poweroff_flag = 1; - ctrl_alt_del(); - return IRQ_HANDLED; -} - -static irqreturn_t beat_reset_event(int virq, void *arg) -{ - printk(KERN_DEBUG "Beat: reset button pressed\n"); - beat_pm_poweroff_flag = 0; - ctrl_alt_del(); - return IRQ_HANDLED; -} - -static struct beat_event_list { - const char *typecode; - irq_handler_t handler; - unsigned int virq; -} beat_event_list[] = { - { "power", beat_power_event, 0 }, - { "reset", beat_reset_event, 0 }, -}; - -static int __init beat_register_event(void) -{ - u64 path[4], data[2]; - int rc, i; - unsigned int virq; - - for (i = 0; i < ARRAY_SIZE(beat_event_list); i++) { - struct beat_event_list *ev = &beat_event_list[i]; - - if (beat_construct_event_receive_port(data) != 0) { - printk(KERN_ERR "Beat: " - "cannot construct event receive port for %s\n", - ev->typecode); - return -EINVAL; - } - - virq = irq_create_mapping(NULL, data[0]); - if (virq == NO_IRQ) { - printk(KERN_ERR "Beat: failed to get virtual IRQ" - " for event receive port for %s\n", - ev->typecode); - beat_destruct_event_receive_port(data[0]); - return -EIO; - } - ev->virq = virq; - - rc = request_irq(virq, ev->handler, 0, - ev->typecode, NULL); - if (rc != 0) { - printk(KERN_ERR "Beat: failed to request virtual IRQ" - " for event receive port for %s\n", - ev->typecode); - beat_destruct_event_receive_port(data[0]); - return rc; - } - - path[0] = 0x1000000065780000ul; /* 1,ex */ - path[1] = 0x627574746f6e0000ul; /* button */ - path[2] = 0; - strncpy((char *)&path[2], ev->typecode, 8); - path[3] = 0; - data[1] = 0; - - beat_create_repository_node(path, data); - } - return 0; -} - -static int __init beat_event_init(void) -{ - if (!firmware_has_feature(FW_FEATURE_BEAT)) - return -EINVAL; - - beat_pm_poweroff_flag = 0; - return beat_register_event(); -} - -device_initcall(beat_event_init); diff --git a/arch/powerpc/platforms/cell/beat.h b/arch/powerpc/platforms/cell/beat.h deleted file mode 100644 index bfcb8e351ae5..000000000000 --- a/arch/powerpc/platforms/cell/beat.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Guest OS Interfaces. - * - * (C) Copyright 2006 TOSHIBA 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef _CELLEB_BEAT_H -#define _CELLEB_BEAT_H - -int64_t beat_get_term_char(uint64_t, uint64_t *, uint64_t *, uint64_t *); -int64_t beat_put_term_char(uint64_t, uint64_t, uint64_t, uint64_t); -int64_t beat_repository_encode(int, const char *, uint64_t[4]); -void beat_restart(char *); -void beat_power_off(void); -void beat_halt(void); -int beat_set_rtc_time(struct rtc_time *); -void beat_get_rtc_time(struct rtc_time *); -ssize_t beat_nvram_get_size(void); -ssize_t beat_nvram_read(char *, size_t, loff_t *); -ssize_t beat_nvram_write(char *, size_t, loff_t *); -int beat_set_xdabr(unsigned long, unsigned long); -void beat_power_save(void); -void beat_kexec_cpu_down(int, int); - -#endif /* _CELLEB_BEAT_H */ diff --git a/arch/powerpc/platforms/cell/beat_htab.c b/arch/powerpc/platforms/cell/beat_htab.c deleted file mode 100644 index bee9232fe619..000000000000 --- a/arch/powerpc/platforms/cell/beat_htab.c +++ /dev/null @@ -1,445 +0,0 @@ -/* - * "Cell Reference Set" HTAB support. - * - * (C) Copyright 2006-2007 TOSHIBA CORPORATION - * - * This code is based on arch/powerpc/platforms/pseries/lpar.c: - * Copyright (C) 2001 Todd Inglett, IBM 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#undef DEBUG_LOW - -#include -#include - -#include -#include -#include -#include -#include - -#include "beat_wrapper.h" - -#ifdef DEBUG_LOW -#define DBG_LOW(fmt...) do { udbg_printf(fmt); } while (0) -#else -#define DBG_LOW(fmt...) do { } while (0) -#endif - -static DEFINE_RAW_SPINLOCK(beat_htab_lock); - -static inline unsigned int beat_read_mask(unsigned hpte_group) -{ - unsigned long rmask = 0; - u64 hpte_v[5]; - - beat_read_htab_entries(0, hpte_group + 0, hpte_v); - if (!(hpte_v[0] & HPTE_V_BOLTED)) - rmask |= 0x8000; - if (!(hpte_v[1] & HPTE_V_BOLTED)) - rmask |= 0x4000; - if (!(hpte_v[2] & HPTE_V_BOLTED)) - rmask |= 0x2000; - if (!(hpte_v[3] & HPTE_V_BOLTED)) - rmask |= 0x1000; - beat_read_htab_entries(0, hpte_group + 4, hpte_v); - if (!(hpte_v[0] & HPTE_V_BOLTED)) - rmask |= 0x0800; - if (!(hpte_v[1] & HPTE_V_BOLTED)) - rmask |= 0x0400; - if (!(hpte_v[2] & HPTE_V_BOLTED)) - rmask |= 0x0200; - if (!(hpte_v[3] & HPTE_V_BOLTED)) - rmask |= 0x0100; - hpte_group = ~hpte_group & (htab_hash_mask * HPTES_PER_GROUP); - beat_read_htab_entries(0, hpte_group + 0, hpte_v); - if (!(hpte_v[0] & HPTE_V_BOLTED)) - rmask |= 0x80; - if (!(hpte_v[1] & HPTE_V_BOLTED)) - rmask |= 0x40; - if (!(hpte_v[2] & HPTE_V_BOLTED)) - rmask |= 0x20; - if (!(hpte_v[3] & HPTE_V_BOLTED)) - rmask |= 0x10; - beat_read_htab_entries(0, hpte_group + 4, hpte_v); - if (!(hpte_v[0] & HPTE_V_BOLTED)) - rmask |= 0x08; - if (!(hpte_v[1] & HPTE_V_BOLTED)) - rmask |= 0x04; - if (!(hpte_v[2] & HPTE_V_BOLTED)) - rmask |= 0x02; - if (!(hpte_v[3] & HPTE_V_BOLTED)) - rmask |= 0x01; - return rmask; -} - -static long beat_lpar_hpte_insert(unsigned long hpte_group, - unsigned long vpn, unsigned long pa, - unsigned long rflags, unsigned long vflags, - int psize, int apsize, int ssize) -{ - unsigned long lpar_rc; - u64 hpte_v, hpte_r, slot; - - if (vflags & HPTE_V_SECONDARY) - return -1; - - if (!(vflags & HPTE_V_BOLTED)) - DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, " - "rflags=%lx, vflags=%lx, psize=%d)\n", - hpte_group, va, pa, rflags, vflags, psize); - - hpte_v = hpte_encode_v(vpn, psize, apsize, MMU_SEGSIZE_256M) | - vflags | HPTE_V_VALID; - hpte_r = hpte_encode_r(pa, psize, apsize) | rflags; - - if (!(vflags & HPTE_V_BOLTED)) - DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r); - - if (rflags & _PAGE_NO_CACHE) - hpte_r &= ~HPTE_R_M; - - raw_spin_lock(&beat_htab_lock); - lpar_rc = beat_read_mask(hpte_group); - if (lpar_rc == 0) { - if (!(vflags & HPTE_V_BOLTED)) - DBG_LOW(" full\n"); - raw_spin_unlock(&beat_htab_lock); - return -1; - } - - lpar_rc = beat_insert_htab_entry(0, hpte_group, lpar_rc << 48, - hpte_v, hpte_r, &slot); - raw_spin_unlock(&beat_htab_lock); - - /* - * Since we try and ioremap PHBs we don't own, the pte insert - * will fail. However we must catch the failure in hash_page - * or we will loop forever, so return -2 in this case. - */ - if (unlikely(lpar_rc != 0)) { - if (!(vflags & HPTE_V_BOLTED)) - DBG_LOW(" lpar err %lx\n", lpar_rc); - return -2; - } - if (!(vflags & HPTE_V_BOLTED)) - DBG_LOW(" -> slot: %lx\n", slot); - - /* We have to pass down the secondary bucket bit here as well */ - return (slot ^ hpte_group) & 15; -} - -static long beat_lpar_hpte_remove(unsigned long hpte_group) -{ - DBG_LOW("hpte_remove(group=%lx)\n", hpte_group); - return -1; -} - -static unsigned long beat_lpar_hpte_getword0(unsigned long slot) -{ - unsigned long dword0; - unsigned long lpar_rc; - u64 dword[5]; - - lpar_rc = beat_read_htab_entries(0, slot & ~3UL, dword); - - dword0 = dword[slot&3]; - - BUG_ON(lpar_rc != 0); - - return dword0; -} - -static void beat_lpar_hptab_clear(void) -{ - unsigned long size_bytes = 1UL << ppc64_pft_size; - unsigned long hpte_count = size_bytes >> 4; - int i; - u64 dummy0, dummy1; - - /* TODO: Use bulk call */ - for (i = 0; i < hpte_count; i++) - beat_write_htab_entry(0, i, 0, 0, -1UL, -1UL, &dummy0, &dummy1); -} - -/* - * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and - * the low 3 bits of flags happen to line up. So no transform is needed. - * We can probably optimize here and assume the high bits of newpp are - * already zero. For now I am paranoid. - */ -static long beat_lpar_hpte_updatepp(unsigned long slot, - unsigned long newpp, - unsigned long vpn, - int psize, int apsize, - int ssize, unsigned long flags) -{ - unsigned long lpar_rc; - u64 dummy0, dummy1; - unsigned long want_v; - - want_v = hpte_encode_avpn(vpn, psize, MMU_SEGSIZE_256M); - - DBG_LOW(" update: " - "avpnv=%016lx, slot=%016lx, psize: %d, newpp %016lx ... ", - want_v & HPTE_V_AVPN, slot, psize, newpp); - - raw_spin_lock(&beat_htab_lock); - dummy0 = beat_lpar_hpte_getword0(slot); - if ((dummy0 & ~0x7FUL) != (want_v & ~0x7FUL)) { - DBG_LOW("not found !\n"); - raw_spin_unlock(&beat_htab_lock); - return -1; - } - - lpar_rc = beat_write_htab_entry(0, slot, 0, newpp, 0, 7, &dummy0, - &dummy1); - raw_spin_unlock(&beat_htab_lock); - if (lpar_rc != 0 || dummy0 == 0) { - DBG_LOW("not found !\n"); - return -1; - } - - DBG_LOW("ok %lx %lx\n", dummy0, dummy1); - - BUG_ON(lpar_rc != 0); - - return 0; -} - -static long beat_lpar_hpte_find(unsigned long vpn, int psize) -{ - unsigned long hash; - unsigned long i, j; - long slot; - unsigned long want_v, hpte_v; - - hash = hpt_hash(vpn, mmu_psize_defs[psize].shift, MMU_SEGSIZE_256M); - want_v = hpte_encode_avpn(vpn, psize, MMU_SEGSIZE_256M); - - for (j = 0; j < 2; j++) { - slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; - for (i = 0; i < HPTES_PER_GROUP; i++) { - hpte_v = beat_lpar_hpte_getword0(slot); - - if (HPTE_V_COMPARE(hpte_v, want_v) - && (hpte_v & HPTE_V_VALID) - && (!!(hpte_v & HPTE_V_SECONDARY) == j)) { - /* HPTE matches */ - if (j) - slot = -slot; - return slot; - } - ++slot; - } - hash = ~hash; - } - - return -1; -} - -static void beat_lpar_hpte_updateboltedpp(unsigned long newpp, - unsigned long ea, - int psize, int ssize) -{ - unsigned long vpn; - unsigned long lpar_rc, slot, vsid; - u64 dummy0, dummy1; - - vsid = get_kernel_vsid(ea, MMU_SEGSIZE_256M); - vpn = hpt_vpn(ea, vsid, MMU_SEGSIZE_256M); - - raw_spin_lock(&beat_htab_lock); - slot = beat_lpar_hpte_find(vpn, psize); - BUG_ON(slot == -1); - - lpar_rc = beat_write_htab_entry(0, slot, 0, newpp, 0, 7, - &dummy0, &dummy1); - raw_spin_unlock(&beat_htab_lock); - - BUG_ON(lpar_rc != 0); -} - -static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long vpn, - int psize, int apsize, - int ssize, int local) -{ - unsigned long want_v; - unsigned long lpar_rc; - u64 dummy1, dummy2; - unsigned long flags; - - DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d\n", - slot, va, psize, local); - want_v = hpte_encode_avpn(vpn, psize, MMU_SEGSIZE_256M); - - raw_spin_lock_irqsave(&beat_htab_lock, flags); - dummy1 = beat_lpar_hpte_getword0(slot); - - if ((dummy1 & ~0x7FUL) != (want_v & ~0x7FUL)) { - DBG_LOW("not found !\n"); - raw_spin_unlock_irqrestore(&beat_htab_lock, flags); - return; - } - - lpar_rc = beat_write_htab_entry(0, slot, 0, 0, HPTE_V_VALID, 0, - &dummy1, &dummy2); - raw_spin_unlock_irqrestore(&beat_htab_lock, flags); - - BUG_ON(lpar_rc != 0); -} - -void __init hpte_init_beat(void) -{ - ppc_md.hpte_invalidate = beat_lpar_hpte_invalidate; - ppc_md.hpte_updatepp = beat_lpar_hpte_updatepp; - ppc_md.hpte_updateboltedpp = beat_lpar_hpte_updateboltedpp; - ppc_md.hpte_insert = beat_lpar_hpte_insert; - ppc_md.hpte_remove = beat_lpar_hpte_remove; - ppc_md.hpte_clear_all = beat_lpar_hptab_clear; -} - -static long beat_lpar_hpte_insert_v3(unsigned long hpte_group, - unsigned long vpn, unsigned long pa, - unsigned long rflags, unsigned long vflags, - int psize, int apsize, int ssize) -{ - unsigned long lpar_rc; - u64 hpte_v, hpte_r, slot; - - if (vflags & HPTE_V_SECONDARY) - return -1; - - if (!(vflags & HPTE_V_BOLTED)) - DBG_LOW("hpte_insert(group=%lx, vpn=%016lx, pa=%016lx, " - "rflags=%lx, vflags=%lx, psize=%d)\n", - hpte_group, vpn, pa, rflags, vflags, psize); - - hpte_v = hpte_encode_v(vpn, psize, apsize, MMU_SEGSIZE_256M) | - vflags | HPTE_V_VALID; - hpte_r = hpte_encode_r(pa, psize, apsize) | rflags; - - if (!(vflags & HPTE_V_BOLTED)) - DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r); - - if (rflags & _PAGE_NO_CACHE) - hpte_r &= ~HPTE_R_M; - - /* insert into not-volted entry */ - lpar_rc = beat_insert_htab_entry3(0, hpte_group, hpte_v, hpte_r, - HPTE_V_BOLTED, 0, &slot); - /* - * Since we try and ioremap PHBs we don't own, the pte insert - * will fail. However we must catch the failure in hash_page - * or we will loop forever, so return -2 in this case. - */ - if (unlikely(lpar_rc != 0)) { - if (!(vflags & HPTE_V_BOLTED)) - DBG_LOW(" lpar err %lx\n", lpar_rc); - return -2; - } - if (!(vflags & HPTE_V_BOLTED)) - DBG_LOW(" -> slot: %lx\n", slot); - - /* We have to pass down the secondary bucket bit here as well */ - return (slot ^ hpte_group) & 15; -} - -/* - * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and - * the low 3 bits of flags happen to line up. So no transform is needed. - * We can probably optimize here and assume the high bits of newpp are - * already zero. For now I am paranoid. - */ -static long beat_lpar_hpte_updatepp_v3(unsigned long slot, - unsigned long newpp, - unsigned long vpn, - int psize, int apsize, - int ssize, unsigned long flags) -{ - unsigned long lpar_rc; - unsigned long want_v; - unsigned long pss; - - want_v = hpte_encode_avpn(vpn, psize, MMU_SEGSIZE_256M); - pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc[psize]; - - DBG_LOW(" update: " - "avpnv=%016lx, slot=%016lx, psize: %d, newpp %016lx ... ", - want_v & HPTE_V_AVPN, slot, psize, newpp); - - lpar_rc = beat_update_htab_permission3(0, slot, want_v, pss, 7, newpp); - - if (lpar_rc == 0xfffffff7) { - DBG_LOW("not found !\n"); - return -1; - } - - DBG_LOW("ok\n"); - - BUG_ON(lpar_rc != 0); - - return 0; -} - -static void beat_lpar_hpte_invalidate_v3(unsigned long slot, unsigned long vpn, - int psize, int apsize, - int ssize, int local) -{ - unsigned long want_v; - unsigned long lpar_rc; - unsigned long pss; - - DBG_LOW(" inval : slot=%lx, vpn=%016lx, psize: %d, local: %d\n", - slot, vpn, psize, local); - want_v = hpte_encode_avpn(vpn, psize, MMU_SEGSIZE_256M); - pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc[psize]; - - lpar_rc = beat_invalidate_htab_entry3(0, slot, want_v, pss); - - /* E_busy can be valid output: page may be already replaced */ - BUG_ON(lpar_rc != 0 && lpar_rc != 0xfffffff7); -} - -static int64_t _beat_lpar_hptab_clear_v3(void) -{ - return beat_clear_htab3(0); -} - -static void beat_lpar_hptab_clear_v3(void) -{ - _beat_lpar_hptab_clear_v3(); -} - -void __init hpte_init_beat_v3(void) -{ - if (_beat_lpar_hptab_clear_v3() == 0) { - ppc_md.hpte_invalidate = beat_lpar_hpte_invalidate_v3; - ppc_md.hpte_updatepp = beat_lpar_hpte_updatepp_v3; - ppc_md.hpte_updateboltedpp = beat_lpar_hpte_updateboltedpp; - ppc_md.hpte_insert = beat_lpar_hpte_insert_v3; - ppc_md.hpte_remove = beat_lpar_hpte_remove; - ppc_md.hpte_clear_all = beat_lpar_hptab_clear_v3; - } else { - ppc_md.hpte_invalidate = beat_lpar_hpte_invalidate; - ppc_md.hpte_updatepp = beat_lpar_hpte_updatepp; - ppc_md.hpte_updateboltedpp = beat_lpar_hpte_updateboltedpp; - ppc_md.hpte_insert = beat_lpar_hpte_insert; - ppc_md.hpte_remove = beat_lpar_hpte_remove; - ppc_md.hpte_clear_all = beat_lpar_hptab_clear; - } -} diff --git a/arch/powerpc/platforms/cell/beat_hvCall.S b/arch/powerpc/platforms/cell/beat_hvCall.S deleted file mode 100644 index 96c801907126..000000000000 --- a/arch/powerpc/platforms/cell/beat_hvCall.S +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Beat hypervisor call I/F - * - * (C) Copyright 2007 TOSHIBA CORPORATION - * - * This code is based on arch/powerpc/platforms/pseries/hvCall.S. - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include - -/* Not implemented on Beat, now */ -#define HCALL_INST_PRECALL -#define HCALL_INST_POSTCALL - - .text - -#define HVSC .long 0x44000022 - -/* Note: takes only 7 input parameters at maximum */ -_GLOBAL(beat_hcall_norets) - HMT_MEDIUM - - mfcr r0 - stw r0,8(r1) - - HCALL_INST_PRECALL - - mr r11,r3 - mr r3,r4 - mr r4,r5 - mr r5,r6 - mr r6,r7 - mr r7,r8 - mr r8,r9 - - HVSC /* invoke the hypervisor */ - - HCALL_INST_POSTCALL - - lwz r0,8(r1) - mtcrf 0xff,r0 - - blr /* return r3 = status */ - -/* Note: takes 8 input parameters at maximum */ -_GLOBAL(beat_hcall_norets8) - HMT_MEDIUM - - mfcr r0 - stw r0,8(r1) - - HCALL_INST_PRECALL - - mr r11,r3 - mr r3,r4 - mr r4,r5 - mr r5,r6 - mr r6,r7 - mr r7,r8 - mr r8,r9 - ld r10,STK_PARAM(R10)(r1) - - HVSC /* invoke the hypervisor */ - - HCALL_INST_POSTCALL - - lwz r0,8(r1) - mtcrf 0xff,r0 - - blr /* return r3 = status */ - -/* Note: takes only 6 input parameters, 1 output parameters at maximum */ -_GLOBAL(beat_hcall1) - HMT_MEDIUM - - mfcr r0 - stw r0,8(r1) - - HCALL_INST_PRECALL - - std r4,STK_PARAM(R4)(r1) /* save ret buffer */ - - mr r11,r3 - mr r3,r5 - mr r4,r6 - mr r5,r7 - mr r6,r8 - mr r7,r9 - mr r8,r10 - - HVSC /* invoke the hypervisor */ - - HCALL_INST_POSTCALL - - ld r12,STK_PARAM(R4)(r1) - std r4, 0(r12) - - lwz r0,8(r1) - mtcrf 0xff,r0 - - blr /* return r3 = status */ - -/* Note: takes only 6 input parameters, 2 output parameters at maximum */ -_GLOBAL(beat_hcall2) - HMT_MEDIUM - - mfcr r0 - stw r0,8(r1) - - HCALL_INST_PRECALL - - std r4,STK_PARAM(R4)(r1) /* save ret buffer */ - - mr r11,r3 - mr r3,r5 - mr r4,r6 - mr r5,r7 - mr r6,r8 - mr r7,r9 - mr r8,r10 - - HVSC /* invoke the hypervisor */ - - HCALL_INST_POSTCALL - - ld r12,STK_PARAM(R4)(r1) - std r4, 0(r12) - std r5, 8(r12) - - lwz r0,8(r1) - mtcrf 0xff,r0 - - blr /* return r3 = status */ - -/* Note: takes only 6 input parameters, 3 output parameters at maximum */ -_GLOBAL(beat_hcall3) - HMT_MEDIUM - - mfcr r0 - stw r0,8(r1) - - HCALL_INST_PRECALL - - std r4,STK_PARAM(R4)(r1) /* save ret buffer */ - - mr r11,r3 - mr r3,r5 - mr r4,r6 - mr r5,r7 - mr r6,r8 - mr r7,r9 - mr r8,r10 - - HVSC /* invoke the hypervisor */ - - HCALL_INST_POSTCALL - - ld r12,STK_PARAM(R4)(r1) - std r4, 0(r12) - std r5, 8(r12) - std r6, 16(r12) - - lwz r0,8(r1) - mtcrf 0xff,r0 - - blr /* return r3 = status */ - -/* Note: takes only 6 input parameters, 4 output parameters at maximum */ -_GLOBAL(beat_hcall4) - HMT_MEDIUM - - mfcr r0 - stw r0,8(r1) - - HCALL_INST_PRECALL - - std r4,STK_PARAM(R4)(r1) /* save ret buffer */ - - mr r11,r3 - mr r3,r5 - mr r4,r6 - mr r5,r7 - mr r6,r8 - mr r7,r9 - mr r8,r10 - - HVSC /* invoke the hypervisor */ - - HCALL_INST_POSTCALL - - ld r12,STK_PARAM(R4)(r1) - std r4, 0(r12) - std r5, 8(r12) - std r6, 16(r12) - std r7, 24(r12) - - lwz r0,8(r1) - mtcrf 0xff,r0 - - blr /* return r3 = status */ - -/* Note: takes only 6 input parameters, 5 output parameters at maximum */ -_GLOBAL(beat_hcall5) - HMT_MEDIUM - - mfcr r0 - stw r0,8(r1) - - HCALL_INST_PRECALL - - std r4,STK_PARAM(R4)(r1) /* save ret buffer */ - - mr r11,r3 - mr r3,r5 - mr r4,r6 - mr r5,r7 - mr r6,r8 - mr r7,r9 - mr r8,r10 - - HVSC /* invoke the hypervisor */ - - HCALL_INST_POSTCALL - - ld r12,STK_PARAM(R4)(r1) - std r4, 0(r12) - std r5, 8(r12) - std r6, 16(r12) - std r7, 24(r12) - std r8, 32(r12) - - lwz r0,8(r1) - mtcrf 0xff,r0 - - blr /* return r3 = status */ - -/* Note: takes only 6 input parameters, 6 output parameters at maximum */ -_GLOBAL(beat_hcall6) - HMT_MEDIUM - - mfcr r0 - stw r0,8(r1) - - HCALL_INST_PRECALL - - std r4,STK_PARAM(R4)(r1) /* save ret buffer */ - - mr r11,r3 - mr r3,r5 - mr r4,r6 - mr r5,r7 - mr r6,r8 - mr r7,r9 - mr r8,r10 - - HVSC /* invoke the hypervisor */ - - HCALL_INST_POSTCALL - - ld r12,STK_PARAM(R4)(r1) - std r4, 0(r12) - std r5, 8(r12) - std r6, 16(r12) - std r7, 24(r12) - std r8, 32(r12) - std r9, 40(r12) - - lwz r0,8(r1) - mtcrf 0xff,r0 - - blr /* return r3 = status */ diff --git a/arch/powerpc/platforms/cell/beat_interrupt.c b/arch/powerpc/platforms/cell/beat_interrupt.c deleted file mode 100644 index 9e5dfbcc00af..000000000000 --- a/arch/powerpc/platforms/cell/beat_interrupt.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Celleb/Beat Interrupt controller - * - * (C) Copyright 2006-2007 TOSHIBA 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include -#include -#include -#include - -#include - -#include "beat_interrupt.h" -#include "beat_wrapper.h" - -#define MAX_IRQS NR_IRQS -static DEFINE_RAW_SPINLOCK(beatic_irq_mask_lock); -static uint64_t beatic_irq_mask_enable[(MAX_IRQS+255)/64]; -static uint64_t beatic_irq_mask_ack[(MAX_IRQS+255)/64]; - -static struct irq_domain *beatic_host; - -/* - * In this implementation, "virq" == "IRQ plug number", - * "(irq_hw_number_t)hwirq" == "IRQ outlet number". - */ - -/* assumption: locked */ -static inline void beatic_update_irq_mask(unsigned int irq_plug) -{ - int off; - unsigned long masks[4]; - - off = (irq_plug / 256) * 4; - masks[0] = beatic_irq_mask_enable[off + 0] - & beatic_irq_mask_ack[off + 0]; - masks[1] = beatic_irq_mask_enable[off + 1] - & beatic_irq_mask_ack[off + 1]; - masks[2] = beatic_irq_mask_enable[off + 2] - & beatic_irq_mask_ack[off + 2]; - masks[3] = beatic_irq_mask_enable[off + 3] - & beatic_irq_mask_ack[off + 3]; - if (beat_set_interrupt_mask(irq_plug&~255UL, - masks[0], masks[1], masks[2], masks[3]) != 0) - panic("Failed to set mask IRQ!"); -} - -static void beatic_mask_irq(struct irq_data *d) -{ - unsigned long flags; - - raw_spin_lock_irqsave(&beatic_irq_mask_lock, flags); - beatic_irq_mask_enable[d->irq/64] &= ~(1UL << (63 - (d->irq%64))); - beatic_update_irq_mask(d->irq); - raw_spin_unlock_irqrestore(&beatic_irq_mask_lock, flags); -} - -static void beatic_unmask_irq(struct irq_data *d) -{ - unsigned long flags; - - raw_spin_lock_irqsave(&beatic_irq_mask_lock, flags); - beatic_irq_mask_enable[d->irq/64] |= 1UL << (63 - (d->irq%64)); - beatic_update_irq_mask(d->irq); - raw_spin_unlock_irqrestore(&beatic_irq_mask_lock, flags); -} - -static void beatic_ack_irq(struct irq_data *d) -{ - unsigned long flags; - - raw_spin_lock_irqsave(&beatic_irq_mask_lock, flags); - beatic_irq_mask_ack[d->irq/64] &= ~(1UL << (63 - (d->irq%64))); - beatic_update_irq_mask(d->irq); - raw_spin_unlock_irqrestore(&beatic_irq_mask_lock, flags); -} - -static void beatic_end_irq(struct irq_data *d) -{ - s64 err; - unsigned long flags; - - err = beat_downcount_of_interrupt(d->irq); - if (err != 0) { - if ((err & 0xFFFFFFFF) != 0xFFFFFFF5) /* -11: wrong state */ - panic("Failed to downcount IRQ! Error = %16llx", err); - - printk(KERN_ERR "IRQ over-downcounted, plug %d\n", d->irq); - } - raw_spin_lock_irqsave(&beatic_irq_mask_lock, flags); - beatic_irq_mask_ack[d->irq/64] |= 1UL << (63 - (d->irq%64)); - beatic_update_irq_mask(d->irq); - raw_spin_unlock_irqrestore(&beatic_irq_mask_lock, flags); -} - -static struct irq_chip beatic_pic = { - .name = "CELL-BEAT", - .irq_unmask = beatic_unmask_irq, - .irq_mask = beatic_mask_irq, - .irq_eoi = beatic_end_irq, -}; - -/* - * Dispose binding hardware IRQ number (hw) and Virtuql IRQ number (virq), - * update flags. - * - * Note that the number (virq) is already assigned at upper layer. - */ -static void beatic_pic_host_unmap(struct irq_domain *h, unsigned int virq) -{ - beat_destruct_irq_plug(virq); -} - -/* - * Create or update binding hardware IRQ number (hw) and Virtuql - * IRQ number (virq). This is called only once for a given mapping. - * - * Note that the number (virq) is already assigned at upper layer. - */ -static int beatic_pic_host_map(struct irq_domain *h, unsigned int virq, - irq_hw_number_t hw) -{ - int64_t err; - - err = beat_construct_and_connect_irq_plug(virq, hw); - if (err < 0) - return -EIO; - - irq_set_status_flags(virq, IRQ_LEVEL); - irq_set_chip_and_handler(virq, &beatic_pic, handle_fasteoi_irq); - return 0; -} - -/* - * Translate device-tree interrupt spec to irq_hw_number_t style (ulong), - * to pass away to irq_create_mapping(). - * - * Called from irq_create_of_mapping() only. - * Note: We have only 1 entry to translate. - */ -static int beatic_pic_host_xlate(struct irq_domain *h, struct device_node *ct, - const u32 *intspec, unsigned int intsize, - irq_hw_number_t *out_hwirq, - unsigned int *out_flags) -{ - const u64 *intspec2 = (const u64 *)intspec; - - *out_hwirq = *intspec2; - *out_flags |= IRQ_TYPE_LEVEL_LOW; - return 0; -} - -static int beatic_pic_host_match(struct irq_domain *h, struct device_node *np) -{ - /* Match all */ - return 1; -} - -static const struct irq_domain_ops beatic_pic_host_ops = { - .map = beatic_pic_host_map, - .unmap = beatic_pic_host_unmap, - .xlate = beatic_pic_host_xlate, - .match = beatic_pic_host_match, -}; - -/* - * Get an IRQ number - * Note: returns VIRQ - */ -static inline unsigned int beatic_get_irq_plug(void) -{ - int i; - uint64_t pending[4], ub; - - for (i = 0; i < MAX_IRQS; i += 256) { - beat_detect_pending_interrupts(i, pending); - __asm__ ("cntlzd %0,%1":"=r"(ub): - "r"(pending[0] & beatic_irq_mask_enable[i/64+0] - & beatic_irq_mask_ack[i/64+0])); - if (ub != 64) - return i + ub + 0; - __asm__ ("cntlzd %0,%1":"=r"(ub): - "r"(pending[1] & beatic_irq_mask_enable[i/64+1] - & beatic_irq_mask_ack[i/64+1])); - if (ub != 64) - return i + ub + 64; - __asm__ ("cntlzd %0,%1":"=r"(ub): - "r"(pending[2] & beatic_irq_mask_enable[i/64+2] - & beatic_irq_mask_ack[i/64+2])); - if (ub != 64) - return i + ub + 128; - __asm__ ("cntlzd %0,%1":"=r"(ub): - "r"(pending[3] & beatic_irq_mask_enable[i/64+3] - & beatic_irq_mask_ack[i/64+3])); - if (ub != 64) - return i + ub + 192; - } - - return NO_IRQ; -} -unsigned int beatic_get_irq(void) -{ - unsigned int ret; - - ret = beatic_get_irq_plug(); - if (ret != NO_IRQ) - beatic_ack_irq(irq_get_irq_data(ret)); - return ret; -} - -/* - */ -void __init beatic_init_IRQ(void) -{ - int i; - - memset(beatic_irq_mask_enable, 0, sizeof(beatic_irq_mask_enable)); - memset(beatic_irq_mask_ack, 255, sizeof(beatic_irq_mask_ack)); - for (i = 0; i < MAX_IRQS; i += 256) - beat_set_interrupt_mask(i, 0L, 0L, 0L, 0L); - - /* Set out get_irq function */ - ppc_md.get_irq = beatic_get_irq; - - /* Allocate an irq host */ - beatic_host = irq_domain_add_nomap(NULL, ~0, &beatic_pic_host_ops, NULL); - BUG_ON(beatic_host == NULL); - irq_set_default_host(beatic_host); -} - -void beatic_deinit_IRQ(void) -{ - int i; - - for (i = 1; i < nr_irqs; i++) - beat_destruct_irq_plug(i); -} diff --git a/arch/powerpc/platforms/cell/beat_interrupt.h b/arch/powerpc/platforms/cell/beat_interrupt.h deleted file mode 100644 index a7e52f91a078..000000000000 --- a/arch/powerpc/platforms/cell/beat_interrupt.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Celleb/Beat Interrupt controller - * - * (C) Copyright 2006 TOSHIBA 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef ASM_BEAT_PIC_H -#define ASM_BEAT_PIC_H -#ifdef __KERNEL__ - -extern void beatic_init_IRQ(void); -extern unsigned int beatic_get_irq(void); -extern void beatic_deinit_IRQ(void); - -#endif -#endif /* ASM_BEAT_PIC_H */ diff --git a/arch/powerpc/platforms/cell/beat_iommu.c b/arch/powerpc/platforms/cell/beat_iommu.c deleted file mode 100644 index 3ce685568935..000000000000 --- a/arch/powerpc/platforms/cell/beat_iommu.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Support for IOMMU on Celleb platform. - * - * (C) Copyright 2006-2007 TOSHIBA 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include -#include -#include -#include - -#include - -#include "beat_wrapper.h" - -#define DMA_FLAGS 0xf800000000000000UL /* r/w permitted, coherency required, - strongest order */ - -static int __init find_dma_window(u64 *io_space_id, u64 *ioid, - u64 *base, u64 *size, u64 *io_page_size) -{ - struct device_node *dn; - const unsigned long *dma_window; - - for_each_node_by_type(dn, "ioif") { - dma_window = of_get_property(dn, "toshiba,dma-window", NULL); - if (dma_window) { - *io_space_id = (dma_window[0] >> 32) & 0xffffffffUL; - *ioid = dma_window[0] & 0x7ffUL; - *base = dma_window[1]; - *size = dma_window[2]; - *io_page_size = 1 << dma_window[3]; - of_node_put(dn); - return 1; - } - } - return 0; -} - -static unsigned long celleb_dma_direct_offset; - -static void __init celleb_init_direct_mapping(void) -{ - u64 lpar_addr, io_addr; - u64 io_space_id, ioid, dma_base, dma_size, io_page_size; - - if (!find_dma_window(&io_space_id, &ioid, &dma_base, &dma_size, - &io_page_size)) { - pr_info("No dma window found !\n"); - return; - } - - for (lpar_addr = 0; lpar_addr < dma_size; lpar_addr += io_page_size) { - io_addr = lpar_addr + dma_base; - (void)beat_put_iopte(io_space_id, io_addr, lpar_addr, - ioid, DMA_FLAGS); - } - - celleb_dma_direct_offset = dma_base; -} - -static void celleb_dma_dev_setup(struct device *dev) -{ - set_dma_ops(dev, &dma_direct_ops); - set_dma_offset(dev, celleb_dma_direct_offset); -} - -static void celleb_pci_dma_dev_setup(struct pci_dev *pdev) -{ - celleb_dma_dev_setup(&pdev->dev); -} - -static int celleb_of_bus_notify(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct device *dev = data; - - /* We are only intereted in device addition */ - if (action != BUS_NOTIFY_ADD_DEVICE) - return 0; - - celleb_dma_dev_setup(dev); - - return 0; -} - -static struct notifier_block celleb_of_bus_notifier = { - .notifier_call = celleb_of_bus_notify -}; - -static int __init celleb_init_iommu(void) -{ - celleb_init_direct_mapping(); - ppc_md.pci_dma_dev_setup = celleb_pci_dma_dev_setup; - bus_register_notifier(&platform_bus_type, &celleb_of_bus_notifier); - - return 0; -} - -machine_arch_initcall(celleb_beat, celleb_init_iommu); diff --git a/arch/powerpc/platforms/cell/beat_spu_priv1.c b/arch/powerpc/platforms/cell/beat_spu_priv1.c deleted file mode 100644 index 13f52589d3a9..000000000000 --- a/arch/powerpc/platforms/cell/beat_spu_priv1.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * spu hypervisor abstraction for Beat - * - * (C) Copyright 2006-2007 TOSHIBA 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include -#include - -#include "beat_wrapper.h" - -static inline void _int_mask_set(struct spu *spu, int class, u64 mask) -{ - spu->shadow_int_mask_RW[class] = mask; - beat_set_irq_mask_for_spe(spu->spe_id, class, mask); -} - -static inline u64 _int_mask_get(struct spu *spu, int class) -{ - return spu->shadow_int_mask_RW[class]; -} - -static void int_mask_set(struct spu *spu, int class, u64 mask) -{ - _int_mask_set(spu, class, mask); -} - -static u64 int_mask_get(struct spu *spu, int class) -{ - return _int_mask_get(spu, class); -} - -static void int_mask_and(struct spu *spu, int class, u64 mask) -{ - u64 old_mask; - old_mask = _int_mask_get(spu, class); - _int_mask_set(spu, class, old_mask & mask); -} - -static void int_mask_or(struct spu *spu, int class, u64 mask) -{ - u64 old_mask; - old_mask = _int_mask_get(spu, class); - _int_mask_set(spu, class, old_mask | mask); -} - -static void int_stat_clear(struct spu *spu, int class, u64 stat) -{ - beat_clear_interrupt_status_of_spe(spu->spe_id, class, stat); -} - -static u64 int_stat_get(struct spu *spu, int class) -{ - u64 int_stat; - beat_get_interrupt_status_of_spe(spu->spe_id, class, &int_stat); - return int_stat; -} - -static void cpu_affinity_set(struct spu *spu, int cpu) -{ - return; -} - -static u64 mfc_dar_get(struct spu *spu) -{ - u64 dar; - beat_get_spe_privileged_state_1_registers( - spu->spe_id, - offsetof(struct spu_priv1, mfc_dar_RW), &dar); - return dar; -} - -static u64 mfc_dsisr_get(struct spu *spu) -{ - u64 dsisr; - beat_get_spe_privileged_state_1_registers( - spu->spe_id, - offsetof(struct spu_priv1, mfc_dsisr_RW), &dsisr); - return dsisr; -} - -static void mfc_dsisr_set(struct spu *spu, u64 dsisr) -{ - beat_set_spe_privileged_state_1_registers( - spu->spe_id, - offsetof(struct spu_priv1, mfc_dsisr_RW), dsisr); -} - -static void mfc_sdr_setup(struct spu *spu) -{ - return; -} - -static void mfc_sr1_set(struct spu *spu, u64 sr1) -{ - beat_set_spe_privileged_state_1_registers( - spu->spe_id, - offsetof(struct spu_priv1, mfc_sr1_RW), sr1); -} - -static u64 mfc_sr1_get(struct spu *spu) -{ - u64 sr1; - beat_get_spe_privileged_state_1_registers( - spu->spe_id, - offsetof(struct spu_priv1, mfc_sr1_RW), &sr1); - return sr1; -} - -static void mfc_tclass_id_set(struct spu *spu, u64 tclass_id) -{ - beat_set_spe_privileged_state_1_registers( - spu->spe_id, - offsetof(struct spu_priv1, mfc_tclass_id_RW), tclass_id); -} - -static u64 mfc_tclass_id_get(struct spu *spu) -{ - u64 tclass_id; - beat_get_spe_privileged_state_1_registers( - spu->spe_id, - offsetof(struct spu_priv1, mfc_tclass_id_RW), &tclass_id); - return tclass_id; -} - -static void tlb_invalidate(struct spu *spu) -{ - beat_set_spe_privileged_state_1_registers( - spu->spe_id, - offsetof(struct spu_priv1, tlb_invalidate_entry_W), 0ul); -} - -static void resource_allocation_groupID_set(struct spu *spu, u64 id) -{ - beat_set_spe_privileged_state_1_registers( - spu->spe_id, - offsetof(struct spu_priv1, resource_allocation_groupID_RW), - id); -} - -static u64 resource_allocation_groupID_get(struct spu *spu) -{ - u64 id; - beat_get_spe_privileged_state_1_registers( - spu->spe_id, - offsetof(struct spu_priv1, resource_allocation_groupID_RW), - &id); - return id; -} - -static void resource_allocation_enable_set(struct spu *spu, u64 enable) -{ - beat_set_spe_privileged_state_1_registers( - spu->spe_id, - offsetof(struct spu_priv1, resource_allocation_enable_RW), - enable); -} - -static u64 resource_allocation_enable_get(struct spu *spu) -{ - u64 enable; - beat_get_spe_privileged_state_1_registers( - spu->spe_id, - offsetof(struct spu_priv1, resource_allocation_enable_RW), - &enable); - return enable; -} - -const struct spu_priv1_ops spu_priv1_beat_ops = { - .int_mask_and = int_mask_and, - .int_mask_or = int_mask_or, - .int_mask_set = int_mask_set, - .int_mask_get = int_mask_get, - .int_stat_clear = int_stat_clear, - .int_stat_get = int_stat_get, - .cpu_affinity_set = cpu_affinity_set, - .mfc_dar_get = mfc_dar_get, - .mfc_dsisr_get = mfc_dsisr_get, - .mfc_dsisr_set = mfc_dsisr_set, - .mfc_sdr_setup = mfc_sdr_setup, - .mfc_sr1_set = mfc_sr1_set, - .mfc_sr1_get = mfc_sr1_get, - .mfc_tclass_id_set = mfc_tclass_id_set, - .mfc_tclass_id_get = mfc_tclass_id_get, - .tlb_invalidate = tlb_invalidate, - .resource_allocation_groupID_set = resource_allocation_groupID_set, - .resource_allocation_groupID_get = resource_allocation_groupID_get, - .resource_allocation_enable_set = resource_allocation_enable_set, - .resource_allocation_enable_get = resource_allocation_enable_get, -}; diff --git a/arch/powerpc/platforms/cell/beat_syscall.h b/arch/powerpc/platforms/cell/beat_syscall.h deleted file mode 100644 index 8580dc7e1798..000000000000 --- a/arch/powerpc/platforms/cell/beat_syscall.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Beat hypervisor call numbers - * - * (C) Copyright 2004-2007 TOSHIBA 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef BEAT_BEAT_syscall_H -#define BEAT_BEAT_syscall_H - -#ifdef __ASSEMBLY__ -#define __BEAT_ADD_VENDOR_ID(__x, __v) ((__v)<<60|(__x)) -#else -#define __BEAT_ADD_VENDOR_ID(__x, __v) ((u64)(__v)<<60|(__x)) -#endif -#define HV_allocate_memory __BEAT_ADD_VENDOR_ID(0, 0) -#define HV_construct_virtual_address_space __BEAT_ADD_VENDOR_ID(2, 0) -#define HV_destruct_virtual_address_space __BEAT_ADD_VENDOR_ID(10, 0) -#define HV_get_virtual_address_space_id_of_ppe __BEAT_ADD_VENDOR_ID(4, 0) -#define HV_query_logical_partition_address_region_info \ - __BEAT_ADD_VENDOR_ID(6, 0) -#define HV_release_memory __BEAT_ADD_VENDOR_ID(13, 0) -#define HV_select_virtual_address_space __BEAT_ADD_VENDOR_ID(7, 0) -#define HV_load_range_registers __BEAT_ADD_VENDOR_ID(68, 0) -#define HV_set_ppe_l2cache_rmt_entry __BEAT_ADD_VENDOR_ID(70, 0) -#define HV_set_ppe_tlb_rmt_entry __BEAT_ADD_VENDOR_ID(71, 0) -#define HV_set_spe_tlb_rmt_entry __BEAT_ADD_VENDOR_ID(72, 0) -#define HV_get_io_address_translation_fault_info __BEAT_ADD_VENDOR_ID(14, 0) -#define HV_get_iopte __BEAT_ADD_VENDOR_ID(16, 0) -#define HV_preload_iopt_cache __BEAT_ADD_VENDOR_ID(17, 0) -#define HV_put_iopte __BEAT_ADD_VENDOR_ID(15, 0) -#define HV_connect_event_ports __BEAT_ADD_VENDOR_ID(21, 0) -#define HV_construct_event_receive_port __BEAT_ADD_VENDOR_ID(18, 0) -#define HV_destruct_event_receive_port __BEAT_ADD_VENDOR_ID(19, 0) -#define HV_destruct_event_send_port __BEAT_ADD_VENDOR_ID(22, 0) -#define HV_get_state_of_event_send_port __BEAT_ADD_VENDOR_ID(25, 0) -#define HV_request_to_connect_event_ports __BEAT_ADD_VENDOR_ID(20, 0) -#define HV_send_event_externally __BEAT_ADD_VENDOR_ID(23, 0) -#define HV_send_event_locally __BEAT_ADD_VENDOR_ID(24, 0) -#define HV_construct_and_connect_irq_plug __BEAT_ADD_VENDOR_ID(28, 0) -#define HV_destruct_irq_plug __BEAT_ADD_VENDOR_ID(29, 0) -#define HV_detect_pending_interrupts __BEAT_ADD_VENDOR_ID(26, 0) -#define HV_end_of_interrupt __BEAT_ADD_VENDOR_ID(27, 0) -#define HV_assign_control_signal_notification_port __BEAT_ADD_VENDOR_ID(45, 0) -#define HV_end_of_control_signal_processing __BEAT_ADD_VENDOR_ID(48, 0) -#define HV_get_control_signal __BEAT_ADD_VENDOR_ID(46, 0) -#define HV_set_irq_mask_for_spe __BEAT_ADD_VENDOR_ID(61, 0) -#define HV_shutdown_logical_partition __BEAT_ADD_VENDOR_ID(44, 0) -#define HV_connect_message_ports __BEAT_ADD_VENDOR_ID(35, 0) -#define HV_destruct_message_port __BEAT_ADD_VENDOR_ID(36, 0) -#define HV_receive_message __BEAT_ADD_VENDOR_ID(37, 0) -#define HV_get_message_port_info __BEAT_ADD_VENDOR_ID(34, 0) -#define HV_request_to_connect_message_ports __BEAT_ADD_VENDOR_ID(33, 0) -#define HV_send_message __BEAT_ADD_VENDOR_ID(32, 0) -#define HV_get_logical_ppe_id __BEAT_ADD_VENDOR_ID(69, 0) -#define HV_pause __BEAT_ADD_VENDOR_ID(9, 0) -#define HV_destruct_shared_memory_handle __BEAT_ADD_VENDOR_ID(51, 0) -#define HV_get_shared_memory_info __BEAT_ADD_VENDOR_ID(52, 0) -#define HV_permit_sharing_memory __BEAT_ADD_VENDOR_ID(50, 0) -#define HV_request_to_attach_shared_memory __BEAT_ADD_VENDOR_ID(49, 0) -#define HV_enable_logical_spe_execution __BEAT_ADD_VENDOR_ID(55, 0) -#define HV_construct_logical_spe __BEAT_ADD_VENDOR_ID(53, 0) -#define HV_disable_logical_spe_execution __BEAT_ADD_VENDOR_ID(56, 0) -#define HV_destruct_logical_spe __BEAT_ADD_VENDOR_ID(54, 0) -#define HV_sense_spe_execution_status __BEAT_ADD_VENDOR_ID(58, 0) -#define HV_insert_htab_entry __BEAT_ADD_VENDOR_ID(101, 0) -#define HV_read_htab_entries __BEAT_ADD_VENDOR_ID(95, 0) -#define HV_write_htab_entry __BEAT_ADD_VENDOR_ID(94, 0) -#define HV_assign_io_address_translation_fault_port \ - __BEAT_ADD_VENDOR_ID(100, 0) -#define HV_set_interrupt_mask __BEAT_ADD_VENDOR_ID(73, 0) -#define HV_get_logical_partition_id __BEAT_ADD_VENDOR_ID(74, 0) -#define HV_create_repository_node2 __BEAT_ADD_VENDOR_ID(90, 0) -#define HV_create_repository_node __BEAT_ADD_VENDOR_ID(90, 0) /* alias */ -#define HV_get_repository_node_value2 __BEAT_ADD_VENDOR_ID(91, 0) -#define HV_get_repository_node_value __BEAT_ADD_VENDOR_ID(91, 0) /* alias */ -#define HV_modify_repository_node_value2 __BEAT_ADD_VENDOR_ID(92, 0) -#define HV_modify_repository_node_value __BEAT_ADD_VENDOR_ID(92, 0) /* alias */ -#define HV_remove_repository_node2 __BEAT_ADD_VENDOR_ID(93, 0) -#define HV_remove_repository_node __BEAT_ADD_VENDOR_ID(93, 0) /* alias */ -#define HV_cancel_shared_memory __BEAT_ADD_VENDOR_ID(104, 0) -#define HV_clear_interrupt_status_of_spe __BEAT_ADD_VENDOR_ID(206, 0) -#define HV_construct_spe_irq_outlet __BEAT_ADD_VENDOR_ID(80, 0) -#define HV_destruct_spe_irq_outlet __BEAT_ADD_VENDOR_ID(81, 0) -#define HV_disconnect_ipspc_service __BEAT_ADD_VENDOR_ID(88, 0) -#define HV_execute_ipspc_command __BEAT_ADD_VENDOR_ID(86, 0) -#define HV_get_interrupt_status_of_spe __BEAT_ADD_VENDOR_ID(205, 0) -#define HV_get_spe_privileged_state_1_registers __BEAT_ADD_VENDOR_ID(208, 0) -#define HV_permit_use_of_ipspc_service __BEAT_ADD_VENDOR_ID(85, 0) -#define HV_reinitialize_logical_spe __BEAT_ADD_VENDOR_ID(82, 0) -#define HV_request_ipspc_service __BEAT_ADD_VENDOR_ID(84, 0) -#define HV_stop_ipspc_command __BEAT_ADD_VENDOR_ID(87, 0) -#define HV_set_spe_privileged_state_1_registers __BEAT_ADD_VENDOR_ID(204, 0) -#define HV_get_status_of_ipspc_service __BEAT_ADD_VENDOR_ID(203, 0) -#define HV_put_characters_to_console __BEAT_ADD_VENDOR_ID(0x101, 1) -#define HV_get_characters_from_console __BEAT_ADD_VENDOR_ID(0x102, 1) -#define HV_get_base_clock __BEAT_ADD_VENDOR_ID(0x111, 1) -#define HV_set_base_clock __BEAT_ADD_VENDOR_ID(0x112, 1) -#define HV_get_frame_cycle __BEAT_ADD_VENDOR_ID(0x114, 1) -#define HV_disable_console __BEAT_ADD_VENDOR_ID(0x115, 1) -#define HV_disable_all_console __BEAT_ADD_VENDOR_ID(0x116, 1) -#define HV_oneshot_timer __BEAT_ADD_VENDOR_ID(0x117, 1) -#define HV_set_dabr __BEAT_ADD_VENDOR_ID(0x118, 1) -#define HV_get_dabr __BEAT_ADD_VENDOR_ID(0x119, 1) -#define HV_start_hv_stats __BEAT_ADD_VENDOR_ID(0x21c, 1) -#define HV_stop_hv_stats __BEAT_ADD_VENDOR_ID(0x21d, 1) -#define HV_get_hv_stats __BEAT_ADD_VENDOR_ID(0x21e, 1) -#define HV_get_hv_error_stats __BEAT_ADD_VENDOR_ID(0x221, 1) -#define HV_get_stats __BEAT_ADD_VENDOR_ID(0x224, 1) -#define HV_get_heap_stats __BEAT_ADD_VENDOR_ID(0x225, 1) -#define HV_get_memory_stats __BEAT_ADD_VENDOR_ID(0x227, 1) -#define HV_get_memory_detail __BEAT_ADD_VENDOR_ID(0x228, 1) -#define HV_set_priority_of_irq_outlet __BEAT_ADD_VENDOR_ID(0x122, 1) -#define HV_get_physical_spe_by_reservation_id __BEAT_ADD_VENDOR_ID(0x128, 1) -#define HV_get_spe_context __BEAT_ADD_VENDOR_ID(0x129, 1) -#define HV_set_spe_context __BEAT_ADD_VENDOR_ID(0x12a, 1) -#define HV_downcount_of_interrupt __BEAT_ADD_VENDOR_ID(0x12e, 1) -#define HV_peek_spe_context __BEAT_ADD_VENDOR_ID(0x12f, 1) -#define HV_read_bpa_register __BEAT_ADD_VENDOR_ID(0x131, 1) -#define HV_write_bpa_register __BEAT_ADD_VENDOR_ID(0x132, 1) -#define HV_map_context_table_of_spe __BEAT_ADD_VENDOR_ID(0x137, 1) -#define HV_get_slb_for_logical_spe __BEAT_ADD_VENDOR_ID(0x138, 1) -#define HV_set_slb_for_logical_spe __BEAT_ADD_VENDOR_ID(0x139, 1) -#define HV_init_pm __BEAT_ADD_VENDOR_ID(0x150, 1) -#define HV_set_pm_signal __BEAT_ADD_VENDOR_ID(0x151, 1) -#define HV_get_pm_signal __BEAT_ADD_VENDOR_ID(0x152, 1) -#define HV_set_pm_config __BEAT_ADD_VENDOR_ID(0x153, 1) -#define HV_get_pm_config __BEAT_ADD_VENDOR_ID(0x154, 1) -#define HV_get_inner_trace_data __BEAT_ADD_VENDOR_ID(0x155, 1) -#define HV_set_ext_trace_buffer __BEAT_ADD_VENDOR_ID(0x156, 1) -#define HV_get_ext_trace_buffer __BEAT_ADD_VENDOR_ID(0x157, 1) -#define HV_set_pm_interrupt __BEAT_ADD_VENDOR_ID(0x158, 1) -#define HV_get_pm_interrupt __BEAT_ADD_VENDOR_ID(0x159, 1) -#define HV_kick_pm __BEAT_ADD_VENDOR_ID(0x160, 1) -#define HV_construct_pm_context __BEAT_ADD_VENDOR_ID(0x164, 1) -#define HV_destruct_pm_context __BEAT_ADD_VENDOR_ID(0x165, 1) -#define HV_be_slow __BEAT_ADD_VENDOR_ID(0x170, 1) -#define HV_assign_ipspc_server_connection_status_notification_port \ - __BEAT_ADD_VENDOR_ID(0x173, 1) -#define HV_get_raid_of_physical_spe __BEAT_ADD_VENDOR_ID(0x174, 1) -#define HV_set_physical_spe_to_rag __BEAT_ADD_VENDOR_ID(0x175, 1) -#define HV_release_physical_spe_from_rag __BEAT_ADD_VENDOR_ID(0x176, 1) -#define HV_rtc_read __BEAT_ADD_VENDOR_ID(0x190, 1) -#define HV_rtc_write __BEAT_ADD_VENDOR_ID(0x191, 1) -#define HV_eeprom_read __BEAT_ADD_VENDOR_ID(0x192, 1) -#define HV_eeprom_write __BEAT_ADD_VENDOR_ID(0x193, 1) -#define HV_insert_htab_entry3 __BEAT_ADD_VENDOR_ID(0x104, 1) -#define HV_invalidate_htab_entry3 __BEAT_ADD_VENDOR_ID(0x105, 1) -#define HV_update_htab_permission3 __BEAT_ADD_VENDOR_ID(0x106, 1) -#define HV_clear_htab3 __BEAT_ADD_VENDOR_ID(0x107, 1) -#endif diff --git a/arch/powerpc/platforms/cell/beat_udbg.c b/arch/powerpc/platforms/cell/beat_udbg.c deleted file mode 100644 index 350735bc8888..000000000000 --- a/arch/powerpc/platforms/cell/beat_udbg.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * udbg function for Beat - * - * (C) Copyright 2006 TOSHIBA 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include - -#include -#include -#include - -#include "beat.h" - -#define celleb_vtermno 0 - -static void udbg_putc_beat(char c) -{ - unsigned long rc; - - if (c == '\n') - udbg_putc_beat('\r'); - - rc = beat_put_term_char(celleb_vtermno, 1, (uint64_t)c << 56, 0); -} - -/* Buffered chars getc */ -static u64 inbuflen; -static u64 inbuf[2]; /* must be 2 u64s */ - -static int udbg_getc_poll_beat(void) -{ - /* The interface is tricky because it may return up to 16 chars. - * We save them statically for future calls to udbg_getc(). - */ - char ch, *buf = (char *)inbuf; - int i; - long rc; - if (inbuflen == 0) { - /* get some more chars. */ - inbuflen = 0; - rc = beat_get_term_char(celleb_vtermno, &inbuflen, - inbuf+0, inbuf+1); - if (rc != 0) - inbuflen = 0; /* otherwise inbuflen is garbage */ - } - if (inbuflen <= 0 || inbuflen > 16) { - /* Catch error case as well as other oddities (corruption) */ - inbuflen = 0; - return -1; - } - ch = buf[0]; - for (i = 1; i < inbuflen; i++) /* shuffle them down. */ - buf[i-1] = buf[i]; - inbuflen--; - return ch; -} - -static int udbg_getc_beat(void) -{ - int ch; - for (;;) { - ch = udbg_getc_poll_beat(); - if (ch == -1) { - /* This shouldn't be needed...but... */ - volatile unsigned long delay; - for (delay = 0; delay < 2000000; delay++) - ; - } else { - return ch; - } - } -} - -/* call this from early_init() for a working debug console on - * vterm capable LPAR machines - */ -void __init udbg_init_debug_beat(void) -{ - udbg_putc = udbg_putc_beat; - udbg_getc = udbg_getc_beat; - udbg_getc_poll = udbg_getc_poll_beat; -} diff --git a/arch/powerpc/platforms/cell/beat_wrapper.h b/arch/powerpc/platforms/cell/beat_wrapper.h deleted file mode 100644 index c1109969f242..000000000000 --- a/arch/powerpc/platforms/cell/beat_wrapper.h +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Beat hypervisor call I/F - * - * (C) Copyright 2007 TOSHIBA CORPORATION - * - * This code is based on arch/powerpc/platforms/pseries/plpar_wrapper.h. - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef BEAT_HCALL -#include -#include "beat_syscall.h" - -/* defined in hvCall.S */ -extern s64 beat_hcall_norets(u64 opcode, ...); -extern s64 beat_hcall_norets8(u64 opcode, u64 arg1, u64 arg2, u64 arg3, - u64 arg4, u64 arg5, u64 arg6, u64 arg7, u64 arg8); -extern s64 beat_hcall1(u64 opcode, u64 retbuf[1], ...); -extern s64 beat_hcall2(u64 opcode, u64 retbuf[2], ...); -extern s64 beat_hcall3(u64 opcode, u64 retbuf[3], ...); -extern s64 beat_hcall4(u64 opcode, u64 retbuf[4], ...); -extern s64 beat_hcall5(u64 opcode, u64 retbuf[5], ...); -extern s64 beat_hcall6(u64 opcode, u64 retbuf[6], ...); - -static inline s64 beat_downcount_of_interrupt(u64 plug_id) -{ - return beat_hcall_norets(HV_downcount_of_interrupt, plug_id); -} - -static inline s64 beat_set_interrupt_mask(u64 index, - u64 val0, u64 val1, u64 val2, u64 val3) -{ - return beat_hcall_norets(HV_set_interrupt_mask, index, - val0, val1, val2, val3); -} - -static inline s64 beat_destruct_irq_plug(u64 plug_id) -{ - return beat_hcall_norets(HV_destruct_irq_plug, plug_id); -} - -static inline s64 beat_construct_and_connect_irq_plug(u64 plug_id, - u64 outlet_id) -{ - return beat_hcall_norets(HV_construct_and_connect_irq_plug, plug_id, - outlet_id); -} - -static inline s64 beat_detect_pending_interrupts(u64 index, u64 *retbuf) -{ - return beat_hcall4(HV_detect_pending_interrupts, retbuf, index); -} - -static inline s64 beat_pause(u64 style) -{ - return beat_hcall_norets(HV_pause, style); -} - -static inline s64 beat_read_htab_entries(u64 htab_id, u64 index, u64 *retbuf) -{ - return beat_hcall5(HV_read_htab_entries, retbuf, htab_id, index); -} - -static inline s64 beat_insert_htab_entry(u64 htab_id, u64 group, - u64 bitmask, u64 hpte_v, u64 hpte_r, u64 *slot) -{ - u64 dummy[3]; - s64 ret; - - ret = beat_hcall3(HV_insert_htab_entry, dummy, htab_id, group, - bitmask, hpte_v, hpte_r); - *slot = dummy[0]; - return ret; -} - -static inline s64 beat_write_htab_entry(u64 htab_id, u64 slot, - u64 hpte_v, u64 hpte_r, u64 mask_v, u64 mask_r, - u64 *ret_v, u64 *ret_r) -{ - u64 dummy[2]; - s64 ret; - - ret = beat_hcall2(HV_write_htab_entry, dummy, htab_id, slot, - hpte_v, hpte_r, mask_v, mask_r); - *ret_v = dummy[0]; - *ret_r = dummy[1]; - return ret; -} - -static inline s64 beat_insert_htab_entry3(u64 htab_id, u64 group, - u64 hpte_v, u64 hpte_r, u64 mask_v, u64 value_v, u64 *slot) -{ - u64 dummy[1]; - s64 ret; - - ret = beat_hcall1(HV_insert_htab_entry3, dummy, htab_id, group, - hpte_v, hpte_r, mask_v, value_v); - *slot = dummy[0]; - return ret; -} - -static inline s64 beat_invalidate_htab_entry3(u64 htab_id, u64 group, - u64 va, u64 pss) -{ - return beat_hcall_norets(HV_invalidate_htab_entry3, - htab_id, group, va, pss); -} - -static inline s64 beat_update_htab_permission3(u64 htab_id, u64 group, - u64 va, u64 pss, u64 ptel_mask, u64 ptel_value) -{ - return beat_hcall_norets(HV_update_htab_permission3, - htab_id, group, va, pss, ptel_mask, ptel_value); -} - -static inline s64 beat_clear_htab3(u64 htab_id) -{ - return beat_hcall_norets(HV_clear_htab3, htab_id); -} - -static inline void beat_shutdown_logical_partition(u64 code) -{ - (void)beat_hcall_norets(HV_shutdown_logical_partition, code); -} - -static inline s64 beat_rtc_write(u64 time_from_epoch) -{ - return beat_hcall_norets(HV_rtc_write, time_from_epoch); -} - -static inline s64 beat_rtc_read(u64 *time_from_epoch) -{ - u64 dummy[1]; - s64 ret; - - ret = beat_hcall1(HV_rtc_read, dummy); - *time_from_epoch = dummy[0]; - return ret; -} - -#define BEAT_NVRW_CNT (sizeof(u64) * 6) - -static inline s64 beat_eeprom_write(u64 index, u64 length, u8 *buffer) -{ - u64 b[6]; - - if (length > BEAT_NVRW_CNT) - return -1; - memcpy(b, buffer, sizeof(b)); - return beat_hcall_norets8(HV_eeprom_write, index, length, - b[0], b[1], b[2], b[3], b[4], b[5]); -} - -static inline s64 beat_eeprom_read(u64 index, u64 length, u8 *buffer) -{ - u64 b[6]; - s64 ret; - - if (length > BEAT_NVRW_CNT) - return -1; - ret = beat_hcall6(HV_eeprom_read, b, index, length); - memcpy(buffer, b, length); - return ret; -} - -static inline s64 beat_set_dabr(u64 value, u64 style) -{ - return beat_hcall_norets(HV_set_dabr, value, style); -} - -static inline s64 beat_get_characters_from_console(u64 termno, u64 *len, - u8 *buffer) -{ - u64 dummy[3]; - s64 ret; - - ret = beat_hcall3(HV_get_characters_from_console, dummy, termno, len); - *len = dummy[0]; - memcpy(buffer, dummy + 1, *len); - return ret; -} - -static inline s64 beat_put_characters_to_console(u64 termno, u64 len, - u8 *buffer) -{ - u64 b[2]; - - memcpy(b, buffer, len); - return beat_hcall_norets(HV_put_characters_to_console, termno, len, - b[0], b[1]); -} - -static inline s64 beat_get_spe_privileged_state_1_registers( - u64 id, u64 offsetof, u64 *value) -{ - u64 dummy[1]; - s64 ret; - - ret = beat_hcall1(HV_get_spe_privileged_state_1_registers, dummy, id, - offsetof); - *value = dummy[0]; - return ret; -} - -static inline s64 beat_set_irq_mask_for_spe(u64 id, u64 class, u64 mask) -{ - return beat_hcall_norets(HV_set_irq_mask_for_spe, id, class, mask); -} - -static inline s64 beat_clear_interrupt_status_of_spe(u64 id, u64 class, - u64 mask) -{ - return beat_hcall_norets(HV_clear_interrupt_status_of_spe, - id, class, mask); -} - -static inline s64 beat_set_spe_privileged_state_1_registers( - u64 id, u64 offsetof, u64 value) -{ - return beat_hcall_norets(HV_set_spe_privileged_state_1_registers, - id, offsetof, value); -} - -static inline s64 beat_get_interrupt_status_of_spe(u64 id, u64 class, u64 *val) -{ - u64 dummy[1]; - s64 ret; - - ret = beat_hcall1(HV_get_interrupt_status_of_spe, dummy, id, class); - *val = dummy[0]; - return ret; -} - -static inline s64 beat_put_iopte(u64 ioas_id, u64 io_addr, u64 real_addr, - u64 ioid, u64 flags) -{ - return beat_hcall_norets(HV_put_iopte, ioas_id, io_addr, real_addr, - ioid, flags); -} - -static inline s64 beat_construct_event_receive_port(u64 *port) -{ - u64 dummy[1]; - s64 ret; - - ret = beat_hcall1(HV_construct_event_receive_port, dummy); - *port = dummy[0]; - return ret; -} - -static inline s64 beat_destruct_event_receive_port(u64 port) -{ - s64 ret; - - ret = beat_hcall_norets(HV_destruct_event_receive_port, port); - return ret; -} - -static inline s64 beat_create_repository_node(u64 path[4], u64 data[2]) -{ - s64 ret; - - ret = beat_hcall_norets(HV_create_repository_node2, - path[0], path[1], path[2], path[3], data[0], data[1]); - return ret; -} - -static inline s64 beat_get_repository_node_value(u64 lpid, u64 path[4], - u64 data[2]) -{ - s64 ret; - - ret = beat_hcall2(HV_get_repository_node_value2, data, - lpid, path[0], path[1], path[2], path[3]); - return ret; -} - -#endif diff --git a/arch/powerpc/platforms/cell/celleb_pci.c b/arch/powerpc/platforms/cell/celleb_pci.c deleted file mode 100644 index 9b11b5dd8b7c..000000000000 --- a/arch/powerpc/platforms/cell/celleb_pci.c +++ /dev/null @@ -1,499 +0,0 @@ -/* - * Support for PCI on Celleb platform. - * - * (C) Copyright 2006-2007 TOSHIBA CORPORATION - * - * This code is based on arch/powerpc/kernel/rtas_pci.c: - * Copyright (C) 2001 Dave Engebretsen, IBM Corporation - * Copyright (C) 2003 Anton Blanchard , IBM - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#undef DEBUG - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "celleb_pci.h" - -#define MAX_PCI_DEVICES 32 -#define MAX_PCI_FUNCTIONS 8 -#define MAX_PCI_BASE_ADDRS 3 /* use 64 bit address */ - -/* definition for fake pci configuration area for GbE, .... ,and etc. */ - -struct celleb_pci_resource { - struct resource r[MAX_PCI_BASE_ADDRS]; -}; - -struct celleb_pci_private { - unsigned char *fake_config[MAX_PCI_DEVICES][MAX_PCI_FUNCTIONS]; - struct celleb_pci_resource *res[MAX_PCI_DEVICES][MAX_PCI_FUNCTIONS]; -}; - -static inline u8 celleb_fake_config_readb(void *addr) -{ - u8 *p = addr; - return *p; -} - -static inline u16 celleb_fake_config_readw(void *addr) -{ - __le16 *p = addr; - return le16_to_cpu(*p); -} - -static inline u32 celleb_fake_config_readl(void *addr) -{ - __le32 *p = addr; - return le32_to_cpu(*p); -} - -static inline void celleb_fake_config_writeb(u32 val, void *addr) -{ - u8 *p = addr; - *p = val; -} - -static inline void celleb_fake_config_writew(u32 val, void *addr) -{ - __le16 val16; - __le16 *p = addr; - val16 = cpu_to_le16(val); - *p = val16; -} - -static inline void celleb_fake_config_writel(u32 val, void *addr) -{ - __le32 val32; - __le32 *p = addr; - val32 = cpu_to_le32(val); - *p = val32; -} - -static unsigned char *get_fake_config_start(struct pci_controller *hose, - int devno, int fn) -{ - struct celleb_pci_private *private = hose->private_data; - - if (private == NULL) - return NULL; - - return private->fake_config[devno][fn]; -} - -static struct celleb_pci_resource *get_resource_start( - struct pci_controller *hose, - int devno, int fn) -{ - struct celleb_pci_private *private = hose->private_data; - - if (private == NULL) - return NULL; - - return private->res[devno][fn]; -} - - -static void celleb_config_read_fake(unsigned char *config, int where, - int size, u32 *val) -{ - char *p = config + where; - - switch (size) { - case 1: - *val = celleb_fake_config_readb(p); - break; - case 2: - *val = celleb_fake_config_readw(p); - break; - case 4: - *val = celleb_fake_config_readl(p); - break; - } -} - -static void celleb_config_write_fake(unsigned char *config, int where, - int size, u32 val) -{ - char *p = config + where; - - switch (size) { - case 1: - celleb_fake_config_writeb(val, p); - break; - case 2: - celleb_fake_config_writew(val, p); - break; - case 4: - celleb_fake_config_writel(val, p); - break; - } -} - -static int celleb_fake_pci_read_config(struct pci_bus *bus, - unsigned int devfn, int where, int size, u32 *val) -{ - char *config; - struct pci_controller *hose = pci_bus_to_host(bus); - unsigned int devno = devfn >> 3; - unsigned int fn = devfn & 0x7; - - /* allignment check */ - BUG_ON(where % size); - - pr_debug(" fake read: bus=0x%x, ", bus->number); - config = get_fake_config_start(hose, devno, fn); - - pr_debug("devno=0x%x, where=0x%x, size=0x%x, ", devno, where, size); - if (!config) { - pr_debug("failed\n"); - return PCIBIOS_DEVICE_NOT_FOUND; - } - - celleb_config_read_fake(config, where, size, val); - pr_debug("val=0x%x\n", *val); - - return PCIBIOS_SUCCESSFUL; -} - - -static int celleb_fake_pci_write_config(struct pci_bus *bus, - unsigned int devfn, int where, int size, u32 val) -{ - char *config; - struct pci_controller *hose = pci_bus_to_host(bus); - struct celleb_pci_resource *res; - unsigned int devno = devfn >> 3; - unsigned int fn = devfn & 0x7; - - /* allignment check */ - BUG_ON(where % size); - - config = get_fake_config_start(hose, devno, fn); - - if (!config) - return PCIBIOS_DEVICE_NOT_FOUND; - - if (val == ~0) { - int i = (where - PCI_BASE_ADDRESS_0) >> 3; - - switch (where) { - case PCI_BASE_ADDRESS_0: - case PCI_BASE_ADDRESS_2: - if (size != 4) - return PCIBIOS_DEVICE_NOT_FOUND; - res = get_resource_start(hose, devno, fn); - if (!res) - return PCIBIOS_DEVICE_NOT_FOUND; - celleb_config_write_fake(config, where, size, - (res->r[i].end - res->r[i].start)); - return PCIBIOS_SUCCESSFUL; - case PCI_BASE_ADDRESS_1: - case PCI_BASE_ADDRESS_3: - case PCI_BASE_ADDRESS_4: - case PCI_BASE_ADDRESS_5: - break; - default: - break; - } - } - - celleb_config_write_fake(config, where, size, val); - pr_debug(" fake write: where=%x, size=%d, val=%x\n", - where, size, val); - - return PCIBIOS_SUCCESSFUL; -} - -static struct pci_ops celleb_fake_pci_ops = { - .read = celleb_fake_pci_read_config, - .write = celleb_fake_pci_write_config, -}; - -static inline void celleb_setup_pci_base_addrs(struct pci_controller *hose, - unsigned int devno, unsigned int fn, - unsigned int num_base_addr) -{ - u32 val; - unsigned char *config; - struct celleb_pci_resource *res; - - config = get_fake_config_start(hose, devno, fn); - res = get_resource_start(hose, devno, fn); - - if (!config || !res) - return; - - switch (num_base_addr) { - case 3: - val = (res->r[2].start & 0xfffffff0) - | PCI_BASE_ADDRESS_MEM_TYPE_64; - celleb_config_write_fake(config, PCI_BASE_ADDRESS_4, 4, val); - val = res->r[2].start >> 32; - celleb_config_write_fake(config, PCI_BASE_ADDRESS_5, 4, val); - /* FALLTHROUGH */ - case 2: - val = (res->r[1].start & 0xfffffff0) - | PCI_BASE_ADDRESS_MEM_TYPE_64; - celleb_config_write_fake(config, PCI_BASE_ADDRESS_2, 4, val); - val = res->r[1].start >> 32; - celleb_config_write_fake(config, PCI_BASE_ADDRESS_3, 4, val); - /* FALLTHROUGH */ - case 1: - val = (res->r[0].start & 0xfffffff0) - | PCI_BASE_ADDRESS_MEM_TYPE_64; - celleb_config_write_fake(config, PCI_BASE_ADDRESS_0, 4, val); - val = res->r[0].start >> 32; - celleb_config_write_fake(config, PCI_BASE_ADDRESS_1, 4, val); - break; - } - - val = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; - celleb_config_write_fake(config, PCI_COMMAND, 2, val); -} - -static int __init celleb_setup_fake_pci_device(struct device_node *node, - struct pci_controller *hose) -{ - unsigned int rlen; - int num_base_addr = 0; - u32 val; - const u32 *wi0, *wi1, *wi2, *wi3, *wi4; - unsigned int devno, fn; - struct celleb_pci_private *private = hose->private_data; - unsigned char **config = NULL; - struct celleb_pci_resource **res = NULL; - const char *name; - const unsigned long *li; - int size, result; - - if (private == NULL) { - printk(KERN_ERR "PCI: " - "memory space for pci controller is not assigned\n"); - goto error; - } - - name = of_get_property(node, "model", &rlen); - if (!name) { - printk(KERN_ERR "PCI: model property not found.\n"); - goto error; - } - - wi4 = of_get_property(node, "reg", &rlen); - if (wi4 == NULL) - goto error; - - devno = ((wi4[0] >> 8) & 0xff) >> 3; - fn = (wi4[0] >> 8) & 0x7; - - pr_debug("PCI: celleb_setup_fake_pci() %s devno=%x fn=%x\n", name, - devno, fn); - - size = 256; - config = &private->fake_config[devno][fn]; - *config = zalloc_maybe_bootmem(size, GFP_KERNEL); - if (*config == NULL) { - printk(KERN_ERR "PCI: " - "not enough memory for fake configuration space\n"); - goto error; - } - pr_debug("PCI: fake config area assigned 0x%016lx\n", - (unsigned long)*config); - - size = sizeof(struct celleb_pci_resource); - res = &private->res[devno][fn]; - *res = zalloc_maybe_bootmem(size, GFP_KERNEL); - if (*res == NULL) { - printk(KERN_ERR - "PCI: not enough memory for resource data space\n"); - goto error; - } - pr_debug("PCI: res assigned 0x%016lx\n", (unsigned long)*res); - - wi0 = of_get_property(node, "device-id", NULL); - wi1 = of_get_property(node, "vendor-id", NULL); - wi2 = of_get_property(node, "class-code", NULL); - wi3 = of_get_property(node, "revision-id", NULL); - if (!wi0 || !wi1 || !wi2 || !wi3) { - printk(KERN_ERR "PCI: Missing device tree properties.\n"); - goto error; - } - - celleb_config_write_fake(*config, PCI_DEVICE_ID, 2, wi0[0] & 0xffff); - celleb_config_write_fake(*config, PCI_VENDOR_ID, 2, wi1[0] & 0xffff); - pr_debug("class-code = 0x%08x\n", wi2[0]); - - celleb_config_write_fake(*config, PCI_CLASS_PROG, 1, wi2[0] & 0xff); - celleb_config_write_fake(*config, PCI_CLASS_DEVICE, 2, - (wi2[0] >> 8) & 0xffff); - celleb_config_write_fake(*config, PCI_REVISION_ID, 1, wi3[0]); - - while (num_base_addr < MAX_PCI_BASE_ADDRS) { - result = of_address_to_resource(node, - num_base_addr, &(*res)->r[num_base_addr]); - if (result) - break; - num_base_addr++; - } - - celleb_setup_pci_base_addrs(hose, devno, fn, num_base_addr); - - li = of_get_property(node, "interrupts", &rlen); - if (!li) { - printk(KERN_ERR "PCI: interrupts not found.\n"); - goto error; - } - val = li[0]; - celleb_config_write_fake(*config, PCI_INTERRUPT_PIN, 1, 1); - celleb_config_write_fake(*config, PCI_INTERRUPT_LINE, 1, val); - -#ifdef DEBUG - pr_debug("PCI: %s irq=%ld\n", name, li[0]); - for (i = 0; i < 6; i++) { - celleb_config_read_fake(*config, - PCI_BASE_ADDRESS_0 + 0x4 * i, 4, - &val); - pr_debug("PCI: %s fn=%d base_address_%d=0x%x\n", - name, fn, i, val); - } -#endif - - celleb_config_write_fake(*config, PCI_HEADER_TYPE, 1, - PCI_HEADER_TYPE_NORMAL); - - return 0; - -error: - if (mem_init_done) { - if (config) - kfree(*config); - if (res) - kfree(*res); - } else { - if (config && *config) { - size = 256; - memblock_free(__pa(*config), size); - } - if (res && *res) { - size = sizeof(struct celleb_pci_resource); - memblock_free(__pa(*res), size); - } - } - - return 1; -} - -static int __init phb_set_bus_ranges(struct device_node *dev, - struct pci_controller *phb) -{ - const int *bus_range; - unsigned int len; - - bus_range = of_get_property(dev, "bus-range", &len); - if (bus_range == NULL || len < 2 * sizeof(int)) - return 1; - - phb->first_busno = bus_range[0]; - phb->last_busno = bus_range[1]; - - return 0; -} - -static void __init celleb_alloc_private_mem(struct pci_controller *hose) -{ - hose->private_data = - zalloc_maybe_bootmem(sizeof(struct celleb_pci_private), - GFP_KERNEL); -} - -static int __init celleb_setup_fake_pci(struct device_node *dev, - struct pci_controller *phb) -{ - struct device_node *node; - - phb->ops = &celleb_fake_pci_ops; - celleb_alloc_private_mem(phb); - - for (node = of_get_next_child(dev, NULL); - node != NULL; node = of_get_next_child(dev, node)) - celleb_setup_fake_pci_device(node, phb); - - return 0; -} - -static struct celleb_phb_spec celleb_fake_pci_spec __initdata = { - .setup = celleb_setup_fake_pci, -}; - -static const struct of_device_id celleb_phb_match[] __initconst = { - { - .name = "pci-pseudo", - .data = &celleb_fake_pci_spec, - }, { - .name = "epci", - .data = &celleb_epci_spec, - }, { - .name = "pcie", - .data = &celleb_pciex_spec, - }, { - }, -}; - -int __init celleb_setup_phb(struct pci_controller *phb) -{ - struct device_node *dev = phb->dn; - const struct of_device_id *match; - const struct celleb_phb_spec *phb_spec; - int rc; - - match = of_match_node(celleb_phb_match, dev); - if (!match) - return 1; - - phb_set_bus_ranges(dev, phb); - phb->buid = 1; - - phb_spec = match->data; - rc = (*phb_spec->setup)(dev, phb); - if (rc) - return 1; - - if (phb_spec->ops) - iowa_register_bus(phb, phb_spec->ops, - phb_spec->iowa_init, - phb_spec->iowa_data); - return 0; -} - -int celleb_pci_probe_mode(struct pci_bus *bus) -{ - return PCI_PROBE_DEVTREE; -} diff --git a/arch/powerpc/platforms/cell/celleb_pci.h b/arch/powerpc/platforms/cell/celleb_pci.h deleted file mode 100644 index a801fcc5f389..000000000000 --- a/arch/powerpc/platforms/cell/celleb_pci.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * pci prototypes for Celleb platform - * - * (C) Copyright 2006-2007 TOSHIBA 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef _CELLEB_PCI_H -#define _CELLEB_PCI_H - -#include - -#include -#include -#include -#include - -struct iowa_bus; - -struct celleb_phb_spec { - int (*setup)(struct device_node *, struct pci_controller *); - struct ppc_pci_io *ops; - int (*iowa_init)(struct iowa_bus *, void *); - void *iowa_data; -}; - -extern int celleb_setup_phb(struct pci_controller *); -extern int celleb_pci_probe_mode(struct pci_bus *); - -extern struct celleb_phb_spec celleb_epci_spec; -extern struct celleb_phb_spec celleb_pciex_spec; - -#endif /* _CELLEB_PCI_H */ diff --git a/arch/powerpc/platforms/cell/celleb_scc.h b/arch/powerpc/platforms/cell/celleb_scc.h deleted file mode 100644 index b596a711c348..000000000000 --- a/arch/powerpc/platforms/cell/celleb_scc.h +++ /dev/null @@ -1,232 +0,0 @@ -/* - * SCC (Super Companion Chip) definitions - * - * (C) Copyright 2004-2006 TOSHIBA 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef _CELLEB_SCC_H -#define _CELLEB_SCC_H - -#define PCI_VENDOR_ID_TOSHIBA_2 0x102f -#define PCI_DEVICE_ID_TOSHIBA_SCC_PCIEXC_BRIDGE 0x01b0 -#define PCI_DEVICE_ID_TOSHIBA_SCC_EPCI_BRIDGE 0x01b1 -#define PCI_DEVICE_ID_TOSHIBA_SCC_BRIDGE 0x01b2 -#define PCI_DEVICE_ID_TOSHIBA_SCC_GBE 0x01b3 -#define PCI_DEVICE_ID_TOSHIBA_SCC_ATA 0x01b4 -#define PCI_DEVICE_ID_TOSHIBA_SCC_USB2 0x01b5 -#define PCI_DEVICE_ID_TOSHIBA_SCC_USB 0x01b6 -#define PCI_DEVICE_ID_TOSHIBA_SCC_ENCDEC 0x01b7 - -#define SCC_EPCI_REG 0x0000d000 - -/* EPCI registers */ -#define SCC_EPCI_CNF10_REG 0x010 -#define SCC_EPCI_CNF14_REG 0x014 -#define SCC_EPCI_CNF18_REG 0x018 -#define SCC_EPCI_PVBAT 0x100 -#define SCC_EPCI_VPMBAT 0x104 -#define SCC_EPCI_VPIBAT 0x108 -#define SCC_EPCI_VCSR 0x110 -#define SCC_EPCI_VIENAB 0x114 -#define SCC_EPCI_VISTAT 0x118 -#define SCC_EPCI_VRDCOUNT 0x124 -#define SCC_EPCI_BAM0 0x12c -#define SCC_EPCI_BAM1 0x134 -#define SCC_EPCI_BAM2 0x13c -#define SCC_EPCI_IADR 0x164 -#define SCC_EPCI_CLKRST 0x800 -#define SCC_EPCI_INTSET 0x804 -#define SCC_EPCI_STATUS 0x808 -#define SCC_EPCI_ABTSET 0x80c -#define SCC_EPCI_WATRP 0x810 -#define SCC_EPCI_DUMYRADR 0x814 -#define SCC_EPCI_SWRESP 0x818 -#define SCC_EPCI_CNTOPT 0x81c -#define SCC_EPCI_ECMODE 0xf00 -#define SCC_EPCI_IOM_AC_NUM 5 -#define SCC_EPCI_IOM_ACTE(n) (0xf10 + (n) * 4) -#define SCC_EPCI_IOT_AC_NUM 4 -#define SCC_EPCI_IOT_ACTE(n) (0xf30 + (n) * 4) -#define SCC_EPCI_MAEA 0xf50 -#define SCC_EPCI_MAEC 0xf54 -#define SCC_EPCI_CKCTRL 0xff0 - -/* bits for SCC_EPCI_VCSR */ -#define SCC_EPCI_VCSR_FRE 0x00020000 -#define SCC_EPCI_VCSR_FWE 0x00010000 -#define SCC_EPCI_VCSR_DR 0x00000400 -#define SCC_EPCI_VCSR_SR 0x00000008 -#define SCC_EPCI_VCSR_AT 0x00000004 - -/* bits for SCC_EPCI_VIENAB/SCC_EPCI_VISTAT */ -#define SCC_EPCI_VISTAT_PMPE 0x00000008 -#define SCC_EPCI_VISTAT_PMFE 0x00000004 -#define SCC_EPCI_VISTAT_PRA 0x00000002 -#define SCC_EPCI_VISTAT_PRD 0x00000001 -#define SCC_EPCI_VISTAT_ALL 0x0000000f - -#define SCC_EPCI_VIENAB_PMPEE 0x00000008 -#define SCC_EPCI_VIENAB_PMFEE 0x00000004 -#define SCC_EPCI_VIENAB_PRA 0x00000002 -#define SCC_EPCI_VIENAB_PRD 0x00000001 -#define SCC_EPCI_VIENAB_ALL 0x0000000f - -/* bits for SCC_EPCI_CLKRST */ -#define SCC_EPCI_CLKRST_CKS_MASK 0x00030000 -#define SCC_EPCI_CLKRST_CKS_2 0x00000000 -#define SCC_EPCI_CLKRST_CKS_4 0x00010000 -#define SCC_EPCI_CLKRST_CKS_8 0x00020000 -#define SCC_EPCI_CLKRST_PCICRST 0x00000400 -#define SCC_EPCI_CLKRST_BC 0x00000200 -#define SCC_EPCI_CLKRST_PCIRST 0x00000100 -#define SCC_EPCI_CLKRST_PCKEN 0x00000001 - -/* bits for SCC_EPCI_INTSET/SCC_EPCI_STATUS */ -#define SCC_EPCI_INT_2M 0x01000000 -#define SCC_EPCI_INT_RERR 0x00200000 -#define SCC_EPCI_INT_SERR 0x00100000 -#define SCC_EPCI_INT_PRTER 0x00080000 -#define SCC_EPCI_INT_SER 0x00040000 -#define SCC_EPCI_INT_PER 0x00020000 -#define SCC_EPCI_INT_PAI 0x00010000 -#define SCC_EPCI_INT_1M 0x00000100 -#define SCC_EPCI_INT_PME 0x00000010 -#define SCC_EPCI_INT_INTD 0x00000008 -#define SCC_EPCI_INT_INTC 0x00000004 -#define SCC_EPCI_INT_INTB 0x00000002 -#define SCC_EPCI_INT_INTA 0x00000001 -#define SCC_EPCI_INT_DEVINT 0x0000000f -#define SCC_EPCI_INT_ALL 0x003f001f -#define SCC_EPCI_INT_ALLERR 0x003f0000 - -/* bits for SCC_EPCI_CKCTRL */ -#define SCC_EPCI_CKCTRL_CRST0 0x00010000 -#define SCC_EPCI_CKCTRL_CRST1 0x00020000 -#define SCC_EPCI_CKCTRL_OCLKEN 0x00000100 -#define SCC_EPCI_CKCTRL_LCLKEN 0x00000001 - -#define SCC_EPCI_IDSEL_AD_TO_SLOT(ad) ((ad) - 10) -#define SCC_EPCI_MAX_DEVNU SCC_EPCI_IDSEL_AD_TO_SLOT(32) - -/* bits for SCC_EPCI_CNTOPT */ -#define SCC_EPCI_CNTOPT_O2PMB 0x00000002 - -/* SCC PCIEXC SMMIO registers */ -#define PEXCADRS 0x000 -#define PEXCWDATA 0x004 -#define PEXCRDATA 0x008 -#define PEXDADRS 0x010 -#define PEXDCMND 0x014 -#define PEXDWDATA 0x018 -#define PEXDRDATA 0x01c -#define PEXREQID 0x020 -#define PEXTIDMAP 0x024 -#define PEXINTMASK 0x028 -#define PEXINTSTS 0x02c -#define PEXAERRMASK 0x030 -#define PEXAERRSTS 0x034 -#define PEXPRERRMASK 0x040 -#define PEXPRERRSTS 0x044 -#define PEXPRERRID01 0x048 -#define PEXPRERRID23 0x04c -#define PEXVDMASK 0x050 -#define PEXVDSTS 0x054 -#define PEXRCVCPLIDA 0x060 -#define PEXLENERRIDA 0x068 -#define PEXPHYPLLST 0x070 -#define PEXDMRDEN0 0x100 -#define PEXDMRDADR0 0x104 -#define PEXDMRDENX 0x110 -#define PEXDMRDADRX 0x114 -#define PEXECMODE 0xf00 -#define PEXMAEA(n) (0xf50 + (8 * n)) -#define PEXMAEC(n) (0xf54 + (8 * n)) -#define PEXCCRCTRL 0xff0 - -/* SCC PCIEXC bits and shifts for PEXCADRS */ -#define PEXCADRS_BYTE_EN_SHIFT 20 -#define PEXCADRS_CMD_SHIFT 16 -#define PEXCADRS_CMD_READ (0xa << PEXCADRS_CMD_SHIFT) -#define PEXCADRS_CMD_WRITE (0xb << PEXCADRS_CMD_SHIFT) - -/* SCC PCIEXC shifts for PEXDADRS */ -#define PEXDADRS_BUSNO_SHIFT 20 -#define PEXDADRS_DEVNO_SHIFT 15 -#define PEXDADRS_FUNCNO_SHIFT 12 - -/* SCC PCIEXC bits and shifts for PEXDCMND */ -#define PEXDCMND_BYTE_EN_SHIFT 4 -#define PEXDCMND_IO_READ 0x2 -#define PEXDCMND_IO_WRITE 0x3 -#define PEXDCMND_CONFIG_READ 0xa -#define PEXDCMND_CONFIG_WRITE 0xb - -/* SCC PCIEXC bits for PEXPHYPLLST */ -#define PEXPHYPLLST_PEXPHYAPLLST 0x00000001 - -/* SCC PCIEXC bits for PEXECMODE */ -#define PEXECMODE_ALL_THROUGH 0x00000000 -#define PEXECMODE_ALL_8BIT 0x00550155 -#define PEXECMODE_ALL_16BIT 0x00aa02aa - -/* SCC PCIEXC bits for PEXCCRCTRL */ -#define PEXCCRCTRL_PEXIPCOREEN 0x00040000 -#define PEXCCRCTRL_PEXIPCONTEN 0x00020000 -#define PEXCCRCTRL_PEXPHYPLLEN 0x00010000 -#define PEXCCRCTRL_PCIEXCAOCKEN 0x00000100 - -/* SCC PCIEXC port configuration registers */ -#define PEXTCERRCHK 0x21c -#define PEXTAMAPB0 0x220 -#define PEXTAMAPL0 0x224 -#define PEXTAMAPB(n) (PEXTAMAPB0 + 8 * (n)) -#define PEXTAMAPL(n) (PEXTAMAPL0 + 8 * (n)) -#define PEXCHVC0P 0x500 -#define PEXCHVC0NP 0x504 -#define PEXCHVC0C 0x508 -#define PEXCDVC0P 0x50c -#define PEXCDVC0NP 0x510 -#define PEXCDVC0C 0x514 -#define PEXCHVCXP 0x518 -#define PEXCHVCXNP 0x51c -#define PEXCHVCXC 0x520 -#define PEXCDVCXP 0x524 -#define PEXCDVCXNP 0x528 -#define PEXCDVCXC 0x52c -#define PEXCTTRG 0x530 -#define PEXTSCTRL 0x700 -#define PEXTSSTS 0x704 -#define PEXSKPCTRL 0x708 - -/* UHC registers */ -#define SCC_UHC_CKRCTRL 0xff0 -#define SCC_UHC_ECMODE 0xf00 - -/* bits for SCC_UHC_CKRCTRL */ -#define SCC_UHC_F48MCKLEN 0x00000001 -#define SCC_UHC_P_SUSPEND 0x00000002 -#define SCC_UHC_PHY_SUSPEND_SEL 0x00000004 -#define SCC_UHC_HCLKEN 0x00000100 -#define SCC_UHC_USBEN 0x00010000 -#define SCC_UHC_USBCEN 0x00020000 -#define SCC_UHC_PHYEN 0x00040000 - -/* bits for SCC_UHC_ECMODE */ -#define SCC_UHC_ECMODE_BY_BYTE 0x00000555 -#define SCC_UHC_ECMODE_BY_WORD 0x00000aaa - -#endif /* _CELLEB_SCC_H */ diff --git a/arch/powerpc/platforms/cell/celleb_scc_epci.c b/arch/powerpc/platforms/cell/celleb_scc_epci.c deleted file mode 100644 index 9438bbed402f..000000000000 --- a/arch/powerpc/platforms/cell/celleb_scc_epci.c +++ /dev/null @@ -1,428 +0,0 @@ -/* - * Support for SCC external PCI - * - * (C) Copyright 2004-2007 TOSHIBA 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#undef DEBUG - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "celleb_scc.h" -#include "celleb_pci.h" - -#define MAX_PCI_DEVICES 32 -#define MAX_PCI_FUNCTIONS 8 - -#define iob() __asm__ __volatile__("eieio; sync":::"memory") - -static inline PCI_IO_ADDR celleb_epci_get_epci_base( - struct pci_controller *hose) -{ - /* - * Note: - * Celleb epci uses cfg_addr as a base address for - * epci control registers. - */ - - return hose->cfg_addr; -} - -static inline PCI_IO_ADDR celleb_epci_get_epci_cfg( - struct pci_controller *hose) -{ - /* - * Note: - * Celleb epci uses cfg_data as a base address for - * configuration area for epci devices. - */ - - return hose->cfg_data; -} - -static inline void clear_and_disable_master_abort_interrupt( - struct pci_controller *hose) -{ - PCI_IO_ADDR epci_base; - PCI_IO_ADDR reg; - epci_base = celleb_epci_get_epci_base(hose); - reg = epci_base + PCI_COMMAND; - out_be32(reg, in_be32(reg) | (PCI_STATUS_REC_MASTER_ABORT << 16)); -} - -static int celleb_epci_check_abort(struct pci_controller *hose, - PCI_IO_ADDR addr) -{ - PCI_IO_ADDR reg; - PCI_IO_ADDR epci_base; - u32 val; - - iob(); - epci_base = celleb_epci_get_epci_base(hose); - - reg = epci_base + PCI_COMMAND; - val = in_be32(reg); - - if (val & (PCI_STATUS_REC_MASTER_ABORT << 16)) { - out_be32(reg, - (val & 0xffff) | (PCI_STATUS_REC_MASTER_ABORT << 16)); - - /* clear PCI Controller error, FRE, PMFE */ - reg = epci_base + SCC_EPCI_STATUS; - out_be32(reg, SCC_EPCI_INT_PAI); - - reg = epci_base + SCC_EPCI_VCSR; - val = in_be32(reg) & 0xffff; - val |= SCC_EPCI_VCSR_FRE; - out_be32(reg, val); - - reg = epci_base + SCC_EPCI_VISTAT; - out_be32(reg, SCC_EPCI_VISTAT_PMFE); - return PCIBIOS_DEVICE_NOT_FOUND; - } - - return PCIBIOS_SUCCESSFUL; -} - -static PCI_IO_ADDR celleb_epci_make_config_addr(struct pci_bus *bus, - struct pci_controller *hose, unsigned int devfn, int where) -{ - PCI_IO_ADDR addr; - - if (bus != hose->bus) - addr = celleb_epci_get_epci_cfg(hose) + - (((bus->number & 0xff) << 16) - | ((devfn & 0xff) << 8) - | (where & 0xff) - | 0x01000000); - else - addr = celleb_epci_get_epci_cfg(hose) + - (((devfn & 0xff) << 8) | (where & 0xff)); - - pr_debug("EPCI: config_addr = 0x%p\n", addr); - - return addr; -} - -static int celleb_epci_read_config(struct pci_bus *bus, - unsigned int devfn, int where, int size, u32 *val) -{ - PCI_IO_ADDR epci_base; - PCI_IO_ADDR addr; - struct pci_controller *hose = pci_bus_to_host(bus); - - /* allignment check */ - BUG_ON(where % size); - - if (!celleb_epci_get_epci_cfg(hose)) - return PCIBIOS_DEVICE_NOT_FOUND; - - if (bus->number == hose->first_busno && devfn == 0) { - /* EPCI controller self */ - - epci_base = celleb_epci_get_epci_base(hose); - addr = epci_base + where; - - switch (size) { - case 1: - *val = in_8(addr); - break; - case 2: - *val = in_be16(addr); - break; - case 4: - *val = in_be32(addr); - break; - default: - return PCIBIOS_DEVICE_NOT_FOUND; - } - - } else { - - clear_and_disable_master_abort_interrupt(hose); - addr = celleb_epci_make_config_addr(bus, hose, devfn, where); - - switch (size) { - case 1: - *val = in_8(addr); - break; - case 2: - *val = in_le16(addr); - break; - case 4: - *val = in_le32(addr); - break; - default: - return PCIBIOS_DEVICE_NOT_FOUND; - } - } - - pr_debug("EPCI: " - "addr=0x%p, devfn=0x%x, where=0x%x, size=0x%x, val=0x%x\n", - addr, devfn, where, size, *val); - - return celleb_epci_check_abort(hose, NULL); -} - -static int celleb_epci_write_config(struct pci_bus *bus, - unsigned int devfn, int where, int size, u32 val) -{ - PCI_IO_ADDR epci_base; - PCI_IO_ADDR addr; - struct pci_controller *hose = pci_bus_to_host(bus); - - /* allignment check */ - BUG_ON(where % size); - - if (!celleb_epci_get_epci_cfg(hose)) - return PCIBIOS_DEVICE_NOT_FOUND; - - if (bus->number == hose->first_busno && devfn == 0) { - /* EPCI controller self */ - - epci_base = celleb_epci_get_epci_base(hose); - addr = epci_base + where; - - switch (size) { - case 1: - out_8(addr, val); - break; - case 2: - out_be16(addr, val); - break; - case 4: - out_be32(addr, val); - break; - default: - return PCIBIOS_DEVICE_NOT_FOUND; - } - - } else { - - clear_and_disable_master_abort_interrupt(hose); - addr = celleb_epci_make_config_addr(bus, hose, devfn, where); - - switch (size) { - case 1: - out_8(addr, val); - break; - case 2: - out_le16(addr, val); - break; - case 4: - out_le32(addr, val); - break; - default: - return PCIBIOS_DEVICE_NOT_FOUND; - } - } - - return celleb_epci_check_abort(hose, addr); -} - -struct pci_ops celleb_epci_ops = { - .read = celleb_epci_read_config, - .write = celleb_epci_write_config, -}; - -/* to be moved in FW */ -static int __init celleb_epci_init(struct pci_controller *hose) -{ - u32 val; - PCI_IO_ADDR reg; - PCI_IO_ADDR epci_base; - int hwres = 0; - - epci_base = celleb_epci_get_epci_base(hose); - - /* PCI core reset(Internal bus and PCI clock) */ - reg = epci_base + SCC_EPCI_CKCTRL; - val = in_be32(reg); - if (val == 0x00030101) - hwres = 1; - else { - val &= ~(SCC_EPCI_CKCTRL_CRST0 | SCC_EPCI_CKCTRL_CRST1); - out_be32(reg, val); - - /* set PCI core clock */ - val = in_be32(reg); - val |= (SCC_EPCI_CKCTRL_OCLKEN | SCC_EPCI_CKCTRL_LCLKEN); - out_be32(reg, val); - - /* release PCI core reset (internal bus) */ - val = in_be32(reg); - val |= SCC_EPCI_CKCTRL_CRST0; - out_be32(reg, val); - - /* set PCI clock select */ - reg = epci_base + SCC_EPCI_CLKRST; - val = in_be32(reg); - val &= ~SCC_EPCI_CLKRST_CKS_MASK; - val |= SCC_EPCI_CLKRST_CKS_2; - out_be32(reg, val); - - /* set arbiter */ - reg = epci_base + SCC_EPCI_ABTSET; - out_be32(reg, 0x0f1f001f); /* temporary value */ - - /* buffer on */ - reg = epci_base + SCC_EPCI_CLKRST; - val = in_be32(reg); - val |= SCC_EPCI_CLKRST_BC; - out_be32(reg, val); - - /* PCI clock enable */ - val = in_be32(reg); - val |= SCC_EPCI_CLKRST_PCKEN; - out_be32(reg, val); - - /* release PCI core reset (all) */ - reg = epci_base + SCC_EPCI_CKCTRL; - val = in_be32(reg); - val |= (SCC_EPCI_CKCTRL_CRST0 | SCC_EPCI_CKCTRL_CRST1); - out_be32(reg, val); - - /* set base translation registers. (already set by Beat) */ - - /* set base address masks. (already set by Beat) */ - } - - /* release interrupt masks and clear all interrupts */ - reg = epci_base + SCC_EPCI_INTSET; - out_be32(reg, 0x013f011f); /* all interrupts enable */ - reg = epci_base + SCC_EPCI_VIENAB; - val = SCC_EPCI_VIENAB_PMPEE | SCC_EPCI_VIENAB_PMFEE; - out_be32(reg, val); - reg = epci_base + SCC_EPCI_STATUS; - out_be32(reg, 0xffffffff); - reg = epci_base + SCC_EPCI_VISTAT; - out_be32(reg, 0xffffffff); - - /* disable PCI->IB address translation */ - reg = epci_base + SCC_EPCI_VCSR; - val = in_be32(reg); - val &= ~(SCC_EPCI_VCSR_DR | SCC_EPCI_VCSR_AT); - out_be32(reg, val); - - /* set base addresses. (no need to set?) */ - - /* memory space, bus master enable */ - reg = epci_base + PCI_COMMAND; - val = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; - out_be32(reg, val); - - /* endian mode setup */ - reg = epci_base + SCC_EPCI_ECMODE; - val = 0x00550155; - out_be32(reg, val); - - /* set control option */ - reg = epci_base + SCC_EPCI_CNTOPT; - val = in_be32(reg); - val |= SCC_EPCI_CNTOPT_O2PMB; - out_be32(reg, val); - - /* XXX: temporay: set registers for address conversion setup */ - reg = epci_base + SCC_EPCI_CNF10_REG; - out_be32(reg, 0x80000008); - reg = epci_base + SCC_EPCI_CNF14_REG; - out_be32(reg, 0x40000008); - - reg = epci_base + SCC_EPCI_BAM0; - out_be32(reg, 0x80000000); - reg = epci_base + SCC_EPCI_BAM1; - out_be32(reg, 0xe0000000); - - reg = epci_base + SCC_EPCI_PVBAT; - out_be32(reg, 0x80000000); - - if (!hwres) { - /* release external PCI reset */ - reg = epci_base + SCC_EPCI_CLKRST; - val = in_be32(reg); - val |= SCC_EPCI_CLKRST_PCIRST; - out_be32(reg, val); - } - - return 0; -} - -static int __init celleb_setup_epci(struct device_node *node, - struct pci_controller *hose) -{ - struct resource r; - - pr_debug("PCI: celleb_setup_epci()\n"); - - /* - * Note: - * Celleb epci uses cfg_addr and cfg_data member of - * pci_controller structure in irregular way. - * - * cfg_addr is used to map for control registers of - * celleb epci. - * - * cfg_data is used for configuration area of devices - * on Celleb epci buses. - */ - - if (of_address_to_resource(node, 0, &r)) - goto error; - hose->cfg_addr = ioremap(r.start, resource_size(&r)); - if (!hose->cfg_addr) - goto error; - pr_debug("EPCI: cfg_addr map 0x%016llx->0x%016lx + 0x%016llx\n", - r.start, (unsigned long)hose->cfg_addr, resource_size(&r)); - - if (of_address_to_resource(node, 2, &r)) - goto error; - hose->cfg_data = ioremap(r.start, resource_size(&r)); - if (!hose->cfg_data) - goto error; - pr_debug("EPCI: cfg_data map 0x%016llx->0x%016lx + 0x%016llx\n", - r.start, (unsigned long)hose->cfg_data, resource_size(&r)); - - hose->ops = &celleb_epci_ops; - celleb_epci_init(hose); - - return 0; - -error: - if (hose->cfg_addr) - iounmap(hose->cfg_addr); - - if (hose->cfg_data) - iounmap(hose->cfg_data); - return 1; -} - -struct celleb_phb_spec celleb_epci_spec __initdata = { - .setup = celleb_setup_epci, - .ops = &spiderpci_ops, - .iowa_init = &spiderpci_iowa_init, - .iowa_data = (void *)0, -}; diff --git a/arch/powerpc/platforms/cell/celleb_scc_pciex.c b/arch/powerpc/platforms/cell/celleb_scc_pciex.c deleted file mode 100644 index 94170e4f2ce7..000000000000 --- a/arch/powerpc/platforms/cell/celleb_scc_pciex.c +++ /dev/null @@ -1,538 +0,0 @@ -/* - * Support for Celleb PCI-Express. - * - * (C) Copyright 2007-2008 TOSHIBA 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#undef DEBUG - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "celleb_scc.h" -#include "celleb_pci.h" - -#define PEX_IN(base, off) in_be32((void __iomem *)(base) + (off)) -#define PEX_OUT(base, off, data) out_be32((void __iomem *)(base) + (off), (data)) - -static void scc_pciex_io_flush(struct iowa_bus *bus) -{ - (void)PEX_IN(bus->phb->cfg_addr, PEXDMRDEN0); -} - -/* - * Memory space access to device on PCIEX - */ -#define PCIEX_MMIO_READ(name, ret) \ -static ret scc_pciex_##name(const PCI_IO_ADDR addr) \ -{ \ - ret val = __do_##name(addr); \ - scc_pciex_io_flush(iowa_mem_find_bus(addr)); \ - return val; \ -} - -#define PCIEX_MMIO_READ_STR(name) \ -static void scc_pciex_##name(const PCI_IO_ADDR addr, void *buf, \ - unsigned long count) \ -{ \ - __do_##name(addr, buf, count); \ - scc_pciex_io_flush(iowa_mem_find_bus(addr)); \ -} - -PCIEX_MMIO_READ(readb, u8) -PCIEX_MMIO_READ(readw, u16) -PCIEX_MMIO_READ(readl, u32) -PCIEX_MMIO_READ(readq, u64) -PCIEX_MMIO_READ(readw_be, u16) -PCIEX_MMIO_READ(readl_be, u32) -PCIEX_MMIO_READ(readq_be, u64) -PCIEX_MMIO_READ_STR(readsb) -PCIEX_MMIO_READ_STR(readsw) -PCIEX_MMIO_READ_STR(readsl) - -static void scc_pciex_memcpy_fromio(void *dest, const PCI_IO_ADDR src, - unsigned long n) -{ - __do_memcpy_fromio(dest, src, n); - scc_pciex_io_flush(iowa_mem_find_bus(src)); -} - -/* - * I/O port access to devices on PCIEX. - */ - -static inline unsigned long get_bus_address(struct pci_controller *phb, - unsigned long port) -{ - return port - ((unsigned long)(phb->io_base_virt) - _IO_BASE); -} - -static u32 scc_pciex_read_port(struct pci_controller *phb, - unsigned long port, int size) -{ - unsigned int byte_enable; - unsigned int cmd, shift; - unsigned long addr; - u32 data, ret; - - BUG_ON(((port & 0x3ul) + size) > 4); - - addr = get_bus_address(phb, port); - shift = addr & 0x3ul; - byte_enable = ((1 << size) - 1) << shift; - cmd = PEXDCMND_IO_READ | (byte_enable << PEXDCMND_BYTE_EN_SHIFT); - PEX_OUT(phb->cfg_addr, PEXDADRS, (addr & ~0x3ul)); - PEX_OUT(phb->cfg_addr, PEXDCMND, cmd); - data = PEX_IN(phb->cfg_addr, PEXDRDATA); - ret = (data >> (shift * 8)) & (0xFFFFFFFF >> ((4 - size) * 8)); - - pr_debug("PCIEX:PIO READ:port=0x%lx, addr=0x%lx, size=%d, be=%x," - " cmd=%x, data=%x, ret=%x\n", port, addr, size, byte_enable, - cmd, data, ret); - - return ret; -} - -static void scc_pciex_write_port(struct pci_controller *phb, - unsigned long port, int size, u32 val) -{ - unsigned int byte_enable; - unsigned int cmd, shift; - unsigned long addr; - u32 data; - - BUG_ON(((port & 0x3ul) + size) > 4); - - addr = get_bus_address(phb, port); - shift = addr & 0x3ul; - byte_enable = ((1 << size) - 1) << shift; - cmd = PEXDCMND_IO_WRITE | (byte_enable << PEXDCMND_BYTE_EN_SHIFT); - data = (val & (0xFFFFFFFF >> (4 - size) * 8)) << (shift * 8); - PEX_OUT(phb->cfg_addr, PEXDADRS, (addr & ~0x3ul)); - PEX_OUT(phb->cfg_addr, PEXDCMND, cmd); - PEX_OUT(phb->cfg_addr, PEXDWDATA, data); - - pr_debug("PCIEX:PIO WRITE:port=0x%lx, addr=%lx, size=%d, val=%x," - " be=%x, cmd=%x, data=%x\n", port, addr, size, val, - byte_enable, cmd, data); -} - -static u8 __scc_pciex_inb(struct pci_controller *phb, unsigned long port) -{ - return (u8)scc_pciex_read_port(phb, port, 1); -} - -static u16 __scc_pciex_inw(struct pci_controller *phb, unsigned long port) -{ - u32 data; - if ((port & 0x3ul) < 3) - data = scc_pciex_read_port(phb, port, 2); - else { - u32 d1 = scc_pciex_read_port(phb, port, 1); - u32 d2 = scc_pciex_read_port(phb, port + 1, 1); - data = d1 | (d2 << 8); - } - return (u16)data; -} - -static u32 __scc_pciex_inl(struct pci_controller *phb, unsigned long port) -{ - unsigned int mod = port & 0x3ul; - u32 data; - if (mod == 0) - data = scc_pciex_read_port(phb, port, 4); - else { - u32 d1 = scc_pciex_read_port(phb, port, 4 - mod); - u32 d2 = scc_pciex_read_port(phb, port + 1, mod); - data = d1 | (d2 << (mod * 8)); - } - return data; -} - -static void __scc_pciex_outb(struct pci_controller *phb, - u8 val, unsigned long port) -{ - scc_pciex_write_port(phb, port, 1, (u32)val); -} - -static void __scc_pciex_outw(struct pci_controller *phb, - u16 val, unsigned long port) -{ - if ((port & 0x3ul) < 3) - scc_pciex_write_port(phb, port, 2, (u32)val); - else { - u32 d1 = val & 0x000000FF; - u32 d2 = (val & 0x0000FF00) >> 8; - scc_pciex_write_port(phb, port, 1, d1); - scc_pciex_write_port(phb, port + 1, 1, d2); - } -} - -static void __scc_pciex_outl(struct pci_controller *phb, - u32 val, unsigned long port) -{ - unsigned int mod = port & 0x3ul; - if (mod == 0) - scc_pciex_write_port(phb, port, 4, val); - else { - u32 d1 = val & (0xFFFFFFFFul >> (mod * 8)); - u32 d2 = val >> ((4 - mod) * 8); - scc_pciex_write_port(phb, port, 4 - mod, d1); - scc_pciex_write_port(phb, port + 1, mod, d2); - } -} - -#define PCIEX_PIO_FUNC(size, name) \ -static u##size scc_pciex_in##name(unsigned long port) \ -{ \ - struct iowa_bus *bus = iowa_pio_find_bus(port); \ - u##size data = __scc_pciex_in##name(bus->phb, port); \ - scc_pciex_io_flush(bus); \ - return data; \ -} \ -static void scc_pciex_ins##name(unsigned long p, void *b, unsigned long c) \ -{ \ - struct iowa_bus *bus = iowa_pio_find_bus(p); \ - __le##size *dst = b; \ - for (; c != 0; c--, dst++) \ - *dst = cpu_to_le##size(__scc_pciex_in##name(bus->phb, p)); \ - scc_pciex_io_flush(bus); \ -} \ -static void scc_pciex_out##name(u##size val, unsigned long port) \ -{ \ - struct iowa_bus *bus = iowa_pio_find_bus(port); \ - __scc_pciex_out##name(bus->phb, val, port); \ -} \ -static void scc_pciex_outs##name(unsigned long p, const void *b, \ - unsigned long c) \ -{ \ - struct iowa_bus *bus = iowa_pio_find_bus(p); \ - const __le##size *src = b; \ - for (; c != 0; c--, src++) \ - __scc_pciex_out##name(bus->phb, le##size##_to_cpu(*src), p); \ -} -#define __le8 u8 -#define cpu_to_le8(x) (x) -#define le8_to_cpu(x) (x) -PCIEX_PIO_FUNC(8, b) -PCIEX_PIO_FUNC(16, w) -PCIEX_PIO_FUNC(32, l) - -static struct ppc_pci_io scc_pciex_ops = { - .readb = scc_pciex_readb, - .readw = scc_pciex_readw, - .readl = scc_pciex_readl, - .readq = scc_pciex_readq, - .readw_be = scc_pciex_readw_be, - .readl_be = scc_pciex_readl_be, - .readq_be = scc_pciex_readq_be, - .readsb = scc_pciex_readsb, - .readsw = scc_pciex_readsw, - .readsl = scc_pciex_readsl, - .memcpy_fromio = scc_pciex_memcpy_fromio, - .inb = scc_pciex_inb, - .inw = scc_pciex_inw, - .inl = scc_pciex_inl, - .outb = scc_pciex_outb, - .outw = scc_pciex_outw, - .outl = scc_pciex_outl, - .insb = scc_pciex_insb, - .insw = scc_pciex_insw, - .insl = scc_pciex_insl, - .outsb = scc_pciex_outsb, - .outsw = scc_pciex_outsw, - .outsl = scc_pciex_outsl, -}; - -static int __init scc_pciex_iowa_init(struct iowa_bus *bus, void *data) -{ - dma_addr_t dummy_page_da; - void *dummy_page_va; - - dummy_page_va = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!dummy_page_va) { - pr_err("PCIEX:Alloc dummy_page_va failed\n"); - return -1; - } - - dummy_page_da = dma_map_single(bus->phb->parent, dummy_page_va, - PAGE_SIZE, DMA_FROM_DEVICE); - if (dma_mapping_error(bus->phb->parent, dummy_page_da)) { - pr_err("PCIEX:Map dummy page failed.\n"); - kfree(dummy_page_va); - return -1; - } - - PEX_OUT(bus->phb->cfg_addr, PEXDMRDADR0, dummy_page_da); - - return 0; -} - -/* - * config space access - */ -#define MK_PEXDADRS(bus_no, dev_no, func_no, addr) \ - ((uint32_t)(((addr) & ~0x3UL) | \ - ((bus_no) << PEXDADRS_BUSNO_SHIFT) | \ - ((dev_no) << PEXDADRS_DEVNO_SHIFT) | \ - ((func_no) << PEXDADRS_FUNCNO_SHIFT))) - -#define MK_PEXDCMND_BYTE_EN(addr, size) \ - ((((0x1 << (size))-1) << ((addr) & 0x3)) << PEXDCMND_BYTE_EN_SHIFT) -#define MK_PEXDCMND(cmd, addr, size) ((cmd) | MK_PEXDCMND_BYTE_EN(addr, size)) - -static uint32_t config_read_pciex_dev(unsigned int __iomem *base, - uint64_t bus_no, uint64_t dev_no, uint64_t func_no, - uint64_t off, uint64_t size) -{ - uint32_t ret; - uint32_t addr, cmd; - - addr = MK_PEXDADRS(bus_no, dev_no, func_no, off); - cmd = MK_PEXDCMND(PEXDCMND_CONFIG_READ, off, size); - PEX_OUT(base, PEXDADRS, addr); - PEX_OUT(base, PEXDCMND, cmd); - ret = (PEX_IN(base, PEXDRDATA) - >> ((off & (4-size)) * 8)) & ((0x1 << (size * 8)) - 1); - return ret; -} - -static void config_write_pciex_dev(unsigned int __iomem *base, uint64_t bus_no, - uint64_t dev_no, uint64_t func_no, uint64_t off, uint64_t size, - uint32_t data) -{ - uint32_t addr, cmd; - - addr = MK_PEXDADRS(bus_no, dev_no, func_no, off); - cmd = MK_PEXDCMND(PEXDCMND_CONFIG_WRITE, off, size); - PEX_OUT(base, PEXDADRS, addr); - PEX_OUT(base, PEXDCMND, cmd); - PEX_OUT(base, PEXDWDATA, - (data & ((0x1 << (size * 8)) - 1)) << ((off & (4-size)) * 8)); -} - -#define MK_PEXCADRS_BYTE_EN(off, len) \ - ((((0x1 << (len)) - 1) << ((off) & 0x3)) << PEXCADRS_BYTE_EN_SHIFT) -#define MK_PEXCADRS(cmd, addr, size) \ - ((cmd) | MK_PEXCADRS_BYTE_EN(addr, size) | ((addr) & ~0x3)) -static uint32_t config_read_pciex_rc(unsigned int __iomem *base, - uint32_t where, uint32_t size) -{ - PEX_OUT(base, PEXCADRS, MK_PEXCADRS(PEXCADRS_CMD_READ, where, size)); - return (PEX_IN(base, PEXCRDATA) - >> ((where & (4 - size)) * 8)) & ((0x1 << (size * 8)) - 1); -} - -static void config_write_pciex_rc(unsigned int __iomem *base, uint32_t where, - uint32_t size, uint32_t val) -{ - uint32_t data; - - data = (val & ((0x1 << (size * 8)) - 1)) << ((where & (4 - size)) * 8); - PEX_OUT(base, PEXCADRS, MK_PEXCADRS(PEXCADRS_CMD_WRITE, where, size)); - PEX_OUT(base, PEXCWDATA, data); -} - -/* Interfaces */ -/* Note: Work-around - * On SCC PCIEXC, one device is seen on all 32 dev_no. - * As SCC PCIEXC can have only one device on the bus, we look only one dev_no. - * (dev_no = 1) - */ -static int scc_pciex_read_config(struct pci_bus *bus, unsigned int devfn, - int where, int size, unsigned int *val) -{ - struct pci_controller *phb = pci_bus_to_host(bus); - - if (bus->number == phb->first_busno && PCI_SLOT(devfn) != 1) { - *val = ~0; - return PCIBIOS_DEVICE_NOT_FOUND; - } - - if (bus->number == 0 && PCI_SLOT(devfn) == 0) - *val = config_read_pciex_rc(phb->cfg_addr, where, size); - else - *val = config_read_pciex_dev(phb->cfg_addr, bus->number, - PCI_SLOT(devfn), PCI_FUNC(devfn), where, size); - - return PCIBIOS_SUCCESSFUL; -} - -static int scc_pciex_write_config(struct pci_bus *bus, unsigned int devfn, - int where, int size, unsigned int val) -{ - struct pci_controller *phb = pci_bus_to_host(bus); - - if (bus->number == phb->first_busno && PCI_SLOT(devfn) != 1) - return PCIBIOS_DEVICE_NOT_FOUND; - - if (bus->number == 0 && PCI_SLOT(devfn) == 0) - config_write_pciex_rc(phb->cfg_addr, where, size, val); - else - config_write_pciex_dev(phb->cfg_addr, bus->number, - PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, val); - return PCIBIOS_SUCCESSFUL; -} - -static struct pci_ops scc_pciex_pci_ops = { - .read = scc_pciex_read_config, - .write = scc_pciex_write_config, -}; - -static void pciex_clear_intr_all(unsigned int __iomem *base) -{ - PEX_OUT(base, PEXAERRSTS, 0xffffffff); - PEX_OUT(base, PEXPRERRSTS, 0xffffffff); - PEX_OUT(base, PEXINTSTS, 0xffffffff); -} - -#if 0 -static void pciex_disable_intr_all(unsigned int *base) -{ - PEX_OUT(base, PEXINTMASK, 0x0); - PEX_OUT(base, PEXAERRMASK, 0x0); - PEX_OUT(base, PEXPRERRMASK, 0x0); - PEX_OUT(base, PEXVDMASK, 0x0); -} -#endif - -static void pciex_enable_intr_all(unsigned int __iomem *base) -{ - PEX_OUT(base, PEXINTMASK, 0x0000e7f1); - PEX_OUT(base, PEXAERRMASK, 0x03ff01ff); - PEX_OUT(base, PEXPRERRMASK, 0x0001010f); - PEX_OUT(base, PEXVDMASK, 0x00000001); -} - -static void pciex_check_status(unsigned int __iomem *base) -{ - uint32_t err = 0; - uint32_t intsts, aerr, prerr, rcvcp, lenerr; - uint32_t maea, maec; - - intsts = PEX_IN(base, PEXINTSTS); - aerr = PEX_IN(base, PEXAERRSTS); - prerr = PEX_IN(base, PEXPRERRSTS); - rcvcp = PEX_IN(base, PEXRCVCPLIDA); - lenerr = PEX_IN(base, PEXLENERRIDA); - - if (intsts || aerr || prerr || rcvcp || lenerr) - err = 1; - - pr_info("PCEXC interrupt!!\n"); - pr_info("PEXINTSTS :0x%08x\n", intsts); - pr_info("PEXAERRSTS :0x%08x\n", aerr); - pr_info("PEXPRERRSTS :0x%08x\n", prerr); - pr_info("PEXRCVCPLIDA :0x%08x\n", rcvcp); - pr_info("PEXLENERRIDA :0x%08x\n", lenerr); - - /* print detail of Protection Error */ - if (intsts & 0x00004000) { - uint32_t i, n; - for (i = 0; i < 4; i++) { - n = 1 << i; - if (prerr & n) { - maea = PEX_IN(base, PEXMAEA(i)); - maec = PEX_IN(base, PEXMAEC(i)); - pr_info("PEXMAEC%d :0x%08x\n", i, maec); - pr_info("PEXMAEA%d :0x%08x\n", i, maea); - } - } - } - - if (err) - pciex_clear_intr_all(base); -} - -static irqreturn_t pciex_handle_internal_irq(int irq, void *dev_id) -{ - struct pci_controller *phb = dev_id; - - pr_debug("PCIEX:pciex_handle_internal_irq(irq=%d)\n", irq); - - BUG_ON(phb->cfg_addr == NULL); - - pciex_check_status(phb->cfg_addr); - - return IRQ_HANDLED; -} - -static __init int celleb_setup_pciex(struct device_node *node, - struct pci_controller *phb) -{ - struct resource r; - int virq; - - /* SMMIO registers; used inside this file */ - if (of_address_to_resource(node, 0, &r)) { - pr_err("PCIEXC:Failed to get config resource.\n"); - return 1; - } - phb->cfg_addr = ioremap(r.start, resource_size(&r)); - if (!phb->cfg_addr) { - pr_err("PCIEXC:Failed to remap SMMIO region.\n"); - return 1; - } - - /* Not use cfg_data, cmd and data regs are near address reg */ - phb->cfg_data = NULL; - - /* set pci_ops */ - phb->ops = &scc_pciex_pci_ops; - - /* internal interrupt handler */ - virq = irq_of_parse_and_map(node, 1); - if (!virq) { - pr_err("PCIEXC:Failed to map irq\n"); - goto error; - } - if (request_irq(virq, pciex_handle_internal_irq, - 0, "pciex", (void *)phb)) { - pr_err("PCIEXC:Failed to request irq\n"); - goto error; - } - - /* enable all interrupts */ - pciex_clear_intr_all(phb->cfg_addr); - pciex_enable_intr_all(phb->cfg_addr); - /* MSI: TBD */ - - return 0; - -error: - phb->cfg_data = NULL; - if (phb->cfg_addr) - iounmap(phb->cfg_addr); - phb->cfg_addr = NULL; - return 1; -} - -struct celleb_phb_spec celleb_pciex_spec __initdata = { - .setup = celleb_setup_pciex, - .ops = &scc_pciex_ops, - .iowa_init = &scc_pciex_iowa_init, -}; diff --git a/arch/powerpc/platforms/cell/celleb_scc_sio.c b/arch/powerpc/platforms/cell/celleb_scc_sio.c deleted file mode 100644 index c8eb57193826..000000000000 --- a/arch/powerpc/platforms/cell/celleb_scc_sio.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * setup serial port in SCC - * - * (C) Copyright 2006-2007 TOSHIBA 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include -#include -#include - -#include -#include - -/* sio irq0=0xb00010022 irq0=0xb00010023 irq2=0xb00010024 - mmio=0xfff000-0x1000,0xff2000-0x1000 */ -static int txx9_serial_bitmap __initdata; - -static struct { - uint32_t offset; - uint32_t index; -} txx9_scc_tab[3] __initdata = { - { 0x300, 0 }, /* 0xFFF300 */ - { 0x400, 0 }, /* 0xFFF400 */ - { 0x800, 1 } /* 0xFF2800 */ -}; - -static int __init txx9_serial_init(void) -{ - extern int early_serial_txx9_setup(struct uart_port *port); - struct device_node *node; - int i; - struct uart_port req; - struct of_phandle_args irq; - struct resource res; - - for_each_compatible_node(node, "serial", "toshiba,sio-scc") { - for (i = 0; i < ARRAY_SIZE(txx9_scc_tab); i++) { - if (!(txx9_serial_bitmap & (1< UHC_RESET_WAIT_MAX) { - printk(KERN_ERR "Failed to disable UHC reset %x\n", - in_be32(uhc_clkctrl)); - break; - } - } - - /* Endian Conversion Mode for Master ALL area */ - out_be32(uhc_ecmode, SCC_UHC_ECMODE_BY_BYTE); - - iounmap(uhc_base); -} - -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA_2, - PCI_DEVICE_ID_TOSHIBA_SCC_USB, enable_scc_uhc); diff --git a/arch/powerpc/platforms/cell/celleb_setup.c b/arch/powerpc/platforms/cell/celleb_setup.c deleted file mode 100644 index 90be8ec51686..000000000000 --- a/arch/powerpc/platforms/cell/celleb_setup.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Celleb setup code - * - * (C) Copyright 2006-2007 TOSHIBA CORPORATION - * - * This code is based on arch/powerpc/platforms/cell/setup.c: - * Copyright (C) 1995 Linus Torvalds - * Adapted from 'alpha' version by Gary Thomas - * Modified by Cort Dougan (cort@cs.nmt.edu) - * Modified by PPC64 Team, IBM Corp - * Modified by Cell Team, IBM Deutschland Entwicklung GmbH - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#undef DEBUG - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "beat_interrupt.h" -#include "beat_wrapper.h" -#include "beat.h" -#include "celleb_pci.h" -#include "interrupt.h" -#include "pervasive.h" -#include "ras.h" - -static char celleb_machine_type[128] = "Celleb"; - -static void celleb_show_cpuinfo(struct seq_file *m) -{ - struct device_node *root; - const char *model = ""; - - root = of_find_node_by_path("/"); - if (root) - model = of_get_property(root, "model", NULL); - /* using "CHRP" is to trick anaconda into installing FCx into Celleb */ - seq_printf(m, "machine\t\t: %s %s\n", celleb_machine_type, model); - of_node_put(root); -} - -static int __init celleb_machine_type_hack(char *ptr) -{ - strlcpy(celleb_machine_type, ptr, sizeof(celleb_machine_type)); - return 0; -} - -__setup("celleb_machine_type_hack=", celleb_machine_type_hack); - -static void celleb_progress(char *s, unsigned short hex) -{ - printk("*** %04x : %s\n", hex, s ? s : ""); -} - -static void __init celleb_setup_arch_common(void) -{ - /* init to some ~sane value until calibrate_delay() runs */ - loops_per_jiffy = 50000000; - -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif -} - -static const struct of_device_id celleb_bus_ids[] __initconst = { - { .type = "scc", }, - { .type = "ioif", }, /* old style */ - {}, -}; - -static int __init celleb_publish_devices(void) -{ - /* Publish OF platform devices for southbridge IOs */ - of_platform_bus_probe(NULL, celleb_bus_ids, NULL); - - return 0; -} -machine_device_initcall(celleb_beat, celleb_publish_devices); -machine_device_initcall(celleb_native, celleb_publish_devices); - - -/* - * functions for Celleb-Beat - */ -static void __init celleb_setup_arch_beat(void) -{ -#ifdef CONFIG_SPU_BASE - spu_priv1_ops = &spu_priv1_beat_ops; - spu_management_ops = &spu_management_of_ops; -#endif - - celleb_setup_arch_common(); -} - -static int __init celleb_probe_beat(void) -{ - unsigned long root = of_get_flat_dt_root(); - - if (!of_flat_dt_is_compatible(root, "Beat")) - return 0; - - powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS - | FW_FEATURE_BEAT | FW_FEATURE_LPAR; - hpte_init_beat_v3(); - pm_power_off = beat_power_off; - - return 1; -} - - -/* - * functions for Celleb-native - */ -static void __init celleb_init_IRQ_native(void) -{ - iic_init_IRQ(); - spider_init_IRQ(); -} - -static void __init celleb_setup_arch_native(void) -{ -#ifdef CONFIG_SPU_BASE - spu_priv1_ops = &spu_priv1_mmio_ops; - spu_management_ops = &spu_management_of_ops; -#endif - - cbe_regs_init(); - -#ifdef CONFIG_CBE_RAS - cbe_ras_init(); -#endif - -#ifdef CONFIG_SMP - smp_init_cell(); -#endif - - cbe_pervasive_init(); - - /* XXX: nvram initialization should be added */ - - celleb_setup_arch_common(); -} - -static int __init celleb_probe_native(void) -{ - unsigned long root = of_get_flat_dt_root(); - - if (of_flat_dt_is_compatible(root, "Beat") || - !of_flat_dt_is_compatible(root, "TOSHIBA,Celleb")) - return 0; - - powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS; - hpte_init_native(); - pm_power_off = rtas_power_off; - - return 1; -} - - -/* - * machine definitions - */ -define_machine(celleb_beat) { - .name = "Cell Reference Set (Beat)", - .probe = celleb_probe_beat, - .setup_arch = celleb_setup_arch_beat, - .show_cpuinfo = celleb_show_cpuinfo, - .restart = beat_restart, - .halt = beat_halt, - .get_rtc_time = beat_get_rtc_time, - .set_rtc_time = beat_set_rtc_time, - .calibrate_decr = generic_calibrate_decr, - .progress = celleb_progress, - .power_save = beat_power_save, - .nvram_size = beat_nvram_get_size, - .nvram_read = beat_nvram_read, - .nvram_write = beat_nvram_write, - .set_dabr = beat_set_xdabr, - .init_IRQ = beatic_init_IRQ, - .get_irq = beatic_get_irq, - .pci_probe_mode = celleb_pci_probe_mode, - .pci_setup_phb = celleb_setup_phb, -#ifdef CONFIG_KEXEC - .kexec_cpu_down = beat_kexec_cpu_down, -#endif -}; - -define_machine(celleb_native) { - .name = "Cell Reference Set (native)", - .probe = celleb_probe_native, - .setup_arch = celleb_setup_arch_native, - .show_cpuinfo = celleb_show_cpuinfo, - .restart = rtas_restart, - .halt = rtas_halt, - .get_boot_time = rtas_get_boot_time, - .get_rtc_time = rtas_get_rtc_time, - .set_rtc_time = rtas_set_rtc_time, - .calibrate_decr = generic_calibrate_decr, - .progress = celleb_progress, - .pci_probe_mode = celleb_pci_probe_mode, - .pci_setup_phb = celleb_setup_phb, - .init_IRQ = celleb_init_IRQ_native, -}; diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index c7c8720aa39f..31b1a67daccf 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c @@ -1234,5 +1234,3 @@ static int __init cell_iommu_init(void) return 0; } machine_arch_initcall(cell, cell_iommu_init); -machine_arch_initcall(celleb_native, cell_iommu_init); - -- cgit v1.2.3 From 4f9c53c8cc76ed84e3bb0cca8c4ffa2b170d0239 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 25 Mar 2015 20:11:57 +1100 Subject: powerpc: Fix compile errors with STRICT_MM_TYPECHECKS enabled Signed-off-by: Aneesh Kumar K.V [mpe: Fix the 32-bit code also] Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/kvm_book3s_64.h | 12 +++++++----- arch/powerpc/mm/dma-noncoherent.c | 2 +- arch/powerpc/mm/fsl_booke_mmu.c | 2 +- arch/powerpc/mm/hugepage-hash64.c | 2 +- arch/powerpc/mm/hugetlbpage.c | 4 ++-- arch/powerpc/mm/pgtable_32.c | 4 ++-- arch/powerpc/mm/pgtable_64.c | 2 +- arch/powerpc/mm/tlb_hash64.c | 2 +- 8 files changed, 16 insertions(+), 14 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h index 2a244bf869c0..14619a59ec09 100644 --- a/arch/powerpc/include/asm/kvm_book3s_64.h +++ b/arch/powerpc/include/asm/kvm_book3s_64.h @@ -290,11 +290,11 @@ static inline pte_t kvmppc_read_update_linux_pte(pte_t *ptep, int writing, pte_t old_pte, new_pte = __pte(0); while (1) { - old_pte = pte_val(*ptep); + old_pte = *ptep; /* * wait until _PAGE_BUSY is clear then set it atomically */ - if (unlikely(old_pte & _PAGE_BUSY)) { + if (unlikely(pte_val(old_pte) & _PAGE_BUSY)) { cpu_relax(); continue; } @@ -305,16 +305,18 @@ static inline pte_t kvmppc_read_update_linux_pte(pte_t *ptep, int writing, return __pte(0); #endif /* If pte is not present return None */ - if (unlikely(!(old_pte & _PAGE_PRESENT))) + if (unlikely(!(pte_val(old_pte) & _PAGE_PRESENT))) return __pte(0); new_pte = pte_mkyoung(old_pte); if (writing && pte_write(old_pte)) new_pte = pte_mkdirty(new_pte); - if (old_pte == __cmpxchg_u64((unsigned long *)ptep, old_pte, - new_pte)) + if (pte_val(old_pte) == __cmpxchg_u64((unsigned long *)ptep, + pte_val(old_pte), + pte_val(new_pte))) { break; + } } return new_pte; } diff --git a/arch/powerpc/mm/dma-noncoherent.c b/arch/powerpc/mm/dma-noncoherent.c index d85e86aac7fb..169aba446a74 100644 --- a/arch/powerpc/mm/dma-noncoherent.c +++ b/arch/powerpc/mm/dma-noncoherent.c @@ -228,7 +228,7 @@ __dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t do { SetPageReserved(page); map_page(vaddr, page_to_phys(page), - pgprot_noncached(PAGE_KERNEL)); + pgprot_val(pgprot_noncached(PAGE_KERNEL))); page++; vaddr += PAGE_SIZE; } while (size -= PAGE_SIZE); diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c index b46912fee7cd..9c90e66cffb6 100644 --- a/arch/powerpc/mm/fsl_booke_mmu.c +++ b/arch/powerpc/mm/fsl_booke_mmu.c @@ -181,7 +181,7 @@ static unsigned long map_mem_in_cams_addr(phys_addr_t phys, unsigned long virt, unsigned long cam_sz; cam_sz = calc_cam_sz(ram, virt, phys); - settlbcam(i, virt, phys, cam_sz, PAGE_KERNEL_X, 0); + settlbcam(i, virt, phys, cam_sz, pgprot_val(PAGE_KERNEL_X), 0); ram -= cam_sz; amount_mapped += cam_sz; diff --git a/arch/powerpc/mm/hugepage-hash64.c b/arch/powerpc/mm/hugepage-hash64.c index 86686514ae13..43dafb9d6a46 100644 --- a/arch/powerpc/mm/hugepage-hash64.c +++ b/arch/powerpc/mm/hugepage-hash64.c @@ -33,7 +33,7 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, * atomically mark the linux large page PMD busy and dirty */ do { - pmd_t pmd = ACCESS_ONCE(*pmdp); + pmd_t pmd = READ_ONCE(*pmdp); old_pmd = pmd_val(pmd); /* If PMD busy, retry the access */ diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index 7e408bfc7948..fa9d5c238d22 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c @@ -964,7 +964,7 @@ pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift *shift = 0; pgdp = pgdir + pgd_index(ea); - pgd = ACCESS_ONCE(*pgdp); + pgd = READ_ONCE(*pgdp); /* * Always operate on the local stack value. This make sure the * value don't get updated by a parallel THP split/collapse, @@ -1045,7 +1045,7 @@ int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long addr, if (pte_end < end) end = pte_end; - pte = ACCESS_ONCE(*ptep); + pte = READ_ONCE(*ptep); mask = _PAGE_PRESENT | _PAGE_USER; if (write) mask |= _PAGE_RW; diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index 1bc1762f358d..70b4752af54f 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c @@ -189,7 +189,7 @@ __ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags, /* Make sure we have the base flags */ if ((flags & _PAGE_PRESENT) == 0) - flags |= PAGE_KERNEL; + flags |= pgprot_val(PAGE_KERNEL); /* Non-cacheable page cannot be coherent */ if (flags & _PAGE_NO_CACHE) @@ -324,7 +324,7 @@ void __init __mapin_ram_chunk(unsigned long offset, unsigned long top) p = memstart_addr + s; for (; s < top; s += PAGE_SIZE) { ktext = ((char *) v >= _stext && (char *) v < etext); - f = ktext ? PAGE_KERNEL_TEXT : PAGE_KERNEL; + f = ktext ? pgprot_val(PAGE_KERNEL_TEXT) : pgprot_val(PAGE_KERNEL); map_page(v, p, f); #ifdef CONFIG_PPC_STD_MMU_32 if (ktext) diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index 6957cc1ca0a7..3ac3a0a1edfb 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c @@ -723,7 +723,7 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr, assert_spin_locked(&mm->page_table_lock); WARN_ON(!pmd_trans_huge(pmd)); #endif - trace_hugepage_set_pmd(addr, pmd); + trace_hugepage_set_pmd(addr, pmd_val(pmd)); return set_pte_at(mm, addr, pmdp_ptep(pmdp), pmd_pte(pmd)); } diff --git a/arch/powerpc/mm/tlb_hash64.c b/arch/powerpc/mm/tlb_hash64.c index d2a94b85dbc2..c522969f012d 100644 --- a/arch/powerpc/mm/tlb_hash64.c +++ b/arch/powerpc/mm/tlb_hash64.c @@ -216,7 +216,7 @@ void __flush_hash_table_range(struct mm_struct *mm, unsigned long start, continue; pte = pte_val(*ptep); if (hugepage_shift) - trace_hugepage_invalidate(start, pte_val(pte)); + trace_hugepage_invalidate(start, pte); if (!(pte & _PAGE_HASHPTE)) continue; if (unlikely(hugepage_shift && pmd_trans_huge(*(pmd_t *)pte))) -- cgit v1.2.3 From f691fa1080c37c48da0cdfeae082c3bef5df2643 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Mon, 30 Mar 2015 14:10:37 +1100 Subject: powerpc: Replace mem_init_done with slab_is_available() We have a powerpc specific global called mem_init_done which is "set on boot once kmalloc can be called". But that's not *quite* true. We set it at the bottom of mem_init(), and rely on the fact that mm_init() calls kmem_cache_init() immediately after that, and nothing is running in parallel. So replace it with the generic and 100% correct slab_is_available(). Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/setup.h | 1 - arch/powerpc/kernel/pci-common.c | 2 +- arch/powerpc/kernel/rtas.c | 4 ++-- arch/powerpc/lib/alloc.c | 2 +- arch/powerpc/mm/mem.c | 3 --- arch/powerpc/mm/pgtable_32.c | 9 ++++----- arch/powerpc/mm/pgtable_64.c | 4 ++-- 7 files changed, 10 insertions(+), 15 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/setup.h b/arch/powerpc/include/asm/setup.h index fbdf18cf954c..e9d384cbd021 100644 --- a/arch/powerpc/include/asm/setup.h +++ b/arch/powerpc/include/asm/setup.h @@ -7,7 +7,6 @@ extern void ppc_printk_progress(char *s, unsigned short hex); extern unsigned int rtas_data; -extern int mem_init_done; /* set on boot once kmalloc can be called */ extern unsigned long long memory_limit; extern unsigned long klimit; extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask); diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 2a525c938158..bcf618bfff1e 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -76,7 +76,7 @@ struct pci_controller *pcibios_alloc_controller(struct device_node *dev) list_add_tail(&phb->list_node, &hose_list); spin_unlock(&hose_spinlock); phb->dn = dev; - phb->is_dynamic = mem_init_done; + phb->is_dynamic = slab_is_available(); #ifdef CONFIG_PPC64 if (dev) { int nid = of_node_to_nid(dev); diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index b9a7b8981ef7..7a488c108410 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -401,7 +401,7 @@ static char *__fetch_rtas_last_error(char *altbuf) buf = altbuf; } else { buf = rtas_err_buf; - if (mem_init_done) + if (slab_is_available()) buf = kmalloc(RTAS_ERROR_LOG_MAX, GFP_ATOMIC); } if (buf) @@ -461,7 +461,7 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...) if (buff_copy) { log_error(buff_copy, ERR_TYPE_RTAS_LOG, 0); - if (mem_init_done) + if (slab_is_available()) kfree(buff_copy); } return ret; diff --git a/arch/powerpc/lib/alloc.c b/arch/powerpc/lib/alloc.c index 4a6c2cf890d9..60b0b3fc8fc1 100644 --- a/arch/powerpc/lib/alloc.c +++ b/arch/powerpc/lib/alloc.c @@ -10,7 +10,7 @@ void * __init_refok zalloc_maybe_bootmem(size_t size, gfp_t mask) { void *p; - if (mem_init_done) + if (slab_is_available()) p = kzalloc(size, mask); else { p = memblock_virt_alloc(size, 0); diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index b7285a5870f8..45fda71feb27 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -61,7 +61,6 @@ #define CPU_FTR_NOEXECUTE 0 #endif -int mem_init_done; unsigned long long memory_limit; #ifdef CONFIG_HIGHMEM @@ -377,8 +376,6 @@ void __init mem_init(void) pr_info(" * 0x%08lx..0x%08lx : vmalloc & ioremap\n", VMALLOC_START, VMALLOC_END); #endif /* CONFIG_PPC32 */ - - mem_init_done = 1; } void free_initmem(void) diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index 70b4752af54f..7692d1bb1bc6 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c @@ -107,9 +107,8 @@ void pgd_free(struct mm_struct *mm, pgd_t *pgd) __init_refok pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) { pte_t *pte; - extern int mem_init_done; - if (mem_init_done) { + if (slab_is_available()) { pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO); } else { pte = __va(memblock_alloc(PAGE_SIZE, PAGE_SIZE)); @@ -216,7 +215,7 @@ __ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags, * Don't allow anybody to remap normal RAM that we're using. * mem_init() sets high_memory so only do the check after that. */ - if (mem_init_done && (p < virt_to_phys(high_memory)) && + if (slab_is_available() && (p < virt_to_phys(high_memory)) && !(__allow_ioremap_reserved && memblock_is_region_reserved(p, size))) { printk("__ioremap(): phys addr 0x%llx is RAM lr %ps\n", (unsigned long long)p, __builtin_return_address(0)); @@ -244,7 +243,7 @@ __ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags, if ((v = p_mapped_by_tlbcam(p))) goto out; - if (mem_init_done) { + if (slab_is_available()) { struct vm_struct *area; area = get_vm_area_caller(size, VM_IOREMAP, caller); if (area == 0) @@ -263,7 +262,7 @@ __ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags, for (i = 0; i < size && err == 0; i += PAGE_SIZE) err = map_page(v+i, p+i, flags); if (err) { - if (mem_init_done) + if (slab_is_available()) vunmap((void *)v); return NULL; } diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index 3ac3a0a1edfb..59daa5eeec25 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c @@ -231,7 +231,7 @@ void __iomem * __ioremap_caller(phys_addr_t addr, unsigned long size, if ((size == 0) || (paligned == 0)) return NULL; - if (mem_init_done) { + if (slab_is_available()) { struct vm_struct *area; area = __get_vm_area_caller(size, VM_IOREMAP, @@ -315,7 +315,7 @@ void __iounmap(volatile void __iomem *token) { void *addr; - if (!mem_init_done) + if (!slab_is_available()) return; addr = (void *) ((unsigned long __force) -- cgit v1.2.3 From a7f4ee1fe93aa9ae191971be9324edb8f9fbcb4a Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Sat, 4 Apr 2015 19:28:50 +1100 Subject: powerpc: Drop return value of smp_ops->probe() smp_ops->probe() is currently supposed to return the number of cpus in the system. The last actual usage of the value was removed in May 2007 in e147ec8f1808 "[POWERPC] Simplify smp_space_timers". We still passed the value around until June 2010 when even that was finally removed in c1aa687d499a "powerpc: Clean up obsolete code relating to decrementer and timebase". So drop that requirement, probe() now returns void, and update all implementations. Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/smp.h | 4 ++-- arch/powerpc/include/asm/xics.h | 2 +- arch/powerpc/platforms/cell/smp.c | 9 +-------- arch/powerpc/platforms/powermac/smp.c | 8 +++----- arch/powerpc/platforms/ps3/smp.c | 4 +--- arch/powerpc/platforms/pseries/smp.c | 6 ++---- arch/powerpc/sysdev/mpic.c | 4 +--- arch/powerpc/sysdev/xics/xics-common.c | 4 +--- 8 files changed, 12 insertions(+), 29 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h index 7c19959cd705..825663c30945 100644 --- a/arch/powerpc/include/asm/smp.h +++ b/arch/powerpc/include/asm/smp.h @@ -42,7 +42,7 @@ struct smp_ops_t { #ifdef CONFIG_PPC_SMP_MUXED_IPI void (*cause_ipi)(int cpu, unsigned long data); #endif - int (*probe)(void); + void (*probe)(void); int (*kick_cpu)(int nr); void (*setup_cpu)(int nr); void (*bringup_done)(void); @@ -174,7 +174,7 @@ static inline void set_hard_smp_processor_id(int cpu, int phys) extern int smt_enabled_at_boot; -extern int smp_mpic_probe(void); +extern void smp_mpic_probe(void); extern void smp_mpic_setup_cpu(int cpu); extern int smp_generic_kick_cpu(int nr); extern int smp_generic_cpu_bootable(unsigned int nr); diff --git a/arch/powerpc/include/asm/xics.h b/arch/powerpc/include/asm/xics.h index 6997f4a271df..0e25bdb190bb 100644 --- a/arch/powerpc/include/asm/xics.h +++ b/arch/powerpc/include/asm/xics.h @@ -146,7 +146,7 @@ extern void xics_update_irq_servers(void); extern void xics_set_cpu_giq(unsigned int gserver, unsigned int join); extern void xics_mask_unknown_vec(unsigned int vec); extern irqreturn_t xics_ipi_dispatch(int cpu); -extern int xics_smp_probe(void); +extern void xics_smp_probe(void); extern void xics_register_ics(struct ics *ics); extern void xics_teardown_cpu(void); extern void xics_kexec_teardown_cpu(int secondary); diff --git a/arch/powerpc/platforms/cell/smp.c b/arch/powerpc/platforms/cell/smp.c index b64e7ead752f..895560f4be69 100644 --- a/arch/powerpc/platforms/cell/smp.c +++ b/arch/powerpc/platforms/cell/smp.c @@ -102,13 +102,6 @@ static inline int smp_startup_cpu(unsigned int lcpu) return 1; } -static int __init smp_iic_probe(void) -{ - iic_request_IPIs(); - - return num_possible_cpus(); -} - static void smp_cell_setup_cpu(int cpu) { if (cpu != boot_cpuid) @@ -139,7 +132,7 @@ static int smp_cell_kick_cpu(int nr) static struct smp_ops_t bpa_iic_smp_ops = { .message_pass = iic_message_pass, - .probe = smp_iic_probe, + .probe = iic_request_IPIs, .kick_cpu = smp_cell_kick_cpu, .setup_cpu = smp_cell_setup_cpu, .cpu_bootable = smp_generic_cpu_bootable, diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index af094ae03dbb..f84ac7ee1107 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c @@ -268,7 +268,7 @@ static void __init psurge_quad_init(void) mdelay(33); } -static int __init smp_psurge_probe(void) +static void __init smp_psurge_probe(void) { int i, ncpus; struct device_node *dn; @@ -766,7 +766,7 @@ static void __init smp_core99_setup(int ncpus) powersave_nap = 0; } -static int __init smp_core99_probe(void) +static void __init smp_core99_probe(void) { struct device_node *cpus; int ncpus = 0; @@ -781,7 +781,7 @@ static int __init smp_core99_probe(void) /* Nothing more to do if less than 2 of them */ if (ncpus <= 1) - return 1; + return; /* We need to perform some early initialisations before we can start * setting up SMP as we are running before initcalls @@ -797,8 +797,6 @@ static int __init smp_core99_probe(void) /* Collect l2cr and l3cr values from CPU 0 */ core99_init_caches(0); - - return ncpus; } static int smp_core99_kick_cpu(int nr) diff --git a/arch/powerpc/platforms/ps3/smp.c b/arch/powerpc/platforms/ps3/smp.c index b358bec6c8cb..3c7707af3384 100644 --- a/arch/powerpc/platforms/ps3/smp.c +++ b/arch/powerpc/platforms/ps3/smp.c @@ -57,7 +57,7 @@ static void ps3_smp_message_pass(int cpu, int msg) " (%d)\n", __func__, __LINE__, cpu, msg, result); } -static int __init ps3_smp_probe(void) +static void __init ps3_smp_probe(void) { int cpu; @@ -100,8 +100,6 @@ static int __init ps3_smp_probe(void) DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu); } - - return 2; } void ps3_smp_cleanup_cpu(int cpu) diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index a3555b10c1a5..6932ea803e33 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c @@ -197,16 +197,14 @@ static void pSeries_cause_ipi_mux(int cpu, unsigned long data) xics_cause_ipi(cpu, data); } -static __init int pSeries_smp_probe(void) +static __init void pSeries_smp_probe(void) { - int ret = xics_smp_probe(); + xics_smp_probe(); if (cpu_has_feature(CPU_FTR_DBELL)) { xics_cause_ipi = smp_ops->cause_ipi; smp_ops->cause_ipi = pSeries_cause_ipi_mux; } - - return ret; } static struct smp_ops_t pSeries_mpic_smp_ops = { diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index fb19084c5860..b2b8447a227a 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -1897,7 +1897,7 @@ void smp_mpic_message_pass(int cpu, int msg) msg * MPIC_INFO(CPU_IPI_DISPATCH_STRIDE), physmask); } -int __init smp_mpic_probe(void) +void __init smp_mpic_probe(void) { int nr_cpus; @@ -1909,8 +1909,6 @@ int __init smp_mpic_probe(void) if (nr_cpus > 1) mpic_request_ipis(); - - return nr_cpus; } void smp_mpic_setup_cpu(int cpu) diff --git a/arch/powerpc/sysdev/xics/xics-common.c b/arch/powerpc/sysdev/xics/xics-common.c index 125743b58c70..878a54036a25 100644 --- a/arch/powerpc/sysdev/xics/xics-common.c +++ b/arch/powerpc/sysdev/xics/xics-common.c @@ -140,15 +140,13 @@ static void xics_request_ipi(void) IRQF_PERCPU | IRQF_NO_THREAD, "IPI", NULL)); } -int __init xics_smp_probe(void) +void __init xics_smp_probe(void) { /* Setup cause_ipi callback based on which ICP is used */ smp_ops->cause_ipi = icp_ops->cause_ipi; /* Register all the IPIs */ xics_request_ipi(); - - return num_possible_cpus(); } #endif /* CONFIG_SMP */ -- cgit v1.2.3 From bdc728a849a7047e55014c6f968aa300cc9f57fa Mon Sep 17 00:00:00 2001 From: Daniel Axtens Date: Tue, 31 Mar 2015 16:00:39 +1100 Subject: powerpc: move find_and_init_phbs() to pSeries specific code Previously, find_and_init_phbs() was used in both PowerNV and pSeries setup. However, since RTAS support has been dropped from PowerNV, we can move it into a platform-specific file. Signed-off-by: Daniel Axtens Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/ppc-pci.h | 3 --- arch/powerpc/kernel/rtas_pci.c | 47 ---------------------------------- arch/powerpc/platforms/pseries/setup.c | 47 ++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 50 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/ppc-pci.h b/arch/powerpc/include/asm/ppc-pci.h index ade75238ceb5..4122a86d6858 100644 --- a/arch/powerpc/include/asm/ppc-pci.h +++ b/arch/powerpc/include/asm/ppc-pci.h @@ -23,8 +23,6 @@ extern void pci_setup_phb_io_dynamic(struct pci_controller *hose, int primary); extern struct list_head hose_list; -extern void find_and_init_phbs(void); - extern struct pci_dev *isa_bridge_pcidev; /* may be NULL if no ISA bus */ /** Bus Unit ID macros; get low and hi 32-bits of the 64-bit BUID */ @@ -81,7 +79,6 @@ static inline const char *eeh_driver_name(struct pci_dev *pdev) #endif /* CONFIG_EEH */ #else /* CONFIG_PCI */ -static inline void find_and_init_phbs(void) { } static inline void init_pci_config_tokens(void) { } #endif /* !CONFIG_PCI */ diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index af29df2517f7..73f1934582c2 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c @@ -277,50 +277,3 @@ int rtas_setup_phb(struct pci_controller *phb) return 0; } - -void __init find_and_init_phbs(void) -{ - struct device_node *node; - struct pci_controller *phb; - struct device_node *root = of_find_node_by_path("/"); - - for_each_child_of_node(root, node) { - if (node->type == NULL || (strcmp(node->type, "pci") != 0 && - strcmp(node->type, "pciex") != 0)) - continue; - - phb = pcibios_alloc_controller(node); - if (!phb) - continue; - rtas_setup_phb(phb); - pci_process_bridge_OF_ranges(phb, node, 0); - isa_bridge_find_early(phb); - } - - of_node_put(root); - pci_devs_phb_init(); - - /* - * PCI_PROBE_ONLY and PCI_REASSIGN_ALL_BUS can be set via properties - * in chosen. - */ - if (of_chosen) { - const int *prop; - - prop = of_get_property(of_chosen, - "linux,pci-probe-only", NULL); - if (prop) { - if (*prop) - pci_add_flags(PCI_PROBE_ONLY); - else - pci_clear_flags(PCI_PROBE_ONLY); - } - -#ifdef CONFIG_PPC32 /* Will be made generic soon */ - prop = of_get_property(of_chosen, - "linux,pci-assign-all-buses", NULL); - if (prop && *prop) - pci_add_flags(PCI_REASSIGN_ALL_BUS); -#endif /* CONFIG_PPC32 */ - } -} diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 70304070a260..bcc6d24c77aa 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -461,6 +461,53 @@ static long pseries_little_endian_exceptions(void) } #endif +static void __init find_and_init_phbs(void) +{ + struct device_node *node; + struct pci_controller *phb; + struct device_node *root = of_find_node_by_path("/"); + + for_each_child_of_node(root, node) { + if (node->type == NULL || (strcmp(node->type, "pci") != 0 && + strcmp(node->type, "pciex") != 0)) + continue; + + phb = pcibios_alloc_controller(node); + if (!phb) + continue; + rtas_setup_phb(phb); + pci_process_bridge_OF_ranges(phb, node, 0); + isa_bridge_find_early(phb); + } + + of_node_put(root); + pci_devs_phb_init(); + + /* + * PCI_PROBE_ONLY and PCI_REASSIGN_ALL_BUS can be set via properties + * in chosen. + */ + if (of_chosen) { + const int *prop; + + prop = of_get_property(of_chosen, + "linux,pci-probe-only", NULL); + if (prop) { + if (*prop) + pci_add_flags(PCI_PROBE_ONLY); + else + pci_clear_flags(PCI_PROBE_ONLY); + } + +#ifdef CONFIG_PPC32 /* Will be made generic soon */ + prop = of_get_property(of_chosen, + "linux,pci-assign-all-buses", NULL); + if (prop && *prop) + pci_add_flags(PCI_REASSIGN_ALL_BUS); +#endif /* CONFIG_PPC32 */ + } +} + static void __init pSeries_setup_arch(void) { set_arch_panic_timeout(10, ARCH_PANIC_TIMEOUT); -- cgit v1.2.3 From c88c2a188905cb3077c3c38dc498e7e9f8eebeee Mon Sep 17 00:00:00 2001 From: Daniel Axtens Date: Tue, 31 Mar 2015 16:00:41 +1100 Subject: powerpc: pcibios_enable_device_hook: return bool rather than int pcibios_enable_device_hook returned an int. Every implementation returned either -EINVAL or 0. The return value wasn't propagated by the caller: any non-zero return value caused pcibios_enable_device to return -EINVAL itself. Therefore, make the hook return a bool. Signed-off-by: Daniel Axtens Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/machdep.h | 4 ++-- arch/powerpc/kernel/pci-common.c | 2 +- arch/powerpc/platforms/powermac/pci.c | 8 ++++---- arch/powerpc/platforms/powermac/pmac.h | 2 +- arch/powerpc/platforms/powernv/pci-ioda.c | 8 ++++---- 5 files changed, 12 insertions(+), 12 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index 098d51e924ea..e29f058c0903 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h @@ -237,9 +237,9 @@ struct machdep_calls { /* Called for each PCI bus in the system when it's probed */ void (*pcibios_fixup_bus)(struct pci_bus *); - /* Called when pci_enable_device() is called. Returns 0 to + /* Called when pci_enable_device() is called. Returns true to * allow assignment/enabling of the device. */ - int (*pcibios_enable_device_hook)(struct pci_dev *); + bool (*pcibios_enable_device_hook)(struct pci_dev *); /* Called after scan and before resource survey */ void (*pcibios_fixup_phb)(struct pci_controller *hose); diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index bcf618bfff1e..17827c7345a7 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -1451,7 +1451,7 @@ EXPORT_SYMBOL_GPL(pcibios_finish_adding_to_bus); int pcibios_enable_device(struct pci_dev *dev, int mask) { if (ppc_md.pcibios_enable_device_hook) - if (ppc_md.pcibios_enable_device_hook(dev)) + if (!ppc_md.pcibios_enable_device_hook(dev)) return -EINVAL; return pci_enable_resources(dev, mask); diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index a792f4552442..9c89fd29da60 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c @@ -942,7 +942,7 @@ void __init pmac_pci_init(void) } #ifdef CONFIG_PPC32 -int pmac_pci_enable_device_hook(struct pci_dev *dev) +bool pmac_pci_enable_device_hook(struct pci_dev *dev) { struct device_node* node; int updatecfg = 0; @@ -958,11 +958,11 @@ int pmac_pci_enable_device_hook(struct pci_dev *dev) && !node) { printk(KERN_INFO "Apple USB OHCI %s disabled by firmware\n", pci_name(dev)); - return -EINVAL; + return false; } if (!node) - return 0; + return true; uninorth_child = node->parent && of_device_is_compatible(node->parent, "uni-north"); @@ -1003,7 +1003,7 @@ int pmac_pci_enable_device_hook(struct pci_dev *dev) L1_CACHE_BYTES >> 2); } - return 0; + return true; } void pmac_pci_fixup_ohci(struct pci_dev *dev) diff --git a/arch/powerpc/platforms/powermac/pmac.h b/arch/powerpc/platforms/powermac/pmac.h index 46d219345537..b8d572159faa 100644 --- a/arch/powerpc/platforms/powermac/pmac.h +++ b/arch/powerpc/platforms/powermac/pmac.h @@ -25,7 +25,7 @@ extern void pmac_pci_init(void); extern void pmac_nvram_update(void); extern unsigned char pmac_nvram_read_byte(int addr); extern void pmac_nvram_write_byte(int addr, unsigned char val); -extern int pmac_pci_enable_device_hook(struct pci_dev *dev); +extern bool pmac_pci_enable_device_hook(struct pci_dev *dev); extern void pmac_pcibios_after_init(void); extern int of_show_percpuinfo(struct seq_file *m, int i); diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 76b344125cef..f93d6c2bd743 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -1911,7 +1911,7 @@ static resource_size_t pnv_pci_window_alignment(struct pci_bus *bus, /* Prevent enabling devices for which we couldn't properly * assign a PE */ -static int pnv_pci_enable_device_hook(struct pci_dev *dev) +static bool pnv_pci_enable_device_hook(struct pci_dev *dev) { struct pci_controller *hose = pci_bus_to_host(dev->bus); struct pnv_phb *phb = hose->private_data; @@ -1923,13 +1923,13 @@ static int pnv_pci_enable_device_hook(struct pci_dev *dev) * PEs isn't ready. */ if (!phb->initialized) - return 0; + return true; pdn = pci_get_pdn(dev); if (!pdn || pdn->pe_number == IODA_INVALID_PE) - return -EINVAL; + return false; - return 0; + return true; } static u32 pnv_ioda_bdfn_to_pe(struct pnv_phb *phb, struct pci_bus *bus, -- cgit v1.2.3 From e02def5bce12b472e9eb6dcdd9f7af72239e6330 Mon Sep 17 00:00:00 2001 From: Daniel Axtens Date: Tue, 31 Mar 2015 16:00:42 +1100 Subject: powerpc: Create pci_controller_ops.dma_dev_setup and shim Introduces the pci_controller_ops structure. Add pci_controller_ops.dma_dev_setup, shadowing ppc_md.pci_dma_dev_setup. Add a shim, and change the callsites to use the shim. Signed-off-by: Daniel Axtens Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/pci-bridge.h | 21 +++++++++++++++++++++ arch/powerpc/kernel/pci-common.c | 3 +-- 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 2c6dc2a3d14a..0f441b8e1ea1 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -14,6 +14,13 @@ struct device_node; +/* + * PCI controller operations + */ +struct pci_controller_ops { + void (*dma_dev_setup)(struct pci_dev *dev); +}; + /* * Structure of a PCI controller (host bridge) */ @@ -46,6 +53,7 @@ struct pci_controller { resource_size_t isa_mem_phys; resource_size_t isa_mem_size; + struct pci_controller_ops controller_ops; struct pci_ops *ops; unsigned int __iomem *cfg_addr; void __iomem *cfg_data; @@ -260,5 +268,18 @@ static inline int pcibios_vaddr_is_ioport(void __iomem *address) } #endif /* CONFIG_PCI */ +/* + * Shims to prefer pci_controller version over ppc_md where available. + */ +static inline void pci_dma_dev_setup(struct pci_dev *dev) +{ + struct pci_controller *phb = pci_bus_to_host(dev->bus); + + if (phb->controller_ops.dma_dev_setup) + phb->controller_ops.dma_dev_setup(dev); + else if (ppc_md.pci_dma_dev_setup) + ppc_md.pci_dma_dev_setup(dev); +} + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_PCI_BRIDGE_H */ diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 17827c7345a7..7e3757e403d4 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -969,8 +969,7 @@ static void pcibios_setup_device(struct pci_dev *dev) set_dma_offset(&dev->dev, PCI_DRAM_OFFSET); /* Additional platform DMA/iommu setup */ - if (ppc_md.pci_dma_dev_setup) - ppc_md.pci_dma_dev_setup(dev); + pci_dma_dev_setup(dev); /* Read default IRQs and fixup if necessary */ pci_read_irq_line(dev); -- cgit v1.2.3 From b122c95494374ab848f8d9f41d98644c2c318ecc Mon Sep 17 00:00:00 2001 From: Daniel Axtens Date: Tue, 31 Mar 2015 16:00:43 +1100 Subject: powerpc: Create pci_controller_ops.dma_bus_setup and shim Add pci_controller_ops.dma_bus_setup, shadowing ppc_md.pci_dma_bus_setup. Add a shim, and changes the callsites to use the shim. Signed-off-by: Daniel Axtens Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/pci-bridge.h | 11 +++++++++++ arch/powerpc/kernel/pci-common.c | 3 +-- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 0f441b8e1ea1..b9732fcb0f5f 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -19,6 +19,7 @@ struct device_node; */ struct pci_controller_ops { void (*dma_dev_setup)(struct pci_dev *dev); + void (*dma_bus_setup)(struct pci_bus *bus); }; /* @@ -281,5 +282,15 @@ static inline void pci_dma_dev_setup(struct pci_dev *dev) ppc_md.pci_dma_dev_setup(dev); } +static inline void pci_dma_bus_setup(struct pci_bus *bus) +{ + struct pci_controller *phb = pci_bus_to_host(bus); + + if (phb->controller_ops.dma_bus_setup) + phb->controller_ops.dma_bus_setup(bus); + else if (ppc_md.pci_dma_bus_setup) + ppc_md.pci_dma_bus_setup(bus); +} + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_PCI_BRIDGE_H */ diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 7e3757e403d4..af357cc38ff6 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -953,8 +953,7 @@ void pcibios_setup_bus_self(struct pci_bus *bus) ppc_md.pcibios_fixup_bus(bus); /* Setup bus DMA mappings */ - if (ppc_md.pci_dma_bus_setup) - ppc_md.pci_dma_bus_setup(bus); + pci_dma_bus_setup(bus); } static void pcibios_setup_device(struct pci_dev *dev) -- cgit v1.2.3 From ff9df8c87d6807e90c5c3b0e1fd1649d09fd3bcd Mon Sep 17 00:00:00 2001 From: Daniel Axtens Date: Tue, 31 Mar 2015 16:00:44 +1100 Subject: powerpc: Create pci_controller_ops.probe_mode and shim Add pci_controller_ops.probe_mode, shadowing ppc_md.pci_probe_mode. Add a shim, and changes the callsites to use the shim. We also need to move the probe mode defines to pci-bridge.h from pci.h. They are required by the shim in order to return a sensible default. Previously, the were defined in pci.h, but pci.h includes pci-bridge.h before the relevant #defines. This means the definitions are absent if pci.h is included before pci-bridge.h. This occurs in some drivers. So, move the definitons now, and move them back when we remove the shim. Anything that wants the defines would have had to include pci.h, and since pci.h includes pci-bridge.h, nothing will lose access to the defines. Signed-off-by: Daniel Axtens Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/pci-bridge.h | 18 ++++++++++++++++++ arch/powerpc/include/asm/pci.h | 5 ----- arch/powerpc/kernel/pci-common.c | 4 ++-- arch/powerpc/kernel/pci-hotplug.c | 3 +-- arch/powerpc/kernel/pci_of_scan.c | 3 +-- 5 files changed, 22 insertions(+), 11 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index b9732fcb0f5f..278f48978bad 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -12,6 +12,11 @@ #include #include +/* Return values for pci_controller_ops.probe_mode function */ +#define PCI_PROBE_NONE -1 /* Don't look at this bus at all */ +#define PCI_PROBE_NORMAL 0 /* Do normal PCI probing */ +#define PCI_PROBE_DEVTREE 1 /* Instantiate from device tree */ + struct device_node; /* @@ -20,6 +25,8 @@ struct device_node; struct pci_controller_ops { void (*dma_dev_setup)(struct pci_dev *dev); void (*dma_bus_setup)(struct pci_bus *bus); + + int (*probe_mode)(struct pci_bus *); }; /* @@ -292,5 +299,16 @@ static inline void pci_dma_bus_setup(struct pci_bus *bus) ppc_md.pci_dma_bus_setup(bus); } +static inline int pci_probe_mode(struct pci_bus *bus) +{ + struct pci_controller *phb = pci_bus_to_host(bus); + + if (phb->controller_ops.probe_mode) + return phb->controller_ops.probe_mode(bus); + if (ppc_md.pci_probe_mode) + return ppc_md.pci_probe_mode(bus); + return PCI_PROBE_NORMAL; +} + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_PCI_BRIDGE_H */ diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h index 1b0739bc14b5..8745067ac702 100644 --- a/arch/powerpc/include/asm/pci.h +++ b/arch/powerpc/include/asm/pci.h @@ -22,11 +22,6 @@ #include -/* Return values for ppc_md.pci_probe_mode function */ -#define PCI_PROBE_NONE -1 /* Don't look at this bus at all */ -#define PCI_PROBE_NORMAL 0 /* Do normal PCI probing */ -#define PCI_PROBE_DEVTREE 1 /* Instantiate from device tree */ - #define PCIBIOS_MIN_IO 0x1000 #define PCIBIOS_MIN_MEM 0x10000000 diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index af357cc38ff6..b0de23c89ca5 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -1622,8 +1622,8 @@ void pcibios_scan_phb(struct pci_controller *hose) /* Get probe mode and perform scan */ mode = PCI_PROBE_NORMAL; - if (node && ppc_md.pci_probe_mode) - mode = ppc_md.pci_probe_mode(bus); + if (node) + mode = pci_probe_mode(bus); pr_debug(" probe mode: %d\n", mode); if (mode == PCI_PROBE_DEVTREE) of_scan_bus(node, bus); diff --git a/arch/powerpc/kernel/pci-hotplug.c b/arch/powerpc/kernel/pci-hotplug.c index 18d9575729a3..27116b1b2d14 100644 --- a/arch/powerpc/kernel/pci-hotplug.c +++ b/arch/powerpc/kernel/pci-hotplug.c @@ -78,8 +78,7 @@ void pcibios_add_pci_devices(struct pci_bus * bus) eeh_add_device_tree_early(PCI_DN(dn)); mode = PCI_PROBE_NORMAL; - if (ppc_md.pci_probe_mode) - mode = ppc_md.pci_probe_mode(bus); + mode = pci_probe_mode(bus); if (mode == PCI_PROBE_DEVTREE) { /* use ofdt-based probe */ diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c index 7122dfece393..4ee63c4f077e 100644 --- a/arch/powerpc/kernel/pci_of_scan.c +++ b/arch/powerpc/kernel/pci_of_scan.c @@ -287,8 +287,7 @@ void of_scan_pci_bridge(struct pci_dev *dev) pr_debug(" bus name: %s\n", bus->name); mode = PCI_PROBE_NORMAL; - if (ppc_md.pci_probe_mode) - mode = ppc_md.pci_probe_mode(bus); + mode = pci_probe_mode(bus); pr_debug(" probe mode: %d\n", mode); if (mode == PCI_PROBE_DEVTREE) -- cgit v1.2.3 From b31e79f8d92ca115a935e37cfd4da74048739689 Mon Sep 17 00:00:00 2001 From: Daniel Axtens Date: Tue, 31 Mar 2015 16:00:45 +1100 Subject: powerpc: Create pci_controller_ops.enable_device_hook and shim Add pci_controller_ops.enable_device_hook, shadowing ppc_md.pcibios_enable_device_hook. Add a shim, and changes the callsites to use the shim. Signed-off-by: Daniel Axtens Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/pci-bridge.h | 15 +++++++++++++++ arch/powerpc/kernel/pci-common.c | 5 ++--- 2 files changed, 17 insertions(+), 3 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 278f48978bad..9d02ea6255ff 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -27,6 +27,10 @@ struct pci_controller_ops { void (*dma_bus_setup)(struct pci_bus *bus); int (*probe_mode)(struct pci_bus *); + + /* Called when pci_enable_device() is called. Returns true to + * allow assignment/enabling of the device. */ + bool (*enable_device_hook)(struct pci_dev *); }; /* @@ -310,5 +314,16 @@ static inline int pci_probe_mode(struct pci_bus *bus) return PCI_PROBE_NORMAL; } +static inline bool pcibios_enable_device_hook(struct pci_dev *dev) +{ + struct pci_controller *phb = pci_bus_to_host(dev->bus); + + if (phb->controller_ops.enable_device_hook) + return phb->controller_ops.enable_device_hook(dev); + if (ppc_md.pcibios_enable_device_hook) + return ppc_md.pcibios_enable_device_hook(dev); + return true; +} + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_PCI_BRIDGE_H */ diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index b0de23c89ca5..8639e9cd65d5 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -1448,9 +1448,8 @@ EXPORT_SYMBOL_GPL(pcibios_finish_adding_to_bus); int pcibios_enable_device(struct pci_dev *dev, int mask) { - if (ppc_md.pcibios_enable_device_hook) - if (!ppc_md.pcibios_enable_device_hook(dev)) - return -EINVAL; + if (!pcibios_enable_device_hook(dev)) + return -EINVAL; return pci_enable_resources(dev, mask); } -- cgit v1.2.3 From 542070baf4a0fe9de14cc2c4ca3ff1b43f14f90f Mon Sep 17 00:00:00 2001 From: Daniel Axtens Date: Tue, 31 Mar 2015 16:00:46 +1100 Subject: powerpc: Create pci_controller_ops.window_alignment and shim Add pci_controller_ops.window_alignment, shadowing ppc_md.pcibios_window_alignment. Add a shim, and changes the callsites to use the shim. Here, we use pci_window_alignment, as pcibios_window_alignment is already taken. Signed-off-by: Daniel Axtens Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/pci-bridge.h | 21 +++++++++++++++++++++ arch/powerpc/kernel/pci-common.c | 10 +--------- 2 files changed, 22 insertions(+), 9 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 9d02ea6255ff..ed4f8ce803bb 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -31,6 +31,9 @@ struct pci_controller_ops { /* Called when pci_enable_device() is called. Returns true to * allow assignment/enabling of the device. */ bool (*enable_device_hook)(struct pci_dev *); + + /* Called during PCI resource reassignment */ + resource_size_t (*window_alignment)(struct pci_bus *, unsigned long type); }; /* @@ -325,5 +328,23 @@ static inline bool pcibios_enable_device_hook(struct pci_dev *dev) return true; } +static inline resource_size_t pci_window_alignment(struct pci_bus *bus, + unsigned long type) +{ + struct pci_controller *phb = pci_bus_to_host(bus); + + if (phb->controller_ops.window_alignment) + return phb->controller_ops.window_alignment(bus, type); + if (ppc_md.pcibios_window_alignment) + return ppc_md.pcibios_window_alignment(bus, type); + + /* + * PCI core will figure out the default + * alignment: 4KiB for I/O and 1MiB for + * memory window. + */ + return 1; +} + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_PCI_BRIDGE_H */ diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 8639e9cd65d5..698e0328d9c3 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -109,15 +109,7 @@ void pcibios_free_controller(struct pci_controller *phb) resource_size_t pcibios_window_alignment(struct pci_bus *bus, unsigned long type) { - if (ppc_md.pcibios_window_alignment) - return ppc_md.pcibios_window_alignment(bus, type); - - /* - * PCI core will figure out the default - * alignment: 4KiB for I/O and 1MiB for - * memory window. - */ - return 1; + return pci_window_alignment(bus, type); } void pcibios_reset_secondary_bus(struct pci_dev *dev) -- cgit v1.2.3 From cd16c7ba0cc21aa1563e4b8430519b6488d0de60 Mon Sep 17 00:00:00 2001 From: Daniel Axtens Date: Tue, 31 Mar 2015 16:00:47 +1100 Subject: powerpc: Create pci_controller_ops.reset_secondary_bus and shim Add pci_controller_ops.reset_secondary_bus, shadowing ppc_md.pcibios_reset_secondary_bus. Add a shim, and changes the callsites to use the shim. Use pcibios_reset_secondary_bus_shim, as both pcibios_reset_secondary_bus and pci_reset_secondary_bus are already taken. Signed-off-by: Daniel Axtens Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/pci-bridge.h | 17 +++++++++++++++++ arch/powerpc/kernel/pci-common.c | 7 +------ 2 files changed, 18 insertions(+), 6 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index ed4f8ce803bb..bb34b1eebfbe 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -34,6 +34,7 @@ struct pci_controller_ops { /* Called during PCI resource reassignment */ resource_size_t (*window_alignment)(struct pci_bus *, unsigned long type); + void (*reset_secondary_bus)(struct pci_dev *dev); }; /* @@ -346,5 +347,21 @@ static inline resource_size_t pci_window_alignment(struct pci_bus *bus, return 1; } +static inline void pcibios_reset_secondary_bus_shim(struct pci_dev *dev) +{ + struct pci_controller *phb = pci_bus_to_host(dev->bus); + + if (phb->controller_ops.reset_secondary_bus) + phb->controller_ops.reset_secondary_bus(dev); + else if (ppc_md.pcibios_reset_secondary_bus) + ppc_md.pcibios_reset_secondary_bus(dev); + else + /* + * Fallback to the generic function if no + * platform-specific one is provided + */ + pci_reset_secondary_bus(dev); +} + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_PCI_BRIDGE_H */ diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 698e0328d9c3..759eb1c87638 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -114,12 +114,7 @@ resource_size_t pcibios_window_alignment(struct pci_bus *bus, void pcibios_reset_secondary_bus(struct pci_dev *dev) { - if (ppc_md.pcibios_reset_secondary_bus) { - ppc_md.pcibios_reset_secondary_bus(dev); - return; - } - - pci_reset_secondary_bus(dev); + pcibios_reset_secondary_bus_shim(dev); } static resource_size_t pcibios_io_size(const struct pci_controller *hose) -- cgit v1.2.3 From 798248a3c083a4cf0ead44a85e66c6a18647abea Mon Sep 17 00:00:00 2001 From: Daniel Axtens Date: Tue, 31 Mar 2015 16:00:48 +1100 Subject: powerpc: dart_iommu: optionally populate controller_ops on init If a pci_controller_ops struct is provided to iommu_init_early_dart, populate that with the DMA setup ops, rather than ppc_md. If NULL is provided, populate ppc_md as before. This also patches the call sites for Maple and Power Mac to pass NULL, so existing behaviour is preserved. The benefit of making this optional is that it means we don't have to change dart, Maple and Power Mac over to the controller_ops system in one fell swoop. Signed-off-by: Daniel Axtens Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/iommu.h | 3 ++- arch/powerpc/platforms/maple/setup.c | 2 +- arch/powerpc/platforms/powermac/setup.c | 2 +- arch/powerpc/sysdev/dart_iommu.c | 16 ++++++++++++---- 4 files changed, 16 insertions(+), 7 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h index f1ea5972f6ec..0be7d9e13189 100644 --- a/arch/powerpc/include/asm/iommu.h +++ b/arch/powerpc/include/asm/iommu.h @@ -29,6 +29,7 @@ #include #include #include +#include #define IOMMU_PAGE_SHIFT_4K 12 #define IOMMU_PAGE_SIZE_4K (ASM_CONST(1) << IOMMU_PAGE_SHIFT_4K) @@ -169,7 +170,7 @@ extern void iommu_unmap_page(struct iommu_table *tbl, dma_addr_t dma_handle, struct dma_attrs *attrs); extern void iommu_init_early_pSeries(void); -extern void iommu_init_early_dart(void); +extern void iommu_init_early_dart(struct pci_controller_ops *controller_ops); extern void iommu_init_early_pasemi(void); extern void alloc_dart_table(void); diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index 56b85cd61aaf..3bf2e0359d5e 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c @@ -203,7 +203,7 @@ static void __init maple_init_early(void) { DBG(" -> maple_init_early\n"); - iommu_init_early_dart(); + iommu_init_early_dart(NULL); DBG(" <- maple_init_early\n"); } diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index efe172db5f8e..71a353c07d0c 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -473,7 +473,7 @@ static void __init pmac_init_early(void) udbg_adb_init(!!strstr(boot_command_line, "btextdbg")); #ifdef CONFIG_PPC64 - iommu_init_early_dart(); + iommu_init_early_dart(NULL); #endif /* SMP Init has to be done early as we need to patch up diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index 9e5353ff6d1b..120e96a9e2cb 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c @@ -369,7 +369,7 @@ static int dart_dma_set_mask(struct device *dev, u64 dma_mask) return 0; } -void __init iommu_init_early_dart(void) +void __init iommu_init_early_dart(struct pci_controller_ops *controller_ops) { struct device_node *dn; @@ -395,15 +395,23 @@ void __init iommu_init_early_dart(void) if (dart_is_u4) ppc_md.dma_set_mask = dart_dma_set_mask; - ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_dart; - ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_dart; - + if (controller_ops) { + controller_ops->dma_dev_setup = pci_dma_dev_setup_dart; + controller_ops->dma_bus_setup = pci_dma_bus_setup_dart; + } else { + ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_dart; + ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_dart; + } /* Setup pci_dma ops */ set_pci_dma_ops(&dma_iommu_ops); return; bail: /* If init failed, use direct iommu and null setup functions */ + if (controller_ops) { + controller_ops->dma_dev_setup = NULL; + controller_ops->dma_bus_setup = NULL; + } ppc_md.pci_dma_dev_setup = NULL; ppc_md.pci_dma_bus_setup = NULL; -- cgit v1.2.3 From 467efc2e4fdc44e6cd4be7dd4adf01c14b3d148e Mon Sep 17 00:00:00 2001 From: Daniel Axtens Date: Tue, 31 Mar 2015 16:00:56 +1100 Subject: powerpc: Remove shims for pci_controller_ops operations Remove shims, patch callsites to use pci_controller_ops versions instead. Also move back the probe mode defines, as explained in the patch for pci_probe_mode. Signed-off-by: Daniel Axtens Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/machdep.h | 14 ------ arch/powerpc/include/asm/pci-bridge.h | 84 ----------------------------------- arch/powerpc/include/asm/pci.h | 5 +++ arch/powerpc/kernel/pci-common.c | 43 ++++++++++++++---- arch/powerpc/kernel/pci-hotplug.c | 6 ++- arch/powerpc/kernel/pci_of_scan.c | 6 ++- arch/powerpc/sysdev/dart_iommu.c | 5 --- 7 files changed, 50 insertions(+), 113 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index e29f058c0903..5c19ac527a8e 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h @@ -103,9 +103,6 @@ struct machdep_calls { #endif #endif /* CONFIG_PPC64 */ - void (*pci_dma_dev_setup)(struct pci_dev *dev); - void (*pci_dma_bus_setup)(struct pci_bus *bus); - /* Platform set_dma_mask and dma_get_required_mask overrides */ int (*dma_set_mask)(struct device *dev, u64 dma_mask); u64 (*dma_get_required_mask)(struct device *dev); @@ -127,7 +124,6 @@ struct machdep_calls { /* PCI stuff */ /* Called after allocating resources */ void (*pcibios_fixup)(void); - int (*pci_probe_mode)(struct pci_bus *); void (*pci_irq_fixup)(struct pci_dev *dev); int (*pcibios_root_bridge_prepare)(struct pci_host_bridge *bridge); @@ -237,19 +233,9 @@ struct machdep_calls { /* Called for each PCI bus in the system when it's probed */ void (*pcibios_fixup_bus)(struct pci_bus *); - /* Called when pci_enable_device() is called. Returns true to - * allow assignment/enabling of the device. */ - bool (*pcibios_enable_device_hook)(struct pci_dev *); - /* Called after scan and before resource survey */ void (*pcibios_fixup_phb)(struct pci_controller *hose); - /* Called during PCI resource reassignment */ - resource_size_t (*pcibios_window_alignment)(struct pci_bus *, unsigned long type); - - /* Reset the secondary bus of bridge */ - void (*pcibios_reset_secondary_bus)(struct pci_dev *dev); - /* Called to shutdown machine specific hardware not already controlled * by other drivers. */ diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index bb34b1eebfbe..7d972bc85638 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -12,11 +12,6 @@ #include #include -/* Return values for pci_controller_ops.probe_mode function */ -#define PCI_PROBE_NONE -1 /* Don't look at this bus at all */ -#define PCI_PROBE_NORMAL 0 /* Do normal PCI probing */ -#define PCI_PROBE_DEVTREE 1 /* Instantiate from device tree */ - struct device_node; /* @@ -284,84 +279,5 @@ static inline int pcibios_vaddr_is_ioport(void __iomem *address) } #endif /* CONFIG_PCI */ -/* - * Shims to prefer pci_controller version over ppc_md where available. - */ -static inline void pci_dma_dev_setup(struct pci_dev *dev) -{ - struct pci_controller *phb = pci_bus_to_host(dev->bus); - - if (phb->controller_ops.dma_dev_setup) - phb->controller_ops.dma_dev_setup(dev); - else if (ppc_md.pci_dma_dev_setup) - ppc_md.pci_dma_dev_setup(dev); -} - -static inline void pci_dma_bus_setup(struct pci_bus *bus) -{ - struct pci_controller *phb = pci_bus_to_host(bus); - - if (phb->controller_ops.dma_bus_setup) - phb->controller_ops.dma_bus_setup(bus); - else if (ppc_md.pci_dma_bus_setup) - ppc_md.pci_dma_bus_setup(bus); -} - -static inline int pci_probe_mode(struct pci_bus *bus) -{ - struct pci_controller *phb = pci_bus_to_host(bus); - - if (phb->controller_ops.probe_mode) - return phb->controller_ops.probe_mode(bus); - if (ppc_md.pci_probe_mode) - return ppc_md.pci_probe_mode(bus); - return PCI_PROBE_NORMAL; -} - -static inline bool pcibios_enable_device_hook(struct pci_dev *dev) -{ - struct pci_controller *phb = pci_bus_to_host(dev->bus); - - if (phb->controller_ops.enable_device_hook) - return phb->controller_ops.enable_device_hook(dev); - if (ppc_md.pcibios_enable_device_hook) - return ppc_md.pcibios_enable_device_hook(dev); - return true; -} - -static inline resource_size_t pci_window_alignment(struct pci_bus *bus, - unsigned long type) -{ - struct pci_controller *phb = pci_bus_to_host(bus); - - if (phb->controller_ops.window_alignment) - return phb->controller_ops.window_alignment(bus, type); - if (ppc_md.pcibios_window_alignment) - return ppc_md.pcibios_window_alignment(bus, type); - - /* - * PCI core will figure out the default - * alignment: 4KiB for I/O and 1MiB for - * memory window. - */ - return 1; -} - -static inline void pcibios_reset_secondary_bus_shim(struct pci_dev *dev) -{ - struct pci_controller *phb = pci_bus_to_host(dev->bus); - - if (phb->controller_ops.reset_secondary_bus) - phb->controller_ops.reset_secondary_bus(dev); - else if (ppc_md.pcibios_reset_secondary_bus) - ppc_md.pcibios_reset_secondary_bus(dev); - else - /* - * Fallback to the generic function if no - * platform-specific one is provided - */ - pci_reset_secondary_bus(dev); -} - #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_PCI_BRIDGE_H */ diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h index 8745067ac702..4aef8d660999 100644 --- a/arch/powerpc/include/asm/pci.h +++ b/arch/powerpc/include/asm/pci.h @@ -22,6 +22,11 @@ #include +/* Return values for pci_controller_ops.probe_mode function */ +#define PCI_PROBE_NONE -1 /* Don't look at this bus at all */ +#define PCI_PROBE_NORMAL 0 /* Do normal PCI probing */ +#define PCI_PROBE_DEVTREE 1 /* Instantiate from device tree */ + #define PCIBIOS_MIN_IO 0x1000 #define PCIBIOS_MIN_MEM 0x10000000 diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 759eb1c87638..9052b4fbc41f 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -109,12 +109,29 @@ void pcibios_free_controller(struct pci_controller *phb) resource_size_t pcibios_window_alignment(struct pci_bus *bus, unsigned long type) { - return pci_window_alignment(bus, type); + struct pci_controller *phb = pci_bus_to_host(bus); + + if (phb->controller_ops.window_alignment) + return phb->controller_ops.window_alignment(bus, type); + + /* + * PCI core will figure out the default + * alignment: 4KiB for I/O and 1MiB for + * memory window. + */ + return 1; } void pcibios_reset_secondary_bus(struct pci_dev *dev) { - pcibios_reset_secondary_bus_shim(dev); + struct pci_controller *phb = pci_bus_to_host(dev->bus); + + if (phb->controller_ops.reset_secondary_bus) { + phb->controller_ops.reset_secondary_bus(dev); + return; + } + + pci_reset_secondary_bus(dev); } static resource_size_t pcibios_io_size(const struct pci_controller *hose) @@ -929,6 +946,8 @@ static void pcibios_fixup_bridge(struct pci_bus *bus) void pcibios_setup_bus_self(struct pci_bus *bus) { + struct pci_controller *phb; + /* Fix up the bus resources for P2P bridges */ if (bus->self != NULL) pcibios_fixup_bridge(bus); @@ -940,11 +959,14 @@ void pcibios_setup_bus_self(struct pci_bus *bus) ppc_md.pcibios_fixup_bus(bus); /* Setup bus DMA mappings */ - pci_dma_bus_setup(bus); + phb = pci_bus_to_host(bus); + if (phb->controller_ops.dma_bus_setup) + phb->controller_ops.dma_bus_setup(bus); } static void pcibios_setup_device(struct pci_dev *dev) { + struct pci_controller *phb; /* Fixup NUMA node as it may not be setup yet by the generic * code and is needed by the DMA init */ @@ -955,7 +977,9 @@ static void pcibios_setup_device(struct pci_dev *dev) set_dma_offset(&dev->dev, PCI_DRAM_OFFSET); /* Additional platform DMA/iommu setup */ - pci_dma_dev_setup(dev); + phb = pci_bus_to_host(dev->bus); + if (phb->controller_ops.dma_dev_setup) + phb->controller_ops.dma_dev_setup(dev); /* Read default IRQs and fixup if necessary */ pci_read_irq_line(dev); @@ -1435,8 +1459,11 @@ EXPORT_SYMBOL_GPL(pcibios_finish_adding_to_bus); int pcibios_enable_device(struct pci_dev *dev, int mask) { - if (!pcibios_enable_device_hook(dev)) - return -EINVAL; + struct pci_controller *phb = pci_bus_to_host(dev->bus); + + if (phb->controller_ops.enable_device_hook) + if (!phb->controller_ops.enable_device_hook(dev)) + return -EINVAL; return pci_enable_resources(dev, mask); } @@ -1608,8 +1635,8 @@ void pcibios_scan_phb(struct pci_controller *hose) /* Get probe mode and perform scan */ mode = PCI_PROBE_NORMAL; - if (node) - mode = pci_probe_mode(bus); + if (node && hose->controller_ops.probe_mode) + mode = hose->controller_ops.probe_mode(bus); pr_debug(" probe mode: %d\n", mode); if (mode == PCI_PROBE_DEVTREE) of_scan_bus(node, bus); diff --git a/arch/powerpc/kernel/pci-hotplug.c b/arch/powerpc/kernel/pci-hotplug.c index 27116b1b2d14..7ed85a69a9c2 100644 --- a/arch/powerpc/kernel/pci-hotplug.c +++ b/arch/powerpc/kernel/pci-hotplug.c @@ -73,12 +73,16 @@ void pcibios_add_pci_devices(struct pci_bus * bus) { int slotno, mode, pass, max; struct pci_dev *dev; + struct pci_controller *phb; struct device_node *dn = pci_bus_to_OF_node(bus); eeh_add_device_tree_early(PCI_DN(dn)); + phb = pci_bus_to_host(bus); + mode = PCI_PROBE_NORMAL; - mode = pci_probe_mode(bus); + if (phb->controller_ops.probe_mode) + mode = phb->controller_ops.probe_mode(bus); if (mode == PCI_PROBE_DEVTREE) { /* use ofdt-based probe */ diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c index 4ee63c4f077e..42e02a2d570b 100644 --- a/arch/powerpc/kernel/pci_of_scan.c +++ b/arch/powerpc/kernel/pci_of_scan.c @@ -207,6 +207,7 @@ void of_scan_pci_bridge(struct pci_dev *dev) { struct device_node *node = dev->dev.of_node; struct pci_bus *bus; + struct pci_controller *phb; const __be32 *busrange, *ranges; int len, i, mode; struct pci_bus_region region; @@ -286,8 +287,11 @@ void of_scan_pci_bridge(struct pci_dev *dev) bus->number); pr_debug(" bus name: %s\n", bus->name); + phb = pci_bus_to_host(bus); + mode = PCI_PROBE_NORMAL; - mode = pci_probe_mode(bus); + if (phb->controller_ops.probe_mode) + mode = phb->controller_ops.probe_mode(bus); pr_debug(" probe mode: %d\n", mode); if (mode == PCI_PROBE_DEVTREE) diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index 120e96a9e2cb..87b80009bc9f 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c @@ -398,9 +398,6 @@ void __init iommu_init_early_dart(struct pci_controller_ops *controller_ops) if (controller_ops) { controller_ops->dma_dev_setup = pci_dma_dev_setup_dart; controller_ops->dma_bus_setup = pci_dma_bus_setup_dart; - } else { - ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_dart; - ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_dart; } /* Setup pci_dma ops */ set_pci_dma_ops(&dma_iommu_ops); @@ -412,8 +409,6 @@ void __init iommu_init_early_dart(struct pci_controller_ops *controller_ops) controller_ops->dma_dev_setup = NULL; controller_ops->dma_bus_setup = NULL; } - ppc_md.pci_dma_dev_setup = NULL; - ppc_md.pci_dma_bus_setup = NULL; /* Setup pci_dma ops */ set_pci_dma_ops(&dma_direct_ops); -- cgit v1.2.3 From ed59190e41b725e1cfd79541f5fc66c20adb0671 Mon Sep 17 00:00:00 2001 From: Cyril Bur Date: Wed, 1 Apr 2015 14:05:30 +0800 Subject: powerpc/powernv: Add interfaces for flash device access This change adds the OPAL interface definitions to allow Linux to read, write and erase from system flash devices. We register platform devices for the flash devices exported by firmware. We clash with the existing opal_flash_init function, which is really for the FSP flash update functionality, so we rename that initcall to opal_flash_update_init(). A future change will add an mtd driver that uses this interface. Changes from Joel Stanley and Jeremy Kerr. Signed-off-by: Cyril Bur Signed-off-by: Jeremy Kerr Signed-off-by: Joel Stanley Acked-by: Stewart Smith Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/opal-api.h | 5 ++++- arch/powerpc/include/asm/opal.h | 9 ++++++++- arch/powerpc/platforms/powernv/opal-flash.c | 2 +- arch/powerpc/platforms/powernv/opal-wrappers.S | 3 +++ arch/powerpc/platforms/powernv/opal.c | 16 +++++++++++++++- 5 files changed, 31 insertions(+), 4 deletions(-) (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h index e8a6baf55e82..0321a909e663 100644 --- a/arch/powerpc/include/asm/opal-api.h +++ b/arch/powerpc/include/asm/opal-api.h @@ -150,7 +150,10 @@ #define OPAL_IPMI_SEND 107 #define OPAL_IPMI_RECV 108 #define OPAL_I2C_REQUEST 109 -#define OPAL_LAST 109 +#define OPAL_FLASH_READ 110 +#define OPAL_FLASH_WRITE 111 +#define OPAL_FLASH_ERASE 112 +#define OPAL_LAST 112 /* Device tree flags */ diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index fde90bacc65e..042af1abfc4d 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h @@ -194,6 +194,13 @@ int64_t opal_ipmi_recv(uint64_t interface, struct opal_ipmi_msg *msg, int64_t opal_i2c_request(uint64_t async_token, uint32_t bus_id, struct opal_i2c_request *oreq); +int64_t opal_flash_read(uint64_t id, uint64_t offset, uint64_t buf, + uint64_t size, uint64_t token); +int64_t opal_flash_write(uint64_t id, uint64_t offset, uint64_t buf, + uint64_t size, uint64_t token); +int64_t opal_flash_erase(uint64_t id, uint64_t offset, uint64_t size, + uint64_t token); + /* Internal functions */ extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data); @@ -226,7 +233,7 @@ extern int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data); struct rtc_time; extern unsigned long opal_get_boot_time(void); extern void opal_nvram_init(void); -extern void opal_flash_init(void); +extern void opal_flash_update_init(void); extern void opal_flash_term_callback(void); extern int opal_elog_init(void); extern void opal_platform_dump_init(void); diff --git a/arch/powerpc/platforms/powernv/opal-flash.c b/arch/powerpc/platforms/powernv/opal-flash.c index 0ff07ff891f0..4ec6219287fc 100644 --- a/arch/powerpc/platforms/powernv/opal-flash.c +++ b/arch/powerpc/platforms/powernv/opal-flash.c @@ -546,7 +546,7 @@ static struct attribute_group image_op_attr_group = { .attrs = image_op_attrs, }; -void __init opal_flash_init(void) +void __init opal_flash_update_init(void) { int ret; diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S index b23fe7c4bf12..4e740375772c 100644 --- a/arch/powerpc/platforms/powernv/opal-wrappers.S +++ b/arch/powerpc/platforms/powernv/opal-wrappers.S @@ -292,3 +292,6 @@ OPAL_CALL(opal_tpo_read, OPAL_READ_TPO); OPAL_CALL(opal_ipmi_send, OPAL_IPMI_SEND); OPAL_CALL(opal_ipmi_recv, OPAL_IPMI_RECV); OPAL_CALL(opal_i2c_request, OPAL_I2C_REQUEST); +OPAL_CALL(opal_flash_read, OPAL_FLASH_READ); +OPAL_CALL(opal_flash_write, OPAL_FLASH_WRITE); +OPAL_CALL(opal_flash_erase, OPAL_FLASH_ERASE); diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index 3fb981c0ca80..2241565b0739 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c @@ -693,6 +693,15 @@ static void __init opal_dump_region_init(void) "rc = %d\n", rc); } +static void opal_flash_init(struct device_node *opal_node) +{ + struct device_node *np; + + for_each_child_of_node(opal_node, np) + if (of_device_is_compatible(np, "ibm,opal-flash")) + of_platform_device_create(np, NULL, NULL); +} + static void opal_ipmi_init(struct device_node *opal_node) { struct device_node *np; @@ -817,7 +826,7 @@ static int __init opal_init(void) /* Setup error log interface */ rc = opal_elog_init(); /* Setup code update interface */ - opal_flash_init(); + opal_flash_update_init(); /* Setup platform dump extract interface */ opal_platform_dump_init(); /* Setup system parameters interface */ @@ -829,6 +838,8 @@ static int __init opal_init(void) /* Initialize OPAL IPMI backend */ opal_ipmi_init(opal_node); + opal_flash_init(opal_node); + return 0; } machine_subsys_initcall(powernv, opal_init); @@ -867,6 +878,9 @@ void opal_shutdown(void) EXPORT_SYMBOL_GPL(opal_invalid_call); EXPORT_SYMBOL_GPL(opal_ipmi_send); EXPORT_SYMBOL_GPL(opal_ipmi_recv); +EXPORT_SYMBOL_GPL(opal_flash_read); +EXPORT_SYMBOL_GPL(opal_flash_write); +EXPORT_SYMBOL_GPL(opal_flash_erase); /* Convert a region of vmalloc memory to an opal sg list */ struct opal_sg_list *opal_vmalloc_to_sg_list(void *vmalloc_addr, -- cgit v1.2.3 From c54b2bf1b5e99760d53ea0376e96a046f93df6ae Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Thu, 9 Apr 2015 12:52:56 +1000 Subject: powerpc: Add ppc64 hard lockup detector support The hard lockup detector uses a PMU event as a periodic NMI to detect if we are stuck (where stuck means no timer interrupts have occurred). Ben's rework of the ppc64 soft disable code has made ppc64 PMU exceptions a partial NMI. They can get disabled if an external interrupt comes in, but otherwise PMU interrupts will fire in interrupt disabled regions. We disable the hard lockup detector by default for a few reasons: - It breaks userspace event based branches on POWER8. - It is likely to produce false positives on KVM guests. - Since PMCs can only count to 2^31, counting cycles means we might take multiple PMU exceptions per second per hardware thread even if our hard lockup timeout is 10 seconds. It can be enabled via a boot option, or via procfs. Signed-off-by: Anton Blanchard Signed-off-by: Michael Ellerman --- arch/powerpc/Kconfig | 1 + arch/powerpc/include/asm/nmi.h | 4 ++++ arch/powerpc/kernel/setup_64.c | 20 ++++++++++++++++++++ 3 files changed, 25 insertions(+) create mode 100644 arch/powerpc/include/asm/nmi.h (limited to 'arch/powerpc/include/asm') diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index c102668b4225..716c9e6a3160 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -152,6 +152,7 @@ config PPC select DCACHE_WORD_ACCESS if PPC64 && CPU_LITTLE_ENDIAN select NO_BOOTMEM select HAVE_GENERIC_RCU_GUP + select HAVE_PERF_EVENTS_NMI if PPC64 config GENERIC_CSUM def_bool CPU_LITTLE_ENDIAN diff --git a/arch/powerpc/include/asm/nmi.h b/arch/powerpc/include/asm/nmi.h new file mode 100644 index 000000000000..ff1ccb375e60 --- /dev/null +++ b/arch/powerpc/include/asm/nmi.h @@ -0,0 +1,4 @@ +#ifndef _ASM_NMI_H +#define _ASM_NMI_H + +#endif /* _ASM_NMI_H */ diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 49f553bbb360..7551e5692597 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -779,3 +780,22 @@ unsigned long memory_block_size_bytes(void) struct ppc_pci_io ppc_pci_io; EXPORT_SYMBOL(ppc_pci_io); #endif + +#ifdef CONFIG_HARDLOCKUP_DETECTOR +u64 hw_nmi_get_sample_period(int watchdog_thresh) +{ + return ppc_proc_freq * watchdog_thresh; +} + +/* + * The hardlockup detector breaks PMU event based branches and is likely + * to get false positives in KVM guests, so disable it by default. + */ +static int __init disable_hardlockup_detector(void) +{ + watchdog_enable_hardlockup_detector(false); + + return 0; +} +early_initcall(disable_hardlockup_detector); +#endif -- cgit v1.2.3