* [PATCH 11/21] powerpc/powernv: Basic support for OPAL
From: Benjamin Herrenschmidt @ 2011-09-10 14:19 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1315664408-16797-1-git-send-email-benh@kernel.crashing.org>
Add definition of OPAL interfaces along with the wrappers to call
into OPAL runtime and the early device-tree parsing hook to locate
the OPAL runtime firmware.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/include/asm/firmware.h | 10 +
arch/powerpc/include/asm/opal.h | 382 +++++++++++++++++++++++-
arch/powerpc/kernel/prom.c | 7 +
arch/powerpc/platforms/powernv/Kconfig | 8 +-
arch/powerpc/platforms/powernv/Makefile | 2 +-
arch/powerpc/platforms/powernv/opal-wrappers.S | 101 +++++++
arch/powerpc/platforms/powernv/opal.c | 154 ++++++++++
arch/powerpc/platforms/powernv/setup.c | 6 +
arch/powerpc/platforms/powernv/smp.c | 25 ++-
9 files changed, 690 insertions(+), 5 deletions(-)
create mode 100644 arch/powerpc/platforms/powernv/opal-wrappers.S
create mode 100644 arch/powerpc/platforms/powernv/opal.c
diff --git a/arch/powerpc/include/asm/firmware.h b/arch/powerpc/include/asm/firmware.h
index 3a6c586..14db29b 100644
--- a/arch/powerpc/include/asm/firmware.h
+++ b/arch/powerpc/include/asm/firmware.h
@@ -48,6 +48,8 @@
#define FW_FEATURE_CMO ASM_CONST(0x0000000002000000)
#define FW_FEATURE_VPHN ASM_CONST(0x0000000004000000)
#define FW_FEATURE_XCMO ASM_CONST(0x0000000008000000)
+#define FW_FEATURE_OPAL ASM_CONST(0x0000000010000000)
+#define FW_FEATURE_OPALv2 ASM_CONST(0x0000000020000000)
#ifndef __ASSEMBLY__
@@ -65,6 +67,8 @@ enum {
FW_FEATURE_PSERIES_ALWAYS = 0,
FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
+ FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL | FW_FEATURE_OPALv2,
+ 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,
@@ -78,6 +82,9 @@ enum {
#ifdef CONFIG_PPC_ISERIES
FW_FEATURE_ISERIES_POSSIBLE |
#endif
+#ifdef CONFIG_PPC_POWERNV
+ FW_FEATURE_POWERNV_POSSIBLE |
+#endif
#ifdef CONFIG_PPC_PS3
FW_FEATURE_PS3_POSSIBLE |
#endif
@@ -95,6 +102,9 @@ enum {
#ifdef CONFIG_PPC_ISERIES
FW_FEATURE_ISERIES_ALWAYS &
#endif
+#ifdef CONFIG_PPC_POWERNV
+ FW_FEATURE_POWERNV_ALWAYS &
+#endif
#ifdef CONFIG_PPC_PS3
FW_FEATURE_PS3_ALWAYS &
#endif
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index ecdb283..53cda41 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -37,14 +37,394 @@ extern long opal_query_takeover(u64 *hal_size, u64 *hal_align);
extern long opal_do_takeover(struct opal_takeover_args *args);
+struct rtas_args;
extern int opal_enter_rtas(struct rtas_args *args,
unsigned long data,
unsigned long 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
+
+/* API Tokens (in r0) */
+#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
+
+#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
+};
+enum OpalPciStatusToken {
+ OPAL_EEH_PHB_NO_ERROR = 0,
+ OPAL_EEH_PHB_FATAL = 1,
+ OPAL_EEH_PHB_RECOVERABLE = 2,
+ OPAL_EEH_PHB_BUS_ERROR = 3,
+ OPAL_EEH_PCI_NO_DEVSEL = 4,
+ OPAL_EEH_PCI_TA = 5,
+ OPAL_EEH_PCIEX_UR = 6,
+ OPAL_EEH_PCIEX_CA = 7,
+ OPAL_EEH_PCI_MMIO_ERROR = 8,
+ OPAL_EEH_PCI_DMA_ERROR = 9
+};
+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
+};
+
+/* Machine check related definitions */
+enum OpalMCE_Version {
+ OpalMCE_V1 = 1,
+};
+
+enum OpalMCE_Severity {
+ OpalMCE_SEV_NO_ERROR = 0,
+ OpalMCE_SEV_WARNING = 1,
+ OpalMCE_SEV_ERROR_SYNC = 2,
+ OpalMCE_SEV_FATAL = 3,
+};
+
+enum OpalMCE_Disposition {
+ OpalMCE_DISPOSITION_RECOVERED = 0,
+ OpalMCE_DISPOSITION_NOT_RECOVERED = 1,
+};
+
+enum OpalMCE_Initiator {
+ OpalMCE_INITIATOR_UNKNOWN = 0,
+ OpalMCE_INITIATOR_CPU = 1,
+};
+
+enum OpalMCE_ErrorType {
+ OpalMCE_ERROR_TYPE_UNKNOWN = 0,
+ OpalMCE_ERROR_TYPE_UE = 1,
+ OpalMCE_ERROR_TYPE_SLB = 2,
+ OpalMCE_ERROR_TYPE_ERAT = 3,
+ OpalMCE_ERROR_TYPE_TLB = 4,
+};
+
+enum OpalMCE_UeErrorType {
+ OpalMCE_UE_ERROR_INDETERMINATE = 0,
+ OpalMCE_UE_ERROR_IFETCH = 1,
+ OpalMCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH = 2,
+ OpalMCE_UE_ERROR_LOAD_STORE = 3,
+ OpalMCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE = 4,
+};
+
+enum OpalMCE_SlbErrorType {
+ OpalMCE_SLB_ERROR_INDETERMINATE = 0,
+ OpalMCE_SLB_ERROR_PARITY = 1,
+ OpalMCE_SLB_ERROR_MULTIHIT = 2,
+};
+
+enum OpalMCE_EratErrorType {
+ OpalMCE_ERAT_ERROR_INDETERMINATE = 0,
+ OpalMCE_ERAT_ERROR_PARITY = 1,
+ OpalMCE_ERAT_ERROR_MULTIHIT = 2,
+};
+
+enum OpalMCE_TlbErrorType {
+ OpalMCE_TLB_ERROR_INDETERMINATE = 0,
+ OpalMCE_TLB_ERROR_PARITY = 1,
+ OpalMCE_TLB_ERROR_MULTIHIT = 2,
+};
+
+enum OpalThreadStatus {
+ OPAL_THREAD_INACTIVE = 0x0,
+ OPAL_THREAD_STARTED = 0x1
+};
+
+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 OpalPciResetAndReinitScope {
+ OPAL_PHB_COMPLETE = 1, OPAL_PCI_LINK = 2, OPAL_PHB_ERROR = 3,
+ OPAL_PCI_HOT_RESET = 4, OPAL_PCI_FUNDAMENTAL_RESET = 5,
+ OPAL_PCI_IODA_RESET = 6,
+};
+
+enum OpalPciResetState { OPAL_DEASSERT_RESET = 0, OPAL_ASSERT_RESET = 1 };
+
+struct opal_machine_check_event {
+ enum OpalMCE_Version version:8; /* 0x00 */
+ uint8_t in_use; /* 0x01 */
+ enum OpalMCE_Severity severity:8; /* 0x02 */
+ enum OpalMCE_Initiator initiator:8; /* 0x03 */
+ enum OpalMCE_ErrorType error_type:8; /* 0x04 */
+ enum OpalMCE_Disposition disposition:8; /* 0x05 */
+ uint8_t reserved_1[2]; /* 0x06 */
+ uint64_t gpr3; /* 0x08 */
+ uint64_t srr0; /* 0x10 */
+ uint64_t srr1; /* 0x18 */
+ union { /* 0x20 */
+ struct {
+ enum OpalMCE_UeErrorType ue_error_type:8;
+ uint8_t effective_address_provided;
+ uint8_t physical_address_provided;
+ uint8_t reserved_1[5];
+ uint64_t effective_address;
+ uint64_t physical_address;
+ uint8_t reserved_2[8];
+ } ue_error;
+
+ struct {
+ enum OpalMCE_SlbErrorType slb_error_type:8;
+ uint8_t effective_address_provided;
+ uint8_t reserved_1[6];
+ uint64_t effective_address;
+ uint8_t reserved_2[16];
+ } slb_error;
+
+ struct {
+ enum OpalMCE_EratErrorType erat_error_type:8;
+ uint8_t effective_address_provided;
+ uint8_t reserved_1[6];
+ uint64_t effective_address;
+ uint8_t reserved_2[16];
+ } erat_error;
+
+ struct {
+ enum OpalMCE_TlbErrorType tlb_error_type:8;
+ uint8_t effective_address_provided;
+ uint8_t reserved_1[6];
+ uint64_t effective_address;
+ uint8_t reserved_2[16];
+ } tlb_error;
+ } u;
+};
+
+typedef struct oppanel_line {
+ /* XXX */
+} oppanel_line_t;
+
+/* API functions */
+int64_t opal_console_write(int64_t term_number, int64_t *length,
+ const uint8_t *buffer);
+int64_t opal_console_read(int64_t term_number, int64_t *length,
+ uint8_t *buffer);
+int64_t opal_console_write_buffer_space(int64_t term_number,
+ int64_t *length);
+int64_t opal_rtc_read(uint32_t *year_month_day,
+ uint64_t *hour_minute_second_millisecond);
+int64_t opal_rtc_write(uint32_t year_month_day,
+ uint64_t hour_minute_second_millisecond);
+int64_t opal_cec_power_down(uint64_t request);
+int64_t opal_cec_reboot(void);
+int64_t opal_read_nvram(uint64_t buffer, uint64_t size, uint64_t offset);
+int64_t opal_write_nvram(uint64_t buffer, uint64_t size, uint64_t offset);
+int64_t opal_handle_interrupt(uint64_t isn, uint64_t *outstanding_event_mask);
+int64_t opal_poll_events(uint64_t *outstanding_event_mask);
+int64_t opal_pci_set_hub_tce_memory(uint64_t hub_id, uint64_t tce_mem_addr,
+ uint64_t tce_mem_size);
+int64_t opal_pci_set_phb_tce_memory(uint64_t phb_id, uint64_t tce_mem_addr,
+ uint64_t tce_mem_size);
+int64_t opal_pci_config_read_byte(uint64_t phb_id, uint64_t bus_dev_func,
+ uint64_t offset, uint8_t *data);
+int64_t opal_pci_config_read_half_word(uint64_t phb_id, uint64_t bus_dev_func,
+ uint64_t offset, uint16_t *data);
+int64_t opal_pci_config_read_word(uint64_t phb_id, uint64_t bus_dev_func,
+ uint64_t offset, uint32_t *data);
+int64_t opal_pci_config_write_byte(uint64_t phb_id, uint64_t bus_dev_func,
+ uint64_t offset, uint8_t data);
+int64_t opal_pci_config_write_half_word(uint64_t phb_id, uint64_t bus_dev_func,
+ uint64_t offset, uint16_t data);
+int64_t opal_pci_config_write_word(uint64_t phb_id, uint64_t bus_dev_func,
+ uint64_t offset, uint32_t data);
+int64_t opal_set_xive(uint32_t isn, uint16_t server, uint8_t priority);
+int64_t opal_get_xive(uint32_t isn, uint16_t *server, uint8_t *priority);
+int64_t opal_register_exception_handler(uint64_t opal_exception,
+ uint64_t handler_address,
+ uint64_t glue_cache_line);
+int64_t opal_pci_eeh_freeze_status(uint64_t phb_id, uint64_t pe_number,
+ uint8_t *freeze_state,
+ uint16_t *pci_error_type,
+ uint64_t *phb_status);
+int64_t opal_pci_eeh_freeze_clear(uint64_t phb_id, uint64_t pe_number,
+ uint64_t eeh_action_token);
+int64_t opal_pci_shpc(uint64_t phb_id, uint64_t shpc_action, uint8_t *state);
+
+
+
+int64_t opal_pci_phb_mmio_enable(uint64_t phb_id, uint16_t window_type,
+ uint16_t window_num, uint16_t enable);
+int64_t opal_pci_set_phb_mem_window(uint64_t phb_id, uint16_t window_type,
+ uint16_t window_num,
+ uint64_t starting_real_address,
+ uint64_t starting_pci_address,
+ uint16_t segment_size);
+int64_t opal_pci_map_pe_mmio_window(uint64_t phb_id, uint16_t pe_number,
+ uint16_t window_type, uint16_t window_num,
+ uint16_t segment_num);
+int64_t opal_pci_set_phb_table_memory(uint64_t phb_id, uint64_t rtt_addr,
+ uint64_t ivt_addr, uint64_t ivt_len,
+ uint64_t reject_array_addr,
+ uint64_t peltv_addr);
+int64_t opal_pci_set_pe(uint64_t phb_id, uint64_t pe_number, uint64_t bus_dev_func,
+ uint8_t bus_compare, uint8_t dev_compare, uint8_t func_compare,
+ uint8_t pe_action);
+int64_t opal_pci_set_peltv(uint64_t phb_id, uint32_t parent_pe, uint32_t child_pe,
+ uint8_t state);
+int64_t opal_pci_set_mve(uint64_t phb_id, uint32_t mve_number, uint32_t pe_number);
+int64_t opal_pci_set_mve_enable(uint64_t phb_id, uint32_t mve_number,
+ uint32_t state);
+int64_t opal_pci_get_xive_reissue(uint64_t phb_id, uint32_t xive_number,
+ uint8_t *p_bit, uint8_t *q_bit);
+int64_t opal_pci_set_xive_reissue(uint64_t phb_id, uint32_t xive_number,
+ uint8_t p_bit, uint8_t q_bit);
+int64_t opal_pci_set_xive_pe(uint64_t phb_id, uint32_t pe_number,
+ uint32_t xive_num);
+int64_t opal_get_xive_source(uint64_t phb_id, uint32_t xive_num,
+ int32_t *interrupt_source_number);
+int64_t opal_get_msi_32(uint64_t phb_id, uint32_t mve_number, uint32_t xive_num,
+ uint8_t msi_range, uint32_t *msi_address,
+ uint32_t *message_data);
+int64_t opal_get_msi_64(uint64_t phb_id, uint32_t mve_number,
+ uint32_t xive_num, uint8_t msi_range,
+ uint64_t *msi_address, uint32_t *message_data);
+int64_t opal_start_cpu(uint64_t thread_number, uint64_t start_address);
+int64_t opal_query_cpu_status(uint64_t thread_number, uint8_t *thread_status);
+int64_t opal_write_oppanel(oppanel_line_t *lines, uint64_t num_lines);
+int64_t opal_pci_map_pe_dma_window(uint64_t phb_id, uint16_t pe_number, uint16_t window_id,
+ uint16_t tce_levels, uint64_t tce_table_addr,
+ uint64_t tce_table_size, uint64_t tce_page_size);
+int64_t opal_pci_map_pe_dma_window_real(uint64_t phb_id, uint16_t pe_number,
+ uint16_t dma_window_number, uint64_t pci_start_addr,
+ uint64_t pci_mem_size);
+int64_t opal_pci_reset(uint64_t phb_id, uint8_t reset_scope, uint8_t assert_state);
+
+/* Internal functions */
+extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data);
+
+extern int opal_get_chars(uint32_t vtermno, char *buf, int count);
+extern int opal_put_chars(uint32_t vtermno, const char *buf, int total_len);
+
+extern void hvc_opal_init_early(void);
+
+/* Internal functions */
+extern int early_init_dt_scan_opal(unsigned long node, const char *uname,
+ int depth, void *data);
+
+#endif /* __ASSEMBLY__ */
#endif /* __OPAL_H */
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 7b90c56..831a201 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -54,6 +54,8 @@
#include <asm/pci-bridge.h>
#include <asm/phyp_dump.h>
#include <asm/kexec.h>
+#include <asm/opal.h>
+
#include <mm/mmu_decl.h>
#ifdef DEBUG
@@ -707,6 +709,11 @@ void __init early_init_devtree(void *params)
of_scan_flat_dt(early_init_dt_scan_rtas, NULL);
#endif
+#ifdef CONFIG_PPC_POWERNV
+ /* Some machines might need OPAL info for debugging, grab it now. */
+ of_scan_flat_dt(early_init_dt_scan_opal, NULL);
+#endif
+
#ifdef CONFIG_PHYP_DUMP
/* scan tree to see if dump occurred during last boot */
of_scan_flat_dt(early_init_dt_scan_phyp_dump, NULL);
diff --git a/arch/powerpc/platforms/powernv/Kconfig b/arch/powerpc/platforms/powernv/Kconfig
index 5cd04f5..268cadb 100644
--- a/arch/powerpc/platforms/powernv/Kconfig
+++ b/arch/powerpc/platforms/powernv/Kconfig
@@ -1,12 +1,16 @@
config PPC_POWERNV
depends on PPC64 && PPC_BOOK3S
bool "IBM PowerNV (Non-Virtualized) platform support"
- select PPC_RTAS
select PPC_NATIVE
select PPC_XICS
select PPC_ICP_NATIVE
- select PPC_ICS_RTAS
select PPC_P7_NAP
select PPC_PCI_CHOICE if EMBEDDED
default y
+config PPC_POWERNV_RTAS
+ depends on PPC_POWERNV
+ bool "Support for RTAS based PowerNV platforms such as BML"
+ default y
+ select PPC_ICS_RTAS
+ select PPC_RTAS
diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile
index 4971330..8f69c0d 100644
--- a/arch/powerpc/platforms/powernv/Makefile
+++ b/arch/powerpc/platforms/powernv/Makefile
@@ -1,2 +1,2 @@
-obj-y += setup.o opal-takeover.o
+obj-y += setup.o opal-takeover.o opal-wrappers.o opal.o
obj-$(CONFIG_SMP) += smp.o
diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S
new file mode 100644
index 0000000..4a3f46d
--- /dev/null
+++ b/arch/powerpc/platforms/powernv/opal-wrappers.S
@@ -0,0 +1,101 @@
+/*
+ * PowerNV OPAL API wrappers
+ *
+ * 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.
+ */
+
+#include <asm/ppc_asm.h>
+#include <asm/hvcall.h>
+#include <asm/asm-offsets.h>
+#include <asm/opal.h>
+
+/* TODO:
+ *
+ * - Trace irqs in/off (needs saving/restoring all args, argh...)
+ * - Get r11 feed up by Dave so I can have better register usage
+ */
+#define OPAL_CALL(name, token) \
+ _GLOBAL(name); \
+ mflr r0; \
+ mfcr r12; \
+ std r0,16(r1); \
+ std r12,8(r1); \
+ std r1,PACAR1(r13); \
+ li r0,0; \
+ mfmsr r12; \
+ ori r0,r0,MSR_EE; \
+ std r12,PACASAVEDMSR(r13); \
+ andc r12,r12,r0; \
+ mtmsrd r12,1; \
+ LOAD_REG_ADDR(r0,.opal_return); \
+ mtlr r0; \
+ li r0,MSR_DR|MSR_IR; \
+ andc r12,r12,r0; \
+ li r0,token; \
+ mtspr SPRN_HSRR1,r12; \
+ LOAD_REG_ADDR(r11,opal); \
+ ld r12,8(r11); \
+ ld r2,0(r11); \
+ mtspr SPRN_HSRR0,r12; \
+ hrfid
+
+_STATIC(opal_return)
+ ld r2,PACATOC(r13);
+ ld r4,8(r1);
+ ld r5,16(r1);
+ ld r6,PACASAVEDMSR(r13);
+ mtspr SPRN_SRR0,r5;
+ mtspr SPRN_SRR1,r6;
+ mtcr r4;
+ rfid
+
+OPAL_CALL(opal_console_write, OPAL_CONSOLE_WRITE);
+OPAL_CALL(opal_console_read, OPAL_CONSOLE_READ);
+OPAL_CALL(opal_console_write_buffer_space, OPAL_CONSOLE_WRITE_BUFFER_SPACE);
+OPAL_CALL(opal_rtc_read, OPAL_RTC_READ);
+OPAL_CALL(opal_rtc_write, OPAL_RTC_WRITE);
+OPAL_CALL(opal_cec_power_down, OPAL_CEC_POWER_DOWN);
+OPAL_CALL(opal_cec_reboot, OPAL_CEC_REBOOT);
+OPAL_CALL(opal_read_nvram, OPAL_READ_NVRAM);
+OPAL_CALL(opal_write_nvram, OPAL_WRITE_NVRAM);
+OPAL_CALL(opal_handle_interrupt, OPAL_HANDLE_INTERRUPT);
+OPAL_CALL(opal_poll_events, OPAL_POLL_EVENTS);
+OPAL_CALL(opal_pci_set_hub_tce_memory, OPAL_PCI_SET_HUB_TCE_MEMORY);
+OPAL_CALL(opal_pci_set_phb_tce_memory, OPAL_PCI_SET_PHB_TCE_MEMORY);
+OPAL_CALL(opal_pci_config_read_byte, OPAL_PCI_CONFIG_READ_BYTE);
+OPAL_CALL(opal_pci_config_read_half_word, OPAL_PCI_CONFIG_READ_HALF_WORD);
+OPAL_CALL(opal_pci_config_read_word, OPAL_PCI_CONFIG_READ_WORD);
+OPAL_CALL(opal_pci_config_write_byte, OPAL_PCI_CONFIG_WRITE_BYTE);
+OPAL_CALL(opal_pci_config_write_half_word, OPAL_PCI_CONFIG_WRITE_HALF_WORD);
+OPAL_CALL(opal_pci_config_write_word, OPAL_PCI_CONFIG_WRITE_WORD);
+OPAL_CALL(opal_set_xive, OPAL_SET_XIVE);
+OPAL_CALL(opal_get_xive, OPAL_GET_XIVE);
+OPAL_CALL(opal_register_exception_handler, OPAL_REGISTER_OPAL_EXCEPTION_HANDLER);
+OPAL_CALL(opal_pci_eeh_freeze_status, OPAL_PCI_EEH_FREEZE_STATUS);
+OPAL_CALL(opal_pci_eeh_freeze_clear, OPAL_PCI_EEH_FREEZE_CLEAR);
+OPAL_CALL(opal_pci_shpc, OPAL_PCI_SHPC);
+OPAL_CALL(opal_pci_phb_mmio_enable, OPAL_PCI_PHB_MMIO_ENABLE);
+OPAL_CALL(opal_pci_set_phb_mem_window, OPAL_PCI_SET_PHB_MEM_WINDOW);
+OPAL_CALL(opal_pci_map_pe_mmio_window, OPAL_PCI_MAP_PE_MMIO_WINDOW);
+OPAL_CALL(opal_pci_set_phb_table_memory, OPAL_PCI_SET_PHB_TABLE_MEMORY);
+OPAL_CALL(opal_pci_set_pe, OPAL_PCI_SET_PE);
+OPAL_CALL(opal_pci_set_peltv, OPAL_PCI_SET_PELTV);
+OPAL_CALL(opal_pci_set_mve, OPAL_PCI_SET_MVE);
+OPAL_CALL(opal_pci_set_mve_enable, OPAL_PCI_SET_MVE_ENABLE);
+OPAL_CALL(opal_pci_get_xive_reissue, OPAL_PCI_GET_XIVE_REISSUE);
+OPAL_CALL(opal_pci_set_xive_reissue, OPAL_PCI_SET_XIVE_REISSUE);
+OPAL_CALL(opal_pci_set_xive_pe, OPAL_PCI_SET_XIVE_PE);
+OPAL_CALL(opal_get_xive_source, OPAL_GET_XIVE_SOURCE);
+OPAL_CALL(opal_get_msi_32, OPAL_GET_MSI_32);
+OPAL_CALL(opal_get_msi_64, OPAL_GET_MSI_64);
+OPAL_CALL(opal_start_cpu, OPAL_START_CPU);
+OPAL_CALL(opal_query_cpu_status, OPAL_QUERY_CPU_STATUS);
+OPAL_CALL(opal_write_oppanel, OPAL_WRITE_OPPANEL);
+OPAL_CALL(opal_pci_map_pe_dma_window, OPAL_PCI_MAP_PE_DMA_WINDOW);
+OPAL_CALL(opal_pci_map_pe_dma_window_real, OPAL_PCI_MAP_PE_DMA_WINDOW_REAL);
+OPAL_CALL(opal_pci_reset, OPAL_PCI_RESET);
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
new file mode 100644
index 0000000..8d55107
--- /dev/null
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -0,0 +1,154 @@
+/*
+ * PowerNV OPAL high level interfaces
+ *
+ * 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.
+ */
+
+#undef DEBUG
+
+#include <linux/types.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <asm/opal.h>
+#include <asm/firmware.h>
+
+#include "powernv.h"
+
+struct opal {
+ u64 base;
+ u64 entry;
+} opal;
+
+static struct device_node *opal_node;
+static DEFINE_SPINLOCK(opal_write_lock);
+
+int __init early_init_dt_scan_opal(unsigned long node,
+ const char *uname, int depth, void *data)
+{
+ const void *basep, *entryp;
+ unsigned long basesz, entrysz;
+
+ if (depth != 1 || strcmp(uname, "ibm,opal") != 0)
+ return 0;
+
+ basep = of_get_flat_dt_prop(node, "opal-base-address", &basesz);
+ entryp = of_get_flat_dt_prop(node, "opal-entry-address", &entrysz);
+
+ if (!basep || !entryp)
+ return 1;
+
+ opal.base = of_read_number(basep, basesz/4);
+ opal.entry = of_read_number(entryp, entrysz/4);
+
+ pr_debug("OPAL Base = 0x%llx (basep=%p basesz=%ld)\n",
+ opal.base, basep, basesz);
+ pr_debug("OPAL Entry = 0x%llx (entryp=%p basesz=%ld)\n",
+ opal.entry, entryp, entrysz);
+
+ powerpc_firmware_features |= FW_FEATURE_OPAL;
+ if (of_flat_dt_is_compatible(node, "ibm,opal-v2")) {
+ powerpc_firmware_features |= FW_FEATURE_OPALv2;
+ printk("OPAL V2 detected !\n");
+ } else {
+ printk("OPAL V1 detected !\n");
+ }
+
+ return 1;
+}
+
+int opal_get_chars(uint32_t vtermno, char *buf, int count)
+{
+ s64 len, rc;
+ u64 evt;
+
+ if (!opal.entry)
+ return 0;
+ opal_poll_events(&evt);
+ if ((evt & OPAL_EVENT_CONSOLE_INPUT) == 0)
+ return 0;
+ len = count;
+ rc = opal_console_read(vtermno, &len, buf);
+ if (rc == OPAL_SUCCESS)
+ return len;
+ return 0;
+}
+
+int opal_put_chars(uint32_t vtermno, const char *data, int total_len)
+{
+ int written = 0;
+ s64 len, rc = OPAL_BUSY;
+ unsigned long flags;
+ u64 evt;
+
+ if (!opal.entry)
+ return 0;
+
+ /* We want put_chars to be atomic to avoid mangling of hvsi
+ * packets. To do that, we first test for room and return
+ * -EAGAIN if there isn't enough
+ */
+ spin_lock_irqsave(&opal_write_lock, flags);
+ rc = opal_console_write_buffer_space(vtermno, &len);
+ if (rc || len < total_len) {
+ spin_unlock_irqrestore(&opal_write_lock, flags);
+ /* Closed -> drop characters */
+ if (rc)
+ return total_len;
+ opal_poll_events(&evt);
+ return -EAGAIN;
+ }
+
+ /* We still try to handle partial completions, though they
+ * should no longer happen.
+ */
+ while(total_len > 0 && (rc == OPAL_BUSY ||
+ rc == OPAL_BUSY_EVENT || rc == OPAL_SUCCESS)) {
+ len = total_len;
+ rc = opal_console_write(vtermno, &len, data);
+ if (rc == OPAL_SUCCESS) {
+ total_len -= len;
+ data += len;
+ written += len;
+ }
+ /* This is a bit nasty but we need that for the console to
+ * flush when there aren't any interrupts. We will clean
+ * things a bit later to limit that to synchronous path
+ * such as the kernel console and xmon/udbg
+ */
+ do
+ opal_poll_events(&evt);
+ while(rc == OPAL_SUCCESS && (evt & OPAL_EVENT_CONSOLE_OUTPUT));
+ }
+ spin_unlock_irqrestore(&opal_write_lock, flags);
+ return written;
+}
+
+static int __init opal_init(void)
+{
+ struct device_node *np, *consoles;
+
+ opal_node = of_find_node_by_path("/ibm,opal");
+ if (!opal_node) {
+ pr_warn("opal: Node not found\n");
+ return -ENODEV;
+ }
+ if (firmware_has_feature(FW_FEATURE_OPALv2))
+ consoles = of_find_node_by_path("/ibm,opal/consoles");
+ else
+ consoles = of_node_get(opal_node);
+
+ /* Register serial ports */
+ for_each_child_of_node(consoles, np) {
+ if (strcmp(np->name, "serial"))
+ continue;
+ of_platform_device_create(np, NULL, NULL);
+ }
+ of_node_put(consoles);
+ return 0;
+}
+subsys_initcall(opal_init);
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
index 569f9cc..b6e5ff8 100644
--- a/arch/powerpc/platforms/powernv/setup.c
+++ b/arch/powerpc/platforms/powernv/setup.c
@@ -74,6 +74,12 @@ static void pnv_show_cpuinfo(struct seq_file *m)
if (root)
model = of_get_property(root, "model", NULL);
seq_printf(m, "machine\t\t: PowerNV %s\n", model);
+ if (firmware_has_feature(FW_FEATURE_OPALv2))
+ seq_printf(m, "firmware\t: OPAL v2\n");
+ else if (firmware_has_feature(FW_FEATURE_OPAL))
+ seq_printf(m, "firmware\t: OPAL v1\n");
+ else
+ seq_printf(m, "firmware\t: BML\n");
of_node_put(root);
}
diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c
index 4f4ec37..e877366 100644
--- a/arch/powerpc/platforms/powernv/smp.c
+++ b/arch/powerpc/platforms/powernv/smp.c
@@ -30,6 +30,7 @@
#include <asm/vdso_datapage.h>
#include <asm/cputhreads.h>
#include <asm/xics.h>
+#include <asm/opal.h>
#include "powernv.h"
@@ -62,6 +63,28 @@ static int pnv_smp_cpu_bootable(unsigned int nr)
return 1;
}
+int __devinit pnv_smp_kick_cpu(int nr)
+{
+ unsigned int pcpu = get_hard_smp_processor_id(nr);
+ unsigned long start_here = __pa(*((unsigned long *)
+ generic_secondary_smp_init));
+ long rc;
+
+ BUG_ON(nr < 0 || nr >= NR_CPUS);
+
+ /* On OPAL v2 the CPU are still spinning inside OPAL itself,
+ * get them back now
+ */
+ if (firmware_has_feature(FW_FEATURE_OPALv2)) {
+ pr_devel("OPAL: Starting CPU %d (HW 0x%x)...\n", nr, pcpu);
+ rc = opal_start_cpu(pcpu, start_here);
+ if (rc != OPAL_SUCCESS)
+ pr_warn("OPAL Error %ld starting CPU %d\n",
+ rc, nr);
+ }
+ return smp_generic_kick_cpu(nr);
+}
+
#ifdef CONFIG_HOTPLUG_CPU
static int pnv_smp_cpu_disable(void)
@@ -127,7 +150,7 @@ static struct smp_ops_t pnv_smp_ops = {
.message_pass = smp_muxed_ipi_message_pass,
.cause_ipi = NULL, /* Filled at runtime by xics_smp_probe() */
.probe = xics_smp_probe,
- .kick_cpu = smp_generic_kick_cpu,
+ .kick_cpu = pnv_smp_kick_cpu,
.setup_cpu = pnv_smp_setup_cpu,
.cpu_bootable = pnv_smp_cpu_bootable,
#ifdef CONFIG_HOTPLUG_CPU
--
1.7.4.1
^ permalink raw reply related
* [PATCH 10/21] powerpc/powernv: Get kernel command line accross OPAL takeover
From: Benjamin Herrenschmidt @ 2011-09-10 14:19 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1315664408-16797-1-git-send-email-benh@kernel.crashing.org>
We stash it in boot_command_line which isn't in BSS and so won't
be overwritten. We then use that as a default cmd_line before
we walk the device-tree.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/kernel/prom.c | 7 +++++++
arch/powerpc/kernel/prom_init.c | 4 ++++
arch/powerpc/kernel/prom_init_check.sh | 3 ++-
3 files changed, 13 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 174e1e9..7b90c56 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -712,6 +712,13 @@ void __init early_init_devtree(void *params)
of_scan_flat_dt(early_init_dt_scan_phyp_dump, NULL);
#endif
+ /* Pre-initialize the cmd_line with the content of boot_commmand_line,
+ * which will be empty except when the content of the variable has
+ * been overriden by a bootloading mechanism. This happens typically
+ * with HAL takeover
+ */
+ strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
+
/* Retrieve various informations from the /chosen node of the
* device-tree, including the platform type, initrd location and
* size, TCE reserve, and more ...
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 9369287..e3f3904 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -1449,6 +1449,10 @@ static void prom_opal_takeover(void)
opal_addr = top_addr;
args->hal_addr = opal_addr;
+ /* Copy the command line to the kernel image */
+ strlcpy(RELOC(boot_command_line), RELOC(prom_cmd_line),
+ COMMAND_LINE_SIZE);
+
prom_debug(" k_image = 0x%lx\n", args->k_image);
prom_debug(" k_size = 0x%lx\n", args->k_size);
prom_debug(" k_entry = 0x%lx\n", args->k_entry);
diff --git a/arch/powerpc/kernel/prom_init_check.sh b/arch/powerpc/kernel/prom_init_check.sh
index 20af6aa..70f4286 100644
--- a/arch/powerpc/kernel/prom_init_check.sh
+++ b/arch/powerpc/kernel/prom_init_check.sh
@@ -21,7 +21,8 @@ _end enter_prom memcpy memset reloc_offset __secondary_hold
__secondary_hold_acknowledge __secondary_hold_spinloop __start
strcmp strcpy strlcpy strlen strncmp strstr logo_linux_clut224
reloc_got2 kernstart_addr memstart_addr linux_banner _stext
-opal_query_takeover opal_do_takeover opal_enter_rtas opal_secondary_entry"
+opal_query_takeover opal_do_takeover opal_enter_rtas opal_secondary_entry
+boot_command_line"
NM="$1"
OBJ="$2"
--
1.7.4.1
^ permalink raw reply related
* [PATCH 12/21] powerpc/powernv: Add support for instanciating OPAL v2 from Open Firmware
From: Benjamin Herrenschmidt @ 2011-09-10 14:19 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1315664408-16797-1-git-send-email-benh@kernel.crashing.org>
OPAL v2 is instantiated in a way similar to RTAS using Open Firmware
client interface calls, and the resulting address and entry point are
put in the device-tree
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/kernel/prom_init.c | 136 +++++++++++++++++++++++++++++++++------
1 files changed, 117 insertions(+), 19 deletions(-)
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index e3f3904..4ef74ea 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -140,7 +140,9 @@ struct mem_map_entry {
typedef u32 cell_t;
-extern void __start(unsigned long r3, unsigned long r4, unsigned long r5);
+extern void __start(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7, unsigned long r8,
+ unsigned long r9);
#ifdef CONFIG_PPC64
extern int enter_prom(struct prom_args *args, unsigned long entry);
@@ -1293,6 +1295,11 @@ static int __initdata prom_rtas_start_cpu;
static u64 __initdata prom_rtas_data;
static u64 __initdata prom_rtas_entry;
+#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
+static u64 __initdata prom_opal_base;
+static u64 __initdata prom_opal_entry;
+#endif
+
/* XXX Don't change this structure without updating opal-takeover.S */
static struct opal_secondary_data {
s64 ack; /* 0 */
@@ -1468,6 +1475,76 @@ static void prom_opal_takeover(void)
for (;;)
opal_do_takeover(args);
}
+
+/*
+ * Allocate room for and instantiate OPAL
+ */
+static void __init prom_instantiate_opal(void)
+{
+ phandle opal_node;
+ ihandle opal_inst;
+ u64 base, entry;
+ u64 size = 0, align = 0x10000;
+ u32 rets[2];
+
+ prom_debug("prom_instantiate_opal: start...\n");
+
+ opal_node = call_prom("finddevice", 1, 1, ADDR("/ibm,opal"));
+ prom_debug("opal_node: %x\n", opal_node);
+ if (!PHANDLE_VALID(opal_node))
+ return;
+
+ prom_getprop(opal_node, "opal-runtime-size", &size, sizeof(size));
+ if (size == 0)
+ return;
+ prom_getprop(opal_node, "opal-runtime-alignment", &align,
+ sizeof(align));
+
+ base = alloc_down(size, align, 0);
+ if (base == 0) {
+ prom_printf("OPAL allocation failed !\n");
+ return;
+ }
+
+ opal_inst = call_prom("open", 1, 1, ADDR("/ibm,opal"));
+ if (!IHANDLE_VALID(opal_inst)) {
+ prom_printf("opening opal package failed (%x)\n", opal_inst);
+ return;
+ }
+
+ prom_printf("instantiating opal at 0x%x...", base);
+
+ if (call_prom_ret("call-method", 4, 3, rets,
+ ADDR("load-opal-runtime"),
+ opal_inst,
+ base >> 32, base & 0xffffffff) != 0
+ || (rets[0] == 0 && rets[1] == 0)) {
+ prom_printf(" failed\n");
+ return;
+ }
+ entry = (((u64)rets[0]) << 32) | rets[1];
+
+ prom_printf(" done\n");
+
+ reserve_mem(base, size);
+
+ prom_debug("opal base = 0x%x\n", base);
+ prom_debug("opal align = 0x%x\n", align);
+ prom_debug("opal entry = 0x%x\n", entry);
+ prom_debug("opal size = 0x%x\n", (long)size);
+
+ prom_setprop(opal_node, "/ibm,opal", "opal-base-address",
+ &base, sizeof(base));
+ prom_setprop(opal_node, "/ibm,opal", "opal-entry-address",
+ &entry, sizeof(entry));
+
+#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
+ RELOC(prom_opal_base) = base;
+ RELOC(prom_opal_entry) = entry;
+#endif
+ prom_debug("prom_instantiate_opal: end...\n");
+}
+
#endif /* CONFIG_PPC_POWERNV */
/*
@@ -1863,7 +1940,7 @@ static int __init prom_find_machine_type(void)
int x;
#endif
- /* Look for a PowerMac */
+ /* Look for a PowerMac or a Cell */
len = prom_getprop(_prom->root, "compatible",
compat, sizeof(compat)-1);
if (len > 0) {
@@ -1889,7 +1966,11 @@ static int __init prom_find_machine_type(void)
}
}
#ifdef CONFIG_PPC64
- /* If not a mac, try to figure out if it's an IBM pSeries or any other
+ /* Try to detect OPAL */
+ if (PHANDLE_VALID(call_prom("finddevice", 1, 1, ADDR("/ibm,opal"))))
+ return PLATFORM_OPAL;
+
+ /* Try to figure out if it's an IBM pSeries or any other
* PAPR compliant platform. We assume it is if :
* - /device_type is "chrp" (please, do NOT use that for future
* non-IBM designs !
@@ -2116,7 +2197,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
unsigned long soff;
unsigned char *valp;
static char pname[MAX_PROPERTY_NAME];
- int l, room;
+ int l, room, has_phandle;
dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
@@ -2200,19 +2281,26 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
valp = make_room(mem_start, mem_end, l, 4);
call_prom("getprop", 4, 1, node, RELOC(pname), valp, l);
*mem_start = _ALIGN(*mem_start, 4);
+
+ if (!strcmp(RELOC(pname), RELOC("phandle")))
+ has_phandle = 1;
}
- /* Add a "linux,phandle" property. */
- soff = dt_find_string(RELOC("linux,phandle"));
- if (soff == 0)
- prom_printf("WARNING: Can't find string index for"
- " <linux-phandle> node %s\n", path);
- else {
- dt_push_token(OF_DT_PROP, mem_start, mem_end);
- dt_push_token(4, mem_start, mem_end);
- dt_push_token(soff, mem_start, mem_end);
- valp = make_room(mem_start, mem_end, 4, 4);
- *(u32 *)valp = node;
+ /* Add a "linux,phandle" property if no "phandle" property already
+ * existed (can happen with OPAL)
+ */
+ if (!has_phandle) {
+ soff = dt_find_string(RELOC("linux,phandle"));
+ if (soff == 0)
+ prom_printf("WARNING: Can't find string index for"
+ " <linux-phandle> node %s\n", path);
+ else {
+ dt_push_token(OF_DT_PROP, mem_start, mem_end);
+ dt_push_token(4, mem_start, mem_end);
+ dt_push_token(soff, mem_start, mem_end);
+ valp = make_room(mem_start, mem_end, 4, 4);
+ *(u32 *)valp = node;
+ }
}
/* do all our children */
@@ -2746,6 +2834,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
* between pSeries SMP and pSeries LPAR
*/
RELOC(of_platform) = prom_find_machine_type();
+ prom_printf("Detected machine type: %x\n", RELOC(of_platform));
#ifndef CONFIG_RELOCATABLE
/* Bail if this is a kdump kernel. */
@@ -2807,7 +2896,8 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
* On non-powermacs, try to instantiate RTAS. PowerMacs don't
* have a usable RTAS implementation.
*/
- if (RELOC(of_platform) != PLATFORM_POWERMAC)
+ if (RELOC(of_platform) != PLATFORM_POWERMAC &&
+ RELOC(of_platform) != PLATFORM_OPAL)
prom_instantiate_rtas();
#ifdef CONFIG_PPC_POWERNV
@@ -2818,7 +2908,8 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
prom_opal_hold_cpus();
prom_opal_takeover();
}
- }
+ } else if (RELOC(of_platform) == PLATFORM_OPAL)
+ prom_instantiate_opal();
#endif
/*
@@ -2826,7 +2917,8 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
*
* PowerMacs use a different mechanism to spin CPUs
*/
- if (RELOC(of_platform) != PLATFORM_POWERMAC)
+ if (RELOC(of_platform) != PLATFORM_POWERMAC &&
+ RELOC(of_platform) != PLATFORM_OPAL)
prom_hold_cpus();
/*
@@ -2894,7 +2986,13 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
reloc_got2(-offset);
#endif
- __start(hdr, kbase, 0);
+#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
+ /* OPAL early debug gets the OPAL base & entry in r8 and r9 */
+ __start(hdr, kbase, 0, 0, 0,
+ RELOC(prom_opal_base), RELOC(prom_opal_entry));
+#else
+ __start(hdr, kbase, 0, 0, 0, 0, 0);
+#endif
return 0;
}
--
1.7.4.1
^ permalink raw reply related
* [PATCH 09/21] powerpc/powernv: Add OPAL takeover from PowerVM
From: Benjamin Herrenschmidt @ 2011-09-10 14:19 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1315664408-16797-1-git-send-email-benh@kernel.crashing.org>
On machines supporting the OPAL firmware version 1, the system
is initially booted under pHyp. We then use a special hypercall
to verify if OPAL is available and if it is, we then trigger
a "takeover" which disables pHyp and loads the OPAL runtime
firmware, giving control to the kernel in hypervisor mode.
This patch add the necessary code to detect that the OPAL takeover
capability is present when running under PowerVM (aka pHyp) and
perform said takeover to get hypervisor control of the processor.
To perform the takeover, we must first use RTAS (within Open
Firmware runtime environment) to start all processors & threads,
in order to give control to OPAL on all of them. We then call
the takeover hypercall on everybody, OPAL will re-enter the kernel
main entry point passing it a flat device-tree.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/include/asm/opal.h | 50 +++++
arch/powerpc/kernel/head_64.S | 4 +
arch/powerpc/kernel/prom_init.c | 239 ++++++++++++++++++++++--
arch/powerpc/kernel/prom_init_check.sh | 3 +-
arch/powerpc/platforms/powernv/Makefile | 2 +-
arch/powerpc/platforms/powernv/opal-takeover.S | 140 ++++++++++++++
6 files changed, 419 insertions(+), 19 deletions(-)
create mode 100644 arch/powerpc/include/asm/opal.h
create mode 100644 arch/powerpc/platforms/powernv/opal-takeover.S
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
new file mode 100644
index 0000000..ecdb283
--- /dev/null
+++ b/arch/powerpc/include/asm/opal.h
@@ -0,0 +1,50 @@
+/*
+ * 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_H
+#define __OPAL_H
+
+/****** Takeover interface ********/
+
+/* PAPR H-Call used to querty the HAL existence and/or instanciate
+ * it from within pHyp (tech preview only).
+ *
+ * This is exclusively used in prom_init.c
+ */
+
+#ifndef __ASSEMBLY__
+
+struct opal_takeover_args {
+ u64 k_image; /* r4 */
+ u64 k_size; /* r5 */
+ u64 k_entry; /* r6 */
+ u64 k_entry2; /* r7 */
+ u64 hal_addr; /* r8 */
+ u64 rd_image; /* r9 */
+ u64 rd_size; /* r10 */
+ u64 rd_loc; /* r11 */
+};
+
+extern long opal_query_takeover(u64 *hal_size, u64 *hal_align);
+
+extern long opal_do_takeover(struct opal_takeover_args *args);
+
+extern int opal_enter_rtas(struct rtas_args *args,
+ unsigned long data,
+ unsigned long entry);
+
+
+#endif /* __ASSEMBLY__ */
+
+/****** OPAL APIs ******/
+
+
+#endif /* __OPAL_H */
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index e708abe..dea8191 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -51,6 +51,10 @@
* For pSeries or server processors:
* 1. The MMU is off & open firmware is running in real mode.
* 2. The kernel is entered at __start
+ * -or- For OPAL entry:
+ * 1. The MMU is off, processor in HV mode, primary CPU enters at 0
+ * with device-tree in gpr3
+ * 2. Secondary processors enter at 0x60 with PIR in gpr3
*
* For iSeries:
* 1. The MMU is on (as it always is for iSeries)
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index a909f4e..9369287 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -43,6 +43,7 @@
#include <asm/btext.h>
#include <asm/sections.h>
#include <asm/machdep.h>
+#include <asm/opal.h>
#include <linux/linux_logo.h>
@@ -185,6 +186,7 @@ static unsigned long __initdata prom_tce_alloc_end;
#define PLATFORM_LPAR 0x0001
#define PLATFORM_POWERMAC 0x0400
#define PLATFORM_GENERIC 0x0500
+#define PLATFORM_OPAL 0x0600
static int __initdata of_platform;
@@ -644,7 +646,7 @@ static void __init early_cmdline_parse(void)
}
}
-#ifdef CONFIG_PPC_PSERIES
+#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
/*
* There are two methods for telling firmware what our capabilities are.
* Newer machines have an "ibm,client-architecture-support" method on the
@@ -1274,6 +1276,195 @@ static void __init prom_init_mem(void)
prom_printf(" ram_top : %x\n", RELOC(ram_top));
}
+static void __init prom_close_stdin(void)
+{
+ struct prom_t *_prom = &RELOC(prom);
+ ihandle val;
+
+ if (prom_getprop(_prom->chosen, "stdin", &val, sizeof(val)) > 0)
+ call_prom("close", 1, 0, val);
+}
+
+#ifdef CONFIG_PPC_POWERNV
+
+static u64 __initdata prom_opal_size;
+static u64 __initdata prom_opal_align;
+static int __initdata prom_rtas_start_cpu;
+static u64 __initdata prom_rtas_data;
+static u64 __initdata prom_rtas_entry;
+
+/* XXX Don't change this structure without updating opal-takeover.S */
+static struct opal_secondary_data {
+ s64 ack; /* 0 */
+ u64 go; /* 8 */
+ struct opal_takeover_args args; /* 16 */
+} opal_secondary_data;
+
+extern char opal_secondary_entry;
+
+static void prom_query_opal(void)
+{
+ long rc;
+
+ prom_printf("Querying for OPAL presence... ");
+ rc = opal_query_takeover(&RELOC(prom_opal_size),
+ &RELOC(prom_opal_align));
+ prom_debug("(rc = %ld) ", rc);
+ if (rc != 0) {
+ prom_printf("not there.\n");
+ return;
+ }
+ RELOC(of_platform) = PLATFORM_OPAL;
+ prom_printf(" there !\n");
+ prom_debug(" opal_size = 0x%lx\n", RELOC(prom_opal_size));
+ prom_debug(" opal_align = 0x%lx\n", RELOC(prom_opal_align));
+ if (RELOC(prom_opal_align) < 0x10000)
+ RELOC(prom_opal_align) = 0x10000;
+}
+
+static int prom_rtas_call(int token, int nargs, int nret, int *outputs, ...)
+{
+ struct rtas_args rtas_args;
+ va_list list;
+ int i;
+
+ rtas_args.token = token;
+ rtas_args.nargs = nargs;
+ rtas_args.nret = nret;
+ rtas_args.rets = (rtas_arg_t *)&(rtas_args.args[nargs]);
+ va_start(list, outputs);
+ for (i = 0; i < nargs; ++i)
+ rtas_args.args[i] = va_arg(list, rtas_arg_t);
+ va_end(list);
+
+ for (i = 0; i < nret; ++i)
+ rtas_args.rets[i] = 0;
+
+ opal_enter_rtas(&rtas_args, RELOC(prom_rtas_data),
+ RELOC(prom_rtas_entry));
+
+ if (nret > 1 && outputs != NULL)
+ for (i = 0; i < nret-1; ++i)
+ outputs[i] = rtas_args.rets[i+1];
+ return (nret > 0)? rtas_args.rets[0]: 0;
+}
+
+static void __init prom_opal_hold_cpus(void)
+{
+ int i, cnt, cpu, rc;
+ long j;
+ phandle node;
+ char type[64];
+ u32 servers[8];
+ struct prom_t *_prom = &RELOC(prom);
+ void *entry = (unsigned long *)&RELOC(opal_secondary_entry);
+ struct opal_secondary_data *data = &RELOC(opal_secondary_data);
+
+ prom_debug("prom_opal_hold_cpus: start...\n");
+ prom_debug(" - entry = 0x%x\n", entry);
+ prom_debug(" - data = 0x%x\n", data);
+
+ data->ack = -1;
+ data->go = 0;
+
+ /* look for cpus */
+ for (node = 0; prom_next_node(&node); ) {
+ type[0] = 0;
+ prom_getprop(node, "device_type", type, sizeof(type));
+ if (strcmp(type, RELOC("cpu")) != 0)
+ continue;
+
+ /* Skip non-configured cpus. */
+ if (prom_getprop(node, "status", type, sizeof(type)) > 0)
+ if (strcmp(type, RELOC("okay")) != 0)
+ continue;
+
+ cnt = prom_getprop(node, "ibm,ppc-interrupt-server#s", servers,
+ sizeof(servers));
+ if (cnt == PROM_ERROR)
+ break;
+ cnt >>= 2;
+ for (i = 0; i < cnt; i++) {
+ cpu = servers[i];
+ prom_debug("CPU %d ... ", cpu);
+ if (cpu == _prom->cpu) {
+ prom_debug("booted !\n");
+ continue;
+ }
+ prom_debug("starting ... ");
+
+ /* Init the acknowledge var which will be reset by
+ * the secondary cpu when it awakens from its OF
+ * spinloop.
+ */
+ data->ack = -1;
+ rc = prom_rtas_call(RELOC(prom_rtas_start_cpu), 3, 1,
+ NULL, cpu, entry, data);
+ prom_debug("rtas rc=%d ...", rc);
+
+ for (j = 0; j < 100000000 && data->ack == -1; j++) {
+ HMT_low();
+ mb();
+ }
+ HMT_medium();
+ if (data->ack != -1)
+ prom_debug("done, PIR=0x%x\n", data->ack);
+ else
+ prom_debug("timeout !\n");
+ }
+ }
+ prom_debug("prom_opal_hold_cpus: end...\n");
+}
+
+static void prom_opal_takeover(void)
+{
+ struct opal_secondary_data *data = &RELOC(opal_secondary_data);
+ struct opal_takeover_args *args = &data->args;
+ u64 align = RELOC(prom_opal_align);
+ u64 top_addr, opal_addr;
+
+ args->k_image = (u64)RELOC(_stext);
+ args->k_size = _end - _stext;
+ args->k_entry = 0;
+ args->k_entry2 = 0x60;
+
+ top_addr = _ALIGN_UP(args->k_size, align);
+
+ if (RELOC(prom_initrd_start) != 0) {
+ args->rd_image = RELOC(prom_initrd_start);
+ args->rd_size = RELOC(prom_initrd_end) - args->rd_image;
+ args->rd_loc = top_addr;
+ top_addr = _ALIGN_UP(args->rd_loc + args->rd_size, align);
+ }
+
+ /* Pickup an address for the HAL. We want to go really high
+ * up to avoid problem with future kexecs. On the other hand
+ * we don't want to be all over the TCEs on P5IOC2 machines
+ * which are going to be up there too. We assume the machine
+ * has plenty of memory, and we ask for the HAL for now to
+ * be just below the 1G point, or above the initrd
+ */
+ opal_addr = _ALIGN_DOWN(0x40000000 - RELOC(prom_opal_size), align);
+ if (opal_addr < top_addr)
+ opal_addr = top_addr;
+ args->hal_addr = opal_addr;
+
+ prom_debug(" k_image = 0x%lx\n", args->k_image);
+ prom_debug(" k_size = 0x%lx\n", args->k_size);
+ prom_debug(" k_entry = 0x%lx\n", args->k_entry);
+ prom_debug(" k_entry2 = 0x%lx\n", args->k_entry2);
+ prom_debug(" hal_addr = 0x%lx\n", args->hal_addr);
+ prom_debug(" rd_image = 0x%lx\n", args->rd_image);
+ prom_debug(" rd_size = 0x%lx\n", args->rd_size);
+ prom_debug(" rd_loc = 0x%lx\n", args->rd_loc);
+ prom_printf("Performing OPAL takeover,this can take a few minutes..\n");
+ prom_close_stdin();
+ mb();
+ data->go = 1;
+ for (;;)
+ opal_do_takeover(args);
+}
+#endif /* CONFIG_PPC_POWERNV */
/*
* Allocate room for and instantiate RTAS
@@ -1326,6 +1517,12 @@ static void __init prom_instantiate_rtas(void)
prom_setprop(rtas_node, "/rtas", "linux,rtas-entry",
&entry, sizeof(entry));
+#ifdef CONFIG_PPC_POWERNV
+ /* PowerVN takeover hack */
+ RELOC(prom_rtas_data) = base;
+ RELOC(prom_rtas_entry) = entry;
+ prom_getprop(rtas_node, "start-cpu", &RELOC(prom_rtas_start_cpu), 4);
+#endif
prom_debug("rtas base = 0x%x\n", base);
prom_debug("rtas entry = 0x%x\n", entry);
prom_debug("rtas size = 0x%x\n", (long)size);
@@ -1543,7 +1740,7 @@ static void __init prom_hold_cpus(void)
*acknowledge = (unsigned long)-1;
if (reg != _prom->cpu) {
- /* Primary Thread of non-boot cpu */
+ /* Primary Thread of non-boot cpu or any thread */
prom_printf("starting cpu hw idx %lu... ", reg);
call_prom("start-cpu", 3, 0, node,
secondary_hold, reg);
@@ -1652,15 +1849,6 @@ static void __init prom_init_stdout(void)
prom_setprop(val, path, "linux,boot-display", NULL, 0);
}
-static void __init prom_close_stdin(void)
-{
- struct prom_t *_prom = &RELOC(prom);
- ihandle val;
-
- if (prom_getprop(_prom->chosen, "stdin", &val, sizeof(val)) > 0)
- call_prom("close", 1, 0, val);
-}
-
static int __init prom_find_machine_type(void)
{
struct prom_t *_prom = &RELOC(prom);
@@ -2504,6 +2692,7 @@ static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
#endif /* CONFIG_BLK_DEV_INITRD */
}
+
/*
* We enter here early on, when the Open Firmware prom is still
* handling exceptions and the MMU hash table for us.
@@ -2565,7 +2754,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
*/
prom_check_initrd(r3, r4);
-#ifdef CONFIG_PPC_PSERIES
+#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
/*
* On pSeries, inform the firmware about our capabilities
*/
@@ -2611,14 +2800,30 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
#endif
/*
- * On non-powermacs, try to instantiate RTAS and puts all CPUs
- * in spin-loops. PowerMacs don't have a working RTAS and use
- * a different way to spin CPUs
+ * On non-powermacs, try to instantiate RTAS. PowerMacs don't
+ * have a usable RTAS implementation.
*/
- if (RELOC(of_platform) != PLATFORM_POWERMAC) {
+ if (RELOC(of_platform) != PLATFORM_POWERMAC)
prom_instantiate_rtas();
- prom_hold_cpus();
+
+#ifdef CONFIG_PPC_POWERNV
+ /* Detect HAL and try instanciating it & doing takeover */
+ if (RELOC(of_platform) == PLATFORM_PSERIES_LPAR) {
+ prom_query_opal();
+ if (RELOC(of_platform) == PLATFORM_OPAL) {
+ prom_opal_hold_cpus();
+ prom_opal_takeover();
+ }
}
+#endif
+
+ /*
+ * On non-powermacs, put all CPUs in spin-loops.
+ *
+ * PowerMacs use a different mechanism to spin CPUs
+ */
+ if (RELOC(of_platform) != PLATFORM_POWERMAC)
+ prom_hold_cpus();
/*
* Fill in some infos for use by the kernel later on
diff --git a/arch/powerpc/kernel/prom_init_check.sh b/arch/powerpc/kernel/prom_init_check.sh
index 9f82f49..20af6aa 100644
--- a/arch/powerpc/kernel/prom_init_check.sh
+++ b/arch/powerpc/kernel/prom_init_check.sh
@@ -20,7 +20,8 @@ WHITELIST="add_reloc_offset __bss_start __bss_stop copy_and_flush
_end enter_prom memcpy memset reloc_offset __secondary_hold
__secondary_hold_acknowledge __secondary_hold_spinloop __start
strcmp strcpy strlcpy strlen strncmp strstr logo_linux_clut224
-reloc_got2 kernstart_addr memstart_addr linux_banner"
+reloc_got2 kernstart_addr memstart_addr linux_banner _stext
+opal_query_takeover opal_do_takeover opal_enter_rtas opal_secondary_entry"
NM="$1"
OBJ="$2"
diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile
index 1c43250..4971330 100644
--- a/arch/powerpc/platforms/powernv/Makefile
+++ b/arch/powerpc/platforms/powernv/Makefile
@@ -1,2 +1,2 @@
-obj-y += setup.o
+obj-y += setup.o opal-takeover.o
obj-$(CONFIG_SMP) += smp.o
diff --git a/arch/powerpc/platforms/powernv/opal-takeover.S b/arch/powerpc/platforms/powernv/opal-takeover.S
new file mode 100644
index 0000000..77b48b2
--- /dev/null
+++ b/arch/powerpc/platforms/powernv/opal-takeover.S
@@ -0,0 +1,140 @@
+/*
+ * PowerNV OPAL takeover assembly code, for use by prom_init.c
+ *
+ * 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.
+ */
+
+#include <asm/ppc_asm.h>
+#include <asm/hvcall.h>
+#include <asm/asm-offsets.h>
+#include <asm/opal.h>
+
+#define STK_PARAM(i) (48 + ((i)-3)*8)
+
+#define H_HAL_TAKEOVER 0x5124
+#define H_HAL_TAKEOVER_QUERY_MAGIC -1
+
+ .text
+_GLOBAL(opal_query_takeover)
+ mfcr r0
+ stw r0,8(r1)
+ std r3,STK_PARAM(r3)(r1)
+ std r4,STK_PARAM(r4)(r1)
+ li r3,H_HAL_TAKEOVER
+ li r4,H_HAL_TAKEOVER_QUERY_MAGIC
+ HVSC
+ ld r10,STK_PARAM(r3)(r1)
+ std r4,0(r10)
+ ld r10,STK_PARAM(r4)(r1)
+ std r5,0(r10)
+ lwz r0,8(r1)
+ mtcrf 0xff,r0
+ blr
+
+_GLOBAL(opal_do_takeover)
+ mfcr r0
+ stw r0,8(r1)
+ mflr r0
+ std r0,16(r1)
+ bl __opal_do_takeover
+ ld r0,16(r1)
+ mtlr r0
+ lwz r0,8(r1)
+ mtcrf 0xff,r0
+ blr
+
+__opal_do_takeover:
+ ld r4,0(r3)
+ ld r5,0x8(r3)
+ ld r6,0x10(r3)
+ ld r7,0x18(r3)
+ ld r8,0x20(r3)
+ ld r9,0x28(r3)
+ ld r10,0x30(r3)
+ ld r11,0x38(r3)
+ li r3,H_HAL_TAKEOVER
+ HVSC
+ blr
+
+ .globl opal_secondary_entry
+opal_secondary_entry:
+ mr r31,r3
+ mfmsr r11
+ li r12,(MSR_SF | MSR_ISF)@highest
+ sldi r12,r12,48
+ or r11,r11,r12
+ mtmsrd r11
+ isync
+ mfspr r4,SPRN_PIR
+ std r4,0(r3)
+1: HMT_LOW
+ ld r4,8(r3)
+ cmpli cr0,r4,0
+ beq 1b
+ HMT_MEDIUM
+1: addi r3,r31,16
+ bl __opal_do_takeover
+ b 1b
+
+_GLOBAL(opal_enter_rtas)
+ mflr r0
+ std r0,16(r1)
+ stdu r1,-PROM_FRAME_SIZE(r1) /* Save SP and create stack space */
+
+ /* Because PROM is running in 32b mode, it clobbers the high order half
+ * of all registers that it saves. We therefore save those registers
+ * PROM might touch to the stack. (r0, r3-r13 are caller saved)
+ */
+ SAVE_GPR(2, r1)
+ SAVE_GPR(13, r1)
+ SAVE_8GPRS(14, r1)
+ SAVE_10GPRS(22, r1)
+ mfcr r10
+ mfmsr r11
+ std r10,_CCR(r1)
+ std r11,_MSR(r1)
+
+ /* Get the PROM entrypoint */
+ mtlr r5
+
+ /* Switch MSR to 32 bits mode
+ */
+ li r12,1
+ rldicr r12,r12,MSR_SF_LG,(63-MSR_SF_LG)
+ andc r11,r11,r12
+ li r12,1
+ rldicr r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
+ andc r11,r11,r12
+ mtmsrd r11
+ isync
+
+ /* Enter RTAS here... */
+ blrl
+
+ /* Just make sure that r1 top 32 bits didn't get
+ * corrupt by OF
+ */
+ rldicl r1,r1,0,32
+
+ /* Restore the MSR (back to 64 bits) */
+ ld r0,_MSR(r1)
+ MTMSRD(r0)
+ isync
+
+ /* Restore other registers */
+ REST_GPR(2, r1)
+ REST_GPR(13, r1)
+ REST_8GPRS(14, r1)
+ REST_10GPRS(22, r1)
+ ld r4,_CCR(r1)
+ mtcr r4
+
+ addi r1,r1,PROM_FRAME_SIZE
+ ld r0,16(r1)
+ mtlr r0
+ blr
--
1.7.4.1
^ permalink raw reply related
* [PATCH 08/21] powerpc/powernv: Add CPU hotplug support
From: Benjamin Herrenschmidt @ 2011-09-10 14:19 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1315664408-16797-1-git-send-email-benh@kernel.crashing.org>
Unplugged CPU go into NAP mode in a loop until woken up
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/Kconfig | 2 +-
arch/powerpc/platforms/powernv/smp.c | 78 +++++++++++++++++++++++++++++++++-
2 files changed, 78 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 6926b61..85baae5 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -323,7 +323,7 @@ config SWIOTLB
config HOTPLUG_CPU
bool "Support for enabling/disabling CPUs"
- depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC)
+ depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC || PPC_POWERNV)
---help---
Say Y here to be able to disable and re-enable individual
CPUs at runtime on SMP machines.
diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c
index 36c7151..4f4ec37 100644
--- a/arch/powerpc/platforms/powernv/smp.c
+++ b/arch/powerpc/platforms/powernv/smp.c
@@ -33,7 +33,14 @@
#include "powernv.h"
-static void __devinit pnv_smp_setup_cpu(int cpu)
+#ifdef DEBUG
+#include <asm/udbg.h>
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+static void __cpuinit pnv_smp_setup_cpu(int cpu)
{
if (cpu != boot_cpuid)
xics_setup_cpu();
@@ -55,6 +62,67 @@ static int pnv_smp_cpu_bootable(unsigned int nr)
return 1;
}
+#ifdef CONFIG_HOTPLUG_CPU
+
+static int pnv_smp_cpu_disable(void)
+{
+ int cpu = smp_processor_id();
+
+ /* This is identical to pSeries... might consolidate by
+ * moving migrate_irqs_away to a ppc_md with default to
+ * the generic fixup_irqs. --BenH.
+ */
+ set_cpu_online(cpu, false);
+ vdso_data->processorCount--;
+ if (cpu == boot_cpuid)
+ boot_cpuid = cpumask_any(cpu_online_mask);
+ xics_migrate_irqs_away();
+ return 0;
+}
+
+static void pnv_smp_cpu_kill_self(void)
+{
+ unsigned int cpu;
+
+ /* If powersave_nap is enabled, use NAP mode, else just
+ * spin aimlessly
+ */
+ if (!powersave_nap) {
+ generic_mach_cpu_die();
+ return;
+ }
+
+ /* Standard hot unplug procedure */
+ local_irq_disable();
+ idle_task_exit();
+ current->active_mm = NULL; /* for sanity */
+ cpu = smp_processor_id();
+ DBG("CPU%d offline\n", cpu);
+ generic_set_cpu_dead(cpu);
+ smp_wmb();
+
+ /* We don't want to take decrementer interrupts while we are offline,
+ * so clear LPCR:PECE1. We keep PECE2 enabled.
+ */
+ mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~(u64)LPCR_PECE1);
+ while (!generic_check_cpu_restart(cpu)) {
+ power7_idle();
+ if (!generic_check_cpu_restart(cpu)) {
+ DBG("CPU%d Unexpected exit while offline !\n", cpu);
+ /* We may be getting an IPI, so we re-enable
+ * interrupts to process it, it will be ignored
+ * since we aren't online (hopefully)
+ */
+ local_irq_enable();
+ local_irq_disable();
+ }
+ }
+ mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) | LPCR_PECE1);
+ DBG("CPU%d coming online...\n", cpu);
+}
+
+#endif /* CONFIG_HOTPLUG_CPU */
+
static struct smp_ops_t pnv_smp_ops = {
.message_pass = smp_muxed_ipi_message_pass,
.cause_ipi = NULL, /* Filled at runtime by xics_smp_probe() */
@@ -62,6 +130,10 @@ static struct smp_ops_t pnv_smp_ops = {
.kick_cpu = smp_generic_kick_cpu,
.setup_cpu = pnv_smp_setup_cpu,
.cpu_bootable = pnv_smp_cpu_bootable,
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_disable = pnv_smp_cpu_disable,
+ .cpu_die = generic_cpu_die,
+#endif /* CONFIG_HOTPLUG_CPU */
};
/* This is called very early during platform setup_arch */
@@ -80,4 +152,8 @@ void __init pnv_smp_init(void)
smp_ops->take_timebase = rtas_take_timebase;
}
#endif /* CONFIG_PPC_RTAS */
+
+#ifdef CONFIG_HOTPLUG_CPU
+ ppc_md.cpu_die = pnv_smp_cpu_kill_self;
+#endif
}
--
1.7.4.1
^ permalink raw reply related
* [PATCH 07/21] of: Change logic to overwrite cmd_line with CONFIG_CMDLINE
From: Benjamin Herrenschmidt @ 2011-09-10 14:19 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1315664408-16797-1-git-send-email-benh@kernel.crashing.org>
We used to overwrite with CONFIG_CMDLINE if we found a chosen
node but failed to get bootargs out of it or they were empty,
unless CONFIG_CMDLINE_FORCE is set.
Instead change that to overwrite if cmd_line is non empty after
the bootargs check. It allows arch code to have other mechanisms
to retrieve the command line prior to parsing the device-tree.
Note: CONFIG_CMDLINE_FORCE case should ideally be handled elsewhere
as it won't work as it-is if the device-tree has no /chosen node
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
drivers/of/fdt.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 65200af..d382163 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -683,7 +683,7 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
#ifdef CONFIG_CMDLINE
#ifndef CONFIG_CMDLINE_FORCE
- if (p == NULL || l == 0 || (l == 1 && (*p) == 0))
+ if (!cmd_line[0])
#endif
strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
#endif /* CONFIG_CMDLINE */
--
1.7.4.1
^ permalink raw reply related
* [PATCH 06/21] powerpc: Add skeleton PowerNV platform
From: Benjamin Herrenschmidt @ 2011-09-10 14:19 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1315664408-16797-1-git-send-email-benh@kernel.crashing.org>
This adds a skeletton for the new Power "Non Virtualized"
platform which will be used by machines supporting running
without an hypervisor, for example in order to run KVM.
These machines will be using a new firmware called OPAL
for which the support will be provided by later patches.
The PowerNV platform is intended to be also usable under
the BML environment used internally for early CPU bringup
which is why the code also supports using RTAS instead of
OPAL in various places.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/boot/Makefile | 1 +
arch/powerpc/platforms/Kconfig | 1 +
arch/powerpc/platforms/Makefile | 1 +
arch/powerpc/platforms/powernv/Kconfig | 12 +++
arch/powerpc/platforms/powernv/Makefile | 2 +
arch/powerpc/platforms/powernv/powernv.h | 10 ++
arch/powerpc/platforms/powernv/setup.c | 153 ++++++++++++++++++++++++++++++
arch/powerpc/platforms/powernv/smp.c | 83 ++++++++++++++++
8 files changed, 263 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/platforms/powernv/Kconfig
create mode 100644 arch/powerpc/platforms/powernv/Makefile
create mode 100644 arch/powerpc/platforms/powernv/powernv.h
create mode 100644 arch/powerpc/platforms/powernv/setup.c
create mode 100644 arch/powerpc/platforms/powernv/smp.c
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index c26200b..52cde90 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -171,6 +171,7 @@ quiet_cmd_wrap = WRAP $@
$(if $3, -s $3)$(if $4, -d $4)$(if $5, -i $5) vmlinux
image-$(CONFIG_PPC_PSERIES) += zImage.pseries
+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
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index b9ba861..6de27d2 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -1,5 +1,6 @@
menu "Platform support"
+source "arch/powerpc/platforms/powernv/Kconfig"
source "arch/powerpc/platforms/pseries/Kconfig"
source "arch/powerpc/platforms/iseries/Kconfig"
source "arch/powerpc/platforms/chrp/Kconfig"
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
index 73e2116..2635a22 100644
--- a/arch/powerpc/platforms/Makefile
+++ b/arch/powerpc/platforms/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_PPC_82xx) += 82xx/
obj-$(CONFIG_PPC_83xx) += 83xx/
obj-$(CONFIG_FSL_SOC_BOOKE) += 85xx/
obj-$(CONFIG_PPC_86xx) += 86xx/
+obj-$(CONFIG_PPC_POWERNV) += powernv/
obj-$(CONFIG_PPC_PSERIES) += pseries/
obj-$(CONFIG_PPC_ISERIES) += iseries/
obj-$(CONFIG_PPC_MAPLE) += maple/
diff --git a/arch/powerpc/platforms/powernv/Kconfig b/arch/powerpc/platforms/powernv/Kconfig
new file mode 100644
index 0000000..5cd04f5
--- /dev/null
+++ b/arch/powerpc/platforms/powernv/Kconfig
@@ -0,0 +1,12 @@
+config PPC_POWERNV
+ depends on PPC64 && PPC_BOOK3S
+ bool "IBM PowerNV (Non-Virtualized) platform support"
+ select PPC_RTAS
+ select PPC_NATIVE
+ select PPC_XICS
+ select PPC_ICP_NATIVE
+ select PPC_ICS_RTAS
+ select PPC_P7_NAP
+ select PPC_PCI_CHOICE if EMBEDDED
+ default y
+
diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile
new file mode 100644
index 0000000..1c43250
--- /dev/null
+++ b/arch/powerpc/platforms/powernv/Makefile
@@ -0,0 +1,2 @@
+obj-y += setup.o
+obj-$(CONFIG_SMP) += smp.o
diff --git a/arch/powerpc/platforms/powernv/powernv.h b/arch/powerpc/platforms/powernv/powernv.h
new file mode 100644
index 0000000..35b7160
--- /dev/null
+++ b/arch/powerpc/platforms/powernv/powernv.h
@@ -0,0 +1,10 @@
+#ifndef _POWERNV_H
+#define _POWERNV_H
+
+#ifdef CONFIG_SMP
+extern void pnv_smp_init(void);
+#else
+static inline void pnv_smp_init(void) { }
+#endif
+
+#endif /* _POWERNV_H */
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
new file mode 100644
index 0000000..569f9cc
--- /dev/null
+++ b/arch/powerpc/platforms/powernv/setup.c
@@ -0,0 +1,153 @@
+/*
+ * PowerNV setup code.
+ *
+ * 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.
+ */
+
+#undef DEBUG
+
+#include <linux/cpu.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/of.h>
+#include <linux/interrupt.h>
+#include <linux/bug.h>
+
+#include <asm/machdep.h>
+#include <asm/firmware.h>
+#include <asm/xics.h>
+
+#include "powernv.h"
+
+static void __init pnv_setup_arch(void)
+{
+ /* Force console to hvc for now until we have sorted out the
+ * real console situation for the platform. This will make
+ * hvc_udbg work at least.
+ */
+ add_preferred_console("hvc", 0, NULL);
+
+ /* Initialize SMP */
+ pnv_smp_init();
+
+ /* XXX PCI */
+
+ /* XXX NVRAM */
+
+ /* Enable NAP mode */
+ powersave_nap = 1;
+
+ /* XXX PMCS */
+}
+
+static void __init pnv_init_early(void)
+{
+ /* XXX IOMMU */
+}
+
+static void __init pnv_init_IRQ(void)
+{
+ xics_init();
+
+ WARN_ON(!ppc_md.get_irq);
+}
+
+static void pnv_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);
+ seq_printf(m, "machine\t\t: PowerNV %s\n", model);
+ of_node_put(root);
+}
+
+static void pnv_restart(char *cmd)
+{
+ for (;;);
+}
+
+static void pnv_power_off(void)
+{
+ for (;;);
+}
+
+static void pnv_halt(void)
+{
+ for (;;);
+}
+
+static unsigned long __init pnv_get_boot_time(void)
+{
+ return 0;
+}
+
+static void pnv_get_rtc_time(struct rtc_time *rtc_tm)
+{
+}
+
+static int pnv_set_rtc_time(struct rtc_time *tm)
+{
+ return 0;
+}
+
+static void pnv_progress(char *s, unsigned short hex)
+{
+}
+
+#ifdef CONFIG_KEXEC
+static void pnv_kexec_cpu_down(int crash_shutdown, int secondary)
+{
+ xics_kexec_teardown_cpu(secondary);
+}
+#endif /* CONFIG_KEXEC */
+
+static int __init pnv_probe(void)
+{
+ unsigned long root = of_get_flat_dt_root();
+
+ if (!of_flat_dt_is_compatible(root, "ibm,powernv"))
+ return 0;
+
+ hpte_init_native();
+
+ pr_debug("PowerNV detected !\n");
+
+ return 1;
+}
+
+define_machine(powernv) {
+ .name = "PowerNV",
+ .probe = pnv_probe,
+ .setup_arch = pnv_setup_arch,
+ .init_early = pnv_init_early,
+ .init_IRQ = pnv_init_IRQ,
+ .show_cpuinfo = pnv_show_cpuinfo,
+ .restart = pnv_restart,
+ .power_off = pnv_power_off,
+ .halt = pnv_halt,
+ .get_boot_time = pnv_get_boot_time,
+ .get_rtc_time = pnv_get_rtc_time,
+ .set_rtc_time = pnv_set_rtc_time,
+ .progress = pnv_progress,
+ .power_save = power7_idle,
+ .calibrate_decr = generic_calibrate_decr,
+#ifdef CONFIG_KEXEC
+ .kexec_cpu_down = pnv_kexec_cpu_down,
+#endif
+};
diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c
new file mode 100644
index 0000000..36c7151
--- /dev/null
+++ b/arch/powerpc/platforms/powernv/smp.c
@@ -0,0 +1,83 @@
+/*
+ * SMP support for PowerNV machines.
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/cpu.h>
+
+#include <asm/irq.h>
+#include <asm/smp.h>
+#include <asm/paca.h>
+#include <asm/machdep.h>
+#include <asm/cputable.h>
+#include <asm/firmware.h>
+#include <asm/system.h>
+#include <asm/rtas.h>
+#include <asm/vdso_datapage.h>
+#include <asm/cputhreads.h>
+#include <asm/xics.h>
+
+#include "powernv.h"
+
+static void __devinit pnv_smp_setup_cpu(int cpu)
+{
+ if (cpu != boot_cpuid)
+ xics_setup_cpu();
+}
+
+static int pnv_smp_cpu_bootable(unsigned int nr)
+{
+ /* Special case - we inhibit secondary thread startup
+ * during boot if the user requests it.
+ */
+ if (system_state < SYSTEM_RUNNING && cpu_has_feature(CPU_FTR_SMT)) {
+ if (!smt_enabled_at_boot && cpu_thread_in_core(nr) != 0)
+ return 0;
+ if (smt_enabled_at_boot
+ && cpu_thread_in_core(nr) >= smt_enabled_at_boot)
+ return 0;
+ }
+
+ return 1;
+}
+
+static struct smp_ops_t pnv_smp_ops = {
+ .message_pass = smp_muxed_ipi_message_pass,
+ .cause_ipi = NULL, /* Filled at runtime by xics_smp_probe() */
+ .probe = xics_smp_probe,
+ .kick_cpu = smp_generic_kick_cpu,
+ .setup_cpu = pnv_smp_setup_cpu,
+ .cpu_bootable = pnv_smp_cpu_bootable,
+};
+
+/* This is called very early during platform setup_arch */
+void __init pnv_smp_init(void)
+{
+ smp_ops = &pnv_smp_ops;
+
+ /* XXX We don't yet have a proper entry point from HAL, for
+ * now we rely on kexec-style entry from BML
+ */
+
+#ifdef CONFIG_PPC_RTAS
+ /* Non-lpar has additional take/give timebase */
+ if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) {
+ smp_ops->give_timebase = rtas_give_timebase;
+ smp_ops->take_timebase = rtas_take_timebase;
+ }
+#endif /* CONFIG_PPC_RTAS */
+}
--
1.7.4.1
^ permalink raw reply related
* [PATCH 05/21] powerpc/powernv: Don't clobber r9 in relative_toc()
From: Benjamin Herrenschmidt @ 2011-09-10 14:19 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1315664408-16797-1-git-send-email-benh@kernel.crashing.org>
With OPAL, r8 and r9 will be used to pass the OPAL base and entry
for debugging purposes (those informations are also in the
device-tree). We don't want to clobber those registers that
early.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/kernel/head_64.S | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 3564c49..e708abe 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -674,9 +674,9 @@ _GLOBAL(enable_64b_mode)
_GLOBAL(relative_toc)
mflr r0
bcl 20,31,$+4
-0: mflr r9
- ld r2,(p_toc - 0b)(r9)
- add r2,r2,r9
+0: mflr r11
+ ld r2,(p_toc - 0b)(r11)
+ add r2,r2,r11
mtlr r0
blr
--
1.7.4.1
^ permalink raw reply related
* [PATCH 04/21] tty/hvc/hvsi_lib: Updates for running under OPAL v2
From: Benjamin Herrenschmidt @ 2011-09-10 14:19 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1315664408-16797-1-git-send-email-benh@kernel.crashing.org>
Experience shows that our hvsi negotiation timeouts were too short
under OPAL v2. This patch bumps them from 200ms to 500ms.
To limit the impact when the console is repeatedly opened/closed,
we also avoid re-negotiating an already opened & established
connection which typically happens when running init scripts
on the tty shared with the kernel console.
Finally, while touching hvsi, I added a comment explaining why we
limit our output packet size to 12 bytes.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/include/asm/hvsi.h | 4 ++++
drivers/tty/hvc/hvsi_lib.c | 12 +++++++-----
2 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/arch/powerpc/include/asm/hvsi.h b/arch/powerpc/include/asm/hvsi.h
index d3f64f3..ca85d9d 100644
--- a/arch/powerpc/include/asm/hvsi.h
+++ b/arch/powerpc/include/asm/hvsi.h
@@ -19,6 +19,10 @@
#define HVSI_TSDTR 0x01
#define HVSI_TSCD 0x20
+/* Never send more than 12 bytes at once, that is 16 bytes
+ * with header, which is the max pHyp can swallow in one
+ * hcall.
+ */
#define HVSI_MAX_OUTGOING_DATA 12
#define HVSI_VERSION 1
diff --git a/drivers/tty/hvc/hvsi_lib.c b/drivers/tty/hvc/hvsi_lib.c
index bd9b098..08e3e90 100644
--- a/drivers/tty/hvc/hvsi_lib.c
+++ b/drivers/tty/hvc/hvsi_lib.c
@@ -316,10 +316,10 @@ void hvsilib_establish(struct hvsi_priv *pv)
pr_devel("HVSI@%x: Establishing...\n", pv->termno);
- /* Try for up to 200ms, there can be a packet to
+ /* Try for up to 500ms, there can be a packet to
* start the process waiting for us...
*/
- for (timeout = 0; timeout < 20; timeout++) {
+ for (timeout = 0; timeout < 50; timeout++) {
if (pv->established)
goto established;
if (!hvsi_get_packet(pv))
@@ -341,8 +341,8 @@ void hvsilib_establish(struct hvsi_priv *pv)
pr_devel("HVSI@%x: ... waiting handshake\n", pv->termno);
- /* Try for up to 200s */
- for (timeout = 0; timeout < 20; timeout++) {
+ /* Try for up to 500ms */
+ for (timeout = 0; timeout < 50; timeout++) {
if (pv->established)
goto established;
if (!hvsi_get_packet(pv))
@@ -379,7 +379,9 @@ int hvsilib_open(struct hvsi_priv *pv, struct hvc_struct *hp)
/* Keep track of the tty data structure */
pv->tty = tty_kref_get(hp->tty);
- hvsilib_establish(pv);
+ WARN_ON(pv->opened && !pv->is_console);
+ if (!pv->opened)
+ hvsilib_establish(pv);
return 0;
}
--
1.7.4.1
^ permalink raw reply related
* [PATCH 03/21] powerpc/pci: Call pcie_bus_configure_settings()
From: Benjamin Herrenschmidt @ 2011-09-10 14:19 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1315664408-16797-1-git-send-email-benh@kernel.crashing.org>
This new function is used to properly setup the PCI Express Max Payload Size
(and in some circumstances Max Read Request Size).
Some systems will not operate properly if these aren't set correctly and
the firmware doesn't always do it.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/kernel/pci-common.c | 11 +++++++++++
1 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 32656f1..1bd47f3 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -1730,6 +1730,17 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose)
if (mode == PCI_PROBE_NORMAL)
hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
+
+ /* Configure PCI Express settings */
+ if (bus) {
+ struct pci_bus *child;
+ list_for_each_entry(child, &bus->children, node) {
+ struct pci_dev *self = child->self;
+ if (!self)
+ continue;
+ pcie_bus_configure_settings(child, self->pcie_mpss);
+ }
+ }
}
static void fixup_hide_host_resource_fsl(struct pci_dev *dev)
--
1.7.4.1
^ permalink raw reply related
* [PATCH 02/21] powerpc/smp: More generic support for "soft hotplug"
From: Benjamin Herrenschmidt @ 2011-09-10 14:19 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1315664408-16797-1-git-send-email-benh@kernel.crashing.org>
This adds more generic support for doing CPU hotplug with a simple
idle loop and no actual reset of the processors. The generic
smp_generic_kick_cpu() does the hotplug bringup trick if the PACA
shows that the CPU has already been started at boot and we provide
an accessor for the CPU state.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/include/asm/smp.h | 1 +
arch/powerpc/kernel/smp.c | 30 +++++++++++++++++++++++++-----
2 files changed, 26 insertions(+), 5 deletions(-)
diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index 15a70b7..adba970 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -65,6 +65,7 @@ int generic_cpu_disable(void);
void generic_cpu_die(unsigned int cpu);
void generic_mach_cpu_die(void);
void generic_set_cpu_dead(unsigned int cpu);
+int generic_check_cpu_restart(unsigned int cpu);
#endif
#ifdef CONFIG_PPC64
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 7bf2187..af7e772 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -70,6 +70,10 @@
static DEFINE_PER_CPU(struct task_struct *, idle_thread_array);
#define get_idle_for_cpu(x) (per_cpu(idle_thread_array, x))
#define set_idle_for_cpu(x, p) (per_cpu(idle_thread_array, x) = (p))
+
+/* State of each CPU during hotplug phases */
+static DEFINE_PER_CPU(int, cpu_state) = { 0 };
+
#else
static struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ;
#define get_idle_for_cpu(x) (idle_thread_array[(x)])
@@ -104,12 +108,25 @@ int __devinit smp_generic_kick_cpu(int nr)
* cpu_start field to become non-zero After we set cpu_start,
* the processor will continue on to secondary_start
*/
- paca[nr].cpu_start = 1;
- smp_mb();
+ if (!paca[nr].cpu_start) {
+ paca[nr].cpu_start = 1;
+ smp_mb();
+ return 0;
+ }
+
+#ifdef CONFIG_HOTPLUG_CPU
+ /*
+ * Ok it's not there, so it might be soft-unplugged, let's
+ * try to bring it back
+ */
+ per_cpu(cpu_state, nr) = CPU_UP_PREPARE;
+ smp_wmb();
+ smp_send_reschedule(nr);
+#endif /* CONFIG_HOTPLUG_CPU */
return 0;
}
-#endif
+#endif /* CONFIG_PPC64 */
static irqreturn_t call_function_action(int irq, void *data)
{
@@ -357,8 +374,6 @@ void __devinit smp_prepare_boot_cpu(void)
}
#ifdef CONFIG_HOTPLUG_CPU
-/* State of each CPU during hotplug phases */
-static DEFINE_PER_CPU(int, cpu_state) = { 0 };
int generic_cpu_disable(void)
{
@@ -406,6 +421,11 @@ void generic_set_cpu_dead(unsigned int cpu)
{
per_cpu(cpu_state, cpu) = CPU_DEAD;
}
+
+int generic_check_cpu_restart(unsigned int cpu)
+{
+ return per_cpu(cpu_state, cpu) == CPU_UP_PREPARE;
+}
#endif
struct create_idle {
--
1.7.4.1
^ permalink raw reply related
* [PATCH 01/21] powerpc/udbg: Fix Kconfig entry for avoiding 44x early debug with KVM
From: Benjamin Herrenschmidt @ 2011-09-10 14:19 UTC (permalink / raw)
To: linuxppc-dev
It was preventing the global early debug selection whenever KVM was enabled
instead of only preventing the 440 specific one.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/Kconfig.debug | 7 +++----
1 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index 067cb84..cc01f1d 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -141,9 +141,6 @@ config BOOTX_TEXT
config PPC_EARLY_DEBUG
bool "Early debugging (dangerous)"
- # PPC_EARLY_DEBUG on 440 leaves AS=1 mappings above the TLB high water
- # mark, which doesn't work with current 440 KVM.
- depends on !KVM
help
Say Y to enable some early debugging facilities that may be available
for your processor/board combination. Those facilities are hacks
@@ -222,7 +219,9 @@ config PPC_EARLY_DEBUG_BEAT
config PPC_EARLY_DEBUG_44x
bool "Early serial debugging for IBM/AMCC 44x CPUs"
- depends on 44x
+ # PPC_EARLY_DEBUG on 440 leaves AS=1 mappings above the TLB high water
+ # mark, which doesn't work with current 440 KVM.
+ depends on 44x && !KVM
help
Select this to enable early debugging for IBM 44x chips via the
inbuilt serial port. If you enable this, ensure you set
--
1.7.4.1
^ permalink raw reply related
* Re: [PATCH] powerpc: Optimize __arch_swab32 and __arch_swab16
From: Benjamin Herrenschmidt @ 2011-09-10 9:24 UTC (permalink / raw)
To: Joakim Tjernlund; +Cc: linuxppc-dev
In-Reply-To: <1315570258-12275-1-git-send-email-Joakim.Tjernlund@transmode.se>
On Fri, 2011-09-09 at 14:10 +0200, Joakim Tjernlund wrote:
> PPC __arch_swab32 and __arch_swab16 generates non optimal code.
> They do not schedule very well, need to copy its input register
> and swab16 needs an extra insn to clear its upper bits.
> Fix this with better inline ASM.
>
> Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
> ---
> arch/powerpc/include/asm/swab.h | 28 ++++++++++++++--------------
> 1 files changed, 14 insertions(+), 14 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/swab.h b/arch/powerpc/include/asm/swab.h
> index c581e3e..3b9a200 100644
> --- a/arch/powerpc/include/asm/swab.h
> +++ b/arch/powerpc/include/asm/swab.h
> @@ -61,25 +61,25 @@ static inline void __arch_swab32s(__u32 *addr)
>
> static inline __attribute_const__ __u16 __arch_swab16(__u16 value)
> {
> - __u16 result;
> -
> - __asm__("rlwimi %0,%1,8,16,23"
> - : "=r" (result)
> - : "r" (value), "0" (value >> 8));
> - return result;
> + __asm__("rlwimi %0,%0,16,0x00ff0000\n\t"
> + "rlwinm %0,%0,24,0x0000ffff"
> + : "+r"(value));
> + return value;
> }
> #define __arch_swab16 __arch_swab16
I don't quite get the thing about needing to clear the high bits.
Value is a u16 to start with, %0 is pre-filled with value >> 8 which
won't add anything to the upper bits, neither will rlwimi, so why would
you need to clear upper bits ?
Now I do see why gcc might generate something sub-optimal here, but can
you provide examples of asm output before/after in the patch commit ?
> static inline __attribute_const__ __u32 __arch_swab32(__u32 value)
> {
> - __u32 result;
> -
> - __asm__("rlwimi %0,%1,24,16,23\n\t"
> - "rlwimi %0,%1,8,8,15\n\t"
> - "rlwimi %0,%1,24,0,7"
> - : "=r" (result)
> - : "r" (value), "0" (value >> 24));
> - return result;
> + __u32 tmp;
> +
> + __asm__("rlwimi %0,%1,24,0xffffffff"
> + : "=r" (value) : "r" (value));
> + tmp = value;
> + __asm__("rlwimi %0,%1,16,0x00ff0000"
> + : "+r" (value) : "r" (tmp));
> + __asm__("rlwimi %0,%1,16,0x000000ff"
> + : "+r" (value) : "r" (tmp));
> + return value;
> }
> #define __arch_swab32 __arch_swab32
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH tip/core/rcu 48/55] powerpc: strengthen value-returning-atomics memory barriers
From: Olof Johansson @ 2011-09-09 18:43 UTC (permalink / raw)
To: paulmck
Cc: mathieu.desnoyers, laijs, eric.dumazet, patches, peterz,
linux-kernel, rostedt, josh, dhowells, darren, niv, linuxppc-dev,
tglx, anton, Valdis.Kletnieks, mingo, akpm, paulus
In-Reply-To: <20110909173455.GH2435@linux.vnet.ibm.com>
On Fri, Sep 9, 2011 at 10:34 AM, Paul E. McKenney
<paulmck@linux.vnet.ibm.com> wrote:
> On Fri, Sep 09, 2011 at 10:23:33AM -0700, Olof Johansson wrote:
>> [+linuxppc-dev]
>>
>> On Tue, Sep 6, 2011 at 11:00 AM, Paul E. McKenney
>> <paulmck@linux.vnet.ibm.com> wrote:
>> > The trailing isync/lwsync in PowerPC value-returning atomics needs
>> > to be a sync in order to provide the required ordering properties.
>> > The leading lwsync/eieio can remain, as the remainder of the required
>> > ordering guarantees are provided by the atomic instructions: Any
>> > reordering will cause the stwcx to fail, which will result in a retry.
>>
>> Admittedly, my powerpc barrier memory is starting to fade, but isn't
>> isync sufficient here? It will make sure all instructions before it
>> have retired, and will restart any speculative/issued instructions
>> beyond it.
>>
>> lwsync not being sufficient makes sense since a load can overtake it.
>
> As I understand it, although isync waits for the prior stwcx to execute,
> it does not guarantee that the corresponding store is visible to all
> processors before any following loads.
Ah yes, combined with brushing up on the semantics in
memory-barriers.txt, this sounds reasonable to me.
>> > diff --git a/arch/powerpc/include/asm/synch.h b/arch/powerpc/include/a=
sm/synch.h
>> > index d7cab44..4d97fbe 100644
>> > --- a/arch/powerpc/include/asm/synch.h
>> > +++ b/arch/powerpc/include/asm/synch.h
>> > @@ -37,11 +37,7 @@ static inline void isync(void)
>> > =A0#endif
>> >
>> > =A0#ifdef CONFIG_SMP
>> > -#define __PPC_ACQUIRE_BARRIER =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 =A0 =A0\
>> > - =A0 =A0 =A0 START_LWSYNC_SECTION(97); =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 \
>> > - =A0 =A0 =A0 isync; =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0\
>> > - =A0 =A0 =A0 MAKE_LWSYNC_SECTION_ENTRY(97, __lwsync_fixup);
>> > -#define PPC_ACQUIRE_BARRIER =A0 =A0"\n" stringify_in_c(__PPC_ACQUIRE_=
BARRIER)
>> > +#define PPC_ACQUIRE_BARRIER =A0 =A0"\n" stringify_in_c(sync;)
>>
>> This can just be done as "\n\tsync\n" instead of the stringify stuff.
>
> That does sound a bit more straightforward, now that you mention it. =A0;=
-)
With that change, I'm:
Acked-by: Olof Johansson <olof@lixom.net>
But at least Ben or Anton should sign off on it too.
-Olof
^ permalink raw reply
* Re: [PATCH tip/core/rcu 48/55] powerpc: strengthen value-returning-atomics memory barriers
From: Paul E. McKenney @ 2011-09-09 17:34 UTC (permalink / raw)
To: Olof Johansson
Cc: mathieu.desnoyers, laijs, eric.dumazet, patches, peterz,
linux-kernel, rostedt, josh, dhowells, darren, niv, linuxppc-dev,
tglx, anton, Valdis.Kletnieks, mingo, akpm, paulus
In-Reply-To: <CAOesGMi--W6TCUMZzF07-Zep9Ta3tBJWZcG+5imEK_Hza0y9Jg@mail.gmail.com>
On Fri, Sep 09, 2011 at 10:23:33AM -0700, Olof Johansson wrote:
> [+linuxppc-dev]
>
> On Tue, Sep 6, 2011 at 11:00 AM, Paul E. McKenney
> <paulmck@linux.vnet.ibm.com> wrote:
> > The trailing isync/lwsync in PowerPC value-returning atomics needs
> > to be a sync in order to provide the required ordering properties.
> > The leading lwsync/eieio can remain, as the remainder of the required
> > ordering guarantees are provided by the atomic instructions: Any
> > reordering will cause the stwcx to fail, which will result in a retry.
>
> Admittedly, my powerpc barrier memory is starting to fade, but isn't
> isync sufficient here? It will make sure all instructions before it
> have retired, and will restart any speculative/issued instructions
> beyond it.
>
> lwsync not being sufficient makes sense since a load can overtake it.
As I understand it, although isync waits for the prior stwcx to execute,
it does not guarantee that the corresponding store is visible to all
processors before any following loads.
> > diff --git a/arch/powerpc/include/asm/synch.h b/arch/powerpc/include/asm/synch.h
> > index d7cab44..4d97fbe 100644
> > --- a/arch/powerpc/include/asm/synch.h
> > +++ b/arch/powerpc/include/asm/synch.h
> > @@ -37,11 +37,7 @@ static inline void isync(void)
> > #endif
> >
> > #ifdef CONFIG_SMP
> > -#define __PPC_ACQUIRE_BARRIER \
> > - START_LWSYNC_SECTION(97); \
> > - isync; \
> > - MAKE_LWSYNC_SECTION_ENTRY(97, __lwsync_fixup);
> > -#define PPC_ACQUIRE_BARRIER "\n" stringify_in_c(__PPC_ACQUIRE_BARRIER)
> > +#define PPC_ACQUIRE_BARRIER "\n" stringify_in_c(sync;)
>
> This can just be done as "\n\tsync\n" instead of the stringify stuff.
That does sound a bit more straightforward, now that you mention it. ;-)
Thanx, Paul
^ permalink raw reply
* Re: [PATCH tip/core/rcu 48/55] powerpc: strengthen value-returning-atomics memory barriers
From: Olof Johansson @ 2011-09-09 17:23 UTC (permalink / raw)
To: Paul E. McKenney
Cc: mathieu.desnoyers, laijs, eric.dumazet, patches, peterz,
linux-kernel, rostedt, josh, dhowells, darren, niv, linuxppc-dev,
tglx, anton, Valdis.Kletnieks, mingo, akpm, paulus
In-Reply-To: <1315332049-2604-48-git-send-email-paulmck@linux.vnet.ibm.com>
[+linuxppc-dev]
On Tue, Sep 6, 2011 at 11:00 AM, Paul E. McKenney
<paulmck@linux.vnet.ibm.com> wrote:
> The trailing isync/lwsync in PowerPC value-returning atomics needs
> to be a sync in order to provide the required ordering properties.
> The leading lwsync/eieio can remain, as the remainder of the required
> ordering guarantees are provided by the atomic instructions: Any
> reordering will cause the stwcx to fail, which will result in a retry.
Admittedly, my powerpc barrier memory is starting to fade, but isn't
isync sufficient here? It will make sure all instructions before it
have retired, and will restart any speculative/issued instructions
beyond it.
lwsync not being sufficient makes sense since a load can overtake it.
> diff --git a/arch/powerpc/include/asm/synch.h b/arch/powerpc/include/asm/=
synch.h
> index d7cab44..4d97fbe 100644
> --- a/arch/powerpc/include/asm/synch.h
> +++ b/arch/powerpc/include/asm/synch.h
> @@ -37,11 +37,7 @@ static inline void isync(void)
> =A0#endif
>
> =A0#ifdef CONFIG_SMP
> -#define __PPC_ACQUIRE_BARRIER =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0\
> - =A0 =A0 =A0 START_LWSYNC_SECTION(97); =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 \
> - =A0 =A0 =A0 isync; =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0\
> - =A0 =A0 =A0 MAKE_LWSYNC_SECTION_ENTRY(97, __lwsync_fixup);
> -#define PPC_ACQUIRE_BARRIER =A0 =A0"\n" stringify_in_c(__PPC_ACQUIRE_BAR=
RIER)
> +#define PPC_ACQUIRE_BARRIER =A0 =A0"\n" stringify_in_c(sync;)
This can just be done as "\n\tsync\n" instead of the stringify stuff.
-Olof
^ permalink raw reply
* RE: [PATCH] eSDHC: Access Freescale eSDHC registers by 32-bit
From: Zang Roy-R61911 @ 2011-09-09 16:00 UTC (permalink / raw)
To: Anton Vorontsov, cjb@laptop.org
Cc: linuxppc-dev@lists.ozlabs.org, akpm@linux-foundation.org,
linux-mmc@vger.kernel.org, Xu Lei-B33228
In-Reply-To: <20110909140701.GA9258@oksana.dev.rtsoft.ru>
DQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogQW50b24gVm9yb250c292
IFttYWlsdG86Y2JvdWF0bWFpbHJ1QGdtYWlsLmNvbV0NCj4gU2VudDogRnJpZGF5LCBTZXB0ZW1i
ZXIgMDksIDIwMTEgMjI6MDcgUE0NCj4gVG86IFphbmcgUm95LVI2MTkxMQ0KPiBDYzogbGludXgt
bW1jQHZnZXIua2VybmVsLm9yZzsgbGludXhwcGMtZGV2QGxpc3RzLm96bGFicy5vcmc7IGFrcG1A
bGludXgtDQo+IGZvdW5kYXRpb24ub3JnOyBYdSBMZWktQjMzMjI4OyBLdW1hciBHYWxhDQo+IFN1
YmplY3Q6IFJlOiBbUEFUQ0hdIGVTREhDOiBBY2Nlc3MgRnJlZXNjYWxlIGVTREhDIHJlZ2lzdGVy
cyBieSAzMi1iaXQNCj4gDQo+IE9uIEZyaSwgU2VwIDA5LCAyMDExIGF0IDA4OjA1OjQ2UE0gKzA4
MDAsIFJveSBaYW5nIHdyb3RlOg0KPiA+IEZyb206IFh1IGxlaSA8QjMzMjI4QGZyZWVzY2FsZS5j
b20+DQo+ID4NCj4gPiBGcmVlc2NhbGUgZVNESEMgcmVnaXN0ZXJzIG9ubHkgc3VwcG9ydCAzMi1i
aXQgYWNjZXNzZXMsDQo+ID4gdGhpcyBwYXRjaCBlbnN1cmVzIHRoYXQgYWxsIEZyZWVzY2FsZSBl
U0RIQyByZWdpc3RlciBhY2Nlc3Nlcw0KPiA+IGFyZSAzMi1iaXQuDQo+ID4NCj4gPiBTaWduZWQt
b2ZmLWJ5OiBYdSBsZWkgPEIzMzIyOEBmcmVlc2NhbGUuY29tPg0KPiA+IFNpZ25lZC1vZmYtYnk6
IFJveSBaYW5nIDx0aWUtZmVpLnphbmdAZnJlZXNjYWxlLmNvbT4NCj4gPiBTaWduZWQtb2ZmLWJ5
OiBLdW1hciBHYWxhIDxnYWxha0BrZXJuZWwuY3Jhc2hpbmcub3JnPg0KPiA+IC0tLQ0KPiANCj4g
VGhlIHBhdGNoIGxvb2tzIE9LLg0KPiANCj4gQWNrZWQtYnk6IEFudG9uIFZvcm9udHNvdiA8Y2Jv
dWF0bWFpbHJ1QGdtYWlsLmNvbT4NClRoYW5rcy4NCkFkZCBDaHJpcy4NCg0KPiANCj4gWy4uLl0N
Cj4gPiArc3RhdGljIHU4IGVzZGhjX3JlYWRiKHN0cnVjdCBzZGhjaV9ob3N0ICpob3N0LCBpbnQg
cmVnKQ0KPiA+ICt7DQo+ID4gKwlpbnQgYmFzZSA9IHJlZyAmIH4weDM7DQo+ID4gKwlpbnQgc2hp
ZnQgPSAocmVnICYgMHgzKSAqIDg7DQo+ID4gKwl1OCByZXQgPSAoaW5fYmUzMihob3N0LT5pb2Fk
ZHIgKyBiYXNlKSA+PiBzaGlmdCkgJiAweGZmOw0KPiA+ICAJcmV0dXJuIHJldDsNCj4gPiAgfQ0K
PiANCj4gVGhvdWdoLCBJIHdvbmRlciBpZiB3ZSBjb3VsZCBjaGFuZ2Ugc2RoY2lfYmUzMmJzX3Jl
YWR7Yix3fSwgaW5zdGVhZA0KPiBvZiBtYWtpbmcgdGhpcyBsb2NhbCB0byBlU0RIQy4NCj4gDQo+
IFRoZSB0aGluZyBpczogc2RoY2lfYmUzMmJzX3dyaXRlYigpIGlzIHVzaW5nIGNscnNldGJpdHNf
YmUzMiwNCj4gc28gdGhlIHdyaXRlIHZhcmlhbnQgYWxyZWFkeSB1c2VzIDMyLWJpdCBhY2Nlc3Nv
cnMsIHNvIG5vdGhpbmcgc2hvdWxkDQo+IGJyZWFrIGlmIHdlIHN3aXRjaCBzZGhjaV9iZTMyYnNf
cmVhZGIoKSB0byBpbl9iZTMyKCkuDQo+IA0KPiBCdXQgbWF5YmUgaXQncyBzYWZlciBpZiB3ZSBk
byB0aGlzIGluIGEgc2VwYXJhdGUgcGF0Y2gsIHNvIHRoYXQgaXQNCj4gY291bGQgYmUgZWFzaWx5
IHJldmVydGVkIHdpdGhvdXQgaW1wYWN0aW5nIGVTREhDIGlmIHNvbWV0aGluZyBhY3R1YWxseQ0K
PiBicmVha3MuDQo+IA0KPiBZb3UgZGVjaWRlLiA6LSkNCj4gDQo+IFRoYW5rcyENClRoZSBzdWdn
ZXN0aW9uIG1ha2VzIHNlbnNlLiBJJ2QgbGlrZSB0byBkbyB0aGlzIGluIGEgc2VwYXJhdGUgcGF0
Y2ggYWZ0ZXIgdGhpcyBwYXRjaCBhcHBsaWVkLg0KVGhhbmtzLg0KUm95DQo=
^ permalink raw reply
* Re: [PATCH 54/62] TTY: irq: Remove IRQF_DISABLED
From: Tobias Klauser @ 2011-09-09 9:49 UTC (permalink / raw)
To: Yong Zhang
Cc: Jesper Nilsson, linux-cris-kernel, nios2-dev, Lucas De Marchi,
Greg Kroah-Hartman, linux-kernel, Mikael Starvik, Jesper Juhl,
linux-serial, Jiri Kosina, uclinux-dist-devel, tglx, Sonic Zhang,
linuxppc-dev, mingo, Alan Cox
In-Reply-To: <1315383059-3673-55-git-send-email-yong.zhang0@gmail.com>
On 2011-09-07 at 10:10:51 +0200, Yong Zhang <yong.zhang0@gmail.com> wrote:
> This flag is a NOOP and can be removed now.
>
> Signed-off-by: Yong Zhang <yong.zhang0@gmail.com>
For altera_jtaguart and altera_uart:
Acked-by: Tobias Klauser <tklauser@distanz.ch>
^ permalink raw reply
* Re: [PATCH] eSDHC: Access Freescale eSDHC registers by 32-bit
From: Anton Vorontsov @ 2011-09-09 14:07 UTC (permalink / raw)
To: Roy Zang; +Cc: linuxppc-dev, akpm, linux-mmc, Xu lei
In-Reply-To: <1315569946-21386-1-git-send-email-tie-fei.zang@freescale.com>
On Fri, Sep 09, 2011 at 08:05:46PM +0800, Roy Zang wrote:
> From: Xu lei <B33228@freescale.com>
>
> Freescale eSDHC registers only support 32-bit accesses,
> this patch ensures that all Freescale eSDHC register accesses
> are 32-bit.
>
> Signed-off-by: Xu lei <B33228@freescale.com>
> Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> ---
The patch looks OK.
Acked-by: Anton Vorontsov <cbouatmailru@gmail.com>
[...]
> +static u8 esdhc_readb(struct sdhci_host *host, int reg)
> +{
> + int base = reg & ~0x3;
> + int shift = (reg & 0x3) * 8;
> + u8 ret = (in_be32(host->ioaddr + base) >> shift) & 0xff;
> return ret;
> }
Though, I wonder if we could change sdhci_be32bs_read{b,w}, instead
of making this local to eSDHC.
The thing is: sdhci_be32bs_writeb() is using clrsetbits_be32,
so the write variant already uses 32-bit accessors, so nothing should
break if we switch sdhci_be32bs_readb() to in_be32().
But maybe it's safer if we do this in a separate patch, so that it
could be easily reverted without impacting eSDHC if something actually
breaks.
You decide. :-)
Thanks!
--
Anton Vorontsov
Email: cbouatmailru@gmail.com
^ permalink raw reply
* Re: [PATCH] eSDHC: Access Freescale eSDHC registers by 32-bit
From: Wolfram Sang @ 2011-09-09 13:08 UTC (permalink / raw)
To: Zang Roy-R61911
Cc: Xu Lei-B33228, linux-mmc@vger.kernel.org,
akpm@linux-foundation.org, cjb@laptop.org,
linuxppc-dev@lists.ozlabs.org
In-Reply-To: <2239AC579C7D3646A720227A37E026811A2311@039-SN1MPN1-005.039d.mgd.msft.net>
[-- Attachment #1: Type: text/plain, Size: 870 bytes --]
> Previously, I sent this patch together with another one. But
> technically they are separated patches. I got some comments from
> Anton about the patch. I will try to address the comment. but for this
> one, it is a stand along patch. I'd like to push it first.
Okay.
> I do not see any comment about byte swapping about this patch.
> you may have mis-understanding here.
I was misguided, yes, sorry. BE/LE issues with additional byteswapping
are a mind twister :/ Having a second look, it looks okay to me. One
could think about putting this into sdhci_platform as well, but this can
be done later if needed. Sadly, I currently don't have hardware to test
it.
Regards,
Wolfram
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply
* RE: [PATCH] eSDHC: Access Freescale eSDHC registers by 32-bit
From: Zang Roy-R61911 @ 2011-09-09 12:48 UTC (permalink / raw)
To: Wolfram Sang
Cc: Xu Lei-B33228, linux-mmc@vger.kernel.org,
akpm@linux-foundation.org, cjb@laptop.org,
linuxppc-dev@lists.ozlabs.org
In-Reply-To: <20110909123324.GQ1912@pengutronix.de>
> -----Original Message-----
> From: Wolfram Sang [mailto:w.sang@pengutronix.de]
> Sent: Friday, September 09, 2011 20:33 PM
> To: Zang Roy-R61911
> Cc: cjb@laptop.org; linux-mmc@vger.kernel.org; linuxppc-dev@lists.ozlabs.=
org;
> akpm@linux-foundation.org; cbouatmailru@gmail.com; Xu Lei-B33228; Kumar G=
ala
> Subject: Re: [PATCH] eSDHC: Access Freescale eSDHC registers by 32-bit
>=20
> On Fri, Sep 09, 2011 at 12:23:05PM +0000, Zang Roy-R61911 wrote:
>=20
> > > > Freescale eSDHC registers only support 32-bit accesses,
> > > > this patch ensures that all Freescale eSDHC register accesses
> > > > are 32-bit.
> > >
> > > So, what about the byte-swapping that Anton needed? You are simply
> > > removing that if I am not mistaken.
> > I do not see any comment for this patch from Anton.
>=20
> Maybe he is busy?
Sounds fair.
>=20
> > You may miss the patch. Please confirm.
>=20
> I don't understand, what needs to be confirmed?
Confirm: there is no comment about this patch.=20
Previously, I sent this patch together with another one. But technically t=
hey are separated patches. I got some comments from Anton about the patch.=
I will try to address the comment. but for this one, it is a stand along p=
atch. I'd like to push it first.
> I am simply wondering
> what happens to the byteswapping that Anton (back then) intentionally
> implemented.
I do not see any comment about byte swapping about this patch.
you may have mis-understanding here.
Roy
^ permalink raw reply
* Re: [PATCH] eSDHC: Access Freescale eSDHC registers by 32-bit
From: Wolfram Sang @ 2011-09-09 12:33 UTC (permalink / raw)
To: Zang Roy-R61911
Cc: Xu Lei-B33228, linux-mmc@vger.kernel.org,
akpm@linux-foundation.org, cjb@laptop.org,
linuxppc-dev@lists.ozlabs.org
In-Reply-To: <2239AC579C7D3646A720227A37E026811A22BD@039-SN1MPN1-005.039d.mgd.msft.net>
[-- Attachment #1: Type: text/plain, Size: 802 bytes --]
On Fri, Sep 09, 2011 at 12:23:05PM +0000, Zang Roy-R61911 wrote:
> > > Freescale eSDHC registers only support 32-bit accesses,
> > > this patch ensures that all Freescale eSDHC register accesses
> > > are 32-bit.
> >
> > So, what about the byte-swapping that Anton needed? You are simply
> > removing that if I am not mistaken.
> I do not see any comment for this patch from Anton.
Maybe he is busy?
> You may miss the patch. Please confirm.
I don't understand, what needs to be confirmed? I am simply wondering
what happens to the byteswapping that Anton (back then) intentionally
implemented.
Regards,
Wolfram
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply
* RE: [PATCH] eSDHC: Access Freescale eSDHC registers by 32-bit
From: Zang Roy-R61911 @ 2011-09-09 12:23 UTC (permalink / raw)
To: Wolfram Sang, cjb@laptop.org
Cc: Xu Lei-B33228, linux-mmc@vger.kernel.org,
akpm@linux-foundation.org, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <20110909114004.GP1912@pengutronix.de>
> -----Original Message-----
> From: Wolfram Sang [mailto:w.sang@pengutronix.de]
> Sent: Friday, September 09, 2011 19:40 PM
> To: Zang Roy-R61911
> Cc: linux-mmc@vger.kernel.org; linuxppc-dev@lists.ozlabs.org; akpm@linux-
> foundation.org; cbouatmailru@gmail.com; Xu Lei-B33228; Kumar Gala
> Subject: Re: [PATCH] eSDHC: Access Freescale eSDHC registers by 32-bit
>=20
> Hi,
>=20
> On Fri, Sep 09, 2011 at 08:05:46PM +0800, Roy Zang wrote:
> > From: Xu lei <B33228@freescale.com>
> >
> > Freescale eSDHC registers only support 32-bit accesses,
> > this patch ensures that all Freescale eSDHC register accesses
> > are 32-bit.
>=20
> So, what about the byte-swapping that Anton needed? You are simply
> removing that if I am not mistaken.
I do not see any comment for this patch from Anton. You may miss the patch.=
Please confirm.
I add Chris in the loop.
Thanks.
Roy
^ permalink raw reply
* RE: [PATCH] eSDHC: Access Freescale eSDHC registers by 32-bit
From: Zang Roy-R61911 @ 2011-09-09 12:16 UTC (permalink / raw)
To: Wolfram Sang, cjb@laptop.org
Cc: Xu Lei-B33228, linux-mmc@vger.kernel.org,
akpm@linux-foundation.org, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <20110909114004.GP1912@pengutronix.de>
> -----Original Message-----
> From: Wolfram Sang [mailto:w.sang@pengutronix.de]
> Sent: Friday, September 09, 2011 19:40 PM
> To: Zang Roy-R61911
> Cc: linux-mmc@vger.kernel.org; linuxppc-dev@lists.ozlabs.org; akpm@linux-
> foundation.org; cbouatmailru@gmail.com; Xu Lei-B33228; Kumar Gala
> Subject: Re: [PATCH] eSDHC: Access Freescale eSDHC registers by 32-bit
>=20
> Hi,
>=20
> On Fri, Sep 09, 2011 at 08:05:46PM +0800, Roy Zang wrote:
> > From: Xu lei <B33228@freescale.com>
> >
> > Freescale eSDHC registers only support 32-bit accesses,
> > this patch ensures that all Freescale eSDHC register accesses
> > are 32-bit.
>=20
> So, what about the byte-swapping that Anton needed? You are simply
> removing that if I am not mistaken.
>=20
> > Signed-off-by: Xu lei <B33228@freescale.com>
> > Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
> > Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> > ---
> > This is a patch resend
> > http://patchwork.ozlabs.org/patch/106245/
> > based on latest Linus tree.
> >
> > Andrew,
> > Could you help to pick up this patch first?
>=20
> mmc-list is not dead, it must go via Chris, I'd think.
This is the third time that I re-send this patch to the list. There is no =
comment.
That is why I ask Andrew's help.
>=20
> > drivers/mmc/host/sdhci-of-esdhc.c | 18 ++++++++++++++----
> > 1 files changed, 14 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci=
-of-
> esdhc.c
> > index fe604df..40036f6 100644
> > --- a/drivers/mmc/host/sdhci-of-esdhc.c
> > +++ b/drivers/mmc/host/sdhci-of-esdhc.c
> > @@ -1,7 +1,7 @@
> > /*
> > * Freescale eSDHC controller driver.
> > *
> > - * Copyright (c) 2007 Freescale Semiconductor, Inc.
> > + * Copyright (c) 2007, 2010 Freescale Semiconductor, Inc.
>=20
> I wonder if such a small change has impact on the copyright.
I just update the year for tracking. Anything wrong?
Roy
^ permalink raw reply
* [PATCH] powerpc: Optimize __arch_swab32 and __arch_swab16
From: Joakim Tjernlund @ 2011-09-09 12:10 UTC (permalink / raw)
To: linuxppc-dev
PPC __arch_swab32 and __arch_swab16 generates non optimal code.
They do not schedule very well, need to copy its input register
and swab16 needs an extra insn to clear its upper bits.
Fix this with better inline ASM.
Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
---
arch/powerpc/include/asm/swab.h | 28 ++++++++++++++--------------
1 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/arch/powerpc/include/asm/swab.h b/arch/powerpc/include/asm/swab.h
index c581e3e..3b9a200 100644
--- a/arch/powerpc/include/asm/swab.h
+++ b/arch/powerpc/include/asm/swab.h
@@ -61,25 +61,25 @@ static inline void __arch_swab32s(__u32 *addr)
static inline __attribute_const__ __u16 __arch_swab16(__u16 value)
{
- __u16 result;
-
- __asm__("rlwimi %0,%1,8,16,23"
- : "=r" (result)
- : "r" (value), "0" (value >> 8));
- return result;
+ __asm__("rlwimi %0,%0,16,0x00ff0000\n\t"
+ "rlwinm %0,%0,24,0x0000ffff"
+ : "+r"(value));
+ return value;
}
#define __arch_swab16 __arch_swab16
static inline __attribute_const__ __u32 __arch_swab32(__u32 value)
{
- __u32 result;
-
- __asm__("rlwimi %0,%1,24,16,23\n\t"
- "rlwimi %0,%1,8,8,15\n\t"
- "rlwimi %0,%1,24,0,7"
- : "=r" (result)
- : "r" (value), "0" (value >> 24));
- return result;
+ __u32 tmp;
+
+ __asm__("rlwimi %0,%1,24,0xffffffff"
+ : "=r" (value) : "r" (value));
+ tmp = value;
+ __asm__("rlwimi %0,%1,16,0x00ff0000"
+ : "+r" (value) : "r" (tmp));
+ __asm__("rlwimi %0,%1,16,0x000000ff"
+ : "+r" (value) : "r" (tmp));
+ return value;
}
#define __arch_swab32 __arch_swab32
--
1.7.3.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox