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

ipmi: Make the DMI probe into a generic platform probe

Rework the DMI probe function to be a generic platform probe, and
then rework the DMI code (and a few other things) to use the more
generic information. This is so other things can declare platform
IPMI devices.

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

+104 -95
+49 -21
drivers/char/ipmi/ipmi_dmi.c
··· 8 8 #include <linux/dmi.h> 9 9 #include <linux/platform_device.h> 10 10 #include <linux/property.h> 11 + #include "ipmi_si_sm.h" 11 12 #include "ipmi_dmi.h" 12 13 14 + #define IPMI_DMI_TYPE_KCS 0x01 15 + #define IPMI_DMI_TYPE_SMIC 0x02 16 + #define IPMI_DMI_TYPE_BT 0x03 17 + #define IPMI_DMI_TYPE_SSIF 0x04 18 + 13 19 struct ipmi_dmi_info { 14 - int type; 20 + enum si_type si_type; 15 21 u32 flags; 16 22 unsigned long addr; 17 23 u8 slave_addr; ··· 27 21 static struct ipmi_dmi_info *ipmi_dmi_infos; 28 22 29 23 static int ipmi_dmi_nr __initdata; 24 + 25 + #define set_prop_entry(_p_, _name_, type, val) \ 26 + do { \ 27 + struct property_entry *_p = &_p_; \ 28 + _p->name = _name_; \ 29 + _p->length = sizeof(type); \ 30 + _p->is_string = false; \ 31 + _p->value.type##_data = val; \ 32 + } while(0) 30 33 31 34 static void __init dmi_add_platform_ipmi(unsigned long base_addr, 32 35 u32 flags, ··· 47 32 struct platform_device *pdev; 48 33 struct resource r[4]; 49 34 unsigned int num_r = 1, size; 50 - struct property_entry p[4] = { 51 - PROPERTY_ENTRY_U8("slave-addr", slave_addr), 52 - PROPERTY_ENTRY_U8("ipmi-type", type), 53 - PROPERTY_ENTRY_U16("i2c-addr", base_addr), 54 - { } 55 - }; 35 + struct property_entry p[5]; 36 + unsigned int pidx = 0; 56 37 char *name, *override; 57 38 int rv; 39 + enum si_type si_type; 58 40 struct ipmi_dmi_info *info; 59 41 60 - info = kmalloc(sizeof(*info), GFP_KERNEL); 61 - if (!info) { 62 - pr_warn("ipmi:dmi: Could not allocate dmi info\n"); 63 - } else { 64 - info->type = type; 65 - info->flags = flags; 66 - info->addr = base_addr; 67 - info->slave_addr = slave_addr; 68 - info->next = ipmi_dmi_infos; 69 - ipmi_dmi_infos = info; 70 - } 42 + memset(p, 0, sizeof(p)); 71 43 72 44 name = "dmi-ipmi-si"; 73 45 override = "ipmi_si"; ··· 64 62 override = "ipmi_ssif"; 65 63 offset = 1; 66 64 size = 1; 65 + si_type = SI_TYPE_INVALID; 67 66 break; 68 67 case IPMI_DMI_TYPE_BT: 69 68 size = 3; 69 + si_type = SI_BT; 70 70 break; 71 71 case IPMI_DMI_TYPE_KCS: 72 + size = 2; 73 + si_type = SI_KCS; 74 + break; 72 75 case IPMI_DMI_TYPE_SMIC: 73 76 size = 2; 77 + si_type = SI_SMIC; 74 78 break; 75 79 default: 76 80 pr_err("ipmi:dmi: Invalid IPMI type: %d", type); 77 81 return; 82 + } 83 + 84 + if (si_type != SI_TYPE_INVALID) 85 + set_prop_entry(p[pidx++], "ipmi-type", u8, si_type); 86 + set_prop_entry(p[pidx++], "slave-addr", u8, slave_addr); 87 + set_prop_entry(p[pidx++], "addr-source", u8, SI_SMBIOS); 88 + 89 + info = kmalloc(sizeof(*info), GFP_KERNEL); 90 + if (!info) { 91 + pr_warn("ipmi:dmi: Could not allocate dmi info\n"); 92 + } else { 93 + info->si_type = si_type; 94 + info->flags = flags; 95 + info->addr = base_addr; 96 + info->slave_addr = slave_addr; 97 + info->next = ipmi_dmi_infos; 98 + ipmi_dmi_infos = info; 78 99 } 79 100 80 101 pdev = platform_device_alloc(name, ipmi_dmi_nr); ··· 107 82 } 108 83 pdev->driver_override = override; 109 84 110 - if (type == IPMI_DMI_TYPE_SSIF) 85 + if (type == IPMI_DMI_TYPE_SSIF) { 86 + set_prop_entry(p[pidx++], "i2c-addr", u16, base_addr); 111 87 goto add_properties; 88 + } 112 89 113 90 memset(r, 0, sizeof(r)); 114 91 ··· 178 151 * This function allows an ACPI-specified IPMI device to look up the 179 152 * slave address from the DMI table. 180 153 */ 181 - int ipmi_dmi_get_slave_addr(int type, u32 flags, unsigned long base_addr) 154 + int ipmi_dmi_get_slave_addr(enum si_type si_type, u32 flags, 155 + unsigned long base_addr) 182 156 { 183 157 struct ipmi_dmi_info *info = ipmi_dmi_infos; 184 158 185 159 while (info) { 186 - if (info->type == type && 160 + if (info->si_type == si_type && 187 161 info->flags == flags && 188 162 info->addr == base_addr) 189 163 return info->slave_addr;
+2 -6
drivers/char/ipmi/ipmi_dmi.h
··· 2 2 * DMI defines for use by IPMI 3 3 */ 4 4 5 - #define IPMI_DMI_TYPE_KCS 0x01 6 - #define IPMI_DMI_TYPE_SMIC 0x02 7 - #define IPMI_DMI_TYPE_BT 0x03 8 - #define IPMI_DMI_TYPE_SSIF 0x04 9 - 10 5 #ifdef CONFIG_IPMI_DMI_DECODE 11 - int ipmi_dmi_get_slave_addr(int type, u32 flags, unsigned long base_addr); 6 + int ipmi_dmi_get_slave_addr(enum si_type si_type, u32 flags, 7 + unsigned long base_addr); 12 8 #endif
+1 -1
drivers/char/ipmi/ipmi_msghandler.c
··· 594 594 595 595 static const char * const addr_src_to_str[] = { 596 596 "invalid", "hotmod", "hardcoded", "SPMI", "ACPI", "SMBIOS", "PCI", 597 - "device-tree" 597 + "device-tree", "platform" 598 598 }; 599 599 600 600 const char *ipmi_addr_src_to_str(enum ipmi_addr_src src)
+1 -1
drivers/char/ipmi/ipmi_si_intf.c
··· 89 89 #define IPMI_BT_INTMASK_CLEAR_IRQ_BIT 2 90 90 #define IPMI_BT_INTMASK_ENABLE_IRQ_BIT 1 91 91 92 - static const char * const si_to_str[] = { "kcs", "smic", "bt" }; 92 + static const char * const si_to_str[] = { "invalid", "kcs", "smic", "bt" }; 93 93 94 94 static int initialized; 95 95
+46 -55
drivers/char/ipmi/ipmi_si_platform.c
··· 6 6 */ 7 7 #include <linux/types.h> 8 8 #include <linux/module.h> 9 - #include "ipmi_dmi.h" 10 - #include <linux/dmi.h> 11 9 #include <linux/of_device.h> 12 10 #include <linux/of_platform.h> 13 11 #include <linux/of_address.h> 14 12 #include <linux/of_irq.h> 15 13 #include <linux/acpi.h> 16 14 #include "ipmi_si.h" 15 + #include "ipmi_dmi.h" 17 16 18 17 #define PFX "ipmi_platform: " 19 18 ··· 20 21 #ifdef CONFIG_ACPI 21 22 static bool si_tryacpi = true; 22 23 #endif 24 + #ifdef CONFIG_OF 25 + static bool si_tryopenfirmware = true; 26 + #endif 23 27 #ifdef CONFIG_DMI 24 28 static bool si_trydmi = true; 29 + #else 30 + static bool si_trydmi = false; 25 31 #endif 26 32 27 33 module_param_named(tryplatform, si_tryplatform, bool, 0); 28 34 MODULE_PARM_DESC(tryplatform, "Setting this to zero will disable the" 29 35 " default scan of the interfaces identified via platform" 30 - " interfaces like openfirmware"); 36 + " interfaces besides ACPI, OpenFirmware, and DMI"); 31 37 #ifdef CONFIG_ACPI 32 38 module_param_named(tryacpi, si_tryacpi, bool, 0); 33 39 MODULE_PARM_DESC(tryacpi, "Setting this to zero will disable the" 34 40 " default scan of the interfaces identified via ACPI"); 41 + #endif 42 + #ifdef CONFIG_OF 43 + module_param_named(tryopenfirmware, si_tryopenfirmware, bool, 0); 44 + MODULE_PARM_DESC(tryacpi, "Setting this to zero will disable the" 45 + " default scan of the interfaces identified via OpenFirmware"); 35 46 #endif 36 47 #ifdef CONFIG_DMI 37 48 module_param_named(trydmi, si_trydmi, bool, 0); ··· 244 235 } 245 236 #endif 246 237 247 - #if defined(CONFIG_DMI) || defined(CONFIG_ACPI) 248 238 static struct resource * 249 239 ipmi_get_info_from_resources(struct platform_device *pdev, 250 240 struct si_sm_io *io) ··· 279 271 return res; 280 272 } 281 273 282 - #endif 283 - 284 - #ifdef CONFIG_DMI 285 - static int dmi_ipmi_probe(struct platform_device *pdev) 274 + static int platform_ipmi_probe(struct platform_device *pdev) 286 275 { 287 276 struct si_sm_io io; 288 - u8 type, slave_addr; 277 + u8 type, slave_addr, addr_source; 289 278 int rv; 290 279 291 - if (!si_trydmi) 292 - return -ENODEV; 280 + rv = device_property_read_u8(&pdev->dev, "addr-source", &addr_source); 281 + if (rv) 282 + addr_source = SI_PLATFORM; 283 + if (addr_source >= SI_LAST) 284 + return -EINVAL; 285 + 286 + if (addr_source == SI_SMBIOS) { 287 + if (!si_trydmi) 288 + return -ENODEV; 289 + } else { 290 + if (!si_tryplatform) 291 + return -ENODEV; 292 + } 293 293 294 294 rv = device_property_read_u8(&pdev->dev, "ipmi-type", &type); 295 295 if (rv) 296 296 return -ENODEV; 297 297 298 298 memset(&io, 0, sizeof(io)); 299 - io.addr_source = SI_SMBIOS; 300 - pr_info(PFX "probing via SMBIOS\n"); 299 + io.addr_source = addr_source; 300 + dev_info(&pdev->dev, PFX "probing via %s\n", 301 + ipmi_addr_src_to_str(addr_source)); 301 302 302 303 switch (type) { 303 - case IPMI_DMI_TYPE_KCS: 304 - io.si_type = SI_KCS; 305 - break; 306 - case IPMI_DMI_TYPE_SMIC: 307 - io.si_type = SI_SMIC; 308 - break; 309 - case IPMI_DMI_TYPE_BT: 310 - io.si_type = SI_BT; 304 + case SI_KCS: 305 + case SI_SMIC: 306 + case SI_BT: 307 + io.si_type = type; 311 308 break; 312 309 default: 310 + dev_err(&pdev->dev, "ipmi-type property is invalid\n"); 313 311 return -EINVAL; 314 312 } 315 313 316 - if (!ipmi_get_info_from_resources(pdev, &io)) { 317 - rv = -EINVAL; 318 - goto err_free; 319 - } 314 + if (!ipmi_get_info_from_resources(pdev, &io)) 315 + return -EINVAL; 320 316 321 317 rv = device_property_read_u8(&pdev->dev, "slave-addr", &slave_addr); 322 318 if (rv) { 323 - dev_warn(&pdev->dev, "device has no slave-addr property"); 319 + dev_warn(&pdev->dev, "device has no slave-addr property\n"); 324 320 io.slave_addr = 0x20; 325 321 } else { 326 322 io.slave_addr = slave_addr; ··· 345 333 ipmi_si_add_smi(&io); 346 334 347 335 return 0; 348 - 349 - err_free: 350 - return rv; 351 336 } 352 - #else 353 - static int dmi_ipmi_probe(struct platform_device *pdev) 354 - { 355 - return -ENODEV; 356 - } 357 - #endif /* CONFIG_DMI */ 358 337 359 338 #ifdef CONFIG_OF 360 339 static const struct of_device_id of_ipmi_match[] = { ··· 368 365 struct device_node *np = pdev->dev.of_node; 369 366 int ret; 370 367 int proplen; 368 + 369 + if (!si_tryopenfirmware) 370 + return -ENODEV; 371 371 372 372 dev_info(&pdev->dev, "probing via device tree\n"); 373 373 ··· 442 436 { 443 437 #ifdef CONFIG_IPMI_DMI_DECODE 444 438 if (!slave_addr) { 445 - int type = -1; 446 439 u32 flags = IORESOURCE_IO; 447 - 448 - switch (io->si_type) { 449 - case SI_KCS: 450 - type = IPMI_DMI_TYPE_KCS; 451 - break; 452 - case SI_BT: 453 - type = IPMI_DMI_TYPE_BT; 454 - break; 455 - case SI_SMIC: 456 - type = IPMI_DMI_TYPE_SMIC; 457 - break; 458 - } 459 440 460 441 if (io->addr_type == IPMI_MEM_ADDR_SPACE) 461 442 flags = IORESOURCE_MEM; 462 443 463 - slave_addr = ipmi_dmi_get_slave_addr(type, flags, 444 + slave_addr = ipmi_dmi_get_slave_addr(io->si_type, flags, 464 445 io->addr_data); 465 446 } 466 447 #endif ··· 556 563 if (acpi_ipmi_probe(pdev) == 0) 557 564 return 0; 558 565 559 - return dmi_ipmi_probe(pdev); 566 + return platform_ipmi_probe(pdev); 560 567 } 561 568 562 569 static int ipmi_remove(struct platform_device *pdev) ··· 576 583 577 584 void ipmi_si_platform_init(void) 578 585 { 579 - if (si_tryplatform) { 580 - int rv = platform_driver_register(&ipmi_platform_driver); 581 - if (rv) 582 - pr_err(PFX "Unable to register driver: %d\n", rv); 583 - } 586 + int rv = platform_driver_register(&ipmi_platform_driver); 587 + if (rv) 588 + pr_err(PFX "Unable to register driver: %d\n", rv); 584 589 585 590 #ifdef CONFIG_ACPI 586 591 if (si_tryacpi)
+1 -1
drivers/char/ipmi/ipmi_si_sm.h
··· 43 43 struct si_sm_data; 44 44 45 45 enum si_type { 46 - SI_KCS, SI_SMIC, SI_BT 46 + SI_TYPE_INVALID, SI_KCS, SI_SMIC, SI_BT 47 47 }; 48 48 49 49 /*
+3 -9
drivers/char/ipmi/ipmi_ssif.c
··· 53 53 #include <linux/acpi.h> 54 54 #include <linux/ctype.h> 55 55 #include <linux/time64.h> 56 + #include "ipmi_si_sm.h" 56 57 #include "ipmi_dmi.h" 57 58 58 59 #define PFX "ipmi_ssif: " ··· 1483 1482 #ifdef CONFIG_IPMI_DMI_DECODE 1484 1483 if (!slave_addr) 1485 1484 slave_addr = ipmi_dmi_get_slave_addr( 1486 - IPMI_DMI_TYPE_SSIF, 1485 + SI_TYPE_INVALID, 1487 1486 i2c_adapter_id(client->adapter), 1488 1487 client->addr); 1489 1488 #endif ··· 2014 2013 #ifdef CONFIG_DMI 2015 2014 static int dmi_ipmi_probe(struct platform_device *pdev) 2016 2015 { 2017 - u8 type, slave_addr = 0; 2016 + u8 slave_addr = 0; 2018 2017 u16 i2c_addr; 2019 2018 int rv; 2020 2019 2021 2020 if (!ssif_trydmi) 2022 - return -ENODEV; 2023 - 2024 - rv = device_property_read_u8(&pdev->dev, "ipmi-type", &type); 2025 - if (rv) 2026 - return -ENODEV; 2027 - 2028 - if (type != IPMI_DMI_TYPE_SSIF) 2029 2021 return -ENODEV; 2030 2022 2031 2023 rv = device_property_read_u16(&pdev->dev, "i2c-addr", &i2c_addr);
+1 -1
include/linux/ipmi.h
··· 277 277 */ 278 278 enum ipmi_addr_src { 279 279 SI_INVALID = 0, SI_HOTMOD, SI_HARDCODED, SI_SPMI, SI_ACPI, SI_SMBIOS, 280 - SI_PCI, SI_DEVICETREE, SI_LAST 280 + SI_PCI, SI_DEVICETREE, SI_PLATFORM, SI_LAST 281 281 }; 282 282 const char *ipmi_addr_src_to_str(enum ipmi_addr_src src); 283 283