Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/scottwood/linux...
authorMichael Ellerman <mpe@ellerman.id.au>
Tue, 7 Apr 2015 03:07:42 +0000 (13:07 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Tue, 7 Apr 2015 03:07:42 +0000 (13:07 +1000)
Freescale updates from Scott:

"Highlights include BMan device tree nodes, an MSI erratum workaround, a
couple minor performance improvements, config updates, and misc
fixes/cleanup."

59 files changed:
Documentation/ABI/testing/sysfs-class-cxl
arch/powerpc/Makefile
arch/powerpc/include/asm/Kbuild
arch/powerpc/include/asm/cache.h
arch/powerpc/include/asm/dcr-native.h
arch/powerpc/include/asm/div64.h [deleted file]
arch/powerpc/include/asm/dma-mapping.h
arch/powerpc/include/asm/irq_regs.h [deleted file]
arch/powerpc/include/asm/kvm_book3s_64.h
arch/powerpc/include/asm/local64.h [deleted file]
arch/powerpc/include/asm/nvram.h
arch/powerpc/include/asm/opal.h
arch/powerpc/include/asm/rtas.h
arch/powerpc/include/asm/systbl.h
arch/powerpc/include/asm/unistd.h
arch/powerpc/include/uapi/asm/unistd.h
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/idle_power7.S
arch/powerpc/kernel/nvram_64.c
arch/powerpc/kernel/rtas.c
arch/powerpc/kernel/syscalls.c
arch/powerpc/kernel/systbl.S
arch/powerpc/kernel/systbl_chk.c
arch/powerpc/lib/copy_32.S
arch/powerpc/lib/locks.c
arch/powerpc/lib/ppc_ksyms.c
arch/powerpc/mm/init_64.c
arch/powerpc/mm/numa.c
arch/powerpc/mm/pgtable_32.c
arch/powerpc/mm/ppc_mmu_32.c
arch/powerpc/perf/core-book3s.c
arch/powerpc/platforms/Kconfig.cputype
arch/powerpc/platforms/cell/spu_callbacks.c
arch/powerpc/platforms/chrp/setup.c
arch/powerpc/platforms/powermac/bootx_init.c
arch/powerpc/platforms/powermac/pic.c
arch/powerpc/platforms/powernv/opal-flash.c
arch/powerpc/platforms/powernv/opal-nvram.c
arch/powerpc/platforms/powernv/opal-sensor.c
arch/powerpc/platforms/powernv/opal.c
arch/powerpc/platforms/powernv/setup.c
arch/powerpc/platforms/pseries/Kconfig
arch/powerpc/platforms/pseries/mobility.c
arch/powerpc/platforms/pseries/nvram.c
arch/powerpc/relocs_check.pl [deleted file]
arch/powerpc/relocs_check.sh [new file with mode: 0755]
arch/powerpc/sysdev/dcr.c
drivers/macintosh/smu.c
drivers/macintosh/via-pmu.c
drivers/net/ethernet/ibm/emac/core.c
drivers/ps3/ps3-lpm.c
fs/pstore/inode.c
include/linux/pstore.h
tools/testing/selftests/powerpc/Makefile
tools/testing/selftests/powerpc/switch_endian/.gitignore [new file with mode: 0644]
tools/testing/selftests/powerpc/switch_endian/Makefile [new file with mode: 0644]
tools/testing/selftests/powerpc/switch_endian/check.S [new file with mode: 0644]
tools/testing/selftests/powerpc/switch_endian/common.h [new file with mode: 0644]
tools/testing/selftests/powerpc/switch_endian/switch_endian_test.S [new file with mode: 0644]

index 3680364b404885cf509f6d2b1261f342873f4244..d46bba801aace45ed29ea559a7a1c9c1fe764fd5 100644 (file)
@@ -100,7 +100,7 @@ Description:    read only
                Hexadecimal value of the device ID found in this AFU
                configuration record.
 
-What:           /sys/class/cxl/<afu>/cr<config num>/vendor
+What:           /sys/class/cxl/<afu>/cr<config num>/class
 Date:           February 2015
 Contact:        linuxppc-dev@lists.ozlabs.org
 Description:    read only
index fc502e042438c237c3c32cfd3fbfd13eb1d057c9..07a480861f785295f51a28879c9ecfa9dad6955f 100644 (file)
@@ -248,10 +248,10 @@ boot := arch/$(ARCH)/boot
 
 ifeq ($(CONFIG_RELOCATABLE),y)
 quiet_cmd_relocs_check = CALL    $<
-      cmd_relocs_check = perl $< "$(OBJDUMP)" "$(obj)/vmlinux"
+      cmd_relocs_check = $(CONFIG_SHELL) $< "$(OBJDUMP)" "$(obj)/vmlinux"
 
 PHONY += relocs_check
-relocs_check: arch/powerpc/relocs_check.pl vmlinux
+relocs_check: arch/powerpc/relocs_check.sh vmlinux
        $(call cmd,relocs_check)
 
 zImage: relocs_check
index 382b28e364dcdd5130c70737a5afa4c609785bd4..4b87205c230ca62f51033094f7014e5a35ca7e2e 100644 (file)
@@ -1,6 +1,8 @@
-
 generic-y += clkdev.h
+generic-y += div64.h
+generic-y += irq_regs.h
 generic-y += irq_work.h
+generic-y += local64.h
 generic-y += mcs_spinlock.h
 generic-y += preempt.h
 generic-y += rwsem.h
index 34a05a1a990bb1337e36a1161d805dcc63efaef3..0dc42c5082b74a1d4fee5709e21100ee0ec8a2df 100644 (file)
@@ -76,9 +76,6 @@ extern void _set_L3CR(unsigned long);
 #define _set_L3CR(val) do { } while(0)
 #endif
 
-extern void cacheable_memzero(void *p, unsigned int nb);
-extern void *cacheable_memcpy(void *, const void *, unsigned int);
-
 #endif /* !__ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_CACHE_H */
index 7d2e6235726d14a94190436891ca157c2457d0c1..4efc11dacb9805013944790c6767d9c1d27c5616 100644 (file)
@@ -31,7 +31,7 @@ typedef struct {
 
 static inline bool dcr_map_ok_native(dcr_host_native_t host)
 {
-       return 1;
+       return true;
 }
 
 #define dcr_map_native(dev, dcr_n, dcr_c) \
diff --git a/arch/powerpc/include/asm/div64.h b/arch/powerpc/include/asm/div64.h
deleted file mode 100644 (file)
index 6cd978c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/div64.h>
index 894d538f356783336f6addf6468ab941cafd0d02..9103687b0436360e99a7977392ce55c83ccc851c 100644 (file)
@@ -191,11 +191,11 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
        struct dev_archdata *sd = &dev->archdata;
 
        if (sd->max_direct_dma_addr && addr + size > sd->max_direct_dma_addr)
-               return 0;
+               return false;
 #endif
 
        if (!dev->dma_mask)
-               return 0;
+               return false;
 
        return addr + size - 1 <= *dev->dma_mask;
 }
diff --git a/arch/powerpc/include/asm/irq_regs.h b/arch/powerpc/include/asm/irq_regs.h
deleted file mode 100644 (file)
index ba94b51..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#include <asm-generic/irq_regs.h>
-
index 2d81e202bdccb7e2d06b128e727da0fc84c4f125..2a244bf869c01a21ea9e19c3d150a6de7e20faa9 100644 (file)
@@ -335,7 +335,7 @@ static inline bool hpte_read_permission(unsigned long pp, unsigned long key)
 {
        if (key)
                return PP_RWRX <= pp && pp <= PP_RXRX;
-       return 1;
+       return true;
 }
 
 static inline bool hpte_write_permission(unsigned long pp, unsigned long key)
@@ -373,7 +373,7 @@ static inline bool slot_is_aligned(struct kvm_memory_slot *memslot,
        unsigned long mask = (pagesize >> PAGE_SHIFT) - 1;
 
        if (pagesize <= PAGE_SIZE)
-               return 1;
+               return true;
        return !(memslot->base_gfn & mask) && !(memslot->npages & mask);
 }
 
diff --git a/arch/powerpc/include/asm/local64.h b/arch/powerpc/include/asm/local64.h
deleted file mode 100644 (file)
index 36c93b5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/local64.h>
index b0fe0fe4e626f4c0f31f592e915094b8d75905fb..09a518bb7c03c681a776e708f78642446b4ecbb4 100644 (file)
@@ -9,12 +9,43 @@
 #ifndef _ASM_POWERPC_NVRAM_H
 #define _ASM_POWERPC_NVRAM_H
 
-
+#include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/list.h>
 #include <uapi/asm/nvram.h>
 
+/*
+ * Set oops header version to distinguish between old and new format header.
+ * lnx,oops-log partition max size is 4000, header version > 4000 will
+ * help in identifying new header.
+ */
+#define OOPS_HDR_VERSION 5000
+
+struct err_log_info {
+       __be32 error_type;
+       __be32 seq_num;
+};
+
+struct nvram_os_partition {
+       const char *name;
+       int req_size;   /* desired size, in bytes */
+       int min_size;   /* minimum acceptable size (0 means req_size) */
+       long size;      /* size of data portion (excluding err_log_info) */
+       long index;     /* offset of data portion of partition */
+       bool os_partition; /* partition initialized by OS, not FW */
+};
+
+struct oops_log_info {
+       __be16 version;
+       __be16 report_length;
+       __be64 timestamp;
+} __attribute__((packed));
+
+extern struct nvram_os_partition oops_log_partition;
+
 #ifdef CONFIG_PPC_PSERIES
+extern struct nvram_os_partition rtas_log_partition;
+
 extern int nvram_write_error_log(char * buff, int length,
                                         unsigned int err_type, unsigned int err_seq);
 extern int nvram_read_error_log(char * buff, int length,
@@ -50,6 +81,23 @@ extern void  pmac_xpram_write(int xpaddr, u8 data);
 /* Synchronize NVRAM */
 extern void    nvram_sync(void);
 
+/* Initialize NVRAM OS partition */
+extern int __init nvram_init_os_partition(struct nvram_os_partition *part);
+
+/* Initialize NVRAM oops partition */
+extern void __init nvram_init_oops_partition(int rtas_partition_exists);
+
+/* Read a NVRAM partition */
+extern int nvram_read_partition(struct nvram_os_partition *part, char *buff,
+                               int length, unsigned int *err_type,
+                               unsigned int *error_log_cnt);
+
+/* Write to NVRAM OS partition */
+extern int nvram_write_os_partition(struct nvram_os_partition *part,
+                                   char *buff, int length,
+                                   unsigned int err_type,
+                                   unsigned int error_log_cnt);
+
 /* Determine NVRAM size */
 extern ssize_t nvram_get_size(void);
 
index 0ef0fd660ac63a30d2887ea2169230722e8b9c99..fde90bacc65ef09b27975dacb2554242ddf97177 100644 (file)
@@ -210,6 +210,8 @@ extern int opal_notifier_unregister(struct notifier_block *nb);
 
 extern int opal_message_notifier_register(enum opal_msg_type msg_type,
                                                struct notifier_block *nb);
+extern int opal_message_notifier_unregister(enum opal_msg_type msg_type,
+                                           struct notifier_block *nb);
 extern void opal_notifier_enable(void);
 extern void opal_notifier_disable(void);
 extern void opal_notifier_update_evt(uint64_t evt_mask, uint64_t evt_val);
@@ -245,6 +247,8 @@ struct opal_sg_list *opal_vmalloc_to_sg_list(void *vmalloc_addr,
                                             unsigned long vmalloc_size);
 void opal_free_sg_list(struct opal_sg_list *sg);
 
+extern int opal_error_code(int rc);
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_POWERPC_OPAL_H */
index 2e23e92a43722fcb0d0e3097b65025631f78dd51..398106f126179aaa1a30be6b7ee51afcfa04b495 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <linux/spinlock.h>
 #include <asm/page.h>
+#include <linux/time.h>
 
 /*
  * Definitions for talking to the RTAS on CHRP machines.
@@ -327,7 +328,7 @@ extern int rtas_suspend_cpu(struct rtas_suspend_me_data *data);
 extern int rtas_suspend_last_cpu(struct rtas_suspend_me_data *data);
 extern int rtas_online_cpus_mask(cpumask_var_t cpus);
 extern int rtas_offline_cpus_mask(cpumask_var_t cpus);
-extern int rtas_ibm_suspend_me(u64 handle, int *vasi_return);
+extern int rtas_ibm_suspend_me(u64 handle);
 
 struct rtc_time;
 extern unsigned long rtas_get_boot_time(void);
@@ -343,8 +344,12 @@ extern int early_init_dt_scan_rtas(unsigned long node,
 extern void pSeries_log_error(char *buf, unsigned int err_type, int fatal);
 
 #ifdef CONFIG_PPC_PSERIES
+extern time64_t last_rtas_event;
+extern int clobbering_unread_rtas_event(void);
 extern int pseries_devicetree_update(s32 scope);
 extern void post_mobility_fixup(void);
+#else
+static inline int clobbering_unread_rtas_event(void) { return 0; }
 #endif
 
 #ifdef CONFIG_PPC_RTAS_DAEMON
index 91062eef582f9c1ed8d824f9e16bcde8a0f8714c..f1863a138b4a496d726bbfe791b2c4f034ea5973 100644 (file)
@@ -367,3 +367,4 @@ SYSCALL_SPU(getrandom)
 SYSCALL_SPU(memfd_create)
 SYSCALL_SPU(bpf)
 COMPAT_SYS(execveat)
+PPC64ONLY(switch_endian)
index 36b79c31eedda5cb090e73cafc6a64c937fcc5f7..f4f8b667d75be5614bd8f706b5573e21cdd9a685 100644 (file)
@@ -12,7 +12,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define __NR_syscalls          363
+#define __NR_syscalls          364
 
 #define __NR__exit __NR_exit
 #define NR_syscalls    __NR_syscalls
index ef5b5b1f31231648135ed092af027933c8dc3f06..e4aa173dae62361e3823f3eda242b2802cdd5da1 100644 (file)
 #define __NR_memfd_create      360
 #define __NR_bpf               361
 #define __NR_execveat          362
+#define __NR_switch_endian     363
 
 #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */
index d180caf2d6de749ecab74fe51bb60146ab044b69..afbc20019c2efba2b81b7cd6298941753d9776b5 100644 (file)
@@ -356,6 +356,11 @@ _GLOBAL(ppc64_swapcontext)
        bl      sys_swapcontext
        b       .Lsyscall_exit
 
+_GLOBAL(ppc_switch_endian)
+       bl      save_nvgprs
+       bl      sys_switch_endian
+       b       .Lsyscall_exit
+
 _GLOBAL(ret_from_fork)
        bl      schedule_tail
        REST_NVGPRS(r1)
index 05adc8bbdef853b4c7adb27c5da88ceada1ea033..eeaa0d5f69d5e60271ccca1790aaf98559ca92fa 100644 (file)
@@ -94,6 +94,7 @@ _GLOBAL(power7_powersave_common)
        beq     1f
        addi    r1,r1,INT_FRAME_SIZE
        ld      r0,16(r1)
+       li      r3,0                    /* Return 0 (no nap) */
        mtlr    r0
        blr
 
index 34f7c9b7cd96b78a7ddf338a61f2d20a5fd16611..1e703f8ebad4e35d8888eed535c71b492e8af87d 100644 (file)
@@ -26,6 +26,9 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/kmsg_dump.h>
+#include <linux/pstore.h>
+#include <linux/zlib.h>
 #include <asm/uaccess.h>
 #include <asm/nvram.h>
 #include <asm/rtas.h>
@@ -54,6 +57,680 @@ struct nvram_partition {
 
 static LIST_HEAD(nvram_partitions);
 
+#ifdef CONFIG_PPC_PSERIES
+struct nvram_os_partition rtas_log_partition = {
+       .name = "ibm,rtas-log",
+       .req_size = 2079,
+       .min_size = 1055,
+       .index = -1,
+       .os_partition = true
+};
+#endif
+
+struct nvram_os_partition oops_log_partition = {
+       .name = "lnx,oops-log",
+       .req_size = 4000,
+       .min_size = 2000,
+       .index = -1,
+       .os_partition = true
+};
+
+static const char *nvram_os_partitions[] = {
+#ifdef CONFIG_PPC_PSERIES
+       "ibm,rtas-log",
+#endif
+       "lnx,oops-log",
+       NULL
+};
+
+static void oops_to_nvram(struct kmsg_dumper *dumper,
+                         enum kmsg_dump_reason reason);
+
+static struct kmsg_dumper nvram_kmsg_dumper = {
+       .dump = oops_to_nvram
+};
+
+/*
+ * For capturing and compressing an oops or panic report...
+
+ * big_oops_buf[] holds the uncompressed text we're capturing.
+ *
+ * oops_buf[] holds the compressed text, preceded by a oops header.
+ * oops header has u16 holding the version of oops header (to differentiate
+ * between old and new format header) followed by u16 holding the length of
+ * the compressed* text (*Or uncompressed, if compression fails.) and u64
+ * holding the timestamp. oops_buf[] gets written to NVRAM.
+ *
+ * oops_log_info points to the header. oops_data points to the compressed text.
+ *
+ * +- oops_buf
+ * |                                   +- oops_data
+ * v                                   v
+ * +-----------+-----------+-----------+------------------------+
+ * | version   | length    | timestamp | text                   |
+ * | (2 bytes) | (2 bytes) | (8 bytes) | (oops_data_sz bytes)   |
+ * +-----------+-----------+-----------+------------------------+
+ * ^
+ * +- oops_log_info
+ *
+ * We preallocate these buffers during init to avoid kmalloc during oops/panic.
+ */
+static size_t big_oops_buf_sz;
+static char *big_oops_buf, *oops_buf;
+static char *oops_data;
+static size_t oops_data_sz;
+
+/* Compression parameters */
+#define COMPR_LEVEL 6
+#define WINDOW_BITS 12
+#define MEM_LEVEL 4
+static struct z_stream_s stream;
+
+#ifdef CONFIG_PSTORE
+#ifdef CONFIG_PPC_POWERNV
+static struct nvram_os_partition skiboot_partition = {
+       .name = "ibm,skiboot",
+       .index = -1,
+       .os_partition = false
+};
+#endif
+
+#ifdef CONFIG_PPC_PSERIES
+static struct nvram_os_partition of_config_partition = {
+       .name = "of-config",
+       .index = -1,
+       .os_partition = false
+};
+#endif
+
+static struct nvram_os_partition common_partition = {
+       .name = "common",
+       .index = -1,
+       .os_partition = false
+};
+
+static enum pstore_type_id nvram_type_ids[] = {
+       PSTORE_TYPE_DMESG,
+       PSTORE_TYPE_PPC_COMMON,
+       -1,
+       -1,
+       -1
+};
+static int read_type;
+#endif
+
+/* nvram_write_os_partition
+ *
+ * We need to buffer the error logs into nvram to ensure that we have
+ * the failure information to decode.  If we have a severe error there
+ * is no way to guarantee that the OS or the machine is in a state to
+ * get back to user land and write the error to disk.  For example if
+ * the SCSI device driver causes a Machine Check by writing to a bad
+ * IO address, there is no way of guaranteeing that the device driver
+ * is in any state that is would also be able to write the error data
+ * captured to disk, thus we buffer it in NVRAM for analysis on the
+ * next boot.
+ *
+ * In NVRAM the partition containing the error log buffer will looks like:
+ * Header (in bytes):
+ * +-----------+----------+--------+------------+------------------+
+ * | signature | checksum | length | name       | data             |
+ * |0          |1         |2      3|4         15|16        length-1|
+ * +-----------+----------+--------+------------+------------------+
+ *
+ * The 'data' section would look like (in bytes):
+ * +--------------+------------+-----------------------------------+
+ * | event_logged | sequence # | error log                         |
+ * |0            3|4          7|8                  error_log_size-1|
+ * +--------------+------------+-----------------------------------+
+ *
+ * event_logged: 0 if event has not been logged to syslog, 1 if it has
+ * sequence #: The unique sequence # for each event. (until it wraps)
+ * error log: The error log from event_scan
+ */
+int nvram_write_os_partition(struct nvram_os_partition *part,
+                            char *buff, int length,
+                            unsigned int err_type,
+                            unsigned int error_log_cnt)
+{
+       int rc;
+       loff_t tmp_index;
+       struct err_log_info info;
+
+       if (part->index == -1)
+               return -ESPIPE;
+
+       if (length > part->size)
+               length = part->size;
+
+       info.error_type = cpu_to_be32(err_type);
+       info.seq_num = cpu_to_be32(error_log_cnt);
+
+       tmp_index = part->index;
+
+       rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info),
+                               &tmp_index);
+       if (rc <= 0) {
+               pr_err("%s: Failed nvram_write (%d)\n", __func__, rc);
+               return rc;
+       }
+
+       rc = ppc_md.nvram_write(buff, length, &tmp_index);
+       if (rc <= 0) {
+               pr_err("%s: Failed nvram_write (%d)\n", __func__, rc);
+               return rc;
+       }
+
+       return 0;
+}
+
+/* nvram_read_partition
+ *
+ * Reads nvram partition for at most 'length'
+ */
+int nvram_read_partition(struct nvram_os_partition *part, char *buff,
+                        int length, unsigned int *err_type,
+                        unsigned int *error_log_cnt)
+{
+       int rc;
+       loff_t tmp_index;
+       struct err_log_info info;
+
+       if (part->index == -1)
+               return -1;
+
+       if (length > part->size)
+               length = part->size;
+
+       tmp_index = part->index;
+
+       if (part->os_partition) {
+               rc = ppc_md.nvram_read((char *)&info,
+                                       sizeof(struct err_log_info),
+                                       &tmp_index);
+               if (rc <= 0) {
+                       pr_err("%s: Failed nvram_read (%d)\n", __func__, rc);
+                       return rc;
+               }
+       }
+
+       rc = ppc_md.nvram_read(buff, length, &tmp_index);
+       if (rc <= 0) {
+               pr_err("%s: Failed nvram_read (%d)\n", __func__, rc);
+               return rc;
+       }
+
+       if (part->os_partition) {
+               *error_log_cnt = be32_to_cpu(info.seq_num);
+               *err_type = be32_to_cpu(info.error_type);
+       }
+
+       return 0;
+}
+
+/* nvram_init_os_partition
+ *
+ * This sets up a partition with an "OS" signature.
+ *
+ * The general strategy is the following:
+ * 1.) If a partition with the indicated name already exists...
+ *     - If it's large enough, use it.
+ *     - Otherwise, recycle it and keep going.
+ * 2.) Search for a free partition that is large enough.
+ * 3.) If there's not a free partition large enough, recycle any obsolete
+ * OS partitions and try again.
+ * 4.) Will first try getting a chunk that will satisfy the requested size.
+ * 5.) If a chunk of the requested size cannot be allocated, then try finding
+ * a chunk that will satisfy the minum needed.
+ *
+ * Returns 0 on success, else -1.
+ */
+int __init nvram_init_os_partition(struct nvram_os_partition *part)
+{
+       loff_t p;
+       int size;
+
+       /* Look for ours */
+       p = nvram_find_partition(part->name, NVRAM_SIG_OS, &size);
+
+       /* Found one but too small, remove it */
+       if (p && size < part->min_size) {
+               pr_info("nvram: Found too small %s partition,"
+                                       " removing it...\n", part->name);
+               nvram_remove_partition(part->name, NVRAM_SIG_OS, NULL);
+               p = 0;
+       }
+
+       /* Create one if we didn't find */
+       if (!p) {
+               p = nvram_create_partition(part->name, NVRAM_SIG_OS,
+                                       part->req_size, part->min_size);
+               if (p == -ENOSPC) {
+                       pr_info("nvram: No room to create %s partition, "
+                               "deleting any obsolete OS partitions...\n",
+                               part->name);
+                       nvram_remove_partition(NULL, NVRAM_SIG_OS,
+                                       nvram_os_partitions);
+                       p = nvram_create_partition(part->name, NVRAM_SIG_OS,
+                                       part->req_size, part->min_size);
+               }
+       }
+
+       if (p <= 0) {
+               pr_err("nvram: Failed to find or create %s"
+                      " partition, err %d\n", part->name, (int)p);
+               return -1;
+       }
+
+       part->index = p;
+       part->size = nvram_get_partition_size(p) - sizeof(struct err_log_info);
+
+       return 0;
+}
+
+/* Derived from logfs_compress() */
+static int nvram_compress(const void *in, void *out, size_t inlen,
+                                                       size_t outlen)
+{
+       int err, ret;
+
+       ret = -EIO;
+       err = zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS,
+                                               MEM_LEVEL, Z_DEFAULT_STRATEGY);
+       if (err != Z_OK)
+               goto error;
+
+       stream.next_in = in;
+       stream.avail_in = inlen;
+       stream.total_in = 0;
+       stream.next_out = out;
+       stream.avail_out = outlen;
+       stream.total_out = 0;
+
+       err = zlib_deflate(&stream, Z_FINISH);
+       if (err != Z_STREAM_END)
+               goto error;
+
+       err = zlib_deflateEnd(&stream);
+       if (err != Z_OK)
+               goto error;
+
+       if (stream.total_out >= stream.total_in)
+               goto error;
+
+       ret = stream.total_out;
+error:
+       return ret;
+}
+
+/* Compress the text from big_oops_buf into oops_buf. */
+static int zip_oops(size_t text_len)
+{
+       struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
+       int zipped_len = nvram_compress(big_oops_buf, oops_data, text_len,
+                                                               oops_data_sz);
+       if (zipped_len < 0) {
+               pr_err("nvram: compression failed; returned %d\n", zipped_len);
+               pr_err("nvram: logging uncompressed oops/panic report\n");
+               return -1;
+       }
+       oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
+       oops_hdr->report_length = cpu_to_be16(zipped_len);
+       oops_hdr->timestamp = cpu_to_be64(ktime_get_real_seconds());
+       return 0;
+}
+
+#ifdef CONFIG_PSTORE
+static int nvram_pstore_open(struct pstore_info *psi)
+{
+       /* Reset the iterator to start reading partitions again */
+       read_type = -1;
+       return 0;
+}
+
+/**
+ * nvram_pstore_write - pstore write callback for nvram
+ * @type:               Type of message logged
+ * @reason:             reason behind dump (oops/panic)
+ * @id:                 identifier to indicate the write performed
+ * @part:               pstore writes data to registered buffer in parts,
+ *                      part number will indicate the same.
+ * @count:              Indicates oops count
+ * @compressed:         Flag to indicate the log is compressed
+ * @size:               number of bytes written to the registered buffer
+ * @psi:                registered pstore_info structure
+ *
+ * Called by pstore_dump() when an oops or panic report is logged in the
+ * printk buffer.
+ * Returns 0 on successful write.
+ */
+static int nvram_pstore_write(enum pstore_type_id type,
+                               enum kmsg_dump_reason reason,
+                               u64 *id, unsigned int part, int count,
+                               bool compressed, size_t size,
+                               struct pstore_info *psi)
+{
+       int rc;
+       unsigned int err_type = ERR_TYPE_KERNEL_PANIC;
+       struct oops_log_info *oops_hdr = (struct oops_log_info *) oops_buf;
+
+       /* part 1 has the recent messages from printk buffer */
+       if (part > 1 || (type != PSTORE_TYPE_DMESG))
+               return -1;
+
+       if (clobbering_unread_rtas_event())
+               return -1;
+
+       oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
+       oops_hdr->report_length = cpu_to_be16(size);
+       oops_hdr->timestamp = cpu_to_be64(ktime_get_real_seconds());
+
+       if (compressed)
+               err_type = ERR_TYPE_KERNEL_PANIC_GZ;
+
+       rc = nvram_write_os_partition(&oops_log_partition, oops_buf,
+               (int) (sizeof(*oops_hdr) + size), err_type, count);
+
+       if (rc != 0)
+               return rc;
+
+       *id = part;
+       return 0;
+}
+
+/*
+ * Reads the oops/panic report, rtas, of-config and common partition.
+ * Returns the length of the data we read from each partition.
+ * Returns 0 if we've been called before.
+ */
+static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type,
+                               int *count, struct timespec *time, char **buf,
+                               bool *compressed, struct pstore_info *psi)
+{
+       struct oops_log_info *oops_hdr;
+       unsigned int err_type, id_no, size = 0;
+       struct nvram_os_partition *part = NULL;
+       char *buff = NULL;
+       int sig = 0;
+       loff_t p;
+
+       read_type++;
+
+       switch (nvram_type_ids[read_type]) {
+       case PSTORE_TYPE_DMESG:
+               part = &oops_log_partition;
+               *type = PSTORE_TYPE_DMESG;
+               break;
+       case PSTORE_TYPE_PPC_COMMON:
+               sig = NVRAM_SIG_SYS;
+               part = &common_partition;
+               *type = PSTORE_TYPE_PPC_COMMON;
+               *id = PSTORE_TYPE_PPC_COMMON;
+               time->tv_sec = 0;
+               time->tv_nsec = 0;
+               break;
+#ifdef CONFIG_PPC_PSERIES
+       case PSTORE_TYPE_PPC_RTAS:
+               part = &rtas_log_partition;
+               *type = PSTORE_TYPE_PPC_RTAS;
+               time->tv_sec = last_rtas_event;
+               time->tv_nsec = 0;
+               break;
+       case PSTORE_TYPE_PPC_OF:
+               sig = NVRAM_SIG_OF;
+               part = &of_config_partition;
+               *type = PSTORE_TYPE_PPC_OF;
+               *id = PSTORE_TYPE_PPC_OF;
+               time->tv_sec = 0;
+               time->tv_nsec = 0;
+               break;
+#endif
+#ifdef CONFIG_PPC_POWERNV
+       case PSTORE_TYPE_PPC_OPAL:
+               sig = NVRAM_SIG_FW;
+               part = &skiboot_partition;
+               *type = PSTORE_TYPE_PPC_OPAL;
+               *id = PSTORE_TYPE_PPC_OPAL;
+               time->tv_sec = 0;
+               time->tv_nsec = 0;
+               break;
+#endif
+       default:
+               return 0;
+       }
+
+       if (!part->os_partition) {
+               p = nvram_find_partition(part->name, sig, &size);
+               if (p <= 0) {
+                       pr_err("nvram: Failed to find partition %s, "
+                               "err %d\n", part->name, (int)p);
+                       return 0;
+               }
+               part->index = p;
+               part->size = size;
+       }
+
+       buff = kmalloc(part->size, GFP_KERNEL);
+
+       if (!buff)
+               return -ENOMEM;
+
+       if (nvram_read_partition(part, buff, part->size, &err_type, &id_no)) {
+               kfree(buff);
+               return 0;
+       }
+
+       *count = 0;
+
+       if (part->os_partition)
+               *id = id_no;
+
+       if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) {
+               size_t length, hdr_size;
+
+               oops_hdr = (struct oops_log_info *)buff;
+               if (be16_to_cpu(oops_hdr->version) < OOPS_HDR_VERSION) {
+                       /* Old format oops header had 2-byte record size */
+                       hdr_size = sizeof(u16);
+                       length = be16_to_cpu(oops_hdr->version);
+                       time->tv_sec = 0;
+                       time->tv_nsec = 0;
+               } else {
+                       hdr_size = sizeof(*oops_hdr);
+                       length = be16_to_cpu(oops_hdr->report_length);
+                       time->tv_sec = be64_to_cpu(oops_hdr->timestamp);
+                       time->tv_nsec = 0;
+               }
+               *buf = kmalloc(length, GFP_KERNEL);
+               if (*buf == NULL)
+                       return -ENOMEM;
+               memcpy(*buf, buff + hdr_size, length);
+               kfree(buff);
+
+               if (err_type == ERR_TYPE_KERNEL_PANIC_GZ)
+                       *compressed = true;
+               else
+                       *compressed = false;
+               return length;
+       }
+
+       *buf = buff;
+       return part->size;
+}
+
+static struct pstore_info nvram_pstore_info = {
+       .owner = THIS_MODULE,
+       .name = "nvram",
+       .open = nvram_pstore_open,
+       .read = nvram_pstore_read,
+       .write = nvram_pstore_write,
+};
+
+static int nvram_pstore_init(void)
+{
+       int rc = 0;
+
+       if (machine_is(pseries)) {
+               nvram_type_ids[2] = PSTORE_TYPE_PPC_RTAS;
+               nvram_type_ids[3] = PSTORE_TYPE_PPC_OF;
+       } else
+               nvram_type_ids[2] = PSTORE_TYPE_PPC_OPAL;
+
+       nvram_pstore_info.buf = oops_data;
+       nvram_pstore_info.bufsize = oops_data_sz;
+
+       spin_lock_init(&nvram_pstore_info.buf_lock);
+
+       rc = pstore_register(&nvram_pstore_info);
+       if (rc != 0)
+               pr_err("nvram: pstore_register() failed, defaults to "
+                               "kmsg_dump; returned %d\n", rc);
+
+       return rc;
+}
+#else
+static int nvram_pstore_init(void)
+{
+       return -1;
+}
+#endif
+
+void __init nvram_init_oops_partition(int rtas_partition_exists)
+{
+       int rc;
+
+       rc = nvram_init_os_partition(&oops_log_partition);
+       if (rc != 0) {
+#ifdef CONFIG_PPC_PSERIES
+               if (!rtas_partition_exists) {
+                       pr_err("nvram: Failed to initialize oops partition!");
+                       return;
+               }
+               pr_notice("nvram: Using %s partition to log both"
+                       " RTAS errors and oops/panic reports\n",
+                       rtas_log_partition.name);
+               memcpy(&oops_log_partition, &rtas_log_partition,
+                                               sizeof(rtas_log_partition));
+#else
+               pr_err("nvram: Failed to initialize oops partition!");
+               return;
+#endif
+       }
+       oops_buf = kmalloc(oops_log_partition.size, GFP_KERNEL);
+       if (!oops_buf) {
+               pr_err("nvram: No memory for %s partition\n",
+                                               oops_log_partition.name);
+               return;
+       }
+       oops_data = oops_buf + sizeof(struct oops_log_info);
+       oops_data_sz = oops_log_partition.size - sizeof(struct oops_log_info);
+
+       rc = nvram_pstore_init();
+
+       if (!rc)
+               return;
+
+       /*
+        * Figure compression (preceded by elimination of each line's <n>
+        * severity prefix) will reduce the oops/panic report to at most
+        * 45% of its original size.
+        */
+       big_oops_buf_sz = (oops_data_sz * 100) / 45;
+       big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
+       if (big_oops_buf) {
+               stream.workspace =  kmalloc(zlib_deflate_workspacesize(
+                                       WINDOW_BITS, MEM_LEVEL), GFP_KERNEL);
+               if (!stream.workspace) {
+                       pr_err("nvram: No memory for compression workspace; "
+                               "skipping compression of %s partition data\n",
+                               oops_log_partition.name);
+                       kfree(big_oops_buf);
+                       big_oops_buf = NULL;
+               }
+       } else {
+               pr_err("No memory for uncompressed %s data; "
+                       "skipping compression\n", oops_log_partition.name);
+               stream.workspace = NULL;
+       }
+
+       rc = kmsg_dump_register(&nvram_kmsg_dumper);
+       if (rc != 0) {
+               pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc);
+               kfree(oops_buf);
+               kfree(big_oops_buf);
+               kfree(stream.workspace);
+       }
+}
+
+/*
+ * This is our kmsg_dump callback, called after an oops or panic report
+ * has been written to the printk buffer.  We want to capture as much
+ * of the printk buffer as possible.  First, capture as much as we can
+ * that we think will compress sufficiently to fit in the lnx,oops-log
+ * partition.  If that's too much, go back and capture uncompressed text.
+ */
+static void oops_to_nvram(struct kmsg_dumper *dumper,
+                         enum kmsg_dump_reason reason)
+{
+       struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
+       static unsigned int oops_count = 0;
+       static bool panicking = false;
+       static DEFINE_SPINLOCK(lock);
+       unsigned long flags;
+       size_t text_len;
+       unsigned int err_type = ERR_TYPE_KERNEL_PANIC_GZ;
+       int rc = -1;
+
+       switch (reason) {
+       case KMSG_DUMP_RESTART:
+       case KMSG_DUMP_HALT:
+       case KMSG_DUMP_POWEROFF:
+               /* These are almost always orderly shutdowns. */
+               return;
+       case KMSG_DUMP_OOPS:
+               break;
+       case KMSG_DUMP_PANIC:
+               panicking = true;
+               break;
+       case KMSG_DUMP_EMERG:
+               if (panicking)
+                       /* Panic report already captured. */
+                       return;
+               break;
+       default:
+               pr_err("%s: ignoring unrecognized KMSG_DUMP_* reason %d\n",
+                      __func__, (int) reason);
+               return;
+       }
+
+       if (clobbering_unread_rtas_event())
+               return;
+
+       if (!spin_trylock_irqsave(&lock, flags))
+               return;
+
+       if (big_oops_buf) {
+               kmsg_dump_get_buffer(dumper, false,
+                                    big_oops_buf, big_oops_buf_sz, &text_len);
+               rc = zip_oops(text_len);
+       }
+       if (rc != 0) {
+               kmsg_dump_rewind(dumper);
+               kmsg_dump_get_buffer(dumper, false,
+                                    oops_data, oops_data_sz, &text_len);
+               err_type = ERR_TYPE_KERNEL_PANIC;
+               oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
+               oops_hdr->report_length = cpu_to_be16(text_len);
+               oops_hdr->timestamp = cpu_to_be64(ktime_get_real_seconds());
+       }
+
+       (void) nvram_write_os_partition(&oops_log_partition, oops_buf,
+               (int) (sizeof(*oops_hdr) + text_len), err_type,
+               ++oops_count);
+
+       spin_unlock_irqrestore(&lock, flags);
+}
+
 static loff_t dev_nvram_llseek(struct file *file, loff_t offset, int origin)
 {
        int size;
index 21c45a2d07062d4e43f7dc28065b938207434944..b9a7b8981ef7ba604b06369d37313caf92fa4328 100644 (file)
@@ -897,7 +897,7 @@ int rtas_offline_cpus_mask(cpumask_var_t cpus)
 }
 EXPORT_SYMBOL(rtas_offline_cpus_mask);
 
-int rtas_ibm_suspend_me(u64 handle, int *vasi_return)
+int rtas_ibm_suspend_me(u64 handle)
 {
        long state;
        long rc;
@@ -919,13 +919,11 @@ int rtas_ibm_suspend_me(u64 handle, int *vasi_return)
                printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned %ld\n",rc);
                return rc;
        } else if (state == H_VASI_ENABLED) {
-               *vasi_return = RTAS_NOT_SUSPENDABLE;
-               return 0;
+               return -EAGAIN;
        } else if (state != H_VASI_SUSPENDING) {
                printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned state %ld\n",
                       state);
-               *vasi_return = -1;
-               return 0;
+               return -EIO;
        }
 
        if (!alloc_cpumask_var(&offline_mask, GFP_TEMPORARY))
@@ -972,7 +970,7 @@ out:
        return atomic_read(&data.error);
 }
 #else /* CONFIG_PPC_PSERIES */
-int rtas_ibm_suspend_me(u64 handle, int *vasi_return)
+int rtas_ibm_suspend_me(u64 handle)
 {
        return -ENOSYS;
 }
@@ -1022,7 +1020,6 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
        unsigned long flags;
        char *buff_copy, *errbuf = NULL;
        int nargs, nret, token;
-       int rc;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
@@ -1054,15 +1051,18 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
        if (token == ibm_suspend_me_token) {
 
                /*
-                * rtas_ibm_suspend_me assumes args are in cpu endian, or at least the
-                * hcall within it requires it.
+                * rtas_ibm_suspend_me assumes the streamid handle is in cpu
+                * endian, or at least the hcall within it requires it.
                 */
-               int vasi_rc = 0;
+               int rc = 0;
                u64 handle = ((u64)be32_to_cpu(args.args[0]) << 32)
                              | be32_to_cpu(args.args[1]);
-               rc = rtas_ibm_suspend_me(handle, &vasi_rc);
-               args.rets[0] = cpu_to_be32(vasi_rc);
-               if (rc)
+               rc = rtas_ibm_suspend_me(handle);
+               if (rc == -EAGAIN)
+                       args.rets[0] = cpu_to_be32(RTAS_NOT_SUSPENDABLE);
+               else if (rc == -EIO)
+                       args.rets[0] = cpu_to_be32(-1);
+               else if (rc)
                        return rc;
                goto copy_return;
        }
index b2702e87db0d44ae28de907ac5517d6ee23879fd..5fa92706444b7f6e874b9c7161c1127974c4aa04 100644 (file)
@@ -121,3 +121,20 @@ long ppc_fadvise64_64(int fd, int advice, u32 offset_high, u32 offset_low,
        return sys_fadvise64(fd, (u64)offset_high << 32 | offset_low,
                             (u64)len_high << 32 | len_low, advice);
 }
+
+long sys_switch_endian(void)
+{
+       struct thread_info *ti;
+
+       current->thread.regs->msr ^= MSR_LE;
+
+       /*
+        * Set TIF_RESTOREALL so that r3 isn't clobbered on return to
+        * userspace. That also has the effect of restoring the non-volatile
+        * GPRs, so we saved them on the way in here.
+        */
+       ti = current_thread_info();
+       ti->flags |= _TIF_RESTOREALL;
+
+       return 0;
+}
index 7ab5d434e2eed9f6e120bb72c537bab29112c1b0..4d6b1d3a747f63cd8b9f54aff9ec3ebb2da11c94 100644 (file)
@@ -22,6 +22,7 @@
 #define PPC_SYS(func)          .llong  DOTSYM(ppc_##func),DOTSYM(ppc_##func)
 #define OLDSYS(func)           .llong  DOTSYM(sys_ni_syscall),DOTSYM(sys_ni_syscall)
 #define SYS32ONLY(func)                .llong  DOTSYM(sys_ni_syscall),DOTSYM(compat_sys_##func)
+#define PPC64ONLY(func)                .llong  DOTSYM(ppc_##func),DOTSYM(sys_ni_syscall)
 #define SYSX(f, f3264, f32)    .llong  DOTSYM(f),DOTSYM(f3264)
 #else
 #define SYSCALL(func)          .long   sys_##func
@@ -29,6 +30,7 @@
 #define PPC_SYS(func)          .long   ppc_##func
 #define OLDSYS(func)           .long   sys_##func
 #define SYS32ONLY(func)                .long   sys_##func
+#define PPC64ONLY(func)                .long   sys_ni_syscall
 #define SYSX(f, f3264, f32)    .long   f32
 #endif
 #define SYSCALL_SPU(func)      SYSCALL(func)
index 238aa63ced8f97270a764757c77ddc3ccca17584..2384129f5893093f82bcd2f8896e2186127ecb49 100644 (file)
 #ifdef CONFIG_PPC64
 #define OLDSYS(func)           -1
 #define SYS32ONLY(func)                -1
+#define PPC64ONLY(func)                __NR_##func
 #else
 #define OLDSYS(func)           __NR_old##func
 #define SYS32ONLY(func)                __NR_##func
+#define PPC64ONLY(func)                -1
 #endif
 #define SYSX(f, f3264, f32)    -1
 
index 55f19f9fd70823f2320498a9d910ebe919633ffd..6813f80d1eec38e64cc02acf7f1ed7ad57b40afd 100644 (file)
@@ -69,54 +69,6 @@ CACHELINE_BYTES = L1_CACHE_BYTES
 LG_CACHELINE_BYTES = L1_CACHE_SHIFT
 CACHELINE_MASK = (L1_CACHE_BYTES-1)
 
-/*
- * Use dcbz on the complete cache lines in the destination
- * to set them to zero.  This requires that the destination
- * area is cacheable.  -- paulus
- */
-_GLOBAL(cacheable_memzero)
-       mr      r5,r4
-       li      r4,0
-       addi    r6,r3,-4
-       cmplwi  0,r5,4
-       blt     7f
-       stwu    r4,4(r6)
-       beqlr
-       andi.   r0,r6,3
-       add     r5,r0,r5
-       subf    r6,r0,r6
-       clrlwi  r7,r6,32-LG_CACHELINE_BYTES
-       add     r8,r7,r5
-       srwi    r9,r8,LG_CACHELINE_BYTES
-       addic.  r9,r9,-1        /* total number of complete cachelines */
-       ble     2f
-       xori    r0,r7,CACHELINE_MASK & ~3
-       srwi.   r0,r0,2
-       beq     3f
-       mtctr   r0
-4:     stwu    r4,4(r6)
-       bdnz    4b
-3:     mtctr   r9
-       li      r7,4
-10:    dcbz    r7,r6
-       addi    r6,r6,CACHELINE_BYTES
-       bdnz    10b
-       clrlwi  r5,r8,32-LG_CACHELINE_BYTES
-       addi    r5,r5,4
-2:     srwi    r0,r5,2
-       mtctr   r0
-       bdz     6f
-1:     stwu    r4,4(r6)
-       bdnz    1b
-6:     andi.   r5,r5,3
-7:     cmpwi   0,r5,0
-       beqlr
-       mtctr   r5
-       addi    r6,r6,3
-8:     stbu    r4,1(r6)
-       bdnz    8b
-       blr
-
 _GLOBAL(memset)
        rlwimi  r4,r4,8,16,23
        rlwimi  r4,r4,16,0,15
@@ -142,85 +94,6 @@ _GLOBAL(memset)
        bdnz    8b
        blr
 
-/*
- * This version uses dcbz on the complete cache lines in the
- * destination area to reduce memory traffic.  This requires that
- * the destination area is cacheable.
- * We only use this version if the source and dest don't overlap.
- * -- paulus.
- */
-_GLOBAL(cacheable_memcpy)
-       add     r7,r3,r5                /* test if the src & dst overlap */
-       add     r8,r4,r5
-       cmplw   0,r4,r7
-       cmplw   1,r3,r8
-       crand   0,0,4                   /* cr0.lt &= cr1.lt */
-       blt     memcpy                  /* if regions overlap */
-
-       addi    r4,r4,-4
-       addi    r6,r3,-4
-       neg     r0,r3
-       andi.   r0,r0,CACHELINE_MASK    /* # bytes to start of cache line */
-       beq     58f
-
-       cmplw   0,r5,r0                 /* is this more than total to do? */
-       blt     63f                     /* if not much to do */
-       andi.   r8,r0,3                 /* get it word-aligned first */
-       subf    r5,r0,r5
-       mtctr   r8
-       beq+    61f
-70:    lbz     r9,4(r4)                /* do some bytes */
-       stb     r9,4(r6)
-       addi    r4,r4,1
-       addi    r6,r6,1
-       bdnz    70b
-61:    srwi.   r0,r0,2
-       mtctr   r0
-       beq     58f
-72:    lwzu    r9,4(r4)                /* do some words */
-       stwu    r9,4(r6)
-       bdnz    72b
-
-58:    srwi.   r0,r5,LG_CACHELINE_BYTES /* # complete cachelines */
-       clrlwi  r5,r5,32-LG_CACHELINE_BYTES
-       li      r11,4
-       mtctr   r0
-       beq     63f
-53:
-       dcbz    r11,r6
-       COPY_16_BYTES
-#if L1_CACHE_BYTES >= 32
-       COPY_16_BYTES
-#if L1_CACHE_BYTES >= 64
-       COPY_16_BYTES
-       COPY_16_BYTES
-#if L1_CACHE_BYTES >= 128
-       COPY_16_BYTES
-       COPY_16_BYTES
-       COPY_16_BYTES
-       COPY_16_BYTES
-#endif
-#endif
-#endif
-       bdnz    53b
-
-63:    srwi.   r0,r5,2
-       mtctr   r0
-       beq     64f
-30:    lwzu    r0,4(r4)
-       stwu    r0,4(r6)
-       bdnz    30b
-
-64:    andi.   r0,r5,3
-       mtctr   r0
-       beq+    65f
-40:    lbz     r0,4(r4)
-       stb     r0,4(r6)
-       addi    r4,r4,1
-       addi    r6,r6,1
-       bdnz    40b
-65:    blr
-
 _GLOBAL(memmove)
        cmplw   0,r3,r4
        bgt     backwards_memcpy
index 170a0346f7561ff345ec9faa57fe4e55af9d9d46..f7deebdf33651fd3f1c5038267117341d84bdf79 100644 (file)
@@ -41,6 +41,7 @@ void __spin_yield(arch_spinlock_t *lock)
        plpar_hcall_norets(H_CONFER,
                get_hard_smp_processor_id(holder_cpu), yield_count);
 }
+EXPORT_SYMBOL_GPL(__spin_yield);
 
 /*
  * Waiting for a read lock or a write lock on a rwlock...
index f993959647b56581ba5d83133d9f48ced0d9e15b..c7f8e9586316181e48079258aedc39abe381b6ae 100644 (file)
@@ -8,10 +8,6 @@ EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(memmove);
 EXPORT_SYMBOL(memcmp);
 EXPORT_SYMBOL(memchr);
-#ifdef CONFIG_PPC32
-EXPORT_SYMBOL(cacheable_memcpy);
-EXPORT_SYMBOL(cacheable_memzero);
-#endif
 
 EXPORT_SYMBOL(strcpy);
 EXPORT_SYMBOL(strncpy);
index 10471f9bb63f1c6eed748a553259f6653f119e0f..d747dd7bc90b72ff7a7756fa745c2027da6c793d 100644 (file)
@@ -132,6 +132,7 @@ void pgtable_cache_add(unsigned shift, void (*ctor)(void *))
        align = max_t(unsigned long, align, minalign);
        name = kasprintf(GFP_KERNEL, "pgtable-2^%d", shift);
        new = kmem_cache_create(name, table_size, align, 0, ctor);
+       kfree(name);
        pgtable_cache[shift - 1] = new;
        pr_debug("Allocated pgtable cache for order %d\n", shift);
 }
index c68471c33731a4292d91efdd605a8bbb856c6918..5e80621d9324c7d176510842595513c915d49d3b 100644 (file)
@@ -958,6 +958,13 @@ void __init initmem_init(void)
 
        memblock_dump_all();
 
+       /*
+        * Reduce the possible NUMA nodes to the online NUMA nodes,
+        * since we do not support node hotplug. This ensures that  we
+        * lower the maximum NUMA node ID to what is actually present.
+        */
+       nodes_and(node_possible_map, node_possible_map, node_online_map);
+
        for_each_online_node(nid) {
                unsigned long start_pfn, end_pfn;
 
index 03b1a3b0fbd539cb3cbc6232bb72f9a8a1cc94b6..24f304a9a09593ef03fe795bb2a09d73642b10a7 100644 (file)
@@ -221,7 +221,7 @@ __ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags,
         */
        if (mem_init_done && (p < virt_to_phys(high_memory)) &&
            !(__allow_ioremap_reserved && memblock_is_region_reserved(p, size))) {
-               printk("__ioremap(): phys addr 0x%llx is RAM lr %pf\n",
+               printk("__ioremap(): phys addr 0x%llx is RAM lr %ps\n",
                       (unsigned long long)p, __builtin_return_address(0));
                return NULL;
        }
index 5029dc19b517cdb1d67a0323c1e6cc3951c002dc..eb0e489b1bb78872a02c42b91fd0798f7740d02e 100644 (file)
@@ -224,7 +224,7 @@ void __init MMU_init_hw(void)
         */
        if ( ppc_md.progress ) ppc_md.progress("hash:find piece", 0x322);
        Hash = __va(memblock_alloc(Hash_size, Hash_size));
-       cacheable_memzero(Hash, Hash_size);
+       memset(Hash, 0, Hash_size);
        _SDR1 = __pa(Hash) | SDR1_LOW_BITS;
 
        Hash_end = (struct hash_pte *) ((unsigned long)Hash + Hash_size);
index 7c4f6690533a5efab955565506a702ca352a56b2..b101c0b6daccbf4ba4354e1a53b462dbf5ab562d 100644 (file)
@@ -1832,8 +1832,10 @@ static int power_pmu_event_init(struct perf_event *event)
                cpuhw->bhrb_filter = ppmu->bhrb_filter_map(
                                        event->attr.branch_sample_type);
 
-               if(cpuhw->bhrb_filter == -1)
+               if (cpuhw->bhrb_filter == -1) {
+                       put_cpu_var(cpu_hw_events);
                        return -EOPNOTSUPP;
+               }
        }
 
        put_cpu_var(cpu_hw_events);
index 76483e3acd60e432a83d568b49924224eec83bbf..7264e91190be928e125d01fe22be89a2b544c597 100644 (file)
@@ -2,6 +2,7 @@ config PPC64
        bool "64-bit kernel"
        default n
        select HAVE_VIRT_CPU_ACCOUNTING
+       select ZLIB_DEFLATE
        help
          This option selects whether a 32-bit or a 64-bit kernel
          will be built.
@@ -15,7 +16,7 @@ choice
          The most common ones are the desktop and server CPUs (601, 603,
          604, 740, 750, 74xx) CPUs from Freescale and IBM, with their
          embedded 512x/52xx/82xx/83xx/86xx counterparts.
-         The other embeeded parts, namely 4xx, 8xx, e200 (55xx) and e500
+         The other embedded parts, namely 4xx, 8xx, e200 (55xx) and e500
          (85xx) each form a family of their own that is not compatible
          with the others.
 
index b0ec78e8ad68882e0237beffa1612471cd4f4662..a494028b2cdfa52eb2accf00f54550c5958f729f 100644 (file)
@@ -39,6 +39,7 @@ static void *spu_syscall_table[] = {
 #define PPC_SYS(func)          sys_ni_syscall,
 #define OLDSYS(func)           sys_ni_syscall,
 #define SYS32ONLY(func)                sys_ni_syscall,
+#define PPC64ONLY(func)                sys_ni_syscall,
 #define SYSX(f, f3264, f32)    sys_ni_syscall,
 
 #define SYSCALL_SPU(func)      sys_##func,
index 860a59eb8ea250248bc1334a864dd372570f6e85..15ebc4e8a151695d6b8dbc6130fd82e4d5860b0d 100644 (file)
@@ -253,7 +253,7 @@ static void briq_restart(char *cmd)
  * But unfortunately, the firmware does not connect /chosen/{stdin,stdout}
  * the the built-in serial node. Instead, a /failsafe node is created.
  */
-static void chrp_init_early(void)
+static __init void chrp_init_early(void)
 {
        struct device_node *node;
        const char *property;
index 3e91ef538114c6adb14401b6e33b5b247f5aa3e4..76f5013c35e5c1cedb9f70b09401b3cc76ec5ab5 100644 (file)
@@ -246,7 +246,7 @@ static void __init bootx_scan_dt_build_strings(unsigned long base,
                DBG(" detected display ! adding properties names !\n");
                bootx_dt_add_string("linux,boot-display", mem_end);
                bootx_dt_add_string("linux,opened", mem_end);
-               strncpy(bootx_disp_path, namep, 255);
+               strlcpy(bootx_disp_path, namep, sizeof(bootx_disp_path));
        }
 
        /* get and store all property names */
index 4c24bf60d39d2834a0795982d583aabce22ae89b..59cfc9d63c2d51a711448c1de281cf42fcf04349 100644 (file)
@@ -321,6 +321,9 @@ static void __init pmac_pic_probe_oldstyle(void)
                max_irqs = max_real_irqs = 64;
 
                /* We might have a second cascaded heathrow */
+
+               /* Compensate for of_node_put() in of_find_node_by_name() */
+               of_node_get(master);
                slave = of_find_node_by_name(master, "mac-io");
 
                /* Check ordering of master & slave */
index 5c21d9c07f4539e3b56a534b4315c4f7ebbd78ca..0ff07ff891f01991fccbed28a90185de5961af62 100644 (file)
@@ -120,7 +120,11 @@ static struct image_header_t       image_header;
 static struct image_data_t     image_data;
 static struct validate_flash_t validate_flash_data;
 static struct manage_flash_t   manage_flash_data;
-static struct update_flash_t   update_flash_data;
+
+/* Initialize update_flash_data status to No Operation */
+static struct update_flash_t   update_flash_data = {
+       .status = FLASH_NO_OP,
+};
 
 static DEFINE_MUTEX(image_data_mutex);
 
index f9896fd5d04afa1acc62f6ca6e82e25edce65d85..9db4398ded5de1f6c8e9a672a51008df1fbc85d7 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/of.h>
 
 #include <asm/opal.h>
+#include <asm/nvram.h>
 #include <asm/machdep.h>
 
 static unsigned int nvram_size;
@@ -62,6 +63,15 @@ static ssize_t opal_nvram_write(char *buf, size_t count, loff_t *index)
        return count;
 }
 
+static int __init opal_nvram_init_log_partitions(void)
+{
+       /* Scan nvram for partitions */
+       nvram_scan_partitions();
+       nvram_init_oops_partition(0);
+       return 0;
+}
+machine_arch_initcall(powernv, opal_nvram_init_log_partitions);
+
 void __init opal_nvram_init(void)
 {
        struct device_node *np;
index 4ab67ef7abc9d8a0d07079795f3801b3d62e035f..655250499d18cd84e59a8217d5f102ffd15ddab0 100644 (file)
@@ -46,18 +46,28 @@ int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data)
 
        mutex_lock(&opal_sensor_mutex);
        ret = opal_sensor_read(sensor_hndl, token, &data);
-       if (ret != OPAL_ASYNC_COMPLETION)
-               goto out_token;
+       switch (ret) {
+       case OPAL_ASYNC_COMPLETION:
+               ret = opal_async_wait_response(token, &msg);
+               if (ret) {
+                       pr_err("%s: Failed to wait for the async response, %d\n",
+                              __func__, ret);
+                       goto out_token;
+               }
 
-       ret = opal_async_wait_response(token, &msg);
-       if (ret) {
-               pr_err("%s: Failed to wait for the async response, %d\n",
-                               __func__, ret);
-               goto out_token;
-       }
+               ret = opal_error_code(be64_to_cpu(msg.params[1]));
+               *sensor_data = be32_to_cpu(data);
+               break;
+
+       case OPAL_SUCCESS:
+               ret = 0;
+               *sensor_data = be32_to_cpu(data);
+               break;
 
-       *sensor_data = be32_to_cpu(data);
-       ret = be64_to_cpu(msg.params[1]);
+       default:
+               ret = opal_error_code(ret);
+               break;
+       }
 
 out_token:
        mutex_unlock(&opal_sensor_mutex);
index 142a08a61bd1bb6ae25c519aa00aa6bdafebee49..3fb981c0ca8046757f47e9d40dfd8d594ce66790 100644 (file)
@@ -23,6 +23,8 @@
 #include <linux/kobject.h>
 #include <linux/delay.h>
 #include <linux/memblock.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
 
 #include <asm/machdep.h>
 #include <asm/opal.h>
@@ -58,6 +60,7 @@ static struct atomic_notifier_head opal_msg_notifier_head[OPAL_MSG_TYPE_MAX];
 static DEFINE_SPINLOCK(opal_notifier_lock);
 static uint64_t last_notified_mask = 0x0ul;
 static atomic_t opal_notifier_hold = ATOMIC_INIT(0);
+static uint32_t opal_heartbeat;
 
 static void opal_reinit_cores(void)
 {
@@ -305,20 +308,23 @@ void opal_notifier_disable(void)
 int opal_message_notifier_register(enum opal_msg_type msg_type,
                                        struct notifier_block *nb)
 {
-       if (!nb) {
-               pr_warning("%s: Invalid argument (%p)\n",
-                          __func__, nb);
-               return -EINVAL;
-       }
-       if (msg_type > OPAL_MSG_TYPE_MAX) {
-               pr_warning("%s: Invalid message type argument (%d)\n",
+       if (!nb || msg_type >= OPAL_MSG_TYPE_MAX) {
+               pr_warning("%s: Invalid arguments, msg_type:%d\n",
                           __func__, msg_type);
                return -EINVAL;
        }
+
        return atomic_notifier_chain_register(
                                &opal_msg_notifier_head[msg_type], nb);
 }
 
+int opal_message_notifier_unregister(enum opal_msg_type msg_type,
+                                    struct notifier_block *nb)
+{
+       return atomic_notifier_chain_unregister(
+                       &opal_msg_notifier_head[msg_type], nb);
+}
+
 static void opal_message_do_notify(uint32_t msg_type, void *msg)
 {
        /* notify subscribers */
@@ -351,7 +357,7 @@ static void opal_handle_message(void)
        type = be32_to_cpu(msg.msg_type);
 
        /* Sanity check */
-       if (type > OPAL_MSG_TYPE_MAX) {
+       if (type >= OPAL_MSG_TYPE_MAX) {
                pr_warning("%s: Unknown message type: %u\n", __func__, type);
                return;
        }
@@ -744,6 +750,29 @@ static void __init opal_irq_init(struct device_node *dn)
        }
 }
 
+static int kopald(void *unused)
+{
+       set_freezable();
+       do {
+               try_to_freeze();
+               opal_poll_events(NULL);
+               msleep_interruptible(opal_heartbeat);
+       } while (!kthread_should_stop());
+
+       return 0;
+}
+
+static void opal_init_heartbeat(void)
+{
+       /* Old firwmware, we assume the HVC heartbeat is sufficient */
+       if (of_property_read_u32(opal_node, "ibm,heartbeat-ms",
+                                &opal_heartbeat) != 0)
+               opal_heartbeat = 0;
+
+       if (opal_heartbeat)
+               kthread_run(kopald, NULL, "kopald");
+}
+
 static int __init opal_init(void)
 {
        struct device_node *np, *consoles;
@@ -772,6 +801,9 @@ static int __init opal_init(void)
        /* Create i2c platform devices */
        opal_i2c_create_devs();
 
+       /* Setup a heatbeat thread if requested by OPAL */
+       opal_init_heartbeat();
+
        /* Find all OPAL interrupts and request them */
        opal_irq_init(opal_node);
 
@@ -794,6 +826,7 @@ static int __init opal_init(void)
                opal_msglog_init();
        }
 
+       /* Initialize OPAL IPMI backend */
        opal_ipmi_init(opal_node);
 
        return 0;
@@ -898,6 +931,25 @@ void opal_free_sg_list(struct opal_sg_list *sg)
        }
 }
 
+int opal_error_code(int rc)
+{
+       switch (rc) {
+       case OPAL_SUCCESS:              return 0;
+
+       case OPAL_PARAMETER:            return -EINVAL;
+       case OPAL_ASYNC_COMPLETION:     return -EINPROGRESS;
+       case OPAL_BUSY_EVENT:           return -EBUSY;
+       case OPAL_NO_MEM:               return -ENOMEM;
+
+       case OPAL_UNSUPPORTED:          return -EIO;
+       case OPAL_HARDWARE:             return -EIO;
+       case OPAL_INTERNAL_ERROR:       return -EIO;
+       default:
+               pr_err("%s: unexpected OPAL error %d\n", __func__, rc);
+               return -EIO;
+       }
+}
+
 EXPORT_SYMBOL_GPL(opal_poll_events);
 EXPORT_SYMBOL_GPL(opal_rtc_read);
 EXPORT_SYMBOL_GPL(opal_rtc_write);
index d2de7d5d7574ca48fb1f31aa5c6892a510107ade..39d1971d77db665bd9904c87ef02c9b091e8798f 100644 (file)
@@ -409,37 +409,39 @@ static int __init pnv_init_idle_states(void)
 {
        struct device_node *power_mgt;
        int dt_idle_states;
-       const __be32 *idle_state_flags;
-       u32 len_flags, flags;
+       u32 *flags;
        int i;
 
        supported_cpuidle_states = 0;
 
        if (cpuidle_disable != IDLE_NO_OVERRIDE)
-               return 0;
+               goto out;
 
        if (!firmware_has_feature(FW_FEATURE_OPALv3))
-               return 0;
+               goto out;
 
        power_mgt = of_find_node_by_path("/ibm,opal/power-mgt");
        if (!power_mgt) {
                pr_warn("opal: PowerMgmt Node not found\n");
-               return 0;
+               goto out;
+       }
+       dt_idle_states = of_property_count_u32_elems(power_mgt,
+                       "ibm,cpu-idle-state-flags");
+       if (dt_idle_states < 0) {
+               pr_warn("cpuidle-powernv: no idle states found in the DT\n");
+               goto out;
        }
 
-       idle_state_flags = of_get_property(power_mgt,
-                       "ibm,cpu-idle-state-flags", &len_flags);
-       if (!idle_state_flags) {
-               pr_warn("DT-PowerMgmt: missing ibm,cpu-idle-state-flags\n");
-               return 0;
+       flags = kzalloc(sizeof(*flags) * dt_idle_states, GFP_KERNEL);
+       if (of_property_read_u32_array(power_mgt,
+                       "ibm,cpu-idle-state-flags", flags, dt_idle_states)) {
+               pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-flags in DT\n");
+               goto out_free;
        }
 
-       dt_idle_states = len_flags / sizeof(u32);
+       for (i = 0; i < dt_idle_states; i++)
+               supported_cpuidle_states |= flags[i];
 
-       for (i = 0; i < dt_idle_states; i++) {
-               flags = be32_to_cpu(idle_state_flags[i]);
-               supported_cpuidle_states |= flags;
-       }
        if (!(supported_cpuidle_states & OPAL_PM_SLEEP_ENABLED_ER1)) {
                patch_instruction(
                        (unsigned int *)pnv_fastsleep_workaround_at_entry,
@@ -449,6 +451,9 @@ static int __init pnv_init_idle_states(void)
                        PPC_INST_NOP);
        }
        pnv_alloc_idle_core_states();
+out_free:
+       kfree(flags);
+out:
        return 0;
 }
 
index a758a9c3bbbab5a788cf61bdb89ff3dc27238cfe..54c87d5d349dbedcbd5e12bc0e0f2af66c6bf5d0 100644 (file)
@@ -16,7 +16,6 @@ config PPC_PSERIES
        select PPC_UDBG_16550
        select PPC_NATIVE
        select PPC_PCI_CHOICE if EXPERT
-       select ZLIB_DEFLATE
        select PPC_DOORBELL
        select HAVE_CONTEXT_TRACKING
        select HOTPLUG_CPU if SMP
index 90cf3dcbd9f268b5430a1cb69bb44cd0fd75d54a..38db1b9f2ac3020a96a02274ddc957c340f2dd11 100644 (file)
@@ -318,28 +318,34 @@ static ssize_t migrate_store(struct class *class, struct class_attribute *attr,
 {
        u64 streamid;
        int rc;
-       int vasi_rc = 0;
 
        rc = kstrtou64(buf, 0, &streamid);
        if (rc)
                return rc;
 
        do {
-               rc = rtas_ibm_suspend_me(streamid, &vasi_rc);
-               if (!rc && vasi_rc == RTAS_NOT_SUSPENDABLE)
+               rc = rtas_ibm_suspend_me(streamid);
+               if (rc == -EAGAIN)
                        ssleep(1);
-       } while (!rc && vasi_rc == RTAS_NOT_SUSPENDABLE);
+       } while (rc == -EAGAIN);
 
        if (rc)
                return rc;
-       if (vasi_rc)
-               return vasi_rc;
 
        post_mobility_fixup();
        return count;
 }
 
+/*
+ * Used by drmgr to determine the kernel behavior of the migration interface.
+ *
+ * Version 1: Performs all PAPR requirements for migration including
+ *     firmware activation and device tree update.
+ */
+#define MIGRATION_API_VERSION  1
+
 static CLASS_ATTR(migration, S_IWUSR, NULL, migrate_store);
+static CLASS_ATTR_STRING(api_version, S_IRUGO, __stringify(MIGRATION_API_VERSION));
 
 static int __init mobility_sysfs_init(void)
 {
@@ -350,7 +356,13 @@ static int __init mobility_sysfs_init(void)
                return -ENOMEM;
 
        rc = sysfs_create_file(mobility_kobj, &class_attr_migration.attr);
+       if (rc)
+               pr_err("mobility: unable to create migration sysfs file (%d)\n", rc);
 
-       return rc;
+       rc = sysfs_create_file(mobility_kobj, &class_attr_api_version.attr.attr);
+       if (rc)
+               pr_err("mobility: unable to create api_version sysfs file (%d)\n", rc);
+
+       return 0;
 }
 machine_device_initcall(pseries, mobility_sysfs_init);
index 054a0ed5c7ee072726cfd3b09ecd45a4b10fe578..9f8184175c86590436645189270712667c26a3da 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/kmsg_dump.h>
 #include <linux/pstore.h>
 #include <linux/ctype.h>
-#include <linux/zlib.h>
 #include <asm/uaccess.h>
 #include <asm/nvram.h>
 #include <asm/rtas.h>
 /* Max bytes to read/write in one go */
 #define NVRW_CNT 0x20
 
-/*
- * Set oops header version to distinguish between old and new format header.
- * lnx,oops-log partition max size is 4000, header version > 4000 will
- * help in identifying new header.
- */
-#define OOPS_HDR_VERSION 5000
-
 static unsigned int nvram_size;
 static int nvram_fetch, nvram_store;
 static char nvram_buf[NVRW_CNT];       /* assume this is in the first 4GB */
 static DEFINE_SPINLOCK(nvram_lock);
 
-struct err_log_info {
-       __be32 error_type;
-       __be32 seq_num;
-};
-
-struct nvram_os_partition {
-       const char *name;
-       int req_size;   /* desired size, in bytes */
-       int min_size;   /* minimum acceptable size (0 means req_size) */
-       long size;      /* size of data portion (excluding err_log_info) */
-       long index;     /* offset of data portion of partition */
-       bool os_partition; /* partition initialized by OS, not FW */
-};
-
-static struct nvram_os_partition rtas_log_partition = {
-       .name = "ibm,rtas-log",
-       .req_size = 2079,
-       .min_size = 1055,
-       .index = -1,
-       .os_partition = true
-};
-
-static struct nvram_os_partition oops_log_partition = {
-       .name = "lnx,oops-log",
-       .req_size = 4000,
-       .min_size = 2000,
-       .index = -1,
-       .os_partition = true
-};
-
-static const char *pseries_nvram_os_partitions[] = {
-       "ibm,rtas-log",
-       "lnx,oops-log",
-       NULL
-};
-
-struct oops_log_info {
-       __be16 version;
-       __be16 report_length;
-       __be64 timestamp;
-} __attribute__((packed));
-
-static void oops_to_nvram(struct kmsg_dumper *dumper,
-                         enum kmsg_dump_reason reason);
-
-static struct kmsg_dumper nvram_kmsg_dumper = {
-       .dump = oops_to_nvram
-};
-
 /* See clobbering_unread_rtas_event() */
 #define NVRAM_RTAS_READ_TIMEOUT 5              /* seconds */
-static unsigned long last_unread_rtas_event;   /* timestamp */
-
-/*
- * For capturing and compressing an oops or panic report...
-
- * big_oops_buf[] holds the uncompressed text we're capturing.
- *
- * oops_buf[] holds the compressed text, preceded by a oops header.
- * oops header has u16 holding the version of oops header (to differentiate
- * between old and new format header) followed by u16 holding the length of
- * the compressed* text (*Or uncompressed, if compression fails.) and u64
- * holding the timestamp. oops_buf[] gets written to NVRAM.
- *
- * oops_log_info points to the header. oops_data points to the compressed text.
- *
- * +- oops_buf
- * |                                   +- oops_data
- * v                                   v
- * +-----------+-----------+-----------+------------------------+
- * | version   | length    | timestamp | text                   |
- * | (2 bytes) | (2 bytes) | (8 bytes) | (oops_data_sz bytes)   |
- * +-----------+-----------+-----------+------------------------+
- * ^
- * +- oops_log_info
- *
- * We preallocate these buffers during init to avoid kmalloc during oops/panic.
- */
-static size_t big_oops_buf_sz;
-static char *big_oops_buf, *oops_buf;
-static char *oops_data;
-static size_t oops_data_sz;
-
-/* Compression parameters */
-#define COMPR_LEVEL 6
-#define WINDOW_BITS 12
-#define MEM_LEVEL 4
-static struct z_stream_s stream;
+static time64_t last_unread_rtas_event;                /* timestamp */
 
 #ifdef CONFIG_PSTORE
-static struct nvram_os_partition of_config_partition = {
-       .name = "of-config",
-       .index = -1,
-       .os_partition = false
-};
-
-static struct nvram_os_partition common_partition = {
-       .name = "common",
-       .index = -1,
-       .os_partition = false
-};
-
-static enum pstore_type_id nvram_type_ids[] = {
-       PSTORE_TYPE_DMESG,
-       PSTORE_TYPE_PPC_RTAS,
-       PSTORE_TYPE_PPC_OF,
-       PSTORE_TYPE_PPC_COMMON,
-       -1
-};
-static int read_type;
-static unsigned long last_rtas_event;
+time64_t last_rtas_event;
 #endif
 
 static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
@@ -246,132 +133,26 @@ static ssize_t pSeries_nvram_get_size(void)
        return nvram_size ? nvram_size : -ENODEV;
 }
 
-
-/* nvram_write_os_partition, nvram_write_error_log
+/* nvram_write_error_log
  *
  * We need to buffer the error logs into nvram to ensure that we have
- * the failure information to decode.  If we have a severe error there
- * is no way to guarantee that the OS or the machine is in a state to
- * get back to user land and write the error to disk.  For example if
- * the SCSI device driver causes a Machine Check by writing to a bad
- * IO address, there is no way of guaranteeing that the device driver
- * is in any state that is would also be able to write the error data
- * captured to disk, thus we buffer it in NVRAM for analysis on the
- * next boot.
- *
- * In NVRAM the partition containing the error log buffer will looks like:
- * Header (in bytes):
- * +-----------+----------+--------+------------+------------------+
- * | signature | checksum | length | name       | data             |
- * |0          |1         |2      3|4         15|16        length-1|
- * +-----------+----------+--------+------------+------------------+
- *
- * The 'data' section would look like (in bytes):
- * +--------------+------------+-----------------------------------+
- * | event_logged | sequence # | error log                         |
- * |0            3|4          7|8                  error_log_size-1|
- * +--------------+------------+-----------------------------------+
- *
- * event_logged: 0 if event has not been logged to syslog, 1 if it has
- * sequence #: The unique sequence # for each event. (until it wraps)
- * error log: The error log from event_scan
+ * the failure information to decode.
  */
-static int nvram_write_os_partition(struct nvram_os_partition *part,
-                                   char *buff, int length,
-                                   unsigned int err_type,
-                                   unsigned int error_log_cnt)
-{
-       int rc;
-       loff_t tmp_index;
-       struct err_log_info info;
-       
-       if (part->index == -1) {
-               return -ESPIPE;
-       }
-
-       if (length > part->size) {
-               length = part->size;
-       }
-
-       info.error_type = cpu_to_be32(err_type);
-       info.seq_num = cpu_to_be32(error_log_cnt);
-
-       tmp_index = part->index;
-
-       rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info), &tmp_index);
-       if (rc <= 0) {
-               pr_err("%s: Failed nvram_write (%d)\n", __func__, rc);
-               return rc;
-       }
-
-       rc = ppc_md.nvram_write(buff, length, &tmp_index);
-       if (rc <= 0) {
-               pr_err("%s: Failed nvram_write (%d)\n", __func__, rc);
-               return rc;
-       }
-       
-       return 0;
-}
-
 int nvram_write_error_log(char * buff, int length,
                           unsigned int err_type, unsigned int error_log_cnt)
 {
        int rc = nvram_write_os_partition(&rtas_log_partition, buff, length,
                                                err_type, error_log_cnt);
        if (!rc) {
-               last_unread_rtas_event = get_seconds();
+               last_unread_rtas_event = ktime_get_real_seconds();
 #ifdef CONFIG_PSTORE
-               last_rtas_event = get_seconds();
+               last_rtas_event = ktime_get_real_seconds();
 #endif
        }
 
        return rc;
 }
 
-/* nvram_read_partition
- *
- * Reads nvram partition for at most 'length'
- */
-static int nvram_read_partition(struct nvram_os_partition *part, char *buff,
-                               int length, unsigned int *err_type,
-                               unsigned int *error_log_cnt)
-{
-       int rc;
-       loff_t tmp_index;
-       struct err_log_info info;
-       
-       if (part->index == -1)
-               return -1;
-
-       if (length > part->size)
-               length = part->size;
-
-       tmp_index = part->index;
-
-       if (part->os_partition) {
-               rc = ppc_md.nvram_read((char *)&info,
-                                       sizeof(struct err_log_info),
-                                       &tmp_index);
-               if (rc <= 0) {
-                       pr_err("%s: Failed nvram_read (%d)\n", __func__, rc);
-                       return rc;
-               }
-       }
-
-       rc = ppc_md.nvram_read(buff, length, &tmp_index);
-       if (rc <= 0) {
-               pr_err("%s: Failed nvram_read (%d)\n", __func__, rc);
-               return rc;
-       }
-
-       if (part->os_partition) {
-               *error_log_cnt = be32_to_cpu(info.seq_num);
-               *err_type = be32_to_cpu(info.error_type);
-       }
-
-       return 0;
-}
-
 /* nvram_read_error_log
  *
  * Reads nvram for error log for at most 'length'
@@ -407,67 +188,6 @@ int nvram_clear_error_log(void)
        return 0;
 }
 
-/* pseries_nvram_init_os_partition
- *
- * This sets up a partition with an "OS" signature.
- *
- * The general strategy is the following:
- * 1.) If a partition with the indicated name already exists...
- *     - If it's large enough, use it.
- *     - Otherwise, recycle it and keep going.
- * 2.) Search for a free partition that is large enough.
- * 3.) If there's not a free partition large enough, recycle any obsolete
- * OS partitions and try again.
- * 4.) Will first try getting a chunk that will satisfy the requested size.
- * 5.) If a chunk of the requested size cannot be allocated, then try finding
- * a chunk that will satisfy the minum needed.
- *
- * Returns 0 on success, else -1.
- */
-static int __init pseries_nvram_init_os_partition(struct nvram_os_partition
-                                                                       *part)
-{
-       loff_t p;
-       int size;
-
-       /* Look for ours */
-       p = nvram_find_partition(part->name, NVRAM_SIG_OS, &size);
-
-       /* Found one but too small, remove it */
-       if (p && size < part->min_size) {
-               pr_info("nvram: Found too small %s partition,"
-                                       " removing it...\n", part->name);
-               nvram_remove_partition(part->name, NVRAM_SIG_OS, NULL);
-               p = 0;
-       }
-
-       /* Create one if we didn't find */
-       if (!p) {
-               p = nvram_create_partition(part->name, NVRAM_SIG_OS,
-                                       part->req_size, part->min_size);
-               if (p == -ENOSPC) {
-                       pr_info("nvram: No room to create %s partition, "
-                               "deleting any obsolete OS partitions...\n",
-                               part->name);
-                       nvram_remove_partition(NULL, NVRAM_SIG_OS,
-                                               pseries_nvram_os_partitions);
-                       p = nvram_create_partition(part->name, NVRAM_SIG_OS,
-                                       part->req_size, part->min_size);
-               }
-       }
-
-       if (p <= 0) {
-               pr_err("nvram: Failed to find or create %s"
-                      " partition, err %d\n", part->name, (int)p);
-               return -1;
-       }
-
-       part->index = p;
-       part->size = nvram_get_partition_size(p) - sizeof(struct err_log_info);
-       
-       return 0;
-}
-
 /*
  * Are we using the ibm,rtas-log for oops/panic reports?  And if so,
  * would logging this oops/panic overwrite an RTAS event that rtas_errd
@@ -476,321 +196,14 @@ static int __init pseries_nvram_init_os_partition(struct nvram_os_partition
  * We assume that if rtas_errd hasn't read the RTAS event in
  * NVRAM_RTAS_READ_TIMEOUT seconds, it's probably not going to.
  */
-static int clobbering_unread_rtas_event(void)
+int clobbering_unread_rtas_event(void)
 {
        return (oops_log_partition.index == rtas_log_partition.index
                && last_unread_rtas_event
-               && get_seconds() - last_unread_rtas_event <=
+               && ktime_get_real_seconds() - last_unread_rtas_event <=
                                                NVRAM_RTAS_READ_TIMEOUT);
 }
 
-/* Derived from logfs_compress() */
-static int nvram_compress(const void *in, void *out, size_t inlen,
-                                                       size_t outlen)
-{
-       int err, ret;
-
-       ret = -EIO;
-       err = zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS,
-                                               MEM_LEVEL, Z_DEFAULT_STRATEGY);
-       if (err != Z_OK)
-               goto error;
-
-       stream.next_in = in;
-       stream.avail_in = inlen;
-       stream.total_in = 0;
-       stream.next_out = out;
-       stream.avail_out = outlen;
-       stream.total_out = 0;
-
-       err = zlib_deflate(&stream, Z_FINISH);
-       if (err != Z_STREAM_END)
-               goto error;
-
-       err = zlib_deflateEnd(&stream);
-       if (err != Z_OK)
-               goto error;
-
-       if (stream.total_out >= stream.total_in)
-               goto error;
-
-       ret = stream.total_out;
-error:
-       return ret;
-}
-
-/* Compress the text from big_oops_buf into oops_buf. */
-static int zip_oops(size_t text_len)
-{
-       struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
-       int zipped_len = nvram_compress(big_oops_buf, oops_data, text_len,
-                                                               oops_data_sz);
-       if (zipped_len < 0) {
-               pr_err("nvram: compression failed; returned %d\n", zipped_len);
-               pr_err("nvram: logging uncompressed oops/panic report\n");
-               return -1;
-       }
-       oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
-       oops_hdr->report_length = cpu_to_be16(zipped_len);
-       oops_hdr->timestamp = cpu_to_be64(get_seconds());
-       return 0;
-}
-
-#ifdef CONFIG_PSTORE
-static int nvram_pstore_open(struct pstore_info *psi)
-{
-       /* Reset the iterator to start reading partitions again */
-       read_type = -1;
-       return 0;
-}
-
-/**
- * nvram_pstore_write - pstore write callback for nvram
- * @type:               Type of message logged
- * @reason:             reason behind dump (oops/panic)
- * @id:                 identifier to indicate the write performed
- * @part:               pstore writes data to registered buffer in parts,
- *                      part number will indicate the same.
- * @count:              Indicates oops count
- * @compressed:         Flag to indicate the log is compressed
- * @size:               number of bytes written to the registered buffer
- * @psi:                registered pstore_info structure
- *
- * Called by pstore_dump() when an oops or panic report is logged in the
- * printk buffer.
- * Returns 0 on successful write.
- */
-static int nvram_pstore_write(enum pstore_type_id type,
-                               enum kmsg_dump_reason reason,
-                               u64 *id, unsigned int part, int count,
-                               bool compressed, size_t size,
-                               struct pstore_info *psi)
-{
-       int rc;
-       unsigned int err_type = ERR_TYPE_KERNEL_PANIC;
-       struct oops_log_info *oops_hdr = (struct oops_log_info *) oops_buf;
-
-       /* part 1 has the recent messages from printk buffer */
-       if (part > 1 || type != PSTORE_TYPE_DMESG ||
-                               clobbering_unread_rtas_event())
-               return -1;
-
-       oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
-       oops_hdr->report_length = cpu_to_be16(size);
-       oops_hdr->timestamp = cpu_to_be64(get_seconds());
-
-       if (compressed)
-               err_type = ERR_TYPE_KERNEL_PANIC_GZ;
-
-       rc = nvram_write_os_partition(&oops_log_partition, oops_buf,
-               (int) (sizeof(*oops_hdr) + size), err_type, count);
-
-       if (rc != 0)
-               return rc;
-
-       *id = part;
-       return 0;
-}
-
-/*
- * Reads the oops/panic report, rtas, of-config and common partition.
- * Returns the length of the data we read from each partition.
- * Returns 0 if we've been called before.
- */
-static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type,
-                               int *count, struct timespec *time, char **buf,
-                               bool *compressed, struct pstore_info *psi)
-{
-       struct oops_log_info *oops_hdr;
-       unsigned int err_type, id_no, size = 0;
-       struct nvram_os_partition *part = NULL;
-       char *buff = NULL;
-       int sig = 0;
-       loff_t p;
-
-       read_type++;
-
-       switch (nvram_type_ids[read_type]) {
-       case PSTORE_TYPE_DMESG:
-               part = &oops_log_partition;
-               *type = PSTORE_TYPE_DMESG;
-               break;
-       case PSTORE_TYPE_PPC_RTAS:
-               part = &rtas_log_partition;
-               *type = PSTORE_TYPE_PPC_RTAS;
-               time->tv_sec = last_rtas_event;
-               time->tv_nsec = 0;
-               break;
-       case PSTORE_TYPE_PPC_OF:
-               sig = NVRAM_SIG_OF;
-               part = &of_config_partition;
-               *type = PSTORE_TYPE_PPC_OF;
-               *id = PSTORE_TYPE_PPC_OF;
-               time->tv_sec = 0;
-               time->tv_nsec = 0;
-               break;
-       case PSTORE_TYPE_PPC_COMMON:
-               sig = NVRAM_SIG_SYS;
-               part = &common_partition;
-               *type = PSTORE_TYPE_PPC_COMMON;
-               *id = PSTORE_TYPE_PPC_COMMON;
-               time->tv_sec = 0;
-               time->tv_nsec = 0;
-               break;
-       default:
-               return 0;
-       }
-
-       if (!part->os_partition) {
-               p = nvram_find_partition(part->name, sig, &size);
-               if (p <= 0) {
-                       pr_err("nvram: Failed to find partition %s, "
-                               "err %d\n", part->name, (int)p);
-                       return 0;
-               }
-               part->index = p;
-               part->size = size;
-       }
-
-       buff = kmalloc(part->size, GFP_KERNEL);
-
-       if (!buff)
-               return -ENOMEM;
-
-       if (nvram_read_partition(part, buff, part->size, &err_type, &id_no)) {
-               kfree(buff);
-               return 0;
-       }
-
-       *count = 0;
-
-       if (part->os_partition)
-               *id = id_no;
-
-       if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) {
-               size_t length, hdr_size;
-
-               oops_hdr = (struct oops_log_info *)buff;
-               if (be16_to_cpu(oops_hdr->version) < OOPS_HDR_VERSION) {
-                       /* Old format oops header had 2-byte record size */
-                       hdr_size = sizeof(u16);
-                       length = be16_to_cpu(oops_hdr->version);
-                       time->tv_sec = 0;
-                       time->tv_nsec = 0;
-               } else {
-                       hdr_size = sizeof(*oops_hdr);
-                       length = be16_to_cpu(oops_hdr->report_length);
-                       time->tv_sec = be64_to_cpu(oops_hdr->timestamp);
-                       time->tv_nsec = 0;
-               }
-               *buf = kmalloc(length, GFP_KERNEL);
-               if (*buf == NULL)
-                       return -ENOMEM;
-               memcpy(*buf, buff + hdr_size, length);
-               kfree(buff);
-
-               if (err_type == ERR_TYPE_KERNEL_PANIC_GZ)
-                       *compressed = true;
-               else
-                       *compressed = false;
-               return length;
-       }
-
-       *buf = buff;
-       return part->size;
-}
-
-static struct pstore_info nvram_pstore_info = {
-       .owner = THIS_MODULE,
-       .name = "nvram",
-       .open = nvram_pstore_open,
-       .read = nvram_pstore_read,
-       .write = nvram_pstore_write,
-};
-
-static int nvram_pstore_init(void)
-{
-       int rc = 0;
-
-       nvram_pstore_info.buf = oops_data;
-       nvram_pstore_info.bufsize = oops_data_sz;
-
-       spin_lock_init(&nvram_pstore_info.buf_lock);
-
-       rc = pstore_register(&nvram_pstore_info);
-       if (rc != 0)
-               pr_err("nvram: pstore_register() failed, defaults to "
-                               "kmsg_dump; returned %d\n", rc);
-
-       return rc;
-}
-#else
-static int nvram_pstore_init(void)
-{
-       return -1;
-}
-#endif
-
-static void __init nvram_init_oops_partition(int rtas_partition_exists)
-{
-       int rc;
-
-       rc = pseries_nvram_init_os_partition(&oops_log_partition);
-       if (rc != 0) {
-               if (!rtas_partition_exists)
-                       return;
-               pr_notice("nvram: Using %s partition to log both"
-                       " RTAS errors and oops/panic reports\n",
-                       rtas_log_partition.name);
-               memcpy(&oops_log_partition, &rtas_log_partition,
-                                               sizeof(rtas_log_partition));
-       }
-       oops_buf = kmalloc(oops_log_partition.size, GFP_KERNEL);
-       if (!oops_buf) {
-               pr_err("nvram: No memory for %s partition\n",
-                                               oops_log_partition.name);
-               return;
-       }
-       oops_data = oops_buf + sizeof(struct oops_log_info);
-       oops_data_sz = oops_log_partition.size - sizeof(struct oops_log_info);
-
-       rc = nvram_pstore_init();
-
-       if (!rc)
-               return;
-
-       /*
-        * Figure compression (preceded by elimination of each line's <n>
-        * severity prefix) will reduce the oops/panic report to at most
-        * 45% of its original size.
-        */
-       big_oops_buf_sz = (oops_data_sz * 100) / 45;
-       big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
-       if (big_oops_buf) {
-               stream.workspace =  kmalloc(zlib_deflate_workspacesize(
-                                       WINDOW_BITS, MEM_LEVEL), GFP_KERNEL);
-               if (!stream.workspace) {
-                       pr_err("nvram: No memory for compression workspace; "
-                               "skipping compression of %s partition data\n",
-                               oops_log_partition.name);
-                       kfree(big_oops_buf);
-                       big_oops_buf = NULL;
-               }
-       } else {
-               pr_err("No memory for uncompressed %s data; "
-                       "skipping compression\n", oops_log_partition.name);
-               stream.workspace = NULL;
-       }
-
-       rc = kmsg_dump_register(&nvram_kmsg_dumper);
-       if (rc != 0) {
-               pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc);
-               kfree(oops_buf);
-               kfree(big_oops_buf);
-               kfree(stream.workspace);
-       }
-}
-
 static int __init pseries_nvram_init_log_partitions(void)
 {
        int rc;
@@ -798,7 +211,7 @@ static int __init pseries_nvram_init_log_partitions(void)
        /* Scan nvram for partitions */
        nvram_scan_partitions();
 
-       rc = pseries_nvram_init_os_partition(&rtas_log_partition);
+       rc = nvram_init_os_partition(&rtas_log_partition);
        nvram_init_oops_partition(rc == 0);
        return 0;
 }
@@ -834,72 +247,3 @@ int __init pSeries_nvram_init(void)
        return 0;
 }
 
-
-/*
- * This is our kmsg_dump callback, called after an oops or panic report
- * has been written to the printk buffer.  We want to capture as much
- * of the printk buffer as possible.  First, capture as much as we can
- * that we think will compress sufficiently to fit in the lnx,oops-log
- * partition.  If that's too much, go back and capture uncompressed text.
- */
-static void oops_to_nvram(struct kmsg_dumper *dumper,
-                         enum kmsg_dump_reason reason)
-{
-       struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
-       static unsigned int oops_count = 0;
-       static bool panicking = false;
-       static DEFINE_SPINLOCK(lock);
-       unsigned long flags;
-       size_t text_len;
-       unsigned int err_type = ERR_TYPE_KERNEL_PANIC_GZ;
-       int rc = -1;
-
-       switch (reason) {
-       case KMSG_DUMP_RESTART:
-       case KMSG_DUMP_HALT:
-       case KMSG_DUMP_POWEROFF:
-               /* These are almost always orderly shutdowns. */
-               return;
-       case KMSG_DUMP_OOPS:
-               break;
-       case KMSG_DUMP_PANIC:
-               panicking = true;
-               break;
-       case KMSG_DUMP_EMERG:
-               if (panicking)
-                       /* Panic report already captured. */
-                       return;
-               break;
-       default:
-               pr_err("%s: ignoring unrecognized KMSG_DUMP_* reason %d\n",
-                      __func__, (int) reason);
-               return;
-       }
-
-       if (clobbering_unread_rtas_event())
-               return;
-
-       if (!spin_trylock_irqsave(&lock, flags))
-               return;
-
-       if (big_oops_buf) {
-               kmsg_dump_get_buffer(dumper, false,
-                                    big_oops_buf, big_oops_buf_sz, &text_len);
-               rc = zip_oops(text_len);
-       }
-       if (rc != 0) {
-               kmsg_dump_rewind(dumper);
-               kmsg_dump_get_buffer(dumper, false,
-                                    oops_data, oops_data_sz, &text_len);
-               err_type = ERR_TYPE_KERNEL_PANIC;
-               oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
-               oops_hdr->report_length = cpu_to_be16(text_len);
-               oops_hdr->timestamp = cpu_to_be64(get_seconds());
-       }
-
-       (void) nvram_write_os_partition(&oops_log_partition, oops_buf,
-               (int) (sizeof(*oops_hdr) + text_len), err_type,
-               ++oops_count);
-
-       spin_unlock_irqrestore(&lock, flags);
-}
diff --git a/arch/powerpc/relocs_check.pl b/arch/powerpc/relocs_check.pl
deleted file mode 100755 (executable)
index 3f46e8b..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/perl
-
-# Copyright Â© 2009 IBM Corporation
-
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version
-# 2 of the License, or (at your option) any later version.
-
-# This script checks the relocations of a vmlinux for "suspicious"
-# relocations.
-
-use strict;
-use warnings;
-
-if ($#ARGV != 1) {
-       die "$0 [path to objdump] [path to vmlinux]\n";
-}
-
-# Have Kbuild supply the path to objdump so we handle cross compilation.
-my $objdump = shift;
-my $vmlinux = shift;
-my $bad_relocs_count = 0;
-my $bad_relocs = "";
-my $old_binutils = 0;
-
-open(FD, "$objdump -R $vmlinux|") or die;
-while (<FD>) {
-       study $_;
-
-       # Only look at relocation lines.
-       next if (!/\s+R_/);
-
-       # These relocations are okay
-       # On PPC64:
-       #       R_PPC64_RELATIVE, R_PPC64_NONE, R_PPC64_ADDR64
-       # On PPC:
-       #       R_PPC_RELATIVE, R_PPC_ADDR16_HI, 
-       #       R_PPC_ADDR16_HA,R_PPC_ADDR16_LO,
-       #       R_PPC_NONE
-
-       next if (/\bR_PPC64_RELATIVE\b/ or /\bR_PPC64_NONE\b/ or
-                /\bR_PPC64_ADDR64\s+mach_/);
-       next if (/\bR_PPC_ADDR16_LO\b/ or /\bR_PPC_ADDR16_HI\b/ or
-                /\bR_PPC_ADDR16_HA\b/ or /\bR_PPC_RELATIVE\b/ or
-                /\bR_PPC_NONE\b/);
-
-       # If we see this type of relocation it's an idication that
-       # we /may/ be using an old version of binutils.
-       if (/R_PPC64_UADDR64/) {
-               $old_binutils++;
-       }
-
-       $bad_relocs_count++;
-       $bad_relocs .= $_;
-}
-
-if ($bad_relocs_count) {
-       print "WARNING: $bad_relocs_count bad relocations\n";
-       print $bad_relocs;
-}
-
-if ($old_binutils) {
-       print "WARNING: You need at least binutils >= 2.19 to build a ".
-             "CONFIG_RELOCATABLE kernel\n";
-}
diff --git a/arch/powerpc/relocs_check.sh b/arch/powerpc/relocs_check.sh
new file mode 100755 (executable)
index 0000000..2e4ebd0
--- /dev/null
@@ -0,0 +1,59 @@
+#!/bin/sh
+
+# Copyright Â© 2015 IBM Corporation
+
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+
+# This script checks the relocations of a vmlinux for "suspicious"
+# relocations.
+
+# based on relocs_check.pl
+# Copyright Â© 2009 IBM Corporation
+
+if [ $# -lt 2 ]; then
+       echo "$0 [path to objdump] [path to vmlinux]" 1>&2
+       exit 1
+fi
+
+# Have Kbuild supply the path to objdump so we handle cross compilation.
+objdump="$1"
+vmlinux="$2"
+
+bad_relocs=$(
+"$objdump" -R "$vmlinux" |
+       # Only look at relocation lines.
+       grep -E '\<R_' |
+       # These relocations are okay
+       # On PPC64:
+       #       R_PPC64_RELATIVE, R_PPC64_NONE
+       #       R_PPC64_ADDR64 mach_<name>
+       # On PPC:
+       #       R_PPC_RELATIVE, R_PPC_ADDR16_HI,
+       #       R_PPC_ADDR16_HA,R_PPC_ADDR16_LO,
+       #       R_PPC_NONE
+       grep -F -w -v 'R_PPC64_RELATIVE
+R_PPC64_NONE
+R_PPC_ADDR16_LO
+R_PPC_ADDR16_HI
+R_PPC_ADDR16_HA
+R_PPC_RELATIVE
+R_PPC_NONE' |
+       grep -E -v '\<R_PPC64_ADDR64[[:space:]]+mach_'
+)
+
+if [ -z "$bad_relocs" ]; then
+       exit 0
+fi
+
+num_bad=$(echo "$bad_relocs" | wc -l)
+echo "WARNING: $num_bad bad relocations"
+echo "$bad_relocs"
+
+# If we see this type of relocation it's an idication that
+# we /may/ be using an old version of binutils.
+if echo "$bad_relocs" | grep -q -F -w R_PPC64_UADDR64; then
+       echo "WARNING: You need at least binutils >= 2.19 to build a CONFIG_RELOCATABLE kernel"
+fi
index 2d8a101b6b9edba7bebe70a8b03ebb4e2f0ba7ab..121e26fffd50946e8df457b51c3c088b6c6fa528 100644 (file)
@@ -54,7 +54,7 @@ bool dcr_map_ok_generic(dcr_host_t host)
        else if (host.type == DCR_HOST_MMIO)
                return dcr_map_ok_mmio(host.host.mmio);
        else
-               return 0;
+               return false;
 }
 EXPORT_SYMBOL_GPL(dcr_map_ok_generic);
 
index 10ae69bcbbd2d47a44f8e258cb3659e9d128bec1..d531f804455d254ec90aa0f2e4573f21aef57ba8 100644 (file)
@@ -557,8 +557,7 @@ int __init smu_init (void)
        return 0;
 
 fail_msg_node:
-       if (smu->msg_node)
-               of_node_put(smu->msg_node);
+       of_node_put(smu->msg_node);
 fail_db_node:
        of_node_put(smu->db_node);
 fail_bootmem:
index dee88e59f0d34be1359661368799d8546668eda7..f9512bfa6c3c7d86ec14da2309b54804b882f057 100644 (file)
@@ -329,10 +329,11 @@ int __init find_via_pmu(void)
                                gaddr = of_translate_address(gpiop, reg);
                        if (gaddr != OF_BAD_ADDR)
                                gpio_reg = ioremap(gaddr, 0x10);
+                       of_node_put(gpiop);
                }
                if (gpio_reg == NULL) {
                        printk(KERN_ERR "via-pmu: Can't find GPIO reg !\n");
-                       goto fail_gpio;
+                       goto fail;
                }
        } else
                pmu_kind = PMU_UNKNOWN;
@@ -340,7 +341,7 @@ int __init find_via_pmu(void)
        via = ioremap(taddr, 0x2000);
        if (via == NULL) {
                printk(KERN_ERR "via-pmu: Can't map address !\n");
-               goto fail;
+               goto fail_via_remap;
        }
        
        out_8(&via[IER], IER_CLR | 0x7f);       /* disable all intrs */
@@ -348,10 +349,8 @@ int __init find_via_pmu(void)
 
        pmu_state = idle;
 
-       if (!init_pmu()) {
-               via = NULL;
-               return 0;
-       }
+       if (!init_pmu())
+               goto fail_init;
 
        printk(KERN_INFO "PMU driver v%d initialized for %s, firmware: %02x\n",
               PMU_DRIVER_VERSION, pbook_type[pmu_kind], pmu_version);
@@ -359,11 +358,15 @@ int __init find_via_pmu(void)
        sys_ctrler = SYS_CTRLER_PMU;
        
        return 1;
- fail:
-       of_node_put(vias);
+
+ fail_init:
+       iounmap(via);
+       via = NULL;
+ fail_via_remap:
        iounmap(gpio_reg);
        gpio_reg = NULL;
- fail_gpio:
+ fail:
+       of_node_put(vias);
        vias = NULL;
        return 0;
 }
@@ -2109,7 +2112,7 @@ pmu_read(struct file *file, char __user *buf,
 
        spin_lock_irqsave(&pp->lock, flags);
        add_wait_queue(&pp->wait, &wait);
-       current->state = TASK_INTERRUPTIBLE;
+       set_current_state(TASK_INTERRUPTIBLE);
 
        for (;;) {
                ret = -EAGAIN;
@@ -2138,7 +2141,7 @@ pmu_read(struct file *file, char __user *buf,
                schedule();
                spin_lock_irqsave(&pp->lock, flags);
        }
-       current->state = TASK_RUNNING;
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(&pp->wait, &wait);
        spin_unlock_irqrestore(&pp->lock, flags);
        
index 162762d1a12cb1ffcb34a2325150278650168c29..220bae6f5e43836615d59b5e8e1f7829ead4b88a 100644 (file)
@@ -79,13 +79,6 @@ MODULE_AUTHOR
     ("Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>");
 MODULE_LICENSE("GPL");
 
-/*
- * PPC64 doesn't (yet) have a cacheable_memcpy
- */
-#ifdef CONFIG_PPC64
-#define cacheable_memcpy(d,s,n) memcpy((d),(s),(n))
-#endif
-
 /* minimum number of free TX descriptors required to wake up TX process */
 #define EMAC_TX_WAKEUP_THRESH          (NUM_TX_BUFF / 4)
 
@@ -1673,7 +1666,7 @@ static inline int emac_rx_sg_append(struct emac_instance *dev, int slot)
                        dev_kfree_skb(dev->rx_sg_skb);
                        dev->rx_sg_skb = NULL;
                } else {
-                       cacheable_memcpy(skb_tail_pointer(dev->rx_sg_skb),
+                       memcpy(skb_tail_pointer(dev->rx_sg_skb),
                                         dev->rx_skb[slot]->data, len);
                        skb_put(dev->rx_sg_skb, len);
                        emac_recycle_rx_skb(dev, slot, len);
@@ -1730,8 +1723,7 @@ static int emac_poll_rx(void *param, int budget)
                                goto oom;
 
                        skb_reserve(copy_skb, EMAC_RX_SKB_HEADROOM + 2);
-                       cacheable_memcpy(copy_skb->data - 2, skb->data - 2,
-                                        len + 2);
+                       memcpy(copy_skb->data - 2, skb->data - 2, len + 2);
                        emac_recycle_rx_skb(dev, slot, len);
                        skb = copy_skb;
                } else if (unlikely(emac_alloc_rx_skb(dev, slot, GFP_ATOMIC)))
index b139b7792e9fcf6a3c266790fa2dbeea0cf06e27..cb7d3a67380df07c0f7c9f2ad0fe616f8dfb55f1 100644 (file)
@@ -105,7 +105,7 @@ struct ps3_lpm_shadow_regs {
  * @open: An atomic variable indicating the lpm driver has been opened.
  * @rights: The lpm rigths granted by the system policy module.  A logical
  *  OR of enum ps3_lpm_rights.
- * @node_id: The node id of a BE prosessor whose performance monitor this
+ * @node_id: The node id of a BE processor whose performance monitor this
  *  lpar has the right to use.
  * @pu_id: The lv1 id of the logical PU.
  * @lpm_id: The lv1 id of this lpm instance.
@@ -412,7 +412,7 @@ u32 ps3_read_pm(u32 cpu, enum pm_reg_name reg)
                result = lv1_set_lpm_interval(lpm_priv->lpm_id, 0, 0, &val);
                if (result) {
                        val = 0;
-                       dev_dbg(sbd_core(), "%s:%u: lv1 set_inteval failed: "
+                       dev_dbg(sbd_core(), "%s:%u: lv1 set_interval failed: "
                                "reg %u, %s\n", __func__, __LINE__, reg,
                                ps3_result(result));
                }
index b32ce53d24ee5d7e07af71ee35873b5f7cb27ad4..56e1ffda4d8936173d70684b0e4f82ee8f8d4688 100644 (file)
@@ -364,6 +364,9 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, int count,
        case PSTORE_TYPE_PMSG:
                scnprintf(name, sizeof(name), "pmsg-%s-%lld", psname, id);
                break;
+       case PSTORE_TYPE_PPC_OPAL:
+               sprintf(name, "powerpc-opal-%s-%lld", psname, id);
+               break;
        case PSTORE_TYPE_UNKNOWN:
                scnprintf(name, sizeof(name), "unknown-%s-%lld", psname, id);
                break;
index 8884f6e507f7c7797b8cce98349e45f3b732a9b8..8e7a25b068b0925e4084c78f87d658d5758e518f 100644 (file)
@@ -40,6 +40,7 @@ enum pstore_type_id {
        PSTORE_TYPE_PPC_OF      = 5,
        PSTORE_TYPE_PPC_COMMON  = 6,
        PSTORE_TYPE_PMSG        = 7,
+       PSTORE_TYPE_PPC_OPAL    = 8,
        PSTORE_TYPE_UNKNOWN     = 255
 };
 
index 27dff8241de3ab40f80ef45a82e437d8fa67bc09..a5d5be7ec4c7f6cc1da05727d5e8488b7da887e6 100644 (file)
@@ -13,7 +13,7 @@ CFLAGS := -Wall -O2 -flto -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CUR
 
 export CC CFLAGS
 
-SUB_DIRS = pmu copyloops mm tm primitives stringloops vphn
+SUB_DIRS = pmu copyloops mm tm primitives stringloops vphn switch_endian
 
 endif
 
diff --git a/tools/testing/selftests/powerpc/switch_endian/.gitignore b/tools/testing/selftests/powerpc/switch_endian/.gitignore
new file mode 100644 (file)
index 0000000..89e762e
--- /dev/null
@@ -0,0 +1,2 @@
+switch_endian_test
+check-reversed.S
diff --git a/tools/testing/selftests/powerpc/switch_endian/Makefile b/tools/testing/selftests/powerpc/switch_endian/Makefile
new file mode 100644 (file)
index 0000000..081473d
--- /dev/null
@@ -0,0 +1,24 @@
+CC := $(CROSS_COMPILE)gcc
+PROGS := switch_endian_test
+
+ASFLAGS += -O2 -Wall -g -nostdlib -m64
+
+all: $(PROGS)
+
+switch_endian_test: check-reversed.S
+
+check-reversed.o: check.o
+       $(CROSS_COMPILE)objcopy -j .text --reverse-bytes=4 -O binary $< $@
+
+check-reversed.S: check-reversed.o
+       hexdump -v -e '/1 ".byte 0x%02X\n"' $< > $@
+
+run_tests: all
+       @-for PROG in $(PROGS); do \
+               ./$$PROG; \
+       done;
+
+clean:
+       rm -f $(PROGS) *.o check-reversed.S
+
+.PHONY: all run_tests clean
diff --git a/tools/testing/selftests/powerpc/switch_endian/check.S b/tools/testing/selftests/powerpc/switch_endian/check.S
new file mode 100644 (file)
index 0000000..e2484d2
--- /dev/null
@@ -0,0 +1,100 @@
+#include "common.h"
+
+/*
+ * Checks that registers contain what we expect, ie. they were not clobbered by
+ * the syscall.
+ *
+ * r15: pattern to check registers against.
+ *
+ * At the end r3 == 0 if everything's OK.
+ */
+       nop                     # guaranteed to be illegal in reverse-endian
+       mr      r9,r15
+       cmpd    r9,r3           # check r3
+       bne     1f
+       addi    r9,r15,4        # check r4
+       cmpd    r9,r4
+       bne     1f
+       lis     r9,0x00FF       # check CR
+       ori     r9,r9,0xF000
+       mfcr    r10
+       and     r10,r10,r9
+       cmpw    r9,r10
+       addi    r9,r15,34
+       bne     1f
+       addi    r9,r15,32       # check LR
+       mflr    r10
+       cmpd    r9,r10
+       bne     1f
+       addi    r9,r15,5        # check r5
+       cmpd    r9,r5
+       bne     1f
+       addi    r9,r15,6        # check r6
+       cmpd    r9,r6
+       bne     1f
+       addi    r9,r15,7        # check r7
+       cmpd    r9,r7
+       bne     1f
+       addi    r9,r15,8        # check r8
+       cmpd    r9,r8
+       bne     1f
+       addi    r9,r15,13       # check r13
+       cmpd    r9,r13
+       bne     1f
+       addi    r9,r15,14       # check r14
+       cmpd    r9,r14
+       bne     1f
+       addi    r9,r15,16       # check r16
+       cmpd    r9,r16
+       bne     1f
+       addi    r9,r15,17       # check r17
+       cmpd    r9,r17
+       bne     1f
+       addi    r9,r15,18       # check r18
+       cmpd    r9,r18
+       bne     1f
+       addi    r9,r15,19       # check r19
+       cmpd    r9,r19
+       bne     1f
+       addi    r9,r15,20       # check r20
+       cmpd    r9,r20
+       bne     1f
+       addi    r9,r15,21       # check r21
+       cmpd    r9,r21
+       bne     1f
+       addi    r9,r15,22       # check r22
+       cmpd    r9,r22
+       bne     1f
+       addi    r9,r15,23       # check r23
+       cmpd    r9,r23
+       bne     1f
+       addi    r9,r15,24       # check r24
+       cmpd    r9,r24
+       bne     1f
+       addi    r9,r15,25       # check r25
+       cmpd    r9,r25
+       bne     1f
+       addi    r9,r15,26       # check r26
+       cmpd    r9,r26
+       bne     1f
+       addi    r9,r15,27       # check r27
+       cmpd    r9,r27
+       bne     1f
+       addi    r9,r15,28       # check r28
+       cmpd    r9,r28
+       bne     1f
+       addi    r9,r15,29       # check r29
+       cmpd    r9,r29
+       bne     1f
+       addi    r9,r15,30       # check r30
+       cmpd    r9,r30
+       bne     1f
+       addi    r9,r15,31       # check r31
+       cmpd    r9,r31
+       bne     1f
+       b       2f
+1:     mr      r3, r9
+       li      r0, __NR_exit
+       sc
+2:     li      r0, __NR_switch_endian
+       nop
diff --git a/tools/testing/selftests/powerpc/switch_endian/common.h b/tools/testing/selftests/powerpc/switch_endian/common.h
new file mode 100644 (file)
index 0000000..69e3996
--- /dev/null
@@ -0,0 +1,6 @@
+#include <ppc-asm.h>
+#include <asm/unistd.h>
+
+#ifndef __NR_switch_endian
+#define __NR_switch_endian 363
+#endif
diff --git a/tools/testing/selftests/powerpc/switch_endian/switch_endian_test.S b/tools/testing/selftests/powerpc/switch_endian/switch_endian_test.S
new file mode 100644 (file)
index 0000000..ef7c971
--- /dev/null
@@ -0,0 +1,81 @@
+#include "common.h"
+
+       .data
+       .balign 8
+message:
+       .ascii "success: switch_endian_test\n\0"
+
+       .section ".toc"
+       .balign 8
+pattern:
+       .llong 0x5555AAAA5555AAAA
+
+       .text
+FUNC_START(_start)
+       /* Load the pattern */
+       ld      r15, pattern@TOC(%r2)
+
+       /* Setup CR, only CR2-CR4 are maintained */
+       lis     r3, 0x00FF
+       ori     r3, r3, 0xF000
+       mtcr    r3
+
+       /* Load the pattern slightly modified into the registers */
+       mr      r3, r15
+       addi    r4, r15, 4
+
+       addi    r5, r15, 32
+       mtlr    r5
+
+       addi    r5, r15, 5
+       addi    r6, r15, 6
+       addi    r7, r15, 7
+       addi    r8, r15, 8
+
+       /* r9 - r12 are clobbered */
+
+       addi    r13, r15, 13
+       addi    r14, r15, 14
+
+       /* Skip r15 we're using it */
+
+       addi    r16, r15, 16
+       addi    r17, r15, 17
+       addi    r18, r15, 18
+       addi    r19, r15, 19
+       addi    r20, r15, 20
+       addi    r21, r15, 21
+       addi    r22, r15, 22
+       addi    r23, r15, 23
+       addi    r24, r15, 24
+       addi    r25, r15, 25
+       addi    r26, r15, 26
+       addi    r27, r15, 27
+       addi    r28, r15, 28
+       addi    r29, r15, 29
+       addi    r30, r15, 30
+       addi    r31, r15, 31
+
+       /*
+        * Call the syscall to switch endian.
+        * It clobbers r9-r12, XER, CTR and CR0-1,5-7.
+        */
+       li r0, __NR_switch_endian
+       sc
+
+#include "check-reversed.S"
+
+       /* Flip back, r0 already has the switch syscall number */
+       .long   0x02000044      /* sc */
+
+#include "check.S"
+
+       li      r0, __NR_write
+       li      r3, 1   /* stdout */
+       ld      r4, message@got(%r2)
+       li      r5, 28  /* strlen(message3) */
+       sc
+       li      r0, __NR_exit
+       li      r3, 0
+       sc
+       b       .