| .. | .. |
|---|
| 5 | 5 | * Handling for platform devices in IPMI (ACPI, OF, and things |
|---|
| 6 | 6 | * coming from the platform. |
|---|
| 7 | 7 | */ |
|---|
| 8 | + |
|---|
| 9 | +#define pr_fmt(fmt) "ipmi_platform: " fmt |
|---|
| 10 | +#define dev_fmt pr_fmt |
|---|
| 11 | + |
|---|
| 8 | 12 | #include <linux/types.h> |
|---|
| 9 | 13 | #include <linux/module.h> |
|---|
| 10 | 14 | #include <linux/of_device.h> |
|---|
| .. | .. |
|---|
| 15 | 19 | #include "ipmi_si.h" |
|---|
| 16 | 20 | #include "ipmi_dmi.h" |
|---|
| 17 | 21 | |
|---|
| 18 | | -#define PFX "ipmi_platform: " |
|---|
| 19 | | - |
|---|
| 22 | +static bool platform_registered; |
|---|
| 20 | 23 | static bool si_tryplatform = true; |
|---|
| 21 | 24 | #ifdef CONFIG_ACPI |
|---|
| 22 | 25 | static bool si_tryacpi = true; |
|---|
| .. | .. |
|---|
| 105 | 108 | |
|---|
| 106 | 109 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
|---|
| 107 | 110 | if (res) { |
|---|
| 108 | | - io->addr_type = IPMI_IO_ADDR_SPACE; |
|---|
| 111 | + io->addr_space = IPMI_IO_ADDR_SPACE; |
|---|
| 109 | 112 | } else { |
|---|
| 110 | 113 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|---|
| 111 | 114 | if (res) |
|---|
| 112 | | - io->addr_type = IPMI_MEM_ADDR_SPACE; |
|---|
| 115 | + io->addr_space = IPMI_MEM_ADDR_SPACE; |
|---|
| 113 | 116 | } |
|---|
| 114 | 117 | if (!res) { |
|---|
| 115 | 118 | dev_err(&pdev->dev, "no I/O or memory address\n"); |
|---|
| .. | .. |
|---|
| 119 | 122 | |
|---|
| 120 | 123 | io->regspacing = DEFAULT_REGSPACING; |
|---|
| 121 | 124 | res_second = platform_get_resource(pdev, |
|---|
| 122 | | - (io->addr_type == IPMI_IO_ADDR_SPACE) ? |
|---|
| 125 | + (io->addr_space == IPMI_IO_ADDR_SPACE) ? |
|---|
| 123 | 126 | IORESOURCE_IO : IORESOURCE_MEM, |
|---|
| 124 | 127 | 1); |
|---|
| 125 | 128 | if (res_second) { |
|---|
| .. | .. |
|---|
| 156 | 159 | |
|---|
| 157 | 160 | memset(&io, 0, sizeof(io)); |
|---|
| 158 | 161 | io.addr_source = addr_source; |
|---|
| 159 | | - dev_info(&pdev->dev, PFX "probing via %s\n", |
|---|
| 162 | + dev_info(&pdev->dev, "probing via %s\n", |
|---|
| 160 | 163 | ipmi_addr_src_to_str(addr_source)); |
|---|
| 161 | 164 | |
|---|
| 162 | 165 | switch (type) { |
|---|
| .. | .. |
|---|
| 186 | 189 | return -EINVAL; |
|---|
| 187 | 190 | |
|---|
| 188 | 191 | rv = device_property_read_u8(&pdev->dev, "slave-addr", &slave_addr); |
|---|
| 189 | | - if (rv) { |
|---|
| 190 | | - dev_warn(&pdev->dev, "device has no slave-addr property\n"); |
|---|
| 192 | + if (rv) |
|---|
| 191 | 193 | io.slave_addr = 0x20; |
|---|
| 192 | | - } else { |
|---|
| 194 | + else |
|---|
| 193 | 195 | io.slave_addr = slave_addr; |
|---|
| 194 | | - } |
|---|
| 195 | 196 | |
|---|
| 196 | | - io.irq = platform_get_irq(pdev, 0); |
|---|
| 197 | + io.irq = platform_get_irq_optional(pdev, 0); |
|---|
| 197 | 198 | if (io.irq > 0) |
|---|
| 198 | 199 | io.irq_setup = ipmi_std_irq_setup; |
|---|
| 199 | 200 | else |
|---|
| .. | .. |
|---|
| 203 | 204 | |
|---|
| 204 | 205 | pr_info("ipmi_si: %s: %s %#lx regsize %d spacing %d irq %d\n", |
|---|
| 205 | 206 | ipmi_addr_src_to_str(addr_source), |
|---|
| 206 | | - (io.addr_type == IPMI_IO_ADDR_SPACE) ? "io" : "mem", |
|---|
| 207 | + (io.addr_space == IPMI_IO_ADDR_SPACE) ? "io" : "mem", |
|---|
| 207 | 208 | io.addr_data, io.regsize, io.regspacing, io.irq); |
|---|
| 208 | 209 | |
|---|
| 209 | 210 | ipmi_si_add_smi(&io); |
|---|
| .. | .. |
|---|
| 247 | 248 | |
|---|
| 248 | 249 | ret = of_address_to_resource(np, 0, &resource); |
|---|
| 249 | 250 | if (ret) { |
|---|
| 250 | | - dev_warn(&pdev->dev, PFX "invalid address from OF\n"); |
|---|
| 251 | + dev_warn(&pdev->dev, "invalid address from OF\n"); |
|---|
| 251 | 252 | return ret; |
|---|
| 252 | 253 | } |
|---|
| 253 | 254 | |
|---|
| 254 | 255 | regsize = of_get_property(np, "reg-size", &proplen); |
|---|
| 255 | 256 | if (regsize && proplen != 4) { |
|---|
| 256 | | - dev_warn(&pdev->dev, PFX "invalid regsize from OF\n"); |
|---|
| 257 | + dev_warn(&pdev->dev, "invalid regsize from OF\n"); |
|---|
| 257 | 258 | return -EINVAL; |
|---|
| 258 | 259 | } |
|---|
| 259 | 260 | |
|---|
| 260 | 261 | regspacing = of_get_property(np, "reg-spacing", &proplen); |
|---|
| 261 | 262 | if (regspacing && proplen != 4) { |
|---|
| 262 | | - dev_warn(&pdev->dev, PFX "invalid regspacing from OF\n"); |
|---|
| 263 | + dev_warn(&pdev->dev, "invalid regspacing from OF\n"); |
|---|
| 263 | 264 | return -EINVAL; |
|---|
| 264 | 265 | } |
|---|
| 265 | 266 | |
|---|
| 266 | 267 | regshift = of_get_property(np, "reg-shift", &proplen); |
|---|
| 267 | 268 | if (regshift && proplen != 4) { |
|---|
| 268 | | - dev_warn(&pdev->dev, PFX "invalid regshift from OF\n"); |
|---|
| 269 | + dev_warn(&pdev->dev, "invalid regshift from OF\n"); |
|---|
| 269 | 270 | return -EINVAL; |
|---|
| 270 | 271 | } |
|---|
| 271 | 272 | |
|---|
| .. | .. |
|---|
| 275 | 276 | io.irq_setup = ipmi_std_irq_setup; |
|---|
| 276 | 277 | |
|---|
| 277 | 278 | if (resource.flags & IORESOURCE_IO) |
|---|
| 278 | | - io.addr_type = IPMI_IO_ADDR_SPACE; |
|---|
| 279 | + io.addr_space = IPMI_IO_ADDR_SPACE; |
|---|
| 279 | 280 | else |
|---|
| 280 | | - io.addr_type = IPMI_MEM_ADDR_SPACE; |
|---|
| 281 | + io.addr_space = IPMI_MEM_ADDR_SPACE; |
|---|
| 281 | 282 | |
|---|
| 282 | 283 | io.addr_data = resource.start; |
|---|
| 283 | 284 | |
|---|
| .. | .. |
|---|
| 305 | 306 | static int find_slave_address(struct si_sm_io *io, int slave_addr) |
|---|
| 306 | 307 | { |
|---|
| 307 | 308 | #ifdef CONFIG_IPMI_DMI_DECODE |
|---|
| 308 | | - if (!slave_addr) { |
|---|
| 309 | | - u32 flags = IORESOURCE_IO; |
|---|
| 310 | | - |
|---|
| 311 | | - if (io->addr_type == IPMI_MEM_ADDR_SPACE) |
|---|
| 312 | | - flags = IORESOURCE_MEM; |
|---|
| 313 | | - |
|---|
| 314 | | - slave_addr = ipmi_dmi_get_slave_addr(io->si_type, flags, |
|---|
| 309 | + if (!slave_addr) |
|---|
| 310 | + slave_addr = ipmi_dmi_get_slave_addr(io->si_type, |
|---|
| 311 | + io->addr_space, |
|---|
| 315 | 312 | io->addr_data); |
|---|
| 316 | | - } |
|---|
| 317 | 313 | #endif |
|---|
| 318 | 314 | |
|---|
| 319 | 315 | return slave_addr; |
|---|
| .. | .. |
|---|
| 337 | 333 | |
|---|
| 338 | 334 | memset(&io, 0, sizeof(io)); |
|---|
| 339 | 335 | io.addr_source = SI_ACPI; |
|---|
| 340 | | - dev_info(&pdev->dev, PFX "probing via ACPI\n"); |
|---|
| 336 | + dev_info(&pdev->dev, "probing via ACPI\n"); |
|---|
| 341 | 337 | |
|---|
| 342 | 338 | io.addr_info.acpi_info.acpi_handle = handle; |
|---|
| 343 | 339 | |
|---|
| .. | .. |
|---|
| 382 | 378 | io.irq = tmp; |
|---|
| 383 | 379 | io.irq_setup = acpi_gpe_irq_setup; |
|---|
| 384 | 380 | } else { |
|---|
| 385 | | - int irq = platform_get_irq(pdev, 0); |
|---|
| 381 | + int irq = platform_get_irq_optional(pdev, 0); |
|---|
| 386 | 382 | |
|---|
| 387 | 383 | if (irq > 0) { |
|---|
| 388 | 384 | io.irq = irq; |
|---|
| .. | .. |
|---|
| 396 | 392 | |
|---|
| 397 | 393 | dev_info(io.dev, "%pR regsize %d spacing %d irq %d\n", |
|---|
| 398 | 394 | res, io.regsize, io.regspacing, io.irq); |
|---|
| 395 | + |
|---|
| 396 | + request_module("acpi_ipmi"); |
|---|
| 399 | 397 | |
|---|
| 400 | 398 | return ipmi_si_add_smi(&io); |
|---|
| 401 | 399 | |
|---|
| .. | .. |
|---|
| 431 | 429 | return ipmi_si_remove_by_dev(&pdev->dev); |
|---|
| 432 | 430 | } |
|---|
| 433 | 431 | |
|---|
| 432 | +static int pdev_match_name(struct device *dev, const void *data) |
|---|
| 433 | +{ |
|---|
| 434 | + struct platform_device *pdev = to_platform_device(dev); |
|---|
| 435 | + const char *name = data; |
|---|
| 436 | + |
|---|
| 437 | + return strcmp(pdev->name, name) == 0; |
|---|
| 438 | +} |
|---|
| 439 | + |
|---|
| 440 | +void ipmi_remove_platform_device_by_name(char *name) |
|---|
| 441 | +{ |
|---|
| 442 | + struct device *dev; |
|---|
| 443 | + |
|---|
| 444 | + while ((dev = bus_find_device(&platform_bus_type, NULL, name, |
|---|
| 445 | + pdev_match_name))) { |
|---|
| 446 | + struct platform_device *pdev = to_platform_device(dev); |
|---|
| 447 | + |
|---|
| 448 | + platform_device_unregister(pdev); |
|---|
| 449 | + put_device(dev); |
|---|
| 450 | + } |
|---|
| 451 | +} |
|---|
| 452 | + |
|---|
| 434 | 453 | static const struct platform_device_id si_plat_ids[] = { |
|---|
| 435 | | - { "hardcode-ipmi-si", 0 }, |
|---|
| 436 | | - { } |
|---|
| 454 | + { "dmi-ipmi-si", 0 }, |
|---|
| 455 | + { "hardcode-ipmi-si", 0 }, |
|---|
| 456 | + { "hotmod-ipmi-si", 0 }, |
|---|
| 457 | + { } |
|---|
| 437 | 458 | }; |
|---|
| 438 | 459 | |
|---|
| 439 | 460 | struct platform_driver ipmi_platform_driver = { |
|---|
| 440 | 461 | .driver = { |
|---|
| 441 | | - .name = DEVICE_NAME, |
|---|
| 462 | + .name = SI_DEVICE_NAME, |
|---|
| 442 | 463 | .of_match_table = of_ipmi_match, |
|---|
| 443 | 464 | .acpi_match_table = ACPI_PTR(acpi_ipmi_match), |
|---|
| 444 | 465 | }, |
|---|
| .. | .. |
|---|
| 451 | 472 | { |
|---|
| 452 | 473 | int rv = platform_driver_register(&ipmi_platform_driver); |
|---|
| 453 | 474 | if (rv) |
|---|
| 454 | | - pr_err(PFX "Unable to register driver: %d\n", rv); |
|---|
| 475 | + pr_err("Unable to register driver: %d\n", rv); |
|---|
| 476 | + else |
|---|
| 477 | + platform_registered = true; |
|---|
| 455 | 478 | } |
|---|
| 456 | 479 | |
|---|
| 457 | 480 | void ipmi_si_platform_shutdown(void) |
|---|
| 458 | 481 | { |
|---|
| 459 | | - platform_driver_unregister(&ipmi_platform_driver); |
|---|
| 482 | + if (platform_registered) |
|---|
| 483 | + platform_driver_unregister(&ipmi_platform_driver); |
|---|
| 460 | 484 | } |
|---|