Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/scom: Change scom_read() and scom_write() to return errors

scom_read() now returns the read value via a pointer argument and
both functions return an int error code

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

+46 -23
+17 -6
arch/powerpc/include/asm/scom.h
··· 54 54 scom_map_t (*map)(struct device_node *ctrl_dev, u64 reg, u64 count); 55 55 void (*unmap)(scom_map_t map); 56 56 57 - u64 (*read)(scom_map_t map, u32 reg); 58 - void (*write)(scom_map_t map, u32 reg, u64 value); 57 + int (*read)(scom_map_t map, u32 reg, u64 *value); 58 + int (*write)(scom_map_t map, u32 reg, u64 value); 59 59 }; 60 60 61 61 extern const struct scom_controller *scom_controller; ··· 133 133 * scom_read - Read a SCOM register 134 134 * @map: Result of scom_map 135 135 * @reg: Register index within that map 136 + * @value: Updated with the value read 137 + * 138 + * Returns 0 (success) or a negative error code 136 139 */ 137 - static inline u64 scom_read(scom_map_t map, u32 reg) 140 + static inline int scom_read(scom_map_t map, u32 reg, u64 *value) 138 141 { 139 - return scom_controller->read(map, reg); 142 + int rc; 143 + 144 + rc = scom_controller->read(map, reg, value); 145 + if (rc) 146 + *value = 0xfffffffffffffffful; 147 + return rc; 140 148 } 141 149 142 150 /** ··· 152 144 * @map: Result of scom_map 153 145 * @reg: Register index within that map 154 146 * @value: Value to write 147 + * 148 + * Returns 0 (success) or a negative error code 155 149 */ 156 - static inline void scom_write(scom_map_t map, u32 reg, u64 value) 150 + static inline int scom_write(scom_map_t map, u32 reg, u64 value) 157 151 { 158 - scom_controller->write(map, reg, value); 152 + return scom_controller->write(map, reg, value); 159 153 } 154 + 160 155 161 156 #endif /* CONFIG_PPC_SCOM */ 162 157 #endif /* __ASSEMBLY__ */
+13 -5
arch/powerpc/platforms/wsp/scom_smp.c
··· 116 116 117 117 scom_write(scom, SCOM_RAMIC, cmd); 118 118 119 - while (!((val = scom_read(scom, SCOM_RAMC)) & mask)) { 119 + for (;;) { 120 + if (scom_read(scom, SCOM_RAMC, &val) != 0) { 121 + pr_err("SCOM error on instruction 0x%08x, thread %d\n", 122 + insn, thread); 123 + return -1; 124 + } 125 + if (val & mask) 126 + break; 120 127 pr_devel("Waiting on RAMC = 0x%llx\n", val); 121 128 if (++n == 3) { 122 129 pr_err("RAMC timeout on instruction 0x%08x, thread %d\n", ··· 158 151 if (rc) 159 152 return rc; 160 153 161 - *out_gpr = scom_read(scom, SCOM_RAMD); 162 - 163 - return 0; 154 + return scom_read(scom, SCOM_RAMD, out_gpr); 164 155 } 165 156 166 157 static int a2_scom_getspr(scom_map_t scom, int thread, int spr, u64 *out_spr) ··· 358 353 359 354 pr_devel("Bringing up CPU%d using SCOM...\n", lcpu); 360 355 361 - pccr0 = scom_read(scom, SCOM_PCCR0); 356 + if (scom_read(scom, SCOM_PCCR0, &pccr0) != 0) { 357 + printk(KERN_ERR "XSCOM failure readng PCCR0 on CPU%d\n", lcpu); 358 + return -1; 359 + } 362 360 scom_write(scom, SCOM_PCCR0, pccr0 | SCOM_PCCR0_ENABLE_DEBUG | 363 361 SCOM_PCCR0_ENABLE_RAM); 364 362
+8 -4
arch/powerpc/platforms/wsp/scom_wsp.c
··· 50 50 iounmap((void *)map); 51 51 } 52 52 53 - static u64 wsp_scom_read(scom_map_t map, u32 reg) 53 + static int wsp_scom_read(scom_map_t map, u32 reg, u64 *value) 54 54 { 55 55 u64 __iomem *addr = (u64 __iomem *)map; 56 56 57 - return in_be64(addr + reg); 57 + *value = in_be64(addr + reg); 58 + 59 + return 0; 58 60 } 59 61 60 - static void wsp_scom_write(scom_map_t map, u32 reg, u64 value) 62 + static int wsp_scom_write(scom_map_t map, u32 reg, u64 value) 61 63 { 62 64 u64 __iomem *addr = (u64 __iomem *)map; 63 65 64 - return out_be64(addr + reg, value); 66 + out_be64(addr + reg, value); 67 + 68 + return 0; 65 69 } 66 70 67 71 static const struct scom_controller wsp_scom_controller = {
+7 -6
arch/powerpc/platforms/wsp/wsp.c
··· 89 89 struct device_node *dn; 90 90 struct device_node *mine; 91 91 struct device_node *me; 92 + int rc; 92 93 93 94 me = of_get_cpu_node(smp_processor_id(), NULL); 94 95 mine = scom_find_parent(me); ··· 102 101 103 102 /* read-modify-write it so the HW probe does not get 104 103 * confused */ 105 - val = scom_read(m, 0); 106 - val |= 1; 107 - scom_write(m, 0, val); 104 + rc = scom_read(m, 0, &val); 105 + if (rc == 0) 106 + scom_write(m, 0, val | 1); 108 107 scom_unmap(m); 109 108 } 110 109 m = scom_map(mine, 0, 1); 111 - val = scom_read(m, 0); 112 - val |= 1; 113 - scom_write(m, 0, val); 110 + rc = scom_read(m, 0, &val); 111 + if (rc == 0) 112 + scom_write(m, 0, val | 1); 114 113 /* should never return */ 115 114 scom_unmap(m); 116 115 }
+1 -2
arch/powerpc/sysdev/scom.c
··· 137 137 if (!scom_map_ok(ent->map)) 138 138 return -EFAULT; 139 139 140 - *val = scom_read(ent->map, 0); 141 - return 0; 140 + return scom_read(ent->map, 0, val); 142 141 } 143 142 DEFINE_SIMPLE_ATTRIBUTE(scom_val_fops, scom_val_get, scom_val_set, 144 143 "0x%llx\n");