.. | .. |
---|
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 | } |
---|