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

ipmi: Consolidate the adding of platform devices

It was being done in two different places now that hard-coded devices
use platform devices, and it's about to be three with hotmod switching
to platform devices. So put the code in one place.

This required some rework on some interfaces to make the type space
clean.

Signed-off-by: Corey Minyard <cminyard@mvista.com>

+205 -214
+5
drivers/char/ipmi/Kconfig
··· 18 18 If unsure, say N. 19 19 20 20 config IPMI_DMI_DECODE 21 + select IPMI_PLAT_DATA 22 + bool 23 + 24 + config IPMI_PLAT_DATA 21 25 bool 22 26 23 27 if IPMI_HANDLER ··· 60 56 61 57 config IPMI_SI 62 58 tristate 'IPMI System Interface handler' 59 + select IPMI_PLAT_DATA 63 60 help 64 61 Provides a driver for System Interfaces (KCS, SMIC, BT). 65 62 Currently, only KCS and SMIC are supported. If
+1
drivers/char/ipmi/Makefile
··· 17 17 obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o 18 18 obj-$(CONFIG_IPMI_SI) += ipmi_si.o 19 19 obj-$(CONFIG_IPMI_DMI_DECODE) += ipmi_dmi.o 20 + obj-$(CONFIG_IPMI_PLAT_DATA) += ipmi_plat_data.o 20 21 obj-$(CONFIG_IPMI_SSIF) += ipmi_ssif.o 21 22 obj-$(CONFIG_IPMI_POWERNV) += ipmi_powernv.o 22 23 obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o
+33 -106
drivers/char/ipmi/ipmi_dmi.c
··· 14 14 #include <linux/property.h> 15 15 #include "ipmi_si_sm.h" 16 16 #include "ipmi_dmi.h" 17 + #include "ipmi_plat_data.h" 17 18 18 19 #define IPMI_DMI_TYPE_KCS 0x01 19 20 #define IPMI_DMI_TYPE_SMIC 0x02 ··· 23 22 24 23 struct ipmi_dmi_info { 25 24 enum si_type si_type; 26 - u32 flags; 25 + unsigned int space; /* addr space for si, intf# for ssif */ 27 26 unsigned long addr; 28 27 u8 slave_addr; 29 28 struct ipmi_dmi_info *next; ··· 34 33 static int ipmi_dmi_nr __initdata; 35 34 36 35 static void __init dmi_add_platform_ipmi(unsigned long base_addr, 37 - u32 flags, 36 + unsigned int space, 38 37 u8 slave_addr, 39 38 int irq, 40 39 int offset, 41 40 int type) 42 41 { 43 - struct platform_device *pdev; 44 - struct resource r[4]; 45 - unsigned int num_r = 1, size; 46 - struct property_entry p[5]; 47 - unsigned int pidx = 0; 48 - char *name; 49 - int rv; 50 - enum si_type si_type; 42 + const char *name; 51 43 struct ipmi_dmi_info *info; 44 + struct ipmi_plat_data p; 52 45 53 - memset(p, 0, sizeof(p)); 46 + memset(&p, 0, sizeof(p)); 54 47 55 48 name = "dmi-ipmi-si"; 56 49 switch (type) { 57 50 case IPMI_DMI_TYPE_SSIF: 58 51 name = "dmi-ipmi-ssif"; 59 - offset = 1; 60 - size = 1; 61 - si_type = SI_TYPE_INVALID; 52 + p.type = SI_TYPE_INVALID; 62 53 break; 63 54 case IPMI_DMI_TYPE_BT: 64 - size = 3; 65 - si_type = SI_BT; 55 + p.type = SI_BT; 66 56 break; 67 57 case IPMI_DMI_TYPE_KCS: 68 - size = 2; 69 - si_type = SI_KCS; 58 + p.type = SI_KCS; 70 59 break; 71 60 case IPMI_DMI_TYPE_SMIC: 72 - size = 2; 73 - si_type = SI_SMIC; 61 + p.type = SI_SMIC; 74 62 break; 75 63 default: 76 64 pr_err("Invalid IPMI type: %d\n", type); 77 65 return; 78 66 } 79 67 80 - if (si_type != SI_TYPE_INVALID) 81 - p[pidx++] = PROPERTY_ENTRY_U8("ipmi-type", si_type); 82 - 83 - p[pidx++] = PROPERTY_ENTRY_U8("slave-addr", slave_addr); 84 - p[pidx++] = PROPERTY_ENTRY_U8("addr-source", SI_SMBIOS); 68 + memset(&p, 0, sizeof(p)); 69 + p.addr = base_addr; 70 + p.space = space; 71 + p.regspacing = offset; 72 + p.irq = irq; 73 + p.slave_addr = slave_addr; 74 + p.addr_source = SI_SMBIOS; 85 75 86 76 info = kmalloc(sizeof(*info), GFP_KERNEL); 87 77 if (!info) { 88 78 pr_warn("Could not allocate dmi info\n"); 89 79 } else { 90 - info->si_type = si_type; 91 - info->flags = flags; 80 + info->si_type = p.type; 81 + info->space = space; 92 82 info->addr = base_addr; 93 83 info->slave_addr = slave_addr; 94 84 info->next = ipmi_dmi_infos; 95 85 ipmi_dmi_infos = info; 96 86 } 97 87 98 - pdev = platform_device_alloc(name, ipmi_dmi_nr); 99 - if (!pdev) { 100 - pr_err("Error allocation IPMI platform device\n"); 101 - return; 102 - } 103 - 104 - if (type == IPMI_DMI_TYPE_SSIF) { 105 - p[pidx++] = PROPERTY_ENTRY_U16("i2c-addr", base_addr); 106 - goto add_properties; 107 - } 108 - 109 - memset(r, 0, sizeof(r)); 110 - 111 - r[0].start = base_addr; 112 - r[0].end = r[0].start + offset - 1; 113 - r[0].name = "IPMI Address 1"; 114 - r[0].flags = flags; 115 - 116 - if (size > 1) { 117 - r[1].start = r[0].start + offset; 118 - r[1].end = r[1].start + offset - 1; 119 - r[1].name = "IPMI Address 2"; 120 - r[1].flags = flags; 121 - num_r++; 122 - } 123 - 124 - if (size > 2) { 125 - r[2].start = r[1].start + offset; 126 - r[2].end = r[2].start + offset - 1; 127 - r[2].name = "IPMI Address 3"; 128 - r[2].flags = flags; 129 - num_r++; 130 - } 131 - 132 - if (irq) { 133 - r[num_r].start = irq; 134 - r[num_r].end = irq; 135 - r[num_r].name = "IPMI IRQ"; 136 - r[num_r].flags = IORESOURCE_IRQ; 137 - num_r++; 138 - } 139 - 140 - rv = platform_device_add_resources(pdev, r, num_r); 141 - if (rv) { 142 - dev_err(&pdev->dev, "Unable to add resources: %d\n", rv); 143 - goto err; 144 - } 145 - 146 - add_properties: 147 - rv = platform_device_add_properties(pdev, p); 148 - if (rv) { 149 - dev_err(&pdev->dev, "Unable to add properties: %d\n", rv); 150 - goto err; 151 - } 152 - 153 - rv = platform_device_add(pdev); 154 - if (rv) { 155 - dev_err(&pdev->dev, "Unable to add device: %d\n", rv); 156 - goto err; 157 - } 158 - 159 - ipmi_dmi_nr++; 160 - return; 161 - 162 - err: 163 - platform_device_put(pdev); 88 + if (ipmi_platform_add(name, ipmi_dmi_nr, &p)) 89 + ipmi_dmi_nr++; 164 90 } 165 91 166 92 /* ··· 97 169 * This function allows an ACPI-specified IPMI device to look up the 98 170 * slave address from the DMI table. 99 171 */ 100 - int ipmi_dmi_get_slave_addr(enum si_type si_type, u32 flags, 172 + int ipmi_dmi_get_slave_addr(enum si_type si_type, unsigned int space, 101 173 unsigned long base_addr) 102 174 { 103 175 struct ipmi_dmi_info *info = ipmi_dmi_infos; 104 176 105 177 while (info) { 106 178 if (info->si_type == si_type && 107 - info->flags == flags && 179 + info->space == space && 108 180 info->addr == base_addr) 109 181 return info->slave_addr; 110 182 info = info->next; ··· 125 197 126 198 static void __init dmi_decode_ipmi(const struct dmi_header *dm) 127 199 { 128 - const u8 *data = (const u8 *) dm; 129 - u32 flags = IORESOURCE_IO; 130 - unsigned long base_addr; 131 - u8 len = dm->length; 132 - u8 slave_addr; 133 - int irq = 0, offset; 134 - int type; 200 + const u8 *data = (const u8 *) dm; 201 + int space = IPMI_IO_ADDR_SPACE; 202 + unsigned long base_addr; 203 + u8 len = dm->length; 204 + u8 slave_addr; 205 + int irq = 0, offset = 0; 206 + int type; 135 207 136 208 if (len < DMI_IPMI_MIN_LENGTH) 137 209 return; ··· 146 218 } 147 219 if (len >= DMI_IPMI_VER2_LENGTH) { 148 220 if (type == IPMI_DMI_TYPE_SSIF) { 149 - offset = 0; 150 - flags = 0; 221 + space = 0; /* Match I2C interface 0. */ 151 222 base_addr = data[DMI_IPMI_ADDR] >> 1; 152 223 if (base_addr == 0) { 153 224 /* ··· 163 236 base_addr &= DMI_IPMI_IO_MASK; 164 237 } else { 165 238 /* Memory */ 166 - flags = IORESOURCE_MEM; 239 + space = IPMI_MEM_ADDR_SPACE; 167 240 } 168 241 169 242 /* ··· 207 280 offset = 1; 208 281 } 209 282 210 - dmi_add_platform_ipmi(base_addr, flags, slave_addr, irq, 283 + dmi_add_platform_ipmi(base_addr, space, slave_addr, irq, 211 284 offset, type); 212 285 } 213 286
+1 -1
drivers/char/ipmi/ipmi_dmi.h
··· 4 4 */ 5 5 6 6 #ifdef CONFIG_IPMI_DMI_DECODE 7 - int ipmi_dmi_get_slave_addr(enum si_type si_type, u32 flags, 7 + int ipmi_dmi_get_slave_addr(enum si_type si_type, unsigned int space, 8 8 unsigned long base_addr); 9 9 #endif
+121
drivers/char/ipmi/ipmi_plat_data.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + 3 + /* 4 + * Add an IPMI platform device. 5 + */ 6 + 7 + #include <linux/platform_device.h> 8 + #include "ipmi_plat_data.h" 9 + #include "ipmi_si.h" 10 + 11 + struct platform_device *ipmi_platform_add(const char *name, unsigned int inst, 12 + struct ipmi_plat_data *p) 13 + { 14 + struct platform_device *pdev; 15 + unsigned int num_r = 1, size, pidx = 0; 16 + struct resource r[4]; 17 + struct property_entry pr[6]; 18 + u32 flags; 19 + int rv; 20 + 21 + memset(pr, 0, sizeof(pr)); 22 + memset(r, 0, sizeof(r)); 23 + 24 + if (p->type == SI_BT) 25 + size = 3; 26 + else if (p->type == SI_TYPE_INVALID) 27 + size = 0; 28 + else 29 + size = 2; 30 + 31 + if (p->regsize == 0) 32 + p->regsize = DEFAULT_REGSIZE; 33 + if (p->regspacing == 0) 34 + p->regspacing = p->regsize; 35 + 36 + pr[pidx++] = PROPERTY_ENTRY_U8("ipmi-type", p->type); 37 + if (p->slave_addr) 38 + pr[pidx++] = PROPERTY_ENTRY_U8("slave-addr", p->slave_addr); 39 + pr[pidx++] = PROPERTY_ENTRY_U8("addr-source", p->addr_source); 40 + if (p->regshift) 41 + pr[pidx++] = PROPERTY_ENTRY_U8("reg-shift", p->regshift); 42 + pr[pidx++] = PROPERTY_ENTRY_U8("reg-size", p->regsize); 43 + /* Last entry must be left NULL to terminate it. */ 44 + 45 + pdev = platform_device_alloc(name, inst); 46 + if (!pdev) { 47 + pr_err("Error allocating IPMI platform device %s.%d\n", 48 + name, inst); 49 + return NULL; 50 + } 51 + 52 + if (size == 0) 53 + /* An invalid or SSIF interface, no resources. */ 54 + goto add_properties; 55 + 56 + /* 57 + * Register spacing is derived from the resources in 58 + * the IPMI platform code. 59 + */ 60 + 61 + if (p->space == IPMI_IO_ADDR_SPACE) 62 + flags = IORESOURCE_IO; 63 + else 64 + flags = IORESOURCE_MEM; 65 + 66 + r[0].start = p->addr; 67 + r[0].end = r[0].start + p->regsize - 1; 68 + r[0].name = "IPMI Address 1"; 69 + r[0].flags = flags; 70 + 71 + if (size > 1) { 72 + r[1].start = r[0].start + p->regspacing; 73 + r[1].end = r[1].start + p->regsize - 1; 74 + r[1].name = "IPMI Address 2"; 75 + r[1].flags = flags; 76 + num_r++; 77 + } 78 + 79 + if (size > 2) { 80 + r[2].start = r[1].start + p->regspacing; 81 + r[2].end = r[2].start + p->regsize - 1; 82 + r[2].name = "IPMI Address 3"; 83 + r[2].flags = flags; 84 + num_r++; 85 + } 86 + 87 + if (p->irq) { 88 + r[num_r].start = p->irq; 89 + r[num_r].end = p->irq; 90 + r[num_r].name = "IPMI IRQ"; 91 + r[num_r].flags = IORESOURCE_IRQ; 92 + num_r++; 93 + } 94 + 95 + rv = platform_device_add_resources(pdev, r, num_r); 96 + if (rv) { 97 + dev_err(&pdev->dev, 98 + "Unable to add hard-code resources: %d\n", rv); 99 + goto err; 100 + } 101 + add_properties: 102 + rv = platform_device_add_properties(pdev, pr); 103 + if (rv) { 104 + dev_err(&pdev->dev, 105 + "Unable to add hard-code properties: %d\n", rv); 106 + goto err; 107 + } 108 + 109 + rv = platform_device_add(pdev); 110 + if (rv) { 111 + dev_err(&pdev->dev, 112 + "Unable to add hard-code device: %d\n", rv); 113 + goto err; 114 + } 115 + return pdev; 116 + 117 + err: 118 + platform_device_put(pdev); 119 + return NULL; 120 + } 121 + EXPORT_SYMBOL(ipmi_platform_add);
+22
drivers/char/ipmi/ipmi_plat_data.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 + 3 + /* 4 + * Generic code to add IPMI platform devices. 5 + */ 6 + 7 + #include <linux/ipmi.h> 8 + 9 + struct ipmi_plat_data { 10 + unsigned int type; /* si_type for si, SI_INVALID for others */ 11 + unsigned int space; /* addr_space for si, intf# for ssif. */ 12 + unsigned long addr; 13 + unsigned int regspacing; 14 + unsigned int regsize; 15 + unsigned int regshift; 16 + unsigned int irq; 17 + unsigned int slave_addr; 18 + enum ipmi_addr_src addr_source; 19 + }; 20 + 21 + struct platform_device *ipmi_platform_add(const char *name, unsigned int inst, 22 + struct ipmi_plat_data *p);
+1
drivers/char/ipmi/ipmi_si.h
··· 7 7 */ 8 8 9 9 #include <linux/interrupt.h> 10 + #include <linux/platform_device.h> 10 11 #include "ipmi_si_sm.h" 11 12 12 13 #define DEFAULT_REGSPACING 1
+18 -99
drivers/char/ipmi/ipmi_si_hardcode.c
··· 5 5 #include <linux/moduleparam.h> 6 6 #include <linux/platform_device.h> 7 7 #include "ipmi_si.h" 8 + #include "ipmi_plat_data.h" 8 9 9 10 /* 10 11 * There can be 4 IO ports passed in (with or without IRQs), 4 addresses, ··· 79 78 static void __init ipmi_hardcode_init_one(const char *si_type_str, 80 79 unsigned int i, 81 80 unsigned long addr, 82 - unsigned int flags) 81 + enum ipmi_addr_space addr_space) 83 82 { 84 - struct platform_device *pdev; 85 - unsigned int num_r = 1, size; 86 - struct resource r[4]; 87 - struct property_entry p[6]; 88 - enum si_type si_type; 89 - unsigned int regspacing, regsize; 90 - int rv; 83 + struct ipmi_plat_data p; 91 84 92 - memset(p, 0, sizeof(p)); 93 - memset(r, 0, sizeof(r)); 85 + memset(&p, 0, sizeof(p)); 94 86 95 87 if (!si_type_str || !*si_type_str || strcmp(si_type_str, "kcs") == 0) { 96 - size = 2; 97 - si_type = SI_KCS; 88 + p.type = SI_KCS; 98 89 } else if (strcmp(si_type_str, "smic") == 0) { 99 - size = 2; 100 - si_type = SI_SMIC; 90 + p.type = SI_SMIC; 101 91 } else if (strcmp(si_type_str, "bt") == 0) { 102 - size = 3; 103 - si_type = SI_BT; 92 + p.type = SI_BT; 104 93 } else if (strcmp(si_type_str, "invalid") == 0) { 105 94 /* 106 95 * Allow a firmware-specified interface to be 107 96 * disabled. 108 97 */ 109 - size = 1; 110 - si_type = SI_TYPE_INVALID; 98 + p.type = SI_TYPE_INVALID; 111 99 } else { 112 100 pr_warn("Interface type specified for interface %d, was invalid: %s\n", 113 101 i, si_type_str); 114 102 return; 115 103 } 116 104 117 - regsize = regsizes[i]; 118 - if (regsize == 0) 119 - regsize = DEFAULT_REGSIZE; 105 + p.regsize = regsizes[i]; 106 + p.slave_addr = slave_addrs[i]; 107 + p.addr_source = SI_HARDCODED; 108 + p.regshift = regshifts[i]; 109 + p.regsize = regsizes[i]; 110 + p.addr = addr; 111 + p.space = addr_space; 120 112 121 - p[0] = PROPERTY_ENTRY_U8("ipmi-type", si_type); 122 - p[1] = PROPERTY_ENTRY_U8("slave-addr", slave_addrs[i]); 123 - p[2] = PROPERTY_ENTRY_U8("addr-source", SI_HARDCODED); 124 - p[3] = PROPERTY_ENTRY_U8("reg-shift", regshifts[i]); 125 - p[4] = PROPERTY_ENTRY_U8("reg-size", regsize); 126 - /* Last entry must be left NULL to terminate it. */ 127 - 128 - /* 129 - * Register spacing is derived from the resources in 130 - * the IPMI platform code. 131 - */ 132 - regspacing = regspacings[i]; 133 - if (regspacing == 0) 134 - regspacing = regsize; 135 - 136 - r[0].start = addr; 137 - r[0].end = r[0].start + regsize - 1; 138 - r[0].name = "IPMI Address 1"; 139 - r[0].flags = flags; 140 - 141 - if (size > 1) { 142 - r[1].start = r[0].start + regspacing; 143 - r[1].end = r[1].start + regsize - 1; 144 - r[1].name = "IPMI Address 2"; 145 - r[1].flags = flags; 146 - num_r++; 147 - } 148 - 149 - if (size > 2) { 150 - r[2].start = r[1].start + regspacing; 151 - r[2].end = r[2].start + regsize - 1; 152 - r[2].name = "IPMI Address 3"; 153 - r[2].flags = flags; 154 - num_r++; 155 - } 156 - 157 - if (irqs[i]) { 158 - r[num_r].start = irqs[i]; 159 - r[num_r].end = irqs[i]; 160 - r[num_r].name = "IPMI IRQ"; 161 - r[num_r].flags = IORESOURCE_IRQ; 162 - num_r++; 163 - } 164 - 165 - pdev = platform_device_alloc("hardcode-ipmi-si", i); 166 - if (!pdev) { 167 - pr_err("Error allocating IPMI platform device %d\n", i); 168 - return; 169 - } 170 - 171 - rv = platform_device_add_resources(pdev, r, num_r); 172 - if (rv) { 173 - dev_err(&pdev->dev, 174 - "Unable to add hard-code resources: %d\n", rv); 175 - goto err; 176 - } 177 - 178 - rv = platform_device_add_properties(pdev, p); 179 - if (rv) { 180 - dev_err(&pdev->dev, 181 - "Unable to add hard-code properties: %d\n", rv); 182 - goto err; 183 - } 184 - 185 - rv = platform_device_add(pdev); 186 - if (rv) { 187 - dev_err(&pdev->dev, 188 - "Unable to add hard-code device: %d\n", rv); 189 - goto err; 190 - } 191 - 192 - ipmi_hc_pdevs[i] = pdev; 193 - return; 194 - 195 - err: 196 - platform_device_put(pdev); 113 + ipmi_hc_pdevs[i] = ipmi_platform_add("hardcode-ipmi-si", i, &p); 197 114 } 198 115 199 116 void __init ipmi_hardcode_init(void) ··· 138 219 for (i = 0; i < SI_MAX_PARMS; i++) { 139 220 if (i < num_ports && ports[i]) 140 221 ipmi_hardcode_init_one(si_type[i], i, ports[i], 141 - IORESOURCE_IO); 222 + IPMI_IO_ADDR_SPACE); 142 223 if (i < num_addrs && addrs[i]) 143 224 ipmi_hardcode_init_one(si_type[i], i, addrs[i], 144 - IORESOURCE_MEM); 225 + IPMI_MEM_ADDR_SPACE); 145 226 } 146 227 } 147 228
+3 -8
drivers/char/ipmi/ipmi_si_platform.c
··· 307 307 static int find_slave_address(struct si_sm_io *io, int slave_addr) 308 308 { 309 309 #ifdef CONFIG_IPMI_DMI_DECODE 310 - if (!slave_addr) { 311 - u32 flags = IORESOURCE_IO; 312 - 313 - if (io->addr_space == IPMI_MEM_ADDR_SPACE) 314 - flags = IORESOURCE_MEM; 315 - 316 - slave_addr = ipmi_dmi_get_slave_addr(io->si_type, flags, 310 + if (!slave_addr) 311 + slave_addr = ipmi_dmi_get_slave_addr(io->si_type, 312 + io->addr_space, 317 313 io->addr_data); 318 - } 319 314 #endif 320 315 321 316 return slave_addr;